<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x627;&#x637;&#x627;&#x631; &#x627;&#x644;&#x639;&#x645;&#x644; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x627;&#x637;&#x627;&#x631; &#x627;&#x644;&#x639;&#x645;&#x644; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; Laravel</description><language>ar</language><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x625;&#x646;&#x634;&#x627;&#x621; &#x623;&#x648;&#x627;&#x645;&#x631; &#x645;&#x62E;&#x635;&#x635;&#x629; &#x641;&#x64A; Laravel 11 &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; PHP Artisan</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D9%85%D8%AE%D8%B5%D8%B5%D8%A9-%D9%81%D9%8A-laravel-11-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-php-artisan-r2581/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2025_05/Laravel11PHPArtisan.png.5bce1ad874bacf78f7b6d1b270d270cb.png" /></p>
<p>
	عندما نعمل على تطبيق لارافيل Laravel، قد نحتاج لتكرار مهام معينة مثل إنشاء ملفات أو تنفيذ أوامر خاصة بالتطبيق. وبدلاً من أن نكتب كل هذه الأوامر يدويًا في كل مرة، يمكننا أتمتة المهام المتكررة باستخدام أداة سطر الأوامر سهلة الاستخدام PHP Artisan المدمجة مع إطار عمل لارافيل، فهي تتيح لنا تنفيذ أوامر جاهزة مثل إنشاء جداول قواعد البيانات، أو تشغيل خادم التطوير المحلي، كما تتيح لنا تنفيذ أوامر جديدة خاصة بنا ننشؤها بأنفسنا، مثل إرسال بريد لمستخدم، أو تحديث بيانات معينة.
</p>

<p>
	سنوضح في هذا المقال كيفية إنشاء أمر Artisan جديد باستخدام الأمر <code>make:command</code> الذي يؤدي لإنشاء صنف جديد في المجلد <code>app/Console/Commands</code> والمستخدَم لإعداد عمليات التهجير Migrations وقوائم الوِجهات Route وإنشاء الأرتال Queueing والأصناف والمهام الأخرى.
</p>

<h2 id="phpartisan">
	نظرة عامة على PHP Artisan
</h2>

<p>
	يستخدم المطورون أوامر Artisan من <a href="https://academy.hsoub.com/programming/php/laravel/" rel="">لارافيل</a> لإكمال المهام الضوروية مثل إنشاء عمليات التهجير، ونشر موارد الحزم.
</p>

<p>
	هناك عدة أوامر مدمجة مع Artisan، ويمكننا عرض قائمة بهذه الأوامر من خلال كتابة أمر <code>php artisan list</code> في الطرفية Terminal، إذ يوفر هذا الأمر قائمةً بجميع الأوامر المتاحة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpg" data-fileid="172405" href="https://academy.hsoub.com/uploads/monthly_2025_05/001___Laravel_Artisan.jpg.0ae711cd4c87e55c89d0c7c72cf5c66f.jpg" rel=""><img alt="001_قائمة_أوامر_Laravel_Artisan.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="172405" data-ratio="61.00" data-unique="mrrilvqtu" width="900" src="https://academy.hsoub.com/uploads/monthly_2025_05/001___Laravel_Artisan.thumb.jpg.3b9eaca6c22010e5b34e4ff10c68d461.jpg"></a>
</p>

<p>
	تساعد هذه الأوامر المطورين على العمل بكفاءة أكبر، فباستخدام أوامر Laravel Artisan المختلفة سنتمكن من إنشاء وظائف الاستيثاق Auth والمتحكم Controller والنموذج والبريد والتهجير والعديد من الوظائف الأخرى بسرعة وبوقت أقل.
</p>

<h2 id="phpartisan-1">
	تشغيل تطبيق لارافيل باستخدام خادم PHP Artisan
</h2>

<p>
	يتيح الأمر <code>serve</code> إمكانية تشغيل التطبيقات على خادم تطوير <a href="https://academy.hsoub.com/programming/php/" rel="">PHP</a> بسهولة، ويمكن للمطورين استخدام Laravel Artisan لإنشاء واختبار ميزات التطبيق المختلفة، إذ يمكن بدء تشغيل <a href="https://academy.hsoub.com/devops/servers/%D8%AF%D9%84%D9%8A%D9%84-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%AE%D8%A7%D8%AF%D9%85-%D9%88%D9%8A%D8%A8-%D9%85%D8%AD%D9%84%D9%8A-%D8%AE%D8%B7%D9%88%D8%A9-%D8%A8%D8%AE%D8%B7%D9%88%D8%A9-r422/" rel="">الخادم المحلي </a>على العنوان <code><a href="http://localhost:8000" ipsnoembed="false" rel="external nofollow">http://localhost:8000</a></code> بكتابة الأمر <code>php artisan serve</code>، مما يسهل اختبار وتطوير التطبيقات بسرعة؛ كما يمكن تخصيص الخادم لاستخدام مضيف ومنفذ مختلف.
</p>

<p>
	يتكامل أمر <code>php artisan serve</code> مع نظام تطوير لارافيل Laravel Ecosystem الذي يتضمن ميزات عديدة مثل تهجير قواعد البيانات Migration، وجدولة المهام، وإدارة الأرتال Queues.
</p>

<h2 id="">
	إنشاء أوامر مخصصة وتشغيلها
</h2>

<p>
	يمكن إنشاء أوامر Artisan مخصصة، مع اختيار مكان تخزينها وتحميلها باستخدام مدير الحزم <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%85%D9%84%D8%AD%D9%86-composer-%D9%85%D8%AF%D9%8A%D8%B1-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D9%81%D9%8A-php-r1123/" rel="">Composer</a>. سنشرح في الفقرات التالية أهم الخطوات المتبعة لإنشاء أوامر مخصصة وتسجيلها وتنفيذها.
</p>

<h3 id="1">
	الخطوة 1: إنشاء أمر جديد
</h3>

<p>
	يمكننا إنشاء أمر جديد باسم <code>customcommand</code> عبر استخدام الأمر <code>make:command</code> الذي سينشئ صنف أوامر جديد تلقائيًا في المجلد <code>app/Console/Commands</code>، وسيتولّد هذا المجلد إن لم يكن موجودًا مسبقًا.
</p>

<p>
	لنكتب الآن الأمر التالي في طرفية Artisan:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_6" style=""><span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">command customcommand</span></pre>

<p>
	قد يبدو ملف الشيفرة البرمجية CustomCommand.php الخاص بهذا الأمر كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_8" style=""><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Console\Commands</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Console\Command</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CustomCommand</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Command</span><span class="pln">

</span><span class="pun">{</span><span class="pln">

</span><span class="kwd">protected</span><span class="pln"> $signature </span><span class="pun">=</span><span class="pln"> </span><span class="str">'custom:command'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">protected</span><span class="pln"> $description </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Description of the custom command'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln">

</span><span class="pun">{</span><span class="pln">

parent</span><span class="pun">::</span><span class="pln">__construct</span><span class="pun">();</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> handle</span><span class="pun">()</span><span class="pln">

</span><span class="pun">{</span><span class="pln">

</span><span class="com">// نضع المنطق البرمجي للأمر هنا</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></pre>

<h3 id="2">
	الخطوة 2: تعريف الأمر
</h3>

<p>
	عند تنفيذ بعض أوامر Artisan، قد نحتاج أحيانًا لأن يُدخل المستخدم بعض المعلومات، مثل اسمه أو بريده الإلكتروني. يتعامل لارافيل مع ذلك باستخدام خاصية التوقيع <code>signature</code>، ويمكننا استخدام الصيغة القصيرة التالية لضبط الوسطاء Arguments والرايات Flags أو الخيارات المطلوبة والاختيارية، وهذا يسهل علينا تحديد الطريقة التي سيتفاعل بها المستخدمون مع الأمر عند تشغيله.
</p>

<p>
	لنلقِ نظرةً على الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_10" style=""><span class="kwd">protected</span><span class="pln"> $signature </span><span class="pun">=</span><span class="pln"> </span><span class="str">'user:update {id} {--name=} {--email=}'</span><span class="pun">;</span></pre>

<p>
	يتوقّع هذا الأمر لأن يدخل المستخدم وسيطًا للمعرّف ID وخيارات الاسم والبريد الإلكتروني الاختيارية.
</p>

<h3 id="3">
	الخطوة 3: دخل وخرج الأمر
</h3>

<p>
	يوفّر لارافيل طرقًا سهلةً للحصول على قيم الوسطاء والخيارات عند تشغيل الأمر، لذا من المهم استخدام التابعين <code>‎$this-&gt;argument()‎</code> و <code>‎$this-&gt;option()‎</code> ضمن التابع <code>handle</code> الخاص بالأمر. وإن لم يكن الوسيط أو الخيار الذي نبحث عنه موجودًا، فسيعيد هذان التابعان القيمة <code>null</code>.
</p>

<p>
	يمكننا الحصول على إدخال من المستخدم أثناء تشغيل الأمر بالإضافة إلى عرض الخرج، حيث يعرض التابع <code>ask</code> سؤالًا للمستخدم ويجمع استجابته ثم يرسلها مرةً أخرى إلى الأمر الخاص بنا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_12" style=""><span class="pln">$name </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">ask</span><span class="pun">(</span><span class="str">'What is your name?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Taylor'</span><span class="pun">);</span></pre>

<p>
	والأمر الآتي لطلب التأكيد:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_14" style=""><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">confirm</span><span class="pun">(</span><span class="str">'Do you wish to continue?'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="com">// متابعة</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	يمكن جعل موجّه التأكيد يعيد القيمة <code>true</code> دائمًا من خلال تمرير القيمة <code>true</code> كوسيط ثانٍ للتابع <code>confirm</code>.
</p>

<h3 id="4">
	الخطوة 4: تسجيل الأوامر
</h3>

<p>
	يسجّل لارافيل جميع الأوامر الموجودة في المجلد <code>app/Console/Commands</code> افتراضيًا، ويمكننا إعداده للبحث في مزيد من المجلدات عن أوامر PHP Artisan، وذلك من خلال استخدام التابع <code>withCommands</code> في ملف <code>bootstrap/app.php</code> الخاص بتطبيقنا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_16" style=""><span class="pun">-&gt;</span><span class="pln">withCommands</span><span class="pun">([</span><span class="pln">

__DIR__</span><span class="pun">.</span><span class="str">'/../app/Domain/Orders/Commands'</span><span class="pun">,</span><span class="pln">

</span><span class="pun">])</span></pre>

<p>
	سيجد <a href="https://wiki.hsoub.com/Laravel/container" rel="external">حاوي الخدمات</a> جميع الأوامر ويسجلها في تطبيقنا باستخدام Artisan.
</p>

<h3 id="5">
	الخطوة 5: تنفيذ الطلبات
</h3>

<p>
	قد نرغب في تشغيل أمر Artisan خارج واجهة سطر الأوامر من وجهة Route أو متحكم Controller مثلًا، حيث يمكن ذلك باستخدام التابع <code>call</code> مع الصنف Facade من Artisan؛ ويحتوي هذا التابع على وسيطين هما:
</p>

<ol>
	<li>
		اسم الأمر أو صنفه
	</li>
	<li>
		قائمة بمعاملات الأمر
	</li>
</ol>

<p>
	ويعيد هذا التابع رمز الخروج.
</p>

<p>
	يمكن أيضًا تمرير أمر Artisan بالكامل إلى التابع <code>call</code> كسلسلة نصية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_18" style=""><span class="typ">Artisan</span><span class="pun">::</span><span class="pln">call</span><span class="pun">(</span><span class="str">'mail:send 1 --queue=default'</span><span class="pun">);</span></pre>

<p>
	يمكن استخدام التابع <code>queue</code> مع الصنف Facade من Artisan لإرسال أوامر Artisan إلى عمّال الرتل، ثم نعالَج هذه الأوامر في الخلفية، ونتأكّد من ضبط الرتل وتشغيل مستمع الرتل قبل استخدام هذا التابع.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_20" style=""><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Artisan</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/user/{user}/mail'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $user</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="typ">Artisan</span><span class="pun">::</span><span class="pln">queue</span><span class="pun">(</span><span class="str">'mail:send'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">

</span><span class="str">'user'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $user</span><span class="pun">,</span><span class="pln"> </span><span class="str">'--queue'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'default'</span><span class="pln">

</span><span class="pun">]);</span><span class="pln">

</span><span class="com">// ...</span><span class="pln">

</span><span class="pun">});</span></pre>

<h3 id="6">
	الخطوة 6: معالجة الإشارات
</h3>

<p>
	يمكن لأوامر Artisan من لارافيل معالجة إشارات النظام مثل إشارات SIGINT، حيث يمكن دمج معالجة الإشارات مع الأمر الخاص بنا باستخدام التابع <code>trap</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_22" style=""><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">trap</span><span class="pun">(</span><span class="pln">SIGINT</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

$this</span><span class="pun">-&gt;</span><span class="pln">info</span><span class="pun">(</span><span class="str">'Command interrupted'</span><span class="pun">);</span><span class="pln">

</span><span class="pun">});</span></pre>

<h3 id="7stub">
	الخطوة 7: تخصيص الملفات الجذرية Stub
</h3>

<p>
	يمكن تخصيص ملفات القوالب التي يستخدمها أمر <code>make:command</code> من Artisan لتسهيل إنشاء الأوامر ذات البنى المتناسقة، لذا نحتاج إلى نشر الملفات الجذرية في مشروعنا كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_24" style=""><span class="pln">php artisan stub</span><span class="pun">:</span><span class="pln">publish</span></pre>

<h3 id="8">
	الخطوة 8: الأحداث
</h3>

<p>
	هناك ثلاثة أحداث يرسلها Artisan عند تشغيل الأوامر وهي:
</p>

<ol>
	<li>
		Illuminate\Console\Events\ArtisanStarting
	</li>
	<li>
		Illuminate\Console\Events\CommandStarting
	</li>
	<li>
		Illuminate\Console\Events\CommandFinished
	</li>
</ol>

<p>
	استخدم التابع <code>event</code> لإطلاق حدث كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_26" style=""><span class="kwd">event</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">CustomCommandExecuted</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">));</span></pre>

<h2 id="migrationsmakemigration">
	إنشاء عمليات التهجير Migrations باستخدام الأمر make:migration
</h2>

<p>
	يُعَد الأمر <code>php artisan make:migration</code> من أوامر Artisan في لارافيل، ويُستخدَم لإنشاء ملف تهجير جديد. عمليات التهجير هي مخططات أولية لمخطط <a href="https://academy.hsoub.com/devops/servers/databases/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-database/" rel="">قاعدة البيانات</a> الخاصة بنا، وتحدّد بنية الجداول والأعمدة والفهارس والعلاقات.
</p>

<p>
	في ما يلي خطوات هذه العملية:
</p>

<ol>
	<li>
		<strong>إنشاء عملية تهجير</strong>: يؤدي تشغيل الأمر <code>make:migration</code> إلى إنشاء ملف <a href="https://wiki.hsoub.com/PHP" rel="external">PHP</a> جديد في المجلد <code>database/migrations</code>
	</li>
	<li>
		<strong>تحديد التغييرات</strong>: يحتوي ملف التهجير على التابعين <code>up</code> و <code>down</code>، حيث يحدّد التابع <code>up</code> التغييرات التي تطرأ على قاعدة البيانات، مثل إنشاء الجداول أو إضافة الأعمدة، ويلغي التابع <code>down</code> هذه التغييرات
	</li>
	<li>
		<strong>تشغيل عملية التهجير</strong>: استخدام الأمر <code>php artisan migrate</code> لتطبيق التغييرات على قاعدة البيانات
	</li>
</ol>

<p>
	يؤدي الأمر التالي مثلًآ إلى إنشاء ملف جديد بالاسم <code>create_users_table</code> في المجلد <code>database/migrations</code>، ويمكن بعد ذلك تحديد بنية جدول <code>users</code> ضمن ملف التهجير.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4716_28" style=""><span class="typ">Bash</span><span class="pln">

php artisan make</span><span class="pun">:</span><span class="pln">migration create_users_table</span></pre>

<h3 id="makemigration">
	فوائد الأمر make:migration
</h3>

<p>
	تتمثل فوائد الأمر <code>make:migration</code> فيما يلي:
</p>

<ul>
	<li>
		<strong>التحكم في الإصدارات</strong>: من خلال تعقّب تغييرات قاعدة البيانات بمرور الوقت
	</li>
	<li>
		<strong>التعاون</strong>: مشاركة بنية قاعدة البيانات مع أعضاء الفريق بسهولة
	</li>
	<li>
		<strong>بذر أو توليد البيانات Seeding لقاعدة البيانات</strong>: ملء قاعدة البيانات بالبيانات التجريبية باستخدام مولّد البيانات Seeder
	</li>
	<li>
		<strong>التراجع عن تغييرات قاعدة البيانات</strong>: يمكن عكس تغييرات قاعدة البيانات بسهولة إن لزم الأمر
	</li>
</ul>

<p>
	تساعد عمليات التهجير على إبقاء مخطط قاعدة البيانات واضحًا ومنظمًا، مما يسهّل عملية إدارة التطبيق وتحديثه.
</p>

<h2 id="laravelartisan">
	قائمة أوامر Laravel Artisan
</h2>

<p>
	تُعَد واجهة سطر أوامر Artisan في لارافيل أداةً مفيدةً للعمل مع التطبيقات، فهي تحتوي على أوامر لمهام مختلفة مثل إنشاء الشيفرة البرمجية وإدارة بيئة التطبيق.
</p>

<p>
	تكون قائمة أوامر Laravel PHP Artisan الكاملة شاملة، حيث يمكننا استخدام أمر <code>PHP Artisan list</code> لجلبها، ولكن سنفصّل فيما يلي الأوامر الأساسية ضمن فئات في Laravel 11.
</p>

<p id="-1">
	تتمثل الأوامر الأساسية في الآتي:
</p>

<ul>
	<li>
		cache: إدارة ذاكرة التطبيق المخبئية مثل المسح والنسيان وإلخ
	</li>
	<li>
		config: تخزين ملفات الضبط Configuration مؤقتًا أو مسحها أو نشرها
	</li>
	<li>
		down: تعطيل التطبيق مؤقتًا
	</li>
	<li>
		env: إدارة متغيرات البيئة
	</li>
	<li>
		key: توليد مفتاح تطبيق جديد
	</li>
	<li>
		migrate: تشغيل عمليات تهجير قاعدة البيانات
	</li>
	<li>
		optimize: تحسين التطبيق للإنتاج
	</li>
	<li>
		queue: إدارة نظام الرتل
	</li>
	<li>
		route: سرد الوِجهات Routes أو مسحها
	</li>
	<li>
		storage: إدارة مجلد التخزين
	</li>
	<li>
		vendor: إدارة اعتماديات مدير الحزم Composer
	</li>
</ul>

<p id="-2">
	أما أوامر توليد الشيفرة البرمجية، فتتمثل في ما يلي:
</p>

<ul>
	<li>
		make: توليد بنى الشيفرة البرمجية المختلفة للمتحكم والنموذج والتهجير وإلخ
	</li>
	<li>
		model: إنشاء نماذج Eloquent
	</li>
	<li>
		migration: إنشاء ملفات التهجير
	</li>
	<li>
		seed: توليد بيانات وهمية لقاعدة البيانات
	</li>
</ul>

<p id="-3">
	في حين أن أوامر الاختبار تكون كالآتي:
</p>

<ul>
	<li>
		test: تشغيل اختبارات التطبيق
	</li>
	<li>
		dusk: تشغيل اختبارات المتصفح باستخدام Dusk
	</li>
</ul>

<p id="-4">
	إلى جانب وجود بعض الأوامر الإضافية التي يمكن اعتمادها، وتتمثل في:
</p>

<ul>
	<li>
		auth: إدارة العمليات المتعلقة بالاستيثاق Authentication
	</li>
	<li>
		breeze: تثبيت نظام استيثاق Breeze
	</li>
	<li>
		config: إدارة ملفات الضبط
	</li>
	<li>
		horizon: إدارة نظام رتل Laravel Horizon
	</li>
	<li>
		passport: إدارة خادم OAuth2
	</li>
	<li>
		sanctum: إدارة واجهة برمجة التطبيقات <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> لاستيثاق الرموز Token
	</li>
	<li>
		telescope: إدارة أداة تنقيح أخطاء Telescope
	</li>
</ul>

<h2 id="-5">
	الخلاصة
</h2>

<p>
	بهذا نكون قد وضّحنا في هذا المقال كيفية إنشاء أوامر مخصصة باستخدام أمر Artisan الذي هو أداة PHP وتتيح تطوير أوامر مختلفة بناءً على احتياجات مشروعنا.
</p>

<p>
	ترجمة -وبتصرّف- للقسم <a href="https://www.cloudways.com/blog/custom-artisan-commands-laravel/" rel="external nofollow">How to Create Custom Commands in Laravel 11 with PHP Artisan</a> لصاحبته Hafsa Tahir.
</p>

<h2 id="-6">
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D9%85%D8%AE%D8%B5%D8%B5%D8%A9-%D9%81%D9%8A-laravel-11-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-php-artisan-r2565/" rel="">إنشاء أوامر مخصصة في Laravel 11 باستخدام PHP Artisan</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%86%D8%B5%D8%A7%D8%A6%D8%AD-%D9%84%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%A3%D8%AF%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2544/" rel="">نصائح لتحسين أداء تطبيقات لارافيل</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D9%81%D8%B6%D9%84-%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%84%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2530/" rel="">أفضل الحزم البرمجية لتحسين تطبيقات لارافيل</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2581</guid><pubDate>Mon, 30 Jun 2025 16:09:01 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x623;&#x648;&#x627;&#x645;&#x631; &#x645;&#x62E;&#x635;&#x635;&#x629; &#x641;&#x64A; Laravel 11 &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; PHP Artisan</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D9%85%D8%AE%D8%B5%D8%B5%D8%A9-%D9%81%D9%8A-laravel-11-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-php-artisan-r2565/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2025_05/10037214.------Laravel-11--PHP-Artisan.png.e6310b14d5646d6d29192cae557044a2.png" /></p>
<p>
	عندما نعمل على تطبيق لارافيل Laravel، قد نحتاج لتكرار مهام معينة خاصة بالتطبيق. وبدلاً من أن نكتب كل هذه الأوامر يدويًا في كل مرة يمكننا أتمتتها باستخدام أداة Artisan المدمجة مع إطار عمل لارافيل، فهذه الأداة تتيح لنا تنفيذ أوامر جاهزة مثل إنشاء جداول قواعد البيانات، أو تشغيل خادم التطوير المحلي، كما تمكننا من تنفيذ أوامر جديدة خاصة بنا كإرسال بريد لمستخدم، أو تحديث بيانات معينة
</p>

<p>
	سنوضح في هذا المقال كيفية إنشاء أمر Artisan جديد في إصدار لارافيل 11، سنبدأ بالتعرف على أساسيات Artisan والأوامر التي توفرها، ثم ننتقل بعد ذلك لشرح طريقة إنشاء وتشغيل أوامرنا المخصصة.
</p>

<h2 id="phpartisan">
	نظرة عامة على Artisan
</h2>

<p>
	Artisan هو أداة سطر الأوامر مدمجة مع <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%B4%D9%87%D9%8A%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/" rel="">إطار العمل لارافيل</a> توفر مجموعة من الأوامر المفيدة التي يمكن أن تساعدنا أثناء بناء التطبيقات، مثل إنشاء عمليات التهجير Migrations، ونشر موارد الحزم.
</p>

<p>
	هنالك عدة أوامر مدمجة مع Artisan ويمكن عرض قائمة بهذه الأوامر من خلال كتابة أمر <code>php artisan list</code> في طرفية Artisan كما في الصورة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpg" data-fileid="171435" href="https://academy.hsoub.com/uploads/monthly_2025_04/001___Laravel_Artisan.jpg.7407522c9ac05a37990463d3ed764208.jpg" rel=""><img alt="001 قائمة أوامر Laravel Artisan" class="ipsImage ipsImage_thumbnailed" data-fileid="171435" data-ratio="61.00" data-unique="ih9h1jmaq" style="width: 600px; height: auto;" width="900" src="https://academy.hsoub.com/uploads/monthly_2025_04/001___Laravel_Artisan.thumb.jpg.c1ae1c84d37213b126e5eaecd40ea5a8.jpg"></a>
</p>

<p>
	تساعدنا هذه الأوامر على العمل بكفاءة أكبر، حيث سنتمكن على سبيل المثال من إنشاء وظائف <a href="https://wiki.hsoub.com/Laravel/authentication" rel="external">الاستيثاق Authentication</a>، والمتحكمات Controllers، والنماذج Models، وإنشاء عمليات التهجير Migrations وغيرها من الوظائف المتقدمة بسهولة وخلال وقت أقل.
</p>

<h2 id="laravelartisan">
	أساسيات أوامر Laravel Artisan
</h2>

<p>
	يُعَد الصنف <code>Illuminate\Console\Application</code> أساسًا في Artisan فهو الذي يحدد كيفية التعامل مع الأوامر، كما أنه يوسّع الصنف <code>Symfony\Component\Console\Application</code>، وهذا يسهّل على مطوري إطار عمل سيمفوني Symfony التعامل مع Artisan لأنهم سيجدون بيئة عمل مألوفة.
</p>

<p>
	فيما يلي مثال على  تعريف أمر بسيط:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8736_6" style=""><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Console\Commands</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Console\Command</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ExampleCommand</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Command</span><span class="pln">

</span><span class="pun">{</span><span class="pln">

</span><span class="kwd">protected</span><span class="pln"> $signature </span><span class="pun">=</span><span class="pln"> </span><span class="str">'example:run {name}'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">protected</span><span class="pln"> $description </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Runs an example command'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> handle</span><span class="pun">()</span><span class="pln">

</span><span class="pun">{</span><span class="pln">

$name </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">argument</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">

$this</span><span class="pun">-&gt;</span><span class="pln">info</span><span class="pun">(</span><span class="str">"Hello, {$name}!"</span><span class="pun">);</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></pre>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير تطبيقات الويب باستخدام لغة PHP
		</p>

		<p class="banner-subtitle">
			احترف تطوير النظم الخلفية والووردبريس وتطبيقات الويب من الألف إلى الياء دون الحاجة لخبرة برمجية مسبقة
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/php-web-application-development/" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<a href="https://academy.hsoub.com/learn/php-web-application-development/" rel=""><img alt="دورة تطوير تطبيقات الويب باستخدام لغة PHP" src="https://academy.hsoub.com/learn/assets/images/courses/php-web-application-development.png"></a>
	</div>
</div>

<h2 id="phpartisan-1">
	تشغيل تطبيق لارافيل باستخدام خادم PHP Artisan
</h2>

<p>
	يتيح الأمر <code>serve</code> تشغيل التطبيقات على خادم تطوير <a href="https://academy.hsoub.com/programming/php/" rel="">PHP</a> بسهولة، ويمكن للمطورين استخدام Artisan لإنشاء واختبار ميزات التطبيق المختلفة، يمكن بدء تشغيل الخادم المحلي على العنوان <code><a href="http://localhost:8000" ipsnoembed="true" rel="external nofollow">http://localhost:8000</a></code> بكتابة الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_402_12" style=""><span class="pln"> php artisan serve </span></pre>

<p>
	وهذا يسهل اختبار وتطوير التطبيقات بسرعة، كما يمكننا تخصيص الخادم لاستخدام مضيف ومنفذ مختلف.
</p>

<h2 id="">
	إنشاء أوامر مخصصة وتشغيلها
</h2>

<p>
	يمكن إنشاء أوامر Artisan مخصصة واختيار مكان تخزينها وتحميلها باستخدام مدير الحزم <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%85%D9%84%D8%AD%D9%86-composer-%D9%85%D8%AF%D9%8A%D8%B1-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D9%81%D9%8A-php-r1123/" rel="">Composer</a>. سنشرح في الفقرات التالية أهم الخطوات المتبعة لإنشاء أوامر مخصصة وتسجيلها وتنفيذها.
</p>

<h3 id="1">
	الخطوة 1: إنشاء أمر جديد
</h3>

<p>
	لإنشاء أمر جديد باسم <code>customcommand</code> نستخدام الأمر <code>make:command</code> الذي ينشئ تلقائيًا صنف أوامر جديد في المجلد <code>app/Console/Commands</code>، ويولّد هذا المجلد إن لم يكن موجودًا مسبقًا.
</p>

<p>
	لنكتب الآن الأمر التالي في طرفية Artisan:
</p>

<pre class="ipsCode">php artisan make:command customcommand
</pre>

<p>
	يبدو ملف الشيفرة البرمجية الخاص بهذا الأمر كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_402_14" style=""><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Console\Commands</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Console\Command</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CustomCommand</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Command</span><span class="pln">

</span><span class="pun">{</span><span class="pln">

</span><span class="kwd">protected</span><span class="pln"> $signature </span><span class="pun">=</span><span class="pln"> </span><span class="str">'custom:command'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">protected</span><span class="pln"> $description </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Description of the custom command'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln">

</span><span class="pun">{</span><span class="pln">

parent</span><span class="pun">::</span><span class="pln">__construct</span><span class="pun">();</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> handle</span><span class="pun">()</span><span class="pln">

</span><span class="pun">{</span><span class="pln">

</span><span class="com">// نضع المنطق البرمجي للأمر هنا</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></pre>

<h3 id="2">
	الخطوة 2: تعريف الأمر المخصص
</h3>

<p>
	عند تنفيذ بعض أوامر Artisan، قد يحتاج المستخدم لإدخال بعض المعلومات كاسمه أو بريده الإلكتروني، ويتعامل لارافيل مع ذلك باستخدام خاصية التوقيع <code>signature</code>. يمكننا استخدام الصيغة القصيرة التالية لضبط الوسطاء arguments والرايات flags أو الخيارات الإجبارية والاختيارية، وهذا يسهّل علينا تحديد الطريقة التي سيتفاعل بها المستخدمون مع الأمر. لنلقِ نظرة على الأمر التالي:
</p>

<pre class="ipsCode">protected $signature = 'user:update {id} {--name=} {--email=}';
</pre>

<p>
	يتوقّع هذا الأمر أن يدخل المستخدم وسيطًا هو المعرف <code>id، </code>ويدخل الاسم والبريد الإلكتروني اختياريًا.
</p>

<h3 id="3">
	الخطوة 3: دخل وخرج الأمر
</h3>

<p>
	يوفّر لارافيل طرقًا سهلة للحصول على قيم الوسطاء عند تشغيل الأمر، حيث يمكننا استخدام التابعين <code>‎$this-&gt;argument()‎</code> و <code>‎$this-&gt;option()‎</code> ضمن التابع <code>handle</code> الخاص بالأمر. إن لم يكن الوسيط أو الخيار الذي نبحث عنه موجودًا، فسيعيد هذان التابعان القيمة <code>null</code>.
</p>

<h4 id="-1">
	المطالبة بالإدخال
</h4>

<p>
	يمكننا الحصول على إدخال من المستخدم أثناء تشغيل الأمر بالإضافة إلى عرض الخرج، حيث يعرض التابع <code>ask</code> سؤالًا للمستخدم ويحصل على استجابته ثم يرسلها مرة أخرى إلى الأمر الخاص بك.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_402_16" style=""><span class="pln">$name </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">ask</span><span class="pun">(</span><span class="str">'What is your name?'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Taylor'</span><span class="pun">);</span></pre>

<h4 id="-2">
	طلب التأكيد
</h4>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_402_18" style=""><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">confirm</span><span class="pun">(</span><span class="str">'Do you wish to continue?'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="com">// متابعة</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	يمكن جعل موجّه التأكيد يعيد القيمة <code>true</code> دائمًا من خلال تمرير القيمة <code>true</code> كوسيط ثانٍ للتابع <code>confirm</code>.
</p>

<h3 id="4">
	الخطوة 4: تسجيل الأوامر
</h3>

<p>
	يسجّل لارافيل جميع الأوامر الموجودة في المجلد <code>app/Console/Commands</code> افتراضيًا، ويمكننا إعداد لارافيل للبحث في مزيد من المجلدات عن أوامر PHP Artisan من خلال استخدام التابع <code>withCommands</code> في ملف <code>bootstrap/app.php</code> الخاص بالتطبيق.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5758_7" style=""><span class="pun">-&gt;</span><span class="pln">withCommands</span><span class="pun">([</span><span class="pln">

__DIR__</span><span class="pun">.</span><span class="str">'/../app/Domain/Orders/Commands'</span><span class="pun">,</span><span class="pln">

</span><span class="pun">])</span></pre>

<p>
	سيجد <a href="https://wiki.hsoub.com/Laravel/container" rel="external">حاوي الخدمات</a> جميع الأوامر ويسجلها في التطبيق باستخدام Artisan.
</p>

<h3 id="5">
	الخطوة 5: تنفيذ الطلبات
</h3>

<p>
	قد نرغب بتشغيل أمر Artisan خارج واجهة سطر الأوامر من وجهة Route أو متحكم Controller مثلًا، ويمكن تحقيق ذلك باستخدام التابع <code>call</code> مع الصنف <code>Facade</code> من Artisan، يحتوي هذا التابع على وسيطين الأول هو اسم الأمر أو اسم الصنف المرتبط بالأمر، والوسيط الثاني هو قائمة بمعاملات الأمر، ويعيد هذا التابع رمز الخروج ليشير إلى ما إذا كان الأمر قد نجح أم لا.
</p>

<p>
	يمكن أيضًا تمرير أمر Artisan بالكامل للتابع <code>call</code> كسلسلة نصية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_402_20" style=""><span class="typ">Artisan</span><span class="pun">::</span><span class="pln">call</span><span class="pun">(</span><span class="str">'mail:send 1 --queue=default'</span><span class="pun">);</span></pre>

<h4 id="artisan">
	ترتيب أوامر Artisan ضمن رتل
</h4>

<p>
	يمكننا استخدام التابع <code>queue</code> مع الصنف <code>Facade</code> من Artisan لإرسال أوامر Artisan إلى عمّال الرتل Queue Workers، ثم تُعالَج هذه الأوامر في الخلفية، وعلينا التأكّد من ضبط الرتل وتشغيل مستمع الرتل قبل استخدام هذا التابع.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_402_22" style=""><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Artisan</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/user/{user}/mail'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $user</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

</span><span class="typ">Artisan</span><span class="pun">::</span><span class="pln">queue</span><span class="pun">(</span><span class="str">'mail:send'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">

</span><span class="str">'user'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $user</span><span class="pun">,</span><span class="pln"> </span><span class="str">'--queue'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'default'</span><span class="pln">

</span><span class="pun">]);</span><span class="pln">

</span><span class="com">// ...</span><span class="pln">

</span><span class="pun">});</span></pre>

<h3 id="6">
	الخطوة 6: معالجة الإشارات
</h3>

<p>
	يمكن لأوامر Artisan من لارافيل معالجة إشارات النظام مثل إشارات SIGINT، حيث يمكننا دمج معالجة الإشارات مع الأمر الخاص بنا باستخدام التابع <code>trap</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_402_24" style=""><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">trap</span><span class="pun">(</span><span class="pln">SIGINT</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

$this</span><span class="pun">-&gt;</span><span class="pln">info</span><span class="pun">(</span><span class="str">'Command interrupted'</span><span class="pun">);</span><span class="pln">

</span><span class="pun">});</span></pre>

<h3 id="7stub">
	الخطوة 7: تخصيص الملفات الجذرية Stub
</h3>

<p>
	يمكن تخصيص ملفات القوالب التي يستخدمها أمر <code>make:command</code> من Artisan لتسهيل إنشاء الأوامر ذات البنى المتناسقة، لذا نحتاج إلى نشر الملفات الجذرية في مشروعنا كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_402_26" style=""><span class="pln">php artisan stub</span><span class="pun">:</span><span class="pln">publish</span></pre>

<h3 id="8">
	الخطوة 8: الأحداث
</h3>

<p>
	هناك ثلاثة أحداث مهمة ترسلها أداة Artisan عند تشغيل الأوامر وهي:
</p>

<ul>
	<li>
		الحدث <code>Illuminate\Console\Events\ArtisanStarting</code>
	</li>
	<li>
		الحدث <code>Illuminate\Console\Events\CommandStarting</code>
	</li>
	<li>
		الحدث <code>Illuminate\Console\Events\CommandFinished</code>
	</li>
</ul>

<p>
	نستخدم التابع <code>event</code> لإطلاق حدث كما يلي:
</p>

<pre class="ipsCode">event(new CustomCommandExecuted($this));
</pre>

<h2 id="migrationsmakemigration">
	إنشاء عمليات التهجير Migrations
</h2>

<p>
	يُعَد الأمر <code>php artisan make:migration</code> من أوامر Artisan المفيدة في لارافيل، حيث يستخدم لإنشاء ملف تهجير جديد. وعمليات التهجير هي مخططات أولية لمخطط قاعدة البيانات وتحدّد لنا بنية الجداول والأعمدة والفهارس والعلاقات.
</p>

<p>
	فيما يلي خطوات هذه العملية:
</p>

<ol>
	<li>
		<strong>إنشاء عملية تهجير</strong>: يؤدي الأمر <code>make:migration</code> لإنشاء ملف جديد في المجلد <code>database/migrations</code>
	</li>
	<li>
		<strong>تحديد التغييرات</strong>: يحتوي ملف التهجير على التابعين <code>up</code> و <code>down</code> يحدّد <code>up</code> التغييرات التي تطرأ على قاعدة البيانات مثل إنشاء الجداول، ويلغي <code>down</code> هذه التغييرات
	</li>
	<li>
		<strong>تشغيل عملية التهجير</strong>: يفيد الأمر <code>php artisan migrate</code> في تطبيق التغييرات على قاعدة البيانات
	</li>
</ol>

<p>
	على سبيل المثال سيؤدي الأمر التالي لإنشاء ملف جديد بالاسم <code>create_users_table</code> في المجلد <code>database/migrations</code>، ويمكننا بعد ذلك تحديد بنية جدول <code>users</code> ضمن ملف التهجير.
</p>

<pre class="ipsCode" id="ips_uid_5758_9">php artisan make:migration create_users_table
</pre>

<p>
	تتمثل فوائد الأمر <code>make:migration</code> فيما يلي:
</p>

<ul>
	<li>
		التحكم في الإصدارات من خلال تعقّب تغييرات قاعدة البيانات بمرور الوقت
	</li>
	<li>
		التعاون ومشاركة بنية قاعدة البيانات مع أعضاء الفريق بسهولة
	</li>
	<li>
		بذر أو توليد البيانات Seeding لقاعدة البيانات لملئها بالبيانات التجريبية باستخدام Seeder
	</li>
	<li>
		التراجع عن تغييرات قاعدة البيانات بسهولة عند الحاجة
	</li>
	<li>
		إبقاء مخطط قاعدة البيانات واضحًا ومنظمًا، مما يسهّل إدارة تطبيقنا وتحديثه
	</li>
</ul>

<h2 id="laravelartisan-1">
	قائمة بأهم أوامر Laravel Artisan
</h2>

<p>
	تحتوي واجهة سطر أوامر Artisan في لارافيل على أوامر لمهام مختلفة مثل إنشاء الشيفرة البرمجية وإدارة بيئة التطبيق ويمكن مطالعة القائمة الشاملة لكافة الأوامر بكتابة الأمر <code>PHP Artisan list</code> كما وضحنا سابقًا، ولكن سنفصّل فيما يلي الأوامر الأساسية الموجودة ضمن لارافيل 11 ضمن فئات.
</p>

<h3 id="-4">
	الأوامر الأساسية
</h3>

<ul>
	<li>
		<code>cache</code>: إدارة ذاكرة التطبيق المخبئية
	</li>
	<li>
		<code>config</code>: تخزين ملفات الضبط Configuration مؤقتًا أو مسحها أو نشرها
	</li>
	<li>
		<code>down</code>: تعطيل التطبيق مؤقتًا
	</li>
	<li>
		<code>env</code>: إدارة متغيرات البيئة
	</li>
	<li>
		<code>key</code>: لتوليد مفتاح تطبيق جديد
	</li>
	<li>
		<code>migrate</code>: تشغيل عمليات تهجير قاعدة البيانات
	</li>
	<li>
		<code>optimize</code>: تحسين التطبيق للإنتاج
	</li>
	<li>
		<code>queue</code>: إدارة نظام الرتل
	</li>
	<li>
		<code>route</code>: سرد الوجهات Routes أو مسحها
	</li>
	<li>
		<code>storage</code>: إدارة مجلد التخزين
	</li>
	<li>
		<code>vendor</code>: إدارة اعتماديات مدير الحزم Composer
	</li>
</ul>

<h3 id="-5">
	أوامر توليد الشيفرة البرمجية
</h3>

<ul>
	<li>
		<code>make</code>: توليد بنى الشيفرة البرمجية المختلفة للمتحكم والنموذج والتهجير ...إلخ.
	</li>
	<li>
		<code>model</code>: إنشاء نماذج Eloquent
	</li>
	<li>
		<code>migration</code>: إنشاء ملفات التهجير
	</li>
	<li>
		<code>seed</code>: توليد بيانات وهمية لقاعدة البيانات
	</li>
</ul>

<h3 id="-6">
	أوامر الاختبار
</h3>

<ul>
	<li>
		<code>test</code>: تشغيل اختبارات التطبيق
	</li>
	<li>
		<code>dusk</code>: تشغيل اختبارات المتصفح باستخدام Dusk
	</li>
</ul>

<h3 id="-7">
	أوامر أخرى
</h3>

<ul>
	<li>
		<code>auth</code>: إدارة العمليات المتعلقة بالاستيثاق Authentication
	</li>
	<li>
		<code>breeze</code>: تثبيت نظام استيثاق Breeze
	</li>
	<li>
		<code>config</code>: إدارة ملفات الضبط
	</li>
	<li>
		<code>horizon</code>: إدارة نظام رتل Laravel Horizon
	</li>
	<li>
		<code>passport</code>: إدارة خادم OAuth2
	</li>
	<li>
		<code>sanctum</code>: إدارة واجهة برمجة التطبيقات <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> لاستيثاق الرموز Token
	</li>
	<li>
		<code>telescope</code>: إدارة أداة تنقيح أخطاء Telescope
	</li>
</ul>

<h2 id="-8">
	الخلاصة
</h2>

<p>
	وضّحنا في هذا المقال كيفية إنشاء أوامر مخصصة باستخدام أمر Artisan الذي يوفر إمكانية تطوير أوامر مختلفة واستدعاءها بناءً على احتياجات مشروعنا.
</p>

<h2 id="-9">
	بعض الأسئلة الشائعة
</h2>

<p>
	لنتعرف على أبرز الأسئلة الشائعة حول أوامر Artisan
</p>

<h3>
	1. ما الغرض من أوامر PHP Artisan في لارافيل
</h3>

<p>
	أوامر Artisan هي أداة سطر أوامر في لارافيل تساعدنا على أتمتة المهام وإدارة عمليات التهجير وتوليد الشيفرة البرمجية المساعدة، ويمكننا استخدامها أيضًا لتشغيل الاختبارات وإنجاز مهام التطوير والإدارة الأخرى في تطبيقات لارافيل.
</p>

<h3>
	2. لماذا نستخدم أمر PHP Artisan Serve
</h3>

<p>
	يشغّل أمر <code>PHP Artisan serve</code> خادم تطوير محلي لتطبيق لارافيل الخاص بنا بسرعة، ويُعَد مثاليًا لإنشاء النماذج الأولية السريعة والاختبار أثناء التطوير.
</p>

<h3>
	3. كيف نشغّل أوامر PHP Artisan في cpanel
</h3>

<p>
	نفتح الطرفية Terminal من cPanel وننتقل إلى مجلد مشروع لارافيل الخاص بنا، ثم نشغّل الأمر باستخدام PHP كما يلي:
</p>

<pre class="ipsCode" id="ips_uid_402_29"> ‎/usr/local/bin/php artisan {command}‎</pre>

<p>
	تحتاج للتأكد من وضع مسار PHP الصحيح للخادم مكان <code>‎/usr/local/bin/php</code>، والذي يمكننا العثور عليه في MultiPHP Manager ضمن cPanel.
</p>

<h3>
	4. هل يمكن تعديل أو توسيع أوامر Artisan الموجودة مسبقًا في لارافيل
</h3>

<p>
	نعم، لدينا القدرة على تعديل أو توسيع أوامر Artisan الموجودة مسبقًا في لارافيل من خلال إنشاء أمر مخصص يرث صنف الأمر الأساسي، ثم تنفيذ المنطق البرمجي أو الوظيفة المحددة التي نريدها ضمن هذا الأمر المخصص.
</p>

<h3>
	5. هل يمكن استخدام أوامر Artisan المخصصة لأتمتة المهام الشائعة في لارافيل
</h3>

<p>
	نعم، يمكننا استخدام أوامر Artisan المخصصة في لارافيل لأتمتة المهام الشائعة مثل تشغيل عمليات التهجير، وتوليد بيانات لقاعدة البيانات وتوليد الشيفرة البرمجية وتطبيق المهام المجدولة وتنفيذ أي منطق برمجي مخصص.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.cloudways.com/blog/custom-artisan-commands-laravel/" rel="external nofollow">How to Create Custom Commands in Laravel 11 with PHP Artisan</a> للكاتبة Hafsa Tahir.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%86%D8%B5%D8%A7%D8%A6%D8%AD-%D9%84%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%A3%D8%AF%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2544/" rel="">نصائح لتحسين أداء تطبيقات لارافيل</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D9%81%D8%B6%D9%84-%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%84%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2530/" rel="">أفضل الحزم البرمجية لتحسين تطبيقات لارافيل</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%86%D9%85%D9%88%D8%B0%D8%AC%D8%A7-model-%D9%81%D9%8A-laravel-r297/" rel="">كيف تنشئ نموذجا Model في Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%AE%D8%A8%D8%A6%D8%A9-cache-%D9%81%D9%8A-laravel-r389/" rel="">أساسيات التخبئة Cache في Laravel</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2565</guid><pubDate>Fri, 02 May 2025 13:07:00 +0000</pubDate></item><item><title>&#x646;&#x635;&#x627;&#x626;&#x62D; &#x644;&#x62A;&#x62D;&#x633;&#x64A;&#x646; &#x623;&#x62F;&#x627;&#x621; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644;</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%86%D8%B5%D8%A7%D8%A6%D8%AD-%D9%84%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%A3%D8%AF%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2544/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2025_03/_(1).png.86937471a92515ee1e4fb990df005edc.png" /></p>
<p>
	تزايدت شعبية إطار العمل لارافيل Laravel بشكل كبير فهو اليوم واحد من أبرز أطر عمل لغة PHP، لا سيما في مجال تطوير تطبيقات الويب ومنصات التجارة الإلكترونية. سنشرح لكم في هذا المقال عدة نصائح وملاحظات لتحسين أداء التطبيقات المطورة بلارافيل.
</p>

<h2 id="-1">
	أهمية تحسين تطبيقات لارافيل
</h2>

<p>
	أصبح إطار العمل لارافيل شائعًا جدًا في تطوير تطبيقات الأعمال التي تساعد في اتخاذ القرارات الإدارية بسرعة وفعالية. ولضمان أداء جيد لهذه التطبيقات، نحتاج لتحسينها والتأكد من تنفيذها للمهام بسرعة وسلاسة، لا سيما إذا كانت هذه التطبيقات تؤثر في اتخاذ قرارات مهمة.
</p>

<p>
	يوفر تحسين أداء تطبيقات لارافيل جملة من الفوائد تشمل زيادة فعالية التطبيق وتعزيز الفرصة لوصوله إلى جمهور أوسع، وتوفير الوقت وتقليل الهدر في الموارد، إلى جانب تحسين التعامل مع حركة البيانات وإدارة الطلبات المتزايدة بكفاءة مع زيادة حجم التطبيق.
</p>

<h2>
	متطلبات العمل
</h2>

<p>
	سنفترض في هذه المقال أن لدينا تطبيق لارافيل مثبت على خادم تتوفر فيه الأمور التالية:
</p>

<ul>
	<li>
		الإصدار Laravel 9.0 من إطار العمل لارافيل
	</li>
	<li>
		الإصدار  PHP 8.0 من لغة PHP
	</li>
	<li>
		قاعدة البيانات MariaDB
	</li>
</ul>

<h2 id="-4">
	نصائح لتحسين أداء تطبيقات لارفيل
</h2>

<p>
	فيما يلي نورد مجموعة من النصائح التي تساعد في تحسين أداء تطبيقات لارافيل.
</p>

<h3 id="-5">
	التخزين المؤقت للإعدادات
</h3>

<p>
	يمكننا من خلال حفظ إعدادات التطبيق في ذاكرة التخزين المؤقت cache memory تسريع الوصول لهذه الإعدادات، بدلاً من تحميلها من الملفات في كل مرة نشغل فيها التطبيق وهذا الأمر يساهم في تحسين أداء التطبيق بشكل عام. 
</p>

<p>
	لتنفيذ هذا الأمر في إطار العمل لارافيل نستخدم الأمر التالي:
</p>

<pre class="ipsCode">php artisan config:cache
</pre>

<p>
	بمجرد تخزين الإعدادات في ذاكرة التخزين المؤقت، فإن أي تغييرات نجريها على هذه الإعدادات لن تؤثر على هذه النسخة في الذاكرة. فإذا أردنا تحديث الذاكرة المؤقتة لتخزن الإعدادات الجديدة، فعلينا تنفيذ الأمر السابق مرة أخرى.
</p>

<p>
	ولمسح التخزين المؤقت للإعدادات نستخدم الأمر التالي:
</p>

<pre class="ipsCode">php artisan config: clear
</pre>

<p>
	لا ينبغي استخدام أمر تخزين الإعدادات مؤقتًا أثناء تطوير التطبيق، لأن الإعدادات قد تتغير بصورة مستمرة طيلة مرحلة التطوير، وبإمكاننا استخدام أداة <code><a href="https://academy.hsoub.com/devops/servers/web/apache/%D9%83%D9%8A%D9%81-%D8%AA%D8%B6%D8%A8%D8%B7-opcache-%D9%84%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%A4%D9%82%D8%AA-%D8%B9%D9%84%D9%89-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D9%88%D9%8A%D8%A8-apache-r52/" rel="">OPcache</a></code> لتحسين التطبيق، فهو يخزّن شيفرة PHP الذاكرة المؤقتة، مما يلغي الحاجة لإعادة تصريف شيفرة PHP في كل مرة نطلبها من الخادم، ويساهم في تسريع التطبيق.
</p>

<h3 id="-6">
	التخزين المؤقت للوجهات Routes
</h3>

<p>
	يفيد التخزين المؤقت للوجهات routes في لارافيل في تحسين التطبيقات، لا سيما تلك التي تحتوي عدد كبير من الوجهات والإعدادات. فمن خلال تخزين المصفوفة الخاصة بالوجهات في الذاكرة المؤقتة، سنتمكن من تحميلها بسرعة أكبر. لتنفيذ هذه الميزة، نستخدم الأمر التالي:
</p>

<pre class="ipsCode">php artisan route: cache
</pre>

<p>
	لا ننسى تنفيذ هذا الأمر كلما تغير ملفات الإعدادات أو الوجهات لمشروعنا، وإلا سيحمّل لارافيل القيم المحفوظة سابقًا. 
</p>

<p>
	لمسح التخزين المؤقت للوجهات routes نستخدم الأمر التالي:
</p>

<pre class="ipsCode">php artisan route: clear
</pre>

<h3 id="-7">
	إزالة الخدمات غير المستخدمة
</h3>

<p>
	الغاية الأساسية <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%B4%D9%87%D9%8A%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/" rel="">لإطار لارافيل</a> هي تسهيل عمل المطورين ولتحقيق هذه الغاية يحمّل إطار لارافيل عند تشغيله مجموعة متنوعة من الخدمات المدمجة والمحددة في الملف <code>config/app.php</code>. لكن قد لا يحتاج المطور للعديد من هذه الخدمات كخدمة التعامل مع قوالب العرض <code>View Service</code> وخدمة إدارة الجلسة <code>Session Service</code>، وسيفيدنا تعطيل الخدمات غير الضرورية في تحسين أداء التطبيق.
</p>

<h3 id="-8">
	تحسين تحميل الملفات
</h3>

<p>
	يستدعي إطار لارافيل ملفات متعددة للتعامل مع الطلبات requests، وبالتالي قد يرتبط تطبيق لارافيل متوسط التعقيد بعدة ملفات، ومن النصائح البسيطة لتحسين الأداء التصريح عن كل الملفات التي يحتاجها التطبيق ضمن ملف واحد يُستدعى ويُحمّل لكل الطلبات.
</p>

<p>
	نستخدم الأمر التالي لتطبيق هذه النصيحة:
</p>

<pre class="ipsCode">php artisan optimize --force
</pre>

<h3 id="composer">
	تحسين الملحن Composer
</h3>

<p>
	الملحن Composer هو أداة مفيدة لإدارة الاعتماديات dependencies في تطبيقات PHP وكذلك في تطبيقات لارافيل. فعند تثبيت هذه الأداة، ستعمل على تحميل جميع اعتماديات بيئة التطوير الخاصة بإطار العمل، وبالرغم من أن هذه الاعتماديات مفيدة في تسريع عملية التطوير، لكن بمجرد اكتمال العمل على التطبيق وتحويله إلى بيئة الإنتاج، تصبح هذه الاعتماديات غير ضرورية وقد تؤثر سلبًا على أداء التطبيق وتبطئه.
</p>

<p>
	يمكننا تحسين الأداء في بيئة الإنتاج بتنفيذ الأمر التالي الذي يثبيت الاعتماديات الضرورية فقط، ويتجنب تحميل الحزم غير المطلوبة:
</p>

<pre class="ipsCode" id="ips_uid_1162_10">composer install --prefer-dist --no-dev -o
</pre>

<h3 id="-9">
	تحديد المكتبات المضمّنة في التطبيق
</h3>

<p>
	من المميزات المفيدة في إطار لارافيل إمكانية تضمين العدد الذي نريده من المكتبات في التطبيق. لكن بالمقابل ستظهر الآثار السلبية لتلك الميزة في بطئ الأداء والتأثير سلبًا على تجربة المستخدمين. لذا، من المهم مراجعة جميع المكتبات التي نضمنّها في التطبيق، ونحذف المكتبات التي يمكننا الاستغناء عنها من الملف <code>config/app.php</code> لتسريع التطبيق. من المهم أيضًا مراجعة الملف <code>composer.json</code>. الذي يحتوي على قائمة بالاعتماديات أو المكتبات التي يعتمد عليها التطبيق والتأكد من أن لكل مكتبة استخدام فعلي في التطبيق وإلا من الأفضل إزالتها.
</p>

<h3 id="jit">
	استخدام مصرّف JIT
</h3>

<p>
	يمكن لتطبيقات لارافيل الاستفادة بشكل كبير من تقنية المصرّف Just In Time أو JIT اختصارًا لتحسين سرعة المعالجة وتقليل وقت الاستجابة، خصوصًا في التطبيقات الكبيرة التي تحتاج لمعالجة معقدة. فعند تنفيذ شيفرة PHP، فهي تترجم أولاً إلى شيفرة البايت Bytecode ثم تنفذ، وهو ما يتطلب استخدامًا مكثفًا للموارد. ولتنفيذ ذلك، يحتاج تطبيق لارافيل لأدوات وسيطة مثل <a href="https://ar.wikipedia.org/wiki/%D9%85%D8%AD%D8%B1%D9%83_%D8%B2%D9%86%D8%AF" rel="external nofollow">Zend Engine</a> التي تعمل على تشغيل برامج فرعية Subroutines بلغة C تُنفّذ في كل مرة نشغّل فيها التطبيق.
</p>

<p>
	المشكلة أن هذه العمليات تستهلك وقتًا وموارد، لذا يكون من الأفضل تنفيذ عملية الترجمة مرة واحدة، وهذا ما تقوم به تقنية المصرّف JIT الذي يصرّف الشيفرة إلى شيفرة <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D9%87%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A2%D9%84%D8%A9-machine-language-r2272/" rel="">بلغة الآلة</a> مباشرة عند الحاجة فقط، مما يساهم في تسريع الأداء بشكل كبير. ولتحقيق أفضل استفادة من هذه التقنية، يُفضّل استخدام المصرّف <a href="https://github.com/facebook/hhvm" rel="external nofollow">HHVM</a> الذي طورته فيسبوك مع تطبيقات لارافيل.
</p>

<h3 id="-10">
	اختيار أسرع برمجيات لتخزين بيانات الذاكرة المؤقتة والجلسة
</h3>

<p>
	من أفضل طرق تحسين أداء لارافيل تخزين بيانات الذاكرة المؤقتة وبيانات الجلسة ضمن ذواكر <a href="https://academy.hsoub.com/apps/operating-systems/%D8%A7%D9%84%D8%B0%D8%A7%D9%83%D8%B1%D8%A9-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-r880/" rel="">RAM</a>. لهذا تُستخدم برمجيات لتخزين البيانات المؤقتة في الواجهة الخلفية مثل برنامج Memcached مما يساهم في تحسين أداء الإصدار لارافيل. كما يمكننا العثور على إعدادات مكتبة تخزين الجلسات أو برنامج إدارة الجلسات في الملف <code>app/config/session.php</code> بينما يمكننا تحديد برنامج إدارة الذاكرة المؤقتة من خلال الإعداد الموجود في الملف <code>app/config/cache.php</code>.
</p>

<h3 id="-11">
	التخزين المؤقت لنتائج الاستعلام
</h3>

<p>
	يساعدنا التخزين المؤقت لنتائج الاستعلامات التي تتكرر كثيرًا في تطبيقاتنا على تحسين أداء لارافيل. ننصح باستخدام الدالة <code>remember</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9623_6" style=""><span class="pln">$posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Cache</span><span class="pun">::</span><span class="pln">remember</span><span class="pun">(</span><span class="str">'index.posts'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'comments'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tags'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'author'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'seo'</span><span class="pun">)</span><span class="pln">
               </span><span class="pun">-&gt;</span><span class="pln">whereHidden</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
               </span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">();</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span></pre>

<p>
	يخزن الكود السابق نتائج استعلام قاعدة البيانات كالمنشورات مع التعليقات، والوسوم، والمؤلف، وتحسين محركات البحث في الذاكرة المؤقتة. فإذا كانت البيانات موجودة في الذاكرة المؤقتة بالفعل، سنسترجعها بسرعة. وإذا لم تكن موجودة، سينفذ الاستعلام لاسترجاع البيانات من قاعدة البيانات ويخزنها في الذاكرة المؤقتة لمدة 30 دقيقة لتحسين الأداء.
</p>

<h3 id="-12">
	استخدام التوسع الأفقي للتطبيق
</h3>

<p>
	ما نعنيه بالتوسيع الأفقي للتطبيق توزيع الحمل على عدة خوادم بدلاً من الاعتماد على خادم واحد فقط. هذه الطريقة مفيدة عند تزايد عدد الطلبات على الواجهة البرمجية لتطبيقنا، مما يساهم في تحسين الأداء والقدرة على التعامل مع عدد أكبر من المستخدمين على التزامن.
</p>

<p>
	يمكن التفكير في توسيع تطبيق لارافيل أفقيًا في حال ازدادت كثافة المرور على الواجهة البرمجية فهذا يساهم في توزيع الحمل على عدد من الخوادم ويسمح لتطبيقنا بالتعامل طلبات الاتصال المتزامنة بفعالية أكبر. يمكننا من خلال نشر نسخ إضافية من التطبيق على خوادم أخرى توزيع الحمل وتخفيف الضغط وضمان استجابة سريعة، وحتى إن تعطل أحد الخوادم سيستمر التطبيق في العمل مما يزيد ثقة العملاء بالتطبيق ويضمن توافره باستمرار.
</p>

<h3 id="eagerloading">
	استخدام التحميل الشره Eager Loading للبيانات
</h3>

<p>
	تقدم لارافيل الأداة <a href="https://www.google.com/url?q=https://academy.hsoub.com/programming/php/laravel/%25D8%25A7%25D8%25B3%25D8%25AA%25D8%25AE%25D8%25AF%25D8%25A7%25D9%2585-eloquent-orm-%25D9%2584%25D9%2584%25D8%25AA%25D8%25B9%25D8%25A7%25D9%2585%25D9%2584-%25D9%2585%25D8%25B9-%25D9%2582%25D8%25A7%25D8%25B9%25D8%25AF%25D8%25A9-%25D8%25A7%25D9%2584%25D8%25A8%25D9%258A%25D8%25A7%25D9%2586%25D8%25A7%25D8%25AA-%25D9%2581%25D9%258A-laravel-5-r227/&amp;sa=D&amp;source=docs&amp;ust=1724849395666307&amp;usg=AOvVaw2h6A4zjcrEmRDot_do2zEu" rel="external nofollow">Eloquent</a>، وهي أداة ممتازة لربط العلاقات بالكائنات <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D9%85%D8%A8%D8%A7%D8%AF%D8%A6-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D9%91%D8%A9-%D9%84%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-eloquent-orm-r410/" rel="">Object-Relational Mapping</a> حيث تنشئ نماذج تجرّد جداول قاعدة البيانات وتساعد المطورين على استخدام بنى بسيطة للبيانات واستخدام Eloquent لتنفيذ كل العمليات الأساسية على قواعد البيانات بلغة PHP. 
</p>

<p>
	عند استخدام التحميل الشره في لارافيل، ستسترجع كافة البيانات المرتبطة بالنموذج -مثل العلاقات بين الجداول- في نفس الاستعلام الأولي. بمعنى آخر، بدلاً من الانتظار لإجراء استعلامات إضافية عند الوصول إلى هذه البيانات المرتبطة، سينفذ تحميلها جميعًا مرة واحدة وتضمن في الاستجابة الأولى للتطبيق ما يساهم في تحسين الأداء ويقلل عدد الاستعلامات إلى قاعدة البيانات.
</p>

<p>
	لنقارن التحميل البطيء lazy loading مع التحميل الشره، إذ يبدو الاستعلام في حالة التحميل البطيء كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9623_8" style=""><span class="pln">$books </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Book</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$books </span><span class="kwd">as</span><span class="pln"> $book</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $book</span><span class="pun">-&gt;</span><span class="pln">author</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويبدو كما يلي في حالة التحميل الشره:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9623_14" style=""><span class="pln">$books </span><span class="pun">=</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Book</span><span class="pun">::</span><span class="kwd">with</span><span class="pun">(</span><span class="str">'author'</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$books </span><span class="kwd">as</span><span class="pln"> $book</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $book</span><span class="pun">-&gt;</span><span class="pln">author</span><span class="pun">-&gt;</span><span class="pln">name</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الكود أكثر كفاءة لأنه يستخدم التحميل الشره لتحميل العلاقة مع المؤلف مرة واحدة بدلاً من تحميل المؤلف في كل مرة وصول إليه، مما يقلل عدد الاستعلامات المرسلة إلى قاعدة البيانات.
</p>

<h3 id="assetsprecompiling">
	التصريف المسبق للأصول Assets Pre-compiling
</h3>

<p>
	عند تطوير تطبيقات لارافيل، يعمل المطورون على توزيع التطبيق عبر عدة ملفات مثل ملفات config و routes، مما يجعل الشيفرة واضحة وسهلة الإدارة. لكن هذا الأسلوب يتطلب الكثير من العمل لجعل الشيفرة جاهزة للعمل.
</p>

<p>
	يقدم لارافيل بعض الأوامر البسيطة لمساعدة المطورين في تحسين الأداء وتحويل الشيفرة إلى نسخة إنتاجية حيث يمكن استخدامها لتجميع الأصول كالأنماط والسكريبتات والصور في ملفات واحدة وضغطها. 
</p>

<p>
	تساهم هذه الأوامر في تسريع تحميل التطبيق وزيادة كفاءة الشيفرة في بيئة الإنتاج:
</p>

<pre class="ipsCode" id="ips_uid_950_9">php artisan optimize
php artisan config:cache
php artisan route:cache
</pre>

<h3 id="cloudflare">
	استخدام شبكة توزيع المحتوى CDN
</h3>

<p>
	شبكة توزيع المحتوى <a href="https://academy.hsoub.com/devops/networking/%D8%B4%D8%A8%D9%83%D8%A7%D8%AA-%D8%AA%D9%88%D8%B2%D9%8A%D8%B9-%D8%A7%D9%84%D9%85%D8%AD%D8%AA%D9%88%D9%89-content-distribution-networks-r569/" rel="">CDN </a>هي مجموعة من الخوادم الموزعة جغرافيًا في أماكن مختلفة حول العالم، والتي تعمل على تخزين وتوزيع المحتوى الثابت مثل ملفات JavaScript، CSS، الصور، ومقاطع الفيديو بكفاءة أكبر. يفيدنا استخدام شبكة CDN لتطبيقات لارافيل في تحسين أداء تحميل الأصول الثابتة للموقع من خلال تقديمها من أقرب خادم جغرافي للمستخدم بدلاً من تحميلها من الخادم الرئيسي للموقع. عندما يزور المستخدم الموقع، تعمل <a href="https://academy.hsoub.com/devops/networking/%D8%B4%D8%A8%D9%83%D8%A7%D8%AA-%D8%AA%D9%88%D8%B2%D9%8A%D8%B9-%D8%A7%D9%84%D9%85%D8%AD%D8%AA%D9%88%D9%89-content-distribution-networks-r569/" rel="">CDN</a> على توجيه الطلب إلى أقرب خادم له، مما يقلل المسافة الجغرافية التي يجب على البيانات قطعها، وبالتالي يسرع من عملية تحميل الصفحة خاصة في الحالات التي يكون فيها المحتوى ثابتًا وغير قابل للتغيير بشكل متكرر، مثل الصور أو ملفات CSS.
</p>

<h3 id="-13">
	استخدام أداة Mix لتجميع الأصول
</h3>

<p>
	تأتي الأداة Mix افتراضيًا مع كل تطبيقات لارافيل، تؤمن هذه الأداة واجهة برمجية فعالة لبناء حزمة <a href="https://academy.hsoub.com/programming/workflow/%D8%AF%D9%84%D9%8A%D9%84-webpack-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-r866/" rel="">Webpack</a> لتطبيقات PHP باستخدام المعالجات الأولية pre processors لملفات CSS وملفات جافا سكريبت  مما يساعد على تحسين إدارة أصول التطبيق وتحسين الأداء.
</p>

<p>
	على سبيل المثال، يمكننا دمج عدة ملفات CSS أو JavaScript في ملف واحد، مما يقلل عدد الطلبات المرسلة للخادم ويحسن من سرعة تحميل الصفحة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9623_24" style=""><span class="pln">mix</span><span class="pun">.</span><span class="pln">styles</span><span class="pun">([</span><span class="pln">
    </span><span class="str">'public/css/vendor/normalize.css'</span><span class="pun">,</span><span class="pln"> 
    </span><span class="str">'public/css/styles.css'</span><span class="pln">
</span><span class="pun">],</span><span class="pln"> </span><span class="str">'public/css/all.css'</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	تُنشئ الشيفرة السابقة ملف CSS باسم <code>all.css</code> يضم التنسيقات الموجودة في الملفين <code>normalize.css</code> و <code>styles.css</code>. وبهذا سنتمكن من استخدام الملف الجديد بسهولة ضمن شيفرة HTML بدلًا من تضمين الملفين السابقين.
</p>

<h3 id="-14">
	تصغير حجم الأصول
</h3>

<p>
	عند تجميع الأصول في ملف واحد، قد ينتج عن ذلك ملف كبير جدًا. وعلى الرغم من أن هذا يحسن من عدد الطلبات، إلا أنه قد لا يحقق أفضل استفادة من فكرة التصريف أو  التخزين المؤقت caching التي تحدثنا عنها سابقًا. لهذا، من الأفضل تقليل حجم الأصول بقدر المستطاع لتسريع تحميل الصفحة من خلال الأمر التالي:
</p>

<pre class="ipsCode">$ npm run production
</pre>

<p>
	يُنفذ الأمر السابق جميع مهام Mix اللازمة لضبط الأصول بشكل يتناسب مع النسخة النهائية من التطبيق. وهو يتضمن تصغير ملفات CSS و JavaScript ودمجها لتقليل حجمها ما يؤدي إلى تسريع تحميلها وبالتالي تحسين أداء التطبيق.
</p>

<h3 id="php">
	استخدام أحدث نسخ PHP
</h3>

<p>
	يساهم تحميل أحدث إصدار من لغة PHP في تحسين أداء التطبيق بشكل كبير. لذا، من الضروري التأكد من تشغيل أحدث نسخة من PHP في تطبيقات لارافيل للاستفادة من التحسينات التي تقدمها النسخ الجديدة، سواء على صعيد الأداء أو الأمان، وتجنب المشكلات المرتبطة بالسرعة وضمان تجربة مستخدم أفضل.
</p>

<h3 id="-15">
	استخدام المنقح Debugger
</h3>

<p>
	على الرغم من أن منقّح لارافيل Laravel Debugbar ليس تقنية مباشرة لتحسين أداء تطبيقات لارافيل، إلا أداة هامة لمراقبة وتحليل أداء التطبيقات. فهو يساعدنا في دمج شريط تنقيح PHP مع لارافيل ويظهره في المتصفح أثناء تشغيل التطبيق، مما يفيدنا في مراقبة عدة أمور في تطبيقنا مثل مدة استجابة التطبيق، ووقت تنفيذ الاستعلامات، وفحص الشيفرة البرمجية، لتحديد المشكلات التي قد تؤثر على كفاءة التطبيق أو التي تؤثر سلبًا على الأداء.
</p>

<h2>
	استخدام إضافات مفيدة لتحسين تطبيقات لارافيل
</h2>

<p>
	يمكننا تنزيل أدوات مفيدة في تحسين تطبيقات لارافيل مثل إضافة تسريع صفحات لارافيل Laravel Page Speed التي تساعد في تقليل حجم البيانات المرسلة إلى المتصفح، مما يسرّع تحميل الصفحات.
</p>

<p>
	نثبت الحزمة ونستخرج الملفات من <code>renatomarinho/laravel-page-speed package</code> باستخدام الملحن Composer ونضيف اسم الحزمة مع تفاصيل نسختها إلى الملف <code>composer.json</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_950_13" style=""><span class="str">"require"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> 
</span><span class="pun">......</span><span class="pln">
</span><span class="pun">......</span><span class="pln">
</span><span class="str">"renatomarinho/laravel-page-speed"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"^1.8"</span><span class="pln">
</span><span class="pun">},</span></pre>

<p>
	ثم ننفذ أمر تحديث الملحن Composer كما يلي:
</p>

<pre class="ipsCode">composer update
</pre>

<p>
	بعد استخراج ملفات الحزمة السابقة، نضيف مزود الخدمة الخاص بها من خلال الانتقال إلى الملف <code>config/app.php</code> وإضافة السطر التالي:
</p>

<pre class="ipsCode">'providers' =&gt; [ 
 ....
 ....
RenatoMarinho\LaravelPageSpeed\ServiceProvider::class,
],
</pre>

<p>
	بعد ذلك، يجب نشر الحزمة حتى نتمكن من استخدامها في التطبيق. يساعد الأمر التالي غلى نشر الحزمة، ولا نستطيع استخدامها قبل تنفيذه:
</p>

<pre class="ipsCode">php artisan vendor:publish --provider="RenatoMarinho\LaravelPageSpeed\ServiceProvider"
</pre>

<p>
	بعد نشر الحزمة، لا بد من إضافة تفاصيل Middleware الخاص بها في الملف <code>app/Http/Kernel.php</code> حتى تتمكن من العمل مع الطلبات الواردة إلى التطبيق. لهذا، ننسخ الشيفرة التالية ونلصقها بعد المصفوفة <code>middlewareGroups$</code><span>:</span>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_9623_29" style=""><span class="kwd">protected</span><span class="pln"> $middlewareGroups </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'web'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="com">// بعض الوسطاء السابقين...</span><span class="pln">

        \RenatoMarinho\LaravelPageSpeed\Middleware\InlineCss</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
        \RenatoMarinho\LaravelPageSpeed\Middleware\ElideAttributes</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
        \RenatoMarinho\LaravelPageSpeed\Middleware\InsertDNSPrefetch</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
        \RenatoMarinho\LaravelPageSpeed\Middleware\RemoveComments</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
        \RenatoMarinho\LaravelPageSpeed\Middleware\TrimUrls</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
        \RenatoMarinho\LaravelPageSpeed\Middleware\RemoveQuotes</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
        \RenatoMarinho\LaravelPageSpeed\Middleware\CollapseWhitespace</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">]</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

</span><span class="com">/* تعريف وجهة */</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/listView'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'listView'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	ننشئ في النهاية قالب Laravel Blade ونضع ضمنه الشيفرة لعرضها.
</p>

<h2 id="-22">
	أدوات مفيدة لمراقبة أداء تطبيقات لارافيل
</h2>

<p>
	يساعدنا مراقبة أداء تطبيقات لارافيل على تحديد الجوانب التي تحتاج إلى تطوير وتحسين في تطبيقنا، وفيما يلي نستعرض بعض الأداوت المفيدة لتحقيق ذلك.
</p>

<h3 id="blackfireio">
	الأداة Blackfire.io
</h3>

<p>
	تُعد <a href="https://www.blackfire.io/" rel="external nofollow">Blackfire.io</a> أداة مفيدة لمراقبة أداء التطبيقات وتنقيحها، فهي تزود المطورين ببيانات مفصلة عن أداء تطبيقاتهم وتوفر لهم إرشادات مفيدة لتحديد أي اختناقات تؤدي إلى بطء التطبيق. كما تساعد على تحديد المشكلات التي تؤثر على الأداء سواء كانت على مستوى الشيفرة أو استعلامات قواعد البيانات أو استدعاءات واجهات برمجية خارجية. وتتكامل هذه الأداة بسلاسة مع أطر عمل PHP مثل لارافيل و Symfony وغيرها، مما يُسهل إعدادها واستخدامها في تحليل الأداء.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169870" href="https://academy.hsoub.com/uploads/monthly_2025_03/01_blackfire.png.74168513bd3b88f5b6be0b0a574e57fd.png" rel=""><img alt="01 blackfire" class="ipsImage ipsImage_thumbnailed" data-fileid="169870" data-unique="p6fa9k5ss" style="width: 700px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/01_blackfire.thumb.png.bcb5796019fbcd63a78d1500d08e85cb.png"> </a>
</p>

<h3 id="laraveldusk">
	الأداة Laravel Dusk
</h3>

<p>
	أداة اختبار End-to-End لإطار العمل لارافيل مصممة لتبسيط الاختبارات المؤتمتة للمتصفح في تطبيقات الويب، فاختبار  End-to-End  هو نوع من الاختبارات الآلية التي تحاكي سلوك المستخدم الحقيقي في التطبيق، مثل تسجيل الدخول والخروج وتعبئة النماذج وإرسالها والتنقل بين الصفحات والتأكد من ظهور العناصر في الواجهة بشكل صحيح.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169871" href="https://academy.hsoub.com/uploads/monthly_2025_03/02_laravel_dusk.png.b54a29b58e2dd8d2f8256cee27c6f7a1.png" rel=""><img alt="02 laravel dusk" class="ipsImage ipsImage_thumbnailed" data-fileid="169871" data-unique="n03sv9ouz" style="width: 700px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/02_laravel_dusk.thumb.png.a0be4a220e8c8825ed987d1027fa0123.png"> </a>
</p>

<h3 id="loadforge">
	الأداة LoadForge
</h3>

<p>
	وهي منصة سحابية تساعد المطورين في قياس قدرة التطبيقات والواجهات البرمجية على التعامل مع ضغط العمل. فمن خلال هذه الأداة يمكننا محاكاة دخول آلاف المستخدمين في نفس الوقت، مما يتيح لنا تقييم أداء المواقع والواجهات البرمجية تحت ضغط مكثف ويساعدنا في تحديد فيما إذا كان التطبيق يحتاج إلى التوسيع لتحمل المزيد من المستخدمين.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169872" href="https://academy.hsoub.com/uploads/monthly_2025_03/03_loadforge.png.fd4cd2bb951da809b0d06944d54401a6.png" rel=""><img alt="03 loadforge" class="ipsImage ipsImage_thumbnailed" data-fileid="169872" data-unique="nti74cqg5" style="width: 700px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/03_loadforge.thumb.png.54817e9e1becce6a3feaf4827af9b7a5.png"> </a>
</p>

<p>
	 
</p>

<h2 id="-23">
	الخاتمة
</h2>

<p>
	استعرضنا في هذا المقال مجموعة من النصائح والممارسات الفعالة لتحسين أداء تطبيقات لارافيل، إلى جانب أدوات قوية تساعد في التعامل مع مختلف متطلبات العمل. ننصح بتطبيق هذه النصائح والاستفادة منها لبناء تطبيقات أسرع وأكثر كفاءة، وموثوقية، ويمكنها التكيف مع توسع التطبيق وزيادة عدد المستخدمين بسلاسة.
</p>

<p>
	ترجمة -وبتصرف- للمقال: <a href="https://www.cloudways.com/blog/laravel-performance-optimization/" rel="external nofollow">17 Tips for Laravel Performance Optimization in 2024</a> لصاحبه <a href="https://www.cloudways.com/blog/author/mansoorahmed/" rel="external nofollow">Mansoor Ahmed Khan</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D9%81%D8%B6%D9%84-%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%84%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2530/" rel="">أفضل الحزم البرمجية لتحسين تطبيقات لارافيل</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%A8%D9%8A%D9%86-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%88%D9%88%D8%B1%D8%AF%D8%A8%D8%B1%D9%8A%D8%B3-%D9%88%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%81%D9%8A-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r2538/" rel="">مقارنة بين استخدام ووردبريس ولارافيل في تطوير الويب</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-%D9%84%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2425/" rel="">إنشاء واجهة أمامية لمدونة باستخدام لارافيل</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%84%D8%BA%D8%A9-php-r2040/" rel="">تعرف على لغة PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2544</guid><pubDate>Tue, 25 Mar 2025 13:00:00 +0000</pubDate></item><item><title>&#x645;&#x642;&#x627;&#x631;&#x646;&#x629; &#x628;&#x64A;&#x646; &#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x648;&#x648;&#x631;&#x62F;&#x628;&#x631;&#x64A;&#x633; &#x648;&#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; &#x641;&#x64A; &#x62A;&#x637;&#x648;&#x64A;&#x631; &#x627;&#x644;&#x648;&#x64A;&#x628;</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%A8%D9%8A%D9%86-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%88%D9%88%D8%B1%D8%AF%D8%A8%D8%B1%D9%8A%D8%B3-%D9%88%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%81%D9%8A-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r2538/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2025_03/-_.png.2c59b3015f6f8d7148e5cb0b96ea41ac.png" /></p>
<p>
	تبرز منصتا ووردبريس ولارافيل كخيارات مثالية في عالم الويب الذي يتطور باستمرار، هذا قد يدفعنا للتساؤل ما الخيار الأفضل من بينهما لتطوير الويب، والجواب على هذا السؤال يعتمد على طبيعة احتياجاتنا، ويحتاج منا لفهم نقاط القوة التي تميز كل منصة ونقاط الضعف المحتملة.
</p>

<p>
	نقارن في هذا المقال بين لارافيل و ووردبريس، ونحاول تقديم رؤية واضحة من خلال البحث في جوانب حساسة تتعلق بالمرونة وإمكانية زيادة حجم الأعمال والأمان وسهولة الاستخدام وقابلية توسيع المنصة extensibility كي نتخذ قرارًا مدروسًا.
</p>

<h2 id="-1">
	نظرة عامة على لارافيل و ووردبريس
</h2>

<p>
	قبل أن ننتقل إلى المقارنة بين إطاري العمل، لنلقِ نظرة سريعة عامة عليهما.
</p>

<h3 id="-2">
	نظرة عامة على لارافيل
</h3>

<p>
	<a href="https://www.google.com/url?q=https://academy.hsoub.com/programming/php/laravel/%25D8%25AA%25D8%25B9%25D8%25B1%25D9%2581-%25D8%25B9%25D9%2584%25D9%2589-%25D8%25A5%25D8%25B7%25D8%25A7%25D8%25B1-%25D8%25B9%25D9%2585%25D9%2584-%25D8%25AA%25D8%25B7%25D9%2588%25D9%258A%25D8%25B1-%25D8%25A7%25D9%2584%25D9%2588%25D9%258A%25D8%25A8-%25D8%25A7%25D9%2584%25D8%25B4%25D9%2587%25D9%258A%25D8%25B1-%25D9%2584%25D8%25A7%25D8%25B1%25D8%25A7%25D9%2581%25D9%258A%25D9%2584-laravel-r2093/&amp;sa=D&amp;source=docs&amp;ust=1724849948669590&amp;usg=AOvVaw3wXzk9FIAxF6Ln9zceIjgS" rel="external nofollow">لارافيل</a> هو إطار عمل <a href="https://academy.hsoub.com/programming/general/%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-framework/" rel="">framework</a> لتطوير الويب يعتمد على لغة PHP ويكتسب شعبية متزايدة بين المطورين، وقد اكتسب شعبيته نظرًا لصياغته المحسنّة وتوثيقه الشامل ووجود مجتمع داعم كبير ونشط. تظهر قوة الإطار في إنتاج تطبيقات ويب مخصصة وقابلة للتوسع.
</p>

<p>
	يقدم لارافيل مجموعة ملفتة من الميزات ويضم طبقة ORM فعّالة للتفاعل مع قاعدة البيانات حيث توفر هذه الطبقة واجهة لتمثيل الجداول في قاعدة البيانات ككائنات objects. ومنظومة توجيه Routing قوية، وصياغة قواعدية Syntax سهلة الفهم. تجعل هذه الميزات من لارافيل خيارًا ممتازًا للمطورين الذي يرغبون في بناء تطبيقات أكثر تخصصًا وقدرة على التكيف.
</p>

<h3 id="-3">
	نظرة عامة على ووردبريس
</h3>

<p>
	تخطى <a href="https://academy.hsoub.com/wordpress/&amp;sa=D&amp;source=docs&amp;ust=1724849948669969&amp;usg=AOvVaw0CgnSLXmMNEBjgRA3wiTio/" rel="">ووردبريس</a> الغاية الأصلية له كمنصة لإنشاء المدونات وتعداها ليصبح نظام إدارة محتوى Content Management System متعدد المهام يدعم أكثر من <a href="https://wordpress.org/40-percent-of-web/" rel="external nofollow">40% </a>من مواقع الويب عالميًا، ولا تزال سمعته كمنصة لإنشاء وإدارة محتوى ويب سهل الاستخدام لا جدال فيها.
</p>

<p>
	تمكن ووردبريس من جذب الكثير من الاهتمام بفضل واجهته الواضحة سهلة الاستخدام والعدد الكبير من ا<a href="https://picalica.com/templates/wordpress" rel="external nofollow">لقوالب</a> والإضافات التي يوفرها وسهولة تشغيله. ويعد إطاراً مناسبًا للأفراد أو الأعمال الصغيرة التي تطمح إلى تأسيس موقع ويب دون الحاجة إلى خبرة تقنية كبيرة.
</p>

<h2 id="-4">
	مقارنة سريعة بين لارافيل و ووردبريس
</h2>

<table>
	<thead>
		<tr>
			<th style="text-align:right;">
				الميزة
			</th>
			<th style="text-align:right;">
				لارافيل
			</th>
			<th style="text-align:right;">
				ووردبريس
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style="text-align:right;">
				نوع إطار العمل
			</td>
			<td style="text-align:right;">
				إطار عمل PHP مع أسلوب MVC
			</td>
			<td style="text-align:right;">
				نظام إدارة محتوى CMS
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				نموذج التطوير
			</td>
			<td style="text-align:right;">
				برمجة كائنية التوجه <abbr title="Object-Oriented Programming | البرمجة كائنية التوجه"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></abbr>
			</td>
			<td style="text-align:right;">
				برمجة إجرائية مع بعض الكائنية
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				تنظيم الشيفرة
			</td>
			<td style="text-align:right;">
				تتبع أسلوب MVC أي نموذج وعرض ومتحكم
			</td>
			<td style="text-align:right;">
				مرن نسبيًا، يتبع هيكلية القوالب والإضافات
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				إمكانية التخصيص
			</td>
			<td style="text-align:right;">
				عالية جدًا
			</td>
			<td style="text-align:right;">
				محدودة بالقوالب والإضافات
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				منحني التعلم
			</td>
			<td style="text-align:right;">
				منحني تعلم متدرج
			</td>
			<td style="text-align:right;">
				أسهل تعلمًا وخاصة للمبتدئين
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				الأداء
			</td>
			<td style="text-align:right;">
				محسّن جدًا وسريع
			</td>
			<td style="text-align:right;">
				قد يتأثر الأداء بالإضافات
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				دعم قواعد البيانات
			</td>
			<td style="text-align:right;">
				يدعم عدة قواعد بيانات من خلال تقنية ORM مثل Eloquent
			</td>
			<td style="text-align:right;">
				دعم مضمّن لقاعدة البيانات MySQL مع دعم قواعد بيانات أخرى
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				الأمان
			</td>
			<td style="text-align:right;">
				يوفر معايير أمان مرتفعة
			</td>
			<td style="text-align:right;">
				عرضة للهجمات إن لم نعمل على صيانته باستمرار
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				إمكانية التوسع
			</td>
			<td style="text-align:right;">
				مناسب لبناء تطبيقات قابلة للتوسع
			</td>
			<td style="text-align:right;">
				يعتمد على الإضافات وعلى الخادم
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				مجتمع الداعمين
			</td>
			<td style="text-align:right;">
				مجتمع كبير ونشط
			</td>
			<td style="text-align:right;">
				مجتمع ضخم وداعم
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حالات الاستخدام
			</td>
			<td style="text-align:right;">
				تطبيقات ويب معقدة وواجهات برمجية
			</td>
			<td style="text-align:right;">
				مدونات ومواقع ويب صغيرة إلى متوسطة
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				سرعة التطوير
			</td>
			<td style="text-align:right;">
				يتطلب وقتًا في تنفيذ الإعدادات الأولية وضبطها
			</td>
			<td style="text-align:right;">
				إعدادات سريعة وميزات وقوالب جاهزة للاستخدام
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				الصيانة
			</td>
			<td style="text-align:right;">
				يحتاج إلى تحديث منتظم وصيانة
			</td>
			<td style="text-align:right;">
				يحتاج إلى تحديث متكرر وصيانة
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				التكلفة
			</td>
			<td style="text-align:right;">
				مجاني ومفتوح المصدر
			</td>
			<td style="text-align:right;">
				مجاني ومفتوح المصدر
			</td>
		</tr>
	</tbody>
</table>

<h2 id="-5">
	المقارنة الشاملة بين لارافيل و ووردبريس
</h2>

<p>
	بعد أن تعرفنا سريعًا على كلتا المنصتين، بإمكاننا الآن المقارنة بينهما من عدة نواحٍ:
</p>

<h3 id="1">
	1- الأداء وإمكانية التوسع
</h3>

<p>
	تعد ميزات الأداء والتوسع ذات أهمية كبيرة في تطوير الويب حاليًا لأنها تؤثر بشكل كبير على تجربة المستخدمين، وزمن تحميل الصفحات، والاستجابة الكلية للتطبيق أو الموقع. لنوضح كيف تتعامل كلتا المنصتين مع هذه النواحي الحيوية:
</p>

<h4 id="-6">
	لارافيل
</h4>

<p>
	لارفيل هو إطار عمل للغة PHP كما ذكرنا سابقًا، لهذا يستخدم مجموعة من التقنيات لتحسين الأداء وتنفيذ العمليات بسلاسة. ونظرًا لكون لارافيل مبني على الوحدات البرمجية وتوسيع الشيفرة فهو يتيح للمطورين بناء تطبيقات قادرة على النمو. ومن خلال دعم لارافيل لإمكانيات التوسع الأفقي، فإنه يستطيع إدارة التطبيقات الموزعة على عدة خوادم باستخدام أدوات مثل موازنات الحمل. كما يسهل لارافيل التعامل مع المهام المتزامنة كونه يدعم أنظمة الأرتال queueing systems مثل Redis و RabbiMO. إضافة إلى ذلك، تستفيد منصة لارافيل من فعالية محرّك PHP الذي يُحدّث ويُحسّن باستمرار.
</p>

<h4 id="-7">
	ووردبريس
</h4>

<p>
	بُني نظام ووردبريس بشكل رئيسي باستخدام <a href="https://www.google.com/url?q=https://wiki.hsoub.com/PHP&amp;sa=D&amp;source=docs&amp;ust=1724849948670094&amp;usg=AOvVaw0onuxWM83sCGk6OeWdXMI-" rel="external nofollow">PHP</a>، وقد خضع لترقيات مهمة في السنوات الأخيرة لتحسين الأداء قدر الإمكان. يوفر ووردبريس مكتبة واسعة من الإضافات والقوالب التي تسمح للمستخدمين يتطوير وتخصيص مواقعهم بسرعة وسهولة.
</p>

<p>
	وعلى الرغم من أن نظام ووردبريس قد صمم أساسًا لبناء مواقع ويب صغيرة الحجم ومحدودة الموارد، إلا أنه يسمح لنا بتعزيز موارد الموقع عند الحاجة  باستخدام إضافات التخزين المؤقت، وشبكات توزيع المحتوى <a href="https://academy.hsoub.com/apps/web/wordpress/4-%D8%B7%D8%B1%D9%82-%D9%84%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%B4%D8%A8%D9%83%D8%A9-%D8%AA%D9%88%D8%B5%D9%8A%D9%84-%D8%A7%D9%84%D9%85%D8%AD%D8%AA%D9%88%D9%89-cdn-%D8%A5%D9%84%D9%89-%D9%88%D9%88%D8%B1%D8%AF%D8%A8%D8%B1%D9%8A%D8%B3-r908/" rel="">CDN</a>، واستخدام بيئة استضافة محسنة لإدارة حركة البيانات الكثيفة فهذه التقنيات تعزز أداء مواقع ووردبريس بشكل كبير.
</p>

<h3 id="2">
	2- سهولة التطوير
</h3>

<p>
	يضع المطورون الأولوية لسهولة تطوير التطبيقات عند اختيارهم لأي منصة أو إطار العمل. لهذا، نناقش في هذه الفقرة الفرق بين لارافيل و ووردبريس من ناحية منحنيات التعلم والموارد والتوثيق ودعم المجتمع الخاص بكل إطار.
</p>

<h4 id="-8">
	لارافيل
</h4>

<p>
	يتميز لارافيل بصياغته القواعدية الأنيقة وميزاته المصممة خصيصًا لتسهيل عمل المطورين، وأولوياته في دعم سهولة تطوير المنتجات. إذ يقدم لارافيل أساس برمجي واضح البناء ومباشر وشيفرة سهلة الصيانة. وتبسط بيئة عمل لارافيل التي تضم حزم مضمّنة جاهزة المهام البرمجية الشائعة مثل التوجيه routing والاستيثاق authentication والتفاعل مع قواعد البيانات والتخزين المؤقت للبيانات.
</p>

<p>
	تتمحور فلسفة لارافيل الجوهرية حول فكرة إنتاجية المطور وسهولة الاستخدام، وتعزز إمكانية إعادة استخدام الشيفرة لتسهيل صيانة وتحديث المنتج.
</p>

<h4 id="-9">
	ووردبريس
</h4>

<p>
	تدور فكرة التطوير في ووردبريس حول البساطة وسهولة الوصول، فهو يزود المستخدم بلوحة إدارة سهلة الاستخدام لتسريع إدارة المحتوى وتخصيصه. وتُعد قوالب وإضافات ووردبريس عناصر بناء التطبيقات التي تسمح للمطور بتوسيع التصميم ووظائف التطبيق دون العودة إلى نقطة الصفر.
</p>

<p>
	وتمكّن خطافات ووردبريس hooks ومرشحاته filters وقوالبه ذات البنية الهرمية وميزة التحديث التلقائي من بناء أقسام مميزة في مواقع الويب، وتعديل الوظائف البنيوية وضمان بقاء الموقع محدّثًا بأدنى جهد ممكن.
</p>

<h3 id="3">
	3- سهولة الاستخدام
</h3>

<p>
	تؤثر سهولة استخدام المنصات على تجربة المستخدم ورضاه، لنلق نظرة الآن على ما يقدمه كل من لارافيل و ووردبريس في هذا الشأن
</p>

<h4 id="-10">
	لارافيل
</h4>

<p>
	يركز لارافيل على سهولة الاستخدام من قبل المطورين أساسًا وبعدها سهولة الاستخدام من قبل المستخدم النهائي، حيث يوفر للمطور قاعدة واضحة وسهلة القراءة لكتابة الشيفرة. كما يبسّط التوثيق الشامل والهيكلية الجيدة للواجهات البرمجية من عملية التطوير.
</p>

<p>
	كما صممت ميزات لارافيل مثل التوجيه routing وإدارة قواعد البيانات والتوثيق لتكون سهلة الاستخدام من قبل المطورين، مما يعطي فعالية أكبر في التطوير دون المساس بالمرونة.
</p>

<h4 id="-11">
	ووردبريس
</h4>

<p>
	يتمير ووردبريس بسهولة الاستخدام، سواء للمطورين أو المستخدمين غير المختصين. إذ فهو يوفر للمستخدمين واجهة سهلة الاستخدام، إضافة إلى لوحة تحكم واضحة ومكتبات كثيرة للقوالب والإضافات ويوفر أدوات لبناء الصفحات عبر تقنية السحب والإفلات، مما يجعل تخصيص مواقع الويب أمرًا سهلًا دون الحاجة إلى خبرات برمجية كبيرة.
</p>

<h3 id="4">
	4- الأمان والصيانة
</h3>

<p>
	يعد موضوع الأمان والصيانة من أكثر الأمور أهمية عند اختيار منصة العمل، لنلق نظرة على ما تقدمه لارافيل و ووردبريس في هاتين الناحيتين.
</p>

<h4 id="-12">
	لارافيل
</h4>

<p>
	يقدم لارافيل حماية مضمّنة من ثغرات الويب الشائعة مثل السكربتات <a href="https://www.google.com/url?q=https://academy.hsoub.com/programming/advanced/%25D8%25AA%25D8%25B9%25D8%25B1%25D9%2581-%25D8%25B9%25D9%2584%25D9%2589-%25D8%25A3%25D9%2585%25D8%25A7%25D9%2586-%25D9%2585%25D9%2588%25D8%25A7%25D9%2582%25D8%25B9-%25D8%25A7%25D9%2584%25D9%2588%25D9%258A%25D8%25A8-r2020/&amp;sa=D&amp;source=docs&amp;ust=1724849948671399&amp;usg=AOvVaw2Ssid1-xeJe_wAu6FeaXNZ" rel="external nofollow">العابرة للمواقع</a> cross-site scripting وسكربتات انتحال الشخصية request forgery وهجوم حقن SQL. إذ يتجاوز باني الاستعلامات وطبقة ORM في لارافيل أي محارف مشبوهة في مدخلات المستخدم للحماية من حقن SQL، وتدعم كلمات السر المرمّزة بما في ذلك ميزات أمنية مثل مفاتيح التحقق CSFR والتعامل الآمن مع الجلسات.
</p>

<h4 id="-13">
	ووردبريس
</h4>

<p>
	يلتزم ووردبريس بتقديم منصة آمنة وتنفيذ معايير أمنية متعددة. وتستهدف تحديثاتها المنتظمة الثغرات التي تظهر ويراقب فريق متخصص المشاكل الأمنية بنشاط ويستجيب لأي مشكلات قد تظهر لاحقًا. إضافة إلى ذلك، يحسن ووردبريس من القدرات الأمنية للتطبيقات من خلال إضافات مخصصة تقدم ميزات مثل فحص البرمجيات الضارة والحماية خلف جدار ناري وتسجيل الدخول الآمن.
</p>

<h3 id="5">
	5- الشعبية
</h3>

<p>
	تلعب شعبية المنصة دورًا مهمًا في اختيارها، فهي تعكس نسبة تبني هذه المنصة والدعم المقدم من مجتمعها وطبيعة بيئة العمل فيها.
</p>

<h4 id="-14">
	لارافيل
</h4>

<p>
	يعود سبب الزيادة الكبيرة في شعبية لارافيل إلى الدعم القوي الذي يقدمه مجتمع دعم المنصة وبيئة العمل التي تدعم التوسع.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169609" href="https://academy.hsoub.com/uploads/monthly_2025_03/01_laravel_popularity.png.088377af7491b32109fdefec38e1a073.png" rel=""><img alt="01 laravel popularity" class="ipsImage ipsImage_thumbnailed" data-fileid="169609" data-ratio="82.33" data-unique="c865uvdnp" style="width: 400px; height: auto;" width="300" src="https://academy.hsoub.com/uploads/monthly_2025_03/01_laravel_popularity.thumb.png.40a0953885d31303a4aaa7136123f6e2.png"> </a>
</p>

<p style="text-align: center;">
	المصدر <a href="https://trends.builtwith.com/framework/laravel" rel="external nofollow">trends.builtwith</a>
</p>

<p>
	يضمن التطوير الفعال للارافيل والتحديثات المستمرة التي تنفذ عليها وصول المطورين إلى أحدث الميزات والتحسينات والتحديثات الأمنية. وتشير شعبية لارافيل المتزايدة إلى الطلب الكبير عليه في سوق العمل، وهذا ما يقدم فرص عمل أوسع لمطوري لارافيل المحترفين.
</p>

<h4 id="-15">
	ووردبريس
</h4>

<p>
	ترجع شعبية ووردبريس إلى القاعدة المعرفية الواسعة لهذه المنصة والدعم الكافي من قبل مجتمعها.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169610" href="https://academy.hsoub.com/uploads/monthly_2025_03/02_wordpress_popularity.png.01bec0292db12f5143a51da05c8f7d2f.png" rel=""><img alt="02 wordpress popularity" class="ipsImage ipsImage_thumbnailed" data-fileid="169610" data-ratio="86.50" data-unique="dsl9l1pka" style="width: 400px; height: auto;" width="400" src="https://academy.hsoub.com/uploads/monthly_2025_03/02_wordpress_popularity.thumb.png.84b5cb80ec2fc4ae7498c338ae663f74.png"> </a>
</p>

<p style="text-align: center;">
	المصدر <a href="https://trends.builtwith.com/framework/WordPress" rel="external nofollow">trends.builtwith</a>
</p>

<p>
	تساعد القوالب والإضافات الكثيرة والمتنوعة في تقديم تصاميم ووظائف مختلفة، كما تثري التطويرات المستمرة التي يقدمها مجتمع ووردبريس من بيئة العمل وتعززها.
</p>

<h3 id="6">
	6- الاستضافة
</h3>

<p>
	إن اختيار الاستضافة المناسبة لموقعنا أو تطبيقنا أمر حيوي جدًا لأدائه وأمانه وتوفّره المستمر. لنرى كيف يكون نهج الاستضافة في كلتا المنصتين.
</p>

<h4 id="-16">
	لارافيل
</h4>

<p>
	لا تتطلب منصة لارافيل أية متطلبات خاصة بالاستضافة نظرًا لمرونتها وكونها إطار عمل للغة PHP. ويمكن للمطورين الاستفادة من مزودات الاستضافة التي تقدم عروضًا مخصصة لمنصة لارافيل أو التي تقدم بيئة عمل محسنة للتطبيقات المبنية على هذه المنصة.
</p>

<h4 id="-17">
	ووردبريس
</h4>

<p>
	صممت منصة ووردبريس لتكون متوافقة مع عدد كبير من بيئات الاستضافة، لكن علينا التفكير بعدة عوامل مثل أداء الخادم وسعة التخزين وحزمة تخديم البيانات ودعم العملاء عند البحث عن استضافة مناسبة لووردبريس. كما تقدم مزودات الاستضافة المخصصة لإدارة تطبيقات ووردبريس إعدادات محسنة للخادم وتحديثات تلقائية وميزات أمان إضافية.
</p>

<h2 id="-18">
	المقارنة بين لارافيل و ووردبريس من ناحية التكلفة
</h2>

<p>
	من الأمور المهمة جدًا في المقارنة بين لارافيل ووردبريس مسألة التكلفة المادية. فمعرفة هيكلية التسعير وخيارات الاستضافة ستساعدنا في اختيار الحل الأكثر فعالية.
</p>

<h3 id="-19">
	تكلفة لارافيل
</h3>

<p>
	لارافيل بحد ذاته مجاني الاستخدام، لكن أي مساعدة في تطوير تطبيقات لارافيل وصيانتها لن تكون رخيصة. وقد يكون مجال تلك التكلفة في الولايات المتحدة الأمريكية مثلًا بين 20-100 دولار في الساعة، مما يجعل كلفة موقع الويب بأكمله بين 3000 و 250 ألف دولار، وفقًا لمتطلبات المشروع وتعقيدها، وبالطبع تختلف هذه الأرقام من منطقة جغرافية لأخرى. كما نضيف إلى ذلك كلفة الاستضافة وقيمتها بالحد الأدنى 10 دولارات شهريًا.
</p>

<h3 id="-20">
	تكلفة ووردبريس
</h3>

<p>
	تختلف تكلفة تطبيقات ووردبريس بحسب إن كنا سنصمم التطبيق بأنفسنا أو نستعين بشركة أو وكالة تطوير. فقد يكلف التطبيق إن قررنا تصميمه بنفسنا بين 20 إلى 300 دولار كما يصل إلى مجال 500-5000 دولار في حال الاستعانة بمطور مستقل وترتفع تكلفة التطوير إلى 3000-100000 دولار إن أردنا الاعتماد على شركة تطوير، ومن جديد ننوه لأن هذه الأرقام  تختلف من منطقة جغرافية لأخرى.
</p>

<p>
	وتتراوح نفقات الصيانة بين 25 دولار في الشهر للصيانة الذاتية وما بين 50 إلى 100 دولار إن استعنا بمطور مستقل، كما قد تصل إلى 450 دولار إن اعتمدنا على شركة مختصة. كما نضيف إلى ذلك كلفة الاستضافة بحد ذاتها والتي تختلف في حدها الأدنى وفق مزود الاستضافة، وقد لا تقل عن 10 دولار شهريًا.
</p>

<p>
	وتتعلق تكلفة الاستضافة عمومًا بحجم الموقع وحجم تبادل البيانات المسموح شهريًا إضافة إلى بعض الميزات الأخرى التي تقع خارج إطار هذا المقال.
</p>

<p>
	بإمكاننا بالطبع الاستفادة من المستقلين العرب المتواجدين في <a href="mostaql.hsoub.com" rel="">منصة مستقل</a> منصة العمل العربي الأكثر شهرة لبناء تطبيقات ويب مميزة باستخدام لارافيل أو ووردبريس بحرفية عالية وأسعار مدروسة.
</p>

<h2 id="-21">
	خلاصة: ما الخيار الأفضل لارافيل أم ووردبريس؟
</h2>

<p>
	يعتمد الخيار الأمثل على احتياجاتنا الخاصة وأهدافنا من التطبيق أو موقع الويب. إذ تكون لارافيل خيارًا مفضلًا عند إنشاء تطبيقات ويب مخصصة لأنها تقدم مرونة كبيرة وقابلية لتوسيع التطبيق وبيئة عمل قوية مفصلة خصيصًا للمطورين. بينما تشتهر ووردبريس في المقابل بسهولة استخدامها وفعاليتها في إدارة المحتوى وفهارسها التي تمتلئ بالقوالب والإضافات، مما يجعلها خيارًا مفضلًا للأعمال الفردية الصغيرة التي تهدف إلى تأسيس مكان على الإنترنت بسرعة. ومن الضروري جدًا أخذ متطلبات مشروعنا بعين الاعتبار، وخبراتنا في تطوير التطبيقات، ورؤيتنا المستقبلية للمنتج قبل أن نقرر ما هي المنصة الملائمة.
</p>

<h2 id="-22">
	أسئلة شائعة
</h2>

<h3 id="2-1">
	1- من أفضل لارافيل أم ووردبريس
</h3>

<p>
	<strong>الجواب</strong>: للمنصتين غايتان مختلفتان فلارافيل هو إطار عمل قوي للغة PHP يستخدم في تطوير تطبيقات الويب، بينما يشتهر ووردبريس بكونه نظام إدارة محتوى متألق في بناء المدونات ومواقع الويب. لهذا السبب، لا يمكن المقارنة بين المنصتين وفق هذا السياق.
</p>

<h3 id="3-1">
	3- هل ووردبريس سهل الاستخدام أكثر من لارافيل
</h3>

<p>
	<strong>الجواب</strong>: يصنف ووردبريس بأنه أسهل استخدامًا وأبسط تعلمًا من لارافيل. فواجهته الواضحة وسهولة استخدامه عند إنشاء مواقع الويب وإدارة محتوياتها تجعله مفضلًا للمبتدئين الذين يفتقرون إلى الخبرة التقنية في مجال تطوير الويب، بينما يحتاج لارافيل في المقابل إلى معرفة برمجية جيدة لتطوير تطبيقات ويب فعالة.
</p>

<h3 id="4-1">
	4- متى نفضل لارافيل على ووردبريس
</h3>

<p>
	<strong>الجواب</strong>: لارافيل هو الحل المناسب لبناء تطبيقات ويب معقدة بوظائف خاصة وقدرة على التوسع والتخصيص. بينما ووردبريس هو خيار مثالي عند بناء مواقع ويب هدفها الأساسي تقديم محتوى مثل المدونات والمواقع التعريفية، لأنه يقدم طريقة سريعة في إعداد الموقع من خلال عمليات واضحة وسهلة الاستخدام.
</p>

<p>
	ترجمة -وبتصرف- لمقال: <a href="https://www.cloudways.com/blog/laravel-vs-wordpress/" rel="external nofollow">Laravel vs WordPress: choosing the Ideal platform for your peb development needs</a> لكاتبه <a href="https://www.cloudways.com/blog/author/inshal/" rel="external nofollow">Inshal Ali</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%B4%D9%87%D9%8A%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/" rel="">تعرف على إطار عمل تطوير الويب الشهير لارافيل Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-%D9%84%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2425/" rel="">إنشاء واجهة أمامية لمدونة باستخدام لارافيل</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D9%81%D8%B6%D9%84-%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%84%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2530/" rel="">أفضل الحزم البرمجية لتحسين تطبيقات لارافيل</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/php/" rel="">تعلم PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/wordpress/" rel="">تعلم ووردبريس</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2538</guid><pubDate>Wed, 19 Mar 2025 12:00:00 +0000</pubDate></item><item><title>&#x623;&#x641;&#x636;&#x644; &#x627;&#x644;&#x62D;&#x632;&#x645; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629; &#x644;&#x62A;&#x62D;&#x633;&#x64A;&#x646; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A3%D9%81%D8%B6%D9%84-%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%84%D8%AA%D8%AD%D8%B3%D9%8A%D9%86-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2530/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2025_03/1142743794_.png.8d8a70483cde1deaf97bccf0895612ae.png" /></p>
<p>
	هل سبق وشعرتم أنكم تكررون كتابة نفس الشيفرة لتنفيذ مهام روتينية شائعة في مشاريع لارافيل؟ وأن بناء ميزات التطبيق من الصفر تستهلك الكثيرمن الوقت وتبطئ العمل! يمكن حل معظم هذه المشكلات باستخدام حزم لارافيل، وهي وحدات برمجية جاهزة وقابلة للاستخدام المتكرر لتنفيذ المهام والوظائف الشائعة، حيث تسهل تلك الحزم مسار عملنا وتعزز أمان تطبيقاتنا وتحسن وظائفها.
</p>

<p>
	نتحدث في هذا المقال عن حزم لارافيل ونستكشف أنواعها ونبحث في الفرق بين الحزم packages والتجميعات bundles، ونعرض قائمة بأفضل الحزم لبناء تطبيقات أسرع.
</p>

<h2>
	فهرس المقال
</h2>

<ul>
	<li>
		<a href="#-1" rel="">مفهوم الحزمة package في لارافيل</a>
	</li>
	<li>
		<a href="#-2" rel="">الفرق بين الحزم packages والتجميعات bundles</a>
	</li>
	<li>
		<a href="#-3" rel="">أنواع حزم لارافيل</a>
	</li>
	<li>
		<a href="#-6" rel="">قائمة بأفضل حزم لارافيل</a>
	</li>
	<li>
		<a href="#-7" rel="">حزم تطوير لارافيل</a>
	</li>
	<li>
		<a href="#-8" rel="">حزم أمان لارافيل</a>
	</li>
	<li>
		<a href="#-9" rel="">حزم لوحة تحكم الإدارة في لارافيل</a>
	</li>
	<li>
		<a href="#-10" rel="">حزم لارافيل المخصصة للتجارة الإلكترونية</a>
	</li>
	<li>
		<a href="#-11" rel="">حزم لارافيل لتحسين محركات البحث</a>
	</li>
	<li>
		<a href="#-12" rel="">حزم لارافيل المخصصة لتنقيح الشيفرة</a>
	</li>
	<li>
		<a href="#-13" rel="">حزم اختبار لارافيل</a>
	</li>
</ul>

<h2 id="-1">
	مفهوم الحزمة package في لارافيل
</h2>

<p>
	تُعد الحزمة package بمثابة صندوق أدوات لكل مهام التطوير، وتكون الحزمة على شكل وحدات برمجية مبنية مسبقًا تقدم وظائف مخصصة لتطبيقات <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%B4%D9%87%D9%8A%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/" rel="">لارافيل</a>. توفر الحزم وقت المطور لانها تلغي الحاجة إلى بناء التطبيق من الصفر وتسمح للمطور بالتركيز على الميزات الجوهرية للتطبيق.
</p>

<h2 id="-2">
	الفرق بين حزم وتجميعات لارفيل
</h2>

<p>
	يستخدم كلا المصطلحين حزمة Package وتجميعة Bundle للإشارة إلى نفس التقنية غالبًا على الرغم من وجود اختلاف صغير بينهما:
</p>

<table>
	<thead>
		<tr>
			<th style="text-align:right;">
				الميزة
			</th>
			<th style="text-align:right;">
				الحزمة
			</th>
			<th style="text-align:right;">
				التجميعة
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style="text-align:right;">
				المصدر
			</td>
			<td style="text-align:right;">
				يطورها مجتمع لارافيل أو طرف خارجي
			</td>
			<td style="text-align:right;">
				يطورها فريق لارافيل الأساسي
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				الحصرية
			</td>
			<td style="text-align:right;">
				غير موجودة افتراضيًا
			</td>
			<td style="text-align:right;">
				موجودة عند تثبيت لارافيل
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				أمثلة
			</td>
			<td style="text-align:right;">
				Debugbar و Socialite
			</td>
			<td style="text-align:right;">
				Authentication و Caching
			</td>
		</tr>
	</tbody>
</table>

<h2 id="-3">
	أنواع حزم لارافيل
</h2>

<p>
	تأتي حزم لارافيل ضمن فئتين أساسيتين: حزنم مستقلة عن إطار العمل، وحزم مخصصة لإطار عمل
</p>

<h3 id="-4">
	الحزم المخصصة لإطار العمل
</h3>

<p>
	صُمِّمت هذه الحزم خصيصًا لإطار العمل لارفيل. وتعزز هذه الحزم ميزات لارافيل وتقاليد الاستخدام وهندستها لتقديم وظائف مخصصة لتطبيقاتها. من الأمثلة عنها نجد حزم الاستيثاق وموسعّات العمل مع التخزين المؤقت.
</p>

<h3 id="-5">
	الحزم المستقلة عن إطار العمل
</h3>

<p>
	لا ترتبط هذه الحزم بإطار عمل لارافيل ويمكن استخدامها في أي مشروع <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%A8%D8%AF%D8%A1-%D9%85%D8%B9-php-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A%D9%87%D8%A7-r1039/" rel="">PHP</a> بصرف النظر عن إطار العمل. تقدم هذه الحزم ميزات لا تتعلق بهندسة لارافيل مما يجعلها متعددة الاستخدامات في مشارع PHP المتنوعة. من الأمثلة عنها نجد مكتبات العمل مع قواعد البيانات وأدوات التحقق من استمارات الويب.
</p>

<h2 id="-6">
	قائمة بأفضل حزم لارفيل
</h2>

<p>
	إليك قائمة بأفضل حزم لارافيل وفقًا لوظائفها المقدمة:
</p>

<table>
	<thead>
		<tr>
			<th style="text-align:right;">
				الفئة
			</th>
			<th style="text-align:right;">
				اسم الحزمة
			</th>
			<th style="text-align:right;">
				الوصف
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style="text-align:right;">
				حزم تطوير
			</td>
			<td style="text-align:right;">
				Laravel Debugbar
			</td>
			<td style="text-align:right;">
				تضيف أشريط أدوات لأغراض التنقيح.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم تطوير
			</td>
			<td style="text-align:right;">
				Laravel User Verification
			</td>
			<td style="text-align:right;">
				تتولى مهام التحقق من المستخدم وتقييم صلاحية البريد الإلكتروني.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم تطوير
			</td>
			<td style="text-align:right;">
				Socialite
			</td>
			<td style="text-align:right;">
				تمكن من تسجيل الدخول إلى مواقع التواصل الاجتماعي (فيسبوك، غوغل،…).
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم تطوير
			</td>
			<td style="text-align:right;">
				Laravel Mix
			</td>
			<td style="text-align:right;">
				أداة تصريف أصول مبنية اعتمادًا على Webpack.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم تطوير
			</td>
			<td style="text-align:right;">
				Eloquent-Sluggable
			</td>
			<td style="text-align:right;">
				توّلد ملاحق عناوين URL محسنة من أجل محركات البحث.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم تطوير
			</td>
			<td style="text-align:right;">
				Migrations Generator
			</td>
			<td style="text-align:right;">
				تولد آليًا ملفات التهجير migration files وفقًا لمخطط قاعدة البيانات.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم تطوير
			</td>
			<td style="text-align:right;">
				Laravel Backup
			</td>
			<td style="text-align:right;">
				تولد نسخًا اختياطية لملفات التطبيق وقاعدة البيانات.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم تطوير
			</td>
			<td style="text-align:right;">
				Laravel IDE Helper
			</td>
			<td style="text-align:right;">
				تعزز تجربة المطوّر من خلال تقديم بيئة تطوير متكاملة IDE.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم أمان
			</td>
			<td style="text-align:right;">
				Entrust
			</td>
			<td style="text-align:right;">
				تقدم أذونات مبنية على أدوار المستخدمين في تطبيقك.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم أمان
			</td>
			<td style="text-align:right;">
				No Captcha
			</td>
			<td style="text-align:right;">
				تقدم خدمة reCaptcha لمنع حالات الوصول غير المرغوبة
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				لوحة تحكم المستخدم
			</td>
			<td style="text-align:right;">
				Voyager
			</td>
			<td style="text-align:right;">
				تقدم أداة بناء مرئية للوحة تحكم المدير.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				لوحة تحكم المستخدم
			</td>
			<td style="text-align:right;">
				LaraAdmin
			</td>
			<td style="text-align:right;">
				مولد مفتوح المصدر للوحة تحكم المدير وعمليات قواعد البيانات الأساسية CRUD.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				لوحة تحكم المستخدم
			</td>
			<td style="text-align:right;">
				Orchid
			</td>
			<td style="text-align:right;">
				صندوق أدوات مفتوح المصدر لبناء واجهات الإدارة ولوحة التحكم.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				تجارة إلكترونية
			</td>
			<td style="text-align:right;">
				Bagisto
			</td>
			<td style="text-align:right;">
				حزمة تجارة إلكترونية مفتوحة المصدر لتطبيقات لارافيل.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				تجارة إلكترونية
			</td>
			<td style="text-align:right;">
				AvoRed
			</td>
			<td style="text-align:right;">
				سلة تسوق لارفيل مفتوحة المصدر مع واجهة سهلة الاستخدام للأجهزة المحمولة
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				تحسين محركات بحث
			</td>
			<td style="text-align:right;">
				Laravel Meta Manager
			</td>
			<td style="text-align:right;">
				تدير البيانات الوصفية لموقع الويب بغرض تحسين محركات البحث.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				تحسين محركات بحث
			</td>
			<td style="text-align:right;">
				SEOTools
			</td>
			<td style="text-align:right;">
				تحسن ترتيب ظهور الموقع في محركات البحث باعتماد أفضل الخبرات المتوفرة.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				تحسين محركات بحث
			</td>
			<td style="text-align:right;">
				Laravel-SEO
			</td>
			<td style="text-align:right;">
				تضيف وتحذف وتدير البيانات الوصفية لموقع الويب.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				حزم تنقيح
			</td>
			<td style="text-align:right;">
				Laravel Telescope
			</td>
			<td style="text-align:right;">
				تقدم إضاءات على الطلبات والاستثناءات والسجل وغيرها.
			</td>
		</tr>
		<tr>
			<td style="text-align:right;">
				 
			</td>
			<td style="text-align:right;">
				 
			</td>
			<td style="text-align:right;">
				 
			</td>
		</tr>
	</tbody>
</table>

<h2 id="-7">
	حزم تطوير لارافيل
</h2>

<p>
	تبسِّط حزم التطوير مسار العمل بقديمها أدوات تنقيح وتصريف أصول وتوليد شيفرة برمجية.
</p>

<h3 id="1laraveldebugbar">
	1. الحزمة Laravel Debugbar
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169175" href="https://academy.hsoub.com/uploads/monthly_2025_03/01_laravel_debugger.png.fbbf25b1eb758912cc2efec2f098daa3.png" rel=""><img alt="01 laravel debugger" class="ipsImage ipsImage_thumbnailed" data-fileid="169175" data-unique="0j9a6snnd" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/01_laravel_debugger.thumb.png.5a3d4a44d54eb096548968dcc8c3e820.png"> </a>
</p>

<p>
	تضيف هذه الحزمة الأساسية صندوق أدوات تطوير وتعطينا تلميحات مباشرة عن أداء التطبيق. إذ تعرض الحزمة <a href="https://academy.hsoub.com/programming/sql/%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85-%D8%B9%D9%86-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-sql-r588/" rel="">استعلامات</a> قواعد البيانات والقوالب المصيّرة والمعاملات المُمرَّرة، كما تساعدنا على إضافة رسائل مخصصة لتسهيل التنقيح، وبالتالي زمنًا أكبر في تطوير التطبيق بدلًا من تخمين المشكلات.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5978_11" style=""><span class="typ">Debugbar</span><span class="pun">::**</span><span class="pln">info</span><span class="pun">**(</span><span class="pln">$object</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Debugbar</span><span class="pun">::**</span><span class="pln">error</span><span class="pun">**(</span><span class="str">'Error!'</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Debugbar</span><span class="pun">::**</span><span class="pln">warning</span><span class="pun">**(</span><span class="str">'Watch out…'</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Debugbar</span><span class="pun">::**</span><span class="pln">addMessage</span><span class="pun">**(</span><span class="str">'Another message'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'mylabel'</span><span class="pun">)</span></pre>

<h3 id="2laraveluserverification">
	2. الحزمة Laravel User Verification
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169176" href="https://academy.hsoub.com/uploads/monthly_2025_03/02_Laravel_User_Verification.png.3c059fcb6d3aa8ff8772797d4d3957a3.png" rel=""><img alt="02 laravel user verification" class="ipsImage ipsImage_thumbnailed" data-fileid="169176" data-unique="3rj4vcym8" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/02_Laravel_User_Verification.thumb.png.3c2e6863e5d21be9874f0e0766e0c959.png"> </a>
</p>

<p>
	تبسّط الحزمة <a href="https://github.com/jrean/laravel-user-verification" rel="external nofollow">Laravel User Verification</a> تقديم المستخدم إلى الموقع حيث تتحقق من البريد الإلكتروني وصلاحيته. كما تزيد الأداة من مرونة تخصيص قوالب البريد الإلكتروني ومنطق التحقق وتجربة المستخدم كي تتلائم تمامًا مع احتياجات التطبيق، وهي تتكامل بسهولة مع نظام <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D9%8A%D8%AB%D8%A7%D9%82-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D9%8A%D9%86-user-authentication-%D9%81%D9%8A-laravel-5-r229/" rel="">الاستيثاق</a> والتنبيهات في لارافيل مما يساعد على ادخار وقت وجهد المطورين.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5978_15" style=""><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">**</span><span class="kwd">register</span><span class="pun">**(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
$this</span><span class="pun">-&gt;**</span><span class="pln">validator</span><span class="pun">**(</span><span class="pln">$request</span><span class="pun">-&gt;**</span><span class="pln">all</span><span class="pun">**())-&gt;**</span><span class="pln">validate</span><span class="pun">**();</span><span class="pln">
$user </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;**</span><span class="pln">create</span><span class="pun">**(</span><span class="pln">$request</span><span class="pun">-&gt;**</span><span class="pln">all</span><span class="pun">**());</span><span class="pln">
</span><span class="pun">**</span><span class="kwd">event</span><span class="pun">**(</span><span class="kwd">new</span><span class="pln"> </span><span class="pun">**</span><span class="typ">Registered</span><span class="pun">**(</span><span class="pln">$user</span><span class="pun">));</span><span class="pln">
$this</span><span class="pun">-&gt;**</span><span class="pln">guard</span><span class="pun">**()-&gt;**</span><span class="pln">login</span><span class="pun">**(</span><span class="pln">$user</span><span class="pun">);</span><span class="pln">
</span><span class="typ">UserVerification</span><span class="pun">::**</span><span class="pln">generate</span><span class="pun">**(</span><span class="pln">$user</span><span class="pun">);</span><span class="pln">
</span><span class="typ">UserVerification</span><span class="pun">::**</span><span class="pln">send</span><span class="pun">**(</span><span class="pln">$user</span><span class="pun">,</span><span class="pln"> </span><span class="str">'My Custom E-mail Subject'</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;**</span><span class="pln">registered</span><span class="pun">**(</span><span class="pln">$request</span><span class="pun">,</span><span class="pln"> $user</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">?:</span><span class="pln"> </span><span class="pun">**</span><span class="pln">redirect</span><span class="pun">**(</span><span class="pln">$this</span><span class="pun">-&gt;**</span><span class="pln">redirectPath</span><span class="pun">**());</span><span class="pln">
 </span><span class="pun">}</span></pre>

<h3 id="3socialite">
	3. الحزمة Socialite
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169177" href="https://academy.hsoub.com/uploads/monthly_2025_03/03_socialite.png.c4231679905aadb9c16f7559e9df1b44.png" rel=""><img alt="03 socialite" class="ipsImage ipsImage_thumbnailed" data-fileid="169177" data-unique="owr24a92c" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/03_socialite.thumb.png.feeed56f06272303cbf13ab94e27f62e.png"> </a>
</p>

<p>
	طوِّرت حزمة <a href="https://github.com/laravel/socialite" rel="external nofollow">Laravel Socialite</a> من قبل فريق لارافيل لتسهيل عمليات تسجيل الدخول على منصات التواصل الاجتماعي مثل فيسبوك وجوجل وإكس، وهي تتكامل مع نظام الاستيثاق والتنبيهات في لارافيل وتتولى تعقيدات تطبيق بروتوكول <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-oauth-2-r72/" rel="">OAuth</a> وراء الكواليس دون تدخل منا كي تساعدنا على التركيز على تطوير ميزات التطبيق الأساسية.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5978_19" style=""><span class="pln">$user </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Socialite</span><span class="pun">::**</span><span class="pln">driver</span><span class="pun">**(</span><span class="str">'github'</span><span class="pun">)-&gt;**</span><span class="pln">user</span><span class="pun">**();</span><span class="pln">
</span><span class="com">// OAuth Two Providers</span><span class="pln">
$token </span><span class="pun">=</span><span class="pln"> $user</span><span class="pun">-&gt;</span><span class="pln">token</span><span class="pun">;</span><span class="pln">
$refreshToken </span><span class="pun">=</span><span class="pln"> $user</span><span class="pun">-&gt;</span><span class="pln">refreshToken</span><span class="pun">;</span><span class="pln"> </span><span class="com">// not always provided</span><span class="pln">
$expiresIn </span><span class="pun">=</span><span class="pln"> $user</span><span class="pun">-&gt;</span><span class="pln">expiresIn</span><span class="pun">;</span><span class="pln">
</span><span class="com">// All Providers</span><span class="pln">
$user</span><span class="pun">-&gt;**</span><span class="pln">getId</span><span class="pun">**();</span><span class="pln">
$user</span><span class="pun">-&gt;**</span><span class="pln">getName</span><span class="pun">**();</span><span class="pln">
$user</span><span class="pun">-&gt;**</span><span class="pln">getEmail</span><span class="pun">**();</span><span class="pln">
$user</span><span class="pun">-&gt;**</span><span class="pln">getAvatar</span><span class="pun">**();</span></pre>

<h3 id="4laravelmix">
	4. الحزمة Laravel Mix
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169178" href="https://academy.hsoub.com/uploads/monthly_2025_03/04_Laravel_Mix.png.9cd8994bb944d0715f90c8edbe36c90b.png" rel=""><img alt="04 laravel  mix" class="ipsImage ipsImage_thumbnailed" data-fileid="169178" data-unique="ejrsbdid1" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/04_Laravel_Mix.thumb.png.1382daf41828dfffb26ff1d21a380b63.png"> </a>
</p>

<p>
	تقدم الحزمة <a href="https://www.npmjs.com/package/laravel-mix" rel="external nofollow">Laravel Mix</a> أداة بسيطة وسهلة الاستخدام لتصريف أصول تطبيق لارافيل. حلّت هذه الحزمة مكان Laravel Elixir وهي تقدم واجهة برمجية واضحة وسهلة الاستخدام لتحديد خطوات بناء التطبيق بطريقة فعالة.
</p>

<p>
	تتكامل الأداة بسهول مع أداة التحزيم <a href="https://www.google.com/url?q=https://academy.hsoub.com/programming/workflow/%25D8%25AF%25D9%2584%25D9%258A%25D9%2584-webpack-%25D8%25A7%25D9%2584%25D8%25B4%25D8%25A7%25D9%2585%25D9%2584-r866/&amp;sa=D&amp;source=docs&amp;ust=1724851007926247&amp;usg=AOvVaw252SIuLuThVETmv0-wtypb" rel="external nofollow">Webpack </a>مما يحسن ميزة استبدال الوحدات البرمجية أثناء التنفيذ HMR والمزامنة مع المتصفح، مما يساعد في رؤية التغييرات مباشرة دون إعادة تحميل يدوي ويوفر وقت المطورين.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5978_22" style=""><span class="pln">mix</span><span class="pun">.**</span><span class="pln">js</span><span class="pun">**(</span><span class="str">'resources/assets/js/app.js'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'public/js'</span><span class="pun">)</span><span class="pln">
 </span><span class="pun">.**</span><span class="pln">sass</span><span class="pun">**(</span><span class="str">'resources/assets/sass/app.scss'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'public/css'</span><span class="pun">);</span></pre>

<h3 id="5eloquentsluggable">
	5. الحزمة Eloquent-Sluggable
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169179" href="https://academy.hsoub.com/uploads/monthly_2025_03/05_Eloquent-Sluggable.png.325ca888111b4236dc0edbc3fadc9761.png" rel=""><img alt="05 eloquent sluggable" class="ipsImage ipsImage_thumbnailed" data-fileid="169179" data-unique="5jj3aeu8m" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/05_Eloquent-Sluggable.thumb.png.50ab713db36433aa4dc1a6a300839c02.png"> </a>
</p>

<p>
	تقدم <a href="https://github.com/cviebrock/eloquent-sluggable" rel="external nofollow">Eloquent-Sluggable</a> أداة مفيدة لتوليد عناوين لطيفة slug بعناوين URL وفقًا لخاصيات نموذجنا وبطريقة مؤتمتة، منشئة عناوين تساعد في تحسين محركات البحث في تطبيقك.
</p>

<p>
	كما تقدم الحزمة خيارت لتخصيص حقول العناوين الملحقة والفواصل separators وسلوك التحديث. كما توفر أيضًا خطافات لمعالجة الحالات الخاصة وتتكامل مع منطق التطبيق للتأكد من تحسين عناوين URL.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5978_25" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Post</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Eloquent</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
 </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Sluggable</span><span class="pun">;</span><span class="pln">
 </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'title'</span><span class="pun">];</span><span class="pln">
 </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">**</span><span class="pln">sluggable</span><span class="pun">**()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
     </span><span class="str">'slug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
       </span><span class="str">'source'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="str">'title'</span><span class="pun">]</span><span class="pln">
     </span><span class="pun">]</span><span class="pln">
   </span><span class="pun">];</span><span class="pln">
 </span><span class="pun">}</span><span class="pln">
 </span><span class="pun">}</span><span class="pln">
 $post </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="pun">**</span><span class="typ">Post</span><span class="pun">**([</span><span class="pln">
 </span><span class="str">'title'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My Awesome Blog Post'</span><span class="pun">,</span><span class="pln">
 </span><span class="pun">]);</span><span class="pln">
 </span><span class="com">// $post-&gt;slug is "my-awesome-blog-post</span></pre>

<h3 id="6migrationsgenerator">
	6. الحزمة Migrations Generator
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169180" href="https://academy.hsoub.com/uploads/monthly_2025_03/06_Migrations_Generator.png.65de231cbb477dae9e12f80d3cbaef27.png" rel=""><img alt="06 migrations generator" class="ipsImage ipsImage_thumbnailed" data-fileid="169180" data-unique="asc1gh076" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/06_Migrations_Generator.thumb.png.c4c50b8ec12f1177ab664688b2fc3de0.png"> </a>
</p>

<p>
	تحلل الحزمة <a href="https://github.com/Xethron/migrations-generator" rel="external nofollow">Laravel Migrations Generator</a> تخطيط قاعدة البيانات وتولد ملفات <a href="https://www.google.com/url?q=https://academy.hsoub.com/programming/php/laravel/%25D8%25AA%25D9%2587%25D8%25AC%25D9%258A%25D8%25B1-%25D9%2582%25D9%2588%25D8%25A7%25D8%25B9%25D8%25AF-%25D8%25A7%25D9%2584%25D8%25A8%25D9%258A%25D8%25A7%25D9%2586%25D8%25A7%25D8%25AA-%25D9%2581%25D9%258A-laravel-5-r224/&amp;sa=D&amp;source=docs&amp;ust=1724851007927837&amp;usg=AOvVaw1LGCVNlasrXM991444LQnX" rel="external nofollow">التهجير</a> migration files تلقائيًا، مما يوفر علينا الوقت ويساعدنا على التركيز على منطق تطوير التطبيق وليس كتابة تلك الملفات. ويمكننا بكل بساطة تنفيذ أمر التهجير لكل جداول قاعدة البيانات معًا وترك الأمر لهذه الحزمة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5978_28" style=""><span class="pln">php artisan migrate</span><span class="pun">:</span><span class="pln">generate

</span><span class="com">//بالإمكان اختيار جداول معينة فقط</span><span class="pln">

php artisan migrate</span><span class="pun">:</span><span class="pln">generate table1</span><span class="pun">,</span><span class="pln">table2</span></pre>

<h3 id="7laravelbackup">
	7. الحزمة Laravel Backup
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169181" href="https://academy.hsoub.com/uploads/monthly_2025_03/07_laravel_backup.png.9dd8f9737a7acf7feabca58bec8a35d9.png" rel=""><img alt="07 laravel backup" class="ipsImage ipsImage_thumbnailed" data-fileid="169181" data-unique="1dc7fb3ai" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/07_laravel_backup.thumb.png.7c165380658710dcceba69d4a027bb89.png"> </a>
</p>

<p>
	تساعدنا الحزمة <a href="https://github.com/spatie/laravel-backup" rel="external nofollow">Laravel Backup</a> في إنشاء نسخ احتياطية عن ملفاتنا عن طريق ضغط المجلدات وقاعدة البيانات في ملف snapshot واحد لضمان حماية وتأمين المشروع، وذلك من خلال تنفيذ أمر واحد.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5978_31" style=""><span class="pln">php artisan backup</span><span class="pun">:</span><span class="pln">run</span></pre>

<h3 id="8laravelidehelper">
	8. الحزمة Laravel IDE Helper
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169182" href="https://academy.hsoub.com/uploads/monthly_2025_03/08_Laravel_IDE_Helper.png.b187eae04c6c53d9d8e2ebb2690f00d9.png" rel=""><img alt="Laravel IDE Helper" class="ipsImage ipsImage_thumbnailed" data-fileid="169182" data-ratio="45.17" data-unique="3sfb7fu6c" style="width: 600px; height: auto;" width="900" src="https://academy.hsoub.com/uploads/monthly_2025_03/08_Laravel_IDE_Helper.thumb.png.bea363163747fb33e06f1e576ceea1fb.png"></a>
</p>

<p>
	تحسن هذه الأداة الأساسية <a href="https://github.com/barryvdh/laravel-ide-helper" rel="external nofollow">IDE Helper</a> تجربتنا مع <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AD%D8%B1%D8%B1-%D8%A3%D9%83%D9%88%D8%A7%D8%AF-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">محررات الأكواد</a> وبيئات التطوير مثل  PhpStorm و VS Code من خلال ميزات عديدة منها الإكمال التلقائي للشيفرة، والتلميح بالنوع خصيصًا لمكونات لارافيل، فلن نضطر مع هذه الأداة إلى البحث عن التعليمات بل سنعرض تلميحات وتوجيهات مباشرة عن التوابع والمعاملات المتاحة. كما تولد الأداة تعليقات توثيقية لتسهّل علينا التنقل ضمن واجهة لارافيل البرمجية ضمن بيئة التطوير التي تفضلها.
</p>

<h2 id="-8">
	حزم أمان لارافيل
</h2>

<p>
	تساعد حزم الأمان في دعم أمان التطبيق من خلال ميزات مثل الاستيثاق والأذونات المبنية على أدوار محددة والتكامل مع خدمة <a href="https://academy.hsoub.com/apps/web/wordpress/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-captcha-%D9%84%D8%AA%D8%A3%D9%85%D9%8A%D9%86-%D9%85%D9%88%D9%82%D8%B9-%D9%88%D9%88%D8%B1%D8%AF%D8%A8%D8%B1%D9%8A%D8%B3-r679/" rel="">reCAPTCHA</a>.
</p>

<h3 id="9entrust">
	9. الحزمة Entrust
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169183" href="https://academy.hsoub.com/uploads/monthly_2025_03/09_entrust.png.59a9a81594636e6bb66becd176449e19.png" rel=""><img alt="09 entrust" class="ipsImage ipsImage_thumbnailed" data-fileid="169183" data-unique="pat9dokcc" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/09_entrust.thumb.png.19af1ec5edf7f2af7ddf0e9956337674.png"> </a>
</p>

<p>
	تساعدنا <a href="https://github.com/Zizaco/entrust" rel="external nofollow">Entrust</a> في تحديد دور كل مستخدم وتسند إليه أذونات أو سماحيات محددة، وبالتالي سيتمكن المستخدم من الوصول إلى وظائف محددة مسبقًا فقط مما يحسن أمان التطبيق. تنشئ هذه الحزمة الجداول الأربعة التالية لأدوار المستخدمين:
</p>

<ul>
	<li>
		جدول أدوار لتخزين سجلات الأدوار
	</li>
	<li>
		جدول الأذونات لتخزين سجلت السماحيات
	</li>
	<li>
		جدول أدوار-مستخدم role-user لتخزين علاقات واحد-إلى-أكثر بين الأدوار والمستخدمين
	</li>
	<li>
		جدول أذونات-دور permission_role لتخزين علاقات واحد-إلى-أكثر بين الأدوار والأذونات
	</li>
</ul>

<p>
	بإمكاننا إنشاء دور بتنفيذ أسطر الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3623_8" style=""><span class="pln">admin </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="pun">**</span><span class="typ">Role</span><span class="pun">**();</span><span class="pln">
$admin</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">'admin'</span><span class="pun">;</span><span class="pln">
$admin</span><span class="pun">-&gt;</span><span class="pln">display_name </span><span class="pun">=</span><span class="pln"> </span><span class="str">'User Administrator'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// optional</span><span class="pln">
$admin</span><span class="pun">-&gt;</span><span class="pln">description </span><span class="pun">=</span><span class="pln"> </span><span class="str">'User is allowed to manage and edit other users'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// optional</span><span class="pln">
$admin</span><span class="pun">-&gt;**</span><span class="pln">save</span><span class="pun">**()</span></pre>

<p>
	نسند الدور إلى المستخدم كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3623_10" style=""><span class="pln">user </span><span class="pun">=</span><span class="pln"> </span><span class="typ">User</span><span class="pun">::**</span><span class="kwd">where</span><span class="pun">**(</span><span class="str">'username'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'='</span><span class="pun">,</span><span class="pln"> </span><span class="str">'michele'</span><span class="pun">)-&gt;**</span><span class="pln">first</span><span class="pun">**();</span><span class="pln">
$user</span><span class="pun">-&gt;**</span><span class="pln">attachRole</span><span class="pun">**(</span><span class="pln">$admin</span><span class="pun">);</span></pre>

<p>
	ثم علينا تحديد الأذونات الخاصة بالدور:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3623_12" style=""><span class="pln">$createPost </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="pun">**</span><span class="typ">Permission</span><span class="pun">**();</span><span class="pln">
$createPost</span><span class="pun">-&gt;</span><span class="pln">name     </span><span class="pun">=</span><span class="pln"> </span><span class="str">'create-post'</span><span class="pun">;</span><span class="pln">
$createPost</span><span class="pun">-&gt;</span><span class="pln">display_name </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Create Posts'</span><span class="pun">;</span><span class="pln">
$createPost</span><span class="pun">-&gt;</span><span class="pln">description </span><span class="pun">=</span><span class="pln"> </span><span class="str">'create new blog posts'</span><span class="pun">;</span><span class="pln">
$createPost</span><span class="pun">-&gt;**</span><span class="pln">save</span><span class="pun">**();</span><span class="pln">
$admin</span><span class="pun">-&gt;**</span><span class="pln">attachPermission</span><span class="pun">**(</span><span class="pln">$createPost</span><span class="pun">);</span></pre>

<h3 id="10nocaptcha">
	10. الحزمة No Captcha
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169184" href="https://academy.hsoub.com/uploads/monthly_2025_03/10_no_capatcha.png.dd25634dba1c4952acc2992c3670f233.png" rel=""><img alt="10 no capatcha" class="ipsImage ipsImage_thumbnailed" data-fileid="169184" data-unique="70rz2260v" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/10_no_capatcha.thumb.png.c62401382c8fd97deb5ed0a43c910bc0.png"> </a>
</p>

<p>
	تعمل الحزمة <a href="https://github.com/anhskohbo/no-captcha" rel="external nofollow">No Captcha</a> على تحقيق تكامل ل<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r149/" rel="">تطبيق لارافيل</a> مع خدمة reCAPTCHA من جوجل لحمايته من الروبوتات  الآلية bots وتضيف طبقة أمان إضافية إليه. لهذا، ننصح بالحصول على مفتاح الواجهة البرمجية <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> المجاني لهذه الحزمة وحماية التطبيقات.
</p>

<p>
	تقدم الحزمة أيضًا خيارات مخصصة لعنصر التحكم CAPTCHA كي نضمن اندماجه مع تصميم الاستمارات Forms بكل بساطة ودون التأثير على تجربة المستخدم.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3623_15" style=""><span class="typ">NoCaptcha</span><span class="pun">::**</span><span class="pln">shouldReceive</span><span class="pun">**(</span><span class="str">'verifyResponse'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-&gt;**</span><span class="pln">once</span><span class="pun">**()</span><span class="pln">
</span><span class="pun">-&gt;**</span><span class="pln">andReturn</span><span class="pun">**(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
$response </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;**</span><span class="pln">json</span><span class="pun">**(</span><span class="str">'POST'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/register'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
</span><span class="str">'g-recaptcha-response'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'1'</span><span class="pun">,</span><span class="pln">
</span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Pardeep'</span><span class="pun">,</span><span class="pln">
</span><span class="str">'email'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'pardeep@example.com'</span><span class="pun">,</span><span class="pln">
</span><span class="str">'password'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'123456'</span><span class="pun">,</span><span class="pln">
</span><span class="str">'password_confirmation'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'123456'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">]);</span></pre>

<h2 id="-9">
	حزم لوحة تحكم إدارة لارافيل
</h2>

<p>
	تساعد حزم إدارة لوحة التحكم على بناء واجهات سهلة الاستخدام للوحات التحكم لمدير الواجهة الخلفية للتطبيقات
</p>

<h3 id="11voyager">
	11. Voyager
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpg" data-fileid="169185" href="https://academy.hsoub.com/uploads/monthly_2025_03/11_voyager.jpg.f2e7118f54d2cfc1393b779321bef327.jpg" rel=""><img alt="11 voyager" class="ipsImage ipsImage_thumbnailed" data-fileid="169185" data-unique="cbh37c7lf" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/11_voyager.thumb.jpg.d59da7ae13f7dcf54dcb37c8606cf5e2.jpg"> </a>
</p>

<p>
	قد يكون بناء لوحة تحكم مدير  واضحة وسهلة أمرًا يستهلك الكثير من وقت المطور، لكن الحزمة <a href="https://voyager.devdojo.com/" rel="external nofollow">Voyager</a> ستبسط العملية من خلال واجهة سهلة الاستخدام. تتميز الحزمة بتوثيقها الجيد وتتضمن واجهة واضحة وسهلة الاستخدام، وتوفر بيانات مخصصة للاختبارات ومدير وسائط متعددة متقدم. وتساعدنا في التركيز على بناء وظائف تطبيقات لارافيل لتتكفل هي بإنشاء لوحات التحكم.
</p>

<h3 id="12laraadmin">
	12. الحزمة LaraAdmin
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpg" data-fileid="169186" href="https://academy.hsoub.com/uploads/monthly_2025_03/12_lara_admin.jpg.7e4dee26b04788e1abfe8ab2ddf99188.jpg" rel=""><img alt="12 lara admin" class="ipsImage ipsImage_thumbnailed" data-fileid="169186" data-unique="g6p7y1w9w" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/12_lara_admin.thumb.jpg.84da855e980c6768d71454aefae225af.jpg"> </a>
</p>

<p>
	تُعد <a href="https://laraadmin.com/" rel="external nofollow">LaraAdmin</a> حزمة مجانية قوية ومفتوحة المصدرية لتطوير لارافيل، حيث تسهِّل إنشاء لوحة تحكم إدارة التطبيق بتقديمها ميزات مثل إدارة المستخدمين، والوصول المشروط بالدور الممنوح للمستخدم، والقوائم الديناميكية.
</p>

<p>
	تقدم الأداة أيضًا جداول بيانات سهلة التخصيص تدعم الفرز والترشيح وتعدد الصفحات مما يسمح بإدارة البيانات المعقدة بكل سهولة. لهذا ستساعدنا هذه الأداة في التركيز على البناء الوظيفي لتطبيقات لارافيل وتتكفل هي بإنشاء واجهات الإدارة.
</p>

<h3 id="13orchid">
	13. الحزمة Orchid
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169187" href="https://academy.hsoub.com/uploads/monthly_2025_03/13_orchid.png.20bc9cbddf1af55d0fb922132ebe2bb1.png" rel=""><img alt="13 orchid" class="ipsImage ipsImage_thumbnailed" data-fileid="169187" data-unique="53ymr0u2e" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/13_orchid.thumb.png.a33907f246258d55f545483efb2dd5aa.png"> </a>
</p>

<p>
	تُقدم الحزمة <a href="https://orchid.software/" rel="external nofollow">Orchid</a> صندوق أدوات يتمتع بتصميم مرن وقابل للتوسع، مما يسمح ببناء واجهات سهلة الاستخدام مفصلة خصيصًا لتلائم تطبيقاتنا. وتتجاوز الأداة إنشاء لوحات تحكم بسيطة وتتصرف كمنظومة لإدارة تطبيقات الويب. إذ يمكن التفكير بها على أنها منظومة إدارة محتوى تسهل إدارة المحتوى والمستخدمين في تطبيقات لارافيل.
</p>

<h2 id="-10">
	حزم لارافيل المخصصة للتجارة الإلكترونية
</h2>

<p>
	تساعدنا هذه الحزم في تسريع تطوير <a href="https://academy.hsoub.com/entrepreneurship/ecommerce/%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D9%85%D8%AA%D8%A7%D8%AC%D8%B1-%D8%A7%D9%84%D8%A5%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A%D8%A9-%D9%88%D9%86%D9%85%D8%A7%D8%B0%D8%AC-%D8%A5%D9%8A%D8%B1%D8%A7%D8%AF%D8%A7%D8%AA%D9%87%D8%A7-r733/" rel="">المتاجر الإلكترونية</a> من خلال ميزاتها المتعددة مثل إدارة المنتجات وعربات التسوق وبوابات الدفع الإلكتروني.
</p>

<h3 id="14bagisto">
	14. الحزمة Bagisto
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="PNG" data-fileid="169318" href="https://academy.hsoub.com/uploads/monthly_2025_03/14Bagisto.PNG.452175c2e6dfebead1434c7e201d4010.PNG" rel=""><img alt="Bagisto 14 " class="ipsImage ipsImage_thumbnailed" data-fileid="169318" data-ratio="44.83" data-unique="aueg2wobs" style="width: 600px; height: auto;" width="900" src="https://academy.hsoub.com/uploads/monthly_2025_03/14Bagisto.thumb.PNG.49770fe88b3f6b3dac6a45f7068c396a.PNG"></a>
</p>

<p>
	تُعد <a href="https://bagisto.com/en/" rel="external nofollow">Bagisto</a> حزمة مفتوحة المصدر مخصصة لمتاجر لارافيل الإلكترونية التي تلفت انتباه المطورين بسرعة. إذ تقدم نظام إدارة مستخدمين سهل مع خيارات متعددة لإدارة المخازن وغيرها من الميزات.
</p>

<p>
	كما تُجمّع الحزمة Laravel CMS مع أدوات تسهل التنقل بين الأقسام المختلفة ضمن لوحة التحكم، وتقدم وظائف كثيرة للمتجر مثل تعدد العملات، وتخصيص الموقع الجغرافي للمتجر، وتحديد مستويات للوصول إلى البيانات، والتكامل مع بوابات الدفع الإلكتروني وغيرها من الميزات.
</p>

<h3 id="15avored">
	15. الحزمة AvoRed
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169189" href="https://academy.hsoub.com/uploads/monthly_2025_03/15_AvoRed.png.8fad6fdc98b1d1b741510f8caa495845.png" rel=""><img alt="15 avored" class="ipsImage ipsImage_thumbnailed" data-fileid="169189" data-unique="og16s1nev" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/15_AvoRed.thumb.png.290465c9075642487825cf8756766d22.png"> </a>
</p>

<p>
	تسمح الحزمة <a href="https://github.com/avored" rel="external nofollow">AvoRed</a> بتخصيص حزمة تسوق لارافيل مفتوحة المصدر بسهولة وحسب الحاجة، وتقدم افتراضيًا واجهة سهلة الاستخدام في الأجهزة المحمولة وتضم أفضل حزم تحسين محركات البحث في لارافيل.
</p>

<p>
	تسمح لك الأداة ببناء كيانات مفيدة مثل الفئات categories والسمات attributes وغيرها، وتقدم إمكانيات فعالة في إدارة طلبات الشراء وتتبّعها وإدارة معلومات العملاء والمتاجر وغيرها.
</p>

<h2 id="-11">
	حزم لارافيل لتحسين محركات البحث
</h2>

<p>
	تساعد هذه الحزم في تحسين تطبيقات لارافيل كي يسهل إيجادها من قبل محركات البحث وذلك من خلال إدارة بيانات الوسوم الوصفية للموقع أو التطبيق وإدارة خارطة الموقع والبيانات المهيكلة.
</p>

<h3 id="16laravelmetamanager">
	16. الحزمة Laravel Meta Manager
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169190" href="https://academy.hsoub.com/uploads/monthly_2025_03/16_Laravel_Meta_Manager.png.f554b488694417f650c4b5868da20df5.png" rel=""><img alt="16 laravel meta manager" class="ipsImage ipsImage_thumbnailed" data-fileid="169190" data-unique="2dphjfs8b" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/16_Laravel_Meta_Manager.thumb.png.c7597585b5636b07f5c47437c4be9879.png"> </a>
</p>

<p>
	تساعد الأداة <a href="https://github.com/davmixcool/laravel-meta-manager" rel="external nofollow">Laravel Meta Manager</a> في تحسين ظهور صفحاتنا في محركات البحث ورفع ترتيبها ضمن صفحات نتائج البحث. حيث توضح بيانات الوسوم Meta tag وتسمح بتصحيحها باتباع أفضل الممارسات المتبعة في تحسين محركات البحث.
</p>

<p>
	تأتي الحزمة مع مجموعة وسوم ميتا جاهزة وموصى بها تتضمن Standard SEO و Dublin Core و Google Plus و Facebook Open Graph وغيرها. فبعد إتمام الإعداد، كل ما علينا هو إضافة هذه الوسوم المتولّدة إلى ترويسة الصفحة التي تريد كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3623_24" style=""><span class="pun">@**</span><span class="pln">include</span><span class="pun">**(</span><span class="str">'meta::manager'</span><span class="pun">)</span></pre>

<p>
	يستخدم الأمر السابق الإعدادات المعرفة سابقًا لإعادة تعيين الوسوم الوصفية، لكن إن أدرنا تعريف خيارات محددة بسرعة دون تدقيق، نستطيع استخدام الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3623_26" style=""><span class="pln"> </span><span class="pun">@**</span><span class="pln">include</span><span class="pun">**(</span><span class="str">'meta::manager'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
  </span><span class="str">'title'</span><span class="pln">     </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'My Example Title'</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'description'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'This is my example description'</span><span class="pun">,</span><span class="pln">
  </span><span class="str">'image'</span><span class="pln">     </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Url to the image'</span><span class="pun">,</span><span class="pln">
 </span><span class="pun">])</span></pre>

<p>
	وإليكم مثالًا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3623_28" style=""><span class="tag">&lt;html</span><span class="pln"> </span><span class="atn">lang</span><span class="pun">=</span><span class="atv">"en"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"UTF-8"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;title&gt;</span><span class="pln">Document</span><span class="tag">&lt;/title&gt;</span><span class="pln">
    @**include**('meta::manager', [
      'title'     =&gt; 'My Example Title',
      'description'  =&gt; 'This is my example description',
      'image'     =&gt; '',
    ])
  </span><span class="tag">&lt;/head&gt;</span><span class="pln">
  </span><span class="tag">&lt;body&gt;</span><span class="pln">
  </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<h3 id="17seotools">
	17. الحزمة SEOTools
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169191" href="https://academy.hsoub.com/uploads/monthly_2025_03/17_seotools.png.5ec48aa0a9f76bb1c64b1e18aba120f7.png" rel=""><img alt="17 seotools" class="ipsImage ipsImage_thumbnailed" data-fileid="169191" data-unique="fn4zw9ws0" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/17_seotools.thumb.png.29f9110aa6c6c76cac091bf1b1fcaee5.png"> </a>
</p>

<p>
	تسمح <a href="https://github.com/artesaos/seotools" rel="external nofollow">SEOTools</a> بتحسين محركات البحث في تطبيقات لارافيل وفقًا لأفضل الممارسات، وتقدم ميزات تحسين ممتازة لمواقع الويب. ومن السهل دمج الحزمة مع المشاريع ولها واجهة سهلة الاستخدام بالنسبة للمبتدئين، كما تسمح بضبط العناوين والوسوم الوصفية لكل من منصة إكس و Open Graph.
</p>

<h3 id="18laravelseo">
	18. الحزمة Laravel-SEO
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169192" href="https://academy.hsoub.com/uploads/monthly_2025_03/18_Laravel-SEO.png.79f74dfefe9a22561bb5deee9bff6a43.png" rel=""><img alt="18 laravel seo" class="ipsImage ipsImage_thumbnailed" data-fileid="169192" data-unique="2vyoetcp5" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/18_Laravel-SEO.thumb.png.aa5e9ff94eab7b5072498021369002ae.png"> </a>
</p>

<p>
	تساعدنا الحزمة <a href="https://github.com/ralphjsmit/laravel-seo" rel="external nofollow">Laravel-SEO</a> في التحكم الكامل بقدرة تطبيقنا على تحسين محركات البحث وتبسّط إدارة الوسوم الوصفية من ناحية الإضافة والتحرير والحذف. وتسمح أيضًا بإضافة بيانات مهيكلة لتحسين نتائج محركات البحث وإدارة الوسوم الوصفية للمنصات الشهيرة مثل Open Graph و Dublin Core دون أي جهد، مما يزيد ظهور تطبيق لارافيل ويعزز ترتيبه في نتائج البحث.
</p>

<h2 id="-12">
	حزم تنقيح لارافيل
</h2>

<p>
	تركز هذه الحزم على سلوك التطبيق من خلال أدوات التنقيح وتحليل الأداء.
</p>

<h3 id="19laraveltelescope">
	19. الحزمة Laravel Telescope
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169193" href="https://academy.hsoub.com/uploads/monthly_2025_03/19_Laravel_Telescope.png.63d8d2eea5d05cdd4e71e3f25207e188.png" rel=""><img alt="19 laravel telescope" class="ipsImage ipsImage_thumbnailed" data-fileid="169193" data-unique="19ua2fer7" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/19_Laravel_Telescope.thumb.png.4c0886970899f3e1b3efe36e7551c1ad.png"> </a>
</p>

<p>
	تُعد الحزمة <a href="https://laravel.com/docs/5.8/telescope" rel="external nofollow">Laravel Telescope</a> أداة فعالة في يد مطوري لارافيل، إذ تكشف لنا كل ما يحدث خلف الستار، وتتعقب الطلبات القادمة وتنفيذها والسجلات واستعلامات قواعد البيانات وغيرها.
</p>

<p>
	وتقدم الأداة ملاحظات مباشرة على سلوك التطبيق أثناء التنفيذ، مما يسمح بتحديد وإصلاح الثغرات بفعالية. تجعل هذه الميزات من <a href="https://laravel.com/docs/5.8/telescope" rel="external nofollow">Laravel Telescope</a> أداة أساسية لأي مطور لارافيل يعمل في بيئة تطور محلية.
</p>

<h2 id="-13">
	حزم اختبار لارافيل
</h2>

<p>
	تساعدك هذه الحزم على تحسين نوعية الشيفرة وإمكانية صيانتها من خلال إعداد اختبارات وحدات واختبارات تكامل فعالة.
</p>

<h3 id="20orchestraltestbench">
	20. الحزمة Orchestral Testbench
</h3>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="169194" href="https://academy.hsoub.com/uploads/monthly_2025_03/20_Orchestral_Testbench.png.ac6cef7c90dd01d386f31d84406ad8e3.png" rel=""><img alt="20 orchestral testbench" class="ipsImage ipsImage_thumbnailed" data-fileid="169194" data-unique="q44b03cl1" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2025_03/20_Orchestral_Testbench.thumb.png.dcca07163a130502eb566695653fe5cc.png"> </a>
</p>

<p>
	لن نتمكن من الوصول إلى جميع مساعدي اختبار لارافيل test helpers عندما نكتب الحزمة بنفسنا. فإن أردنا كتابة اختبارات لحزمتنا كما لو كانت ضمن تطبيق لارافيل نمطي ننصح باستخدام <a href="https://github.com/orchestral/testbench" rel="external nofollow"> Orchestral Testbench package</a> كالتالي:
</p>

<ol>
	<li>
		ضبط ملف Composer.json للحزمة الجديدة
	</li>
	<li>
		إضافة مزود خدمة
	</li>
	<li>
		ضبط الأسماء المستعارة Alias
	</li>
	<li>
		إنشاء صنف واجهة facade class
	</li>
</ol>

<p>
	هذه الخطوات الأربعة مهمة جدًا في كتابة حزمة لارافيل لتسريع الإنتاجية.
</p>

<h2 id="-14">
	الخلاصة
</h2>

<p>
	قدمنا في هذا المقال قائمة بأفضل حزم لارافيل التي تساعدنا على تحسين إنتاجية تطبيقاتنا. ويعتمد اختيار أفضل حزم لارافيل على متطلبات المشروع بالدرجة الأولى. وطالما أن لارافيل تسهل على المطور تنفيذ عمليات مخصصة يحددونها بأنفسهم، سيكون استخدام تلك الحزم مساعدًا في تنفيذ تلك المهام الوظيفية بفعالية أكبر.
</p>

<h2 id="-15">
	أسئلة شائعة
</h2>

<h3 id="1">
	1. ما هي حزم لارافيل؟
</h3>

<p>
	الحزم في <a href="https://academy.hsoub.com/php/" rel="">PHP</a> هي مجموعة من الوجهات routes والمتحكمات controllers والعروض views المهيأة لتوسيع وظائف تطبيق لارافيل.
</p>

<h3 id="2">
	2. ماهي التجميعة في لارافيل؟
</h3>

<p>
	هي تقنية قّدمت أول مرة في لارافيل 3.0، وهي طريقة لتجميع الشيفرة ضمن مكونات يمكن إضافتها إلى تطبيقات لارافيل. ولن يضطر المطور من إنشاء تلك المكونات من الصفر دائمًا عند استخدام التجميعات.
</p>

<p>
	ترجمة -وبتصرف- للمقال: <a href="https://www.cloudways.com/blog/best-laravel-packages/#Laravel-Package" rel="external nofollow">Best laravel packages to optimize performance, security and SEO in 2024</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%84%D8%AB-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-crud-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2427/" rel="">استخدام عمليات CRUD لإنشاء مدونة بسيطة في لارافيل</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AC%D8%B1%D9%8A%D8%AF-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D8%A8%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-migration-%D9%88%D8%A7%D9%84%D8%A8%D8%B0%D8%B1-seeder-r1725/" rel="">تجريد إعداد قواعد البيانات في لارافيل باستعمال عملية التهجير Migration والبذر Seeder</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-framework/" rel="">تعرف على مفهوم إطار العمل Framework وأهميته في البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%84%D8%BA%D8%A9-php-r2040/" rel="">تعرف على لغة PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2530</guid><pubDate>Wed, 12 Mar 2025 12:00:00 +0000</pubDate></item><item><title>&#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; &#x644;&#x644;&#x645;&#x628;&#x62A;&#x62F;&#x626;&#x64A;&#x646;-&#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62E;&#x627;&#x645;&#x633;: &#x625;&#x646;&#x634;&#x627;&#x621; &#x627;&#x644;&#x648;&#x627;&#x62C;&#x647;&#x629; &#x627;&#x644;&#x623;&#x645;&#x627;&#x645;&#x64A;&#x629; &#x644;&#x645;&#x62F;&#x648;&#x646;&#x629; &#x628;&#x633;&#x64A;&#x637;&#x629;</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AE%D8%A7%D9%85%D8%B3-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-%D9%84%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2442/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2024_11/----------.png.3bb02f0d17e3aed38462e76061a107d8.png" /></p>
<p>
	سننشئ في هذا المقال الأخير من <a href="https://academy.hsoub.com/tags/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84%20%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/" rel="">هذه السلسلة</a> جزء الواجهة الأمامية من التطبيق، ولكن لنضع خطة أولًا، حيث سيكون لدينا الصفحة الرئيسية لتطبيق المدونة التي تعرض قائمة بجميع المنشورات الحديثة، وصفحة فئة Category المنشور التي تعرض قائمة المنشورات ضمن فئة معينة، وصفحة الوسم Tag التي تعرض قائمة المنشورات التي لها وسم مُحدَّد، وصفحة المنشور التي تعرض محتوى منشور معين، وصفحة بحث تعرض قائمة المنشورات بناءً على استعلام بحث معين.
</p>

<p>
	كما ستحتوي جميع هذه الصفحات على شريط جانبي مع مربع بحث وقائمة الفئات والوسوم، وستحتوي صفحة المنشور أيضًا على قسم المنشورات ذات الصلة في نهايتها.
</p>

<p>
	تحدّثنا عن قاعدة البيانات والنماذج Models في <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%B1%D8%A7%D8%A8%D8%B9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%84%D9%88%D8%AD%D8%A9-%D8%AA%D8%AD%D9%83%D9%85-%D9%84%D9%85%D9%88%D9%82%D8%B9-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7-r2428/" rel="">المقال السابق</a>، وسنبدأ الآن بالوِجهات Routes.
</p>

<h2 id="-1">
	إنشاء الوِجهات
</h2>

<p>
	ننشئ الوِجهات في<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%B4%D9%87%D9%8A%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/" rel=""> لارافيل</a> ضمن الملف <code>routes/web.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_8" style=""><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

</span><span class="com">// الصفحة الرئيسية</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">PostController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'home'</span><span class="pun">])-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'home'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// قائمة المنشورات ضمن هذه الفئة</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/category/{category}'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">CategoryController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'category'</span><span class="pun">])-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'category'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// قائمة المنشورات التي لها هذا الوسم</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/tag/{tag}'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">TagController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'tag'</span><span class="pun">])-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'tag'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// عرض منشور واحد</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/post/{post}'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">PostController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'post'</span><span class="pun">])-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'post'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// قائمة المنشورات بناء على استعلام البحث</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/search'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">PostController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'search'</span><span class="pun">])-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'search'</span><span class="pun">);</span><span class="pln">

</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span></pre>

<h2 id="-2">
	الصفحة الرئيسية
</h2>

<p>
	يكون لكل من هذه الوِجهات تابع تحكم مقابل، حيث سنبدأ أولًا بالمتحكم <code>home()‎</code> إذًا لنضع ما يلي في الملف <code>app/Http/Controllers/PostController.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_10" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Category</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Tag</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Auth</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Builder</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * عرض الصفحة الرئيسية
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> home</span><span class="pun">():</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'is_published'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)-&gt;</span><span class="pln">paginate</span><span class="pun">(</span><span class="pln">env</span><span class="pun">(</span><span class="str">'PAGINATE_NUM'</span><span class="pun">));</span><span class="pln">
       $categories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">
       $tags </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'home'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'posts'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $posts</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'categories'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $categories</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'tags'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tags
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هناك شيئان يجب عليك ملاحظتهما في السطر 20 من الشيفرة البرمجية السابقة وهما:
</p>

<ul>
	<li>
		أولًا، تتأكد التعليمة <code>where('is_published', true)‎</code> من استرداد المقالات المنشورة فقط.
	</li>
	<li>
		ثانيًا، يُعَد التابع <code>paginate()‎</code> أحد توابع لارافيل Laravel المُضمَّنة، مما يسمح لك بإنشاء ترقيم للصفحات Pagination في تطبيقك بسهولة. يأخذ التابع <code>paginate()‎</code> عددًا صحيحًا كدخل، فمثلًا يمثّل <code>paginate(10)‎</code> عرض 10 عناصر في كل صفحة، وسيُستخدَم متغير الدخل في العديد من الصفحات، لذا يمكنك إنشاء متغير بيئة في ملف <code>‎.env</code> كما يلي، ثم يمكنك استرداده في أيّ مكان باستخدام التابع <code>env()‎</code>:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_12" style=""><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
PAGINATE_NUM</span><span class="pun">=</span><span class="lit">12</span></pre>

<p>
	لننشئ الآن عرض View الصفحة الرئيسية المقابل. اطّلع على <a href="https://github.com/ericsdevblog/blog-template" rel="external nofollow">بنية القوالب</a> التي أنشأئاها، وإليك بنية العروض التالية:
</p>

<pre class="ipsCode">resources/views
├── category.blade.php
├── home.blade.php
├── layout.blade.php
├── post.blade.php
├── search.blade.php
├── tag.blade.php
├── vendor
│   ├── list.blade.php
│   └── sidebar.blade.php
└── welcome.blade.php
</pre>

<p>
	سنبدأ أولًا بالعرض <code>layout.blade.php</code> الذي يمثل تخطيط الصفحة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_14" style=""><span class="dec">&lt;!doctype html&gt;</span><span class="pln">
</span><span class="tag">&lt;html</span><span class="pln"> </span><span class="atn">lang</span><span class="pun">=</span><span class="atv">"en"</span><span class="tag">&gt;</span><span class="pln">
 </span><span class="tag">&lt;head&gt;</span><span class="pln">
   </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"UTF-8"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
   </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">http-equiv</span><span class="pun">=</span><span class="atv">"X-UA-Compatible"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"IE=edge"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
   </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"viewport"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"width=device-width, initial-scale=1.0"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
   @vite(['resources/css/app.css', 'resources/js/app.js']) @yield('title')
 </span><span class="tag">&lt;/head&gt;</span><span class="pln">

 </span><span class="tag">&lt;body</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container mx-auto font-serif"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;nav</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"flex flex-row justify-between h-16 items-center border-b-2"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"px-5 text-2xl"</span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/"</span><span class="tag">&gt;</span><span class="pln"> My Blog </span><span class="tag">&lt;/a&gt;</span><span class="pln">
     </span><span class="tag">&lt;/div&gt;</span><span class="pln">
     </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"hidden lg:flex content-between space-x-10 px-10 text-lg"</span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;a</span><span class="pln">
         </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"https://github.com/ericnanhu"</span><span class="pln">
         </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"hover:underline hover:underline-offset-1"</span><span class="pln">
         </span><span class="tag">&gt;</span><span class="pln">GitHub</span><span class="tag">&lt;/a</span><span class="pln">
       </span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;a</span><span class="pln">
         </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('dashboard') }}"</span><span class="pln">
         </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"hover:underline hover:underline-offset-1"</span><span class="pln">
         </span><span class="tag">&gt;</span><span class="pln">Dashboard</span><span class="tag">&lt;/a</span><span class="pln">
       </span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"#"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"hover:underline hover:underline-offset-1"</span><span class="tag">&gt;</span><span class="pln">Link</span><span class="tag">&lt;/a&gt;</span><span class="pln">
     </span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;/nav&gt;</span><span class="pln">

   @yield('content')

   </span><span class="tag">&lt;footer</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-gray-700 text-white"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;div</span><span class="pln">
       </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"flex justify-center items-center sm:justify-between flex-wrap lg:max-w-screen-2xl mx-auto px-4 sm:px-8 py-10"</span><span class="pln">
     </span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"font-serif text-center mb-3 sm:mb-0"</span><span class="tag">&gt;</span><span class="pln">
         Copyright ©
         </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"https://www.ericsdevblog.com/"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"hover:underline"</span><span class="pln">
           </span><span class="tag">&gt;</span><span class="pln">Eric Hu</span><span class="tag">&lt;/a</span><span class="pln">
         </span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;/p&gt;</span><span class="pln">

       </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"flex justify-center space-x-4"</span><span class="tag">&gt;</span><span class="pln">. . .</span><span class="tag">&lt;/div&gt;</span><span class="pln">
     </span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;/footer&gt;</span><span class="pln">
 </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يستخدم لارافيل الأداة Vite افتراضيًا لتجميع أصول المشروع كما في السطر 8، وثبّتنا الحزمة Breeze من لارافيل في <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%B1%D8%A7%D8%A8%D8%B9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%84%D9%88%D8%AD%D8%A9-%D8%AA%D8%AD%D9%83%D9%85-%D9%84%D9%85%D9%88%D9%82%D8%B9-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7-r2428/" rel="">المقال السابق</a>، وتستخدم هذه الحزمة إطار عمل <a href="https://academy.hsoub.com/programming/css/bootstrap/%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%A8%D9%8A%D9%86-bootstrap-%D9%88-tailwind-css-r1595/" rel="">Tailwind CSS</a>، حيث سيستورد السطر 8 من الشيفرة البرمجية السابقة تلقائيًا الملفين <code>app.css</code> و <code>app.js</code> المقابلَين. يمكنك استخدام<a href="https://academy.hsoub.com/programming/general/%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-framework/" rel=""> إطار عمل</a> مختلف أيضًا، ولكن يجب أن تعود إلى توثيقه للحصول على تفاصيل حول كيفية استخدامه مع لارافيل أو Vite.
</p>

<p>
	لننشئ الآن عرض الصفحة الرئيسية <code>resources/views/home.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_20" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Home</span><span class="pun">&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"grid grid-cols-4 gap-4 py-10"</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"col-span-3 grid grid-cols-1"</span><span class="pun">&gt;</span><span class="lit">@include</span><span class="pun">(</span><span class="str">'vendor.list'</span><span class="pun">)&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="lit">@include</span><span class="pun">(</span><span class="str">'vendor.sidebar'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	ويكون عرض قائمة المنشورات <code>resources/views/vendor/list.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_22" style=""><span class="com">&lt;!-- قائمة المنشورات --&gt;</span><span class="pln">
</span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"grid grid-cols-3 gap-4"</span><span class="tag">&gt;</span><span class="pln">
 @foreach ($posts as $post)
 </span><span class="com">&lt;!-- المنشور --&gt;</span><span class="pln">
 </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"mb-4 ring-1 ring-slate-200 rounded-md h-fit hover:shadow-md"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('post', ['post' =&gt;</span><span class="pln"> $post-&gt;id]) }}"
     &gt;</span><span class="tag">&lt;img</span><span class="pln">
       </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"rounded-t-md object-cover h-60 w-full"</span><span class="pln">
       </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"{{ Storage::url($post-&gt;</span><span class="pln">cover) }}"
       alt="..."
   /&gt;</span><span class="tag">&lt;/a&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"m-4 grid gap-2"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"text-sm text-gray-500"</span><span class="tag">&gt;</span><span class="pln">
       {{ \Carbon\Carbon::parse($post-&gt;created_at)-&gt;format('M d, Y') }}
     </span><span class="tag">&lt;/div&gt;</span><span class="pln">
     </span><span class="tag">&lt;h2</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"text-lg font-bold"</span><span class="tag">&gt;</span><span class="pln">{{ $post-&gt;title }}</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
     </span><span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"text-base"</span><span class="tag">&gt;</span><span class="pln">
       {{ Str::limit(strip_tags($post-&gt;content), 150, '...') }}
     </span><span class="tag">&lt;/p&gt;</span><span class="pln">
     </span><span class="tag">&lt;a</span><span class="pln">
       </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-blue-500 hover:bg-blue-700 rounded-md p-2 text-white uppercase text-sm font-semibold font-sans w-fit focus:ring"</span><span class="pln">
       </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('post', ['post' =&gt;</span><span class="pln"> $post-&gt;id]) }}"
       &gt;Read more →</span><span class="tag">&lt;/a</span><span class="pln">
     </span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 @endforeach
</span><span class="tag">&lt;/div&gt;</span><span class="pln">

{{ $posts-&gt;links() }}</span></pre>

<p>
	يولّد السطر 9 <code>Storage::url($post-&gt;cover)‎</code> عنوان URL الذي يؤشّر إلى صورة الغلاف. لا تُعَد الطريقة التي يخزن بها لارافيل العلامات الزمنية Timestamps سهلة الاستخدام، لذلك استخدمنا حزمة Carbon في السطر 14 لإعادة تنسيق العلامات الزمنية.<br>
	استخدمنا أيضًا الدالة <code>strip_tags()‎</code> في السطر 18 لإزالة وسوم <a href="https://wiki.hsoub.com/HTML" rel="external">HTML</a>، ثم تحدِّد الدالة <code>limit()‎</code> الحد الأقصى لطول السلسلة، وستوضَع نقاط <code>...</code> مكان الجزء الزائد منها. استخدمنا التابع <code>paginate()‎</code> لإنشاء مرقّم الصفحات في المتحكم، ولكن يمكننا عرض مرقّم الصفحات في العرض باستخدام التعليمة <code>‎{{ $posts-&gt;links() }}‎</code> الموجودة في السطر 30.
</p>

<p>
	لننشئ الآن عرض الشريط الجانبي <code>resources/views/vendor/sidebar.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_25" style=""><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"col-span-1"</span><span class="tag">&gt;</span><span class="pln">
 </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"border rounded-md mb-4"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-slate-200 p-4"</span><span class="tag">&gt;</span><span class="pln">Search</span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"p-4"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;form</span><span class="pln">
       </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"{{ route('search') }}"</span><span class="pln">
       </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"POST"</span><span class="pln">
       </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"grid grid-cols-4 gap-2"</span><span class="pln">
     </span><span class="tag">&gt;</span><span class="pln">
       {{ csrf_field() }}
       </span><span class="tag">&lt;input</span><span class="pln">
         </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text"</span><span class="pln">
         </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"q"</span><span class="pln">
         </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"search"</span><span class="pln">
         </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"border rounded-md w-full focus:ring p-2 col-span-3"</span><span class="pln">
         </span><span class="atn">placeholder</span><span class="pun">=</span><span class="atv">"Search something..."</span><span class="pln">
       </span><span class="tag">/&gt;</span><span class="pln">
       </span><span class="tag">&lt;button</span><span class="pln">
         </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="pln">
         </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-blue-500 hover:bg-blue-700 rounded-md p-2 text-white uppercase font-semibold font-sans w-full focus:ring col-span-1"</span><span class="pln">
       </span><span class="tag">&gt;</span><span class="pln">
         Search
       </span><span class="tag">&lt;/button&gt;</span><span class="pln">
     </span><span class="tag">&lt;/form&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"border rounded-md mb-4"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-slate-200 p-4"</span><span class="tag">&gt;</span><span class="pln">Categories</span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"p-4"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"list-none list-inside"</span><span class="tag">&gt;</span><span class="pln">
       @foreach ($categories as $category)
       </span><span class="tag">&lt;li&gt;</span><span class="pln">
         </span><span class="tag">&lt;a</span><span class="pln">
           </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('category', ['category' =&gt;</span><span class="pln"> $category-&gt;id]) }}"
           class="text-blue-500 hover:underline"
           &gt;{{ $category-&gt;name }}</span><span class="tag">&lt;/a</span><span class="pln">
         </span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;/li&gt;</span><span class="pln">
       @endforeach
     </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"border rounded-md mb-4"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-slate-200 p-4"</span><span class="tag">&gt;</span><span class="pln">Tags</span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"p-4"</span><span class="tag">&gt;</span><span class="pln">
     @foreach ($tags as $tag)
     </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"mr-2"</span><span class="pln">
       </span><span class="tag">&gt;&lt;a</span><span class="pln">
         </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('tag', ['tag' =&gt;</span><span class="pln"> $tag-&gt;id]) }}"
         class="text-blue-500 hover:underline"
         &gt;{{ $tag-&gt;name }}</span><span class="tag">&lt;/a</span><span class="pln">
       </span><span class="tag">&gt;&lt;/span</span><span class="pln">
     </span><span class="tag">&gt;</span><span class="pln">
     @endforeach
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"border rounded-md mb-4"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-slate-200 p-4"</span><span class="tag">&gt;</span><span class="pln">More Card</span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"p-4"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;p&gt;</span><span class="pln">
       Lorem ipsum dolor sit amet consectetur adipisicing elit. Placeat,
       voluptatem ab tempore recusandae sequi libero sapiente autem! Sit hic
       reprehenderit pariatur autem totam, voluptates non officia accusantium
       rerum unde provident!
     </span><span class="tag">&lt;/p&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"border rounded-md mb-4"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-slate-200 p-4"</span><span class="tag">&gt;</span><span class="pln">...</span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"p-4"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;p&gt;</span><span class="pln">
       Lorem ipsum dolor sit amet consectetur adipisicing elit. Placeat,
       voluptatem ab tempore recusandae sequi libero sapiente autem! Sit hic
       reprehenderit pariatur autem totam, voluptates non officia accusantium
       rerum unde provident!
     </span><span class="tag">&lt;/p&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/div&gt;</span></pre>

<h2 id="category">
	صفحة الفئة Category
</h2>

<p>
	ضع ما يلي في ملف المتحكم <code>app/Http/Controllers/CategoryController.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_27" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Category</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Tag</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CategoryController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * عرض قائمة المنشورات التي تنتمي إلى الفئة
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> category</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $category </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
       $posts </span><span class="pun">=</span><span class="pln"> $category</span><span class="pun">-&gt;</span><span class="pln">posts</span><span class="pun">()-&gt;</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'is_published'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)-&gt;</span><span class="pln">paginate</span><span class="pun">(</span><span class="pln">env</span><span class="pun">(</span><span class="str">'PAGINATE_NUM'</span><span class="pun">));</span><span class="pln">
       $categories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">
       $tags </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'category'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'category'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $category</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'posts'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $posts</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'categories'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $categories</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'tags'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tags
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويكون عرض الفئة المقابل <code>resources/views/category.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_29" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Category</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> $category</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">}}&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"grid grid-cols-4 gap-4 py-10"</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"col-span-3 grid grid-cols-1"</span><span class="pun">&gt;</span><span class="lit">@include</span><span class="pun">(</span><span class="str">'vendor.list'</span><span class="pun">)&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="lit">@include</span><span class="pun">(</span><span class="str">'vendor.sidebar'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<h2 id="tag">
	صفحة الوسم Tag
</h2>

<p>
	ضع ما يلي في ملف المتحكم <code>app/Http/Controllers/TagController.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_31" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Category</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Tag</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">TagController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * عرض قائمة المنشورات التي تنتمي إلى الوسم
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> tag</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $tag </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
       $posts </span><span class="pun">=</span><span class="pln"> $tag</span><span class="pun">-&gt;</span><span class="pln">posts</span><span class="pun">()-&gt;</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'is_published'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)-&gt;</span><span class="pln">paginate</span><span class="pun">(</span><span class="pln">env</span><span class="pun">(</span><span class="str">'PAGINATE_NUM'</span><span class="pun">));</span><span class="pln">
       $categories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">
       $tags </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'tag'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'tag'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tag</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'posts'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $posts</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'categories'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $categories</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'tags'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tags
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويكون عرض الوسم المقابل <code>resources/views/tag.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_33" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Tag</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> $tag</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">}}&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"grid grid-cols-4 gap-4 py-10"</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"col-span-3 grid grid-cols-1"</span><span class="pun">&gt;</span><span class="lit">@include</span><span class="pun">(</span><span class="str">'vendor.list'</span><span class="pun">)&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="lit">@include</span><span class="pun">(</span><span class="str">'vendor.sidebar'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<h2 id="-3">
	صفحة المنشور
</h2>

<p>
	ضع ما يلي في ملف المتحكم <code>app/Http/Controllers/PostController.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_35" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Category</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Tag</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Auth</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Builder</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

   </span><span class="com">/**
    * عرض المنشور المطلوب
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> post</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $post </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
       $categories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">
       $tags </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">
       $related_posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'is_published'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)-&gt;</span><span class="pln">whereHas</span><span class="pun">(</span><span class="str">'tags'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Builder</span><span class="pln"> $query</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">use</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$post</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="kwd">return</span><span class="pln"> $query</span><span class="pun">-&gt;</span><span class="pln">whereIn</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">,</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">tags</span><span class="pun">-&gt;</span><span class="pln">pluck</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">));</span><span class="pln">
       </span><span class="pun">})-&gt;</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'!='</span><span class="pun">,</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">)-&gt;</span><span class="pln">take</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'post'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'post'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'categories'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $categories</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'tags'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tags</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'related_posts'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $related_posts
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لاحظ في السطور من 27 إلى 29 أن هذه هي الطريقة التي يمكننا من خلالها استرداد المنشورات ذات الصلة، حيث نريد الحصول على المنشورات التي يكون لها الوسوم نفسها. قد تبدو سلسلة هذه التوابع مخيفة نوعًا ما، لكن لا تقلق بشأن ذلك، حيث سنوضّحها واحدًا تلو الآخر كما يلي:
</p>

<ul>
	<li>
		يعيد التابع الأول <code>where('is_published', true)‎</code> جميع المنشورات التي نشرناها.
	</li>
	<li>
		تتعقد الأمور بعض الشيء عند التابع <code>whereHas()‎</code>، حيث إذا أردنا فهم هذا التابع، فيجب أن نتحدث أولًا عن التابع <code>has()‎</code>، وهو تابع <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D9%85%D8%A8%D8%A7%D8%AF%D8%A6-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D9%91%D8%A9-%D9%84%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-eloquent-orm-r410/" rel="">Laravel Eloquent</a> الذي يسمح لنا بالتحقق من وجود علاقة كما في المثال التالي:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6293_37" style=""><span class="pln">$posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">has</span><span class="pun">(</span><span class="str">'comments'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'&gt;'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)-&gt;</span><span class="pln">get</span><span class="pun">();</span></pre>

<p>
	ستسترد الشيفرة البرمجية السابقة جميع المنشورات التي تحتوي على أكثر من 3 تعليقات، ولاحظ أنه لا يمكنك استخدام <code>where()‎</code> لإنجاز ذلك، لأن <code>comments</code> ليس عمودًا في الجدول <code>posts</code>، بل هو جدول آخر له علاقة بالجدول <code>posts</code>. يعمل التابع <code>whereHas()‎</code> مثل التابع <code>has()‎</code> تمامًا، ولكنه يوفر مزيدًا من القوة، فالمعامل الثاني هو دالة تسمح بفحص محتوى جدول آخر، وهو الجدول <code>tags</code> في حالتنا، ويمكننا الوصول إلى الجدول <code>tags</code> من خلال المتغير <code>‎$q</code>.
</p>

<ul>
	<li>
		يأخذ التابع <code>whereIn()‎</code> في السطر 28 معاملَين هما: الأول هو العمود المحدَّد، والثاني هو مصفوفة من القيم المقبولة. يعيد هذا التابع السجلات ذات القيم المقبولة فقط ويستبعد الباقي.
	</li>
	<li>
		يجب أن تكون بقية التوابع سهلة الفهم، حيث يستبعد التابع <code>where('id', '!=', $post-&gt;id)‎</code> المنشور الحالي، ويأخذ التابع <code>take(3)‎</code> السجلات الثلاثة الأولى.
	</li>
</ul>

<p>
	يكون عرض المنشور المقابل <code>resources/views/post.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_40" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln">

</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Page</span><span class="pln"> </span><span class="typ">Title</span><span class="pun">&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln">

</span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"grid grid-cols-4 gap-4 py-10"</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"col-span-3"</span><span class="pun">&gt;</span><span class="pln">

       </span><span class="pun">&lt;</span><span class="pln">img </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"rounded-md object-cover h-96 w-full"</span><span class="pln"> src</span><span class="pun">=</span><span class="str">"{{ Storage::url($post-&gt;cover) }}"</span><span class="pln"> alt</span><span class="pun">=</span><span class="str">"..."</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln">
       </span><span class="pun">&lt;</span><span class="pln">h1 </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"mt-5 mb-2 text-center text-2xl font-bold"</span><span class="pun">&gt;{{</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">title </span><span class="pun">}}&lt;/</span><span class="pln">h1</span><span class="pun">&gt;</span><span class="pln">
       </span><span class="pun">&lt;</span><span class="pln">p </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"mb-5 text-center text-sm text-slate-500 italic"</span><span class="pun">&gt;</span><span class="typ">By</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">user</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">}}</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> \Carbon\Carbon</span><span class="pun">::</span><span class="pln">parse</span><span class="pun">(</span><span class="pln">$post</span><span class="pun">-&gt;</span><span class="pln">created_at</span><span class="pun">)-&gt;</span><span class="pln">format</span><span class="pun">(</span><span class="str">'M d, Y'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">

       </span><span class="str">&lt;div&gt;</span><span class="pun">{!!</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">content </span><span class="pun">!!}&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">

       </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"my-5"</span><span class="pun">&gt;</span><span class="pln">
           </span><span class="lit">@foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$post</span><span class="pun">-&gt;</span><span class="pln">tags </span><span class="kwd">as</span><span class="pln"> $tag</span><span class="pun">)</span><span class="pln">
           </span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"{{ route('tag', ['tag' =&gt; $tag-&gt;id]) }}"</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"text-blue-500 hover:underline"</span><span class="pln"> mr</span><span class="pun">-</span><span class="lit">3</span><span class="str">"&gt;#{{ $tag-&gt;name }}&lt;/a&gt;
           @endforeach
       &lt;/div&gt;

       &lt;hr&gt;

       &lt;!-- المنشورات ذات الصلة --&gt;

       &lt;div class="</span><span class="pln">grid grid</span><span class="pun">-</span><span class="pln">cols</span><span class="pun">-</span><span class="lit">3</span><span class="pln"> gap</span><span class="pun">-</span><span class="lit">4</span><span class="pln"> </span><span class="kwd">my</span><span class="pun">-</span><span class="lit">5</span><span class="str">"&gt;
           @foreach ($related_posts as $post)
           &lt;!-- المنشور --&gt;
           &lt;div class="</span><span class="pln">mb</span><span class="pun">-</span><span class="lit">4</span><span class="pln"> ring</span><span class="pun">-</span><span class="lit">1</span><span class="pln"> ring</span><span class="pun">-</span><span class="pln">slate</span><span class="pun">-</span><span class="lit">200</span><span class="pln"> rounded</span><span class="pun">-</span><span class="pln">md h</span><span class="pun">-</span><span class="pln">fit hover</span><span class="pun">:</span><span class="pln">shadow</span><span class="pun">-</span><span class="pln">md</span><span class="str">"&gt;
               &lt;a href="</span><span class="pun">{{</span><span class="pln"> route</span><span class="pun">(</span><span class="str">'post'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'post'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">])</span><span class="pln"> </span><span class="pun">}}</span><span class="str">"&gt;&lt;img class="</span><span class="pln">rounded</span><span class="pun">-</span><span class="pln">t</span><span class="pun">-</span><span class="pln">md </span><span class="kwd">object</span><span class="pun">-</span><span class="pln">cover h</span><span class="pun">-</span><span class="lit">60</span><span class="pln"> w</span><span class="pun">-</span><span class="pln">full</span><span class="str">" src="</span><span class="pun">{{</span><span class="pln"> </span><span class="typ">Storage</span><span class="pun">::</span><span class="pln">url</span><span class="pun">(</span><span class="pln">$post</span><span class="pun">-&gt;</span><span class="pln">cover</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}</span><span class="str">" alt="</span><span class="pun">...</span><span class="str">" /&gt;&lt;/a&gt;
               &lt;div class="</span><span class="pln">m</span><span class="pun">-</span><span class="lit">4</span><span class="pln"> grid gap</span><span class="pun">-</span><span class="lit">2</span><span class="str">"&gt;
                   &lt;div class="</span><span class="pln">text</span><span class="pun">-</span><span class="pln">sm text</span><span class="pun">-</span><span class="pln">gray</span><span class="pun">-</span><span class="lit">500</span><span class="str">"&gt;
                       {{ \Carbon\Carbon::parse($post-&gt;created_at)-&gt;format('M d, Y') }}
                   &lt;/div&gt;
                   &lt;h2 class="</span><span class="pln">text</span><span class="pun">-</span><span class="pln">lg font</span><span class="pun">-</span><span class="pln">bold</span><span class="str">"&gt;{{ $post-&gt;title }}&lt;/h2&gt;
                   &lt;p class="</span><span class="pln">text</span><span class="pun">-</span><span class="kwd">base</span><span class="str">"&gt;
                       {{ Str::limit(strip_tags($post-&gt;content), 150, '...') }}
                   &lt;/p&gt;
                   &lt;a class="</span><span class="pln">bg</span><span class="pun">-</span><span class="pln">blue</span><span class="pun">-</span><span class="lit">500</span><span class="pln"> hover</span><span class="pun">:</span><span class="pln">bg</span><span class="pun">-</span><span class="pln">blue</span><span class="pun">-</span><span class="lit">700</span><span class="pln"> rounded</span><span class="pun">-</span><span class="pln">md p</span><span class="pun">-</span><span class="lit">2</span><span class="pln"> text</span><span class="pun">-</span><span class="pln">white uppercase text</span><span class="pun">-</span><span class="pln">sm font</span><span class="pun">-</span><span class="pln">semibold font</span><span class="pun">-</span><span class="pln">sans w</span><span class="pun">-</span><span class="pln">fit focus</span><span class="pun">:</span><span class="pln">ring</span><span class="str">" href="</span><span class="pun">{{</span><span class="pln"> route</span><span class="pun">(</span><span class="str">'post'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'post'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">])</span><span class="pln"> </span><span class="pun">}}</span><span class="str">"&gt;Read more →&lt;/a&gt;
               &lt;/div&gt;
           &lt;/div&gt;
           @endforeach
       &lt;/div&gt;

   &lt;/div&gt;
   @include('vendor.sidebar')
&lt;/div&gt;
@endsection</span></pre>

<p>
	يُعَد ‎<code>{!! $post-&gt;content !!}</code>‎ في السطر 15 هو الوضع الآمن في لارافيل، حيث يخبر لارافيل بعرض وسوم HTML بدلًا من عرضها كنص عادي.
</p>

<h2 id="-4">
	صفحة البحث
</h2>

<p>
	ضع ما يلي في ملف المتحكم <code>app/Http/Controllers/PostController.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_42" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Category</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Tag</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Auth</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Builder</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

   </span><span class="com">/**
    * عرض نتيجة البحث
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> search</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $key </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'q'</span><span class="pun">);</span><span class="pln">
       $posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'like'</span><span class="pun">,</span><span class="pln"> </span><span class="str">"%{$key}%"</span><span class="pun">)-&gt;</span><span class="pln">orderBy</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'desc'</span><span class="pun">)-&gt;</span><span class="pln">paginate</span><span class="pun">(</span><span class="pln">env</span><span class="pun">(</span><span class="str">'PAGINATE_NUM'</span><span class="pun">));</span><span class="pln">
       $categories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">
       $tags </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'search'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'key'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $key</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'posts'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $posts</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'categories'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $categories</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'tags'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tags</span><span class="pun">,</span><span class="pln">
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يكون عرض البحث المقابل <code>resources/views/search.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6293_44" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Search</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> $key </span><span class="pun">}}&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"grid grid-cols-4 gap-4 py-10"</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"col-span-3 grid grid-cols-1"</span><span class="pun">&gt;</span><span class="lit">@include</span><span class="pun">(</span><span class="str">'vendor.list'</span><span class="pun">)&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="lit">@include</span><span class="pun">(</span><span class="str">'vendor.sidebar'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	ترجمة -وبتصرُّف- للمقال <a href="https://www.ericsdevblog.com/posts/laravel-for-beginners-5/" rel="external nofollow">Laravel for Beginners #5 - Create the Frontend</a> لصاحبه Eric Hu.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%B1%D8%A7%D8%A8%D8%B9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%84%D9%88%D8%AD%D8%A9-%D8%AA%D8%AD%D9%83%D9%85-%D9%84%D9%85%D9%88%D9%82%D8%B9-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7-r2428/" rel="">لارافيل للمبتدئين-الجزء الرابع: إنشاء لوحة تحكم لموقع مدونة بسيطة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%B4%D9%87%D9%8A%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/" rel="">تعرف على إطار عمل تطوير الويب الشهير لارافيل Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D8%B4%D8%A6-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-query-builder-%D9%84%D9%84%D8%AA%D8%AE%D8%A7%D8%B7%D8%A8-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-r398/" rel="">كيف تستخدم منشئ الاستعلامات Query builder للتخاطب مع قاعدة البيانات في Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AC%D8%B1%D9%8A%D8%AF-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D8%A8%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-migration-%D9%88%D8%A7%D9%84%D8%A8%D8%B0%D8%B1-seeder-r1725/" rel="">تجريد إعداد قواعد البيانات في لارافيل باستعمال عملية التهجير Migration والبذر Seeder</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2442</guid><pubDate>Wed, 06 Nov 2024 15:02:01 +0000</pubDate></item><item><title>&#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; &#x644;&#x644;&#x645;&#x628;&#x62A;&#x62F;&#x626;&#x64A;&#x646;-&#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x631;&#x627;&#x628;&#x639;: &#x625;&#x646;&#x634;&#x627;&#x621; &#x644;&#x648;&#x62D;&#x629; &#x62A;&#x62D;&#x643;&#x645; &#x644;&#x645;&#x62F;&#x648;&#x646;&#x629; &#x628;&#x633;&#x64A;&#x637;&#x629;</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%B1%D8%A7%D8%A8%D8%B9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%84%D9%88%D8%AD%D8%A9-%D8%AA%D8%AD%D9%83%D9%85-%D9%84%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2428/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2024_10/-----------.png.b81005b85da2592e4bb404464f2cb8c9.png" /></p>
<p>
	سننشئ في هذا المقال تطبيق مدونة باستخدام لارافيل ونجعل تطبيقنا كامل الميزات ويحتوي على منشورات وفئات Categories ووسوم Tags، حيث ناقشنا في <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%84%D8%AB-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-crud-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2427/" rel="">المقال السابق</a> عمليات CRUD للمنشورات، وسنكرر اليوم هذه العمليات نفسها على كل من الفئات والوسوم، كما سنناقش كيفية التعامل مع العلاقات فيما بينها.
</p>

<h2 id="-1">
	تهيئة مشروع لارافيل جديد
</h2>

<p>
	سنبدأ بمشروع <a href="https://wiki.hsoub.com/Laravel" rel="external">لارافيل</a> جديد، حيث سننشئ مجلد العمل وننتقل إليه، ولكن تأكّد من تشغيل دوكر <a href="https://academy.hsoub.com/devops/cloud-computing/docker/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AF%D9%88%D9%83%D8%B1-docker-r607/" rel="">Docker</a>، ثم نفّذ الأمر التالي:
</p>

<pre class="ipsCode">curl -s https://laravel.build/&lt;app_name&gt; | bash
</pre>

<p>
	انتقل إلى مجلد التطبيق وابدأ تشغيل الخادم كما يلي:
</p>

<pre class="ipsCode">cd &lt;app_name&gt;
</pre>

<pre class="ipsCode">./vendor/bin/sail up
</pre>

<p>
	لننشئ اسمًا بديلًا للأداة <code>sail</code> لتسهيل الأمور، لذا شغّل الأمر التالي:
</p>

<pre class="ipsCode">alias sail='[ -f sail ] &amp;&amp; sh sail || sh vendor/bin/sail'
</pre>

<p>
	يمكنك من الآن فصاعدًا تشغيل الأداة Sail مباشرةً دون تحديد المسار بأكمله كما يلي:
</p>

<pre class="ipsCode">sail up
</pre>

<h2 id="userauthentication">
	استيثاق المستخدم User authentication
</h2>

<p>
	يأتي إطار عمل لارافيل مع نظام بيئي كبير فهو  يحتوي على العديد من الأدوات والموارد الإضافية التي تسهل على المطورين <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA/" rel="">برمجة التطبيقات</a>، وتُعَد حزمة Breeze من لارافيل جزءًا من هذا النظام، فهي توفر طريقة سريعة لإعداد <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D9%8A%D8%AB%D8%A7%D9%82-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D9%8A%D9%86-user-authentication-%D9%81%D9%8A-laravel-5-r229/" rel="">استيثاق المستخدم </a>وتسجيله في تطبيق لارافيل. تتضمّن حزمة Breeze عروضًا Views ومتحكّمات Controllers مبنية مسبقًا خاصة بالاستيثاق، بالإضافة إلى مجموعة من <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-r1314/" rel="">واجهات برمجة التطبيقات</a> الخلفية للتعامل مع استيثاق المستخدم وتسجيله، وصُمِّمت هذه الحزمة لتكون سهلة التثبيت والضبط مع وجود الحد الأدنى من الإعداد المطلوب.
</p>

<p>
	استخدم الأوامر التالية لتثبيت حزمة Breeze من لارافيل:
</p>

<pre class="ipsCode" id="ips_uid_4578_9">sail composer require laravel/breeze --dev
sail artisan breeze:install
sail artisan migrate
sail npm install
sail npm run dev
</pre>

<p>
	ستولّد هذه العملية تلقائيًا كل من المتحكمات والبرمجيات الوسيطة والعروض المطلوبة اللازمة لإنشاء نظام استيثاق مستخدم أساسي في تطبيقك. يمكنك الوصول إلى صفحة التسجيل من العنوان <code>http://127.0.0.1/register</code>، ثم تسجّل حسابًا جديدًا وسيُعاد توجيهك إلى لوحة التحكم.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159700" href="https://academy.hsoub.com/uploads/monthly_2024_10/01_register.png.078f74a172cc68c898da17fc5ec90e1a.png" rel=""><img alt="01 register" class="ipsImage ipsImage_thumbnailed" data-fileid="159700" data-unique="ja43l6n5r" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2024_10/01_register.thumb.png.f8084ce284d91bea8a356b25e1ec39b8.png"> </a>
</p>

<p>
	لن نناقش في هذا المقال كيفية عمل نظام استيثاق المستخدم، لأنه يرتبط ببعض المفاهيم المتقدمة إلى حدٍ ما، ولكن يوصَى بشدة بإلقاء نظرة على الملفات التي تولّدت هنا، فهي توفر نظرة أعمق حول كيفية العمل في لارافيل.
</p>

<h2 id="-2">
	إعداد قاعدة البيانات
</h2>

<p>
	يجب بعد ذلك أن يكون لدينا تصور حول كيفية ظهور تطبيق المدونة، حيث نحتاج أولًا إلى قاعدة بيانات يمكنها تخزين المنشورات والفئات والوسوم، وسيكون لكل جدول قاعدة بيانات البنيةُ التالية:
</p>

<p>
	<strong>جدول المنشورات Posts</strong>:
</p>

<table>
	<thead>
		<tr>
			<th>
				المفتاح
			</th>
			<th>
				نوعه
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				id
			</td>
			<td>
				عدد صحيح كبير BigInteger
			</td>
		</tr>
		<tr>
			<td>
				created_at
			</td>
			<td>
				timestamps يملأ تلقائيًا عند إنشاء سجل جديد
			</td>
		</tr>
		<tr>
			<td>
				updated_at
			</td>
			<td>
				timestamps يملأ تلقائيًا عند تحديث سجل جديد
			</td>
		</tr>
		<tr>
			<td>
				title
			</td>
			<td>
				سلسلة نصية String
			</td>
		</tr>
		<tr>
			<td>
				cover
			</td>
			<td>
				سلسلة نصية String
			</td>
		</tr>
		<tr>
			<td>
				content
			</td>
			<td>
				نص Text
			</td>
		</tr>
		<tr>
			<td>
				is_published
			</td>
			<td>
				قيمة منطقية Boolean
			</td>
		</tr>
	</tbody>
</table>

<p>
	<strong>جدول الفئات Categories</strong>:
</p>

<table>
	<thead>
		<tr>
			<th>
				المفتاح
			</th>
			<th>
				نوعه
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				id
			</td>
			<td>
				عدد صحيح كبير
			</td>
		</tr>
		<tr>
			<td>
				created_at
			</td>
			<td>
				timestamps يملأ تلقائيًا عند إنشاء سجل جديد
			</td>
		</tr>
		<tr>
			<td>
				updated_at
			</td>
			<td>
				timestamps يملأ تلقائيًا عند تحديث سجل جديد
			</td>
		</tr>
		<tr>
			<td>
				name
			</td>
			<td>
				سلسلة نصية String
			</td>
		</tr>
	</tbody>
</table>

<p>
	<strong>جدول الوسوم Tags</strong>:
</p>

<table>
	<thead>
		<tr>
			<th>
				المفتاح
			</th>
			<th>
				نوعه
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				id
			</td>
			<td>
				عدد صحيح كبير
			</td>
		</tr>
		<tr>
			<td>
				created_at
			</td>
			<td>
				timestamps يملأ تلقائيًا عند إنشاء سجل جديد
			</td>
		</tr>
		<tr>
			<td>
				updated_at
			</td>
			<td>
				timestamps يملأ تلقائيًا عند إنشاء سجل جديد
			</td>
		</tr>
		<tr>
			<td>
				name
			</td>
			<td>
				سلسلة نصية
			</td>
		</tr>
	</tbody>
</table>

<p>
	يجب أن يكون هناك أيضًا جدول للمستخدمين <code>users</code>، ولكن لاحاجة لأن ننشئه فقد ولّدته حزمة Breeze من لارافيل مسبقًا، لذا سنتخطى هذه الخطوة حاليًا.
</p>

<p>
	يكون لهذه الجداول <a href="https://academy.hsoub.com/programming/sql/%D8%A7%D9%84%D8%B9%D9%84%D8%A7%D9%82%D8%A7%D8%AA-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%AF%D8%A7%D9%88%D9%84-%D9%81%D9%8A-sql-r590/" rel="">علاقات</a> مع بعضها البعض كما هو موضح فيما يلي:
</p>

<ul>
	<li>
		كل مستخدم لديه منشورات متعددة.
	</li>
	<li>
		كل فئة لديها العديد من المنشورات.
	</li>
	<li>
		كل وسم لديه العديد من المنشورات.
	</li>
	<li>
		يعودة كل منشور إلى مستخدم واحد.
	</li>
	<li>
		يعود كل منشور إلى فئة واحدة.
	</li>
	<li>
		كل منشور له العديد من الوسوم.
	</li>
</ul>

<p>
	يمكننا إنشاء هذه العلاقات، ولكن يجب تعديل جدول المنشورات كما يلي:
</p>

<p>
	<strong>جدول المنشورات مع العلاقات</strong>:
</p>

<table>
	<thead>
		<tr>
			<th>
				المفتاح
			</th>
			<th>
				نوعه
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				id
			</td>
			<td>
				عدد صحيح كبير
			</td>
		</tr>
		<tr>
			<td>
				created_at
			</td>
			<td>
				timestamps يملأ تلقائيًا عند إنشاء سجل جديد
			</td>
		</tr>
		<tr>
			<td>
				updated_at
			</td>
			<td>
				timestamps يملأ تلقائيًا عند تحديث سجل جديد
			</td>
		</tr>
		<tr>
			<td>
				title
			</td>
			<td>
				سلسلة نصية String
			</td>
		</tr>
		<tr>
			<td>
				cover
			</td>
			<td>
				سلسلة نصية String
			</td>
		</tr>
		<tr>
			<td>
				content
			</td>
			<td>
				نص Text
			</td>
		</tr>
		<tr>
			<td>
				is_published
			</td>
			<td>
				قيمة منطقية
			</td>
		</tr>
		<tr>
			<td>
				user_id
			</td>
			<td>
				عدد صحيح كبير
			</td>
		</tr>
		<tr>
			<td>
				category_id
			</td>
			<td>
				عدد صحيح كبير
			</td>
		</tr>
	</tbody>
</table>

<p>
	ونحتاج أيضًا إلى جدول منفصل لعلاقة المنشور مع الوسم كما يلي:
</p>

<p>
	<strong>جدول يمثل علاقة المنشور مع الوسم Post/Tag</strong>:
</p>

<table>
	<thead>
		<tr>
			<th>
				المفتاح
			</th>
			<th>
				نوعه
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				post_id
			</td>
			<td>
				عدد صحيح كبير
			</td>
		</tr>
		<tr>
			<td>
				tag_id
			</td>
			<td>
				عدد صحيح كبير
			</td>
		</tr>
	</tbody>
</table>

<h3 id="-3">
	تطبيق بنية قاعدة البيانات
</h3>

<p>
	يمكن تطبيق التصميم السابق من خلال توليد النماذج Models وملفات<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r224/" rel=""> التهجير Migration</a> باستخدام الأوامر التالية:
</p>

<pre class="ipsCode">sail artisan make:model Post --migration
</pre>

<pre class="ipsCode">sail artisan make:model Category --migration
</pre>

<pre class="ipsCode">sail artisan make:model Tag --migration
</pre>

<p>
	بالإضافة إلى توليد ملف تهجير منفصل للجدول <code>post_tag</code> باستخدام الأمر التالي:
</p>

<pre class="ipsCode">sail artisan make:migration create_post_tag_table
</pre>

<p>
	وسينشأ ملف التهجير <code>database/migrations/create_posts_table.php</code> التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_12" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Migrations\Migration</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Schema\Blueprint</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Schema</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Migration</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * تشغيل عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">);</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'cover'</span><span class="pun">);</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">text</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">);</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="kwd">boolean</span><span class="pun">(</span><span class="str">'is_published'</span><span class="pun">);</span><span class="pln">

           $table</span><span class="pun">-&gt;</span><span class="pln">bigInteger</span><span class="pun">(</span><span class="str">'user_id'</span><span class="pun">);</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">bigInteger</span><span class="pun">(</span><span class="str">'category_id'</span><span class="pun">);</span><span class="pln">
       </span><span class="pun">});</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عكس عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> down</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	وسينشأ ملف التهجير <code>database/migrations/create_categories_table.php</code> التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_14" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Migrations\Migration</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Schema\Blueprint</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Schema</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Migration</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * تشغيل عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'categories'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">
       </span><span class="pun">});</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عكس عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> down</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'categories'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	وسينشأ ملف التهجير <code>database/migrations/create_tags_table.php</code> التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_16" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Migrations\Migration</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Schema\Blueprint</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Schema</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Migration</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * تشغيل عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'tags'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">
       </span><span class="pun">});</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عكس عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> down</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'tags'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	وسينشأ أيضُا ملف التهجير <code>database/migrations/create_post_tag_table.php</code> التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_18" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Migrations\Migration</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Schema\Blueprint</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Schema</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Migration</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * تشغيل عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'post_tag'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">bigInteger</span><span class="pun">(</span><span class="str">'post_id'</span><span class="pun">);</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">bigInteger</span><span class="pun">(</span><span class="str">'tag_id'</span><span class="pun">);</span><span class="pln">
       </span><span class="pun">});</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عكس عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> down</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'post_tag'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	طبّق هذه التغييرات باستخدام الأمر التالي:
</p>

<pre class="ipsCode">sail artisan migrate
</pre>

<p>
	يجب بعد ذلك تفعيل الإسناد الجماعي <a href="https://laravel.com/docs/11.x/eloquent#mass-assignment" rel="external nofollow">Mass Assignment</a> لحقول محدَّدة بالنسبة للنماذج المقابلة حتى نتمكّن من استخدام تابعَي <code>create</code> أو <code>update</code> معها كما ناقشنا في المقال السابق، ويجب أيضًا تعريف العلاقات بين جداول قاعدة البيانات.
</p>

<p>
	سيكون ملف النموذج <code>app/Models/Post.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_20" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Factories\HasFactory</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Relations\BelongsTo</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Relations\BelongsToMany</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Post</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">HasFactory</span><span class="pun">;</span><span class="pln">

   </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
       </span><span class="str">"title"</span><span class="pun">,</span><span class="pln">
       </span><span class="str">'content'</span><span class="pun">,</span><span class="pln">
       </span><span class="str">'cover'</span><span class="pun">,</span><span class="pln">
       </span><span class="str">'is_published'</span><span class="pln">
   </span><span class="pun">];</span><span class="pln">

   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> user</span><span class="pun">():</span><span class="pln"> </span><span class="typ">BelongsTo</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">belongsTo</span><span class="pun">(</span><span class="typ">User</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> category</span><span class="pun">():</span><span class="pln"> </span><span class="typ">BelongsTo</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">belongsTo</span><span class="pun">(</span><span class="typ">Category</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> tags</span><span class="pun">():</span><span class="pln"> </span><span class="typ">BelongsToMany</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">belongsToMany</span><span class="pun">(</span><span class="typ">Tag</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	وسيكون ملف النموذج <code>app/Models/Category.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_22" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Factories\HasFactory</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Relations\HasMany</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Category</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">HasFactory</span><span class="pun">;</span><span class="pln">

   </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
       </span><span class="str">'name'</span><span class="pun">,</span><span class="pln">
   </span><span class="pun">];</span><span class="pln">

   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> posts</span><span class="pun">():</span><span class="pln"> </span><span class="typ">HasMany</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">hasMany</span><span class="pun">(</span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويكون ملف النموذج <code>app/Models/Tag.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_24" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Factories\HasFactory</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Relations\BelongsToMany</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Tag</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">HasFactory</span><span class="pun">;</span><span class="pln">

   </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
       </span><span class="str">'name'</span><span class="pun">,</span><span class="pln">
   </span><span class="pun">];</span><span class="pln">

   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> posts</span><span class="pun">():</span><span class="pln"> </span><span class="typ">BelongsToMany</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">belongsToMany</span><span class="pun">(</span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويكون ملف النموذج <code>app/Models/User.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_26" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models</span><span class="pun">;</span><span class="pln">

</span><span class="com">// use Illuminate\Contracts\Auth\MustVerifyEmail;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Factories\HasFactory</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Relations\HasMany</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Foundation\Auth\User </span><span class="kwd">as</span><span class="pln"> </span><span class="typ">Authenticatable</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Notifications\Notifiable</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Laravel</span><span class="pln">\Sanctum\HasApiTokens</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">User</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Authenticatable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">HasApiTokens</span><span class="pun">,</span><span class="pln"> </span><span class="typ">HasFactory</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Notifiable</span><span class="pun">;</span><span class="pln">

   </span><span class="com">/**
    * السمات‫ Attributes التي نسندها إسنادًا جماعيًا
    *
    * @var array&lt;int, string&gt;
    */</span><span class="pln">
   </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
       </span><span class="str">'name'</span><span class="pun">,</span><span class="pln">
       </span><span class="str">'email'</span><span class="pun">,</span><span class="pln">
       </span><span class="str">'password'</span><span class="pun">,</span><span class="pln">
   </span><span class="pun">];</span><span class="pln">

   </span><span class="com">/**
    * ‫السمات التي يجب أن تكون مخفية لعملية السَلسلة Serialization
    *
    * @var array&lt;int, string&gt;
    */</span><span class="pln">
   </span><span class="kwd">protected</span><span class="pln"> $hidden </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
       </span><span class="str">'password'</span><span class="pun">,</span><span class="pln">
       </span><span class="str">'remember_token'</span><span class="pun">,</span><span class="pln">
   </span><span class="pun">];</span><span class="pln">

   </span><span class="com">/**
    * السمات التي يجب تغيير نوعها‫ Cast
    *
    * @var array&lt;string, string&gt;
    */</span><span class="pln">
   </span><span class="kwd">protected</span><span class="pln"> $casts </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
       </span><span class="str">'email_verified_at'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'datetime'</span><span class="pun">,</span><span class="pln">
   </span><span class="pun">];</span><span class="pln">

   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> posts</span><span class="pun">():</span><span class="pln"> </span><span class="typ">HasMany</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">hasMany</span><span class="pun">(</span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="controllersroutes">
	المتحكمات Controllers والوِجهات Routes
</h2>

<p>
	نحتاج إلى إنشاء متحكم موارد واحد لكل مورد (منشور وفئة ووسم) باستخدام الأوامر التالية:
</p>

<pre class="ipsCode">php artisan make:controller PostController --resource
</pre>

<pre class="ipsCode">php artisan make:controller CategoryController --resource
</pre>

<pre class="ipsCode">php artisan make:controller TagController --resource
</pre>

<p>
	ننشئ بعد ذلك وِجهات لكل من هذه المتحكمات في الملف <code>routes/web.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_29" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\CategoryController</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\PostController</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\ProfileController</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\TagController</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Route</span><span class="pun">;</span><span class="pln">

</span><span class="com">// وِجهات لوحة التحكم</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">prefix</span><span class="pun">(</span><span class="str">'dashboard'</span><span class="pun">)-&gt;</span><span class="kwd">group</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">

   </span><span class="com">// الصفحة الرئيسية للوحة التحكم</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'dashboard'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">})-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'dashboard'</span><span class="pun">);</span><span class="pln">

   </span><span class="com">// مورد الفئة للوحة التحكم</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="pln">resource</span><span class="pun">(</span><span class="str">'categories'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">CategoryController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">

   </span><span class="com">// مورد الوسم للوحة التحكم</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="pln">resource</span><span class="pun">(</span><span class="str">'tags'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">TagController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">

   </span><span class="com">// مورد المنشور للوحة التحكم</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="pln">resource</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">PostController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">

</span><span class="pun">})-&gt;</span><span class="pln">middleware</span><span class="pun">([</span><span class="str">'auth'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'verified'</span><span class="pun">]);</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">middleware</span><span class="pun">(</span><span class="str">'auth'</span><span class="pun">)-&gt;</span><span class="kwd">group</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/profile'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">ProfileController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'edit'</span><span class="pun">])-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'profile.edit'</span><span class="pun">);</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="pln">patch</span><span class="pun">(</span><span class="str">'/profile'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">ProfileController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'update'</span><span class="pun">])-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'profile.update'</span><span class="pun">);</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">delete</span><span class="pun">(</span><span class="str">'/profile'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">ProfileController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'destroy'</span><span class="pun">])-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'profile.destroy'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="kwd">require</span><span class="pln"> __DIR__ </span><span class="pun">.</span><span class="pln"> </span><span class="str">'/auth.php'</span><span class="pun">;</span></pre>

<p>
	لاحظ تجميع جميع الوِجهات باستخدام البادئة <code>‎/dashboard</code>، ويكون للمجموعة البرمجيةُ الوسيطة <code>auth</code>، مما يعني أنه يجب على المستخدم تسجيل الدخول للوصول إلى لوحة التحكم.
</p>

<h3 id="categorytag">
	متحكمات الفئة والوسم Category/Tag
</h3>

<p>
	يُعََد المتحكمان <code>CategoryController</code> و <code>TagController</code> واضحَين إلى حدٍ ما، ويمكنك إعدادهما بالطريقة نفسها التي أنشأنا بها المتحكم <code>PostController</code> في <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%84%D8%AB-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-crud-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2427/" rel="">المقال السابق</a>.
</p>

<p>
	إذًا لننشئ أولًا <strong>متحكم الفئة</strong> <code>app/Http/Controllers/CategoryController.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_31" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Category</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CategoryController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * عرض قائمة الموارد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">():</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $categories </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'categories.index'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'categories'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $categories
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عرض الاستمارة الخاصة بإنشاء مورد جديد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> create</span><span class="pun">():</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'categories.create'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * تخزين المورد الذي أنشأناه حديثًا في وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">// الحصول على البيانات من الطلب</span><span class="pln">
       $name </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">

       </span><span class="com">// إنشاء نسخة جديدة من المنشور‫ Post ووضع البيانات المطلوبة في العمود المقابل</span><span class="pln">
       $category </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">();</span><span class="pln">
       $category</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> $name</span><span class="pun">;</span><span class="pln">

       </span><span class="com">// حفظ البيانات</span><span class="pln">
       $category</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'categories.index'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عرض المورد المُحدَّد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> show</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $category </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
       $posts </span><span class="pun">=</span><span class="pln"> $category</span><span class="pun">-&gt;</span><span class="pln">posts</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'categories.show'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'category'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $category</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'posts'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $posts
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عرض الاستمارة الخاصة بتعديل المورد المُحدَّد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> edit</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $category </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'categories.edit'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'category'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $category
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * تحديث المورد المُحدَّد في وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> update</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">// الحصول على البيانات من الطلب</span><span class="pln">
       $name </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">

       </span><span class="com">// البحث عن الفئة المطلوبة ووضع البيانات المطلوبة في العمود المقابل</span><span class="pln">
       $category </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
       $category</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> $name</span><span class="pun">;</span><span class="pln">

       </span><span class="com">// حفظ البيانات</span><span class="pln">
       $category</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'categories.index'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * إزالة المورد المٌحدَّد من وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> destroy</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $category </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">

       $category</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'categories.index'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ولننشئ الآن <strong>متحكم الوسم</strong> <code>app/Http/Controllers/TagController.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_33" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Tag</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">TagController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * عرض قائمة الموارد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">():</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $tags </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'tags.index'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'tags'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tags
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عرض الاستمارة الخاصة بإنشاء مورد جديد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> create</span><span class="pun">():</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'tags.create'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
   </span><span class="com">/**
    * تخزين المورد الذي أنشأناه حديثًا في وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">// الحصول على البيانات من الطلب</span><span class="pln">
       $name </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">

       </span><span class="com">// إنشاء نسخة جديدة من المنشور‫ Post ووضع البيانات المطلوبة في العمود المقابل</span><span class="pln">
       $tag </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">();</span><span class="pln">
       $tag</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> $name</span><span class="pun">;</span><span class="pln">

       </span><span class="com">// حفظ البيانات</span><span class="pln">
       $tag</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'tags.index'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عرض المورد المُحدَّد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> show</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $tag </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
       $posts </span><span class="pun">=</span><span class="pln"> $tag</span><span class="pun">-&gt;</span><span class="pln">posts</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'tags.show'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'tag'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tag</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'posts'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $posts
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عرض الاستمارة الخاصة بتعديل المورد المُحدَّد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> edit</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $tag </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'tags.edit'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'tag'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $tag
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * تحديث المورد المُحدَّد في وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> update</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">// الحصول على البيانات من الطلب</span><span class="pln">
       $name </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">

       </span><span class="com">// البحث عن الوسم المطلوب ووضع البيانات المطلوبة في العمود المقابل</span><span class="pln">
       $tag </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
       $tag</span><span class="pun">-&gt;</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> $name</span><span class="pun">;</span><span class="pln">

       </span><span class="com">// حفظ البيانات</span><span class="pln">
       $tag</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'tags.index'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * إزالة المورد المُحدَّد من وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> destroy</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $tag </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Tag</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">

       $tag</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'tags.index'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تذكّر أنه يمكنك التحقق من اسم الوِجهات باستخدام الأمر التالي:
</p>

<pre class="ipsCode">sail artisan route:list
</pre>

<h3 id="post">
	متحكم المنشور Post
</h3>

<p>
	يُعَد متحكم المنشور <code>PostController</code> أكثر تعقيدًا بعض الشيء، إذ يجب عليك التعامل مع عمليات رفع الصور والعلاقات بين الجداول في قاعدة البيانات في التابع <code>store()‎</code>. إذًا لننشئ هذا المتحكم <code>app/Http/Controllers/PostController.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_35" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Category</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Tag</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Auth</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Builder</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

   </span><span class="com">/**
    * تخزين المورد الذي أنشأناه حديثًا في وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">// الحصول على البيانات من الطلب</span><span class="pln">
       $title </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">);</span><span class="pln">
       $content </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">);</span><span class="pln">

       </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'is_published'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">'on'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           $is_published </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
       </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           $is_published </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
       </span><span class="pun">}</span><span class="pln">

       </span><span class="com">// ‫إنشاء نسخة جديدة من المنشور Post ووضع البيانات المطلوبة في العمود المقابل</span><span class="pln">
       $post </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">();</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">title </span><span class="pun">=</span><span class="pln"> $title</span><span class="pun">;</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">content </span><span class="pun">=</span><span class="pln"> $content</span><span class="pun">;</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">is_published </span><span class="pun">=</span><span class="pln"> $is_published</span><span class="pun">;</span><span class="pln">

       </span><span class="com">// حفظ صورة الغلاف</span><span class="pln">
       $path </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">file</span><span class="pun">(</span><span class="str">'cover'</span><span class="pun">)-&gt;</span><span class="pln">store</span><span class="pun">(</span><span class="str">'cover'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'public'</span><span class="pun">);</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">cover </span><span class="pun">=</span><span class="pln"> $path</span><span class="pun">;</span><span class="pln">

       </span><span class="com">// ضبط المستخدم</span><span class="pln">
       $user </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Auth</span><span class="pun">::</span><span class="pln">user</span><span class="pun">();</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">user</span><span class="pun">()-&gt;</span><span class="pln">associate</span><span class="pun">(</span><span class="pln">$user</span><span class="pun">);</span><span class="pln">

       </span><span class="com">// ضبط الفئة</span><span class="pln">
       $category </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Category</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'category'</span><span class="pun">));</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">category</span><span class="pun">()-&gt;</span><span class="pln">associate</span><span class="pun">(</span><span class="pln">$category</span><span class="pun">);</span><span class="pln">

       </span><span class="com">// حفظ المنشور</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">

       </span><span class="com">// ضبط الوسوم</span><span class="pln">
       $tags </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'tags'</span><span class="pun">);</span><span class="pln">

       </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$tags </span><span class="kwd">as</span><span class="pln"> $tag</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           $post</span><span class="pun">-&gt;</span><span class="pln">tags</span><span class="pun">()-&gt;</span><span class="pln">attach</span><span class="pun">(</span><span class="pln">$tag</span><span class="pun">);</span><span class="pln">
       </span><span class="pun">}</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'posts.index'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هناك بعض الأشياء التي يجب ملاحظتها في التابع <code>store()‎</code>، حيث سنستخدم في الأسطر من 28 إلى 32 <a href="https://wiki.hsoub.com/HTML/input/checkbox" rel="external">مربع اختيار HTML</a> لتمثيل الحقل <code>is_published</code>، وتكون قيمته إما <code>'on'</code> أو <code>null</code>، ولكن تُحفَظ قيمته في قاعدة البيانات بوصفها <code>true</code> أو <code>false</code>، لذلك يجب استخدام التعليمة <code>if</code> لحل هذه المشكلة.
</p>

<p>
	يمكننا استرداد الملفات في السطور من 41 إلى 42 من خلال استخدام التابع <code>file()‎</code> بدلًا من التابع <code>input()‎</code>، ويُحفظ الملف في القرص <code>public</code> ضمن المجلد <code>cover</code>.
</p>

<p>
	نحصل في السطور من 45 إلى 46 على المستخدم الحالي باستخدام التابع <code>Auth::user()‎</code>، ونربط المنشور بالمستخدم باستخدام التابع <code>associate()‎</code>، وتفعَل السطور من 49 إلى 50 الشيء نفسه بالنسبة للفئة، وتذكّر أنه يمكنك تطبيق ذلك فقط مع المتغير <code>‎$post</code> وليس <code>‎$user</code> أو <code>‎$category</code>، لأن العمودان <code>user_id</code> و <code>category_id</code> موجودان في الجدول <code>posts</code>.
</p>

<p>
	وأخيرًا، يجب حفظ المنشور الحالي في قاعدة البيانات، ثم استرداد قائمة الوسوم وإرفاق كل منها بالمنشور واحدًا تلوَ الآخر باستخدام التابع <code>attach()‎</code> بالنسبة للوسوم كما هو موضح في السطور من 56 إلى 60.
</p>

<p>
	تجري الأمور بطريقة مشابهة بالنسبة إلى التابع <code>update()‎</code>، باستثناء أنه يجب إزالة جميع الوسوم الموجودة قبل أن تتمكّن من إرفاق الوسوم الجديدة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4578_25" style=""><span class="pln">$post</span><span class="pun">-&gt;</span><span class="pln">tags</span><span class="pun">()-&gt;</span><span class="pln">detach</span><span class="pun">();</span></pre>

<h2 id="views">
	العروض Views
</h2>

<p>
	تذكر دائمًا أن تكون منظّمًا عند إنشاء نظام عرض، حيث سنتّبع البنية التالية في مثالنا:
</p>

<pre class="ipsCode">resources/views
├── auth
├── categories
│   ├── create.blade.php
│   ├── edit.blade.php
│   ├── index.blade.php
│   └── show.blade.php
├── components
├── layouts
├── posts
│   ├── create.blade.php
│   ├── edit.blade.php
│   ├── index.blade.php
│   └── show.blade.php
├── profile
├── tags
│   ├── create.blade.php
│   ├── edit.blade.php
│   ├── index.blade.php
│   └── show.blade.php
├── dashboard.blade.php
└── welcome.blade.php
</pre>

<p>
	أنشأنا ثلاثة مجلدات هي: <code>posts</code> و <code>categories</code> و <code>tags</code>، ولكل منها أربعة قوالب هي: <code>create</code> و <code>edit</code> و <code>index</code> و <code>show</code> باستثناء المجلد <code>posts</code>، لأن وجود صفحة <code>show</code> للمنشورات في لوحة التحكم أمر غير ضروري.
</p>

<p>
	يؤدي تضمين جميع هذه العروض في مقال واحد إلى جعل هذا المقال طويلًا بلا داعٍ، لذا سنوضّح فقط صفحات إنشاء وتعديل وفهرس المنشورات، ولكن يمكنك الاطلاع على الشيفرة المصدرية الكاملة على <a href="https://github.com/ericsdevblog/laravel-beginner" rel="external nofollow">Github</a>.
</p>

<h3 id="-4">
	عرض إنشاء منشور
</h3>

<p>
	لننشئ أولًا عرض إنشاء المنشور <code>resources/views/posts/create.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_40" style=""><span class="tag">&lt;x-app-layout&gt;</span><span class="pln">
 </span><span class="tag">&lt;x-slot</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"header"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"flex justify-between"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;h2</span><span class="pln">
       </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight"</span><span class="pln">
     </span><span class="tag">&gt;</span><span class="pln">
       {{ __('Posts') }}
     </span><span class="tag">&lt;/h2&gt;</span><span class="pln">
     </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('posts.create') }}"</span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;x-primary-button&gt;</span><span class="pln">{{ __('New') }}</span><span class="tag">&lt;/x-primary-button&gt;</span><span class="pln">
     </span><span class="tag">&lt;/a&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">

   </span><span class="tag">&lt;script</span><span class="pln">
     </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://cdn.tiny.cloud/. . ./tinymce.min.js"</span><span class="pln">
     </span><span class="atn">referrerpolicy</span><span class="pun">=</span><span class="atv">"origin"</span><span class="pln">
   </span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
 </span><span class="tag">&lt;/x-slot&gt;</span><span class="pln">

 </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"py-12"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"max-w-7xl mx-auto sm:px-6 lg:px-8"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg"</span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">""</span><span class="tag">&gt;</span><span class="pln">
         </span><span class="tag">&lt;form</span><span class="pln">
           </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"{{ route('posts.store') }}"</span><span class="pln">
           </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"POST"</span><span class="pln">
           </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"mt-6 space-y-3"</span><span class="pln">
           </span><span class="atn">enctype</span><span class="pun">=</span><span class="atv">"multipart/form-data"</span><span class="pln">
         </span><span class="tag">&gt;</span><span class="pln">
           {{ csrf_field() }}
           </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"checkbox"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"is_published"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"is_published"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"is_published"</span><span class="pln">
             </span><span class="tag">&gt;</span><span class="pln">Make this post public</span><span class="tag">&lt;/x-input-label</span><span class="pln">
           </span><span class="tag">&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"title"</span><span class="tag">&gt;</span><span class="pln">{{ __('Title') }}</span><span class="tag">&lt;/x-input-label&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-text-input</span><span class="pln">
             </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"title"</span><span class="pln">
             </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"title"</span><span class="pln">
             </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text"</span><span class="pln">
             </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"mt-1 block w-full"</span><span class="pln">
             </span><span class="atn">required</span><span class="pln">
             </span><span class="atn">autofocus</span><span class="pln">
             </span><span class="atn">autocomplete</span><span class="pun">=</span><span class="atv">"name"</span><span class="pln">
           </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"content"</span><span class="tag">&gt;</span><span class="pln">{{ __('Content') }}</span><span class="tag">&lt;/x-input-label&gt;</span><span class="pln">
           </span><span class="tag">&lt;textarea</span><span class="pln">
             </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"content"</span><span class="pln">
             </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"content"</span><span class="pln">
             </span><span class="atn">cols</span><span class="pun">=</span><span class="atv">"30"</span><span class="pln">
             </span><span class="atn">rows</span><span class="pun">=</span><span class="atv">"30"</span><span class="pln">
           </span><span class="tag">&gt;&lt;/textarea&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"cover"</span><span class="tag">&gt;</span><span class="pln">{{ __('Cover Image') }}</span><span class="tag">&lt;/x-input-label&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-text-input</span><span class="pln">
             </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"cover"</span><span class="pln">
             </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"cover"</span><span class="pln">
             </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"file"</span><span class="pln">
             </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"mt-1 block w-full"</span><span class="pln">
             </span><span class="atn">required</span><span class="pln">
             </span><span class="atn">autofocus</span><span class="pln">
             </span><span class="atn">autocomplete</span><span class="pun">=</span><span class="atv">"cover"</span><span class="pln">
           </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"category"</span><span class="tag">&gt;</span><span class="pln">{{ __('Category') }}</span><span class="tag">&lt;/x-input-label&gt;</span><span class="pln">
           </span><span class="tag">&lt;select</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"category"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"category"</span><span class="tag">&gt;</span><span class="pln">
             @foreach($categories as $category)
             </span><span class="tag">&lt;option</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"{{ $category-&gt;</span><span class="pln">id }}"&gt;{{ $category-&gt;name }}</span><span class="tag">&lt;/option&gt;</span><span class="pln">
             @endforeach
           </span><span class="tag">&lt;/select&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"tags"</span><span class="tag">&gt;</span><span class="pln">{{ __('Tags') }}</span><span class="tag">&lt;/x-input-label&gt;</span><span class="pln">
           </span><span class="tag">&lt;select</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"tags"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"tags[]"</span><span class="pln"> </span><span class="atn">multiple</span><span class="tag">&gt;</span><span class="pln">
             @foreach($tags as $tag)
             </span><span class="tag">&lt;option</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"{{ $tag-&gt;</span><span class="pln">id }}"&gt;{{ $tag-&gt;name }}</span><span class="tag">&lt;/option&gt;</span><span class="pln">
             @endforeach
           </span><span class="tag">&lt;/select&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-primary-button&gt;</span><span class="pln">{{ __('Save') }}</span><span class="tag">&lt;/x-primary-button&gt;</span><span class="pln">
         </span><span class="tag">&lt;/form&gt;</span><span class="pln">
         </span><span class="tag">&lt;script&gt;</span><span class="pln">
           tinymce</span><span class="pun">.</span><span class="pln">init</span><span class="pun">({.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.});</span><span class="pln">
         </span><span class="tag">&lt;/script&gt;</span><span class="pln">
       </span><span class="tag">&lt;/div&gt;</span><span class="pln">
     </span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/x-app-layout&gt;</span></pre>

<p>
	استخدمنا في مثالنا محرّر النصوص <a href="https://www.tiny.cloud/" rel="external nofollow">TinyMCE</a>، ولكن يمكنك استخدام محرّر نصوص آخر عوضًا عنه، أو استخدم<br>
	العنصر <code><a href="https://wiki.hsoub.com/HTML/textarea" rel="external">&lt;textarea&gt;&lt;/textarea&gt;</a></code> إذا أدرتَ ذلك.
</p>

<p>
	يجب أن تحتوي الاستمارة الموجودة في السطر 24 على السمة التي هي <code>enctype="multipart/form-data"‎</code> لأننا لا ننقل النصوص فحسب، بل توجد ملفات أيضًا. تذكر في السطر 59 استخدام السمة <code>type="file"‎</code> لأننا نرفع صورة، وستُنقَل قيمة الخيار في السطور من 67 إلى 71 إلى الواجهة الخلفية.
</p>

<p>
	هناك شيئان يجب الانتباه إليهما في الأسطر من 74 إلى 78، فلاحظ أولًا السمة <code>name="tags[]"‎</code>، حيث تخبر هذه الأقواس <code>[]</code> لارافيل بنقل مصفوفة قابلة للتكرار بدلًا من النصوص. ثانيًا، تنشئ السمة <code>multiple</code> استمارة متعددة التحديد بدلًا من تحديد فردي مثل استمارة الفئات.
</p>

<h3 id="-5">
	عرض تعديل المنشور
</h3>

<p>
	لننشئ الآن العرض <code>resources/views/posts/edit.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_42" style=""><span class="tag">&lt;x-app-layout&gt;</span><span class="pln">
 </span><span class="tag">&lt;x-slot</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"header"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"flex justify-between"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;h2</span><span class="pln">
       </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight"</span><span class="pln">
     </span><span class="tag">&gt;</span><span class="pln">
       {{ __('Posts') }}
     </span><span class="tag">&lt;/h2&gt;</span><span class="pln">
     </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('posts.create') }}"</span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;x-primary-button&gt;</span><span class="pln">{{ __('New') }}</span><span class="tag">&lt;/x-primary-button&gt;</span><span class="pln">
     </span><span class="tag">&lt;/a&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">

   </span><span class="tag">&lt;script</span><span class="pln">
     </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://cdn.tiny.cloud/. . ./tinymce.min.js"</span><span class="pln">
     </span><span class="atn">referrerpolicy</span><span class="pun">=</span><span class="atv">"origin"</span><span class="pln">
   </span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
 </span><span class="tag">&lt;/x-slot&gt;</span><span class="pln">

 </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"py-12"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"max-w-7xl mx-auto sm:px-6 lg:px-8"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"p-4 sm:p-8 bg-white dark:bg-gray-800 shadow sm:rounded-lg"</span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">""</span><span class="tag">&gt;</span><span class="pln">
         </span><span class="tag">&lt;form</span><span class="pln">
           </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"{{ route('posts.update', ['post' =&gt;</span><span class="pln"> $post-&gt;id]) }}"
           method="POST"
           class="mt-6 space-y-3"
           enctype="multipart/form-data"
         &gt;
           {{ csrf_field() }} {{ method_field('PUT') }}
           </span><span class="tag">&lt;input</span><span class="pln">
             </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"checkbox"</span><span class="pln">
             </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"is_published"</span><span class="pln">
             </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"is_published"</span><span class="pln">
             @</span><span class="atn">checked</span><span class="pln">($</span><span class="atn">post</span><span class="pln">-
           </span><span class="tag">/&gt;</span><span class="pln">is_published)/&gt;
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"is_published"</span><span class="pln">
             </span><span class="tag">&gt;</span><span class="pln">Make this post public</span><span class="tag">&lt;/x-input-label</span><span class="pln">
           </span><span class="tag">&gt;</span><span class="pln">

           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"title"</span><span class="tag">&gt;</span><span class="pln">{{ __('Title') }}</span><span class="tag">&lt;/x-input-label&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-text-input</span><span class="pln">
             </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"title"</span><span class="pln">
             </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"title"</span><span class="pln">
             </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text"</span><span class="pln">
             </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"mt-1 block w-full"</span><span class="pln">
             </span><span class="atn">required</span><span class="pln">
             </span><span class="atn">autofocus</span><span class="pln">
             </span><span class="atn">autocomplete</span><span class="pun">=</span><span class="atv">"name"</span><span class="pln">
             </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"{{ $post-&gt;</span><span class="pln">title }}"
           /&gt;
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"content"</span><span class="tag">&gt;</span><span class="pln">{{ __('Content') }}</span><span class="tag">&lt;/x-input-label&gt;</span><span class="pln">
           </span><span class="tag">&lt;textarea</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"content"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"content"</span><span class="pln"> </span><span class="atn">cols</span><span class="pun">=</span><span class="atv">"30"</span><span class="pln"> </span><span class="atn">rows</span><span class="pun">=</span><span class="atv">"30"</span><span class="tag">&gt;</span><span class="pln">
{{ $post-&gt;content }}</span><span class="tag">&lt;/textarea</span><span class="pln">
           </span><span class="tag">&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"cover"</span><span class="pln">
             </span><span class="tag">&gt;</span><span class="pln">{{ __('Update Cover Image') }}</span><span class="tag">&lt;/x-input-label</span><span class="pln">
           </span><span class="tag">&gt;</span><span class="pln">
           </span><span class="tag">&lt;img</span><span class="pln">
             </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"{{ Illuminate\Support\Facades\Storage::url($post-&gt;</span><span class="pln">cover) }}"
             alt="cover image"
             width="200"
           /&gt;
           </span><span class="tag">&lt;x-text-input</span><span class="pln">
             </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"cover"</span><span class="pln">
             </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"cover"</span><span class="pln">
             </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"file"</span><span class="pln">
             </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"mt-1 block w-full"</span><span class="pln">
             </span><span class="atn">autofocus</span><span class="pln">
             </span><span class="atn">autocomplete</span><span class="pun">=</span><span class="atv">"cover"</span><span class="pln">
           </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">

           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"category"</span><span class="tag">&gt;</span><span class="pln">{{ __('Category') }}</span><span class="tag">&lt;/x-input-label&gt;</span><span class="pln">
           </span><span class="tag">&lt;select</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"category"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"category"</span><span class="tag">&gt;</span><span class="pln">
             @foreach($categories as $category)
             </span><span class="tag">&lt;option</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"{{ $category-&gt;</span><span class="pln">id }}" @selected($post-&gt;
               category-&gt;id == $category-&gt;id)&gt;{{ $category-&gt;name }}
             </span><span class="tag">&lt;/option&gt;</span><span class="pln">
             @endforeach
           </span><span class="tag">&lt;/select&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-input-label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"tags"</span><span class="tag">&gt;</span><span class="pln">{{ __('Tags') }}</span><span class="tag">&lt;/x-input-label&gt;</span><span class="pln">
           </span><span class="tag">&lt;select</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"tags"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"tags[]"</span><span class="pln"> </span><span class="atn">multiple</span><span class="tag">&gt;</span><span class="pln">
             @foreach($tags as $tag)
             </span><span class="tag">&lt;option</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"{{ $tag-&gt;</span><span class="pln">id }}" @selected($post-&gt;
               tags-&gt;contains($tag))&gt;{{ $tag-&gt;name }}
             </span><span class="tag">&lt;/option&gt;</span><span class="pln">
             @endforeach
           </span><span class="tag">&lt;/select&gt;</span><span class="pln">
           </span><span class="tag">&lt;br</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
           </span><span class="tag">&lt;x-primary-button&gt;</span><span class="pln">{{ __('Save') }}</span><span class="tag">&lt;/x-primary-button&gt;</span><span class="pln">
         </span><span class="tag">&lt;/form&gt;</span><span class="pln">
         </span><span class="tag">&lt;script&gt;</span><span class="pln">
           tinymce</span><span class="pun">.</span><span class="pln">init</span><span class="pun">({.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.});</span><span class="pln">
         </span><span class="tag">&lt;/script&gt;</span><span class="pln">
       </span><span class="tag">&lt;/div&gt;</span><span class="pln">
     </span><span class="tag">&lt;/div&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/x-app-layout&gt;</span></pre>

<p>
	لاحظ في السطور من 24 إلى 26 أن لغة HTML لا تدعم التابع <code>PUT</code> افتراضيًا، لذا نستخدم السمة <code>method="POST"‎</code> ثم نخبر لارافيل باستخدام التابع <code>PUT</code> من خلال التعليمة ‎<code>{{ method_field('PUT') }}</code>‎.
</p>

<h3 id="-6">
	عرض فهرس المنشورات
</h3>

<p>
	لننشئ الآن العرض <code>resources/views/posts/index.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2354_44" style=""><span class="tag">&lt;x-app-layout&gt;</span><span class="pln">
 </span><span class="tag">&lt;x-slot</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"header"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"flex justify-between"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;h2</span><span class="pln">
       </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight"</span><span class="pln">
     </span><span class="tag">&gt;</span><span class="pln">
       {{ __('Posts') }}
     </span><span class="tag">&lt;/h2&gt;</span><span class="pln">
     </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('posts.create') }}"</span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;x-primary-button&gt;</span><span class="pln">{{ __('New') }}</span><span class="tag">&lt;/x-primary-button&gt;</span><span class="pln">
     </span><span class="tag">&lt;/a&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/x-slot&gt;</span><span class="pln">

 </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"py-12"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"max-w-7xl mx-auto sm:px-6 lg:px-8"</span><span class="tag">&gt;</span><span class="pln">
     @foreach($posts as $post)
     </span><span class="tag">&lt;div</span><span class="pln">
       </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg mb-4 px-4 h-20 flex justify-between items-center"</span><span class="pln">
     </span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"text-gray-900 dark:text-gray-100"</span><span class="tag">&gt;</span><span class="pln">
         </span><span class="tag">&lt;p&gt;</span><span class="pln">{{ $post-&gt;title }}</span><span class="tag">&lt;/p&gt;</span><span class="pln">
       </span><span class="tag">&lt;/div&gt;</span><span class="pln">
       </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"space-x-2"</span><span class="tag">&gt;</span><span class="pln">
         </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('posts.edit', ['post' =&gt;</span><span class="pln"> $post-&gt;id]) }}"&gt;
           </span><span class="tag">&lt;x-primary-button&gt;</span><span class="pln">{{ __('Edit') }}</span><span class="tag">&lt;/x-primary-button&gt;&lt;/a</span><span class="pln">
         </span><span class="tag">&gt;</span><span class="pln">

         </span><span class="tag">&lt;form</span><span class="pln">
           </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"post"</span><span class="pln">
           </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"{{ route('posts.destroy', ['post' =&gt;</span><span class="pln"> $post-&gt;id]) }}"
           class="inline"
         &gt;
           {{ csrf_field() }} {{ method_field('DELETE') }}
           </span><span class="tag">&lt;x-danger-button&gt;</span><span class="pln"> {{ __('Delete') }} </span><span class="tag">&lt;/x-danger-button&gt;</span><span class="pln">
         </span><span class="tag">&lt;/form&gt;</span><span class="pln">
       </span><span class="tag">&lt;/div&gt;</span><span class="pln">
     </span><span class="tag">&lt;/div&gt;</span><span class="pln">
     @endforeach
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/div&gt;</span><span class="pln">
</span><span class="tag">&lt;/x-app-layout&gt;</span></pre>

<p>
	لاحظ أن زر الحذف ليس زرًا عاديًا، إذ يجب أن يكون استمارة مع تابع <code>DELETE</code>، لأن الرابط العادي يمتلك التابع <code>GET</code> فقط.
</p>

<p>
	يُفترَض الآن أن تكون قادرًا على إنشاء بقية نظام العرض بسهولة.
</p>

<h3 id="-7">
	لقطات الشاشة
</h3>

<p>
	وأخيرًا، إليك بعض لقطات الشاشة للوحة التحكم التي أنشأناها:
</p>

<p>
	<strong>صفحة إدارة التصنيفات</strong>:
</p>

<p>
	ننتقل لصفحة الإدارة كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159701" href="https://academy.hsoub.com/uploads/monthly_2024_10/02_home.png.15ac76f239eecab17069e47ed531f133.png" rel=""><img alt="02 home" class="ipsImage ipsImage_thumbnailed" data-fileid="159701" data-unique="j8leav716" style="width: 400px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2024_10/02_home.thumb.png.889def374be422c302ca3b4d1b2c49c6.png"> </a>
</p>

<p>
	ثم نختار التصنيفات Categories من الصورة أعلاه لننتقل للصفحة التالية لإدارة التصنيفات:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159702" href="https://academy.hsoub.com/uploads/monthly_2024_10/03_category-list.png.bc3594258599b383d2548176bdbbcc7a.png" rel=""><img alt="03 category list" class="ipsImage ipsImage_thumbnailed" data-fileid="159702" data-unique="wfuh0tlew" style="width: 400px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2024_10/03_category-list.thumb.png.2b89119db92d75362115ce098c47dd45.png"> </a>
</p>

<p>
	<strong>صفحة إنشاء تصنيف جديد</strong>:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159703" href="https://academy.hsoub.com/uploads/monthly_2024_10/04_create-category.png.50f2e82236a054ed1af947be01470087.png" rel=""><img alt="04 create category" class="ipsImage ipsImage_thumbnailed" data-fileid="159703" data-unique="q7l6spodb" style="width: 400px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2024_10/04_create-category.thumb.png.5c04966c54755c9bbc398b60b4ae5690.png"> </a>
</p>

<p>
	<strong>صفحة تحديث المنشور</strong>:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159704" href="https://academy.hsoub.com/uploads/monthly_2024_10/05_update-post.png.7d220071bdf3f8fce805af302a0e4c55.png" rel=""><img alt="05 update post" class="ipsImage ipsImage_thumbnailed" data-fileid="159704" data-unique="k3p61stkr" style="width: 311px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2024_10/05_update-post.thumb.png.5ba24d90500cfbb3354aa22aecba3454.png"> </a>
</p>

<p>
	تابع معنا <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AE%D8%A7%D9%85%D8%B3-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-%D9%84%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2442/" rel="">المقال التالي</a> والأخير من هذه السلسلة حيث سننشئ فيه كل ما يخص الواجهة الأمامية من التطبيق كي يتمكن المستخدمون من رؤية منشورات المدونة والتفاعل معها.
</p>

<p>
	ترجمة -وبتصرُّف- للمقال <a href="https://www.ericsdevblog.com/posts/laravel-for-beginners-4/" rel="external nofollow">Laravel for Beginners #4 - Create a Dashboard</a> لصاحبه Eric Hu.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%84%D8%AB-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-crud-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2427/" rel="">لارافيل للمبتدئين-الجزء الثالث: استخدام عمليات CRUD لإنشاء مدونة بسيطة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AC%D8%B1%D9%8A%D8%AF-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D8%A8%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-migration-%D9%88%D8%A7%D9%84%D8%A8%D8%B0%D8%B1-seeder-r1725/" rel="">تجريد إعداد قواعد البيانات في لارافيل باستعمال عملية التهجير Migration والبذر Seeder</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D8%B4%D8%A6-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-query-builder-%D9%84%D9%84%D8%AA%D8%AE%D8%A7%D8%B7%D8%A8-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-r398/" rel="">كيف تستخدم منشئ الاستعلامات Query builder للتخاطب مع قاعدة البيانات في Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D8%B3%D8%AA%D9%85%D8%A7%D8%B1%D8%A9-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%D9%81%D9%8A-laravel-5-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D9%8A%D8%B2%D8%A9-form-request-r128/" rel="">إنشاء استمارة اتصال في Laravel باستخدام ميزة Form Request</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2428</guid><pubDate>Wed, 30 Oct 2024 15:06:00 +0000</pubDate></item><item><title>&#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; &#x644;&#x644;&#x645;&#x628;&#x62A;&#x62F;&#x626;&#x64A;&#x646;-&#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62B;&#x627;&#x644;&#x62B;: &#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x639;&#x645;&#x644;&#x64A;&#x627;&#x62A; CRUD &#x644;&#x625;&#x646;&#x634;&#x627;&#x621; &#x645;&#x62F;&#x648;&#x646;&#x629; &#x628;&#x633;&#x64A;&#x637;&#x629;</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%84%D8%AB-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-crud-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2427/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2024_10/--------CRUD---.png.557827fd76222fa1a1cdcb90c1bb65c0.png" /></p>
<p>
	سنستخدم في هذا المقال كل ما تعلّمناه في المقالين السابقين من سلسلة مقالات <a href="https://academy.hsoub.com/tags/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84%20%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86/" rel="">لارافيل للمبتدئين</a> لإنشاء مشروع حقيقي، حيث سننشئ مدونة صغيرة تحتوي على منشورات فقط بدون فئات Categories أو وسوم Tags، وكل منشور له عنوان ومحتوى، إذ لن ننشئ تطبيق مدونة كامل المواصفات، وسنوضّح كيفية استرداد البيانات من قاعدة البيانات، وكيفية إنشاء أو تحديث معلومات جديدة، وكيفية حفظها في قاعدة البيانات، وكيفية حذفها، حيث يمثّل الاختصار CRUD عمليات الإنشاء ‎<strong>C</strong>reate والقراءة ‎<strong>R</strong>ead والتحديث ‎<strong>U</strong>pdate والحذف ‎<strong>D</strong>elete.
</p>

<h2 id="">
	تصميم بنية قاعدة البيانات
</h2>

<p>
	سننشئ أولًا ملف تهجير Migration للجدول <code>post</code>، ويجب أن يحتوي هذا الجدول على العنوان والمحتوى، ويمكنك توليد ملف تهجير باستخدام الأمر التالي:
</p>

<pre class="ipsCode">php artisan make:migration create_posts_table
</pre>

<p>
	وسيتضمن الملف ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_7" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Migrations\Migration</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Schema\Blueprint</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Schema</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Migration</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * تشغيل عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">);</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">text</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">);</span><span class="pln">
       </span><span class="pun">});</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عكس عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> down</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	أنشأنا في هذا المثال خمسة أعمدة في الجدول <code>post</code> باستدعاء 5 توابع وهي:
</p>

<ul>
	<li>
		ينشئ التابع <code>id()‎</code> عمود المعرّف <code>id</code> الذي يُستخدَم عادة للفهرسة.
	</li>
	<li>
		ينشئ التابع <code>timestamps()‎</code> عمودين هما: <code>created_at</code> و <code>uptated_at</code>، وسيُحدَّث هذان العمودان تلقائيًا عند إنشاء السجل وتحديثه.
	</li>
	<li>
		ينشئ التابع <code>string('title')‎</code> العمود <code>title</code> الذي نوعه <code>VARCHAR</code> ويبلغ طوله الافتراضي 255 بايتًا.
	</li>
	<li>
		ينشئ التابع <code>string('content')‎</code> عمود المحتوى <code>content</code>.
	</li>
</ul>

<p>
	يمكنك تطبيق التغييرات من خلال تشغيل الأمر التالي:
</p>

<pre class="ipsCode">php artisan migrate
</pre>

<p>
	ويجب أن ينشأ جدول <code>posts</code> جديد كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159696" href="https://academy.hsoub.com/uploads/monthly_2024_10/01_database.png.d2e75c43fb4720cac22b7526ab108158.png" rel=""><img alt="01 database" class="ipsImage ipsImage_thumbnailed" data-fileid="159696" data-unique="kgljc4mp9" src="https://academy.hsoub.com/uploads/monthly_2024_10/01_database.thumb.png.21e7c8cf2d3e9e7f81252ebc7fabb8a0.png"> </a>
</p>

<p>
	يمكننا الآن إنشاء النموذج Model المقابل لهذا الجدول باستخدام الأمر التالي:
</p>

<pre class="ipsCode">php artisan make:model Post
</pre>

<p>
	وسيتضمّن هذا النموذج <code>app/Models/Post.php</code> ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_9" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Factories\HasFactory</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Post</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">HasFactory</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لننشئ الآن متحكم الموارد Resource Controller المقابل باستخدام الأمر التالي:
</p>

<pre class="ipsCode">php artisan make:controller PostController --resource
</pre>

<p>
	وأخيرًا، سجّل هذا المتحكم في الموجِّه Router كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_13" style=""><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\PostController</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">resource</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">PostController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span></pre>

<p>
	يمكنك التحقق من الوِجهات Routes المُسجَّلة من خلال تشغيل الأمر التالي:
</p>

<pre class="ipsCode">php artisan route:list
</pre>

<p>
	وسيظهر الخرج التالي:
</p>

<pre class="ipsCode">GET|HEAD        posts ................................................................. posts.index › PostController@index
POST            posts ................................................................. posts.store › PostController@store
GET|HEAD        posts/create ........................................................ posts.create › PostController@create
GET|HEAD        posts/{post} ............................................................ posts.show › PostController@show
PUT|PATCH       posts/{post} ........................................................ posts.update › PostController@update
DELETE          posts/{post} ...................................................... posts.destroy › PostController@destroy
GET|HEAD        posts/{post}/edit ....................................................... posts.edit › PostController@edit
</pre>

<p>
	يحتوي الخرج السابق على معلومات مثل توابع الطلبات Request Methods وتوابع المتحكّمات Controller Methods بالإضافة إلى أسماء الوِجهات، وتُعَد هذه المعلومات مهمة جدًا وسنحتاج إليها لاحقًا في هذا المقال.
</p>

<h2 id="crud-1">
	عمليات CRUD
</h2>

<p>
	حان الوقت الآن لنتعمّق في التطبيق نفسه، فمن غير المحتمل أن ننشئ جميع المتحكمات أولًا ثم نصمّم القوالب ثم ننتقل إلى الموجّهات عند إنشاء تطبيقات واقعية، إذ يجب أن نفكّر من وجهة نظر المستخدم وفي الإجراءات التي قد يرغب المستخدم في اتخاذها. يجب أن يكون لدى المستخدم القدرة على إجراء أربع عمليات لكل مورد، والذي هو <code>Post</code> في حالتنا، وهذه العمليات هي:
</p>

<ul>
	<li>
		<strong>الإنشاء Create</strong>: يجب أن يكون المستخدم قادرًا على إنشاء موارد جديدة وحفظها في قاعدة البيانات.
	</li>
	<li>
		<strong>القراءة Read</strong>: يجب أن يكون المستخدم قادرًا على قراءة الموارد سواءً من خلال استرداد قائمة الموارد أو التحقق من تفاصيل مورد محدّد.
	</li>
	<li>
		<strong>التحديث Update</strong>: يجب أن يكون المستخدم قادرًا على تحديث الموارد الموجودة وتحديث سجل قاعدة البيانات المقابلة لها.
	</li>
	<li>
		<strong>الحذف Delete</strong>: يجب أن يكون المستخدم قادرًا على إزالة مورد من قاعدة البيانات.
	</li>
</ul>

<p>
	ويشار إلى هذه العمليات مع بعضها البعض باسم عمليات CRUD.
</p>

<h2 id="create">
	إجراء الإنشاء Create
</h2>

<p>
	لا تزال قاعدة بياناتنا فارغة حاليًا، لذا قد يرغب المستخدم في إنشاء منشورات جديدة، فلنبدأ بإجراء الإنشاء (C)، حيث يمكن إكمال هذا الإجراء من خلال استخدام التابعين التاليين:
</p>

<ul>
	<li>
		تابع المتحكم <code>create()‎</code> الذي يعرض استمارة، مما يسمح للمستخدم بملء العنوان والمحتوى.
	</li>
	<li>
		تابع المتحكم <code>store()‎</code> الذي يحفظ المنشور الذي أنشأناه حديثًا في قاعدة البيانات، ويعيد توجيه المستخدم إلى صفحة القائمة.
	</li>
</ul>

<p>
	يطابق التابع <code>create()‎</code> نمط URL الذي هو <code>‎/posts/create</code> (التابع <code>GET</code>)، ويطابق التابع <code>store()‎</code> نمط URL الذي هو <code>‎/post</code> (التابع <code>POST</code>).
</p>

<p>
	إليك مراجعةً مختصرة لتوابع HTTP في حال احتياجك إلى تجديد بعض المعلومات:
</p>

<ul>
	<li>
		تابع <code>GET</code> هو تابع <a href="https://wiki.hsoub.com/Laravel/requests" rel="external" target="_blank">طلبات HTTP</a> الأكثر استخدامًا، ويُستخدَم لطلب البيانات والموارد من الخادم.
	</li>
	<li>
		يُستخدَم تابع <code>POST</code> لإرسال البيانات إلى الخادم، ويُستخدَم لإنشاء أو تحديث المورد.
	</li>
	<li>
		يعمل تابع <code>HEAD</code> مثل تابع <code>GET</code> تمامًا، باستثناء أن استجابة HTTP ستحتوي على الترويسة فقط بدون الجسم، ويستخدم المطورون هذا التابع لأغراض تنقيح الأخطاء Debugging.
	</li>
	<li>
		يُعَد تابع <code>PUT</code> مشابهًا لتابع <code>POST</code>، مع اختلاف واحد بسيط، حيث إذا أرسلتَ باستخدام التابع <code>POST</code> موردًا موجودًا مسبقًا على الخادم، فلن يسبّب هذا الإجراء أيّ فرق، ولكن سيكرّر تابع <code>PUT</code> هذا المورد في كل مرة نقدّم فيها الطلب.
	</li>
	<li>
		يزيل تابع <code>DELETE</code> موردًا من الخادم.
	</li>
</ul>

<p>
	لنبدأ بالتابع <code>create()‎</code>، حيث سيتضمّن ملف المتحكم <code>app/Http/Controllers/PostController.php</code> ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_16" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

   </span><span class="com">/**
    *  عرض الاستمارة الخاصة بإنشاء مورد جديد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> create</span><span class="pun">():</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'posts.create'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيُنفّذ هذا التابع عندما ترسل طلب <code>GET</code> إلى <code>‎/posts/create</code>، وسيؤشّر إلى العرض <code>views/posts/create.blade.php</code>. لاحظ تغيير الاستجابة <code>Response</code> إلى عرض <code>View</code> في السطر 16، لأن هذه التوابع يجب أن تعيد عرضًا.
</p>

<p>
	يجب بعد ذلك أن ننشئ العرض المقابل، حيث سنبدأ بعرض تخطيط الصفحة <code>layout</code>، إذ سيتضمّن الملف <code>views/layout.blade.php</code> ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_18" style=""><span class="dec">&lt;!doctype html&gt;</span><span class="pln">
</span><span class="tag">&lt;html</span><span class="pln"> </span><span class="atn">lang</span><span class="pun">=</span><span class="atv">"en"</span><span class="tag">&gt;</span><span class="pln">
 </span><span class="tag">&lt;head&gt;</span><span class="pln">
   </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"UTF-8"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
   </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">http-equiv</span><span class="pun">=</span><span class="atv">"X-UA-Compatible"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"IE=edge"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
   </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"viewport"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"width=device-width, initial-scale=1.0"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
   </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"https://cdn.tailwindcss.com"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
   @yield('title')
 </span><span class="tag">&lt;/head&gt;</span><span class="pln">

 </span><span class="tag">&lt;body</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container mx-auto font-serif"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-white text-black font-serif"</span><span class="tag">&gt;</span><span class="pln">
     </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"nav"</span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;nav</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"flex flex-row justify-between h-16 items-center shadow-md"</span><span class="tag">&gt;</span><span class="pln">
         </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"px-5 text-2xl"</span><span class="tag">&gt;</span><span class="pln">
           </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('posts.index') }}"</span><span class="tag">&gt;</span><span class="pln"> My Blog </span><span class="tag">&lt;/a&gt;</span><span class="pln">
         </span><span class="tag">&lt;/div&gt;</span><span class="pln">
         </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"hidden lg:flex content-between space-x-10 px-10 text-lg"</span><span class="tag">&gt;</span><span class="pln">
           </span><span class="tag">&lt;a</span><span class="pln">
             </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{ route('posts.create') }}"</span><span class="pln">
             </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"hover:underline hover:underline-offset-1"</span><span class="pln">
             </span><span class="tag">&gt;</span><span class="pln">New Post</span><span class="tag">&lt;/a</span><span class="pln">
           </span><span class="tag">&gt;</span><span class="pln">
           </span><span class="tag">&lt;a</span><span class="pln">
             </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"https://github.com/ericnanhu"</span><span class="pln">
             </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"hover:underline hover:underline-offset-1"</span><span class="pln">
             </span><span class="tag">&gt;</span><span class="pln">GitHub</span><span class="tag">&lt;/a</span><span class="pln">
           </span><span class="tag">&gt;</span><span class="pln">
         </span><span class="tag">&lt;/div&gt;</span><span class="pln">
       </span><span class="tag">&lt;/nav&gt;</span><span class="pln">
     </span><span class="tag">&lt;/div&gt;</span><span class="pln">

     @yield('content')

     </span><span class="tag">&lt;footer</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"bg-gray-700 text-white"</span><span class="tag">&gt;</span><span class="pln">
       </span><span class="tag">&lt;div</span><span class="pln">
         </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"flex justify-center items-center sm:justify-between flex-wrap lg:max-w-screen-2xl mx-auto px-4 sm:px-8 py-10"</span><span class="pln">
       </span><span class="tag">&gt;</span><span class="pln">
         </span><span class="tag">&lt;p</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"font-serif text-center mb-3 sm:mb-0"</span><span class="tag">&gt;</span><span class="pln">
           Copyright ©
           </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"https://www.ericsdevblog.com/"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"hover:underline"</span><span class="pln">
             </span><span class="tag">&gt;</span><span class="pln">Eric Hu</span><span class="tag">&lt;/a</span><span class="pln">
           </span><span class="tag">&gt;</span><span class="pln">
         </span><span class="tag">&lt;/p&gt;</span><span class="pln">

         </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"flex justify-center space-x-4"</span><span class="tag">&gt;</span><span class="pln">. . .</span><span class="tag">&lt;/div&gt;</span><span class="pln">
       </span><span class="tag">&lt;/div&gt;</span><span class="pln">
     </span><span class="tag">&lt;/footer&gt;</span><span class="pln">
   </span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	لاحظ في السطرين 16 و 20 وجود الأقواس المزدوجة المتعرجة <code>{{ }}</code> التي تسمح بتنفيذ شيفرة PHP البرمجية ضمن القالب، وبالتالي سيعيد التابع <code>route('posts.index')‎</code> الوِجهة التي اسمها <code>posts.index</code>، حيث يمكنك التحقق من أسماء الوِجهات من خلال الرجوع إلى خرج الأمر <code>php artisan route:list</code>.
</p>

<p>
	لننتقل بعد ذلك إلى العرض <code>create</code>، حيث يجب أن تكون منظمًا في هذا العرض. يُعَد العرض <code>create</code> مُخصّصًا للإجراءات المتعلقة بالمنشور، لذا أنشأنا المجلد <code>post</code> لتخزين هذا العرض. سيتضمن العرض <code>views/posts/create.blade.php</code> ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_20" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Create</span><span class="pun">&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"w-96 mx-auto my-8"</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">h2 </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"text-2xl font-semibold underline mb-4"</span><span class="pun">&gt;</span><span class="typ">Create</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> post</span><span class="pun">&lt;/</span><span class="pln">h2</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">form action</span><span class="pun">=</span><span class="str">"{{ route('posts.store') }}"</span><span class="pln"> method</span><span class="pun">=</span><span class="str">"POST"</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">{{</span><span class="pln"> csrf_field</span><span class="pun">()</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">label </span><span class="kwd">for</span><span class="pun">=</span><span class="str">"title"</span><span class="pun">&gt;</span><span class="typ">Title</span><span class="pun">:&lt;</span><span class="str">/label&gt;&lt;br /</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">input
     type</span><span class="pun">=</span><span class="str">"text"</span><span class="pln">
     id</span><span class="pun">=</span><span class="str">"title"</span><span class="pln">
     name</span><span class="pun">=</span><span class="str">"title"</span><span class="pln">
     </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"p-2 w-full bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300"</span><span class="pln">
   </span><span class="pun">/&gt;&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">label </span><span class="kwd">for</span><span class="pun">=</span><span class="str">"content"</span><span class="pun">&gt;</span><span class="typ">Content</span><span class="pun">:&lt;</span><span class="str">/label&gt;&lt;br /</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">textarea
     type</span><span class="pun">=</span><span class="str">"text"</span><span class="pln">
     id</span><span class="pun">=</span><span class="str">"content"</span><span class="pln">
     name</span><span class="pun">=</span><span class="str">"content"</span><span class="pln">
     rows</span><span class="pun">=</span><span class="str">"15"</span><span class="pln">
     </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"p-2 w-full bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300"</span><span class="pln">
   </span><span class="pun">&gt;&lt;/</span><span class="pln">textarea
   </span><span class="pun">&gt;&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">button
     type</span><span class="pun">=</span><span class="str">"submit"</span><span class="pln">
     </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"font-sans text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-md text-sm w-full px-5 py-2.5 text-center"</span><span class="pln">
   </span><span class="pun">&gt;</span><span class="pln">
     </span><span class="typ">Submit</span><span class="pln">
   </span><span class="pun">&lt;/</span><span class="pln">button</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;/</span><span class="pln">form</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	توجد بعض الأشياء التي يجب ملاحظتها عند استخدام الاستمارات لنقل البيانات، وهي:
</p>

<ul>
	<li>
		السطر 6: تحدِّد سمة Attribute الإجراء <code>action</code> ما يحدث عند إرسال هذه الاستمارة، وتوجّه المتصفح في هذه الحالة لزيارة الوِجهة <code>posts.store</code> باستخدام تابع HTTP الذي هو <code>POST</code>.
	</li>
	<li>
		السطر 7 <code>‎{{ csrf_field() }}‎</code>: يُعَد CSRF هجومًا ضارًا يستهدف تطبيقات الويب، وتوفر الدالة <code>csrf_field()‎</code> الحماية من هذا النوع من الهجمات. اطلع على مقال <a href="https://academy.hsoub.com/programming/advanced/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A3%D9%85%D8%A7%D9%86-%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r2020/" rel="">تعرف على أمان مواقع الويب</a> لمعرفة المزيد عن هجمات تزوير الطلبات عبر المواقع Cross-Site Request Forgery -أو CSRF اختصارًا.
	</li>
	<li>
		السمة <code>name</code> في السطر 12 و 20: يُربَط ما يدخله المستخدم بمتغير عند إرسال الاستمارة، وتحدّد السمة <code>name</code> اسم هذا المتغير، فمثلًا إذا كان <code>name="title"‎</code>، فسيُربَط دخل المستخدم بالمتغير <code>title</code>، ويمكن الوصول إلى قيمته باستخدام التعليمة <code>‎$request-&gt;input('title')‎</code>، حيث سنرى كيفية عملها لاحقًا.
	</li>
	<li>
		السطر 27: يجب ضبط السمة <code>type</code> على القيمة <code>submit</code> حتى تعمل هذه الاستمارة.
	</li>
</ul>

<p>
	شغّل الآن خادم التطوير وانتقل إلى العنوان <code>http://127.0.0.1:8000/posts/create</code> حيث ستظهر الصفحة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159697" href="https://academy.hsoub.com/uploads/monthly_2024_10/02_the-create-page.png.d99e623866a6e224c7057501929e183f.png" rel=""><img alt="02 the create page" class="ipsImage ipsImage_thumbnailed" data-fileid="159697" data-unique="edak5hdd2" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2024_10/02_the-create-page.thumb.png.a6f74126ca8d7b71cd33a5d3674c0957.png"> </a>
</p>

<p>
	إذا نقرتَ على زر الإرسال "Submit"، فسيرسل المتصفح طلب <code>POST</code> إلى الخادم، وسيُنفَّذ التابع <code>store()‎</code> هذه المرة، وسيحتوي طلب <code>POST</code> على دخل المستخدم، ويمكن الوصول إليه كما يلي في الملف <code>PostController.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_22" style=""><span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">
</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

   </span><span class="com">/**
    * تخزين مورد أنشأناه حديثًا في وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">// الحصول على البيانات من الطلب</span><span class="pln">
       $title </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">);</span><span class="pln">
       $content </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">);</span><span class="pln">

       </span><span class="com">// إنشاء نسخة جديدة من‫ المنشور Post ووضع البيانات المطلوبة في العمود المقابل</span><span class="pln">
       $post </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">;</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">title </span><span class="pun">=</span><span class="pln"> $title</span><span class="pun">;</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">content </span><span class="pun">=</span><span class="pln"> $content</span><span class="pun">;</span><span class="pln">

       </span><span class="com">// حفظ البيانات</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'posts.index'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيُعاد توجيهك إلى الوِجهة <code>posts.index</code> بعد تخزين البيانات. عُد إلى متصفحك واكتب عنوانًا ومحتوًى جديدًا، ثم انقر على زر الإرسال. لم ننشئ العرض <code>index</code> بعد، لذا ستُعاد رسالة خطأ، ولكن إذا تحققتَ من قاعدة البيانات، فيجب وجود سجل جديد مضاف كما يلي:
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159698" href="https://academy.hsoub.com/uploads/monthly_2024_10/03_new-record.png.d10f15430a4dc6a5c4c8d77e116b1b85.png" rel=""><img alt="03_new-record.png" class="ipsImage ipsImage_thumbnailed" data-fileid="159698" data-ratio="14.11" data-unique="sxp0iclhi" width="900" src="https://academy.hsoub.com/uploads/monthly_2024_10/03_new-record.thumb.png.a6755a4f4588270f52cc916a963fc73b.png"></a>
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="" rel=""> </a>
</p>

<h2 id="list">
	إجراء القائمة List
</h2>

<p>
	لننتقل الآن إلى عملية القراءة Read، حيث يوجد نوعان مختلفان من عمليات القراءة هما: الأول هو إجراء القائمة الذي يعيد قائمةً بجميع المنشورات إلى المستخدم، والإجراء الثاني سنوضّحه في الفقرة التالية. يقابل إجراء القائمة التابعَ <code>index()‎</code> في الملف <code>PostController.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_26" style=""><span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * عرض قائمة الموارد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">():</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'posts.index'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'posts'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $posts</span><span class="pun">,</span><span class="pln">
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويكون عرض <code>index</code> المقابل هو <code>views/post/index.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_28" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Page</span><span class="pln"> </span><span class="typ">Title</span><span class="pun">&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"max-w-screen-lg mx-auto my-8"</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="lit">@foreach</span><span class="pun">(</span><span class="pln">$posts </span><span class="kwd">as</span><span class="pln"> $post</span><span class="pun">)</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">h2 </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"text-2xl font-semibold underline mb-2"</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">a href</span><span class="pun">=</span><span class="str">"{{ route('posts.show', ['post' =&gt; $post-&gt;id]) }}"</span><span class="pln">
     </span><span class="pun">&gt;{{</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">title </span><span class="pun">}}&lt;/</span><span class="pln">a
   </span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;/</span><span class="pln">h2</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">p </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"mb-4"</span><span class="pun">&gt;{{</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Str</span><span class="pun">::</span><span class="pln">words</span><span class="pun">(</span><span class="pln">$post</span><span class="pun">-&gt;</span><span class="pln">content</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="lit">@endforeach</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	تتكرر حلقة <code>foreach</code> في السطر 5 على جميع المنشورات <code>‎$posts</code> المُسترَدة، ثم تسنِد كل قيمة إلى المتغير <code>‎$post</code>. لاحظ في السطر7 كيفية تمرير معرّف <code>id</code> المنشور إلى الوِجهة <code>posts.show</code>، ثم ستمرِّر هذه الوِجهة هذا المتغير إلى تابع المتحكم <code>show()‎</code> الذي سنراه لاحقًا. يُعَد التابع <code>Str::words()‎</code> في السطر 11 دالةً مساعدة في لغة PHP، وسيأخذ أول 100 كلمة من المحتوى <code>content</code> فقط.
</p>

<h2 id="show">
	إجراء العرض Show
</h2>

<p>
	عملية القراءة الثانية هي إجراء العرض الذي يعرض تفاصيل مورد معين، ويتحقّق هذا الإجراء باستخدام التابع <code>show()‎</code> في الملف <code>PostController.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_30" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

   </span><span class="com">/**
    * عرض المورد المُحدَّد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> show</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $post </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'posts.show'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'post'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">,</span><span class="pln">
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويكون عرض <code>show</code> المقابل هو <code>views/post/show.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_32" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="pun">{{</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">title </span><span class="pun">}}&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"max-w-screen-lg mx-auto my-8"</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">h2 </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"text-2xl font-semibold underline mb-2"</span><span class="pun">&gt;{{</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">title </span><span class="pun">}}&lt;/</span><span class="pln">h2</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">p </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"mb-4"</span><span class="pun">&gt;{{</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">content </span><span class="pun">}}&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">

 </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"grid grid-cols-2 gap-x-2"</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">a
     href</span><span class="pun">=</span><span class="str">"{{ route('posts.edit', ['post' =&gt; $post-&gt;id]) }}"</span><span class="pln">
     </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"font-sans text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-md text-sm w-full px-5 py-2.5 text-center"</span><span class="pln">
     </span><span class="pun">&gt;</span><span class="typ">Update</span><span class="pun">&lt;/</span><span class="pln">a
   </span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">form
     action</span><span class="pun">=</span><span class="str">"{{ route('posts.destroy', ['post' =&gt; $post-&gt;id]) }}"</span><span class="pln">
     method</span><span class="pun">=</span><span class="str">"POST"</span><span class="pln">
   </span><span class="pun">&gt;</span><span class="pln">
     </span><span class="pun">{{</span><span class="pln"> csrf_field</span><span class="pun">()</span><span class="pln"> </span><span class="pun">}}</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> method_field</span><span class="pun">(</span><span class="str">'DELETE'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
     </span><span class="pun">&lt;</span><span class="pln">button
       type</span><span class="pun">=</span><span class="str">"submit"</span><span class="pln">
       </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"font-sans text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-md text-sm w-full px-5 py-2.5 text-center"</span><span class="pln">
     </span><span class="pun">&gt;</span><span class="pln">
       </span><span class="typ">Delete</span><span class="pln">
     </span><span class="pun">&lt;/</span><span class="pln">button</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">&lt;/</span><span class="pln">form</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	هناك بعض الأشياء التي يجب أن نلاحظها في المثال السابق. أولًا، لاحظ كيف أن زر التحديث "Update" هو رابط بسيط، ولكن زر الحذف "Delete" هو استمارة، لأن الرابط سيخبر المتصفح بإرسال طلب <code>GET</code> إلى الخادم، بينما نحتاج شيئًا آخر لإجراء الحذف، حيث إذا نظرتَ داخل الاستمارة، فستجد أنها تحتوي على السمة <code>method="POST"‎</code>، ولكننا نحتاج التابع <code>DELETE</code> لإجراء الحذف. تدعم لغة HTML التابعين <code>GET</code> و <code>POST</code> افتراضيًا، وإذا كنت بحاجة شيء آخر، فيجب أن تضبط السمة <code>method="POST"‎</code>، وأن تستخدم التابع <code>method_field()‎</code> بدلًا من ذلك.
</p>

<h2 id="update">
	إجراء التحديث Update
</h2>

<p>
	تستخدم عملية التحديث التابع <code>edit()‎</code> الذي يعرض استمارة HTML، والتابع <code>update()‎</code> الذي يجري تغييرات على قاعدة البيانات، لذا ضع هذين التابعين في الملف <code>PostController.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_34" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

   </span><span class="com">/**
    * عرض الاستمارة الخاصة بتعديل المورد المُحدَّد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> edit</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $post </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'posts.edit'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'post'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">,</span><span class="pln">
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * تحديث المورد المحدَّد في وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> update</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">// الحصول على البيانات من الطلب</span><span class="pln">
       $title </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">);</span><span class="pln">
       $content </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">);</span><span class="pln">

       </span><span class="com">// البحث عن المنشور المطلوب ووضع البيانات المطلوبة في العمود المقابل</span><span class="pln">
       $post </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">title </span><span class="pun">=</span><span class="pln"> $title</span><span class="pun">;</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">content </span><span class="pun">=</span><span class="pln"> $content</span><span class="pun">;</span><span class="pln">

       </span><span class="com">// حفظ البيانات</span><span class="pln">
       $post</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'posts.show'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'post'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $id</span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ويكون عرض <code>edit</code> المقابل هو <code>views/post/edit.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_36" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Edit</span><span class="pun">&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"w-96 mx-auto my-8"</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">h2 </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"text-2xl font-semibold underline mb-4"</span><span class="pun">&gt;</span><span class="typ">Edit</span><span class="pln"> post</span><span class="pun">&lt;/</span><span class="pln">h2</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;</span><span class="pln">form
   action</span><span class="pun">=</span><span class="str">"{{ route('posts.update', ['post' =&gt; $post-&gt;id]) }}"</span><span class="pln">
   method</span><span class="pun">=</span><span class="str">"POST"</span><span class="pln">
 </span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">{{</span><span class="pln"> csrf_field</span><span class="pun">()</span><span class="pln"> </span><span class="pun">}}</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> method_field</span><span class="pun">(</span><span class="str">'PUT'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">label </span><span class="kwd">for</span><span class="pun">=</span><span class="str">"title"</span><span class="pun">&gt;</span><span class="typ">Title</span><span class="pun">:&lt;</span><span class="str">/label&gt;&lt;br /</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">input
     type</span><span class="pun">=</span><span class="str">"text"</span><span class="pln">
     id</span><span class="pun">=</span><span class="str">"title"</span><span class="pln">
     name</span><span class="pun">=</span><span class="str">"title"</span><span class="pln">
     </span><span class="kwd">value</span><span class="pun">=</span><span class="str">"{{ $post-&gt;title }}"</span><span class="pln">
     </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"p-2 w-full bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300"</span><span class="pln">
   </span><span class="pun">/&gt;&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">label </span><span class="kwd">for</span><span class="pun">=</span><span class="str">"content"</span><span class="pun">&gt;</span><span class="typ">Content</span><span class="pun">:&lt;</span><span class="str">/label&gt;&lt;br /</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">textarea
     type</span><span class="pun">=</span><span class="str">"text"</span><span class="pln">
     id</span><span class="pun">=</span><span class="str">"content"</span><span class="pln">
     name</span><span class="pun">=</span><span class="str">"content"</span><span class="pln">
     rows</span><span class="pun">=</span><span class="str">"15"</span><span class="pln">
     </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"p-2 w-full bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300"</span><span class="pln">
   </span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{{</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">content </span><span class="pun">}}&lt;/</span><span class="pln">textarea
   </span><span class="pun">&gt;&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">br </span><span class="pun">/&gt;</span><span class="pln">
   </span><span class="pun">&lt;</span><span class="pln">button
     type</span><span class="pun">=</span><span class="str">"submit"</span><span class="pln">
     </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"font-sans text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-md text-sm w-full px-5 py-2.5 text-center"</span><span class="pln">
   </span><span class="pun">&gt;</span><span class="pln">
     </span><span class="typ">Submit</span><span class="pln">
   </span><span class="pun">&lt;/</span><span class="pln">button</span><span class="pun">&gt;</span><span class="pln">
 </span><span class="pun">&lt;/</span><span class="pln">form</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<h2 id="delete">
	إجراء الحذف Delete
</h2>

<p>
	وأخيرًا، يوجد التابع <code>destroy()‎</code> للحذف، إذًا لنضعه في الملف <code>PostController.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2674_38" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\View\View</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">

   </span><span class="com">/**
    * إزالة المورد المُحدَّد من وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> destroy</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       $post </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">()-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">

       $post</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">();</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">()-&gt;</span><span class="pln">route</span><span class="pun">(</span><span class="str">'posts.index'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا يتطلب هذا الإجراء عرضًا، بما أنه يعيد توجيهك إلى <code>posts.index</code> بعد اكتمال الإجراء.
</p>

<p>
	ترجمة -وبتصرُّف- للمقال <a href="https://www.ericsdevblog.com/posts/laravel-for-beginners-3/" rel="external nofollow" target="_blank">Laravel for Beginners #3 - The CRUD Operations</a> لصاحبه Eric Hu.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D9%86%D9%8A%D8%A9-mvc-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2426/" rel="">لارافيل للمبتدئين-الجزء الثاني: استخدام بنية MVC لإنشاء مدونة بسيطة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%B4%D9%87%D9%8A%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/" rel="">تعرف على إطار عمل تطوير الويب الشهير لارافيل Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D9%85%D8%A8%D8%A7%D8%AF%D8%A6-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D9%91%D8%A9-%D9%84%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-eloquent-orm-r410/" rel="">المبادئ الأساسيّة لإطار العمل Eloquent ORM</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%AD%D9%82%D9%82-%D9%85%D9%86-%D8%A7%D9%84%D9%85%D8%AF%D8%AE%D9%84%D8%A7%D8%AA-%D9%81%D9%8A-laravel-r352/" rel="">أساسيات التحقق من المدخلات في Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D8%B4%D8%A6-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-query-builder-%D9%84%D9%84%D8%AA%D8%AE%D8%A7%D8%B7%D8%A8-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-r398/" rel="">كيف تستخدم منشئ الاستعلامات Query builder للتخاطب مع قاعدة البيانات في Laravel</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2427</guid><pubDate>Sun, 27 Oct 2024 15:08:03 +0000</pubDate></item><item><title>&#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; &#x644;&#x644;&#x645;&#x628;&#x62A;&#x62F;&#x626;&#x64A;&#x646;-&#x627;&#x644;&#x62C;&#x632;&#x621; &#x627;&#x644;&#x62B;&#x627;&#x646;&#x64A;: &#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x628;&#x646;&#x64A;&#x629; MVC &#x644;&#x625;&#x646;&#x634;&#x627;&#x621; &#x645;&#x62F;&#x648;&#x646;&#x629; &#x628;&#x633;&#x64A;&#x637;&#x629;</title><link>https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D9%86%D9%8A%D8%A9-mvc-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2426/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2024_10/--------MVC---.png.a1eab86bf3fee3e8962c5d3fe976c6d5.png" /></p>
<p>
	سنتحدث في هذا المقال عن معمارية MVC الخاصة بإطار عمل لارافيل Laravel، فبنية MVC هي مبدأ تصميم الويب الذي يتكون من النموذج ‎<strong>M</strong>odel المسؤول عن التواصل مع قاعدة البيانات، والمتحكِّم ‎<strong>C</strong>ontroller وهو المكان الذي نخزّن فيه شيفرة تطبيقنا البرمجية، والعرض ‎<strong>V</strong>iew وهو الواجهة الأمامية للتطبيق.
</p>

<p>
	يوجد مُوجّه Router في تطبيق الويب عادةً، وهذا ما ناقشناه في المقال السابق، حيث يؤشّر الموجّه إلى المتحكم، ويبحث المتحكم عن البيانات المطلوبة في قاعدة البيانات عبر النموذج، ثم يضع البيانات المُسترَّدة إلى الموقع المقابل في العرض، وأخيرًا يعيد هذا العرض إلى المستخدم.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159695" href="https://academy.hsoub.com/uploads/monthly_2024_10/01_mvc.png.3d2a1b93132ae01519096ed3ec791189.png" rel=""><img alt="laravel mvc" class="ipsImage ipsImage_thumbnailed" data-fileid="159695" data-unique="eobjpcde5" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2024_10/01_mvc.thumb.png.d018ec053f57542c41edea757ed6ac35.png"> </a>
</p>

<h2 id="">
	طبقة العرض
</h2>

<p>
	لنبدأ أولًا بطبقة بالعرض، حيث عرّفنا في <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-%D8%A7%D9%84%D8%A8%D8%AF%D8%A1-%D9%81%D9%8A-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2425/" rel="">المقال السابق</a> الوِجهة Route التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_6" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'welcome'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	تؤشّر هذه الوِجهة إلى العرض <code>welcome</code> المُخزَّن في المجلد <code>resources/views</code> وله الامتداد <code>‎.blade.php</code>، حيث يُعلِم هذا الامتداد لارافيل أننا نستخدم نظام قوالب <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%84%D8%A8-blade-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B9%D8%B1%D9%88%D8%B6-laravel-r220/" rel="">Blade</a> الذي سنتحدث عنه لاحقًا.
</p>

<p>
	يمكننا إنشاء عرض آخر من خلال إنشاء ملف آخر له الامتداد نفسه في المجلد <code>views</code>، إذًا لننشئ العرض <code>greetings.blade.php</code> التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4499_9" style=""><span class="tag">&lt;html&gt;</span><span class="pln">
 </span><span class="tag">&lt;body&gt;</span><span class="pln">
   </span><span class="tag">&lt;h1&gt;</span><span class="pln">Hello!</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
 </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	تحدثنا أيضًا في <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-%D8%A7%D9%84%D8%A8%D8%AF%D8%A1-%D9%81%D9%8A-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2425/" rel="">المقال السابق</a> عن إمكانية تمرير البيانات من الوِجهة إلى العرض كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_12" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'greeting'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'James'</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	أسندنا في المثال السابق القيمة <code>'James'</code> إلى المتغير <code>name</code>، ومرّرنا هذا المتغير إلى العرض <code>greeting.blade.php</code> الذي أنشأناه مسبقًا، ويمكننا استخدام الأقواس المزدوجة المتعرجة <code>{{ }}</code> لعرض هذه البيانات في العرض <code>greetings.blade.php</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_14" style=""><span class="tag">&lt;html&gt;</span><span class="pln">
 </span><span class="tag">&lt;body&gt;</span><span class="pln">
   </span><span class="tag">&lt;h1&gt;</span><span class="pln">Hello, {{ $name }}</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
 </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	من الشائع تنظيم ملفات العرض في مجلدات مختلفة بالنسبة لتطبيقات الويب الكبيرة، فمثلًا يمكن أن يحتوي تطبيقك على لوحة إدارة، وبالتالي ستخزّن العروض Views المقابلة لها في مجلد فرعي اسمه <code>admin</code> مثلًا، وتذكّر استخدام <code>.</code> بدلًا من <code>/</code> عندما تؤشّر إلى ملفات العرض في بنية متداخلة من الموجّه، حيث يؤشّر المثال التالي إلى الملف <code>home.blade.php</code> الموجود في المجلد <code>views/admin/‎</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_17" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/admin'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'admin.home'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<h3 id="blade">
	صيغة قوالب Blade
</h3>

<p>
	تستخدم عروض لارافيل قالب Blade افتراضيًا، وهو مشابه لنظام <a href="https://academy.hsoub.com/programming/javascript/vuejs/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D9%85%D9%83%D9%88%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-vuejs-r1031/" rel="">المكونات في إطار عمل Vue.js</a>. تُعَد العروض مستندات <a href="https://academy.hsoub.com/programming/html/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%84%D8%BA%D8%A9-html-r1752/" rel="">HTML</a>، ويضيف قالب Blade ميزات برمجية إليها مثل نظام الوراثة والتحكم في التدفق والحلقات والمفاهيم البرمجية الأخرى، مما يؤدي إلى إنشاء صفحة ويب أكثر ديناميكية مع كتابة تعليمات برمجية أقل.
</p>

<h4 id="if">
	التعليمة الشرطية if
</h4>

<p>
	يمكننا إنشاء تعليمات <code>if</code> باستخدام التوجيهات Directives التي هي <code>‎@if</code> و <code>‎@elseif</code> و <code>‎@else</code> و <code>‎@endif</code>، حيث تعمل هذه التعليمات مثل تعليمات <code>if</code> التي نراها في لغات البرمجة الأخرى.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_20" style=""><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$num </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;p&gt;</span><span class="typ">The</span><span class="pln"> number </span><span class="kwd">is</span><span class="pln"> one</span><span class="pun">.&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@elseif</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$num </span><span class="pun">==</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;p&gt;</span><span class="typ">The</span><span class="pln"> number </span><span class="kwd">is</span><span class="pln"> two</span><span class="pun">.&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@else</span><span class="pln">
</span><span class="str">&lt;p&gt;</span><span class="typ">The</span><span class="pln"> number </span><span class="kwd">is</span><span class="pln"> three</span><span class="pun">.&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endif</span></pre>

<p>
	يمكننا اختبار هذه الشيفرة البرمجية باستخدام الوِجهة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_22" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/number/{num}'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'view'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'num'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $num</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	نفترض هنا أن المتغير <code>num</code> يمكن أن يكون قيمته 1 أو 2 أو 3 فقط.
</p>

<h4 id="switch">
	التعليمة switch
</h4>

<p>
	تكون بنية هذه التعليمة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_24" style=""><span class="lit">@switch</span><span class="pun">(</span><span class="pln">$i</span><span class="pun">)</span><span class="pln">
 </span><span class="lit">@case</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln">
     </span><span class="typ">First</span><span class="pln"> </span><span class="kwd">case</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
     </span><span class="lit">@break</span><span class="pln">

 </span><span class="lit">@case</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
     </span><span class="typ">Second</span><span class="pln"> </span><span class="kwd">case</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
     </span><span class="lit">@break</span><span class="pln">

 </span><span class="lit">@default</span><span class="pln">
     </span><span class="typ">Default</span><span class="pln"> </span><span class="kwd">case</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="lit">@endswitch</span></pre>

<h4 id="-1">
	الحلقات
</h4>

<p>
	يمكن أن نمثل الحلقات بحلقة <code>for</code> بسيطة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_26" style=""><span class="lit">@for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln">
 </span><span class="typ">The</span><span class="pln"> current </span><span class="kwd">value</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> $i </span><span class="pun">}}</span><span class="pln">
</span><span class="lit">@endfor</span></pre>

<p>
	أو بحلقة <code>foreach</code>، حيث يساوي المتغير <code>‎$user</code> العنصر التالي من <code>‎$users</code> لكل تكرار في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_28" style=""><span class="lit">@foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$users </span><span class="kwd">as</span><span class="pln"> $user</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;p&gt;</span><span class="typ">This</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> user </span><span class="pun">{{</span><span class="pln"> $user</span><span class="pun">-&gt;</span><span class="pln">id </span><span class="pun">}}&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endforeach</span></pre>

<p>
	يمكن أن نمثّل الحلقات بحلقة <code>while</code> أيضًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_30" style=""><span class="lit">@while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;p&gt;</span><span class="pln">I</span><span class="str">'m looping forever.&lt;/p&gt;
@endwhile</span></pre>

<p>
	تُعَد هذه التعليمات بسيطة جدًا، وتعمل تمامًا مثل نظيراتها في <a href="https://academy.hsoub.com/PHP/" rel="">لغة PHP</a>، ولكن يوجد شيء خاص بهذه الحلقات هو المتغير <code>‎$loop</code>، فمثلًا ليكن لدينا شيء نريد عرضه مرة واحدة فقط، حيث يمكنك تطبيق ما يلي في التكرار الأول:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_32" style=""><span class="lit">@foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$users </span><span class="kwd">as</span><span class="pln"> $user</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$loop</span><span class="pun">-&gt;</span><span class="pln">first</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;p&gt;</span><span class="typ">This</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> the first iteration</span><span class="pun">.&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endif</span><span class="pln">

</span><span class="str">&lt;p&gt;</span><span class="typ">This</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> user </span><span class="pun">{{</span><span class="pln"> $user</span><span class="pun">-&gt;</span><span class="pln">id </span><span class="pun">}}&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endforeach</span></pre>

<p>
	سيُعرَض عنصر الفقرة <code>&lt;p&gt;This is the first iteration.&lt;/p&gt;</code> مرة واحدة فقط في التكرار الأول، وتوجد العديد من الخاصيات الأخرى التي يمكنك الوصول إليها، لذا اطلع عليها في <a href="https://laravel.com/docs/11.x/blade#the-loop-variable" rel="external nofollow">توثيق لارافيل الرسمي</a>. لاحظ أنه لا يمكن الوصول إلى المتغير <code>‎$loop</code> إلا ضمن الحلقة.
</p>

<h4 id="conditionalclass">
	الصنف الشرطي Conditional Class
</h4>

<p>
	يُعَد الصنف Class الطريقة الأكثر استخدامًا لإسناد التنسيقات Styles إلى عناصر HTML المختلفة، ويمكننا بسهولة تغيير مظهر هذا العنصر من خلال تغيير صنفه، حيث يقدّم لارافيل طريقة لإسناد الأصناف ديناميكيًا بالاعتماد على المتغيرات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_34" style=""><span class="tag">&lt;span</span><span class="pln"> @</span><span class="atn">class</span><span class="pln">([
   </span><span class="atv">'p-4'</span><span class="pln">,
   </span><span class="atv">'font-bold'</span><span class="pln"> </span><span class="tag">=&gt;</span><span class="pln"> $isActive,
   'bg-red' =&gt; $hasError,
])&gt;</span><span class="tag">&lt;/span&gt;</span></pre>

<p>
	يعتمد الصنفان <code>font-bold</code> و <code>bg-red</code> في المثال السابق على قيمة المتغيرين <code>‎$isActive</code> و ‎<code>$hasError</code>‎.
</p>

<h3 id="layout">
	بناء تخطيط الصفحة Layout
</h3>

<p>
	توجد دائمًا بعض أجزاء الصفحة التي ستظهر في صفحات متعددة عندما نبني تطبيق ويب، حيث تُعَد كتابة الشيفرة البرمجية نفسها مرارًا وتكرارًا مضيعة للوقت والموارد، ولا يُعَد ذلك جيدًا للصيانة، لذا يجب فصل الجزء الذي سيظهر عدة مرات ووضعه في ملف آخر، وسنستورده ببساطة عندما نحتاج إليه. يقدم إطار عمل لارافيل طريقتين مختلفتين لذلك هما: <strong>وراثة القوالب ووراثة المكونات</strong>، حيث يُعَد فهم وراثة القوالب أسهل بكثير للمبتدئين، ولكن توفّر المكونات مزيدًا من الميزات، إذًا لنبدأ أولًا بوراثة القوالب.
</p>

<h4 id="-2">
	وراثة القوالب
</h4>

<p>
	نحاول في المثال التالي تعريف صفحة رئيسية، وتكون الوِجهة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_36" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'home'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يستورد العرض <code>layout.blade.php</code> ملفات <a href="https://academy.hsoub.com/programming/css/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-css/" rel="">CSS</a> وجافاسكريبت <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%AC%D8%A7%D9%81%D8%A7-%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-%D9%85%D9%86-%D8%A7%D9%84%D8%B5%D9%81%D8%B1-%D8%AD%D8%AA%D9%89-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D8%B1%D8%A7%D9%81-r2046/" rel="">JavaScript</a> الضرورية، بالإضافة إلى شريط التنقل وتذييل الصفحة التي ستظهر في جميع الصفحات، وسنرث <code>layout.blade.php</code> في الملف <code>home.blade.php</code>. لنضع أولًا ما يلي في الملف <code>layout.blade.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_40" style=""><span class="tag">&lt;html&gt;</span><span class="pln">
 </span><span class="tag">&lt;head&gt;</span><span class="pln">
   @yield('title')
 </span><span class="tag">&lt;/head&gt;</span><span class="pln">

 </span><span class="tag">&lt;body&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">@yield('content')</span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	ولنضع الآن ما يلي في الملف <code>home.blade.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_42" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Home</span><span class="pln"> </span><span class="typ">Page</span><span class="pun">&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;p&gt;</span><span class="typ">Lorem</span><span class="pln"> ipsum dolor sit amet</span><span class="pun">,</span><span class="pln"> consectetur adipiscing elit</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span></pre>

<p>
	لاحظ أن <code>‎@section('title')‎</code> يقابل <code>‎@yield('title')‎</code>، وأن <code>‎@section('content')‎</code> يقابل <code>‎@yield('content')‎</code>. سيرى لارافيل أولًا التوجيه <code>‎@extends('layout')‎</code> عند عرض الصفحة الرئيسية في مثالنا، وسيعرف أنه يجب عليه الانتقال إلى الملف <code>layout.blade.php</code>. سيحدد لارافيل بعد ذلك موقع <code>‎@yield('title')‎</code> ويضع القسم <code>title</code> مكانه، ثم يبحث عن التوجيه <code>‎@yield('content')‎</code> ويضع القسم <code>content</code> مكانه.
</p>

<p>
	سنحتاج في بعض الأحيان إلى تحميل عرض آخر من العرض الحالي، فمثلًا إذا أردنا إضافة شريط جانبي إلى صفحتنا الرئيسية، وهو شيء سنضمّنه في بعض الصفحات دون صفحات أخرى، فلن نضعه في الملف <code>layout.blade.php</code>، ولكن سيكون من الصعب جدًا صيانته إذا أنشأتَ شريطًا جانبيًا لكل صفحة تتطلب ذلك. يمكننا في مثالنا إنشاء الملف <code>sidebar.blade.php</code>، ثم استخدام التوجيه <code>‎@include</code> لاستيراد هذا الملف في الصفحة الرئيسية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_44" style=""><span class="lit">@extends</span><span class="pun">(</span><span class="str">'layout'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;title&gt;</span><span class="typ">Home</span><span class="pln"> </span><span class="typ">Page</span><span class="pun">&lt;/</span><span class="pln">title</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">@endsection</span><span class="pln"> </span><span class="lit">@section</span><span class="pun">(</span><span class="str">'content'</span><span class="pun">)</span><span class="pln">
</span><span class="str">&lt;p&gt;</span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.&lt;/</span><span class="pln">p</span><span class="pun">&gt;</span><span class="pln">

</span><span class="lit">@include</span><span class="pun">(</span><span class="str">'sidebar'</span><span class="pun">)</span><span class="pln"> </span><span class="lit">@endsection</span></pre>

<h4 id="components">
	المكونات Components
</h4>

<p>
	يشبه نظام المكونات في لارافيل إلى حد كبير النظام الموجود في إطار عمل Vue.js. سنبني صفحة رئيسية مع تخطيطها، ولكننا سنعرّف التخطيط بوصفه مكونًا، لذا سننشئ المجلد <code>components</code> ضمن المجلد <code>resources/views/‎</code>، ثم ننشئ الملف <code>layout.blade.php</code> بداخله.
</p>

<p>
	لنضع أولًا ما يلي في الملف <code>views/components/layout.blade.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_46" style=""><span class="tag">&lt;html&gt;</span><span class="pln">
 </span><span class="tag">&lt;head&gt;</span><span class="pln">
   . . .
 </span><span class="tag">&lt;/head&gt;</span><span class="pln">

 </span><span class="tag">&lt;body&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">{{ $slot }}</span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يمكن استخدام هذا المكون من خلال استخدام الوسم <code>&lt;x-layout&gt;</code>، وتذكّر دائمًا البادئة <code>x-‎</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_48" style=""><span class="tag">&lt;x-layout&gt;</span><span class="pln">
 </span><span class="tag">&lt;p&gt;</span><span class="pln">
   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eu elit
   semper ex varius vehicula.
 </span><span class="tag">&lt;/p&gt;</span><span class="pln">
</span><span class="tag">&lt;/x-layout&gt;</span></pre>

<p>
	سيُسنَد المحتوى الموجود ضمن العنصر <code>&lt;x-layout&gt;</code> إلى المتغير <code>‎$slot</code> تلقائيًا، ولكن إذا كان لدينا فتحات Slots متعددة كما في مثالنا الذي يحتوي على قسم <code>title</code> وقسم <code>content</code>، فيمكن حل هذه المشكلة من خلال تعريف عنصر <code>&lt;x-slot&gt;</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_50" style=""><span class="tag">&lt;x-layout&gt;</span><span class="pln">
 </span><span class="tag">&lt;x-slot</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"title"</span><span class="tag">&gt;</span><span class="pln">
   </span><span class="tag">&lt;title&gt;</span><span class="pln">Home Page</span><span class="tag">&lt;/title&gt;</span><span class="pln">
 </span><span class="tag">&lt;/x-slot&gt;</span><span class="pln">

 </span><span class="tag">&lt;p&gt;</span><span class="pln">
   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eu elit
   semper ex varius vehicula.
 </span><span class="tag">&lt;/p&gt;</span><span class="pln">
</span><span class="tag">&lt;/x-layout&gt;</span></pre>

<p>
	سيُسنَد محتوى <code>&lt;x-slot name="title"‎&gt;</code> إلى المتغير <code>‎$title</code> وسيُسنَد المحتوى المتبقي إلى المتغير <code>‎$slot</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_52" style=""><span class="tag">&lt;html&gt;</span><span class="pln">
 </span><span class="tag">&lt;head&gt;</span><span class="pln">
   {{ $title }}
 </span><span class="tag">&lt;/head&gt;</span><span class="pln">

 </span><span class="tag">&lt;body&gt;</span><span class="pln">
   </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container"</span><span class="tag">&gt;</span><span class="pln">{{ $slot }}</span><span class="tag">&lt;/div&gt;</span><span class="pln">
 </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<h2 id="-3">
	التعامل مع قواعد البيانات في لارافيل
</h2>

<p>
	سنناقش أولًا كيفية التعامل مع قواعد البيانات في لارافيل قبل أن نتحدث بمزيد من التفصيل عن طبقة النموذج والمتحكم في بنية MVC. يمكن أن نستخدم ملف <code>‎.txt</code> بسيط لتخزين المعلومات عند استخدام جافاسكريبت <a href="https://academy.hsoub.com/JavaScript/" rel="">JavaScript  </a>و <a href="https://academy.hsoub.com/programming/javascript/%D8%A8%D9%8A%D8%A6%D8%A9-nodejs-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D9%84%D9%85%D8%AA%D8%B5%D9%81%D8%AD-r1402/" rel="">Node.js</a>، ولكن لن ينجح ذلك في تطبيق الويب الواقعي، لذا سنحتاج لاستخدام قاعدة بيانات لتخزين ومعالجتها المعلومات بكفاءة.
</p>

<p>
	استخدمنا في مقالنا الحالي أداة Sail الخاصة بلارافيل لإنشاء هذا المشروع، لذا أعدت هذه الأداة قاعدة بيانات <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D8%AC-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-r28/" rel="">MySQL</a>، إذ يجب أن توجد متغيرات البيئة التالية في ملف <code>‎.env</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_55" style=""><span class="pln">DB_CONNECTION</span><span class="pun">=</span><span class="pln">mysql
DB_HOST</span><span class="pun">=</span><span class="pln">mysql
DB_PORT</span><span class="pun">=</span><span class="lit">3306</span><span class="pln">
DB_DATABASE</span><span class="pun">=</span><span class="pln">curl_demo
DB_USERNAME</span><span class="pun">=</span><span class="pln">sail
DB_PASSWORD</span><span class="pun">=</span><span class="pln">password</span></pre>

<h3 id="migrations">
	عمليات تهجير Migrations قاعدة البيانات
</h3>

<p>
	تكون قاعدة البيانات فارغة حاليًا، لذا سنضيف بعض جداول قاعدة البيانات لاستخدامها، حيث ستحتوي هذه الجداول على أعمدة، وستكون للأعمدة أسماء وبعض المتطلبات الخاصة، وتسمى عملية الإعداد هذه بتشغيل عمليات التهجير. تُخزَّن جميع ملفات التهجير في لارافيل ضمن المجلد <code>database/migrations</code>، ويمكننا إنشاء ملف تهجير جديد من خلال استخدام الأمر البسيط التالي، ولكن إذا استخدمتَ أداة Sail لإنشاء مشروع لارافيل، فضع <code>‎./vendor/bin/sail</code> بدلًا من <code>php</code> لتشغيل PHP داخل حاوية دوكر Docker، وإن لم تستخدم أداة Sail، فتابع كالمعتاد:
</p>

<pre class="ipsCode">php artisan make:migration create_flights_table
</pre>

<p>
	يمكن تطبيق ملف التهجير كما يلي:
</p>

<pre class="ipsCode">php artisan migrate
</pre>

<p>
	وإذا أردتَ التراجع عن عملية التهجير السابقة، فاستخدم الأمر التالي:
</p>

<pre class="ipsCode">php artisan migrate:rollback
</pre>

<p>
	أو إذا أردتَ إعادة ضبط عمليات التهجير بالكامل والتراجع عن جميع التغييرات المطبقة على قاعدة البيانات، فاستخدم الأمر التالي:
</p>

<pre class="ipsCode">php artisan migrate:reset
</pre>

<h4 id="-4">
	إنشاء جدول
</h4>

<p>
	لنلقِ نظرة على المثال التالي قبل إنشاء ملف التهجير. افتح ملف التهجير <code>database/migrations/2014_10_12_000000_create_users_table.php</code> التالي الذي يأتي مع لارافيل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_57" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Migrations\Migration</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Schema\Blueprint</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Schema</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Migration</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * تشغيل عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">);</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'email'</span><span class="pun">)-&gt;</span><span class="pln">unique</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">timestamp</span><span class="pun">(</span><span class="str">'email_verified_at'</span><span class="pun">)-&gt;</span><span class="pln">nullable</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'password'</span><span class="pun">);</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">rememberToken</span><span class="pun">();</span><span class="pln">
           $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
       </span><span class="pun">});</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عكس عمليات التهجير
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> down</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يحتوي هذا الملف على صنف class له تابعان مختلفان، حيث يُستخدَم التابع ‎<code>up()</code>‎ لإنشاء جداول وأعمدة جديدة، بينما يمكن استخدام التابع ‎<code>down()</code>‎ لعكس العمليات التي يطبّقها التابع ‎<code>up()</code>‎. يستخدم لارافيل داخل التابع ‎<code>up()</code>‎ التابع <code>create()‎</code> ضمن الصنف <code>Schema</code> لإنشاء جدول جديد بالاسم <code>'users'</code>. وينشئ كل سطر من السطور 15 إلى 21 في الشيفرة البرمجية السابقة عمودًا مختلفًا مع اسم ونوع مختلفين، فمثلًا ينشئ السطر <code>‎$table-&gt;string('name');‎</code> عمودًا بالاسم <code>name</code> ضمن الجدول <code>users</code>، ويجب أن يخزّن هذا العمود سلاسلًا نصية.
</p>

<p>
	اطّلع على <a href="https://laravel.com/docs/11.x/migrations#available-column-types" rel="external nofollow">القائمة الكاملة</a> لأنواع الأعمدة المتوفرة في لارافيل. لن نستعرض جميع هذه الأنواع، بل سنناقش أهمها وسبب اختيارنا لنوع العمود عندما نواجه مشكلات محددة مستقبلًا.
</p>

<p>
	لاحظ السطر 17 في الشيفرة البرمجية السابقة <code>‎$table-&gt;string('email')-&gt;unique();‎</code>، حيث يوجد التابع <code>unique()‎</code> بعد التصريح عن اسم العمود ونوعه، حيث يُسمَّى هذا التابع بمُعدِّل العمود Column Modifier، لأنه يضيف قيودًا إضافية إلى هذا العمود، ويتأكد في هذه الحالة من أن العمود لا يمكن أن يحتوي على قيم متكررة، ويجب أن يكون كل بريد إلكتروني يقدّمه المستخدم فريدًا.
</p>

<p>
	اطّلع على <a href="https://laravel.com/docs/11.x/migrations#column-modifiers" rel="external nofollow">القائمة الكاملة</a> لمُعدِّلي الأعمدة المتوفرة في لارافيل.
</p>

<h4 id="-5">
	إجراء تغييرات على الجدول
</h4>

<p>
	يمكن أيضًا تحديث الجداول باستخدام التابع <code>table()‎</code> كما يلي، حيث تضيف الشيفرة البرمجية التالية عمودًا جديدًا هو العمود <code>age</code> إلى الجدول <code>users</code> الموجود مسبقًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_59" style=""><span class="typ">Schema</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   $table</span><span class="pun">-&gt;</span><span class="pln">integer</span><span class="pun">(</span><span class="str">'age'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	كما يمكننا إعادة تسمية الجدول باستخدام التابع <code>rename()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_61" style=""><span class="typ">Schema</span><span class="pun">::</span><span class="pln">rename</span><span class="pun">(</span><span class="pln">$from</span><span class="pun">,</span><span class="pln"> $to</span><span class="pun">);</span></pre>

<p>
	ويمكننا حذف جدول نهائيًا كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_63" style=""><span class="typ">Schema</span><span class="pun">::</span><span class="pln">drop</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">);</span><span class="pln">

</span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">);</span></pre>

<h3 id="seeding">
	البذر أو توليد البيانات Seeding
</h3>

<p>
	يُستخدَم مولّد البيانات Seeder لإنشاء بيانات وهمية لقاعدة بياناتك، وبالتالي يسهّل عليك إجراء الاختبارات، حيث يمكنك إنشاء مولّد بيانات من خلال تشغيل الأمر التالي:
</p>

<pre class="ipsCode">php artisan make:seeder UserSeeder
</pre>

<p>
	يولّد الأمر السابق مولّد بيانات للجدول <code>users</code>، وسيُوضَع في المجلد <code>database/seeders</code>، حيث وضع ما يلي في الملف <code>UserSeeder.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_66" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">Database</span><span class="pln">\Seeders</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Seeder</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\DB</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Hash</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Str</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UserSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * تشغيل مولّدات بيانات قاعدة البيانات
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">():</span><span class="pln"> </span><span class="kwd">void</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">)-&gt;</span><span class="pln">insert</span><span class="pun">([</span><span class="pln">
           </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Str</span><span class="pun">::</span><span class="pln">random</span><span class="pun">(</span><span class="lit">10</span><span class="pun">),</span><span class="pln">
           </span><span class="str">'email'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Str</span><span class="pun">::</span><span class="pln">random</span><span class="pun">(</span><span class="lit">10</span><span class="pun">).</span><span class="str">'@gmail.com'</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'password'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Hash</span><span class="pun">::</span><span class="pln">make</span><span class="pun">(</span><span class="str">'password'</span><span class="pun">),</span><span class="pln">
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	شغّل الأمر التالي لتنفيذ مولّد البيانات السابق وملء جداول قاعدة البيانات بالبيانات الافتراضية:
</p>

<pre class="ipsCode">php artisan db:seed UserSeeder
</pre>

<h3 id="querybuilder">
	باني الاستعلامات Query Builder
</h3>

<p>
	باني الاستعلامات هو واجهة تسمح لنا بالتفاعل مع قاعدة البيانات، فمثلًا يمكننا استخدام التابع <code>table()‎</code> الذي يوفره الصنف <code>DB</code> لاسترداد جميع الصفوف الموجودة في الجدول كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_68" style=""><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\DB</span><span class="pun">;</span><span class="pln">

$users </span><span class="pun">=</span><span class="pln"> DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">();</span></pre>

<p>
	يمكننا إضافة مزيدٍ من القيود من خلال إضافة التابع <code>where()‎</code> إلى سلسلة التوابع كما يلي، حيث ستحصل الشيفرة البرمجية التالية على جميع الصفوف التي تكون فيها القيمة المخزنة في العمود <code>age</code> أكبر من أو تساوي 21:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_70" style=""><span class="pln">$users </span><span class="pun">=</span><span class="pln"> DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'users'</span><span class="pun">)-&gt;</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'age'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'&gt;='</span><span class="pun">,</span><span class="pln"> </span><span class="lit">21</span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">();</span></pre>

<p>
	توجد الكثير من التوابع الأخرى إلى جانب التابعين <code>where()‎</code> و <code>get()‎</code>، والتي سنتحدث عنها لاحقًا.
</p>

<h2 id="model">
	طبقة النموذج Model
</h2>

<p>
	يُعَد النموذج مفهومًا مهمًا جدًا في تصميم الويب الحديث، فهو مسؤول عن التفاعل مع قاعدة بيانات تطبيق الويب، وهو جزء من نظام رابط الكائنات بالعلاقات Object-Relational Mapper -أو ORM اختصارًا- في لارافيل الذي هو نظام Eloquent، حيث يمكن عَدّه باني استعلام مع بعض الميزات الإضافية. يمكننا استخدام الأمر <code>make:model</code> لإنشاء نموذج جديد كما يلي:
</p>

<pre class="ipsCode">php artisan make:model Post
</pre>

<p>
	إذا أردتَ توليد ملف تهجير مقابل للنموذج، فاستخدم الخيار <code>‎--migration</code>:
</p>

<pre class="ipsCode">php artisan make:model Post --migration
</pre>

<p>
	وسيتضمّن ملف النموذج <code>app/Models/Post.php</code> ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_72" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Factories\HasFactory</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Post</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">HasFactory</span><span class="pun">;</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يفترِض النموذج السابق وجود الجدول <code>posts</code> في قاعدة البيانات افتراضيًا، وإذا أردتَ تغيير هذا الإعداد، فاضبط الخاصية <code>‎$table</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_74" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Post</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * الجدول المرتبط بالنموذج
    *
    * @var string
    */</span><span class="pln">
   </span><span class="kwd">protected</span><span class="pln"> $table </span><span class="pun">=</span><span class="pln"> </span><span class="str">'my_posts'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3 id="-6">
	استرداد النموذج
</h3>

<p>
	يُعَد نموذج Eloquent بانيَ استعلامات قويًا ويسمح بالتواصل مع قاعدة البيانات، فمثلًا يمكننا استخدام التابع <code>all()‎</code> لاسترداد كافة السجلات في الجدول كما يلي، ولاحظ أننا استوردنا النموذج <code>Post</code> بدلًا من الصنف <code>DB</code>، حيث سيتصل النموذج <code>Post</code> تلقائيًا بالجدول <code>posts</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_76" style=""><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\Post</span><span class="pun">;</span><span class="pln">

$posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span></pre>

<p>
	بما أن النموذج هو باني استعلامات، لذا يمكن أن تصل النماذج إلى جميع توابع باني الاستعلامات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_78" style=""><span class="pln">$posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'published'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
              </span><span class="pun">-&gt;</span><span class="pln">orderBy</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
              </span><span class="pun">-&gt;</span><span class="pln">take</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln">
              </span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">();</span></pre>

<p>
	إذا استخدمتَ التابعين <code>all()‎</code> أو <code>get()‎</code> لاسترداد البيانات، فلن تكون القيمة المُعادة مصفوفةً أو كائنًا بسيطًا، ولكنها ستكون نسخة من الصنف <code>Illuminate\Database\Eloquent\Collection</code>، حيث يوفّر الصنف <code>Collection</code> عدة توابع أقوى من الكائنات البسيطة.
</p>

<p>
	يمكن استخدام التابع <code>find()‎</code> مثلًا لتحديد موقع سجل باستخدام مفتاح رئيسي هو <code>id</code> عادة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_80" style=""><span class="pln">$posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

$post </span><span class="pun">=</span><span class="pln"> $posts</span><span class="pun">-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span></pre>

<p>
	سيكون <code>‎$post</code> في هذا المثال هو المنشور ذو المعرّف <code>id==1</code>.
</p>

<h3 id="-7">
	إدراج وتحديث النموذج
</h3>

<p>
	يمكننا أيضًا إدراج السجلات أو تحديثها باستخدام النموذج، ولكن تأكد أولًا من أن النموذج المقابل له الخاصية <code>‎$fillable</code> وتأكد من سرد جميع الأعمدة التي يجب أن تكون قابلة للملء.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_82" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Post</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * السمات‫ Attributes التي يمكن إسنادها بطريقة جماعية
    *
    * @var array
    */</span><span class="pln">
   </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'title'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'content'</span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكننا بعد ذلك استخدام التابع <code>create()‎</code> لإنشاء سجل جديد كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_84" style=""><span class="pln">$flight </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">create</span><span class="pun">([</span><span class="pln">
   </span><span class="str">'title'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'. . .'</span><span class="pun">,</span><span class="pln">
   </span><span class="str">'content'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'. . .'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">]);</span></pre>

<p>
	أو يمكننا تحديث السجلات الموجودة مسبقًا باستخدام التابع <code>update()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_86" style=""><span class="typ">Flight</span><span class="pun">::</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'published'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)-&gt;</span><span class="pln">update</span><span class="pun">([</span><span class="str">'published'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">]);</span></pre>

<h3 id="-8">
	حذف النموذج
</h3>

<p>
	يوجد تابعان يسمحان بحذف السجلات، حيث إذا أردتَ حذف سجل واحد، فاستخدم التابع <code>delete()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_88" style=""><span class="pln">$posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

$post </span><span class="pun">=</span><span class="pln"> $posts</span><span class="pun">-&gt;</span><span class="pln">find</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln">

$post</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">();</span></pre>

<p>
	وإذا أردتَ حذف السجلات بطريقة جماعية، فاستخدم التابع <code>truncate()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_90" style=""><span class="pln">$posts </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'published'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">)</span><span class="pln">
              </span><span class="pun">-&gt;</span><span class="pln">orderBy</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">)</span><span class="pln">
              </span><span class="pun">-&gt;</span><span class="pln">take</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln">
              </span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">();</span><span class="pln">

$posts</span><span class="pun">-&gt;</span><span class="pln">truncate</span><span class="pun">();</span></pre>

<h2 id="-9">
	علاقات قاعدة البيانات
</h2>

<p>
	لا تكون جداول قاعدة البيانات في تطبيقات الويب مستقلة بل تكون مترابطة بعلاقات فيما بينها، فمثلًا يمكن أن يكون لدينا مستخدم لديه منشورات ويمكن أن يكون لدينا منشوراتٌ تخص مستخدمًا ما، لذا يقدّم لارافيل طريقة لتعريف هذه العلاقات باستخدام نماذج Eloquent.
</p>

<p>
	يُحتمَل أن يكون القسم التالي صعبًا بعض الشيء بالنسبة للمبتدئين، ولكن لا تقلق بهذا الشأن، إذ سنعود إلى هذا الموضوع لاحقًا عندما نبدأ في إنشاء تطبيق المدونة، حيث سنوضّح فقط ما نحتاج إلى استخدامه لبناء نظام تدوين بسيط.
</p>

<h3 id="-10">
	علاقة واحد إلى واحد
</h3>

<p>
	تُعَد علاقة واحد إلى واحد One to One العلاقة الأساسية، فمثلًا يرتبط كل مستخدم <code>User</code> بحيوان أليف <code>Pet</code> واحد. يمكن تعريف هذه العلاقة من خلال وضع التابع <code>pet</code> في النموذج <code>User</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_92" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">User</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * الحصول على الحيوان الأليف المرتبط بالمستخدم
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> pet</span><span class="pun">()</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">hasOne</span><span class="pun">(</span><span class="typ">Pet</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا أردنا أن نطبّق العكس، حيث يكون معكوس العلاقة "يملك" has one هو "يعود إلى" belongs to one، مما يعني أن كل حيوان أليف <code>Pet</code> يعود إلى مستخدم <code>User</code> واحد، ويمكن تعريف معكوس العلاقة واحد إلى واحد من خلال وضع التابع <code>user</code> في النموذج <code>Pet</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_94" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Pet</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * الحصول على المستخدم الذي يملك الحيوان الأليف
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> user</span><span class="pun">()</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">belongsTo</span><span class="pun">(</span><span class="typ">User</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لكننا لم ننتهِ بعد، إذ يجب أيضًا إجراء بعض التغييرات على جداول قاعدة البيانات المتقابلة، إذ يفترض النموذج <code>User</code> وجود العمود <code>pet_id</code> ضمن الجدول <code>users</code>، ويخزّن معرّف <code>id</code> الحيوان الأليف الذي يملكه المستخدم. يجب أيضًا إجراء تعديلات على الجدول <code>pets</code> المقابل، إذ يجب وجود العمود <code>user_id</code> الذي يخزّن معرّف <code>id</code> المستخدم الذي يعود إليه هذا الحيوان الأليف.
</p>

<h3 id="-11">
	علاقة واحد إلى متعدد
</h3>

<p>
	تُستخدم علاقة واحد إلى متعدد One-to-Many لتعريف العلاقات التي يمتلك فيها نموذج واحد نسخًا متعددة من نموذج آخر، فمثلًا يمكن أن تحتوي فئة <code>Category</code> واحدة على العديد من المنشورات <code>posts</code>، ويمكن تعريف هذه العلاقة من خلال وضع التابع <code>posts</code> في النموذج <code>Category</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_96" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Category</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> posts</span><span class="pun">()</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">hasMany</span><span class="pun">(</span><span class="typ">Post</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ولكن يجب في بعض الأحيان العثور على الفئة عبر المنشور، فمعكوس العلاقة "لديه العديد" has many هو "ينتمي إلى" belongs to، ويمكن تعريف معكوس العلاقة واحد إلى متعدد من خلال وضع التابع <code>category</code> في النموذج <code>Post</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_98" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Post</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> category</span><span class="pun">()</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">belongsTo</span><span class="pun">(</span><span class="typ">Category</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تفترض هذه العلاقة أن الجدول <code>posts</code> يحتوي على العمود <code>category_id</code> الذي يخزّن معرّف <code>id</code> الفئة التي ينتمي إليها هذا المنشور.
</p>

<h3 id="-12">
	علاقة متعدد إلى متعدد
</h3>

<p>
	تُعَد العلاقة متعدد إلى متعدد Many-to-Many أصعب بعض الشيء، فمثلًا يمكن أن يكون لدينا مستخدم <code>User</code> لديه العديد من الأدوار، ويمكن أن يكون لدينا دور <code>Role</code> له العديد من المستخدمين كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4499_100" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">User</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * الأدوار التي تخص المستخدم
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> roles</span><span class="pun">()</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">belongsToMany</span><span class="pun">(</span><span class="typ">Role</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1367_24" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Role</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * المستخدمون الذين ينتمون إلى الدور
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> users</span><span class="pun">()</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">belongsToMany</span><span class="pun">(</span><span class="typ">User</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تفترض هذه العلاقة وجود الجدول <code>role_user</code> في قاعدة البيانات واحتواء الجدول <code>role_user</code> على العمودين <code>user_id</code> و <code>role_id</code>، وبالتالي يمكننا مطابقة المستخدم مع دوره والعكس صحيح.
</p>

<p>
	لنفترض أن لدينا الجدول <code>role_user</code> كما يلي:
</p>

<table>
	<thead>
		<tr>
			<th>
				user_id
			</th>
			<th>
				role_id
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				1
			</td>
			<td>
				1
			</td>
		</tr>
		<tr>
			<td>
				2
			</td>
			<td>
				1
			</td>
		</tr>
		<tr>
			<td>
				3
			</td>
			<td>
				2
			</td>
		</tr>
		<tr>
			<td>
				1
			</td>
			<td>
				2
			</td>
		</tr>
		<tr>
			<td>
				2
			</td>
			<td>
				3
			</td>
		</tr>
	</tbody>
</table>

<p>
	يمتلك المستخدم الذي له المعرّف <code>id=1</code> دورَين لهما المعرّف <code>id=1</code> والمعرّف <code>id=2</code>. إذا أردنا عكس الأمر للعثور على المستخدمين عبر الدور، فيمكننا أن نرى مستخدمَين لهما المعرّف <code>id=3</code> والمعرّف <code>id=1</code> بالنسبة للدور ذي المعرّف <code>id=2</code>.
</p>

<h2 id="controller">
	طبقة المتحكم Controller
</h2>

<p>
	وضّحنا الوِجهات والعروض والنماذج وعلاقات قاعدة البيانات، وحان الوقت الآن لنتعرّف على الشيء الذي يربطها جميعًا مع بعضها البعض. تحدّثنا في المقال السابق عن الوِجهات، واستخدمنا المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1367_7" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/number/{num}'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$num</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'view'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'num'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $num</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	يبدو الأمر جيدًا في الأمثلة البسيطة، ولكن إذا كان لديك مشروع ضخم، فسيؤدي وضع كل الشيفرة البرمجية في ملف الوِجهة Route File إلى جعل الأمر فوضويًا جدًا، والحل الأفضل هو التأكّد من أن الوِجهة تؤشّر دائمًا إلى تابع في المتحكم مع وضع الشيفرة البرمجية ضمن هذا التابع.
</p>

<p>
	 
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1367_9" style=""><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\UserController</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/users/{name}'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">UserController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'show'</span><span class="pun">]);</span><span class="pln">
</span></pre>

<p>
	يمكن إنشاء متحكم جديد من خلال استخدام الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1367_11" style=""><span class="pln">php artisan make:controller UserController</span></pre>

<p>
	تُخزَّن ملفات متحكم لارافيل ضمن المجلد <code> app/Http/Controllers/‎</code>.
</p>

<h3>
	المتحكم الأساسي
</h3>

<p>
	لنلقِ نظرة على المثال التالي، حيث يتوقع التابع <code>show()‎</code> المتغير <code>‎$id</code>، ويستخدِم هذا المعرّف <code>id</code> لتحديد موقع المستخدم في قاعدة البيانات، ويعيد هذا المستخدم في العرض.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1367_13" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Models\User</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\View\View</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">UserController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * عرض الملف الشخصي لمستخدمٍ معين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> show</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $name</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'user.profile'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'user'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">User</span><span class="pun">::</span><span class="pln">firstWhere</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">,</span><span class="pln"> $name</span><span class="pun">);</span><span class="pln">
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تحتاج في بعض الأحيان إلى تعريف متحكم له تابع واحد فقط، ويمكننا في هذه الحالة تبسيط الشيفرة البرمجية من خلال تغيير اسم التابع إلى <code>‎_invoke.</code>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1367_15" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">UserController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __invoke</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $name</span><span class="pun">):</span><span class="pln"> </span><span class="typ">View</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'user.profile'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
           </span><span class="str">'user'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">User</span><span class="pun">::</span><span class="pln">firstWhere</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">,</span><span class="pln"> $name</span><span class="pun">);</span><span class="pln">
       </span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا حاجة الآن لتحديد اسم التابع في الوِجهة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1367_19" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/users/{id}'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">UserController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span></pre>

<h3>
	متحكم الموارد
</h3>

<p>
	المورد Resource هو مفهوم حديث آخر لتصميم الويب، حيث نرى جميع نماذج Eloquent بوصفها مواردًا، مما يعني أننا سنجري مجموعة الإجراءات نفسها عليها جميعًا، وهذه الإجراءات هي الإنشاء ‎<strong>C</strong>reate والقراءة ‎<strong>R</strong>ead والتحديث ‎<strong>U</strong>pdate والحذف ‎<strong>D</strong>elete -أو CRUD اختصارًا.
</p>

<p>
	يمكن إنشاء متحكم موارد من خلال استخدام الخيار <code>‎--resource</code> كما يلي:
</p>

<pre class="ipsCode" id="ips_uid_1367_26">php artisan make:controller PostController --resource
</pre>

<p>
	سيحتوي المتحكم الذي أنشأناه على التوابع التالية تلقائيًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1367_30" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\RedirectResponse</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Response</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PostController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * عرض قائمة الموارد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">():</span><span class="pln"> </span><span class="typ">Response</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">//</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عرض الاستمارة الخاصة بإنشاء مورد جديد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> create</span><span class="pun">():</span><span class="pln"> </span><span class="typ">Response</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">//</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * تخزين المورد الذي أنشأناه حديثًا في وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> store</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">//</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عرض المورد المُحدَّد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> show</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Response</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">//</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * عرض الاستمارة الخاصة بتعديل المورد المُحدَّد
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> edit</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Response</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">//</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * تحديث المورد المحدَّد في وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> update</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">//</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">

   </span><span class="com">/**
    * إزالة المورد المُحدَّد من وحدة التخزين
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> destroy</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $id</span><span class="pun">):</span><span class="pln"> </span><span class="typ">RedirectResponse</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="com">//</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تشرح التعليقات في الشيفرة البرمجية السابقة وظيفة التوابع والغرض منها.
</p>

<p>
	يقدّم لارافيل أيضًا طريقة سهلة جدًا لتسجيل الوِجهات لكل من التوابع السابقة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1367_32" style=""><span class="typ">Route</span><span class="pun">::</span><span class="pln">resource</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> </span><span class="typ">PostController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span></pre>

<p>
	ستَنشَأ الوِجهات التالية باستخدام توابع HTTP المختلفة تلقائيًا:
</p>

<table>
	<thead>
		<tr>
			<th>
				تابع HTTP
			</th>
			<th>
				مسار URI
			</th>
			<th>
				الإجراء
			</th>
			<th>
				اسم الوِجهة
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				GET ‏
			</td>
			<td>
				‎/posts ‏
			</td>
			<td>
				index ‏
			</td>
			<td>
				posts.index
			</td>
		</tr>
		<tr>
			<td>
				GET ‏
			</td>
			<td>
				‎/posts/create ‏
			</td>
			<td>
				create ‏
			</td>
			<td>
				posts.create
			</td>
		</tr>
		<tr>
			<td>
				POST ‏
			</td>
			<td>
				‎/posts ‏
			</td>
			<td>
				store ‏
			</td>
			<td>
				posts.store
			</td>
		</tr>
		<tr>
			<td>
				GET ‏
			</td>
			<td>
				‎/posts/{post}‎ ‏
			</td>
			<td>
				show ‏
			</td>
			<td>
				posts.show
			</td>
		</tr>
		<tr>
			<td>
				GET ‏
			</td>
			<td>
				‎/posts/{post}/edit ‏
			</td>
			<td>
				edit ‏
			</td>
			<td>
				posts.edit
			</td>
		</tr>
		<tr>
			<td>
				PUT/PATCH ‏
			</td>
			<td>
				‎/posts/{post}‎ ‏
			</td>
			<td>
				update ‏
			</td>
			<td>
				posts.update
			</td>
		</tr>
		<tr>
			<td>
				DELETE ‏
			</td>
			<td>
				‎/posts/{post}‎ ‏
			</td>
			<td>
				destroy ‏
			</td>
			<td>
				posts.destroy
			</td>
		</tr>
	</tbody>
</table>

<p>
	ترجمة -وبتصرُّف- للمقال <a href="https://www.ericsdevblog.com/posts/laravel-for-beginners-2/" rel="external nofollow">Laravel for Beginners #2 - The MVC Structure</a> لصاحبه Eric Hu.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-%D8%A7%D9%84%D8%A8%D8%AF%D8%A1-%D9%81%D9%8A-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2425/" rel="">لارافيل للمبتدئين-الجزء الأول: البدء في إنشاء مدونة بسيطة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D8%B4%D8%A6-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-query-builder-%D9%84%D9%84%D8%AA%D8%AE%D8%A7%D8%B7%D8%A8-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-r398/" rel="">كيف تستخدم منشئ الاستعلامات Query builder للتخاطب مع قاعدة البيانات في Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/" rel="">تعرف على إطار عمل تطوير الويب لارافيل Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AC%D8%B1%D9%8A%D8%AF-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D8%A8%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-migration-%D9%88%D8%A7%D9%84%D8%A8%D8%B0%D8%B1-seeder-r1725/" rel="">تجريد إعداد قواعد البيانات في لارافيل باستعمال عملية التهجير Migration والبذر Seeder</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%B9%D9%84%D8%A7%D9%82%D8%A7%D8%AA-eloquent-%D9%88%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D8%A7%D9%84%D8%AD%D8%AB%D9%8A%D8%AB-%D9%81%D9%8A-laravel-5-r193/" rel="">علاقات Eloquent والتحميل الحثيث في Laravel 5</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2426</guid><pubDate>Sun, 20 Oct 2024 15:08:01 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x648;&#x627;&#x62C;&#x647;&#x629; &#x623;&#x645;&#x627;&#x645;&#x64A;&#x629; &#x644;&#x645;&#x62F;&#x648;&#x646;&#x629; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A3%D9%85%D8%A7%D9%85%D9%8A%D8%A9-%D9%84%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-r2425/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2024_10/----------(1).png.0e8c3f323fcc643bd0c0a16ffdd3bfea.png" /></p>
<p>
	يُعَد لارافيل Laravel إطار ويب يستخدم لغة PHP، وهو مجاني ومفتوح المصدر ويُستخدَم على نطاق واسع لتطوير تطبيقات الويب، كما أنه معروف بصيغته الأنيقة وأدواته المُستخدَمة للمهام الشائعة مثل التوجيه Routing والاستيثاق Authentication والتخزين المؤقت أو التخبئة <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%AE%D8%A8%D8%A6%D8%A9-cache-%D9%81%D9%8A-laravel-r389/" rel="">Caching</a> وقدرته على التعامل مع حركة الزوار العالية.
</p>

<p>
	يتبع لارافيل معمارية نموذج-عرض-متحكم Model-View-Controller (أو MVC اختصارًا)، ويتضمن دعمًا مُدمجًا لربط الكائنات بالعلاقات Object-Relational Mapping (أو ORM اختصارًا) وباني الاستعلامات، مما يسهّل التفاعل مع قواعد البيانات.
</p>

<p>
	يضم لارافيل مجتمعًا كبيرًا ونشطًا يوفّر مجموعةً كبيرة من البرامج التعليمية والحزم والموارد الأخرى التي يمكن للمطورين استخدامها، إذ يُعَد لارافيل أحد <a href="https://academy.hsoub.com/programming/general/%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-framework/" rel="">أطر عمل</a> الويب الأكثر شعبية وقوة للغة <a href="https://academy.hsoub.com/php/" rel="">PHP</a>، وتثق به العديد من الشركات والمؤسسات لبناء تطبيقات ويب قوية وقابلة للتوسّع. سنشرح في هذا المقال الاستخدام الأساسي لإطار عمل لارافيل من خلال بناء نظام تدوين بسيط.
</p>

<p>
	<strong>ملاحظة</strong>: تعتمد هذه السلسلة من المقالات على الإصدار 11 من لارافيل.
</p>

<h2 id="-1">
	إنشاء مشروع لارافيل جديد
</h2>

<p>
	لا يُعَد إعداد بيئة تطوير <a href="https://academy.hsoub.com/programming/php/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%84%D8%BA%D8%A9-php-r2040" rel="">PHP</a> مهمة سهلة، وخاصة إذا استخدمت أنظمة لينكس Linux، ولكن قدّم لارافيل منذ الإصدار 8.0 أداة جديدة اسمها Sail، والتي توفر حلًا سهلًا لتشغيل تطبيقات <a href="https://academy.hsoub.com/programming/php/laravel/" rel="">لارافيل</a> من خلال استخدام أداة دوكر <a href="https://academy.hsoub.com/devops/cloud-computing/docker/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AF%D9%88%D9%83%D8%B1-docker-r607/" rel="">Docker</a> بغض النظر عن نظام التشغيل الذي تستخدمه، طالما أن هذه الأداة مُثبَّتة لديك.
</p>

<p>
	أنشئ أولًا مجلد عمل جديد بالاسم <code>laravel-tutorial</code> مثلًا، ثم افتحه في محرّر الأكواد الذي تفضله وليكن VS Code، ونفّذ الأمر الآتي لإنشاء مشروع لارافيل جديد، وتأكّد من تشغيل دوكر قبل تنفيذ هذا الأمر، إذ قد تستغرق هذه العملية من 5 إلى 10 دقائق حتى الاكتمال:
</p>

<pre class="ipsCode">curl -s https://laravel.build/&lt;app_name&gt; | bash
</pre>

<p>
	<strong>ملاحظة</strong>: إذا كنت تعمل على نظام ويندوز Windows، فتأكّد من تشغيل هذا الأمر ضمن نظام ويندوز الفرعي لنظام التشغيل لينكس WSL 2 الذي يسمح لك بتشغيل نواة Linux كاملة داخل ويندوز دون الحاجة إلى تثبيت نظام لينكس.
</p>

<p>
	ثانيًا، استخدم الأمر التالي للانتقال إلى مجلد التطبيق وشغّل الخادم:
</p>

<pre class="ipsCode">cd &lt;app_name&gt;
</pre>

<p>
	سيؤدي الأمر التالي إلى بدء حاوية دوكر بالإضافة إلى خادم تطوير لارافيل:
</p>

<pre class="ipsCode">./vendor/bin/sail up
</pre>

<p>
	يمكنك الوصول إلى تطبيق لارافيل على العنوان <code><a href="http://localhost/%E2%80%8E" ipsnoembed="true" rel="external nofollow">http://localhost/‎</a></code>، وإن لم يعمل هذا العنوان، فحاول الانتقال إلى العنوان <code>http://127.0.0.1/‎</code> بدلًا من ذلك، ثم يجب أن تشاهد صفحة ترحيب لارافيل التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159690" href="https://academy.hsoub.com/uploads/monthly_2024_10/01_laravel-welcome.png.1aeceebc66061b548d50633dcf5883fc.png" rel=""><img alt="صفحة-ترحيب-لارافيل" class="ipsImage ipsImage_thumbnailed" data-fileid="159690" data-ratio="61.23" data-unique="bds26zasc" style="width: 503px; height: auto;" width="900" src="https://academy.hsoub.com/uploads/monthly_2024_10/01_laravel-welcome.thumb.png.153d4bae751fb467c6c1e33f1beb8ac7.png"></a>
</p>

<h2 id="-2">
	استكشاف بنية تطبيق لارافيل
</h2>

<p>
	لنلقِ نظرة على المجلدات والملفات التي تنشأ ضمن مشروعنا قبل أن نبدأ ببرمجته، لذا إليك نظرة عامة على المجلد الجذر للمشروع:
</p>

<pre class="ipsCode">.
├── app
│   ├── Console
│   ├── Exceptions
│   ├── Http
│   │   ├── Controllers
│   │   └── Middleware
│   ├── Models
│   └── Providers
├── bootstrap
├── config
├── database
│   ├── factories
│   ├── migrations
│   └── seeders
├── public
├── resources
│   ├── css
│   ├── js
│   └── views
├── routes
├── storage
│   ├── app
│   ├── framework
│   └── logs
├── tests
│   ├── Feature
│   └── Unit
└── vendor
</pre>

<ul>
	<li>
		المجلد <code>app</code>: يُعَد هذا المجلد المكون الأساسي لمشروعنا، ويحتوي على مجلدات متعددة من أهمها مجلد المتحكمات <code>controllers</code> والبرمجيات الوسيطة <code>middleware</code> والنماذج <code>models</code>، حيث يعرّف المتحكم الشيفرة البرمجية الأساسية للتطبيق، وتعرّف البرمجيات الوسيطة الإجراءات التي يجب اتخاذها قبل استدعاء المتحكم، ويوفّر النموذج واجهة تسمح لنا بالتعامل مع قواعد البيانات، إذ سنتحدث عن كل منها بالتفصيل لاحقًا.
	</li>
	<li>
		المجلد <code>bootstrap</code>: يحتوي هذا المجلد على الملف <code>app.php</code> الذي يشغّل المشروع بأكمله، ولا حاجة لتعديل أيّ شيء في هذا المجلد.
	</li>
	<li>
		المجلد <code>config</code>: يحتوي على ملفات الضبط Configuration كما يدل اسمه، ولا حاجة للاهتمام بهذا الضبط في هذه السلسلة من المقالات.
	</li>
	<li>
		المجلد <code>database</code>: يحتوي على ملفات التهجير <code>migrations</code> والمصانع <code>factories</code> والبذور <code>seeds</code>، حيث تصف ملفات التهجير بنية قاعدة البيانات، وتُعَد ملفات المصانع والبذور طريقتين مختلفتين يمكننا من خلالهما ملء قاعدة البيانات ببيانات وهمية في لارافيل.
	</li>
	<li>
		المجلد <code>public</code>: يحتوي على الملف <code>index.php</code> الذي يُعَد نقطة الدخول إلى لتطبيق.
	</li>
	<li>
		المجلد <code>resources</code>: يحتوي على ملفات العرض <code>views</code> التي تمثّل جزء الواجهة الأمامية من تطبيق لارافيل.
	</li>
	<li>
		المجلد <code>routes</code>: يحتوي على جميع الموجّهات Routers لعناوين URL للمشروع فعندما ترسل طلب إلى عنوان URL محدد، سيتوجه الطلب إلى المُوجِّه المناسب بناءً على الوجهات التي تحددها الملفات ضمن هذا المجلد.
	</li>
	<li>
		المجلد <code>storage</code>: هو مساحة تخزين المشروع بأكمله، ويحتوي على السجلات <code>logs</code> والعروض المُصرَّفة Compiled Views بالإضافة إلى الملفات التي رفعها المستخدم.
	</li>
	<li>
		المجلد <code>tests</code>: يحتوي على ملفات الاختبار، حيث يُعَد الاختبار مفهومًا أكثر تقدمًا نسبيًا في لارافيل، لذلك لن نوضّحه في هذه السلسلة من المقالات، ولكن يمكنك الاطلاع على مقال <a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-phpunit-%D9%84%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-r296/" rel="">كيفية استخدام PHPUnit لاختبار تطبيقات لارافيل</a> لمزيد من التفاصيل حول الاختبارات.
	</li>
	<li>
		المجلد <code>vendor</code>: يتضمن جميع الاعتماديات Dependencies.
	</li>
</ul>

<h2 id="-3">
	متغيرات البيئة
</h2>

<p>
	سنلقي نظرة أيضًا على متغيرات البيئة التي تُخزَّن في ملف <code>‎.env</code>، حيث أُعِدت الكثير من عمليات الضبط افتراضيًا عندما أنشأنا مشروعنا باستخدام أداة Sail في لارافيل، ولكننا سنتحدث عن عملها فيما يلي.
</p>

<h3 id="app_url">
	المتغير APP_URL
</h3>

<p>
	يحدّد المتغير <code>APP_URL</code> عنوان URL للتطبيق، ويكون هذا العنوان هو <code><a href="http://localhost" ipsnoembed="true" rel="external nofollow">http://localhost</a></code> افتراضيًا، ولكن قد تحتاج إلى تغييره إلى العنوان <code>http://127.0.0.1</code> عندما يعطي العنوانُ <code>http://127.0.0.1</code> صفحةَ خادم Apache2 الافتراضية.
</p>

<pre class="ipsCode">APP_URL=http://127.0.0.1
</pre>

<p>
	أو:
</p>

<pre class="ipsCode">APP_URL=http://localhost
</pre>

<h3 id="-4">
	قاعدة البيانات
</h3>

<p>
	ستثبّت أداة Sail من لارافيل نظامَ إدارة قواعد البيانات <a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D8%AA%D8%B9%D9%84%D9%85-%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-mysql-r297/" rel="">MySQL</a> بوصفه التطبيق الخاص بقاعدة البيانات، وتُعرَّف اتصالات قاعدة البيانات كما يلي:
</p>

<pre class="ipsCode">DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=curl_demo
DB_USERNAME=sail
DB_PASSWORD=password
</pre>

<p>
	يمكنك أيضًا تعريف متغيرات بيئة خاصة بك إن احتجت إليها كما يلي، ثم يمكنك الوصول إليها في أي مكان من المشروع:
</p>

<pre class="ipsCode">CUSTOM_VARIABLE=true
</pre>

<p>
	ويمكن الوصول إلى هذا المتغير كما يلي:
</p>

<pre class="ipsCode">env('CUSTOM_VARIABLE', true)
</pre>

<p>
	يمثّل المعامل الثاني القيمة الافتراضية لهذا المتغير، حيث إن لم يكن المتغير <code>CUSTOM_VARIABLE</code> موجودًا، فسيُعاد المعامل الثاني.
</p>

<h2 id="routing">
	أساسيات التوجيه Routing في لارافيل
</h2>

<p>
	سنلقي نظرة في هذا القسم على وِجهات Route لارافيل وبرمجياتها الوسيطة، حيث تُعرَّف الوِجهات في المجلد <code>routes</code>. لاحظ وجود أربعة ملفات مختلفة في المجلد <code>routes</code> افتراضيًا، ولكن ما يهمنا الملفان <code>api.php</code> و <code>web.php</code> بالنسبة لمعظم المشاريع.
</p>

<p>
	إذا أردت استخدام لارافيل بطريقة صارمة مع الواجهة الخلفية (بدون العرض)، فيجب أن تحدّد الوِجهات في الملف <code>api.php</code>، ولكننا سنستخدم في هذا المقال لارافيل بوصفه إطار عمل متكامل full-stack، لذلك سنستخدم الملف <code>web.php</code> بدلًا من ذلك.
</p>

<p>
	الفرق بين هذين الملفين هو أن الملف <code>api.php</code> تغلِّفه مجموعة برمجيات <code>api</code> الوسيطة وأن الملف <code>web.php</code> موجود ضمن مجموعة برمجيات <code>web</code> الوسيطة، ويوفر هذان الملفان دوالًا مختلفة، وسيكون للوِجهات المحددة في الملف <code>api.php</code> بادئة عنوان URL التي هي <code>/api/</code>، وبالتالي يجب أن يكون عنوان URL مثل العنوان: <code><a href="http://example.com/api/somthing-else" ipsnoembed="true" rel="external nofollow">http://example.com/api/somthing-else</a></code> للوصول إلى وِجهة <code>api</code>.
</p>

<p>
	تقبل الوِجهة الأساسية في لارافيل عنوان URL ثم تعيد قيمة، حيث يمكن أن تكون هذه القيمة سلسلة نصية أو عرضًا أو متحكمًا. انتقل إلى الملف <code>routes/web.php</code>، وسترى أن هناك وِجهة مُعرَّفة مسبقًا هي: <code>routes/web.php</code>. يخبرنا الجزء التالي من الشيفرة البرمجية أنه إذا استقبل لارافيل الوِجهة "<code>/</code>"، فسيعيد عرضًا بالاسم "<code>welcome</code>"، والذي يقع في <code>resources/views/welcome.blade.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_11" style=""><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Route</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'welcome'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	افتح المتصفح، وانتقل إلى العنوان <code>http://127.0.0.1:8000</code>، وستحصل على الصفحة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159690" href="https://academy.hsoub.com/uploads/monthly_2024_10/01_laravel-welcome.png.1aeceebc66061b548d50633dcf5883fc.png" rel=""><img alt="صفحة-ترحيب-لارافيل" class="ipsImage ipsImage_thumbnailed" data-fileid="159690" data-ratio="61.23" data-unique="bds26zasc" style="width: 503px; height: auto;" width="900" src="https://academy.hsoub.com/uploads/monthly_2024_10/01_laravel-welcome.thumb.png.153d4bae751fb467c6c1e33f1beb8ac7.png"></a>
</p>

<p>
	يمكن التحقق من أن <code>welcome.blade.php</code> هو العرض الظاهر من خلال إجراء بعض التغييرات على الملف، ثم تحديث متصفحك للتأكد من تغيير الصفحة.
</p>

<h3 id="-5">
	توابع الموجهات
</h3>

<p>
	لنلقِ الآن نظرة على الموجِّه التالي في <code>routes/web.php</code> ونفهم كيفية عمله:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_13" style=""><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Route</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'welcome'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	نستورد أولًا الصنف <code>Route</code> ونستدعي التابع <code>get()‎</code>، حيث يتطابق هذا التابع مع تابع HTTP الذي هو <code>GET</code>، وهناك توابع أخرى مُضمَّنة في الصنف <code>Route</code>، حيث تتطابق هذه التوابع مع توابع <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-http-%D8%B4%D8%B1%D8%AD-%D8%A7%D9%84%D8%AA%D8%AE%D8%A7%D8%B7%D8%A8-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%B9%D9%85%D9%8A%D9%84-%D9%88%D8%A7%D9%84%D8%AE%D8%A7%D8%AF%D9%85-r74/" rel="">طلبات HTTP</a> الأخرى كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_15" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="pln">$uri</span><span class="pun">,</span><span class="pln"> $callback</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">post</span><span class="pun">(</span><span class="pln">$uri</span><span class="pun">,</span><span class="pln"> $callback</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">put</span><span class="pun">(</span><span class="pln">$uri</span><span class="pun">,</span><span class="pln"> $callback</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">patch</span><span class="pun">(</span><span class="pln">$uri</span><span class="pun">,</span><span class="pln"> $callback</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">delete</span><span class="pun">(</span><span class="pln">$uri</span><span class="pun">,</span><span class="pln"> $callback</span><span class="pun">);</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">options</span><span class="pun">(</span><span class="pln">$uri</span><span class="pun">,</span><span class="pln"> $callback</span><span class="pun">);</span></pre>

<p>
	إذا أردتَ أن تطابق الوِجهة بين توابع HTTP متعددة، فيمكنك استخدام تابع <code>match</code> أو <code>any</code> بدلًا من ذلك، حيث يتطلب التابع <code>match()‎</code> تحديد مصفوفة توابع HTTP التي ترغب في مطابقتها، ويطابق التابع <code>any()‎</code> ببساطة بين جميع طلبات HTTP.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_18" style=""><span class="typ">Route</span><span class="pun">::</span><span class="pln">match</span><span class="pun">([</span><span class="str">'get'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'post'</span><span class="pun">],</span><span class="pln"> </span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">any</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">});</span></pre>

<h3 id="-6">
	تمرير البيانات إلى العرض
</h3>

<p>
	يحتوي التابع <code>get()‎</code> على معاملَين هما: المعامل الأول هو عنوان URL الذي يُفترَض أن يطابقه الموجِّه، والمعامل الثاني هو دالة رد النداء Callback التي تُنفَّذ عند نجاح المطابقة. تُعاد الدالة <code>view()‎</code> المُضمَّنة ضمن دالة رد النداء، حيث ستبحث هذه الدالة عن ملف العرض المقابل بناءً على المعامل المُمرَّر إليها.
</p>

<p>
	يقدم لارافيل اختصارًا بسيطًا هو <code>Route::view()‎</code> إذا أردتَ إعادة عرض فقط، حيث يسمح لك هذا التابع بتجنب كتابة وِجهة كاملة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_20" style=""><span class="typ">Route</span><span class="pun">::</span><span class="pln">view</span><span class="pun">(</span><span class="str">'/welcome'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'welcome'</span><span class="pun">);</span></pre>

<p>
	الوسيط الأول لهذا التابع هو عنوان URL، والمعامل الثاني هو العرض المقابل، ويوجد أيضًا وسيط ثالث يسمح بتمرير بعض البيانات إلى هذا العرض كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_22" style=""><span class="typ">Route</span><span class="pun">::</span><span class="pln">view</span><span class="pun">(</span><span class="str">'/welcome'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'welcome'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Taylor'</span><span class="pun">]);</span></pre>

<p>
	سنتحدث عن كيفية الوصول إلى البيانات عندما نصل إلى <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%84%D8%A8-blade-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B9%D8%B1%D9%88%D8%B6-laravel-r220/" rel="">قوالب Blade</a>.
</p>

<h3 id="-7">
	من الموجه إلى المتحكم
</h3>

<p>
	يمكن أن نجعل الموجّه يؤشّر إلى المتحكم الذي يؤشّر بدوره إلى العرض، فالمتحكم هو أساسًا نسخة موسعة من دالة رد النداء، حيث سنتحدث عن المتحكمات بالتفصيل في المقال التالي. يخبرنا سطر الشيفرة البرمجية التالي أنه إذا استقبل الموجّه الوِجهة "<code>‎/user</code>"، فسيذهب لارافيل إلى الصنف <code>UserController</code>، ويستدعي التابع <code>index</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_25" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/user'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">UserController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'index'</span><span class="pun">]);</span></pre>

<h3 id="-8">
	معاملات الوجهة
</h3>

<p>
	تحتاج في بعض الأحيان إلى استخدام أجزاء من عنوان URL بوصفها معاملات، فمثلًا لنفترض أن لدينا مدونة مطورة بالكامل، ويوجد مستخدم يبحث عن منشور في المدونة له الاسم Slug الموجود في الرابط <code>this-is-a-post</code>، ويحاول العثور على هذا المنشور من خلال كتابة <code><a href="http://www.example.com/posts/this-is-a-post" ipsnoembed="true" rel="external nofollow">http://www.example.com/posts/this-is-a-post</a></code> في متصفحه.
</p>

<p>
	يمكن التأكد من أن المستخدم قد عثر على المنشور الصحيح من خلال أخذ الجزء الموجود بعد <code>posts/‎</code> كمعامل وإرساله إلى الواجهة الخلفية، ثم يمكن للمتحكم استخدام هذا المعامل للعثور على المنشور الصحيح وإعادته إلى المستخدم، حيث يمكنك تطبيق ذلك من خلال كتابة الشيفرة البرمجية التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_27" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'post/{slug}'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">PostController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'show'</span><span class="pun">]);</span></pre>

<p>
	سيتأكد السطر السابق من أن موجّه لارافيل يطابق الكلمة الموجودة بعد <code>post/‎</code> كمعامل، ويسندها إلى المتغير <code>slug</code> عندما يرسلها لارافيل إلى الواجهة الخلفية. تُضمَّن معاملات الصنف <code>Route</code> دائمًا بين قوسين <code>{}</code> ويجب أن تتكون من أحرف أبجدية، ولا يجوز أن تحتوي على المحرف <code>-</code>.
</p>

<p>
	بما أننا لم نذكر المتحكمات في مثالنا، فيمكننا وضع دالة رد نداء بسيطة مكان المعامل الثاني واختبار الشيفرة البرمجية التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_29" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/post/{slug}'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$slug</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> $slug</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	افتح الآن متصفحك وانتقل إلى العنوان <code>http://127.0.0.1:8000/posts/this-is-a-slug</code>، وستظهر الصفحة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="159691" href="https://academy.hsoub.com/uploads/monthly_2024_10/02_router-parameters.png.b2e812eedd1180fb48319fd62bac7fbb.png" rel=""><img alt="02_router-parameters.png" class="ipsImage ipsImage_thumbnailed" data-fileid="159691" data-ratio="22.78" data-unique="kntdhiljb" style="width: 500px; height: auto;" width="900" src="https://academy.hsoub.com/uploads/monthly_2024_10/02_router-parameters.thumb.png.e63496b1580b5b6936d723d692b7c815.png"></a>
</p>

<p>
	يمكن أيضًا مطابقة معاملات متعددة في عنوان URL كما يلي:
</p>

<pre class="ipsCode">Route::get('category/{category}/post/{slug}', [PostController::class, 'show']);
</pre>

<p>
	سيُسنَد الجزء الموجود بعد <code>category/‎</code> إلى المتغير <code>category</code> في هذه الحالة، وسيُسنَد الجزء الموجود بعد <code>post/‎</code> إلى المتغير <code>slug</code>.
</p>

<p>
	لا تعرف في بعض الأحيان ما إذا كان المعامل موجودًا في عنوان URL، وبالتالي يمكنك جعل هذا المعامل اختياريًا من خلال إلحاقه بإشارة استفهام (<code>?</code>) كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_31" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'post/{slug?}'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">PostController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'show'</span><span class="pun">]);</span></pre>

<p>
	وأخيرًا، يمكنك التحقق من صحة المعاملات باستخدام <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D9%86%D9%85%D8%B7%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1374/" rel="">التعابير النمطية</a> Regular Expressions، فمثلًا يمكنك التأكد من أن معرّف المستخدم هو عدد دائمًا كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_34" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'user/{id}'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">UserController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'show'</span><span class="pun">])-&gt;</span><span class="kwd">where</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'[0-9]+'</span><span class="pun">);</span></pre>

<h3 id="-9">
	الموجهات المسماة
</h3>

<p>
	تسمح الوِجهات المُسماة بإنشاء عناوين URL أو إعادة التوجيه بصورة مناسبة إلى وِجهات محددة، حيث يمكنك تحديد اسمٍ لوِجهة من خلال إضافة التابع <code>name</code> إلى سلسلة تعريف الوِجهة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_36" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'user/profile'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">UserController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'show'</span><span class="pun">])-&gt;</span><span class="pln">name</span><span class="pun">(</span><span class="str">'profile'</span><span class="pun">);</span></pre>

<p>
	وبالتالي إذا احتجت إلى الوصول إلى عنوان URL هذا، فيجب أن تستدعي الدالة <code>route('profile')‎</code> فقط.
</p>

<h3 id="-10">
	تجميع الموجهات
</h3>

<p>
	إذا أردت إنشاء موقع ويب كبير، فيجب أن يكون لديك عشرات أو حتى مئات من الموجّهات، وبالتالي من المنطقي أن تجمّعها مع بعضها بعضًا، فمثلًا يمكنك تجميعها بناءً على البرمجيات الوسيطة <code>middleware</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_38" style=""><span class="typ">Route</span><span class="pun">::</span><span class="pln">middleware</span><span class="pun">([</span><span class="str">'auth'</span><span class="pun">])-&gt;</span><span class="kwd">group</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/user/profile'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">UserController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'show'</span><span class="pun">]);</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/user/setting'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">UserController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'setting'</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	وستُسنَد الآن البرمجية الوسيطة <code>auth</code> إلى الموجّهَين.
</p>

<p>
	يمكنك أيضًا إسناد بادئات Prefixes إلى مجموعة من الموجّهات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_40" style=""><span class="typ">Route</span><span class="pun">::</span><span class="pln">prefix</span><span class="pun">(</span><span class="str">'admin'</span><span class="pun">)-&gt;</span><span class="kwd">group</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/users'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="typ">UserController</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln"> </span><span class="str">'show'</span><span class="pun">]);</span><span class="pln">
   </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	سيكون لجميع الموجّهات المحدّدة في هذه المجموعة البادئة <code>/admin/</code>.
</p>

<h2 id="middleware">
	البرمجيات الوسيطة Middleware
</h2>

<p>
	البرمجية الوسيطة هي شيء يمكنه فحص وترشيح طلبات HTTP الواردة قبل أن تصل إلى تطبيقك، ويحدث بعد أن تطابق الوِجهة عنوان URL دون تنفيذ دالة رد النداء، وبالتالي هي شيء موجود في منطقة وسطى، ومن هنا جاءت تسميتها بالبرمجيات الوسيطة. يُعَد <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D9%8A%D8%AB%D8%A7%D9%82-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D9%8A%D9%86-user-authentication-%D9%81%D9%8A-laravel-5-r229/" rel="">استيثاق المستخدم</a> User Authentication من أمثلة البرمجيات الوسيطة، حيث إذا كان المستخدم مُستوثَقًا، فستأخذ الوِجهة هذا المستخدم إلى الهدف المفترض، وإن لم يكن الأمر كذلك، فستأخذ المستخدم إلى صفحة تسجيل الدخول أولًا.
</p>

<p>
	لن نكتب أيّ برمجيات وسيطة في هذه السلسلة من المقالات، ولكن البرمجية الوسيطة الوحيدة التي نحتاج إلى استخدامها هي البرمجية الوسيطة <code>auth</code> المُضمَّنة لأغراض الاستيثاق، والتي سنشرح أساسياتها. ننشئ برمجية وسيطة من خلال تشغيل الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_43" style=""><span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">middleware </span><span class="typ">EnsureTokenIsValid</span></pre>

<p>
	مما سيؤدي إلى إنشاء صنف <code>EnsureTokenIsValid</code> جديد ضمن المجلد <code>app/Http/Middleware</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_45" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Middleware</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Closure</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">EnsureTokenIsValid</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="com">/**
    * معالجة الطلب الوارد
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Closure  $next
    * @return mixed
    */</span><span class="pln">
   </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> handle</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Closure</span><span class="pln"> $next</span><span class="pun">)</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'token'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">!==</span><span class="pln"> </span><span class="str">'my-secret-token'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
           </span><span class="kwd">return</span><span class="pln"> redirect</span><span class="pun">(</span><span class="str">'home'</span><span class="pun">);</span><span class="pln">
       </span><span class="pun">}</span><span class="pln">

       </span><span class="kwd">return</span><span class="pln"> $next</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">);</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ستحصل هذه البرمجيات الوسيطة على قيمة المفتاح Token من الطلب، وتقارنها مع المفتاح السري المُخزَّن على موقعنا، حيث إذا كان مطابقًا، فانتقل إلى الخطوة التالية، وإذا لم يكن كذلك، فأعِد التوجيه إلى الصفحة الرئيسية. يمكنك استخدام هذه البرمجية الوسيطة من خلال تسجيلها في لارافيل، لذا انتقل إلى الملف <code>app/Http/Kernel.php</code>، وابحث عن الخاصية <code>‎$routeMiddleware</code>، وأدرِج البرمجية الوسيطة التي أنشأناها.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_47" style=""><span class="com">/**
 * البرمجيات الوسيطة لوِجهات التطبيق
 *
 * يمكن إسناد هذه البرمجيات الوسيطة إلى مجموعات أو استخدامها بصورة فردية
 *
 * @var array&lt;string, class-string|string&gt;
**/</span><span class="pln">
 </span><span class="kwd">protected</span><span class="pln"> $routeMiddleware </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
   </span><span class="str">'auth'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> \App\Http\Middleware\Authenticate</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
   </span><span class="str">'auth.basic'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
   </span><span class="str">'cache.headers'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> \Illuminate\Http\Middleware\SetCacheHeaders</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
   </span><span class="str">'can'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> \Illuminate\Auth\Middleware\Authorize</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
   </span><span class="str">'guest'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> \App\Http\Middleware\RedirectIfAuthenticated</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
   </span><span class="str">'password.confirm'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> \Illuminate\Auth\Middleware\RequirePassword</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
   </span><span class="str">'signed'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> \Illuminate\Routing\Middleware\ValidateSignature</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
   </span><span class="str">'throttle'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> \Illuminate\Routing\Middleware\ThrottleRequests</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
   </span><span class="str">'verified'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> \Illuminate\Auth\Middleware\EnsureEmailIsVerified</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span><span class="pln">
 </span><span class="pun">];</span></pre>

<p>
	وأخيرًا، تعرّفنا سابقًا على كيفية استخدام البرمجيات الوسيطة مع الموجّه كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4181_49" style=""><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/profile'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{.</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="pun">.})-&gt;</span><span class="pln">middleware</span><span class="pun">(</span><span class="str">'auth'</span><span class="pun">);</span></pre>

<p>
	ترجمة -وبتصرُّف- للمقال <a href="https://www.ericsdevblog.com/posts/laravel-for-beginners-1/" rel="external nofollow">Laravel for Beginners #1 - Getting Started</a> لصاحبه Eric Hu.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%B4%D9%87%D9%8A%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/" rel="">تعرف على إطار عمل تطوير الويب لارافيل Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%A8%D9%8A%D9%86-django-%D9%88-laravel-%D9%88-rails-r634/" rel="">مقارنة بين Django و Laravel و Rails</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-laravel-5-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D9%87-%D8%B9%D9%84%D9%89-windows-%D9%88ubuntu-r212/" rel="">تثبيت لارافيل وإعداده على Windows وUbuntu</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-r231/" rel="">إنشاء مدونة باستخدام Laravel 5</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2425</guid><pubDate>Fri, 11 Oct 2024 15:00:00 +0000</pubDate></item><item><title>&#x62A;&#x639;&#x631;&#x641; &#x639;&#x644;&#x649; &#x625;&#x637;&#x627;&#x631; &#x639;&#x645;&#x644; &#x62A;&#x637;&#x648;&#x64A;&#x631; &#x627;&#x644;&#x648;&#x64A;&#x628; &#x627;&#x644;&#x634;&#x647;&#x64A;&#x631; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%B4%D9%87%D9%8A%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2093/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_08/---Laravel-------PHP2.png.f9f2c2c6d7057cbdab37e1555c894057.png" /></p>
<p>
	يعد إطار عمل لارافيل Laravel واحدًا من أهم أطر عمل PHP وأكثرها شهرة وقوة، فقد تمكن لارافيل من إثبات جدارته واحتلال مواقع متصدرة بين نظم تطوير تطبيقات الويب لما يتمتع به من ميزات أبرزها توفير الكثير من الوظائف البرمجية الجاهزة التي تجعل تطوير الويب أسهل وأسرع، واهتمامه الخاص بأمن مواقع الويب وحمايتها من الثغرات الأمنية.
</p>

<p>
	فإذا كنت تتساءل ما هو لارافيل Laravel وما فوائد استخدامه، وترغب في التعرف على أبرز مميزاته وعيوبه، واكتشاف أفضل المصادر العربية التي تمكنك من تعلم لارافيل واستخدامه في إنشاء مواقع وتطبيقات ويب بميزات متقدمة فهذا المقال لك.
</p>

<h2>
	ما هو لارافيل Laravel
</h2>

<p>
	<strong>لارافيل Laravel</strong> هو إطار عمل مفتوح المصدر مبني على لغة PHP يستخدم لتطوير تطبيقات الويب، طوره تايلور أوتويل Taylor Otwell عام 2011 ليمكّن المطورين من إنشاء تطبيقات ويب متكاملة الميزات بسهولة وسرعة من خلال توفير أكثر المهام والوظائف الشائعة التي يحتاجونها في مشاريع الويب.
</p>

<p>
	وإطار العمل Framework هو باختصار بيئة توفر مجموعة من الوظائف والأدوات الجاهزة المكتوبة مسبقًا والتي يستخدمها المبرمجون والمطورون لتسهل عليه عملهم في التطوير وتمكنهم من أداء المطلوب باستخدام أقل قدر من التعليمات البرمجية، وللمزيد من المعلومات أنصح بالاطلاع على مقال <a href="https://academy.hsoub.com/programming/general/%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-framework/" rel="">تعرف على مفهوم إطار العمل Framework وأهميته في البرمجة</a>
</p>

<p>
	لقد عزز إطار العمل لارافيل من قوة <a href="https://academy.hsoub.com/programming/php/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%84%D8%BA%D8%A9-php-r2040/" rel="">لغة PHP</a> وساهم في استمراريتها وديمومتها، حيث أنه وفر للمبرمجين طريقة أكثر كفاءة في التعامل معها وبسّط كتابة تعليماتها المعقدة نوعًا ما وجعل تطوير تطبيقات الويب باستخدامها أسرع وأسهل.
</p>

<h2>
	إصدارات لارافيل Laravel
</h2>

<p>
	قبل إصدار لارافيل 9 كان فريق لارافيل يوفر إصدارًا رئيسيًا كل ستة أشهر بمعدل نسختين رئيسيتين سنويًا لتخفيف أعباء الصيانة، لكن تقرر بعد ذلك توفير الإصدارات الجديدة بشكل سنوي.
</p>

<p>
	يتطور لارافيل Laravel بسرعة فائقة مع مرور الوقت ويضيف تحسينات وميزات ووظائف جديدة تواكب اتجاهات السوق المتغيرة باستمرار أو يغير بعض الوظائف أو يلغيها لذلك من الضروري معرفة الإصدار الذي تستخدمه في تطوير مشاريعك.
</p>

<p>
	وإليك قائمة بأهم إصدارات لارافيل laravel وتاريخ صدورها:
</p>

<ul>
	<li>
		أطلق الإصدار الأول لارافيل 1.0 في 9 يونيو/حزيران 2011
	</li>
	<li>
		توالت بعدها الإصدارات لغاية لارافيل 8 الذي تم إطلاقه في 8 سبتمبر/أيلول 2020 وهو الإصدار العشرين من Laravel ولم تعد كافة هذه الإصدارات تتلقى تحديثات أمنية لذا يفضل أن تتم ترقية التطبيقات المبنية بأحدها لإصدار أحدث لمنع الثغرات الأمنية والوصول إلى الميزات الجديدة.
	</li>
	<li>
		صدر لارافيل 9 بتاريخ 8 فبراير 2022 ويتطلب هذا الإصدار نسخة PHP 8.0 كحد أدنى.
	</li>
	<li>
		صدر لارافيل 10 بتاريخ 7 فبراير 2023 وتضمن العديد من الميزات الجديدة التي تعزز أداء تطبيقات الويب وأمانها ووظائفها ويتطلب هذا الإصدار نسخة 8.1 من لغة PHP كحد أدنى.
	</li>
</ul>

<p>
	ومن المتوقع أن يصدر لارافيل 11 في الربع الأول من عام 2024، وللمزيد من التفاصيل يمكنك مطالعة <a href="https://laravelversions.com/ar" rel="external nofollow" target="_blank">الصفحة التالية لكافة إصدارات لارافيل</a>، والجدير بالذكر أن لارافيل قد أثبت كفاءته لأكثر من عقد من الزمن وتمكن من فرض نفسه كأحد أكثر أطر PHP شيوعًا وتفضيلًا من قبل مطوري الويب بفضل طريقة تنظيمه الأنيقة وميزاته القوية.
</p>

<h2>
	أهمية إطار لارافيل في سوق العمل
</h2>

<p>
	يعد لارافيل أحد أشهر أطر عمل PHP وأكثرها استخدامًا ويملك مجتمعًا كبيرًا من المطورين الذين يوفرون الكثير من المكتبات والحزم الجاهزة والمتاحة للاستخدام بسهولة. كما يعد لارافيل أحد المهارات المطلوبة بشدة في سوق العمل، ويبحث الكثير من أرباب العمل عن مطورين محترفين في استخدام إطار العمل لارافيل لتطوير تطبيقاتهم ومواقعهم الإلكترونية ولا عجب في ذلك فهو واحد من أسرع أطر عمل PHP نموًا وأكثرها غنىً بالميزات.
</p>

<p>
	وتستخدم العديد من المواقع الكبرى لارافيل في تطوير تطبيقاتها الخاصة،فبحسب موقع <a href="https://trends.builtwith.com/" rel="external nofollow" target="_blank">builtwith</a> الذي يحدد التقنيات المستخدمة في إنشاء المواقع هناك 1,175,772 موقع ويب مبني باستخدام إطار عمل Laravel ولك أن تتخيل مدى شعبيته.
</p>

<p>
	كما يلبي لارافيل كافة متطلبات العمل لكونه يعتمد على لغة PHP العريقة التي تعد واحدة من أقوى لغات البرمجة من جانب الخادم والتي تستخدم في تطوير ملايين المواقع الإلكترونية من بينها مواقع شهيرة مثل فيسبوك وويكيبيديا.
</p>

<p>
	فإذا كنت مهتمًا بمجال تطوير الويب فتعلم إطار عمل لارافيل Laravel يوفر لك الكثير من الفرص المميزة في مجال تطوير تطبيقات الويب ويمكنك من إنشاء كافة أنواع التطبيقات والمواقع الإلكترونية سواء المواقع البسيطة للشركات الناشئة منها أو المواقع المتقدمة كمواقع التجارة الإلكترونية بسرعة واحترافية.
</p>

<p>
	ويتنافس إطار عمل لارافيل مع أطر عمل تطوير الويب الأخرى في سوق العمل مثل جانغو <a href="https://academy.hsoub.com/programming/python/django/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%B9%D9%85%D9%84-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%AC%D8%A7%D9%86%D8%BA%D9%88-django-r2041/" rel="">Django</a> المبني باستخدام لغة البرمجة بايثون <a href="https://wiki.hsoub.com/Python" rel="external" target="_blank">Python</a> والتي تعتبر أسرع من لغة PHP وأكثر شعبية منها، وإطار عمل إكسبريس <a href="https://academy.hsoub.com/programming/javascript/nodejs/express/" rel="">Express</a> المبني باستخدام لغة <a href="https://wiki.hsoub.com/JavaScript" rel="external" target="_blank">جافا سكريبت</a> أحد أكثر لغات البرمجة شهرة واستخدامًا بين أوساط المطورين، وإطار عمل ريلز <a href="https://academy.hsoub.com/programming/ruby/rails/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-ruby-on-rails-r526/" rel="">Rails</a> المبني باستخدام لغة البرمجة روبي <a href="https://wiki.hsoub.com/Ruby" rel="external" target="_blank">Ruby</a> المحببة للمبتدئين، تقدم معظم أطر العمل ميزات متشابهة وكي تتمكن من اختيار إطار العمل الأنسب لك عليك أن تأخذ عدة أمور بعين الاعتبار مثل لغة البرمجة التي تفضل تعلمها وطبيعة المشاريع التي تعمل عليها، ولمزيد من التفاصيل حول أشهر أطر عمل تطوير الويب أنصح بمطالعة مقال <a href="https://academy.hsoub.com/programming/general/%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%A8%D9%8A%D9%86-django-%D9%88-laravel-%D9%88-rails-r634/" rel="">مقارنة بين Django و Laravel و Rails</a>.
</p>

<h2>
	مميزات لارافيل Laravel
</h2>

<p>
	لاشك أن لارافيل Laravel ليس إطار العمل الوحيد المتاح اليوم بل هو واحد من بين عشرات أطر عمل تطوير الويب، وقد تتساءل لماذا أستخدم لارافيل دونًا عن غيره؟ وما الذي يميزه عن غيره من أطر عمل تطوير الويب؟
</p>

<p>
	في الواقع نجد تحيز من قبل المبرمجين لاختيار لارافيل دون غيره نظرًا لما يتمتع به من ميزات، وإليك قائمة بأهم 10 مميزات لإطار لارافيل:
</p>

<ol>
	<li>
		سهولة التعلم والاستخدام.
	</li>
	<li>
		تسريع وقت التطوير.
	</li>
	<li>
		التوثيق الجيد.
	</li>
	<li>
		غني بالميزات وقابل للتوسيع.
	</li>
	<li>
		يهتم بأمان التطبيقات.
	</li>
	<li>
		يحسن أداء التطبيقات.
	</li>
	<li>
		يدعم تعدد اللغات.
	</li>
	<li>
		يسهل تصحيح أخطاء التطبيقات وصيانتها.
	</li>
	<li>
		يوفر نظام لتهجير البيانات Migration.
	</li>
	<li>
		يوفر نظام التوجيه Routing.
	</li>
</ol>

<p>
	لنناقش كل خاصية من هذه الخواص بمزيد من التفصيل ونكتشف أهميتها في تطوير الويب.
</p>

<h3>
	1. سهولة التعلم والاستخدام
</h3>

<p>
	يتميز لارافيل بكود سهل التعلم والاستخدام، لكنه بالطبع يشترط امتلاك معرفة مسبقة بأساسيات <a href="https://wiki.hsoub.com/PHP" rel="external" target="_blank">PHP</a> ومبادئ البرمجة كائنية التوجه <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%83%D8%A7%D8%A6%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%87-r1375/" rel=""><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></abbr></a> إلى جانب وجود معرفة جيدة حول <a href="https://wiki.hsoub.com/HTML" rel="external" target="_blank">HTML</a> وأحد أنظمة إدارة قواعد البيانات مثل MySQL أو PostgreSQL بعدها سيكون تعلم لارافيل أمرًا في غاية البساطة.
</p>
<iframe allowfullscreen="" class="ipsEmbed_finishedLoading" data-controller="core.front.core.autosizeiframe" data-embedauthorid="3889" data-embedcontent="" data-embedid="embed5661305986" src="https://academy.hsoub.com/files/26-%D8%AA%D8%B5%D9%85%D9%8A%D9%85-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA/?do=embed" style="overflow: hidden; height: 470px; max-width: 500px; margin: auto;"></iframe>

<h3>
	2. تسريع وقت التطوير
</h3>

<p>
	يتضمن لارافيل Laravel العديد من الوظائف التي تسهل على المطور تنفيذ المهام الشائعة مثل عمليات المصادقة authentication، والتوجيه routing، وتهجير قواعد البيانات migrating، والتخزين المؤقت <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%AE%D8%A8%D8%A6%D8%A9-cache-%D9%81%D9%8A-laravel-r389/" rel="">cach</a>، فكل هذه الوظائف مضمنة ومدمجة في نظام لارافيل وجاهزة لتستخدمها بكل سهولة.
</p>

<p>
	كما يتضمن واجهة سطر أوامر مدمجة تسمى آرتيزان Artisan توفر مجموعة من الأوامر المفيدة في بناء تطبيقات الويب، وبالجمع بين أوامر آرتيزان والوظائف المضمنة تصبح عملية تطوير تطبيقات الويب أسرع بكثير.
</p>

<h3>
	3. التوثيق الجيد
</h3>

<p>
	يحتوي لارافيل Laravel على <a href="https://laravel.com/docs/10.x" rel="external nofollow" target="_blank">توثيق مميز عبر الإنترنت</a> يساعد المطورين والمبرمجين في تعلم كل ما يحتاجونه والعثور على إجابات لكافة تساؤلاتهم حول التعامل مع هذا الإطار، كما تتوفر معلومات هائلة متاحة من <a href="https://laravel.io" rel="external nofollow" target="_blank">مجتمع مطوري لارافيل</a>. المشكلة الوحيدة التي توجد في هذه المصادر هو أنها متاحة باللغة الإنجليزية وشرحها جامد إلى حد ما، وفي فقرة تعلم لارافيل سأطلعك على مصادر عربية جيدة تساعدك في تعلم لارافيل.
</p>

<h3>
	4. غني بالميزات وقابل للتوسيع
</h3>

<p>
	يعد لارافيل نظامًا قويًا وغنيًا بالكثير من الميزات المضمنة ويوفر مجموعة متنوعة من المكتبات المضمنة التي تساعدك على بناء تطبيقات متقدمة تعالج ملايين الطلبات بفضل دعمه للتخزين المؤقت السريع والتخزين الموزع، كما يوفر لارافيل منصات سحابية <a href="https://academy.hsoub.com/devops/cloud-computing/%D8%B3%D8%A8%D8%B9-%D9%85%D9%86%D8%B5%D8%A7%D8%AA-%D9%85%D9%81%D8%AA%D9%88%D8%AD%D8%A9-%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1-%D9%84%D9%84%D8%A8%D8%AF%D8%A1-%D9%81%D9%8A-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%AD%D9%88%D8%B3%D8%A8%D8%A9-%D8%AE%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AE%D9%88%D8%A7%D8%AF%D9%85-serverless-r408/" rel="">خفية الخوادم Serverless </a> مثل Laravel Forge و Vapor تمكنك من نشر التطبيقات وتشغيلها دون الحاجة إلى إدارة الخوادم وهي منصات قابلة للتوسيع التلقائي بكل سهولة.
</p>

<p>
	أضف إلى ذلك يوفر مطوروا لارافيل الكثير من الحزم الخارجية لأي وظيفة أو ميزة تحتاجها، على سبيل المثال يمكنك باستخدام مكتبة <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D8%A7%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%B9%D8%A8%D8%B1-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AC%D8%AA%D9%85%D8%A7%D8%B9%D9%8A%D8%A9-%D9%81%D9%8A-laravel-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-socialite-r275/" rel="">Socialite</a> تضمين ميزة تسجيل الدخول إلى موقعك باستخدام حسابات شبكات التواصل الاجتماعي على فيسبوك أو تويتر أو لينكدإن أو جيتهب أو جوجل بكل سهولة.
</p>

<h3>
	5. يهتم بأمان التطبيقات
</h3>

<p>
	يمكنك لارافيل من تطوير مواقع وتطبيقات آمنة بفضل العديد من ميزات الأمان المدمجة مثل نظام المصادقة أو الاستيثاق المدمج authentication system ونظام المصادقة authorization والتحقق من صحة البيانات data validation وتشفير البيانات والتحقق من البريد الإلكتروني وإعادة تعيين كلمة المرور، كما يسهل عليك تكوين ميزات الأمان المتقدمة التي تحمي تطبيقاتك من الاختراق وتضمن أمان بيانات عملائك.
</p>

<h3>
	6. يحسن أداء التطبيقات
</h3>

<p>
	يوفر لارافيل عدة طرق لتحسين سرعة التطبيقات وتحسين أدائها مثل دعم التخزين المؤقت لموقعك الإلكتروني على الخادم، كما أنه يسهل تنفيذ تقنيات أخرى لتحسين السرعة مثل تقليل استخدام الذاكرة وفهرسة قاعدة البيانات. فإذا كانت سرعة الموقع أولوية لديك فإن لارافيل خيارك الأنسب.
</p>

<h3>
	7. يدعم تعدد اللغات
</h3>

<p>
	فمن خلال ميزة التوطين localization يمكنك لارافيل من إنشاء تطبيقات متعددة اللغات واسترداد السلاسل النصية بلغات مختلفة، وهو يدعم عدة لغات من بينها اللغة العربية.
</p>

<h3>
	8. يسهل تصحيح أخطاء التطبيقات وصيانتها
</h3>

<p>
	يحتوي لارافيل على ميزات تختبر كل جزء من موقع الويب الخاص بك للبحث عن أي أخطاء ويعرض لك رسائل واضحة ومفصلة تبين كافة الأخطاء التي تحدث في موقعك ويسهل عليك تصحيحها، كما أنه يسهل صيانة التطبيقات بفضل ميزات الكود النظيف واعتماد مبادئ البرمجة كائنية التوجه <abbr title="Object-Oriented Programming | البرمجة كائنية التوجه"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></abbr> ومعمارية MVC التي تنظم الكود وتمكن أي مطور من متابعة العمل على مشروع سابق وتطويره وإضافة الميزات المطلوبة له.
</p>

<h3>
	9.يوفر نظام تهجير البيانات Migration
</h3>

<p>
	يوفر لارافيل ميزة تهجير البيانات Migration التي توفر آليات لإنشاء وتعديل جداول قاعدة البيانات كما يوفر آلية شبيهة بنظام التحكم في الإصدارات لقاعدة البيانات الخاصة بك تتعقب كيفية تعديل قاعدة البيانات مع الوقت وتسمح لكافة أعضاء فريق التطوير بتعديل قاعدة بيانات المشروع ومشاركته فيما بينهم وتسهل حذف قاعدة البيانات وإعادة إنشائها عند الضرورة. وللمزيد من التفاصيل حول هذه الميزة يمكنك مطالعة مقال <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-5-r224/" rel="">تهجير قواعد البيانات في لارافيل 5</a>
</p>

<h3>
	10. يوفر نظام التوجيه Routing
</h3>

<p>
	يوفر لارافيل نظام توجيه Routing قوي لمعالجة وإدارة مسارات تطبيق الويب ويُمكِّنك من الانتقال من مكان لآخر في تطبيقك وتبادل المعلومات بينها بسهولة، كما يمكّنك من استخدام أسماء بسيطة ترتبط بأجزاء مختلفة من تطبيقك بدلاً من الأسماء الطويلة والمربكة، ستجد كافة المسارات الخاصة بالتطبيق في الملف web.php ضمن المجلد routes لمشروعك وللمزيد من التفاصيل يمكنك الاطلاع على توثيق <a href="https://wiki.hsoub.com/Laravel/routing" rel="external" target="_blank">التوجيه Routing في لارافيل</a>.
</p>

<h2>
	عيوب لارافيل Laravel
</h2>

<p>
	لا تخلو أي تقنية مهما كانت متقدمة من بعض العيوب ومن بينها لارافيل، فهو يملك بعض جوانب النقص وإليك قائمة بأبرز عيوب لارافيل:
</p>

<ul>
	<li>
		يعتبر إطار عمل لارافيل بطيئًا نسبيًا عند مقارنته ببعض أطر تطوير الويب الأخرى.
	</li>
	<li>
		رغم كونه آمنًا بشكل كبير إلا أنه لا يزال مهددًا باستهدافه بالثغرات الأمنية بسبب اعتماده على PHP التي وسمت بكثرة الثغرات الأمنية فيها تحديدًا في الإصدارات القديمة منها.
	</li>
	<li>
		تكلفته عالية فالمواقع المطورة بإطار لارافيل قد تكون أغلى نسبيًا من المواقع المطورة بغيرها من تقنيات الويب كأنظمة إدارة المحتوى أو أطر العمل الأخرى وهذا رغم كونه عامل قوة لك كمطور لكنه قد يجعل بعض العملاء يفضلون الخيارات الأرخص.
	</li>
	<li>
		وجود تحديثات متكررة قد يجعلك تواجه صعوبات في تعلم الجديد في كل إصدار وتعديل شيفرة تطبيقاتك المطورة بإصدارات قديمة لذا يجب أن تكون لديك رغبة مستمرة في التعلم كي تتلاءم مع كل إصدار جديد.
	</li>
</ul>

<p>
	كانت هذه قائمة بأبرز عيوب أو سلبيات لارافيل Laravel، وبموازنة السلبيات والإيجابيات يمكن أن تقرر فيما إذا كان إطار لارافيل سيلبي احتياجاتك أم لا.
</p>

<h2>
	تنظيم الكود في لارافيل Laravel
</h2>

<p>
	يتميز إطار لارافيل Laravel بكود منظم وسهل الصيانة يحافظ على تنظيم مشاريعك البرمجة من خلال استخدامه معمارية <strong>MVC</strong> وهي اختصار لثلاث كلمات هي:
</p>

<ul>
	<li>
		النموذج <strong>M</strong>odel الذي يعني بيانات التطبيق فهو يتفاعل مباشرة مع قاعدة البيانات الخاصة بك ويسترد المعلومات منها.
	</li>
	<li>
		العرض <strong>V</strong>iew الذي يعني واجهة التطبيق فهو يعرض الصفحات التي يتفاعل معها المستخدم مباشرة.
	</li>
	<li>
		المتحكم <strong>C</strong>ontroller وهو صلة الوصل بين العرض والنموذج فهو يستقبل طلبات المستخدمين ويسترد البيانات المطلوبة من النموذج ويعالجها ويرسلها إلى صفحات العرض.
	</li>
</ul>

<p style="text-align: center;">
	<img alt="mvc in laravel.png" class="ipsImage ipsImage_thumbnailed" data-fileid="133066" data-ratio="62.50" data-unique="lpqux6ima" style="width: 600px; height: auto;" width="600" src="https://academy.hsoub.com/uploads/monthly_2023_08/mvcinlaravel.thumb.png.b443bf2633de34544555ba9cd18cff96.png">
</p>

<p>
	وباستخدام هذا الأسلوب التنظيمي يستطيع لارافيل فصل كود التطبيق إلى ثلاث مجموعات لكل منها وظيفة محددة وهي الواجهة الخلفية والواجهة الأمامية ووحدة التحكم للربط بين الواجهتين وهذه الميزة تجعل من لارافيل أفضل إطار عمل PHP لتطبيقات الويب.
</p>

<p>
	بالإضافة إلى ذلك يستخدم لارافيل المسارات <strong>routes</strong> لتعيين عناوين URL الخاصة بإجراءات متحكم معين، فعندما يقوم المستخدم بإدخال عنوان URL خاص بالتطبيق يعين المسار المرتبط بهذا العنوان عنوان URL للمتحكم المسؤول عن استرداد البيانات المطلوبة من قاعدة البيانات أو النموذج ويمررها إلى صفحات العرض النهائية.
</p>

<h2>
	كيف أتعلم لارافيل Laravel؟
</h2>

<p>
	بعد أن تعرفنا على إطار عمل لارافيل وأهم مميزاته واستخداماته، سنوضح لك في هذه الفقرة طريقة تعلم لارافيل وأهم الخطوات التي عليك اتباعها كي تحترفه.
</p>

<ol>
	<li>
		قبل أن تبدأ بتعلم لارافيل يجب أن تكون على دراية بأساسيات تطوير الويب والمفاهيم الأساسية في <a href="https://wiki.hsoub.com/HTML" rel="external" target="_blank">HTML</a> و <a href="https://wiki.hsoub.com/CSS" rel="external" target="_blank">CSS</a>.
	</li>
	<li>
		يجب أن تتعلم أساسيات البرمجة بلغة PHP وتتمكن من كتابة برامج PHP بسيطة وتعرف كذلك مبادئ البرمجة كائنية التوجه <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%83%D8%A7%D8%A6%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%87-object-oriented-programming-%D9%81%D9%8A-php-r316/" rel=""><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></abbr></a>.
	</li>
	<li>
		تعلم المكونات الأساسية لإطار عمل لارافيل ومعمارية MVC ومفاهيم النماذج وصفحات العرض والمتحكمات من خلال مصادر التعلم التي تفضلها سواء كانت مواقع الإنترنت أو الكتب أو الدورات التعليمية واحرص على تحديد خطة للتعلم والتزم بها كي تحقق أهدافك.
	</li>
	<li>
		طور مشاريع تطبق فيها ما تعلمته، فالتطبيق العملي طريقة رائعة لتعلم المفاهيم التي تعلمتها، ابدأ بمشروع بسيط ثم انتقل إلى مشاريع أكثر تقدمًا فهذا يساعدك على إنشاء معرض أعمال يعزز مسيرتك المهنية.
	</li>
	<li>
		لا تتوقف عن التعلم واطلع على كل جديد في مجال تطوير الويب عمومًا وإطار لارافيل على وجه الخصوص، فالتقنيات تتطور بسرعة والتعلم المستمر يساعدك على التكيف مع أي تطور جديد والبقاء في الصدارة.
	</li>
</ol>

<h2>
	مصادر تعلم لارافيل Laravel
</h2>

<p>
	إذا كنت تبحث عن مصدر عربي موثوق لتعلم لارافيل من الصفر للاحتراف بشهادة معتمدة تعزز فرصتك في سوق العمل ستجد في أكاديمية حسوب <a href="https://academy.hsoub.com/learn/php-web-application-development/" rel="">دورة تطوير تطبيقات الويب باستخدام لغة PHP</a> وهي دورة تدريبية عالية الجودة تضم مسارات متعددة ولا تتطلب منك أي معرفة مسبقة وتعلمك كل ما يخص لغة PHP وإطار عملها لارافيل وتدمج بين الشرح النظري والتطبيق العملي، فمن خلالها ستتعلم تطوير العديد من تطبيقات الويب المتكاملة وتبني من خلالها معرض أعمال قوي، كما ستتمكن من خلال هذه الدورة من التواصل مع مدربين أكفاء وطرح أي سؤال أو مشكلة تواجهك عند تطبيق مشروعك البرمجي.
</p>

<p>
	<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="450" id="ips_uid_4064_5" src="https://academy.hsoub.com/applications/core/interface/index.html" title="دورة تطوير تطبيقات الويب باستخدام لغة PHP - أكاديمية حسوب" width="800" data-embed-src="https://www.youtube.com/embed/o3ilJek788w"></iframe>
</p>

<p>
	كما ستجد في أكاديمية حسوب الكثير من مصادر التعلم المجانية مثل <a href="https://academy.hsoub.com/programming/php/laravel/" rel="">المقالات والدروس المتنوعة حول PHP وحول إطار عمل لارافيل Laravel</a>، وبالإضافة لكل ما سبق فقد <a href="https://wiki.hsoub.com/Laravel" rel="external" target="_blank">ترجمت موسوعة حسوب توثيق لارافيل الأجنبي إلى اللغة العربية</a> ويمكنك من خلاله أن تتعرف على كل ما يخص هذا الإطار بتسلسل منظم وواضح.
</p>

<h2>
	تنصيب لارافيل Laravel
</h2>

<p>
	كي تتمكن من التعامل مع مشاريع لارافيل في حاسوبك المحلي عليك اتباع مجموعة من الخطوات وهي كالتالي:
</p>

<ul>
	<li>
		أول خطوة قبل البدء بتثبيت لارافيل Laravel على جهازك المحلي هي تحويل حاسوبك إلى <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AE%D8%A7%D8%AF%D9%85-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r574/" rel="">خادم ويب</a> محلي كي يتمكن من تشغيل PHP و نظام إدارة قواعد البيانات مثل MySQL أو PostgreSQL، يمكنك القيام بذلك باستخدام <a href="https://www.apachefriends.org/download.html" rel="external nofollow" target="_blank">XAMPP</a> المتوافق مع كافة أنظمة التشغيل.
	</li>
	<li>
		عليك كذلك تثبيت أي محرر أكواد أو بيئة تطوير متكاملة IDE ترغب بها لتحرير أكواد مشروعك مثل PhpStorm أو Visual Studio Code أو أي محرر آخر تتآلف معه.
	</li>
	<li>
		بعدها عليك تثبيت مدير الحزم <a href="https://getcomposer.org/" rel="external nofollow" target="_blank">كومبوزر Composer</a> لتحميل إطار لارافيل من خلاله، وهو ضروري لتحديد المكتبات التي يحتاجها مشروعك بكل سهولة وإدارتها بالنيابة عنك. وللمزيد يمكنك <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%A7-%D9%87%D9%88-composer-%D9%88%D9%84%D9%85%D8%A7%D8%B0%D8%A7-%D9%8A%D8%AC%D8%A8-%D8%B9%D9%84%D9%89-%D9%83%D9%84-%D9%85%D8%B7%D9%88%D8%B1-php-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%D9%87-r10/" rel="">مطالعة مقال ما هو Composer ولماذا يجب على كل مطور PHP استخدامه</a>.
	</li>
	<li>
		الآن يمكنك تثبيت لارافيل على جهازك، وأبسط طريقة لتحميل لارافيل هي تشغيل محرر الأوامر في نظامك والانتقال للمسار الذي تريد إنشاء مشروع لارافيل الخاص بك فيه ثم كتابة الأمر التالي، هنا أنشأنا مشروع لارافيل باسم example-app
	</li>
</ul>

<pre class="ipsCode">composer create-project laravel/laravel example-app
</pre>

<p>
	لتشغيل المشروع انتقل إلى مجلد مشروعك وهو في حالتنا D:\example-app ونفذ الأمر التالي:
</p>

<pre class="ipsCode">D:\cd example-app
D:\example-app&gt;php artisan serve
</pre>

<p>
	هذا الأمر سيشغل تطبيق لارافيل على خادم تطوير PHP وينتج عن تنفيذه عرض رابط المشروع بالشكل التالي http://127.0.0.1:8000، كل ما عليك هو نسخ هذا الرابط ولصقه في المستعرض لتظهر لك الصفحة الرئيسية لموقع لارافيل الخاص بك كما هو موضح في الصورة التالية.
</p>

<p style="text-align: center;">
	<img alt="الصفحة الرئيسية laravel.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="133067" data-unique="uiziutheu" src="https://academy.hsoub.com/uploads/monthly_2023_08/laravel.thumb.PNG.730b71a1305b55f946ff2504e466e54a.PNG">
</p>

<p>
	ولإيقاف تشغيل خادم التطوير من خلال سطر الأوامر اضغط على مفتاحي <strong>Ctrl+C</strong> في لوحة المفاتيح.<br>
	ولمزيد من المعلومات حول تثبيت لارافيل يمكنك مطالعة مقال  <a href="https://academy.hsoub.com/devops/cloud-computing/docker/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-%D8%B9%D9%84%D9%89-%D8%AF%D9%88%D9%83%D8%B1-%D9%83%D9%88%D9%85%D8%A8%D9%88%D8%B2-docker-compose-r650/" rel="">تثبيت وإعداد لارافيل Laravel على دوكر كومبوز Docker Compose</a> ومقال  <a href="https://academy.hsoub.com/programming/php/laravel/%d8%aa%d8%ab%d8%a8%d9%8a%d8%aa-laravel-5-%d9%88%d8%a5%d8%b9%d8%af%d8%a7%d8%af%d9%87-%d8%b9%d9%84%d9%89-windows-%d9%88ubuntu-r212/" rel="">تثبيت Laravel 5 وإعداده على Windows وUbuntu</a>.
</p>

<p>
	أخيرًا أنصحك أن تفتح مشروع في محرر الشيفرات الذي اخترته وتتعرف على <a href="https://wiki.hsoub.com/Laravel/structure" rel="external" target="_blank">بنية المجلدات في Laravel</a> وتفهم دورها في المشروع ومساهمتها في نموذج MVC المستخدم في إطار العمل لارافيل.
</p>

<p>
	هذا كل شيء! أنت جاهز الآن لتبدأ رحلتك في اكتشاف لارافيل والبدء بتعلمه.
</p>

<h2>
	الخلاصة
</h2>

<p>
	اكتشفنا في مقال اليوم ما هو إطار عمل لارافيل Laravel وأهميته في سوق العمل، وتعرفنا على أهم المميزات التي يقدمها في مجال تطوير مواقع وتطبيقات الويب، كما تعرفنا على كيفية تنصيب لارافيل وبدء التعامل معه وأهم مصادر تعلمه.
</p>

<p>
	وسواء كنت مطورًا مبتدئًا أو خبيرًا في برمجة تطبيقات الويب فإن لارافيل Laravel خيار مناسب لك تمامًا فهو يوفر لك بيئة تطوير سهلة وقوية ويقدم لك الكثير من الميزات والوظائف المبرمجة مسبقًا التي تمكنك من بناء تطبيقات ويب احترافية وعالية الجودة بسرعة وسهولة. لا تتردد وابدأ من اليوم بتعلم لارافيل وإن اعترضك أي سؤال حوله شاركنا إياه في قسم التعليقات أسفل المقال.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AF%D9%84%D9%8A%D9%84-%D9%85%D8%B7%D9%88%D9%91%D8%B1%D9%8A-php-%D9%84%D9%84%D8%A8%D8%AF%D8%A1-%D9%81%D9%8A-%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%91%D9%84-r363/" rel="">دليل مطوّري PHP للبدء في بناء تطبيقات Laravel - الجزء الأوّل</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AF%D9%84%D9%8A%D9%84-%D9%85%D8%B7%D9%88%D9%91%D8%B1%D9%8A-php-%D9%84%D9%84%D8%A8%D8%AF%D8%A1-%D9%81%D9%8A-%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%AB%D8%A7%D9%86%D9%8A-r364/" rel="">دليل مطوّري PHP للبدء في بناء تطبيقات Laravel - الجزء الثاني</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%B1%D9%81%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D9%91%D8%A7%D8%AA-%D9%88%D8%A5%D8%AF%D8%A7%D8%B1%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-laravel-r392/" rel="">رفع الملفّات وإدارتها في تطبيقات Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AC%D8%B1%D9%8A%D8%AF-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D8%A8%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-migration-%D9%88%D8%A7%D9%84%D8%A8%D8%B0%D8%B1-seeder-r1725/" rel="">تجريد إعداد قواعد البيانات في لارافيل باستعمال عملية التهجير Migration والبذر Seeder</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-%D8%A7%D9%84%D8%A8%D8%AF%D8%A1-%D9%81%D9%8A-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%85%D8%AF%D9%88%D9%86%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-r2425/" rel="">لارافيل للمبتدئين-الجزء الأول: البدء في إنشاء مدونة بسيطة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2093</guid><pubDate>Thu, 24 Aug 2023 14:00:00 +0000</pubDate></item><item><title>&#x628;&#x631;&#x645;&#x62C;&#x629; &#x62A;&#x637;&#x628;&#x64A;&#x642; '&#x644;&#x62E;&#x635;&#x644;&#x64A;' &#x644;&#x62A;&#x644;&#x62E;&#x64A;&#x635; &#x627;&#x644;&#x645;&#x642;&#x627;&#x644;&#x627;&#x62A; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; ChatGPT &#x648;&#x644;&#x627;&#x631;&#x627;&#x641;&#x644;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D9%84%D8%AE%D8%B5%D9%84%D9%8A-%D9%84%D8%AA%D9%84%D8%AE%D9%8A%D8%B5-%D8%A7%D9%84%D9%85%D9%82%D8%A7%D9%84%D8%A7%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-chatgpt-%D9%88%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%84-r2008/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_06/---------ChatGPT-.png.8bbfa0e342838fc03a65266776e1e9b0.png" /></p>
<p>
	يسعى مجال الذكاء الاصطناعي إلى محاكاة ذكاء البشر في قدرتهم على تحليل المعطيات الحسية كالصورة والأصوات واستنتاج المعلومات المفيدة منها، وبينما يُمثل البشر تلك المعطيات بيولوجيًا طور علماء الرياضيات والحاسوب طرقًا لتمثيل ومعالجة تلك المعطيات رقميًا لنتمكن من معالجتها بخوارزميات رياضية ضمن الحاسوب، حيث يمكن تدريب نماذج الذكاء الاصطناعي على البيانات لتتمكن محاكاة ذكاء البشر في مجال محدد، أحد أنواع تلك النماذج هي نماذج اللغة الكبيرة LLM's (أو Large Language Models) وهي نماذج دُربت على كميات كبيرة من النصوص فامتلكت القدرة على توليد نصوص مشابهة لها وبل حتى فهم نصوص جديدة لم تشاهدها ضمن بيانات التدريب من قبل.
</p>

<p>
	من نماذج اللغة الكبيرة <a href="https://academy.hsoub.com/apps/web/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A8%D9%88%D8%AA-%D8%A7%D9%84%D9%85%D8%AD%D8%A7%D8%AF%D8%AB%D8%A9-%D8%A7%D9%84%D8%B0%D9%83%D9%8A-%D8%B4%D8%A7%D8%AA-%D8%AC%D9%8A-%D8%A8%D9%8A-%D8%AA%D9%8A-chatgpt-r863/" rel="">النموذج ChatGPT</a> من شركة OpenAI والذي دُرّب على كمية كبيرة من النصوص الموجودة على شبكة الانترنت وطوّر ليستجيب إلى الأوامر المرسلة له من قبل المستخدم، مما يجعل هذا النموذج قادرًا على محاكاة تلك النصوص وتحديد النقاط الرئيسية فيها والرد عليها بردود كما لو أنها مكتوبة من قبل إنسان، لذا يمكن الاستفادة من مرونة التعامل معه وفهمه للأوامر باللغة الطبيعية في العديد من التطبيقات العملية، كتوليد المحتوى أو التعديل على نص معين أو التلخيص واستخراج النقاط الرئيسية من نص ما والكثير من الأفكار الأخرى، أي يمكن اعتبار تلك النماذج كمساعد ذكي يمكن طلب أي مهمة منه كما لو كنا نطلبها من شخص حقيقي، وأهم ما في تلك النماذج هو سهولة برمجتها نسبيًا، فلم نعد بحاجة لتعلم لغة برمجة مخصصة بل يمكننا التعامل معها باللغة الطبيعية وبعدة لغات أيضًا منها اللغة العربية كما سنرى لاحقًا.
</p>

<p>
	وفي هذا المقال سنستفيد من قدرة ذلك النموذج على فهم النصوص وإعادة صياغتها وتلخيصها في تلخيص مقالات من الإنترنت، حيث سنبني تطبيق ويب باستخدام <a href="https://academy.hsoub.com/programming/php/laravel/" rel="">لارافل Laravel</a> لجلب محتوى المقال الذي يرغب المستخدم في تلخيصه، ثم الطلب من نموذج ChatGPT تلخيص ذلك المقال للمستخدم، ولمتابعة هذا المقال يجب أن تملك خبرة أساسية في <a href="https://academy.hsoub.com/php/" rel="">لغة PHP</a> عمومًا وإطار لارافل خصوصًا.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير تطبيقات الويب باستخدام لغة PHP
		</p>

		<p class="banner-subtitle">
			احترف تطوير النظم الخلفية وتطبيقات الويب من الألف إلى الياء دون الحاجة لخبرة برمجية مسبقة
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/php-web-application-development/" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة تطوير تطبيقات الويب باستخدام لغة PHP" src="https://academy.hsoub.com/learn/assets/images/courses/php-web-application-development.png">
	</div>
</div>

<h2>
	إنشاء مشروع لارافل جديد وبناء الواجهات الأمامية
</h2>

<p>
	يتألف مشروعنا بشكل عام من صفحتين رئيسيتين الأولى يدخل فيها المستخدم رابط المقال الذي يريد تلخيصه، والثانية يظهر له فيها الملخص لذلك المقال بعد أن يجلب التطبيق صفحة المقال من على الأنترنت ويستخرج محتوى المقال ويرسلها إلى نموذج ChatGPT لتلخيصها كما سنرى بالتفصيل لاحقًا، ولنبدأ أولًا بإنشاء مشروع وليكن بالاسم summarizer عبر تنفيذ الأمر التالي ضمن الطرفية والذي سيُنشئ مجلد جديد باسم المشروع يحوي هيكلية الملفات الأساسية لمشروع لارافل جديد:
</p>

<pre class="ipsCode">composer create-project laravel/laravel summarizer
</pre>

<p>
	نحتاج لهذا المشروع صفحتين، الصفحة الأولى لإدخال رابط المقال المُراد تلخيصه وتحوي على نموذج form بسيط يرسل القيم بداخله بالطريقة POST إلى المسار summary/ والذي سنُعرفه لاحقًا، ويحوي النموذج على حقل لإدخال الرابط بالاسم url وزر الإرسال ولا ننسى تضمين قيمة الحقل csrf ضمن النموذج، وننشئ للصفحة ملف جديد بصيغة <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%84%D8%A8-blade-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%B9%D8%B1%D9%88%D8%B6-laravel-r220/" rel="">قالب blade</a> جديدة ضمن المسار التالي resources\views\index.blade.php يحوي التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_10" style=""><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;title&gt;</span><span class="pln">لخصلي</span><span class="tag">&lt;/title&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"style.css"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/head&gt;</span><span class="pln">

</span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;h1&gt;</span><span class="pln">✍<span class="ipsEmoji">?</span></span><span class="tag">&lt;/h1&gt;</span><span class="pln">
    </span><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"/summary"</span><span class="pln"> </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"POST"</span><span class="tag">&gt;</span><span class="pln">
        @csrf
        </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"url"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"url"</span><span class="pln"> </span><span class="atn">placeholder</span><span class="pun">=</span><span class="atv">"أدخل رابط المقال"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"submit"</span><span class="tag">&gt;</span><span class="pln">لخصلي</span><span class="tag">&lt;/button&gt;</span><span class="pln">
    </span><span class="tag">&lt;/form&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span></pre>

<p>
	والصفحة الثانية هي لعرض نتيجة التلخيص، تحوي على الملخص ورابط للمقال الأصل في حال أراد المستخدم قراءته ورابط للرجوع للصفحة الرئيسية لطلب تلخيص جديد، ونُنشئ ملف قالب تلك الصفحة ضمن المسار resources\views\summary.blade.php ويحوي التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_8" style=""><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;title&gt;</span><span class="pln">لخصلي</span><span class="tag">&lt;/title&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"style.css"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="tag">&lt;/head&gt;</span><span class="pln">

</span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;h2&gt;</span><span class="pln">ملخص المقال</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
    </span><span class="tag">&lt;p&gt;</span><span class="pln">{{ $summary }}</span><span class="tag">&lt;/p&gt;</span><span class="pln">
    </span><span class="tag">&lt;footer&gt;</span><span class="pln">
        </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"{{$url}}"</span><span class="pln"> </span><span class="atn">target</span><span class="pun">=</span><span class="atv">"_blank"</span><span class="tag">&gt;</span><span class="pln">قراءة المقال</span><span class="tag">&lt;/a&gt;</span><span class="pln">
        </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/"</span><span class="tag">&gt;</span><span class="pln">تلخيص مقال جديد</span><span class="tag">&lt;/a&gt;</span><span class="pln">
    </span><span class="tag">&lt;/footer&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span></pre>

<p>
	نلاحظ ربط ملف تنسيقات CSS بالاسم style.css في كلا الصفحتين لتنسيق محتواهما، ونُنشئ ذلك الملف ضمن المسار public\style.css ويحوي التنسيق التالي:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_1726_12" style=""><span class="pln">body </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">direction</span><span class="pun">:</span><span class="pln"> rtl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">display</span><span class="pun">:</span><span class="pln"> flex</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">flex-direction</span><span class="pun">:</span><span class="pln"> column</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">max-width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">60ch</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">justify-items</span><span class="pun">:</span><span class="pln"> center</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">align-items</span><span class="pun">:</span><span class="pln"> center</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">font-size</span><span class="pun">:</span><span class="pln"> x-large</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">margin</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> auto</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">padding</span><span class="pun">:</span><span class="pln"> </span><span class="lit">20vh</span><span class="pln"> </span><span class="lit">10vw</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">background-color</span><span class="pun">:</span><span class="pln"> </span><span class="lit">#f9f9f9</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">color</span><span class="pun">:</span><span class="pln"> </span><span class="lit">#121212</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">font-family</span><span class="pun">:</span><span class="pln"> system-ui</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

p </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">line-height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">text-align</span><span class="pun">:</span><span class="pln"> center</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">border</span><span class="pun">:</span><span class="pln"> </span><span class="lit">.25rem</span><span class="pln"> solid</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">padding</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3rem</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">white-space</span><span class="pun">:</span><span class="pln"> pre-line</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

a </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">padding</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1rem</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">font-size</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">inherit</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">margin</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">.5rem</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">color</span><span class="pun">:</span><span class="pln"> darkblue</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

footer </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">margin-top</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2rem</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

form </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">display</span><span class="pun">:</span><span class="pln"> flex</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">flex-direction</span><span class="pun">:</span><span class="pln"> column</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">gap</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2rem</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">text-align</span><span class="pun">:</span><span class="pln"> center</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

button </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">background-color</span><span class="pun">:</span><span class="pln"> </span><span class="lit">#121212</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">color</span><span class="pun">:</span><span class="pln"> </span><span class="lit">#f9f9f9</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">border</span><span class="pun">:</span><span class="pln"> none</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">padding</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1rem</span><span class="pln"> </span><span class="lit">2rem</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">font-size</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">inherit</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">cursor</span><span class="pun">:</span><span class="pln"> pointer</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">font-family</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">inherit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

input </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">padding</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1rem</span><span class="pln"> </span><span class="lit">2rem</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">font-size</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">inherit</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">font-family</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">inherit</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">text-align</span><span class="pun">:</span><span class="pln"> center</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">border</span><span class="pun">:</span><span class="pln"> </span><span class="lit">.2rem</span><span class="pln"> solid</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نعرف ضمن ملف التوجيه routes\web.php مسارين الأول لعرض صفحة الإدخال نعيد فيها قالب الصفحة الأولى، والمسار الثاني summary/ لاستقبال <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-http-%D8%B4%D8%B1%D8%AD-%D8%A7%D9%84%D8%AA%D8%AE%D8%A7%D8%B7%D8%A8-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%B9%D9%85%D9%8A%D9%84-%D9%88%D8%A7%D9%84%D8%AE%D8%A7%D8%AF%D9%85-r74/" rel="">طلبات HTTP</a> من نوع POST نستخرج ضمنه قيمة الرابط url المُدخل من قبل المستخدم ويلخص ذلك المقال ثم يعرض النتيجة ضمن قالب الصفحة الثانية ليكون محتوى الملف كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_14" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Route</span><span class="pun">;</span><span class="pln">

</span><span class="com">// صفحة الإدخال</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">view</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'index'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// صفحة عرض التلخيص </span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/summary'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $url </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'url'</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'summary'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'url'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $url</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'summary'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'ملخص المقال هنا'</span><span class="pln">
    </span><span class="pun">]);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	والآن يمكننا استعراض الصفحتين بتشغيل خادم التطوير أولًا باستخدام الأمر التالي:
</p>

<pre class="ipsCode">php artisan serve
</pre>

<p>
	واستعراض الصفحة الرئيسية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="129058" href="https://academy.hsoub.com/uploads/monthly_2023_06/index.png.cac12a6e07f50f938f206cbd5f1b2d3d.png" rel=""><img alt="index.png" class="ipsImage ipsImage_thumbnailed" data-fileid="129058" data-unique="44hbk4wzm" src="https://academy.hsoub.com/uploads/monthly_2023_06/index.thumb.png.1492fee115fc75f8117f188fbd19055e.png"> </a>
</p>

<p>
	وإدخال أي رابط ضمن تلك الصفحة وطلب تلخيصه لنستعرض صفحة النتيجة:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="129055" href="https://academy.hsoub.com/uploads/monthly_2023_06/summary-template.png.d7a38389f786ac929e25c0965e7a45af.png" rel=""><img alt="summary-template.png" class="ipsImage ipsImage_thumbnailed" data-fileid="129055" data-unique="2tk30lr2l" src="https://academy.hsoub.com/uploads/monthly_2023_06/summary-template.thumb.png.14e86b332c13fbda7555b0437306103e.png"> </a>
</p>

<p>
	بعد أن جهزنا المشروع الجديد والصفحات وعملية إرسال طلب تلخيص جديد سنبدأ في الفقرات التالية تضمين عملية جلب محتوى المقال المطلوب ثم تلخيصه باستخدام ChatGPT.
</p>

<h2>
	جلب محتوى المقال
</h2>

<p>
	نبدأ بإنشاء صنف جديد بالاسم <code>Article</code> ضمن المسار app\Article.php والذي سيكون مسؤولًا عن جلب محتوى المقال عن طريق الرابط له، ويحوي على التابع <code>fromURL</code> والذي يقبل رابط المقال كمعامل أول ويعيد نص المقال كسلسلة نصية، ويُنفذ ذلك باستخدام الصنف المساعد <code>HTTP</code> الذي يتيحه لارافل لإرسال طلب من نوع GET لجلب محتوى صفحة المقال كاملةً، ثم الاستعانة بالصنف <code>DOMDocument</code> لتحليل محتوى HTML من تلك الصفحة واستخراج المحتوى النصي لعناصر الفقرات ذات الوسم <code>p</code> والتي تحوي عادةً المحتوى النصي للمقال، ونجمع محتوى تلك الفقرات معًا في سلسلة نصية لتكون المحتوى النصي للمقال كاملًا ضمن الصفحة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_16" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">DOMDocument</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Http</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Article</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> fromURL</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">):</span><span class="pln"> </span><span class="kwd">string</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// جلب محتوى الصفحة</span><span class="pln">
        $html </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Http</span><span class="pun">::</span><span class="pln">withHeaders</span><span class="pun">([</span><span class="str">'User-Agent'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36'</span><span class="pun">])</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">body</span><span class="pun">();</span><span class="pln">

        </span><span class="com">// استخراج الفقرات</span><span class="pln">
        $document </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DOMDocument</span><span class="pun">();</span><span class="pln">
        </span><span class="lit">@$document</span><span class="pun">-&gt;</span><span class="pln">loadHTML</span><span class="pun">(</span><span class="pln">$html</span><span class="pun">);</span><span class="pln">
        $paragraphs </span><span class="pun">=</span><span class="pln"> $document</span><span class="pun">-&gt;</span><span class="pln">getElementsByTagName</span><span class="pun">(</span><span class="str">'p'</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// جمع محتوى الفقرات معًا</span><span class="pln">
        $article </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$paragraphs </span><span class="kwd">as</span><span class="pln"> $paragraph</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $article </span><span class="pun">=</span><span class="pln"> trim</span><span class="pun">(</span><span class="pln">$article </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n\n"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $paragraph</span><span class="pun">-&gt;</span><span class="pln">textContent</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $article</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أضفنا للطلب المُرسل الترويسة <code>User-Agent</code> والتي تتطلبها بعض المواقع لإرسال محتوى الصفحة، ونلاحظ أيضًا إضافة العلامة <code>@</code> قبل تحميل محتوى الصفحة باستخدام التابع <code>loadHTML</code> لتجنب بعض الأخطاء التي قد تحدث عند محاولة تفسير محتوى الصفحة، ولاستخدام ذلك الصنف يمكننا تمريره كمعامل لتابع معالجة مسار صفحة النتيجة ليُنشئ لارافل تلقائيًا كائنًا جديدًا من ذلك الصنف ويمرره لتابع المسار لنتمكن من استخدامه لجلب محتوى المقال من الرابط المُرسل كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_18" style=""><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Article</span><span class="pun">;</span><span class="pln">

</span><span class="pun">...</span><span class="pln">

</span><span class="com">// صفحة عرض التلخيص </span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/summary'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Article</span><span class="pln"> $article</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $url </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'url'</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// جلب محتوى المقال</span><span class="pln">
    $content </span><span class="pun">=</span><span class="pln"> $article</span><span class="pun">-&gt;</span><span class="pln">fromURL</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'summary'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'url'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $url</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'summary'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'ملخص المقال هنا'</span><span class="pln">
    </span><span class="pun">]);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	وفي الفقرة التالية سنرسل ذلك المحتوى إلى ChatGPT لتلخيصه ثم عرضه للمستخدم.
</p>
<iframe allowfullscreen="" data-controller="core.front.core.autosizeiframe" data-embedauthorid="3889" data-embedcontent="" src="https://academy.hsoub.com/files/29-%D8%B9%D8%B4%D8%B1%D8%A9-%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%B9%D9%86-%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1-%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A/?do=embed" style="margin: auto;"></iframe>

<h2>
	تلخيص محتوى المقال باستخدام ChatGPT
</h2>

<p>
	بعد أن استخرجنا محتوى المقال كاملًا يمكننا إرساله إلى ChatGPT محاطًا بتعليمة نخبر بها النموذج بأننا نريد ملخص قصير عن ذلك النص، ولكن نماذج اللغة الكبيرة مثل ChatGPT تملك حد أقصى من طول المحتوى المُرسل إليها وهو 4097 رمز (أو token) بحسب <a href="https://platform.openai.com/docs/models/gpt-3-5" rel="external nofollow">التوثيق الرسمي للنموذج</a>، والرمز هو قطعة من النص يحدد طولها بكلمة أو عدة أحرف أو عدة كلمات أحيانًا، أي في حال كان المقال طويل وعدد الرموز المكونة له أكبر من الحد الأقصى لن نتمكن من إرساله دفعة واحدة، ويمكن الاطلاع من خلال <a href="https://platform.openai.com/tokenizer" rel="external nofollow">أداة توفرها الشركة</a> على حساب تلك الرموز من أي نص.
</p>

<p>
	ويمكن حل المشكلة الحد الأقصى للرموز بعدة طرق والطريقة التي سنستخدمها هي تقسيم نص المقال إلى عدة مقاطع أقصر، ثم تلخيص كل مقطع منها على حدى وجمعها معًا للحصول على ملخص المقال كاملًا، وفي حال كان ذلك الملخص أطول مما نرغب بعرضه للمستخدم نعيد تلخيص الملخص نفسه مجددًا للحصول على ملخص أقصر، ونكرر ذلك حتى الحصول على ملخص بطول مناسب للمقال كاملًا، وانتبه إلى أن هذه الطريقة اعتمدناها فقط لأغراض تعليمية وقد لا تعطي نتائج جيدة لذا ابحث عن طريقة أفضل لحل هذه المشكلة.
</p>

<p>
	نكمل العمل بإنشاء صنف جديد بالاسم <code>Summary</code> ضمن المسار app\Summary.php سيحوي على عدة لتقسيم وتلخيص النصوص سنشرحها تباعًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_21" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Summary</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
 </span><span class="pun">...</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	التابع الرئيسي لتلخيص المقال اسمه <code>toWords</code> وهو يستقبل النص المراد تلخيصه وعدد يعبر عن عدد الكلمات الأقصى للملخص النهائي لذلك النص، بحيث يكون ذلك التابع مسؤولًا عن تلخيص النص باستخدام التابع <code>summarize</code> الذي سنعرفه لاحقًا، ثم التحقق من عدد كلمات الملخص وتكرار عملية التلخيص إن لزم الأمر إلى أن نحصل على ملخص نهائي بالطول المناسب:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_23" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Summary</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> toWords</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> $at_most</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $text</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// تلخيص أولي للنص</span><span class="pln">
        $summary </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">summarize</span><span class="pun">(</span><span class="pln">$text</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// تكرار عملية التلخيص حسب الطول المطلوب</span><span class="pln">
        </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">count</span><span class="pun">(</span><span class="pln">explode</span><span class="pun">(</span><span class="str">" "</span><span class="pun">,</span><span class="pln"> $summary</span><span class="pun">))</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> $at_most</span><span class="pun">)</span><span class="pln">
            $summary </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">summarize</span><span class="pun">(</span><span class="pln">$summary</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> $summary</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> summarize</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $text</span><span class="pun">):</span><span class="pln"> </span><span class="kwd">string</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">...</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ونستدعي ذلك التابع ضمن تابع معالجة بعد تعريفه ضمن المعاملات في ملف التوجيه routes/web.php لتلخيص محتوى المقال بعد استخراجه إلى عدد كلمات مناسب وليكن 150 كلمة وتمرير الملخص إلى قالب الصفحة لعرضه للمستخدم كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_25" style=""><span class="com">// صفحة عرض التلخيص</span><span class="pln">
</span><span class="typ">Route</span><span class="pun">::</span><span class="pln">post</span><span class="pun">(</span><span class="str">'/summary'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Article</span><span class="pln"> $article</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Summary</span><span class="pln"> $summarizer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $url </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'url'</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// جلب محتوى المقال</span><span class="pln">
    $content </span><span class="pun">=</span><span class="pln"> $article</span><span class="pun">-&gt;</span><span class="pln">fromURL</span><span class="pun">(</span><span class="pln">$url</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// تلخيص المقال</span><span class="pln">
    $summary </span><span class="pun">=</span><span class="pln"> $summarizer</span><span class="pun">-&gt;</span><span class="pln">toWords</span><span class="pun">(</span><span class="lit">100</span><span class="pun">,</span><span class="pln"> $content</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'summary'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'url'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $url</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'summary'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $summary
    </span><span class="pun">]);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	التابع <code>summarize</code> ضمن الصنف <code>Summary</code> مهمته تجزئة النص إلى فقرات بطول مناسب لإرسالها إلى ChatGPT للتلخيص، حيث نبدأ بتجزئة النص إلى فقراته التي يفصل بينها سطر فارغ، ثم تجميعها إلى مجموعات ولتكن مؤلفة من 8 فقرات معًا، بعدها نطلب تلخيص كل مجموعة على حدى، وبما طلب تلخيص كل مجموعة لا يتعلق بالأخرى فيمكننا إرسال طلبات التلخيص لتلك المجموعات معًا على التوازي لاختصار وقت التلخيص الكلي، فلا داعي في طريقتنا لانتظار تلخيص أول فقرة حتى نلخص التي تليها، وننفذ ذلك باستخدام التابع <code>pool</code> من الصنف المساعد في لارافل <code>HTTP</code> والذي نمرر له تابعًا يقبل معامل من النوع <code>Pool</code> والذي يعبر عن مجموعة من طلبات HTTP ستُرسل معًا على التوازي، توليد الطلب الواحد سنوكله لتابع منفصل بالاسم <code>summaryRequest</code>، وبعد انتهاء كل الطلبات نستخرج منها الملخصات من مفتاح <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D9%84%D9%85-json-r604/" rel="">JSON</a> في المسار <code>choices.0.message.content</code> باستخدام التابع <code>json</code> من كل طلب منها، ثم نضمها معًا مجددًا لتشكل الملخص لكل الفقرات المرسلة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_27" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Summary</span><span class="pln">
</span><span class="pun">{</span><span class="pln">

   </span><span class="pun">...</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> summarize</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $text</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// الفاصل بين الفقرات</span><span class="pln">
        $seperator </span><span class="pun">=</span><span class="pln"> </span><span class="str">"\n\n"</span><span class="pun">;</span><span class="pln">

        </span><span class="com">// فصل النص إلى فقرات بطول مناسب</span><span class="pln">
        $paragraphs </span><span class="pun">=</span><span class="pln"> collect</span><span class="pun">(</span><span class="pln">explode</span><span class="pun">(</span><span class="pln">$seperator</span><span class="pun">,</span><span class="pln"> $text</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">chunk</span><span class="pun">(</span><span class="lit">8</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">map</span><span class="pun">(</span><span class="pln">fn </span><span class="pun">(</span><span class="pln">$chunks</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $chunks</span><span class="pun">-&gt;</span><span class="kwd">join</span><span class="pun">(</span><span class="pln">$seperator</span><span class="pun">));</span><span class="pln">

        </span><span class="com">// إرسال طلبات التلخيص على التوازي</span><span class="pln">
        $responses </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Http</span><span class="pun">::</span><span class="pln">pool</span><span class="pun">(</span><span class="pln">fn </span><span class="pun">(</span><span class="typ">Pool</span><span class="pln"> $pool</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $paragraphs</span><span class="pun">-&gt;</span><span class="pln">map</span><span class="pun">(</span><span class="pln">
            fn </span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $paragraph</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">summaryRequest</span><span class="pun">(</span><span class="pln">$pool</span><span class="pun">,</span><span class="pln"> $paragraph</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">));</span><span class="pln">

        </span><span class="com">// استخراج تجميع الملخصات معًا</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> collect</span><span class="pun">(</span><span class="pln">$responses</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">map</span><span class="pun">(</span><span class="pln">fn </span><span class="pun">(</span><span class="pln">$response</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $response</span><span class="pun">-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="str">'choices.0.message.content'</span><span class="pun">))</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="kwd">join</span><span class="pun">(</span><span class="pln">$seperator</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> summaryRequest</span><span class="pun">(</span><span class="typ">Pool</span><span class="pln"> $pool</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $text</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">...</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ضمن التابع <code>summaryRequest</code> سنرسل الطلب باستخدام <code>pool$</code> إلى ChatGPT لتلخيص محتوى الفقرة <code>text$</code> المٌمررة له، وإرسال أي طلب للواجهة البرمجية الخاصة به تحتاج منا أولًا الحصول على مفتاح استيثاق يمكن توليده بعد إنشاء حساب جديد ضمن موقع الشركة المالكة للنموذج OpenAI وإكمال إعدادات الحساب وتعيين وسيلة الدفع ضمنه، وبعد توليد المفتاح نضعه ضمن ملف متغيرات البيئة env. ضمن مفتاح بالاسم <code>OPENAI_API_KEY</code> ضمن ملفات المشروع لنتمكن من اختبار إرسال الطلبات محليًا كالتالي:
</p>

<pre class="ipsCode">...
OPENAI_API_KEY=&lt;مفتاح الاستيثاق&gt;
</pre>

<p>
	وبحسب <a href="https://platform.openai.com/docs/api-reference/chat" rel="external nofollow">صفحة التوثيق</a> الخاصة بتلك الواجهة البرمجية فيجب أن نضع ذلك المفتاح ضمن قيمة الترويسة <code>Authorization</code> يسبقها الكلمة Bearer ويفصل بينهما مسافة، ويمكننا استخراج قيمة المفتاح السابق باستخدام التابع <code>env</code> من لارافل، ويُرسل طلب HTTP بالنوع POST إلى نموذج المحادثة ChatGPT إلى مسار الواجهة البرمجية <a href="https://api.openai.com/v1/chat/completions%D8%8C" ipsnoembed="true" rel="external nofollow">https://api.openai.com/v1/chat/completions،</a> وضمن جسم الطلب نحدد قيمتين، الأولى هي اسم النموذج ضمن المفتاح model في حالتنا هو gpt-3.5-turbo، والقيمة الثانية هي messages تحوي تاريخ الرسائل الواقعة بين المستخدم والنموذج سابقًا، وفي حالتنا نحتاج رسالة مستخدم واحدة تحوي تعليمات للنموذج بتلخيص الفقرة ضمن تلك الرسالة وصيغتها كالتالي:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		لخص الفقرة التالية من المقال تلخيص دقيق: &lt;الفقرة&gt; التلخيص:
	</p>
</blockquote>

<p>
	سيفهم النموذج التعليمة السابقة ويرد برسالة تحوي تلخيص للفقرة المذكورة، ليكون بذلك تابع تلخيص الفقرة <code>summaryRequest</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1726_29" style=""><span class="pln">    </span><span class="kwd">protected</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> summaryRequest</span><span class="pun">(</span><span class="typ">Pool</span><span class="pln"> $pool</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $text</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $pool
            </span><span class="pun">-&gt;</span><span class="pln">withHeaders</span><span class="pun">([</span><span class="str">'Authorization'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"Bearer "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> env</span><span class="pun">(</span><span class="str">'OPENAI_API_KEY'</span><span class="pun">)])</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">post</span><span class="pun">(</span><span class="str">'https://api.openai.com/v1/chat/completions'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
                </span><span class="str">'model'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'gpt-3.5-turbo'</span><span class="pun">,</span><span class="pln">
                </span><span class="str">'messages'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
                    </span><span class="pun">[</span><span class="str">'role'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'user'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'content'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">"\n"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
                        </span><span class="str">"لخص الفقرة التالية من المقال تلخيص دقيق:"</span><span class="pun">,</span><span class="pln">
                        $text</span><span class="pun">,</span><span class="pln">
                        </span><span class="str">"التلخيص:"</span><span class="pln">
                    </span><span class="pun">])]</span><span class="pln">
                </span><span class="pun">],</span><span class="pln">
            </span><span class="pun">]);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	بذلك يكون تضمين صنف التلخيص <code>Summary</code> جاهزًا سنختبره في الفقرة التالية ونرى نتيجة تلخيصه.
</p>

<h2>
	اختبار التطبيق
</h2>

<p>
	لنختبر التطبيق بتلخيص مقال من موقع أكاديمية حسوب عن <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1-%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A/?do=getLastComment&amp;d=2&amp;id=1877" rel="">الذكاء الاصطناعي</a> بإدخال رابطه ضمن صفحة الإدخال وطلب التلخيص:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="129057" href="https://academy.hsoub.com/uploads/monthly_2023_06/result-1.png.60439f3fdd59781854885724946630ee.png" rel=""><img alt="result-1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="129057" data-unique="b1zs8z8g0" src="https://academy.hsoub.com/uploads/monthly_2023_06/result-1.thumb.png.3507425af00b86e63e5e7bd232823a77.png"> </a>
</p>

<p>
	نلاحظ أن الملخص يحوي ذكر لمعظم الأفكار التي يغطيها المقال ما يعطي صورة عامة عنه، ولنختبره مجددًا بتلخيص جديد من أكاديمية حسوب عن <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/?do=getLastComment&amp;d=2&amp;id=662" rel="">تعلم البرمجة</a>:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="129056" href="https://academy.hsoub.com/uploads/monthly_2023_06/result-2.png.183cd1987ee650fc699af7581250cc46.png" rel=""><img alt="result-2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="129056" data-unique="favu7s8ip" src="https://academy.hsoub.com/uploads/monthly_2023_06/result-2.thumb.png.967d7ec516fd98449d73c6836cb6622f.png"> </a>
</p>

<p>
	يمكن التطوير على التطبيق من عدة نواحي، فمثلًا يمكن أن نوفر للمستخدم خيارات لإدخال محتوى المقال عن طريق رابط مثلًا أو نسخ المحتوى مباشرةً، أو أن نسمح للمستخدم بتحديد طول الملخص الذي يرغب به، أو الطلب من النموذج كتابة الملخص على شكل نقاط رئيسية، أو تحديد لغة النتيجة قبل عرضها للمستخدم، وهناك العديد من الأفكار المفيدة التي يمكن تطبيقها بالاستفادة من نماذج اللغة كنموذج ChatGPT وميزاته بفهم اللغة الطبيعية بلغات متعددة.
</p>
<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة الذكاء الاصطناعي
		</p>

		<p class="banner-subtitle">
			احترف برمجة الذكاء الاصطناعي AI وتحليل البيانات وتعلم كافة المعلومات التي تحتاجها لبناء نماذج ذكاء اصطناعي متخصصة.
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/artificial-intelligence" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<a href="https://academy.hsoub.com/learn/artificial-intelligence" rel=""><img alt="دورة الذكاء الاصطناعي AI" src="https://academy.hsoub.com/learn/assets/images/courses/artificial-intelligence.png"></a>
	</div>
</div>
<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D9%88%D8%B5%D9%81%D8%A9-%D9%84%D8%A7%D9%82%D8%AA%D8%B1%D8%A7%D8%AD-%D8%A7%D9%84%D9%88%D8%AC%D8%A8%D8%A7%D8%AA-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-chatgpt-%D9%88-dall-e-%D9%81%D9%8A-php-r2005/" rel="">تطوير تطبيق 'وصفة' لاقتراح الوجبات باستخدام ChatGPT و DALL-E في PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%AA%D8%B5%D9%86%D9%8A%D9%81-%D8%A7%D9%84%D8%B5%D9%88%D8%B1-%D9%88%D8%A7%D9%84%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D9%88%D8%AC%D9%87-%D9%81%D9%8A-%D9%85%D8%AC%D8%A7%D9%84-%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1-%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A-r1197/" rel="">تصنيف الصور والتعرف على الوجه في مجال الذكاء الاصطناعي</a>
	</li>
	<li>
		دليلك الشامل إلى: <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA/" rel="">برمجة التطبيقات</a>
	</li>
	<li>
		دليلك الشامل إلى: <a href="https://academy.hsoub.com/programming/php/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%84%D8%BA%D8%A9-php-r2040/" rel="">لغة PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2008</guid><pubDate>Thu, 22 Jun 2023 13:00:00 +0000</pubDate></item><item><title>&#x62A;&#x62B;&#x628;&#x64A;&#x62A; &#x648;&#x636;&#x628;&#x637; &#x62A;&#x637;&#x628;&#x64A;&#x642; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; &#x645;&#x639; &#x62E;&#x627;&#x62F;&#x645; Nginx &#x639;&#x644;&#x649; &#x62D;&#x632;&#x645;&#x629; LEMP &#x645;&#x646; &#x623;&#x648;&#x628;&#x646;&#x62A;&#x648;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%B6%D8%A8%D8%B7-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%85%D8%B9-%D8%AE%D8%A7%D8%AF%D9%85-nginx-%D8%B9%D9%84%D9%89-%D8%AD%D8%B2%D9%85%D8%A9-lemp-%D9%85%D9%86-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-r1968/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_04/-------Nginx---Ubuntu.png.d96dfe217ba12c0bfeb891b07e531439.png" /></p>
<p>
	يُعَد <a href="https://wiki.hsoub.com/Laravel" rel="external">لارافيل Laravel</a> إطار عمل بلغة <a href="https://wiki.hsoub.com/PHP" rel="external">PHP</a>، وهو مفتوح المصدر ويوفر مجموعة من الأدوات والموارد لبناء تطبيقات PHP الحديثة. نمت شعبية لارافيل بسرعة في السنوات القليلة الماضية مع وجود نظام بيئي كامل يستفيد من ميزاته المبنية مسبقًا، واعتماد العديد من المطورين له بوصفه إطار العمل المفضل لديهم لعمليات التطوير الفعالة.
</p>

<p>
	سنثبّت ونضبط في هذا المقال تطبيق لارافيل جديد على خادم لينكس أوبنتو Ubuntu 22.04 باستخدام مدير الحزم <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%85%D9%84%D8%AD%D9%86-composer-%D9%85%D8%AF%D9%8A%D8%B1-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D9%81%D9%8A-php-r1123/" rel="">Composer</a> لتنزيل وإدارة اعتماديات إطار العمل وخادم Nginx لتخديم التطبيق، وسيكون لديك في النهاية تطبيق لارافيل تجريبي عملي يسحب المحتوى من قاعدة بيانات MySQL 8.
</p>

<h2>
	المتطلبات الأساسية
</h2>

<p>
	يجب أولًا تنفيذ المهام التالية على <a href="https://academy.hsoub.com/devops/linux/%D8%A7%D9%84%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%A7%D9%84%D8%A3%D9%88%D9%84%D9%8A%D8%A9-%D9%84%D8%AE%D8%A7%D8%AF%D9%85-%D8%A3%D9%88%D8%A8%D9%88%D9%86%D8%AA%D9%88-1804-r431/" rel="">خادم لينكس أوبنتو</a>:
</p>

<ul>
	<li>
		أنشئ مستخدم <code>sudo</code> وفعّل <code>ufw</code>.
	</li>
	<li>
		ثبّت حزمة LEMP مع قاعدة بيانات MySQL 8.
	</li>
	<li>
		ثبّت مدير الحزم Composer الذي سنستخدمه لتثبيت لارافيل واعتمادياته.
	</li>
</ul>

<h2>
	الخطوة الأولى: تثبيت وحدات PHP المطلوبة
</h2>

<p>
	يجب تثبيت بعض وحدات <a href="https://academy.hsoub.com/programming/php/" rel="">PHP</a> التي يتطلبها إطار العمل قبل أن تتمكن من تثبيت لارافيل، حيث سنستخدم الأمر <code>apt</code> لتثبيت وحدات PHP، وهي وحدات <code>php-mbstring</code> و <code>php-xml</code> و <code>php-bcmath</code>. توفر هذه التوسّعات الخاصة <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AF%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%B3%D8%B1%D9%8A%D8%B9-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-php-r609/" rel="">بلغة PHP</a> دعمًا إضافيًا للتعامل مع تشفير المحارف وتنسيق XML والدقة الرياضية.
</p>

<p>
	إذا كانت هذه هي المرة الأولى التي تستخدم فيها الأمر <code>apt</code> في هذه الجلسة، فيجب عليك أولًا تشغيل أمر <code>update</code> التالي لتحديث جدول الحزم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_7" style=""><span class="pln">sudo apt update</span></pre>

<p>
	يمكنك الآن تثبيت الحزم المطلوبة باستخدام الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_9" style=""><span class="pln">sudo apt install php</span><span class="pun">-</span><span class="pln">mbstring php</span><span class="pun">-</span><span class="pln">xml php</span><span class="pun">-</span><span class="pln">bcmath</span></pre>

<p>
	أصبح نظامك جاهزًا لتنفيذ تثبيت لارافيل باستخدام مدير الحزم Composer، ولكن ستحتاج إلى قاعدة بيانات لتطبيقك قبل ذلك.
</p>

<h2>
	الخطوة الثانية: إنشاء قاعدة بيانات للتطبيق
</h2>

<p>
	سننشئ تطبيق قائمة السفر Travel List الذي يعرض قائمة بالأماكن التي يرغب المستخدم في السفر إليها وقائمة بالأماكن التي زارها فعليًا لتوضيح تثبيت لارافيل واستخدامه الأساسي، حيث يمكن تخزين هذه القوائم في جدول الأماكن Places مع حقل للمواقع التي سنسميه name وحقل آخر لتمييز المواقع بوصفها مُزارة visited أو غير مُزارة not visited، حيث سنسميه هذا الحقل visited، وسنضمّن حقل المعرّف id لتحديد كل إدخال بصورة فريدة. سننشئ مستخدم MySQL مخصص ونمنحه صلاحيات كاملة في قاعدة البيانات <code>travellist</code> للاتصال بقاعدة البيانات من تطبيق لارافيل.
</p>

<p>
	<a href="https://www.php.net/manual/en/ref.pdo-mysql.php" rel="external nofollow">لا تدعم المكتبة <code>mysqlnd</code></a> -وهي مكتبة MySQL PHP الأصيلة- التابعَ <code>caching_sha2_authentication</code> الذي هو تابع الاستيثاق الافتراضي لقاعدة بيانات MySQL 8، لذا يجب إعداد مستخدم <a href="https://academy.hsoub.com/devops/servers/databases/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-database/" rel="">قاعدة البيانات</a> باستخدام تابع الاستيثاق <code>mysql_native_password</code> حتى نتمكّن من الاتصال بقاعدة بيانات MySQL من PHP.
</p>

<p>
	أولًا، سجّل الدخول إلى طرفية <a href="https://academy.hsoub.com/devops/servers/databases/%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%A8%D9%8A%D9%86-mysql-%D9%88-mongodb-r627/" rel="">MySQL</a> بوصفك مستخدم قاعدة البيانات الجذر باستخدام الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_14" style=""><span class="pln">sudo mysql</span></pre>

<p>
	شغّل الأمر التالي من طرفية MySQL لإنشاء قاعدة بيانات جديدة:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_16" style=""><span class="pln">CREATE DATABASE travellist</span><span class="pun">;</span></pre>

<p>
	يمكنك الآن إنشاء مستخدم جديد ومنحه الصلاحيات الكاملة في قاعدة البيانات المخصصة التي أنشأتها، حيث سننشئ في مثالنا مستخدم باسم <code>travellist_user</code> مع كلمة مرور <code>password</code> بالرغم من أنه يجب عليك تغييرها إلى كلمة مرور آمنة من اختيارك:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_18" style=""><span class="pln">CREATE USER </span><span class="str">'travellist_user'</span><span class="pun">@</span><span class="str">'%'</span><span class="pln"> IDENTIFIED WITH mysql_native_password BY </span><span class="str">'password'</span><span class="pun">;</span></pre>

<p>
	يجب الآن أن نمنح هذا المستخدم إذنًا في قاعدة بيانات <code>travellist</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_21" style=""><span class="pln">GRANT ALL ON travellist</span><span class="pun">.*</span><span class="pln"> TO </span><span class="str">'travellist_user'</span><span class="pun">@</span><span class="str">'%'</span><span class="pun">;</span></pre>

<p>
	مما يؤدي إلى إعطاء المستخدم travellist_user الصلاحيات الكاملة في قاعدة بيانات <code>travellist</code>، مع منع هذا المستخدم من إنشاء أو تعديل قواعد بيانات أخرى على خادمك.
</p>

<p>
	اخرج بعد ذلك من صدفة MySQL:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_23" style=""><span class="kwd">exit</span></pre>

<p>
	يمكنك الآن اختبار ما إذا كان المستخدم الجديد لديه الأذونات المناسبة من خلال تسجيل الدخول إلى طرفية MySQL مرة أخرى باستخدام ثبوتيات المستخدم المخصَّص هذه المرة:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_25" style=""><span class="pln">mysql </span><span class="pun">-</span><span class="pln">u travellist_user </span><span class="pun">-</span><span class="pln">p</span></pre>

<p>
	لاحظ الخيار <code>‎-p</code> في هذا الأمر، والتي ستطلب كلمة المرور المُستخدَمة عند إنشاء المستخدم <code>travellist_user</code>. تأكد بعد تسجيل الدخول إلى طرفية MySQL من أنه يمكنك الوصول إلى قاعدة بيانات <code>travellist</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_28" style=""><span class="pln">SHOW DATABASES</span><span class="pun">;</span></pre>

<p>
	وسيظهر الخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_30" style=""><span class="pun">+--------------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="typ">Database</span><span class="pln">           </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------------------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> information_schema </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> travellist        </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+--------------------+</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> rows </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.01</span><span class="pln"> sec</span><span class="pun">)</span></pre>

<p>
	أنشئ بعد ذلك جدولًا بالاسم <code>places</code> في قاعدة البيانات <code>travellist</code> من خلال تشغيل التعليمة التالية من طرفية MySQL:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_32" style=""><span class="pln">CREATE TABLE travellist</span><span class="pun">.</span><span class="pln">places </span><span class="pun">(</span><span class="pln">
    id INT AUTO_INCREMENT</span><span class="pun">,</span><span class="pln">
    name VARCHAR</span><span class="pun">(</span><span class="lit">255</span><span class="pun">),</span><span class="pln">
    visited BOOLEAN</span><span class="pun">,</span><span class="pln">
    PRIMARY KEY</span><span class="pun">(</span><span class="pln">id</span><span class="pun">)</span><span class="pln">
</span><span class="pun">);</span></pre>

<p>
	املأ الجدول <code>places</code> ببعض البيانات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_34" style=""><span class="pln">INSERT INTO travellist</span><span class="pun">.</span><span class="pln">places </span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> visited</span><span class="pun">)</span><span class="pln">
VALUES </span><span class="pun">(</span><span class="str">"Tokyo"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Budapest"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Nairobi"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Berlin"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Lisbon"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Denver"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Moscow"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Olso"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Rio"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Cincinnati"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">),</span><span class="pln">
</span><span class="pun">(</span><span class="str">"Helsinki"</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">);</span></pre>

<p>
	شغّل التعليمة التالية لتأكيد حفظ البيانات بنجاح في جدولك:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_36" style=""><span class="pln">SELECT </span><span class="pun">*</span><span class="pln"> FROM travellist</span><span class="pun">.</span><span class="pln">places</span><span class="pun">;</span></pre>

<p>
	وسترى خرجًا مشابهًا لما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_38" style=""><span class="pun">+----+-----------+---------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> id </span><span class="pun">|</span><span class="pln"> name      </span><span class="pun">|</span><span class="pln"> visited </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----+-----------+---------+</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Tokyo</span><span class="pln">     </span><span class="pun">|</span><span class="pln">       </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Budapest</span><span class="pln">  </span><span class="pun">|</span><span class="pln">       </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">3</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Nairobi</span><span class="pln">   </span><span class="pun">|</span><span class="pln">       </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">4</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Berlin</span><span class="pln">    </span><span class="pun">|</span><span class="pln">       </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">5</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Lisbon</span><span class="pln">    </span><span class="pun">|</span><span class="pln">       </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Denver</span><span class="pln">    </span><span class="pun">|</span><span class="pln">       </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">7</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Moscow</span><span class="pln">    </span><span class="pun">|</span><span class="pln">       </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">8</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Oslo</span><span class="pln">      </span><span class="pun">|</span><span class="pln">       </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln">  </span><span class="lit">9</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Rio</span><span class="pln">       </span><span class="pun">|</span><span class="pln">       </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Cincinnati</span><span class="pun">|</span><span class="pln">       </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> </span><span class="lit">11</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="typ">Helsinki</span><span class="pln">  </span><span class="pun">|</span><span class="pln">       </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----+-----------+---------+</span><span class="pln">
</span><span class="lit">11</span><span class="pln"> rows </span><span class="kwd">in</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.00</span><span class="pln"> sec</span><span class="pun">)</span></pre>

<p>
	يمكنك الخروج من طرفية MySQL بعد التأكد من وجود بيانات صالحة في جدول اختبارك:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_40" style=""><span class="kwd">exit</span></pre>

<p>
	أصبحتَ الآن جاهزًا لإنشاء التطبيق وضبطه للاتصال بقاعدة البيانات الجديدة.
</p>

<h2>
	الخطوة الثالثة: إنشاء تطبيق لارافيل جديد
</h2>

<p>
	ستنشئ الآن تطبيق لارافيل جديد باستخدام الأمر <code>composer create-project</code>، إذ يُستخدَم هذا الأمر لتشغيل التطبيقات الجديدة بناءً على أطر العمل وأنظمة إدارة المحتوى الحالية.
</p>

<p>
	سنستخدم في هذا المقال الاسم <code>travellist</code> للتطبيق، ولكن يمكنك تغييره إلى أي شيء آخر. سيعرض تطبيق <code>travellist</code> قائمةً بالمواقع المسحوبة من خادم MySQL محلي بهدف توضيح ضبط تطبيق لارافيل الأساسي والتأكد من قدرتك على الاتصال بقاعدة البيانات.
</p>

<p>
	انتقل أولًا إلى مجلد المنزل كما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_42" style=""><span class="pln">cd </span><span class="pun">~</span></pre>

<p>
	ينشئ الأمر التالي مجلد <code>travellist</code> جديد يحتوي على تطبيق لارافيل هيكلي استنادًا إلى الإعدادات الافتراضية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_48" style=""><span class="pln">composer create</span><span class="pun">-</span><span class="pln">project </span><span class="pun">--</span><span class="pln">prefer</span><span class="pun">-</span><span class="pln">dist laravel</span><span class="pun">/</span><span class="pln">laravel travellist</span></pre>

<p>
	وسترى خرجًا مشابهًا لما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_46" style=""><span class="typ">Creating</span><span class="pln"> a </span><span class="str">"laravel/laravel"</span><span class="pln"> project at </span><span class="str">"./travellist"</span><span class="pln">
</span><span class="typ">Installing</span><span class="pln"> laravel</span><span class="pun">/</span><span class="pln">laravel </span><span class="pun">(</span><span class="pln">v10</span><span class="pun">.</span><span class="lit">1.1</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Downloading</span><span class="pln"> laravel</span><span class="pun">/</span><span class="pln">laravel </span><span class="pun">(</span><span class="pln">v10</span><span class="pun">.</span><span class="lit">1.1</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Installing</span><span class="pln"> laravel</span><span class="pun">/</span><span class="pln">laravel </span><span class="pun">(</span><span class="pln">v10</span><span class="pun">.</span><span class="lit">1.1</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Extracting</span><span class="pln"> archive
</span><span class="typ">Created</span><span class="pln"> project </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">/</span><span class="pln">tmp</span><span class="pun">/</span><span class="pln">travellist
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">@php</span><span class="pln"> </span><span class="pun">-</span><span class="pln">r </span><span class="str">"file_exists('.env') || copy('.env.example', '.env');"</span><span class="pln">
</span><span class="typ">Loading</span><span class="pln"> composer repositories </span><span class="kwd">with</span><span class="pln"> </span><span class="kwd">package</span><span class="pln"> information
</span><span class="typ">Updating</span><span class="pln"> dependencies
</span><span class="typ">Lock</span><span class="pln"> file operations</span><span class="pun">:</span><span class="pln"> </span><span class="lit">106</span><span class="pln"> installs</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> updates</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> removals
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Locking</span><span class="pln"> brick</span><span class="pun">/</span><span class="pln">math </span><span class="pun">(</span><span class="lit">0.11</span><span class="pun">.</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Locking</span><span class="pln"> dflydev</span><span class="pun">/</span><span class="pln">dot</span><span class="pun">-</span><span class="pln">access</span><span class="pun">-</span><span class="pln">data </span><span class="pun">(</span><span class="pln">v3</span><span class="pun">.</span><span class="lit">0.2</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Locking</span><span class="pln"> doctrine</span><span class="pun">/</span><span class="pln">inflector </span><span class="pun">(</span><span class="lit">2.0</span><span class="pun">.</span><span class="lit">6</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Locking</span><span class="pln"> doctrine</span><span class="pun">/</span><span class="pln">lexer </span><span class="pun">(</span><span class="lit">3.0</span><span class="pun">.</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Locking</span><span class="pln"> dragonmantank</span><span class="pun">/</span><span class="pln">cron</span><span class="pun">-</span><span class="pln">expression </span><span class="pun">(</span><span class="pln">v3</span><span class="pun">.</span><span class="lit">3.2</span><span class="pun">)</span><span class="pln">
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Locking</span><span class="pln"> egulias</span><span class="pun">/</span><span class="pln">email</span><span class="pun">-</span><span class="pln">validator </span><span class="pun">(</span><span class="lit">4.0</span><span class="pun">.</span><span class="lit">1</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	انتقل إلى مجلد التطبيق عند انتهاء التثبيت وشغّل أمر لارافيل <code>artisan</code> للتحقق من تثبيت جميع المكونات بنجاح:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_50" style=""><span class="pln">cd travellist
php artisan</span></pre>

<p>
	وسترى خرجًا مشابهًا لما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_52" style=""><span class="typ">Laravel</span><span class="pln"> </span><span class="typ">Framework</span><span class="pln"> </span><span class="lit">10.9</span><span class="pun">.</span><span class="lit">0</span><span class="pln">

</span><span class="typ">Usage</span><span class="pun">:</span><span class="pln">
  command </span><span class="pun">[</span><span class="pln">options</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="pln">arguments</span><span class="pun">]</span><span class="pln">

</span><span class="typ">Options</span><span class="pun">:</span><span class="pln">
  </span><span class="pun">-</span><span class="pln">h</span><span class="pun">,</span><span class="pln"> </span><span class="pun">--</span><span class="pln">help            </span><span class="typ">Display</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> help message
  </span><span class="pun">-</span><span class="pln">q</span><span class="pun">,</span><span class="pln"> </span><span class="pun">--</span><span class="pln">quiet           </span><span class="typ">Do</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> output any message
  </span><span class="pun">-</span><span class="pln">V</span><span class="pun">,</span><span class="pln"> </span><span class="pun">--</span><span class="pln">version         </span><span class="typ">Display</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> application version
      </span><span class="pun">--</span><span class="pln">ansi            </span><span class="typ">Force</span><span class="pln"> ANSI output
      </span><span class="pun">--</span><span class="kwd">no</span><span class="pun">-</span><span class="pln">ansi         </span><span class="typ">Disable</span><span class="pln"> ANSI output
  </span><span class="pun">-</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> </span><span class="pun">--</span><span class="kwd">no</span><span class="pun">-</span><span class="pln">interaction  </span><span class="typ">Do</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> ask any interactive question
      </span><span class="pun">--</span><span class="pln">env</span><span class="pun">[=</span><span class="pln">ENV</span><span class="pun">]</span><span class="pln">       </span><span class="typ">The</span><span class="pln"> environment the command should run under
  </span><span class="pun">-</span><span class="pln">v</span><span class="pun">|</span><span class="pln">vv</span><span class="pun">|</span><span class="pln">vvv</span><span class="pun">,</span><span class="pln"> </span><span class="pun">--</span><span class="pln">verbose  </span><span class="typ">Increase</span><span class="pln"> the verbosity </span><span class="kwd">of</span><span class="pln"> messages</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> normal output</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> more verbose output </span><span class="kwd">and</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> debug
</span><span class="pun">...</span></pre>

<p>
	يؤكد هذا الخرج أن ملفات التطبيق في مكانها المناسب، وأن أدوات سطر أوامر لارافيل تعمل كما هو متوقع، ولكن ما زلنا بحاجة إلى ضبط التطبيق لإعداد قاعدة البيانات وبعض التفاصيل الأخرى.
</p>

<h2>
	الخطوة الرابعة: ضبط تطبيق لارافيل
</h2>

<p>
	توجد ملفات ضبط لارافيل في مجلد بالاسم <code>config</code> ضمن المجلد الجذر للتطبيق، وإذا ثَبّتَ لارافيل باستخدام مدير الحزم Composer، فسينشئ ملف بيئة Environment File، حيث يحتوي هذا الملف على إعدادات خاصة بالبيئة الحالية التي يعمل بها التطبيق، وستكون لها الأفضلية على القيم المحددة في ملفات الضبط العادية الموجودة في المجلد <code>config</code>. يتطلب كل تثبيت في بيئة جديدة ملف بيئة مخصص لتعريف أشياء مثل إعدادات اتصال قاعدة البيانات وخيارات تنقيح الأخطاء <a href="https://academy.hsoub.com/programming/general/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%B9%D9%86%D9%88%D8%A7%D9%86-url-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87-r1435/" rel="">وعنوان URL</a> للتطبيق وعناصر أخرى تختلف اعتمادًا على البيئة التي يعمل بها التطبيق.
</p>

<p>
	<strong>تحذير</strong>: يحتوي ملف ضبط البيئة على معلومات حساسة حول خادمك، بما في ذلك ثبوتيات قاعدة البيانات ومفاتيح الأمان، لذلك لا يجب أبدًا مشاركة هذا الملف علنًا.
</p>

<p>
	سنعدّل ملف <code>‎.env</code> لتخصيص خيارات الضبط لبيئة التطبيق الحالية. افتح ملف <code>‎.env</code> باستخدام محرر سطر الأوامر الذي تختاره، حيث سنستخدم هنا <code>nano</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_55" style=""><span class="pln">nano </span><span class="pun">.</span><span class="pln">env</span></pre>

<p>
	توجد العديد من متغيرات الضبط في هذا الملف، ولكنك لن تحتاج إلى إعدادها جميعًا الآن. تحتوي القائمة التالية على نظرة عامة على المتغيرات التي يجب الاهتمام بها:
</p>

<ul>
	<li>
		<code>APP_NAME</code>: اسم التطبيق المُستخدَم للإشعارات والرسائل.
	</li>
	<li>
		<code>APP_ENV</code>: بيئة التطبيق الحالية.
	</li>
	<li>
		<code>APP_KEY</code>: يُستخدم لتوليد السلاسل النصية الإضافية Salts والقيم المُعمَّاة المختصَرة Hashes، ويُنشَأ هذا المفتاح الفريد تلقائيًا عند تثبيت لارافيل باستخدام مدير الحزم Composer، لذلك لا حاجة إلى تغييره.
	</li>
	<li>
		<code>APP_DEBUG</code>: يحدد إظهار معلومات تنقيح الأخطاء من طرف العميل أم لا.
	</li>
	<li>
		<code>APP_URL</code>: عنوان URL الأساسي للتطبيق، ويُستخدَم لتوليد روابط التطبيق.
	</li>
	<li>
		<code>DB_DATABASE</code>: اسم قاعدة البيانات.
	</li>
	<li>
		<code>DB_USERNAME</code>: اسم المستخدم للاتصال بقاعدة البيانات.
	</li>
	<li>
		<code>DB_PASSWORD</code>: كلمة المرور للاتصال بقاعدة البيانات.
	</li>
</ul>

<p>
	تُضبَط هذه القيم افتراضيًا لبيئة التطوير المحلية التي تستخدم بيئة تطوير <a href="https://laravel.com/docs/10.x/homestead" rel="external nofollow">Homestead</a>، وهي بيئة أداة Vagrant المُحزَّمة مسبَقًا التي يوفّرها إطار عمل لارافيل، حيث سنغيّر هذه القيم لتمثل إعدادات البيئة الحالية لتطبيقنا.
</p>

<p>
	إذا أردتَ تثبيت لارافيل في بيئة تطوير development أو اختبار testing، فيمكنك ترك الخيار <code>APP_DEBUG</code> مفعّلًا، حيث سيعطيك هذا الخيار معلومات تنقيح الأخطاء المهمة أثناء اختبار التطبيق من المتصفح، ويجب ضبط المتغير <code>APP_ENV</code> على القيمة <code>development</code> أو <code>testing</code> في هذه الحالة. بينما إذا أردتَ تثبيت لارافيل في بيئة الإنتاج، فيجب عليك تعطيل الخيار <code>APP_DEBUG</code>، لأنه يعرض معلومات حساسة حول تطبيقك للمستخدم النهائي، ويجب ضبط المتغير <code>APP_ENV</code> على القيمة <code>production</code> في هذه الحالة.
</p>

<p>
	<strong>ملاحظة</strong>: يحتوي المتغير <code>APP_KEY</code> على مفتاح فريد ينشأ تلقائيًا عند تثبيت لارافيل باستخدام <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%85%D9%84%D8%AD%D9%86-composer-%D9%85%D8%AF%D9%8A%D8%B1-%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF%D9%8A%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AD%D8%B2%D9%85-%D9%81%D9%8A-php-r1123/" rel="">مدير الحزم Composer</a>، ولست بحاجة إلى تغيير هذه القيمة. إذا أردتَ إنشاء مفتاح أمان جديد، فيمكنك استخدام الأمر <code>php artisan key:generate</code>.
</p>

<p>
	يضبط ملف <code>‎.env</code> التالي تطبيقنا من أجل عملية التطوير كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_58" style=""><span class="pln">APP_NAME</span><span class="pun">=</span><span class="typ">TravelList</span><span class="pln">
APP_ENV</span><span class="pun">=</span><span class="pln">development
APP_KEY</span><span class="pun">=</span><span class="pln">APPLICATION_UNIQUE_KEY_DONT_COPY
APP_DEBUG</span><span class="pun">=</span><span class="kwd">true</span><span class="pln">
APP_URL</span><span class="pun">=</span><span class="pln">http</span><span class="pun">:</span><span class="com">//domain_or_IP</span><span class="pln">

LOG_CHANNEL</span><span class="pun">=</span><span class="pln">stack

DB_CONNECTION</span><span class="pun">=</span><span class="pln">mysql
DB_HOST</span><span class="pun">=</span><span class="lit">127.0</span><span class="pun">.</span><span class="lit">0.1</span><span class="pln">
DB_PORT</span><span class="pun">=</span><span class="lit">3306</span><span class="pln">
DB_DATABASE</span><span class="pun">=</span><span class="pln">travellist
DB_USERNAME</span><span class="pun">=</span><span class="pln">travellist_user
DB_PASSWORD</span><span class="pun">=</span><span class="pln">password

</span><span class="pun">...</span></pre>

<p>
	عدّل متغيراتك وفقًا لذلك، ثم احفظ الملف وأغلقه للاحتفاظ بالتغييرات التي أجريتها، حيث إذا كنت تستخدم المحرر <code>nano</code>، فيمكنك تطبيق ذلك باستخدام <code>CTRL+X</code> ثم اضغط على <code>Y</code> و <code>Enter</code> للتأكيد.
</p>

<p>
	ضبطنا الآن تطبيق لارافيل، ولكننا ما زلنا بحاجة إلى ضبط <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AE%D8%A7%D8%AF%D9%85-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r574/" rel="">خادم الويب</a> حتى نتمكّن من الوصول إليه من المتصفح، حيث سنضبط خادم Nginx لخدمة تطبيق لارافيل في الخطوة التالية.
</p>

<h2>
	الخطوة الخامسة: إعداد خادم Nginx
</h2>

<p>
	ثبّتنا لارافيل في مجلد محلي من المجلد الرئيسي للمستخدم البعيد، إذ يعمل ذلك جيدًا مع بيئات التطوير المحلية، إلا أنه ليس ممارسة موصًى بها لخوادم الويب المفتوحة لشبكة الإنترنت العامة. سننقل مجلد التطبيق إلى <code>‎/var/www</code>، وهو الموقع المعتاد لتطبيقات الويب التي تعمل على خادم Nginx.
</p>

<p>
	أولًا، استخدم الأمر <code>mv</code> لنقل مجلد التطبيق بكل محتوياته إلى <code>‎/var/www/travellist</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_63" style=""><span class="pln">sudo mv </span><span class="pun">~</span><span class="str">/travellist /</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">www</span><span class="pun">/</span><span class="pln">travellist</span></pre>

<p>
	يجب الآن منح مستخدم خادم الويب إذن الوصول للكتابة في مجلدات <code>storage</code> و <code>cache</code> حيث يخزّن لارافيل الملفات التي أنشأها التطبيق كما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_67" style=""><span class="pln">sudo chown </span><span class="pun">-</span><span class="pln">R www</span><span class="pun">-</span><span class="pln">data</span><span class="pun">.</span><span class="pln">www</span><span class="pun">-</span><span class="pln">data </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">www</span><span class="pun">/</span><span class="pln">travellist</span><span class="pun">/</span><span class="pln">storage
sudo chown </span><span class="pun">-</span><span class="pln">R www</span><span class="pun">-</span><span class="pln">data</span><span class="pun">.</span><span class="pln">www</span><span class="pun">-</span><span class="pln">data </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">www</span><span class="pun">/</span><span class="pln">travellist</span><span class="pun">/</span><span class="pln">bootstrap</span><span class="pun">/</span><span class="pln">cache</span></pre>

<p>
	أصبحت ملفات التطبيق مرتبة الآن، ولكننا ما زلنا بحاجة إلى ضبط خادم Nginx لخدمة المحتوى، لذا سننشئ ملف ضبط مضيف وهمي جديد في <code>‎/etc/nginx/sites-available</code>:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_69" style=""><span class="pln">sudo nano </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">sites</span><span class="pun">-</span><span class="pln">available</span><span class="pun">/</span><span class="pln">travellist</span></pre>

<p>
	يحتوي ملف الضبط التالي على <a href="https://laravel.com/docs/5.8/deployment#server-configuration" rel="external nofollow">الإعدادات الموصَى بها</a> لتطبيقات لارافيل على خادم Nginx:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_71" style=""><span class="pln">server </span><span class="pun">{</span><span class="pln">
    listen </span><span class="lit">80</span><span class="pun">;</span><span class="pln">
    server_name server_domain_or_IP</span><span class="pun">;</span><span class="pln">
    root </span><span class="pun">/</span><span class="kwd">var</span><span class="pun">/</span><span class="pln">www</span><span class="pun">/</span><span class="pln">travellist</span><span class="pun">/</span><span class="kwd">public</span><span class="pun">;</span><span class="pln">

    add_header X</span><span class="pun">-</span><span class="typ">Frame</span><span class="pun">-</span><span class="typ">Options</span><span class="pln"> </span><span class="str">"SAMEORIGIN"</span><span class="pun">;</span><span class="pln">
    add_header X</span><span class="pun">-</span><span class="pln">XSS</span><span class="pun">-</span><span class="typ">Protection</span><span class="pln"> </span><span class="str">"1; mode=block"</span><span class="pun">;</span><span class="pln">
    add_header X</span><span class="pun">-</span><span class="typ">Content</span><span class="pun">-</span><span class="typ">Type</span><span class="pun">-</span><span class="typ">Options</span><span class="pln"> </span><span class="str">"nosniff"</span><span class="pun">;</span><span class="pln">

    index index</span><span class="pun">.</span><span class="pln">html index</span><span class="pun">.</span><span class="pln">htm index</span><span class="pun">.</span><span class="pln">php</span><span class="pun">;</span><span class="pln">

    charset utf</span><span class="pun">-</span><span class="lit">8</span><span class="pun">;</span><span class="pln">

    location </span><span class="pun">/</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        try_files $uri $uri</span><span class="pun">/</span><span class="pln"> </span><span class="pun">/</span><span class="pln">index</span><span class="pun">.</span><span class="pln">php</span><span class="pun">?</span><span class="pln">$query_string</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    location </span><span class="pun">=</span><span class="pln"> </span><span class="pun">/</span><span class="pln">favicon</span><span class="pun">.</span><span class="pln">ico </span><span class="pun">{</span><span class="pln"> access_log off</span><span class="pun">;</span><span class="pln"> log_not_found off</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    location </span><span class="pun">=</span><span class="pln"> </span><span class="pun">/</span><span class="pln">robots</span><span class="pun">.</span><span class="pln">txt  </span><span class="pun">{</span><span class="pln"> access_log off</span><span class="pun">;</span><span class="pln"> log_not_found off</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    error_page </span><span class="lit">404</span><span class="pln"> </span><span class="pun">/</span><span class="pln">index</span><span class="pun">.</span><span class="pln">php</span><span class="pun">;</span><span class="pln">

    location </span><span class="pun">~</span><span class="pln"> \.php$ </span><span class="pun">{</span><span class="pln">
        fastcgi_pass unix</span><span class="pun">:</span><span class="str">/var/</span><span class="pln">run</span><span class="pun">/</span><span class="pln">php</span><span class="pun">/</span><span class="pln">php7</span><span class="pun">.</span><span class="lit">4</span><span class="pun">-</span><span class="pln">fpm</span><span class="pun">.</span><span class="pln">sock</span><span class="pun">;</span><span class="pln">
        fastcgi_index index</span><span class="pun">.</span><span class="pln">php</span><span class="pun">;</span><span class="pln">
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name</span><span class="pun">;</span><span class="pln">
        include fastcgi_params</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    location </span><span class="pun">~</span><span class="pln"> </span><span class="pun">/</span><span class="pln">\.</span><span class="pun">(?!</span><span class="pln">well</span><span class="pun">-</span><span class="pln">known</span><span class="pun">).*</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        deny all</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	انسخ هذا المحتوى إلى الملف <code>‎/etc/nginx/sites-available/travellist</code>، واضبط القيم <code>server_domain_or_IP</code> و <code>travellist</code> التي تمثل اسم الخادم والمجلد الجذر لتتماشى مع ضبطك الخاص إن لزم الأمر. احفظ الملف وأغلقه عند الانتهاء من التعديل.
</p>

<p>
	أنشئ وصلة رمزية إلى <code>travellist</code> في الملف <code>sites-enabled</code> لتنشيط ملف ضبط المضيف الوهمي الجديد كما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_73" style=""><span class="pln">sudo ln </span><span class="pun">-</span><span class="pln">s </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">sites</span><span class="pun">-</span><span class="pln">available</span><span class="pun">/</span><span class="pln">travellist </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">sites</span><span class="pun">-</span><span class="pln">enabled</span><span class="pun">/</span></pre>

<p>
	<strong>ملاحظة</strong>: إذا كان لديك ملف مضيف وهمي آخر مضبوط مسبقًا على اسم الخادم <code>server_name</code> نفسه المُستخدَم في المضيف الوهمي <code>travellist</code>، فيمكن أن تحتاج إلى تعطيل الضبط القديم من خلال إزالة الرابط الرمزي المقابل في <code>/etc/nginx/sites-enabled/</code>.
</p>

<p>
	يمكنك استخدام الأمر التالي للتأكد من أن الضبط لا يحتوي على أيّ أخطاء صياغية:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_75" style=""><span class="pln">sudo nginx </span><span class="pun">-</span><span class="pln">t</span></pre>

<p>
	ويجب أن ترى خرجًا يشبه ما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_77" style=""><span class="typ">Outputnginx</span><span class="pun">:</span><span class="pln"> the configuration file </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">.</span><span class="pln">conf syntax </span><span class="kwd">is</span><span class="pln"> ok
nginx</span><span class="pun">:</span><span class="pln"> configuration file </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">.</span><span class="pln">conf test </span><span class="kwd">is</span><span class="pln"> successful</span></pre>

<p>
	أعِد تحميل خادم Nginx باستخدام الأمر التالي لتطبيق التغييرات:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_5346_79" style=""><span class="pln">sudo systemctl reload nginx</span></pre>

<p>
	انتقل الآن إلى متصفحك وادخل إلى التطبيق باستخدام اسم نطاق أو عنوان IP الخاص بالخادم كما حدّده الموجّه <code>server_name</code> في ملف ضبطك الخاص:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_81" style=""><span class="pln">http</span><span class="pun">:</span><span class="com">//server_domain_or_IP</span></pre>

<p>
	وسترى صفحة تشبه ما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="124056" href="https://academy.hsoub.com/uploads/monthly_2023_04/01_laravel.png.2f2bcf8c304d31c8738ba9c88ad2fc5e.png" rel=""><img alt="01_laravel.png" class="ipsImage ipsImage_thumbnailed" data-fileid="124056" data-unique="dq6zaf002" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2023_04/01_laravel.png.2f2bcf8c304d31c8738ba9c88ad2fc5e.png"> </a>
</p>

<p>
	يؤكد ذلك أن خادم Nginx مضبوط بصورة صحيحة لخدمة تطبيق لارافيل، ويمكنك بعد ذلك البدء في إنشاء تطبيقك على التطبيق الهيكلي الذي يوفره التثبيت الافتراضي.
</p>

<p>
	سنعدّل في الخطوة التالية طريق التطبيق الرئيسي للاستعلام عن البيانات في قاعدة البيانات باستخدام واجهة <code>DB</code> في إطار عمل لارافيل.
</p>

<h2>
	الخطوة السادسة: إنشاء صفحتك الرئيسية
</h2>

<p>
	يجب أن يكون لديك تطبيق لارافيل يعمل بنجاح وجدول قاعدة بيانات بالاسم <code>places</code> يحتوي على بعض البيانات بافتراض أنك اتبعت جميع الخطوات الواردة في هذا المقال حتى الآن، وسنعدّل الآن مسار التطبيق الرئيسي للاستعلام عن قاعدة البيانات وإعادة المحتويات إلى عرض التطبيق.
</p>

<p>
	افتح ملف الموجهات Routes الرئيسي <code>routes/web.php</code>:
</p>

<pre class="ipsCode">nano routes/web.php
</pre>

<p>
	يحتوي هذا الملف افتراضيًا على المحتوى التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_84" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="com">/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'welcome'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	تُحدَّد الطرق ضمن هذا الملف باستخدام التابع الساكن <code>Route::get</code> الذي يأخذ مسارًا Path ودالة رد نداء بوصفهما وسائطًا.
</p>

<p>
	تحل الشيفرة البرمجية الآتية محل دالة رد نداء الطريق الرئيسي، حيث تجري استعلامَين إلى قاعدة البيانات باستخدام الراية <code>visited</code> لترشيح النتائج، وتعيد النتائج إلى عرض بالاسم <code>travellist</code> الذي سننشئه لاحقًا. انسخ المحتوى التالي إلى الملف <code>routes/web.php</code> بدلًا من الشيفرة البرمجية الموجودة مسبقًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_86" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\DB</span><span class="pun">;</span><span class="pln">

</span><span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  $visited </span><span class="pun">=</span><span class="pln"> DB</span><span class="pun">::</span><span class="kwd">select</span><span class="pun">(</span><span class="str">'select * from places where visited = ?'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">]);</span><span class="pln">    
  $togo </span><span class="pun">=</span><span class="pln"> DB</span><span class="pun">::</span><span class="kwd">select</span><span class="pun">(</span><span class="str">'select * from places where visited = ?'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">

  </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'travellist'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'visited'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $visited</span><span class="pun">,</span><span class="pln"> </span><span class="str">'togo'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $togo </span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	احفظ الملف وأغلقه عند الانتهاء من التعديل. سننشئ الآن العرض الذي سيعرض نتائج قاعدة البيانات للمستخدِم، لذا أنشِئ ملف عرض جديد ضمن المجلد <code>resources/views</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5346_88" style=""><span class="pln">nano resources</span><span class="pun">/</span><span class="pln">views</span><span class="pun">/</span><span class="pln">travellist</span><span class="pun">.</span><span class="pln">blade</span><span class="pun">.</span><span class="pln">php</span></pre>

<p>
	يُنشِئ القالب التالي قائمتين من الأماكن بناءً على المتغيرات <code>visited</code> و <code>togo</code>. انسخ المحتوى التالي إلى ملف العرض الجديد:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5346_90" style=""><span class="tag">&lt;html&gt;</span><span class="pln">
</span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;title&gt;</span><span class="pln">Travel List</span><span class="tag">&lt;/title&gt;</span><span class="pln">
</span><span class="tag">&lt;/head&gt;</span><span class="pln">

</span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;h1&gt;</span><span class="pln">My Travel Bucket List</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
    </span><span class="tag">&lt;h2&gt;</span><span class="pln">Places I'd Like to Visit</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
    </span><span class="tag">&lt;ul&gt;</span><span class="pln">
      @foreach ($togo as $newplace)
        </span><span class="tag">&lt;li&gt;</span><span class="pln">{{ $newplace-&gt;name }}</span><span class="tag">&lt;/li&gt;</span><span class="pln">
      @endforeach
    </span><span class="tag">&lt;/ul&gt;</span><span class="pln">

    </span><span class="tag">&lt;h2&gt;</span><span class="pln">Places I've Already Been To</span><span class="tag">&lt;/h2&gt;</span><span class="pln">
    </span><span class="tag">&lt;ul&gt;</span><span class="pln">
          @foreach ($visited as $place)
                </span><span class="tag">&lt;li&gt;</span><span class="pln">{{ $place-&gt;name }}</span><span class="tag">&lt;/li&gt;</span><span class="pln">
          @endforeach
    </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	احفظ الملف وأغلقه عند الانتهاء، ثم انتقل إلى متصفحك وأعِد تحميل التطبيق، وسترى الصفحة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="124055" href="https://academy.hsoub.com/uploads/monthly_2023_04/02_travel_list.png.61b996890d6d4a19f18db3153cbd4fc0.png" rel=""><img alt="02_travel_list.png" class="ipsImage ipsImage_thumbnailed" data-fileid="124055" data-unique="v7h0dw5fc" style="width: 300px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2023_04/02_travel_list.png.61b996890d6d4a19f18db3153cbd4fc0.png"> </a>
</p>

<p>
	لديك الآن تطبيق لارافيل عملي يسحب المحتويات من قاعدة بيانات MySQL.
</p>

<h2>
	الخلاصة
</h2>

<p>
	ضبطنا في هذا المقال تطبيق لارافيل جديد باستخدام حزمة LEMP أو (Linux و Nginx و MySQL و PHP) ويعمل على خادم أوبنتو 22.04، وخصّصنا الطريق الافتراضي للاستعلام عن محتوى قاعدة البيانات وعرض النتائج في عرض مُخصَّص.
</p>

<p>
	يمكنك الآن إنشاء طرق وعروض جديدة للصفحات الإضافية التي يحتاجها تطبيقك. اطلع على توثيق لارافيل على موسوعة حسوب لمزيد من المعلومات حول <a href="https://wiki.hsoub.com/Laravel/routing" rel="external">الطرق Routes</a> و<a href="https://wiki.hsoub.com/Laravel/views" rel="external">العروض Views</a> و<a href="https://wiki.hsoub.com/Laravel/database" rel="external">دعم قاعدة البيانات</a>، وإذا أردتَ النشر في بيئة الإنتاج، فيمكنك الاطلاع على قسم <a href="https://wiki.hsoub.com/Laravel/deployment#.D8.A7.D9.84.D8.AA.D8.AD.D8.B3.D9.8A.D9.86" rel="external">التحسين Optimization</a> للتعرف على بعض الطرق المختلفة التي يمكنك من خلالها تحسين أداء تطبيقك.
</p>

<p>
	ترجمة -وبتصرُّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-laravel-with-nginx-on-ubuntu-20-04" rel="external nofollow">How To Install and Configure Laravel with Nginx on Ubuntu 20.04 (LEMP)</a> لصاحبته Erika Heidi.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/" rel="">مدخل إلى Laravel 5</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-laravel-5-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D9%87-%D8%B9%D9%84%D9%89-windows-%D9%88ubuntu-r212/" rel="">تثبيت Laravel 5 وإعداده على Windows وUbuntu</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/web/nginx/%D9%81%D9%8A%D8%AF%D9%8A%D9%88-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%B6%D8%A8%D8%B7-%D8%AE%D8%A7%D8%AF%D9%85-nginx-r401/" rel="">[فيديو] تثبيت وضبط خادم </a><a href="https://academy.hsoub.com/devops/servers/web/nginx/%D9%81%D9%8A%D8%AF%D9%8A%D9%88-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-%D9%88%D8%B6%D8%A8%D8%B7-%D8%AE%D8%A7%D8%AF%D9%85-nginx-r401/" rel="">Nginx</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/web/nginx/%D9%83%D9%8A%D9%81-%D8%AA%D8%A4%D9%85%D9%91%D9%86-%D8%AE%D8%A7%D8%AF%D9%85-%D9%88%D9%8A%D8%A8-nginx-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1604-r365/" rel="">كيف تؤمّن خادم ويب NGINX على أوبنتو 16.04</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">ما هو نظام التشغيل لينكس؟</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1968</guid><pubDate>Tue, 02 May 2023 16:00:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x625;&#x634;&#x639;&#x627;&#x631;&#x627;&#x62A; &#x639;&#x628;&#x631; &#x627;&#x644;&#x648;&#x64A;&#x628; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; &#x648;&#x642;&#x646;&#x648;&#x627;&#x62A; Pusher</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A5%D8%B4%D8%B9%D8%A7%D8%B1%D8%A7%D8%AA-%D8%B9%D8%A8%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%88%D9%82%D9%86%D9%88%D8%A7%D8%AA-pusher-r1741/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/633ff0164ab12_-------Pusher.jpg.f9ff93e500c0d377d11889586f7f5785.jpg" /></p>

<p>
	تتضمن العديد من تطبيقات الويب نظام إشعارات مبني ضمن التطبيق والذي يُعلِم المستخدم فورًا عندما يحاول شخص ما تنفيذ فعل ما مرتبط به، إذ يتلقى المستخدم في شبكة التواصل الاجتماعي فيسبوك مثلًا إشعارًا عندما يُعجَبُ أحدهم بحالة ما قد نشرها المستخدم أو عندما يضع أحدهم تعليقًا على صفحة المستخدم الشخصية. ننشئ في هذه المقالة آليةً شبيهةً بذلك عن طريق تطوير منظومة إشعارات معتمدة على الويب باستخدام بيئة <a href="https://laravel.com/" rel="external nofollow">لارافيل</a> ومكتبة <a href="https://pusher.com/" rel="external nofollow">Pusher</a>.
</p>

<h2>
	المتطلبات الأساسية
</h2>

<p>
	يجب التأكد من تثبيت خادم PHP ولارافيل Laravel على الحاسوب لإكمال المشروع كما يجب امتلاك حساب على منصة بوشر Pusher.
</p>

<h2>
	ما الذي سنبنيه؟
</h2>

<p>
	يتضمن العمل إنشاء تطبيق ويب بسيط يعرض الإشعارات باستخدام لارافيل وقنوات بوشر Pusher. يبين العرض التالي ما الذي نريد بناءه:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109247" href="https://academy.hsoub.com/uploads/monthly_2022_10/Create_notification_system_GIF.gif.6dc4fd55eb379fe28f79b3c6e7f43339.gif" rel=""><img alt="Create_notification_system_GIF" class="ipsImage ipsImage_thumbnailed" data-fileid="109247" data-unique="r1mey449h" src="https://academy.hsoub.com/uploads/monthly_2022_10/Create_notification_system_GIF.thumb.gif.2d3a98352ca6e288866259db915bd95e.gif" style="width: 700px; height: auto;"></a>
</p>

<h2>
	إعداد تطبيق Pusher
</h2>

<p>
	ننشئ بدايةً حسابًا على منصة <a href="https://pusher.com/" rel="external nofollow">Pusher</a> ومن ثم نضبط التطبيق كما هو موضح بالصورة أدناه:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109248" href="https://academy.hsoub.com/uploads/monthly_2022_10/Pusher_account_img.png.b22c93d65f31734ebe51a9c09a0c5f5e.png" rel=""><img alt="Pusher_account" class="ipsImage ipsImage_thumbnailed" data-fileid="109248" data-unique="c63a11f3y" src="https://academy.hsoub.com/uploads/monthly_2022_10/Pusher_account_img.thumb.png.2291c0994d572d613c0d669982b6997c.png" style="width: 600px; height: auto;"></a>
</p>

<h2>
	إعداد تطبيق لارافيل
</h2>

<p>
	ننشئ تطبيق لارافيل جديد بإجراء الأمر التالي في موجه الأوامر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1224_8" style="">
<span class="pln">laravel </span><span class="kwd">new</span><span class="pln"> laravel</span><span class="pun">-</span><span class="pln">web</span><span class="pun">-</span><span class="pln">notifications</span></pre>

<p>
	نثبت حزمة التطوير البرمجي الخاصة بمنصة بوشر Pusher والمعتمدة على <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AF%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%B3%D8%B1%D9%8A%D8%B9-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-php-r609/" rel="">لغة PHP</a> بتنفيذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1224_11" style="">
<span class="pln">composer </span><span class="kwd">require</span><span class="pln"> pusher</span><span class="pun">/</span><span class="pln">pusher</span><span class="pun">-</span><span class="pln">php</span><span class="pun">-</span><span class="pln">server</span></pre>

<p>
	نوجّه لارافيل لاستخدام منصة بوشر على أنها وسيلة لإرسال رسائل بث broadcast تُستخدم لإعلام أجزاء البرنامج بوقوع حدثٍ ما، ولتحقيق ذلك نفتح الملف "‎.env" الموجود في المجلد الجذر Root الخاص بلارافيل، ثم نحدّث محتواه ليوافق الضبط التالي مع ضرورة استبدال الرموز X بالقيم الخاصة بالحساب الخاص بك:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1224_13" style="">
<span class="pln">PUSHER_APP_ID</span><span class="pun">=</span><span class="lit">322700</span><span class="pln">
BROADCAST_DRIVER</span><span class="pun">=</span><span class="pln">pusher

</span><span class="com">// ‫نضيف المعلومات المتعلقة بالحساب الخاص بنا من منصة بوشر</span><span class="pln">
PUSHER_APP_ID</span><span class="pun">=</span><span class="pln">XXXXX
PUSHER_APP_KEY</span><span class="pun">=</span><span class="pln">XXXXXXX
PUSHER_APP_SECRET</span><span class="pun">=</span><span class="pln">XXXXXXX</span></pre>

<p>
	<strong>ملاحظة مهمة</strong>: يتصل لارافيل افتراضيًا بخوادم الولايات المتحدة الأمريكية، وعند الحاجة لاستخدام خوادم أخرى، يجب تحديث مصفوفة الخيارات الموجودة ضمن الملف "config/broadcasting.php"، كما يُعدّل الملف "config/app.php" ويحذف التعليق الموجود في الجزء:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1224_15" style="">
<span class="typ">App</span><span class="pln">\Providers\BroadcastServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pln"> </span></pre>

<h2>
	إنشاء التطبيق الذي يدمج لارافيل مع Pusher
</h2>

<p>
	ننشئ التطبيق بعد الانتهاء من العمليات السابقة، حيث نبدأ بإنشاء صنف الحدث <code>Event</code>، الذي يبث الرسائل إلى قنوات بوشر Pusher انطلاقًا من تطبيق لارافيل. تُستدعى الأحداث من أي مكان نرغب به ضمن التطبيق.
</p>

<pre class="ipsCode">
php artisan make:event StatusLiked
</pre>

<p>
	ينشئ هذا السطر صنفًا باسم <code>StatusLiked</code> ضمن مجلد "app/Events". نفتح هذا الملف ونحدّث محتواه كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1224_17" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Events</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Queue\SerializesModels</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Foundation\Events\Dispatchable</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Broadcasting\InteractsWithSockets</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Contracts\Broadcasting\ShouldBroadcast</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">StatusLiked</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">ShouldBroadcast</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Dispatchable</span><span class="pun">,</span><span class="pln"> </span><span class="typ">InteractsWithSockets</span><span class="pun">,</span><span class="pln"> </span><span class="typ">SerializesModels</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> $username</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> $message</span><span class="pun">;</span><span class="pln">

    </span><span class="com">/**
     * إنشاء عينة جديدة من الحدث
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">(</span><span class="pln">$username</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">username </span><span class="pun">=</span><span class="pln"> $username</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">message  </span><span class="pun">=</span><span class="pln"> </span><span class="str">"{$username} liked your status"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
     * تحديد القنوات التي سيُبث الحدث عليها
     *
     * @return Channel|array
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> broadcastOn</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="str">'status-liked'</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تخبر الواجهة <code>ShouldBroadcast</code> لارافيل أن الحدث الحالي يجب أن يُرسل وفقًا للطريقة المحدّدة في ملف الضبط الذي أعددناه مسبقًا.
</p>

<p>
	يوجد تابع باني يأخذ وسيطين، هما: اسم المستخدم وفعل verb، إذ تُسند قيم المتغيرات إلى خصائص الصنف التي تأخذ نفس الأسماء، ويجب أن تكون هذه الخصائص عامة public وإلا فسيجري تجاهلها.
</p>

<h2>
	إنشاء واجهة عرض التطبيق
</h2>

<p>
	نستخدم واجهة عرض وحيدة تحتوي شريط تنقّل وأيقونة للإشعارات، إذ تُحدّث الأيقونة عند وجود إشعارات جديدة دون الحاجة لإعادة تحميل الصفحة. لن تستمر الإشعارات طويلًا في التجربة الحالية ولكن يمكن زيادة المدة الزمنية لاستمرار الإشعار حسب الحاجة.
</p>

<p>
	نفتح الملف "welcome.blade.php" ونستبدل محتواه بما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1224_19" style="">
<span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="tag">&lt;html</span><span class="pln"> </span><span class="atn">lang</span><span class="pun">=</span><span class="atv">"en"</span><span class="tag">&gt;</span><span class="pln">
  </span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"utf-8"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">http-equiv</span><span class="pun">=</span><span class="atv">"X-UA-Compatible"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"IE=edge"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"viewport"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"width=device-width, initial-scale=1"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;title&gt;</span><span class="pln">Demo Application</span><span class="tag">&lt;/title&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"</span><span class="pln"> </span><span class="atn">integrity</span><span class="pun">=</span><span class="atv">"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="pun">=</span><span class="atv">"anonymous"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="tag">&lt;link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/css"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"/css/bootstrap-notifications.min.css"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="com">&lt;!--[if lt IE 9]&gt;
      &lt;script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"&gt;&lt;/script&gt;
      &lt;script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"&gt;&lt;/script&gt;
    &lt;![endif]--&gt;</span><span class="pln">
  </span><span class="tag">&lt;/head&gt;</span><span class="pln">
  </span><span class="tag">&lt;body&gt;</span><span class="pln">
    </span><span class="tag">&lt;nav</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar navbar-inverse"</span><span class="tag">&gt;</span><span class="pln">
      </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"container-fluid"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar-header"</span><span class="tag">&gt;</span><span class="pln">
          </span><span class="tag">&lt;button</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"button"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar-toggle collapsed"</span><span class="pln"> </span><span class="atn">data-toggle</span><span class="pun">=</span><span class="atv">"collapse"</span><span class="pln"> </span><span class="atn">data-target</span><span class="pun">=</span><span class="atv">"#bs-example-navbar-collapse-9"</span><span class="pln"> </span><span class="atn">aria-expanded</span><span class="pun">=</span><span class="atv">"false"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"sr-only"</span><span class="tag">&gt;</span><span class="pln">Toggle navigation</span><span class="tag">&lt;/span&gt;</span><span class="pln">
            </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"icon-bar"</span><span class="tag">&gt;&lt;/span&gt;</span><span class="pln">
            </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"icon-bar"</span><span class="tag">&gt;&lt;/span&gt;</span><span class="pln">
            </span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"icon-bar"</span><span class="tag">&gt;&lt;/span&gt;</span><span class="pln">
          </span><span class="tag">&lt;/button&gt;</span><span class="pln">
          </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"navbar-brand"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"#"</span><span class="tag">&gt;</span><span class="pln">Demo App</span><span class="tag">&lt;/a&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">

        </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"collapse navbar-collapse"</span><span class="tag">&gt;</span><span class="pln">
          </span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"nav navbar-nav"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;li</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"dropdown dropdown-notifications"</span><span class="tag">&gt;</span><span class="pln">
              </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"#notifications-panel"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"dropdown-toggle"</span><span class="pln"> </span><span class="atn">data-toggle</span><span class="pun">=</span><span class="atv">"dropdown"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;i</span><span class="pln"> </span><span class="atn">data-count</span><span class="pun">=</span><span class="atv">"0"</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"glyphicon glyphicon-bell notification-icon"</span><span class="tag">&gt;&lt;/i&gt;</span><span class="pln">
              </span><span class="tag">&lt;/a&gt;</span><span class="pln">

              </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"dropdown-container"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"dropdown-toolbar"</span><span class="tag">&gt;</span><span class="pln">
                  </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"dropdown-toolbar-actions"</span><span class="tag">&gt;</span><span class="pln">
                    </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"#"</span><span class="tag">&gt;</span><span class="pln">Mark all as read</span><span class="tag">&lt;/a&gt;</span><span class="pln">
                  </span><span class="tag">&lt;/div&gt;</span><span class="pln">
                  </span><span class="tag">&lt;h3</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"dropdown-toolbar-title"</span><span class="tag">&gt;</span><span class="pln">Notifications (</span><span class="tag">&lt;span</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"notif-count"</span><span class="tag">&gt;</span><span class="pln">0</span><span class="tag">&lt;/span&gt;</span><span class="pln">)</span><span class="tag">&lt;/h3&gt;</span><span class="pln">
                </span><span class="tag">&lt;/div&gt;</span><span class="pln">
                </span><span class="tag">&lt;ul</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"dropdown-menu"</span><span class="tag">&gt;</span><span class="pln">
                </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
                </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"dropdown-footer text-center"</span><span class="tag">&gt;</span><span class="pln">
                  </span><span class="tag">&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"#"</span><span class="tag">&gt;</span><span class="pln">View All</span><span class="tag">&lt;/a&gt;</span><span class="pln">
                </span><span class="tag">&lt;/div&gt;</span><span class="pln">
              </span><span class="tag">&lt;/div&gt;</span><span class="pln">
            </span><span class="tag">&lt;/li&gt;</span><span class="pln">
            </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"#"</span><span class="tag">&gt;</span><span class="pln">Timeline</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
            </span><span class="tag">&lt;li&gt;&lt;a</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"#"</span><span class="tag">&gt;</span><span class="pln">Friends</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="pln">
          </span><span class="tag">&lt;/ul&gt;</span><span class="pln">
        </span><span class="tag">&lt;/div&gt;</span><span class="pln">
      </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/nav&gt;</span><span class="pln">

    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"//js.pusher.com/3.1/pusher.min.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"</span><span class="pln"> </span><span class="atn">integrity</span><span class="pun">=</span><span class="atv">"sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"</span><span class="pln"> </span><span class="atn">crossorigin</span><span class="pun">=</span><span class="atv">"anonymous"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">

    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/javascript"</span><span class="tag">&gt;</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> notificationsWrapper   </span><span class="pun">=</span><span class="pln"> $</span><span class="pun">(</span><span class="str">'.dropdown-notifications'</span><span class="pun">);</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> notificationsToggle    </span><span class="pun">=</span><span class="pln"> notificationsWrapper</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="str">'a[data-toggle]'</span><span class="pun">);</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> notificationsCountElem </span><span class="pun">=</span><span class="pln"> notificationsToggle</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="str">'i[data-count]'</span><span class="pun">);</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> notificationsCount     </span><span class="pun">=</span><span class="pln"> parseInt</span><span class="pun">(</span><span class="pln">notificationsCountElem</span><span class="pun">.</span><span class="pln">data</span><span class="pun">(</span><span class="str">'count'</span><span class="pun">));</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> notifications          </span><span class="pun">=</span><span class="pln"> notificationsWrapper</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="str">'ul.dropdown-menu'</span><span class="pun">);</span><span class="pln">

      </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">notificationsCount </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        notificationsWrapper</span><span class="pun">.</span><span class="pln">hide</span><span class="pun">();</span><span class="pln">
      </span><span class="pun">}</span><span class="pln">
</span><span class="com">// ‫تأهيل وظيفة السجلات الخاصة بمكتبة بوشر Pusher </span><span class="pln">
</span><span class="com">// لا نستخدم هذه الوظيفة في بيئة الإنتاج الفعلية</span><span class="pln">
</span><span class="com">// Pusher.logToConsole = true;</span><span class="pln">

      </span><span class="kwd">var</span><span class="pln"> pusher </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Pusher</span><span class="pun">(</span><span class="str">'API_KEY_HERE'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        encrypted</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
      </span><span class="pun">});</span><span class="pln">
</span><span class="com">// الإشتراك بالقناة التي حددناها في صنف الحدث المعرّف في لارافيل</span><span class="pln">
      </span><span class="kwd">var</span><span class="pln"> channel </span><span class="pun">=</span><span class="pln"> pusher</span><span class="pun">.</span><span class="pln">subscribe</span><span class="pun">(</span><span class="str">'status-liked'</span><span class="pun">);</span><span class="pln">
</span><span class="com">// ربط تابع ما بالحدث الذي عرّفناه في الصنف </span><span class="pln">
    channel</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'App\\Events\\StatusLiked'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">var</span><span class="pln"> existingNotifications </span><span class="pun">=</span><span class="pln"> notifications</span><span class="pun">.</span><span class="pln">html</span><span class="pun">();</span><span class="pln">
        </span><span class="kwd">var</span><span class="pln"> avatar </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Math</span><span class="pun">.</span><span class="pln">floor</span><span class="pun">(</span><span class="typ">Math</span><span class="pun">.</span><span class="pln">random</span><span class="pun">()</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="lit">71</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">20</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">))</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">20</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">var</span><span class="pln"> newNotificationHtml </span><span class="pun">=</span><span class="pln"> </span><span class="pun">`</span><span class="pln">
          </span><span class="pun">&lt;</span><span class="pln">li </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"notification active"</span><span class="pun">&gt;</span><span class="pln">
              </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"media"</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"media-left"</span><span class="pun">&gt;</span><span class="pln">
                  </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"media-object"</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="pun">&lt;</span><span class="pln">img src</span><span class="pun">=</span><span class="str">"https://api.adorable.io/avatars/71/`+avatar+`.png"</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"img-circle"</span><span class="pln"> alt</span><span class="pun">=</span><span class="str">"50x50"</span><span class="pln"> style</span><span class="pun">=</span><span class="str">"width: 50px; height: 50px;"</span><span class="pun">&gt;</span><span class="pln">
                  </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"media-body"</span><span class="pun">&gt;</span><span class="pln">
                  </span><span class="pun">&lt;</span><span class="pln">strong </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"notification-title"</span><span class="pun">&gt;`+</span><span class="pln">data</span><span class="pun">.</span><span class="pln">message</span><span class="pun">+`&lt;/</span><span class="pln">strong</span><span class="pun">&gt;</span><span class="pln">
                  </span><span class="pun">&lt;!--</span><span class="pln">p </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"notification-desc"</span><span class="pun">&gt;</span><span class="typ">Extra</span><span class="pln"> description can go here</span><span class="pun">&lt;/</span><span class="pln">p</span><span class="pun">--&gt;</span><span class="pln">
                  </span><span class="pun">&lt;</span><span class="pln">div </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"notification-meta"</span><span class="pun">&gt;</span><span class="pln">
                    </span><span class="pun">&lt;</span><span class="pln">small </span><span class="kwd">class</span><span class="pun">=</span><span class="str">"timestamp"</span><span class="pun">&gt;</span><span class="pln">about a minute ago</span><span class="pun">&lt;/</span><span class="pln">small</span><span class="pun">&gt;</span><span class="pln">
                  </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
                </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
              </span><span class="pun">&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span><span class="pln">
          </span><span class="pun">&lt;/</span><span class="pln">li</span><span class="pun">&gt;</span><span class="pln">
        </span><span class="pun">`;</span><span class="pln">
        notifications</span><span class="pun">.</span><span class="pln">html</span><span class="pun">(</span><span class="pln">newNotificationHtml </span><span class="pun">+</span><span class="pln"> existingNotifications</span><span class="pun">);</span><span class="pln">

        notificationsCount </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
        notificationsCountElem</span><span class="pun">.</span><span class="pln">attr</span><span class="pun">(</span><span class="str">'data-count'</span><span class="pun">,</span><span class="pln"> notificationsCount</span><span class="pun">);</span><span class="pln">
        notificationsWrapper</span><span class="pun">.</span><span class="pln">find</span><span class="pun">(</span><span class="str">'.notif-count'</span><span class="pun">).</span><span class="pln">text</span><span class="pun">(</span><span class="pln">notificationsCount</span><span class="pun">);</span><span class="pln">
        notificationsWrapper</span><span class="pun">.</span><span class="pln">show</span><span class="pun">();</span><span class="pln">
      </span><span class="pun">});</span><span class="pln">
    </span><span class="tag">&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	نركّز على الجزء الخاص <a href="https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D8%AF%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%B3%D8%B1%D9%8A%D8%B9-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-javascript-r550/" rel="">بلغة جافا سكريبت JavaScript</a>، الذي يتضمن الأجزاء الخاصة بمكتبة Pusher التي ترسل الإشعارات. وفيما يلي الجزء المهم من الكتلة البرمجية الخاصة بعملية الإرسال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1224_22" style="">
<span class="com">// ‫تأهيل وظيفة السجلات الخاصة بمكتبة بوشر </span><span class="pln">
</span><span class="com">//لا نستخدم هذه الوظيفة في بيئة الإنتاج الفعلية</span><span class="pln">
</span><span class="com">// Pusher.logToConsole = true;</span><span class="pln">
</span><span class="com">// نهيئ مكتبة جافا سكريبت الخاصة بقنوات بوشر</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> pusher </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Pusher</span><span class="pun">(</span><span class="str">'API_KEY_HERE'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    encrypted</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
</span><span class="com">// الإشتراك بالقناة التي حددناها في صنف الحدث المعرّف في لارافيل</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> channel </span><span class="pun">=</span><span class="pln"> pusher</span><span class="pun">.</span><span class="pln">subscribe</span><span class="pun">(</span><span class="str">'status-liked'</span><span class="pun">);</span><span class="pln">
</span><span class="com">// ربط تابع ما بالحدث الذي عرّفناه في الصنف </span><span class="pln">
channel</span><span class="pun">.</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'App\\Events\\StatusLiked'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="com">// يُستدْعى هذا التابع عند استلام إشعار بالحدث</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	<strong>ملاحظة</strong>: ستبث لارافيل الحدث افتراضيًا تحت اسم الصنف الخاص بالحدث ولكن يمكن تخصيص هذا الاسم عن طريق تعريف طريقة خاصة للبث الخاص بالحدث:
</p>

<pre class="ipsCode">
public function broadcastAs() {
  return 'event-name';
}
</pre>

<p>
	تهيئ الشيفرة السابقة مكتبة الجافا سكريبت الخاصة بالتعامل مع بوشر Pusher وتؤسس قناة اتصال لإرسال واستقبال الأحداث المختلفة، وتتضمن أيضًا طريقةً خاصةً تُستَدعى عند استلام عملية بث تخص حدث ما عن طريق القناة.
</p>

<h2>
	اختبار التطبيق
</h2>

<p>
	ننشئ الاتجاه Route اللازم لتنفيذ الحدث والذي يسبب وصول الإشعار إلى المستخدم، إذ يظهر الإشعار عند الوصول إلى هذا الاتجاه ما لم يوجد خطأ ما في الخطوات السابقة. نضيف الاتجاه الجديد كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1224_25" style="">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'test'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    event</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Events\StatusLiked</span><span class="pun">(</span><span class="str">'Someone'</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"Event has been sent!"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	نشغّل خادم PHP عن طريق لارافيل لاختبار نجاح عمل البرنامج الذي كتبناه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1224_27" style="">
<span class="pln">php artisan serve</span></pre>

<h2>
	الخاتمة
</h2>

<p>
	أنشأنا نظام إشعارات خاص بالويب باستخدام عددٍ قليل نسبيًا من السطور البرمجية بالاعتماد على قنوات بوشر Pusher، وما أنجزناه يُعد مثالًا بسيطًا على قدرات هذه المكتبة وأداةً يمكن تضمينها في عدة مشاريع، ولا شك أنه يمكن الاعتماد على مكتبة بوشر Pusher في تطوير كثيرٍ من الأدوات المفيدة أيضًا والتي يمكن تضمينها ضمن مختلف المشاريع البرمجية.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.digitalocean.com/community/tutorials/create-web-notifications-using-laravel-and-pusher-channels" rel="external nofollow">How To Create Web Notifications Using Laravel and Pusher Channels</a> لصاحبه Neo Ighodaro.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A8%D9%86%D8%A7%D8%A1-%D8%A7%D9%84%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-laravel-5-r216/" rel="">أساسيات بناء التطبيقات في إطار العمل Laravel 5</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-todo-list-%D8%A8%D8%B3%D9%8A%D8%B7-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-laravel-5-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r149/" rel="">إنشاء تطبيق Todo List بسيط باستخدام Laravel 5 - الجزء الأول</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1741</guid><pubDate>Fri, 07 Oct 2022 09:44:57 +0000</pubDate></item><item><title>&#x628;&#x646;&#x627;&#x621; &#x628;&#x648;&#x62A; Bot &#x62A;&#x644;&#x63A;&#x631;&#x627;&#x645; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; &#x648;&#x628;&#x648;&#x62A;&#x645;&#x627;&#x646; BotMan</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A8%D9%86%D8%A7%D8%A1-%D8%A8%D9%88%D8%AA-bot-%D8%AA%D9%84%D8%BA%D8%B1%D8%A7%D9%85-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D9%88%D8%A8%D9%88%D8%AA%D9%85%D8%A7%D9%86-botman-r1740/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/633fe7aa10009_------Potman.jpg.1e883ec44d091717190dbe5c009f34ae.jpg" /></p>

<p>
	نستطيع استخدام البوتات الآلية (يُطلق عليها اسم بوتات bots عندما تكون في الويب) لتقديم بيانات مخصصة للمستخدمين بناءً على طلباتهم، إذ يتيح إطارا عمل لارافيل Laravel وبوتمان Potman الأدوات اللازمة لإنشاء بوتات قادرة على تنفيذ هذه المهمة بسهولة. نعمل في هذا المقال على إنشاء بوت تلغرام لمحبي الكلاب باستخدام <a href="https://dog.ceo/dog-api/#all" rel="external nofollow">DOG <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a>، ويمكن اختيار أي نوعٍ مختلفٍ من البيانات عند الرغبة. يظهر البوت عند الانتهاء من العمل كما في الشكل التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109230" href="https://academy.hsoub.com/uploads/monthly_2022_10/bot.jpg.c49d9c4cebe2dd59b33806a5176471e8.jpg" rel=""><img alt="bot" class="ipsImage ipsImage_thumbnailed" data-fileid="109230" data-unique="79q37ozxj" src="https://academy.hsoub.com/uploads/monthly_2022_10/bot.thumb.jpg.4830e83da766602caf92101c98b1978a.jpg" style="width: 550px; height: auto;"></a>
</p>

<h2>
	تثبيت لارافيل وبوتمان
</h2>

<p>
	يُعد إطار عمل <a href="https://github.com/botman/botman" rel="external nofollow">بوتمان</a> مكتبةً خاصةً <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AF%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%B3%D8%B1%D9%8A%D8%B9-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-php-r609/" rel="">بلغة البرمجة PHP</a>، وصُمِّمَت لتبسيط عملية تطوير بوتات مبتكرة لمنصات المراسلة المتعددة، مثل منصة سلاك Slack، وتلغرام، وإطار عمل مايكروسوفت بوت وNixmo وفيسبوك وغيرها.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_10" style="">
<span class="pln">$botman</span><span class="pun">-&gt;</span><span class="pln">hears</span><span class="pun">(</span><span class="str">'Bot, What’s the best Web Development training website?'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">BotMan</span><span class="pln"> $bot</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $bot</span><span class="pun">-&gt;</span><span class="pln">reply</span><span class="pun">(</span><span class="str">'DigitalOcean for sure. Give me a harder question!!'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<h2>
	تثبيت بوتمان استوديو
</h2>

<p>
	وفّر المطور <a href="https://twitter.com/marcelpociot" rel="external nofollow">مارسيل بوكيوت Marcel Pociot</a> كثيرًا من الوقت على المطورين من خلال تطويره برنامج <a href="https://github.com/botman/studio" rel="external nofollow">بوتمان استوديو Botman Studio</a> بالاعتماد على لارافيل مع بوتمان لنحصل على برنامج سهل الاستخدام محدّث باستمرار. ننشئ مشروعًا جديدًا ضمن بوتمان استوديو بتنفيذ التعليمة التالية في موجه الأوامر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_12" style="">
<span class="pln">composer create</span><span class="pun">-</span><span class="pln">project </span><span class="pun">--</span><span class="pln">prefer</span><span class="pun">-</span><span class="pln">dist botman</span><span class="pun">/</span><span class="pln">studio ilovedogs</span></pre>

<p>
	نتحقق من نجاح عملية التثبيت بتنفيذ التعليمة التالية في موجه الأوامر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_14" style="">
<span class="pln">php artisan botman</span><span class="pun">:</span><span class="pln">tinker</span></pre>

<p>
	يمكن إدخال الكلمة "Hi" في موجه الأوامر ليظهر الرد بعبارة "Hello" في حالة العمل الصحيح كما هو موضح بالشكل التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109242" href="https://academy.hsoub.com/uploads/monthly_2022_10/Test_app_work.jpg.33f853039a37277a08c7a13c7c6e435f.jpg" rel=""><img alt="Test_app_work" class="ipsImage ipsImage_thumbnailed" data-fileid="109242" data-unique="25381t0b3" src="https://academy.hsoub.com/uploads/monthly_2022_10/Test_app_work.thumb.jpg.6aba4a49ead1239cda0dd6d878a25a0a.jpg" style="width: 600px; height: auto;"></a>
</p>

<h2>
	إنشاء الأوامر
</h2>

<p>
	يتميز البوت الذي ننشئه بالقدرة على الرد على أنواع مختلفة من الرسائل والأوامر التي تصله، أي أنه يستطيع التعامل مع هذه الحالات:
</p>

<ul>
<li>
		إرسال صورة عشوائية للكلاب من جميع السلالات.
	</li>
	<li>
		إرسال صورة عشوائية للكلب حسب سلالته.
	</li>
	<li>
		إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية.
	</li>
	<li>
		إجراء محادثة وتقديم المساعدة.
	</li>
	<li>
		الاستجابة للأوامر غير المعروفة.
	</li>
</ul>
<p>
	لتحقيق هذه الوظائف، نفرغ محتوى الملف "routes/botman.php" لأننا سنضيف له محتوى جديد كليًا ويجب إزالة المحتوى القديم لعدم حصول تعارض.
</p>

<h3>
	إرسال صورة عشوائية للكلاب من جميع السلالات
</h3>

<p>
	نحصل على صورة كلب عشوائي من البوت بإرسال الأمر "random/" ونعدل على النص البرمجي في ملف "routes/botman.php" ليصبح كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_17" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Conversations\StartConversation</span><span class="pun">;</span><span class="pln">

$botman </span><span class="pun">=</span><span class="pln"> resolve</span><span class="pun">(</span><span class="str">'botman'</span><span class="pun">);</span><span class="pln">

$botman</span><span class="pun">-&gt;</span><span class="pln">hears</span><span class="pun">(</span><span class="str">'/random'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'App\Http\Controllers\AllBreedsController@random'</span><span class="pun">);</span></pre>

<p>
	ننشئ المتحكم باستخدام التعليمة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_19" style="">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">AllBreedsController</span></pre>

<p>
	نكتب الشيفرة البرمجية التالية في المتحكم الذي أنشأناه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_21" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Services\DogService</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\Controller</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AllBreedsController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
     * الباني الخاص بالمتحكم
     * 
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">photos </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DogService</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
     * إعادة صورة عشوائية لكلب من إحدى السلالات
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> random</span><span class="pun">(</span><span class="pln">$bot</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// $this-&gt;photos-&gt;random() يمثل رابط الصورة ‫URL التي تعيدها هذه الخدمة‫‪</span><span class="pln">
        </span><span class="com">// $bot-&gt;reply تمثل ما نستخدمه لإرسال الصورة إلى المستخدم</span><span class="pln">
        $bot</span><span class="pun">-&gt;</span><span class="pln">reply</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">photos</span><span class="pun">-&gt;</span><span class="pln">random</span><span class="pun">());</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></pre>

<p>
	ننشئ عينةً من الصنف <code>DogService</code> الموجود ضمن الملف "app//services/DogService.php" ليكون مسؤولاً عن الاستجابة لاستدعاءات <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-api-r1314/" rel="">الواجهة البرمجية <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a> الخاصة بجلب الصور ونضع به الشيفرة البرمجية التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_25" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Services</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">GuzzleHttp</span><span class="pln">\Client</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DogService</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// عنوان الوجهة التي سنحصل منها على صورة الكلاب</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> RANDOM_ENDPOINT </span><span class="pun">=</span><span class="pln"> </span><span class="str">'https://dog.ceo/api/breeds/image/random'</span><span class="pun">;</span><span class="pln">

    </span><span class="com">/**
     * Guzzle client.
     *
     * @var GuzzleHttp\Client
     */</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $client</span><span class="pun">;</span><span class="pln">

    </span><span class="com">/**
     * DogService constructor
     * 
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">client </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Client</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
     *  إحضار وإعادة صورة كلب عشوائية من إحدى السلالات
     *
     * @return string
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> random</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// التي استلمناها JSON فك ترميز استجابة</span><span class="pln">
            $response </span><span class="pun">=</span><span class="pln"> json_decode</span><span class="pun">(</span><span class="pln">
               </span><span class="com">// التي تعيد الجسم الخاص بالاستجابة <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> استدعاء</span><span class="pln">
                $this</span><span class="pun">-&gt;</span><span class="pln">client</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">::</span><span class="pln">RANDOM_ENDPOINT</span><span class="pun">)-&gt;</span><span class="pln">getBody</span><span class="pun">()</span><span class="pln">
            </span><span class="pun">);</span><span class="pln">

            </span><span class="com">// إعادة رابط الصورة</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> $response</span><span class="pun">-&gt;</span><span class="pln">message</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> $e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
             </span><span class="com">// نستخدم هذا السطر لإعادة رسالة الخطأ للمستخدم في حال وقوع مشكلة ما.</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="str">'An unexpected error occurred. Please try again later.'</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إرسال صورة عشوائية للكلب حسب سلالته
</h3>

<p>
	نكرر العملية السابقة ولكن نضيف الأمر <code>‎/b {breed}‎</code>، ونعدل الملف "routes/botman.php" بإضافة السطر البرمجي التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_27" style="">
<span class="pln">botman</span><span class="pun">-&gt;</span><span class="pln">hears</span><span class="pun">(</span><span class="str">'/b {breed}'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'App\Http\Controllers\AllBreedsController@byBreed'</span><span class="pun">);</span></pre>

<p>
	نضيف ما يلي على المتحكم <code>AllBreedsController</code> الذي أنشأناه مسبقًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_29" style="">
<span class="com">/**
 * إعادة صورة كلب من سلالة محددة
*
 * @return void
 */</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> byBreed</span><span class="pun">(</span><span class="pln">$bot</span><span class="pun">,</span><span class="pln"> $name</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// نترك أمر معالجة استدعاء الواجهة البرمجية إلى صنف الخدمة ونرد على الطلب القادم بالنتيجة فور وصولها إلينا</span><span class="pln">
    $bot</span><span class="pun">-&gt;</span><span class="pln">reply</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">photos</span><span class="pun">-&gt;</span><span class="pln">byBreed</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نضيف التابع <code>byBreed</code> إلى الصنف <code>DogService</code> الذي أنشأناه على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_31" style="">
<span class="com">/**
 * جلب وإعادة صورة عشوائية من سلالة محددة
 *
 * @param string $breed
 * @return string
 */</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> byBreed</span><span class="pun">(</span><span class="pln">$breed</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// لدى الطرف الآخر باسم الصنف المحدد %s نستبدل</span><span class="pln">
        $endpoint </span><span class="pun">=</span><span class="pln"> sprintf</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">::</span><span class="pln">BREED_ENDPOINT</span><span class="pun">,</span><span class="pln"> $breed</span><span class="pun">);</span><span class="pln">

        $response </span><span class="pun">=</span><span class="pln"> json_decode</span><span class="pun">(</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">client</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="pln">$endpoint</span><span class="pun">)-&gt;</span><span class="pln">getBody</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> $response</span><span class="pun">-&gt;</span><span class="pln">message</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> $e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"Sorry I couldn\"t get you any photos from $breed. Please try with a different breed."</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يجب إضافة نقطة النهاية <code>const</code> المُستخدمة أعلاه إلى نفس الملف على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_33" style="">
<span class="com">// نقطة النهاية التي سنصل إليها للحصول على صورة عشوائية باسم سلالة معطى</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> BREED_ENDPOINT </span><span class="pun">=</span><span class="pln"> </span><span class="str">'https://dog.ceo/api/breed/%s/images/random'</span><span class="pun">;</span></pre>

<h3>
	إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية
</h3>

<p>
	نضيف الأمر <code>‎/s {breed}:{subBreed}‎</code> من أجل السلالات الفرعية على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_35" style="">
<span class="pln">botman</span><span class="pun">-&gt;</span><span class="pln">hears</span><span class="pun">(</span><span class="str">'/s {breed}:{subBreed}'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'App\Http\Controllers\SubBreedController@random'</span><span class="pun">);</span></pre>

<p>
	ننشئ متحكمًا جديدًا :
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_37" style="">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">SubBreedController</span></pre>

<p>
	نعرّف التابع <code>random</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_39" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Conversations</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Services\DogService</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\Controller</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">SubBreedController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
     * التابع الباني للمتحكم
     * 
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> __construct</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">photos </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DogService</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
     * إعادة صورة عشوائية لكلب من إحدى السلالات
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> random</span><span class="pun">(</span><span class="pln">$bot</span><span class="pun">,</span><span class="pln"> $breed</span><span class="pun">,</span><span class="pln"> $subBreed</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $bot</span><span class="pun">-&gt;</span><span class="pln">reply</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">photos</span><span class="pun">-&gt;</span><span class="pln">bySubBreed</span><span class="pun">(</span><span class="pln">$breed</span><span class="pun">,</span><span class="pln"> $subBreed</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يجب إضافة نقطة الاتصال النهائية والتابع الذي حدثنا محتواه إلى الصنف <code>DogService</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_41" style="">
<span class="com">// تعيد نقطة الاتصال النهائية صورة عشوائية لكلب من سلالة محددة وسلالة فرعية محددة</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> SUB_BREED_ENDPOINT </span><span class="pun">=</span><span class="pln"> </span><span class="str">'https://dog.ceo/api/breed/%s/%s/images/random'</span><span class="pun">;</span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_43" style="">
<span class="com">/**
 * جلب وإعادة صورة عشوائية لصورة عشوائية من سلالة معينة وسلالة فرعية
 *
 * @param string $breed
 * @param string $subBreed
 * @return string
 */</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> bySubBreed</span><span class="pun">(</span><span class="pln">$breed</span><span class="pun">,</span><span class="pln"> $subBreed</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $endpoint </span><span class="pun">=</span><span class="pln"> sprintf</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">::</span><span class="pln">SUB_BREED_ENDPOINT</span><span class="pun">,</span><span class="pln"> $breed</span><span class="pun">,</span><span class="pln"> $subBreed</span><span class="pun">);</span><span class="pln">

        $response </span><span class="pun">=</span><span class="pln"> json_decode</span><span class="pun">(</span><span class="pln">
            $this</span><span class="pun">-&gt;</span><span class="pln">client</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="pln">$endpoint</span><span class="pun">)-&gt;</span><span class="pln">getBody</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> $response</span><span class="pun">-&gt;</span><span class="pln">message</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Exception</span><span class="pln"> $e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="str">"Sorry I couldn\"t get you any photos from $breed. Please try with a different breed."</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	إجراء محادثة وتقديم المساعدة
</h3>

<p>
	لا نحبّذ الرد على كلمات رئيسية مفردة عند برمجة بوت الدردشة، وإنما نجمع معلومات المستخدمين من خلال المحادثة، بحيث يتعامل بوت الدردشة مع كل مستخدم بصورةٍ مناسبة تتوافق مع بياناته. لتحقيق ذلك نضيف الى الملف "routes/botman.php" ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_45" style="">
<span class="pln">botman</span><span class="pun">-&gt;</span><span class="pln">hears</span><span class="pun">(</span><span class="str">'Start conversation'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'App\Http\Controllers\ConversationController@index'</span><span class="pun">);</span></pre>

<p>
	ننشئ متحكمًا جديدًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_47" style="">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">ConversationController</span></pre>

<p>
	نعرّف التابع <code>index</code> ضمن الصنف على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_49" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\Controller</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Conversations\DefaultConversation</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ConversationController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
     * إنشاء محادثة جديدة
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">(</span><span class="pln">$bot</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// التي يوفرها إطار العمل بوتمان لبدء محادثة جديدة startConversation نستخدم التابع</span><span class="pln">
        $bot</span><span class="pun">-&gt;</span><span class="pln">startConversation</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DefaultConversation</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا كنا نستخدم بوتمان ستوديو، نجد مجلد باسم "Conversations" ضمن مجلد التطبيق، لذلك ننشئ داخل هذا المجلد ملفًا جديدًا ونسميه "DefaultConversation.php" ونضع فيه المحتوى التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_51" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Conversations</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">BotMan</span><span class="pln">\BotMan\Messages\Incoming\Answer</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">BotMan</span><span class="pln">\BotMan\Messages\Outgoing\Question</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">BotMan</span><span class="pln">\BotMan\Messages\Outgoing\Actions\Button</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">BotMan</span><span class="pln">\BotMan\Messages\Conversations\Conversation</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DefaultConversation</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Conversation</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
     * بدء المحادثة بالسؤال الاول
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> defaultQuestion</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// نبدأ المحادثة بإضافة السؤال الأول ونضبط الخيارات المتاحة للإجابة على هذا السؤال</span><span class="pln">
        $question </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Question</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'Huh - you woke me up. What do you need?'</span><span class="pun">)</span><span class="pln">
            </span><span class="pun">-&gt;</span><span class="pln">addButtons</span><span class="pun">([</span><span class="pln">
                </span><span class="typ">Button</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'Random dog photo'</span><span class="pun">)-&gt;</span><span class="pln">value</span><span class="pun">(</span><span class="str">'random'</span><span class="pun">),</span><span class="pln">
                </span><span class="typ">Button</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'A photo by breed'</span><span class="pun">)-&gt;</span><span class="pln">value</span><span class="pun">(</span><span class="str">'breed'</span><span class="pun">),</span><span class="pln">
                </span><span class="typ">Button</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'A photo by sub-breed'</span><span class="pun">)-&gt;</span><span class="pln">value</span><span class="pun">(</span><span class="str">'sub-breed'</span><span class="pun">),</span><span class="pln">
            </span><span class="pun">]);</span><span class="pln">

        </span><span class="com">//  نسأل المستخدم السؤال الذي أعددناه</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">ask</span><span class="pun">(</span><span class="pln">$question</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Answer</span><span class="pln"> $answer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">//     نفحص إذا كان المستخدم قد كتب عبارة ما أم ضغط على أحد الخيارات</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$answer</span><span class="pun">-&gt;</span><span class="pln">isInteractiveMessageReply</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="com">// نقارن جواب المستخدم مع الإجابات المعدة مسبقًا</span><span class="pln">
                </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$answer</span><span class="pun">-&gt;</span><span class="pln">getValue</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'random'</span><span class="pun">:</span><span class="pln">
                    $this</span><span class="pun">-&gt;</span><span class="pln">say</span><span class="pun">((</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Services\DogService</span><span class="pun">)-&gt;</span><span class="pln">random</span><span class="pun">());</span><span class="pln">
                    </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
                    </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'breed'</span><span class="pun">:</span><span class="pln">
                        $this</span><span class="pun">-&gt;</span><span class="pln">askForBreedName</span><span class="pun">();</span><span class="pln">
                        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
                    </span><span class="kwd">case</span><span class="pln"> </span><span class="str">'sub-breed'</span><span class="pun">:</span><span class="pln">
                        $this</span><span class="pun">-&gt;</span><span class="pln">askForSubBreed</span><span class="pun">();</span><span class="pln">
                        </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">
                </span><span class="pun">}</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
     * السؤال عن سلالة الكلب وسلالته الفرعية
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> askForBreedName</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">ask</span><span class="pun">(</span><span class="str">'What\'s the breed name?'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Answer</span><span class="pln"> $answer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $name </span><span class="pun">=</span><span class="pln"> $answer</span><span class="pun">-&gt;</span><span class="pln">getText</span><span class="pun">();</span><span class="pln">

            $this</span><span class="pun">-&gt;</span><span class="pln">say</span><span class="pun">((</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Services\DogService</span><span class="pun">)-&gt;</span><span class="pln">byBreed</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">));</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
     *طلب اسم السلالة وإرسال الصورة
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> askForSubBreed</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">ask</span><span class="pun">(</span><span class="str">'What\'s the breed and sub-breed names? ex:hound:afghan'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Answer</span><span class="pln"> $answer</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $answer </span><span class="pun">=</span><span class="pln"> explode</span><span class="pun">(</span><span class="str">':'</span><span class="pun">,</span><span class="pln"> $answer</span><span class="pun">-&gt;</span><span class="pln">getText</span><span class="pun">());</span><span class="pln">

            $this</span><span class="pun">-&gt;</span><span class="pln">say</span><span class="pun">((</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Services\DogService</span><span class="pun">)-&gt;</span><span class="pln">bySubBreed</span><span class="pun">(</span><span class="pln">$answer</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> $answer</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]));</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
     * بدء المحادثة
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">//   يُعد هذه التابع إقلاعي فهو ما سيجري تنفيذه أولًا</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">defaultQuestion</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الاستجابة للأوامر غير المعروفة
</h3>

<p>
	تُستخدم هذه الحالة عندما يرسل المستخدم رسالةً لا يتعرف عليها البوت فلا بد من إعلامه بإعادة طلبه على نحوٍ صحيح. نضيف إلى الملف "routes/botman.php" السطر البرمجي التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_53" style="">
<span class="pln">botman</span><span class="pun">-&gt;</span><span class="pln">fallback</span><span class="pun">(</span><span class="str">'App\Http\Controllers\FallbackController@index'</span><span class="pun">);</span></pre>

<p>
	ننشئ متحكمًا جديدًا على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_55" style="">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">controller </span><span class="typ">FallbackController</span></pre>

<p>
	نضيف الرسالة التي يراها المستخدم عند إرساله لأمر غير معروف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_57" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\Controller</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">FallbackController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
     * الإجابة برسالة عامة
     *
     * @param Botman $bot
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">(</span><span class="pln">$bot</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $bot</span><span class="pun">-&gt;</span><span class="pln">reply</span><span class="pun">(</span><span class="str">'Sorry, I did not understand these commands. Try: \'Start Conversation\''</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	اختبار البوت
</h2>

<ul>
<li>
		إرسال صورة عشوائية للكلاب من جميع السلالات.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109235" href="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog.gif.0482626c55137b1731c2b9b69cc70b75.gif" rel=""><img alt="random_dog.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109235" data-unique="hkjayjufl" src="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog.gif.0482626c55137b1731c2b9b69cc70b75.gif"></a>
</p>

<ul>
<li>
		إرسال صورة عشوائية للكلب حسب سلالته.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109238" href="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog_photo_by_its_breed.gif.03d1811bee01c488665510590414d22e.gif" rel=""><img alt="random_dog_photo_by_its_breed.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109238" data-unique="i5mizzzzc" src="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog_photo_by_its_breed.gif.03d1811bee01c488665510590414d22e.gif"></a>
</p>

<ul>
<li>
		إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109237" href="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog_photo_by_a_its_breed_and_sub_breed.gif.15af255b8e386516730ec849cd7a379a.gif" rel=""><img alt="random_dog_photo_by_a_its_breed_and_sub_breed.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109237" data-unique="fvkiwl86k" src="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog_photo_by_a_its_breed_and_sub_breed.gif.15af255b8e386516730ec849cd7a379a.gif"></a>
</p>

<ul>
<li>
		إجراء محادثة وتقديم المساعدة.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109232" href="https://academy.hsoub.com/uploads/monthly_2022_10/conversation_and_provide_help.gif.bc7a31ca90653bcb9a57e2b1df539d25.gif" rel=""><img alt="conversation_and_provide_help.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109232" data-unique="wfb6d550p" src="https://academy.hsoub.com/uploads/monthly_2022_10/conversation_and_provide_help.gif.bc7a31ca90653bcb9a57e2b1df539d25.gif"></a>
</p>

<ul>
<li>
		الاستجابة للأوامر غير المعروفة.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109243" href="https://academy.hsoub.com/uploads/monthly_2022_10/unrecognised_commands.gif.2ec78c9152223912326aea2268bc5839.gif" rel=""><img alt="unrecognised_commands.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="109243" data-unique="7cldqezd6" src="https://academy.hsoub.com/uploads/monthly_2022_10/unrecognised_commands.gif.2ec78c9152223912326aea2268bc5839.gif"></a>
</p>

<h2>
	تثبيت برنامج تشغيل تلغرام
</h2>

<p>
	بعد الانتهاء من تطوير التطبيق يجب دمجه مع برنامج تلغرام، ولتحقيق ذلك نحتاج برنامج تشغيل التلغرام Telegram driver الذي يقدمه بوتمان والذي نحصل عليه بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_59" style="">
<span class="pln">composer </span><span class="kwd">require</span><span class="pln"> botman</span><span class="pun">/</span><span class="pln">driver</span><span class="pun">-</span><span class="pln">telegram</span></pre>

<h2>
	إنشاء بوت تلغرام
</h2>

<p>
	نفتح تطبيق تلغرام ونبحث عن BotFather ونكتب "‎/newbot" وندخل اسم مستخدم البوت كما في الشكل:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109234" href="https://academy.hsoub.com/uploads/monthly_2022_10/create_new_bot.jpg.cf33453214e1d8f6acbc01ca3a20e097.jpg" rel=""><img alt="create_new_bot" class="ipsImage ipsImage_thumbnailed" data-fileid="109234" data-unique="xkf8g0u14" src="https://academy.hsoub.com/uploads/monthly_2022_10/create_new_bot.thumb.jpg.37a2bdc6b90780294eecbcb4be97ddfa.jpg" style="width: 700px; height: auto;"></a>
</p>

<p>
	نضيف الرمز إلى ملف "env." ونستبدل <code>YOUR_TOKEN</code> بالرمز المميز Token الذي يقدمه تلغرام:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_62" style="">
<span class="pln">TELEGRAM_TOKEN</span><span class="pun">=</span><span class="pln">YOUR_TOKEN</span></pre>

<h2>
	تثبيت وتشغيل الأداة ngrok
</h2>

<p>
	يتطلّب التلغرام استخدام رابط URL صالح وآمن لإعداد الخطافات webhooks وتلقي الرسائل من المستخدمين، ولتحقيق ذلك نستخدم ngrok أو نضع التطبيق على خادم ونُعِد له <a href="https://academy.hsoub.com/devops/servers/%d9%83%d9%8a%d9%81%d9%8a%d8%a9-%d8%aa%d8%ab%d8%a8%d9%8a%d8%aa-%d8%b4%d9%87%d8%a7%d8%af%d8%a9-ssl-%d9%85%d9%86-%d8%b3%d9%84%d8%b7%d8%a9-%d8%b4%d9%87%d8%a7%d8%af%d8%a7%d8%aa-%d8%aa%d8%ac%d8%a7%d8%b1%d9%8a%d8%a9-%d8%a7%d9%84%d9%85%d9%81%d8%a7%d9%87%d9%8a%d9%85-%d8%a7%d9%84%d8%a3%d8%b3%d8%a7%d8%b3%d9%8a%d8%a9-r146/" rel="">شهادة <abbr title="Secure Socket Layer | طبقة المنافذ الآمنة">SSL</abbr></a>، ولكن لسهولة التنفيذ سنستخدم ngrok. نستطيع الحصول عليه <a href="https://ngrok.com/download" rel="external nofollow">من الموقع الرسمي</a> باختيار النسخة المناسبة لنظام التشغيل الذي سنعمل عليه.
</p>

<p>
	ننتقل إلى مجلد التطبيق وننفّذ التعليمة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_66" style="">
<span class="pln"> php artisan serve</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109240" href="https://academy.hsoub.com/uploads/monthly_2022_10/run_app.jpg.e2231132ac347e0fc347ed4f5452012a.jpg" rel=""><img alt="run_app" class="ipsImage ipsImage_thumbnailed" data-fileid="109240" data-unique="7x2nmhws6" src="https://academy.hsoub.com/uploads/monthly_2022_10/run_app.thumb.jpg.4bb87ed4bd0f7479a80aa8d0cb224c10.jpg" style="width: 600px; height: auto;"></a>
</p>

<p>
	ننتقل إلى المجلد الذي ثبتنا البرنامج ضمنه ونشغل الأداة ngrok بتنفيذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_69" style="">
<span class="pln"> </span><span class="pun">/</span><span class="pln">ngrok http </span><span class="lit">8000</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109241" href="https://academy.hsoub.com/uploads/monthly_2022_10/run_ngrok.jpg.46dc2802d323dc527db94ea537293d0d.jpg" rel=""><img alt="run_ngrok" class="ipsImage ipsImage_thumbnailed" data-fileid="109241" data-unique="w118md4rh" src="https://academy.hsoub.com/uploads/monthly_2022_10/run_ngrok.thumb.jpg.db1844a66ef1764881b6689b84862ec9.jpg" style="width: 600px; height: auto;"></a>
</p>

<h2>
	ربط البوت بالتلغرام
</h2>

<p>
	نربط تطبيقنا ببوت التلغرام الذي أنشأناه مسبقاً بإرسال طلب من نوع POST إلى عنوان الرابط هذا وتمرير عنوان الرابط الذي ولّده ngrok:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_72" style="">
<span class="pln">https</span><span class="pun">:</span><span class="com">//api.telegram.org/bot{TOKEN}/setWebhook</span></pre>

<p>
	نستخدم برنامج بوستمان أو أداة "CURL" لتحقيق ذلك على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_74" style="">
<span class="pln">curl </span><span class="pun">-</span><span class="pln">X POST </span><span class="pun">-</span><span class="pln">F </span><span class="str">'url=https://{YOU_URL}/botman'</span><span class="pln"> https</span><span class="pun">:</span><span class="com">//api.telegram.org/bot{TOKEN}/setWebhook</span></pre>

<p>
	يصل الرد التالي بصيغة JSON في حال نجاح العملية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3395_76" style="">
<span class="pun">{</span><span class="pln">
    </span><span class="str">"ok"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"result"</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln">
    </span><span class="str">"description"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Webhook was set"</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الاختبار باستخدام تلغرام
</h2>

<ul>
<li>
		إرسال صورة عشوائية للكلاب من جميع السلالات.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109236" href="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog_last_test.jpg.e2dee85830eaa7202b3cba55c48e630c.jpg" rel=""><img alt="random_dog_last_test" class="ipsImage ipsImage_thumbnailed" data-fileid="109236" data-unique="2srsehl7x" src="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog_last_test.thumb.jpg.0c6a92d6dbc5aca569f30717b836060f.jpg" style="width: 600px; height: auto;"></a>
</p>

<ul>
<li>
		إرسال صورة عشوائية للكلب حسب سلالته.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109239" href="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog_photo_by_its_breed_last_test.jpg.c9e5a2726b996529fed7ffafa0856295.jpg" rel=""><img alt="random_dog_photo_by_its_breed_last_test" class="ipsImage ipsImage_thumbnailed" data-fileid="109239" data-unique="5cgzidd12" src="https://academy.hsoub.com/uploads/monthly_2022_10/random_dog_photo_by_its_breed_last_test.thumb.jpg.29de1245c1a7972a6e212b3cdafd83a7.jpg" style="width: 600px; height: auto;"></a>
</p>

<ul>
<li>
		إرسال صورة عشوائية للكلب حسب سلالته وسلالته الفرعية.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109231" href="https://academy.hsoub.com/uploads/monthly_2022_10/breed_and_sub_breed_last_test.jpg.70fd53537f59807a0e99bdd7108fdfe9.jpg" rel=""><img alt="breed_and_sub_breed_last_test" class="ipsImage ipsImage_thumbnailed" data-fileid="109231" data-unique="jfdlr1b3t" src="https://academy.hsoub.com/uploads/monthly_2022_10/breed_and_sub_breed_last_test.thumb.jpg.6ee1aa863c57a5684be7694e566744ec.jpg" style="width: 600px; height: auto;"></a>
</p>

<ul>
<li>
		إجراء محادثة وتقديم المساعدة.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109233" href="https://academy.hsoub.com/uploads/monthly_2022_10/conversation_provide_help_last_test.jpg.7c865cc6a194a2acf5ac23ca317e835a.jpg" rel=""><img alt="conversation_provide_help_last_test" class="ipsImage ipsImage_thumbnailed" data-fileid="109233" data-unique="9fw19hx7s" src="https://academy.hsoub.com/uploads/monthly_2022_10/conversation_provide_help_last_test.thumb.jpg.75c03fd653cc939f5971f86339a5b8a1.jpg" style="width: 600px; height: auto;"></a>
</p>

<ul>
<li>
		الاستجابة للأوامر غير المعروفة.
	</li>
</ul>
<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="109244" href="https://academy.hsoub.com/uploads/monthly_2022_10/unrecognised_commands_last_test.jpg.7382d2033e6c31a9f7f23705c911c458.jpg" rel=""><img alt="unrecognised_commands_last_test" class="ipsImage ipsImage_thumbnailed" data-fileid="109244" data-unique="151lfos4n" src="https://academy.hsoub.com/uploads/monthly_2022_10/unrecognised_commands_last_test.thumb.jpg.1c78f7df5a31faba2ed1ee1e2477d03f.jpg" style="width: 600px; height: auto;"></a>
</p>

<h2>
	الخاتمة
</h2>

<p>
	قدم هذا المقال طريقةً لتطوير بوت وربطه بإحدى وسائل التواصل الاجتماعي الشهيرة وهي التلغرام، إذ يمكن الاعتماد على إطار العمل بوتمان للربط مع العديد من <a href="https://academy.hsoub.com/marketing/social-media/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%88%D8%B3%D8%A7%D8%A6%D9%84-%D8%A7%D9%84%D8%AA%D9%88%D8%A7%D8%B5%D9%84-%D8%A7%D9%84%D8%A7%D8%AC%D8%AA%D9%85%D8%A7%D8%B9%D9%8A-%D9%88%D8%A2%D9%84%D9%8A%D8%A9-%D8%B9%D9%85%D9%84%D9%87%D8%A7-r526/" rel="">وسائل التواصل الاجتماعي</a> لتطوير بوت قادر على الاتصال بشريحة واسعة من المستخدمين، كما تضمن المقال خطوات تحديد الأوامر المتاحة للبوت ليتخاطب بها مع المستخدمين وطريقة التعامل مع الحالات الخاصة.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-build-a-telegram-bot-with-laravel-and-botman" rel="external nofollow">How To Build a Telegram Bot with Laravel and BotMan</a> لصاحبه Rachid Laasri.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%d8%a7%d8%b3%d8%aa%d8%ae%d8%af%d8%a7%d9%85-%d9%82%d9%88%d8%a7%d9%84%d8%a8-blade-%d9%84%d8%a5%d9%86%d8%b4%d8%a7%d8%a1-%d8%b9%d8%b1%d9%88%d8%b6-laravel-r220/" rel="">استخدام قوالب Blade لإنشاء عروض Laravel</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AC%D8%B1%D9%8A%D8%AF-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D8%A8%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-migration-%D9%88%D8%A7%D9%84%D8%A8%D8%B0%D8%B1-seeder-r1725/" rel="">تجريد إعداد قواعد البيانات في لارافيل باستعمال عملية التهجير Migration والبذر Seeder</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1740</guid><pubDate>Sun, 09 Oct 2022 16:08:01 +0000</pubDate></item><item><title>&#x62A;&#x62C;&#x631;&#x64A;&#x62F; &#x625;&#x639;&#x62F;&#x627;&#x62F; &#x642;&#x648;&#x627;&#x639;&#x62F; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x641;&#x64A; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; &#x628;&#x627;&#x633;&#x62A;&#x639;&#x645;&#x627;&#x644; &#x639;&#x645;&#x644;&#x64A;&#x629; &#x627;&#x644;&#x62A;&#x647;&#x62C;&#x64A;&#x631; Migration &#x648;&#x627;&#x644;&#x628;&#x630;&#x631; Seeder</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AC%D8%B1%D9%8A%D8%AF-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-%D8%A8%D8%A7%D8%B3%D8%AA%D8%B9%D9%85%D8%A7%D9%84-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%87%D8%AC%D9%8A%D8%B1-migration-%D9%88%D8%A7%D9%84%D8%A8%D8%B0%D8%B1-seeder-r1725/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_10/633821a2deecf_---------Migration--Seeder.jpg.bcdd0d55d43e5ad3d05aa29b864a64a9.jpg" /></p>
<p>
	يتيح إطار العمل لارافيل Laravel المعتمد على <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AF%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%B3%D8%B1%D9%8A%D8%B9-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-php-r609/" rel="">لغة PHP</a> عدة أدوات مُستخدمة مع <a href="https://academy.hsoub.com/devops/servers/databases/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-database/" rel="">قواعد البيانات</a> ومن أهمها أداتي التهجير وتوليد البيانات أو البذر seeder اللتان تساعدان المطور على تهيئة قاعدة البيانات أو التخلص منها أو إعادة إنشائها بسرعة عالية، إذ تقلل هذه الأدوات من مشاكل عدم الاتساق الخاصة بقاعدة البيانات، والتي تظهر عند تشارك عدة مطورين باستخدام نفس قاعدة البيانات أو نفس التطبيق في الوقت ذاته. ينفذ المطوّر الذي يحتاج للعمل مع قواعد البيانات المشتركة مجموعةً بسيطةً من أوامر "artisan" لإعداد قاعدة البيانات لتصبح جاهزة للاستخدام.
</p>

<p>
	نستخدم في عملنا هذا عدة عمليات تهجير لقواعد البيانات وتوليد بيانات نموذجية لملء قاعدة بيانات خاصة بتطبيق لارافيل توضيحي، وسنحذف الجداول ونعيد إنشائها عدة مرات باستخدام أوامر "artisan" فقط.
</p>

<h2>
	المتطلبات الأساسية
</h2>

<p>
	لاتباع خطوات هذا المقال ستحتاج ما يلي:
</p>

<ul>
	<li>
		الوصول إلى حاسب يعمل بنظام التشغيل أوبنتو Ubuntu ذي رقم إصدار 18.04 أو إلى <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AE%D8%A7%D8%AF%D9%85-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r574/" rel="">خادم</a> تطوير يعمل بنفس <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">نظام التشغيل</a> المذكور بواسطة مستخدم ذي صلاحيات إدارة sudo ولا يفضل استخدام حساب الجذر Root لأسباب تتعلق بأمان الخادم كما يفضّل وجود جدار حماية نشط في حال العمل على خادم بعيد.
	</li>
	<li>
		تثبيت الأداة دوكر Docker على الخادم.
	</li>
	<li>
		تثبيت الأداة دوكر كومبوز Docker Compose على الخادم.
	</li>
</ul>

<p>
	<strong>ملاحظة</strong>: نستخدم بيئة تطوير حاويات تديرها الأداة دوكر كومبوز لتشغيل التطبيق كما يمكن اختيار <a href="https://academy.hsoub.com/devops/servers/%D9%83%D9%8A%D9%81-%D8%AA%D8%AB%D8%A8%D8%AA-%D8%AD%D8%B2%D9%85-mysql-%D8%8Cnginx-%D8%8Clinux-lemp-%D9%88php-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1404-r29/" rel="">حزمة التخديم LEMP</a> لتشغيله.
</p>

<h2>
	الخطوة 1- الحصول على التطبيق التوضيحي
</h2>

<p>
	نبدأ بتحميل تطبيق لارافيل التوضيحي من مخزن <a href="https://github.com/do-community/travellist-laravel-demo" rel="external nofollow">Github</a> وننتقل إلى الفرع tutorial-02، الذي يحتوي إعداد الأداة دوكر كومبوز لتشغيل التطبيق على الحاويات، نحمّل التطبيق التوضيحي في المجلد الافتراضي ولكن يمكن اختيار أي مجلد آخر إذا دعت الحاجة لذلك، ومن ثم ننفذ الأوامر التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_7" style=""><span class="pln">cd </span><span class="pun">~</span><span class="pln">
curl </span><span class="pun">-</span><span class="pln">L https</span><span class="pun">:</span><span class="com">//github.com/do-community/travellist-laravel-demo/archive/tutorial-2.0.1.zip -o travellist.zip</span></pre>

<p>
	يبدأ تحميل الملف المضغوط بصيغة "zip." لذلك يجب عند انتهاء التحميل فك الضغط بعد التأكد من تحديث الحزم الخاصة بنظام التشغيل ما لم تكن محدّثة مؤخرًا، وذلك بتنفيذ الأوامر التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_9" style=""><span class="pln">sudo apt update</span></pre>

<p>
	نثبت الحزمة "unzip" بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_11" style=""><span class="pln">sudo apt install unzip</span></pre>

<p>
	مع إتمام عملية التثبيت نفك ضغط الملف بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_13" style=""><span class="pln">unzip travellist</span><span class="pun">.</span><span class="pln">zip</span></pre>

<p>
	نعيد تسمية المجلد ليصبح باسم "travellist-demo" لسهولة الوصول إليه بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_15" style=""><span class="pln">mv travellist</span><span class="pun">-</span><span class="pln">laravel</span><span class="pun">-</span><span class="pln">demo</span><span class="pun">-</span><span class="pln">tutorial</span><span class="pun">-</span><span class="lit">2.0</span><span class="pun">.</span><span class="lit">1</span><span class="pln"> travellist</span><span class="pun">-</span><span class="pln">demo</span></pre>

<h2>
	الخطوة 2- إعداد ملف "env." الخاص بالتطبيق
</h2>

<p>
	يتضمن الملف "env." <a href="https://12factor.net/config" rel="external nofollow">عمليات الضبط الخاصة بالبيئة</a>، مثل بيانات الاعتماد Credentials وأية معلومات تختلف بين عمليات نشر التطبيقات، لذلك لا يُضمّن هذا الملف ضمن ملفات التحكم بالإصدارات لكي لا تنتشر هذه المعلومات لجميع المستخدمين الذين يستخدمون صورة التطبيق لاحقًا.
</p>

<p>
	<strong>تحذير:</strong> يحتوي ملف ضبط البيئة على معلومات حساسة حول الخادم، بما في ذلك بيانات اعتماد قاعدة البيانات ومفاتيح الأمان، لهذا السبب لا يجب مشاركة هذا الملف علنًا.
</p>

<p>
	توجد أولوية للقيم الموجودة في الملف "env." على القيم الموجودة في ملفات التهيئة الأخرى الموجودة في المجلد "config"، وتتطلب كل عملية تثبيت في بيئة جديدة ملف بيئة مخصص لتعريف معلومات خاصة، مثل إعدادات الاتصال بقاعدة البيانات، خيارات التصحيح debug والرابط الخاص بالتطبيق <a href="https://academy.hsoub.com/programming/general/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%B9%D9%86%D9%88%D8%A7%D9%86-url-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87-r1435/" rel="">URL</a>، إضافةً لبقية العناصر التي تختلف تبعاً للبيئة التي يعمل بها التطبيق.
</p>

<p>
	ننتقل إلى المجلّد "travellist-demo" بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_17" style=""><span class="pln">cd travellist</span><span class="pun">-</span><span class="pln">demo</span></pre>

<p>
	ننشئ ملف "env." جديد لتخصيص خيارات الإعداد لبيئة التطوير التي نعدها. ويمكننا نسخ الملف "example.env" الذي الموجود افتراضيًا ضمن أي تطبيق لارافيل بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_19" style=""><span class="pln">cp </span><span class="pun">.</span><span class="pln">env</span><span class="pun">.</span><span class="pln">example </span><span class="pun">.</span><span class="pln">env</span></pre>

<p>
	نستخدم محرر نانو nano لتعديل محتوى الملف بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_23" style=""><span class="pln">nano </span><span class="pun">.</span><span class="pln">env</span></pre>

<p>
	يبدو هذا الملف بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_21" style=""><span class="pln">APP_NAME</span><span class="pun">=</span><span class="typ">Travellist</span><span class="pln">
APP_ENV</span><span class="pun">=</span><span class="pln">dev
APP_KEY</span><span class="pun">=</span><span class="pln">
APP_DEBUG</span><span class="pun">=</span><span class="kwd">true</span><span class="pln">
APP_URL</span><span class="pun">=</span><span class="pln">http</span><span class="pun">:</span><span class="com">//localhost:8000 </span><span class="pln">

LOG_CHANNEL</span><span class="pun">=</span><span class="pln">stack

DB_CONNECTION</span><span class="pun">=</span><span class="pln">mysql
DB_HOST</span><span class="pun">=</span><span class="pln">db
DB_PORT</span><span class="pun">=</span><span class="lit">3306</span><span class="pln">
DB_DATABASE</span><span class="pun">=</span><span class="pln">travellist
DB_USERNAME</span><span class="pun">=</span><span class="pln">travellist_user
DB_PASSWORD</span><span class="pun">=</span><span class="pln">password
</span><span class="pun">…</span></pre>

<p>
	يحتوي ملف "env." الحالي الخاص بتطبيق "travellist" التوضيحي إعدادات لاستخدام بيئة الحاويات التي أنشأناها باستخدام أداة دوكر كومبوز. لا نحتاج إلى تغيير أي من هذه القيم، ولكن يمكن تعديل <code>DB_DATABASE</code> و <code>DB_USERNAME</code> و <code>DB_PASSWORD</code> عند الحاجة، حيث أنّ هذه القيم تُسحب بالاعتماد على الملف <code>docker-compose.yml</code> تلقائيًا لإعداد قاعدة البيانات.
</p>

<p>
	نتأكد من بقاء المتغير <code>DB_HOST</code> دون تغيير، لأنه يشير إلى اسم خادم قاعدة البيانات داخل بيئة دوكر كومبوز. نضغط على الاختصار "CTRL + X" ثم زر "Y" وأخيرًا زر الإدخال "Enter" عند الانتهاء من تعديل الملف.
</p>

<p>
	<strong>ملاحظة</strong>: نحتاج عند تشغيل التطبيق على <strong>خادم LEMP</strong> إلى تغيير القيم المشار إليها لتتوافق مع إعدادات قاعدة البيانات بما في ذلك المتغير "DB_HOST".
</p>

<h2>
	الخطوة 3- تثبيت اعتماديات التطبيق مع كومبوزر
</h2>

<p>
	نستخدم الأداة <a href="https://getcomposer.org/" rel="external nofollow">كومبوزر</a> لإدارة الاعتمادية الخاصة ببرامج <a href="https://wiki.hsoub.com/PHP" rel="external">PHP</a>، إذ تُستخدم لتثبيت جميع اعتماديات التطبيق والتأكد من إمكانية استخدام أوامر "artisan".
</p>

<p>
	نُظهر بيئة دوكر كومبوز حيث نبني صورة "travellist" لتشغيل التطبيق مثل خدمة "app" كما تُحمَّل جميع صور دوكر المتعلقة بالتطبيق مثل "nginx" و "db" لتشكيل بيئة التطبيق الكاملة. ننفذ الأمر التالي لتحقيق ذلك:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_26" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose up </span><span class="pun">-</span><span class="pln">d</span></pre>

<p>
	وسيكون الخرج على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_28" style=""><span class="typ">Creating</span><span class="pln"> network </span><span class="str">"travellist-demo_travellist"</span><span class="pln"> </span><span class="kwd">with</span><span class="pln"> driver </span><span class="str">"bridge"</span><span class="pln">
</span><span class="typ">Building</span><span class="pln"> app
</span><span class="typ">Step</span><span class="pln"> </span><span class="lit">1</span><span class="pun">/</span><span class="lit">11</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> FROM php</span><span class="pun">:</span><span class="lit">7.4</span><span class="pun">-</span><span class="pln">fpm
 </span><span class="pun">---&gt;</span><span class="pln"> fa37bd6db22a
</span><span class="typ">Step</span><span class="pln"> </span><span class="lit">2</span><span class="pun">/</span><span class="lit">11</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> ARG user
 </span><span class="pun">---&gt;</span><span class="pln"> </span><span class="typ">Running</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="lit">9259bb2ac034</span><span class="pln">
</span><span class="pun">…</span><span class="pln">
</span><span class="typ">Creating</span><span class="pln"> travellist</span><span class="pun">-</span><span class="pln">app   </span><span class="pun">...</span><span class="pln"> </span><span class="kwd">done</span><span class="pln">
</span><span class="typ">Creating</span><span class="pln"> travellist</span><span class="pun">-</span><span class="pln">nginx </span><span class="pun">...</span><span class="pln"> </span><span class="kwd">done</span><span class="pln">
</span><span class="typ">Creating</span><span class="pln"> travellist</span><span class="pun">-</span><span class="pln">db    </span><span class="pun">...</span><span class="pln"> </span><span class="kwd">done</span></pre>

<p>
	تستغرق هذه العملية بضع دقائق حتى تكتمل ومن ثم نشغّل كومبوزر لتثبيت اعتماديات التطبيق. نستخدم الأمر <code>docker-compose exec</code> لتنفيذ أوامر كومبوزر وجميع الأوامر الأخرى ضمن حاوية خدمة التطبيق، إذ يسمح الأمر<code>exec</code> بتنفيذ أي أمر على الحاويات التي يديرها دوكر كومبوز، ويُكتب هذا الأمر وفقًا للصيغة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_30" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> service_name command</span></pre>

<p>
	إذ يُستبدل المتغير <code>service_name</code> باسم الخدمة التي نرغب بتنفيذ الأمر عليها ويُستبدل المتغير<code>command </code>بالأمر الذي نريد تطبيقه.
</p>

<p>
	<strong>ملاحظة</strong>: نتجاهل عمليات الأمر <code>docker-compose exec</code> في حال استخدام خادم LEMP لتشغيل التطبيق التجريبي ونستخدم الأمر <code>composer install</code>عوضًا عنه.
</p>

<p>
	ننفذ الأمر <code>composer install</code> ضمن الحاوية <code>app</code> بتطبيق الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_32" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> app composer install </span></pre>

<p>
	يظهر الخرج التالي بعد انتهاء التنفيذ:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_34" style=""><span class="typ">Loading</span><span class="pln"> composer repositories </span><span class="kwd">with</span><span class="pln"> </span><span class="kwd">package</span><span class="pln"> information
</span><span class="typ">Installing</span><span class="pln"> dependencies </span><span class="pun">(</span><span class="pln">including </span><span class="kwd">require</span><span class="pun">-</span><span class="pln">dev</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="kwd">lock</span><span class="pln"> file
</span><span class="typ">Package</span><span class="pln"> operations</span><span class="pun">:</span><span class="pln"> </span><span class="lit">85</span><span class="pln"> installs</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> updates</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> removals
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Installing</span><span class="pln"> doctrine</span><span class="pun">/</span><span class="pln">inflector </span><span class="pun">(</span><span class="lit">1.3</span><span class="pun">.</span><span class="lit">1</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Downloading</span><span class="pln"> </span><span class="pun">(</span><span class="lit">100</span><span class="pun">%)</span><span class="pln">         
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Installing</span><span class="pln"> doctrine</span><span class="pun">/</span><span class="pln">lexer </span><span class="pun">(</span><span class="lit">1.2</span><span class="pun">.</span><span class="lit">0</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Downloading</span><span class="pln"> </span><span class="pun">(</span><span class="lit">100</span><span class="pun">%)</span><span class="pln">         
  </span><span class="pun">-</span><span class="pln"> </span><span class="typ">Installing</span><span class="pln"> dragonmantank</span><span class="pun">/</span><span class="pln">cron</span><span class="pun">-</span><span class="pln">expression </span><span class="pun">(</span><span class="pln">v2</span><span class="pun">.</span><span class="lit">3.0</span><span class="pun">):</span><span class="pln"> </span><span class="typ">Downloading</span><span class="pln"> </span><span class="pun">(</span><span class="lit">100</span><span class="pun">%)</span><span class="pln">     
</span><span class="pun">…</span></pre>

<p>
	ننتظر إلى أن ينتهي كومبوزر من تثبيت اعتماديات التطبيق ومن ثم نستطيع تنفيذ أوامر "artisan". نختبر قدرة التطبيق على الاتصال بقاعدة البيانات بتنفيذ الأمر التالي الذي يفرّغ محتوى الجداول الموجودة مسبقًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_36" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> app php artisan db</span><span class="pun">:</span><span class="pln">wipe</span></pre>

<p>
	يظهر الخرج التالي ما لم توجد مشكلة ما وعندها يكون التطبيق قادرًا على الاتصال بقاعدة البيانات:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1458_41" style=""><span class="typ">Dropped</span><span class="pln"> all tables successfully</span><span class="pun">.</span></pre>

<p>
	نستخدم أداة "artisan" في تهجير وتوليد المعطيات بعد التأكد من قدرة التطبيق على الاتصال بقاعدة البيانات.
</p>

<h2>
	الخطوة 4- تهجير قاعدة البيانات
</h2>

<p>
	يتضمن الأمر "artisan" المُتاح افتراضيًا ضمن لارافيل عدة أوامر مساعدة تُستخدم في إدارة التطبيقات وتهيئة الأصناف الجديدة، نستخدم الأمر <code>make:migration</code> لتوليد صنف تهجير بيانات جديد بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_43" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> app php artisan make</span><span class="pun">:</span><span class="pln">migration create_places_table</span></pre>

<p>
	تستنتج لارافيل من الأمر السابق أن العملية المطلوبة هي عملية إنشاء <code>create</code> وأنّ اسم الجدول المطلوب <code>places</code>. تحدد لارافيل إذا ما كانت عملية التهجير تنشئ جدولًا جديدًا أم لا بناءً على الاسم الوصفي الموجود في الأمر <code>make:migration</code>.
</p>

<p>
	يظهر الخرج التالي بعد تنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_45" style=""><span class="typ">Created</span><span class="pln"> </span><span class="typ">Migration</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2020</span><span class="pln">_02_03_143622_create_places_table</span></pre>

<p>
	يولَّد ملف جديد في المجلد "database/migrations" ضمن التطبيق ويُستخدم الطابع الزمني المضمّن في الملف المُنشأ تلقائيًا بوساطة لارافيل لتحديد الترتيب الذي تُنفّذ عمليات التهجير وفقًا له. نحرر الملف الذي ولّدناه باستخدام محرر النصوص المفضّل مع التركيز على استبدال اسم الملف أدناه باسم الملف الفعلي في حال وجود اختلاف بينهما.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_48" style=""><span class="pln">nano database</span><span class="pun">/</span><span class="pln">migrations</span><span class="pun">/</span><span class="lit">2020</span><span class="pln">_02_03_143622_create_places_table</span><span class="pun">.</span><span class="pln">php</span></pre>

<p>
	يحتوي هذا الملف على صنفٍ يدعى <code>CreatePlacesTable</code> كما هو مبين فيما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_50" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Migrations\Migration</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Schema\Blueprint</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\Schema</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CreatePlacesTable</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Migration</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
     * Run the migrations.
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'places'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">bigIncrements</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">/**
     * Reverse the migrations.
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> down</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">dropIfExists</span><span class="pun">(</span><span class="str">'places'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يتضمن هذا الصنف تابعين هما <code>up</code> و <code>down</code>، اللتان تحتويان على شيفرة تهيئة التشغيل التي تحدد ما يحدث عند تنفيذ عملية التهجير وعند التراجع عنها.
</p>

<p>
	نعدّل التابع <code>up</code> بحيث يعكس الجدول <code>places</code> البنية التي نستخدمها في تطبيقنا الحالي:
</p>

<ul>
	<li>
		<code>id</code>: حقل المفتاح الأساسي.
	</li>
	<li>
		<code>name</code>: حقل اسم المكان.
	</li>
	<li>
		<code>visited</code>: حقل يشير إذا ما حدثت زيارة لهذا المكان مسبقًا أم لا.
	</li>
</ul>

<p>
	يقدِّم مُنشِئ المخططات schema في لارافيل طرقًا لإنشاء وتعديل وحذف الجداول في قاعدة البيانات، إذ يعرّف الصنف <code>Blueprint</code> بنية الجدول ويقدم مجموعة <a href="https://wiki.hsoub.com/Laravel/migrations#.D8.A5.D9.86.D8.B4.D8.A7.D8.A1_.D8.A7.D9.84.D8.A3.D8.B9.D9.85.D8.AF.D8.A9" rel="external">توابع</a> تحدّد حقول الجدول على نحوٍ مجرّد.
</p>

<p>
	تُعد الشيفرة البرمجية المولّدة تلقائيًا حقلًا للمعرف الأساسي <code>id</code> كما ينشئ التابع <code>timestamps</code> حقلين من نوع معطيات <code>timestamps</code> يُعدَلان آليًا عند إضافة قيم إلى الجدول أو عند تعديل القيم الموجودة مسبقًا ضمن الجدول، ويُضاف إلى هذه الحقول حقلين إضافيين هما <code>name</code> و <code>visited</code>.
</p>

<p>
	يُضبط نوع الحقل <code>name</code> ليكون سلسلة نصية "string" والحقل <code>visited</code> من النوع "boolean" وتوضع القيمة "0" في الحقل <code>visited</code> على أنها قيمة افتراضية لتمثّل عدم زيارة المكان مسبقًا ليصبح التابع الذي نعدّله على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_52" style=""><span class="pun">…</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> up</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="typ">Schema</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="str">'places'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Blueprint</span><span class="pln"> $table</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">bigIncrements</span><span class="pun">(</span><span class="str">'id'</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">string</span><span class="pun">(</span><span class="str">'name'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="kwd">boolean</span><span class="pun">(</span><span class="str">'visited'</span><span class="pun">)-&gt;</span><span class="kwd">default</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln">
            $table</span><span class="pun">-&gt;</span><span class="pln">timestamps</span><span class="pun">();</span><span class="pln">
        </span><span class="pun">});</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">…</span></pre>

<p>
	<strong>ملاحظة</strong>: توجد قائمة بجميع أنواع الأعمدة المتاحة ضمن <a href="https://wiki.hsoub.com/Laravel/migrations#.D8.A5.D9.86.D8.B4.D8.A7.D8.A1_.D8.A7.D9.84.D8.A3.D8.B9.D9.85.D8.AF.D8.A9" rel="external">التوثيق الخاص بلارافيل</a>.
</p>

<p>
	نحفظ الملف بعد التأكد من إضافة كامل المحتوى السابق، ثم نغلقه فتصبح قاعدة البيانات جاهزة للتهجير بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_54" style=""><span class="pln">artisan migrate</span></pre>

<p>
	تُنشأ حاليًا جداول فارغة بالبنية التي اعتمدناها ولملء هذه الجداول ببيانات من اختيارنا لا بُد من استخدام مولّدات قواعد البيانات.
</p>

<h2>
	الخطوة 5- إنشاء مولدات قواعد البيانات
</h2>

<p>
	يستخدم الصنف الخاص Seeder لتوليد وإدخال البيانات إلى قاعدة البيانات، وتساعد هذه الميزة المطورين على إعادة إنشاء قاعدة البيانات وإدخال البيانات إليها بسرعة عالية دون الحاجة إلى عمليات يدوية لتحقيق ذلك. يولَّد صنف توليد بيانات آليًا باستخدام الأمر <code>artisan</code> ويحمل هذا الصنف الاسم <code>PlacesTableSeeder</code> بتنفيذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_56" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> app php artisan make</span><span class="pun">:</span><span class="pln">seeder </span><span class="typ">PlacesTableSeeder</span></pre>

<p>
	يظهر ملف جديد اسمه "PlacesTableSeeder.php" ضمن المجلد "database/seeds". نحرّر محتوى الملف باستخدام محرر النصوص المفضّل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_60" style=""><span class="pln">nano database</span><span class="pun">/</span><span class="pln">seeds</span><span class="pun">/</span><span class="typ">PlacesTableSeeder</span><span class="pun">.</span><span class="pln">php</span></pre>

<p>
	يتضمن الملف "PlacesTableSeeder.php" المُولّد تلقائيًا المحتوى التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_58" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Seeder</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PlacesTableSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
     * Run the database seeds.
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">//</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يحتوي الصنف على تابع فارغ <code>run</code> والذي يبدأ عمله عند تنفيذ الأمر <code>db:seed</code>. نعدّل محتوى هذا التابع ليتضمن التعليمات التي تُدخِل عينةً من البيانات إلى قاعدة البيانات، ونستخدم <a href="https://wiki.hsoub.com/Laravel/queries" rel="external">مُنشئ استعلامات لارافيل</a> لتنفيذ ذلك.
</p>

<p>
	يتيح منشئ استعلام لارافيل واجهة سلسة لعمليات قاعدة البيانات، مثل إدراج البيانات وتحديثها وحذفها واسترجاعها، كما أنّه يحمي قاعدة البيانات من هجمات حقن <a href="https://academy.hsoub.com/programming/sql/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-sql-r844/" rel="">SQL</a>. يمكن الوصول إلى باني الاستعلامات بالاعتماد على واجهة خاصة تدعى <a href="https://wiki.hsoub.com/Laravel/facades" rel="external">facade</a> وهي وكيل Proxy ساكن إلى الأصناف الخاصة بقاعدة البيانات ضمن حاوية التطبيق.
</p>

<p>
	ننشئ متغير ساكن من نوع مصفوفة ضمن الصنف والذي يحتوي على جميع الأماكن التي نرغب بإدخالها إلى قاعدة البيانات مثل مصفوفة. نستخدم حلقة <code>foreach</code> للتجوال على جميع القيم وإدخال كل منها بالاعتماد على باني الاستعلامات وسندعو هذا المتغير بالاسم <code>places$</code>كما في الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_65" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Seeder</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PlacesTableSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> $places </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'Berlin'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Budapest'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Cincinnati'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Denver'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Helsinki'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Lisbon'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Moscow'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Nairobi'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Oslo'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Rio'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Tokyo'</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">

</span><span class="pun">…</span></pre>

<p>
	نستخدم عبارة <code>use</code> ضمن الصنف <code>PlacesTableSeeder</code> للمساعدة في الإشارة إلى واجهات قاعدة البيانات ضمن الشيفرة البرمجية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_67" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Seeder</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\DB</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PlacesTableSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</span><span class="pln">
</span><span class="pun">…</span></pre>

<p>
	نستخدم حلقة <code>foreach</code> للتجوال ضمن قيم المصفوفة <code>places$</code> وإدخال كل من هذه القيم ضمن الجدول <code>places</code> باستخدام باني الاستعلامات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_69" style=""><span class="pln"> </span><span class="pun">…</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">self</span><span class="pun">::</span><span class="pln">$places </span><span class="kwd">as</span><span class="pln"> $place</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'places'</span><span class="pun">)-&gt;</span><span class="pln">insert</span><span class="pun">([</span><span class="pln">
                </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $place</span><span class="pun">,</span><span class="pln">
                </span><span class="str">'visited'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> rand</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="pun">]);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span></pre>

<p>
	تتكرر تعليمات حلقة <code>foreach</code>على قيم المصفوفة الساكنة <code>places$</code> واحدةً تلو الأخرى، ومع كل تكرار تُدخِل واجهة قاعدة البيانات سطرًا جديدًا ضمن الجدول <code>places</code>، بحيث يُضاف قيمة اسم المدينة الموجود في الجدول ضمن قاعدة البيانات من القيمة الموافقة في المصفوفة <code>places$</code>، كما توضع قيمة عشوائية إما أن تكون 0 أو 1 ضمن الحقل <code>visited</code>.
</p>

<p>
	يصبح محتوى الشيفرة البرمجية الكاملة للصف <code>PlacesTableSeeder</code> بعد تجميع الأجزاء البرمجية السابقة على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_71" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Seeder</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Support\Facades\DB</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">PlacesTableSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">static</span><span class="pln"> $places </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'Berlin'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Budapest'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Cincinnati'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Denver'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Helsinki'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Lisbon'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Moscow'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Nairobi'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Oslo'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Rio'</span><span class="pun">,</span><span class="pln">
        </span><span class="str">'Tokyo'</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">

    </span><span class="com">/**
     * Run the database seeds.
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">self</span><span class="pun">::</span><span class="pln">$places </span><span class="kwd">as</span><span class="pln"> $place</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            DB</span><span class="pun">::</span><span class="pln">table</span><span class="pun">(</span><span class="str">'places'</span><span class="pun">)-&gt;</span><span class="pln">insert</span><span class="pun">([</span><span class="pln">
                </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $place</span><span class="pun">,</span><span class="pln">
                </span><span class="str">'visited'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> rand</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
            </span><span class="pun">]);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا تُحمّل أصناف توليد البيانات آليًا ضمن التطبيق، أي أنّه يجب تعديل الصنف <code>DatabaseSeeder</code> الرئيسي لتضمينها استدعاءً للصنف الذي أنشأناه. نحرر الملف "database/seeds/DatabaseSeeder.php" باستخدام محرر نانو أو أي محرر مفضل لديك بتنفيذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_73" style=""><span class="pln">nano database</span><span class="pun">/</span><span class="pln">seeds</span><span class="pun">/</span><span class="typ">DatabaseSeeder</span><span class="pun">.</span><span class="pln">php</span></pre>

<p>
	لا يختلف الصنف "DatabaseSeeder" عن أية صنف آخر لتوليد البيانات، إذ أنّه يرث الصنف "Seeder" ويمتلك التابع "run" الذي نُحدّث محتواه ليتضمن استدعاءً للصنف "PlacesTableSeeder".
</p>

<p>
	نحدّث محتوى التابع <code>run</code> ضمن الصنف <code>DatabaseSeeder</code> بإزالة التعليق الموجود ضمنه وإضافة ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_75" style=""><span class="pun">…</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="typ">PlacesTableSeeder</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">…</span></pre>

<p>
	يصبح محتوى الشيفرة البرمجية للصنف <code>DatabaseSeeder</code> بعد التحديث كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_77" style=""><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Seeder</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">DatabaseSeeder</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Seeder</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
     * Seed the application's database.
     *
     * @return void
     */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="typ">PlacesTableSeeder</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نحفظ الملف السابق وبهذا يكون قد انتهى إعداد كل من وظيفتي التهجير وتوليد البيانات الخاصتين بالجدول <code>places</code> ويبقى تنفيذ هذه الإجراءات.
</p>

<h2>
	الخطوة 6- ترحيل قواعد البيانات وتوليد البيانات
</h2>

<p>
	نتأكد من أنّ التطبيق الذي أعددناه جاهز للعمل، ومن ثم نُعدّ مفاتيح التشفير الخاصة بالتطبيق وعندها نستطيع اختبار التطبيق بطلبه ضمن المتصفح ومراقبة استجابة الخادم للطلب. نولّد مفاتيح التشفير الضرورية لعمل لارافيل وذلك باستخدام الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_79" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> app php artisan key</span><span class="pun">:</span><span class="pln">generate</span></pre>

<p>
	نطلب من المتصفح رابط التطبيق على المنفذ 8000 كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1458_81" style=""><span class="pln">http</span><span class="pun">:</span><span class="com">//server_host_or_ip:8000</span></pre>

<p>
	نرى الاستجابة التالية على المتصفح:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="108902" href="https://academy.hsoub.com/uploads/monthly_2022_10/browser_responce_befor_migration.jpg.8bfb705cf5ced5f1f68299eafb6380df.jpg" rel="" data-fileext="jpg"><img alt="browser_responce_befor_migration.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="108902" data-unique="ofs87ici5" style="width: 650px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/browser_responce_befor_migration.thumb.jpg.ac1479990f0e71381c5c280e0187ee89.jpg"></a>
</p>

<p>
	نستنتج أن التطبيق يستطيع الاتصال بقاعدة البيانات لكنه لم يعثر على جدول باسم <code>places</code> ولذا ننشئ هذا الجدول بأمر التهجير التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_42" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> app php artisan migrate</span></pre>

<p>
	يظهر الخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_44" style=""><span class="typ">Migration</span><span class="pln"> table created successfully</span><span class="pun">.</span><span class="pln">
</span><span class="typ">Migrating</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2014</span><span class="pln">_10_12_000000_create_users_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2014</span><span class="pln">_10_12_000000_create_users_table </span><span class="pun">(</span><span class="lit">0.06</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Migrating</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2014</span><span class="pln">_10_12_100000_create_password_resets_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2014</span><span class="pln">_10_12_100000_create_password_resets_table </span><span class="pun">(</span><span class="lit">0.06</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Migrating</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2019</span><span class="pln">_08_19_000000_create_failed_jobs_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2019</span><span class="pln">_08_19_000000_create_failed_jobs_table </span><span class="pun">(</span><span class="lit">0.03</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Migrating</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2020</span><span class="pln">_02_10_144134_create_places_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2020</span><span class="pln">_02_10_144134_create_places_table </span><span class="pun">(</span><span class="lit">0.03</span><span class="pln"> seconds</span><span class="pun">)</span></pre>

<p>
	نلاحظ تنفيذ عمليات تهجير إضافية إلى جانب التهجير <code>create_places_table</code> الذي أعددناه، إذ يجري إعداد هذه العمليات الإضافية عند تثبيت لارافيل. لا تفيد هذه الجداول ضمن نطاق العمل الحالي إلا أنها أساسيةٌ عند توسيع عمل التطبيق لتشمل المهام المجدولة والتعامل مع المستخدمين المسجّلين ولهذا لا نعدل في محتواها الآن.
</p>

<p>
	تخلو الجداول السابقة من البيانات ومن أجل توليد بيانات في الجدول places نستخدم الأمر <code>db:seed</code> بالمحتوى الذي أنشأناه مسبقًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_46" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> app php artisan db</span><span class="pun">:</span><span class="pln">seed</span></pre>

<p>
	يشغّل الأمر السابق المُولد الذي أنشأناه ضمن الصنف <code>PlacesTableSeeder</code>، ويظهر خرجٌ مشابهٌ لما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_48" style=""><span class="typ">Seeding</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PlacesTableSeeder</span><span class="pln">
</span><span class="typ">Seeded</span><span class="pun">:</span><span class="pln">  </span><span class="typ">PlacesTableSeeder</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.06</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Database</span><span class="pln"> seeding completed successfully</span><span class="pun">.</span></pre>

<p>
	نعيد تحميل صفحة المتصفح لتظهر بالشكل التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="108901" href="https://academy.hsoub.com/uploads/monthly_2022_10/browser_responce_after_migration.jpg.ab2f99002823f3cf935b8c1b323e50d0.jpg" rel="" data-fileext="jpg"><img alt="browser_responce_after_migration.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="108901" data-unique="95hx9edxa" style="width: 300px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_10/browser_responce_after_migration.jpg.ab2f99002823f3cf935b8c1b323e50d0.jpg"></a>
</p>

<p>
	يمكن إفراغ الجداول من بياناتها بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_53" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> app php artisan db</span><span class="pun">:</span><span class="pln">wipe</span></pre>

<p>
	ويكون الخرج على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_55" style=""><span class="typ">Dropped</span><span class="pln"> all tables successfully</span><span class="pun">.</span></pre>

<p>
	ويمكن تنفيذ عمليتي التهجير والتوليد بأمر برمجي واحد بتنفيذ الأمر:
</p>

<pre class="ipsCode">docker-compose exec app php artisan migrate --seed
</pre>

<p>
	ويكون الخرج على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_57" style=""><span class="typ">Migration</span><span class="pln"> table created successfully</span><span class="pun">.</span><span class="pln">
</span><span class="typ">Migrating</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2014</span><span class="pln">_10_12_000000_create_users_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2014</span><span class="pln">_10_12_000000_create_users_table </span><span class="pun">(</span><span class="lit">0.06</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Migrating</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2014</span><span class="pln">_10_12_100000_create_password_resets_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2014</span><span class="pln">_10_12_100000_create_password_resets_table </span><span class="pun">(</span><span class="lit">0.07</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Migrating</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2019</span><span class="pln">_08_19_000000_create_failed_jobs_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2019</span><span class="pln">_08_19_000000_create_failed_jobs_table </span><span class="pun">(</span><span class="lit">0.03</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Migrating</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2020</span><span class="pln">_02_10_144134_create_places_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2020</span><span class="pln">_02_10_144134_create_places_table </span><span class="pun">(</span><span class="lit">0.03</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Seeding</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PlacesTableSeeder</span><span class="pln">
</span><span class="typ">Seeded</span><span class="pun">:</span><span class="pln">  </span><span class="typ">PlacesTableSeeder</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0.06</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Database</span><span class="pln"> seeding completed successfully</span><span class="pun">.</span></pre>

<p>
	يمكن التراجع عن عملية التهجير بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_59" style=""><span class="pln">docker</span><span class="pun">-</span><span class="pln">compose </span><span class="kwd">exec</span><span class="pln"> app php artisan migrate</span><span class="pun">:</span><span class="pln">rollback</span></pre>

<p>
	حيث يُستدعى التابع <code>down</code> من أجل كل عملية تهجير معرّفة ضمن الصنف وتكون هذه الأصناف مجمّعةً في مجلد "migrations" حيث تجري إزالة جميع الجداول التي أنشأتها أصناف التهجير باستثناء تلك التي أنشأها المستخدم يدويًا. يظهر لدينا خرج مشابهٌ لما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3249_61" style=""><span class="typ">Rolling</span><span class="pln"> back</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2020</span><span class="pln">_02_10_144134_create_places_table
</span><span class="typ">Rolled</span><span class="pln"> back</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2020</span><span class="pln">_02_10_144134_create_places_table </span><span class="pun">(</span><span class="lit">0.02</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Rolling</span><span class="pln"> back</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2019</span><span class="pln">_08_19_000000_create_failed_jobs_table
</span><span class="typ">Rolled</span><span class="pln"> back</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2019</span><span class="pln">_08_19_000000_create_failed_jobs_table </span><span class="pun">(</span><span class="lit">0.02</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Rolling</span><span class="pln"> back</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2014</span><span class="pln">_10_12_100000_create_password_resets_table
</span><span class="typ">Rolled</span><span class="pln"> back</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2014</span><span class="pln">_10_12_100000_create_password_resets_table </span><span class="pun">(</span><span class="lit">0.02</span><span class="pln"> seconds</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Rolling</span><span class="pln"> back</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2014</span><span class="pln">_10_12_000000_create_users_table
</span><span class="typ">Rolled</span><span class="pln"> back</span><span class="pun">:</span><span class="pln">  </span><span class="lit">2014</span><span class="pln">_10_12_000000_create_users_table </span><span class="pun">(</span><span class="lit">0.02</span><span class="pln"> seconds</span><span class="pun">)</span></pre>

<p>
	يفيد أمر التراجع بصورةٍ خاصة عندما نعدّل النماذج الخاصة بالتطبيق علمًا أنّ الأمر "db:wipe" لا يكون متاحًا للاستخدام كما في حالة اعتماد أكثر من نظام على قاعدة بيانات مشتركة.
</p>

<h2>
	الخاتمة
</h2>

<p>
	تضمنّت هذه المقالة توضيحًا بمدى أهمية عمليات تهجير وتوليد البيانات ضمن قاعدة البيانات من أجل إعداد واختبار قواعد البيانات الخاصة بتطبيقات لارافيل من الإصدار 6.
</p>

<p>
	ترجمة –وبتصرف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-use-database-migrations-and-seeders-to-abstract-database-setup-in-laravel" rel="external nofollow">How To Use Database Migrations and Seeders to Abstract Database Setup in Laravel</a> لصاحبه Erika Heidi.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/sql/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%B9%D9%86-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-r584/" rel="">مقدمة عن قواعد البيانات</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/%d8%aa%d9%87%d8%ac%d9%8a%d8%b1-%d9%82%d9%88%d8%a7%d8%b9%d8%af-%d8%a7%d9%84%d8%a8%d9%8a%d8%a7%d9%86%d8%a7%d8%aa-%d9%81%d9%8a-laravel-5-r224/" rel="">تهجير قواعد البيانات في Laravel 5</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/laravel/migration/" rel="">تهجير قواعد البيانات (migrations) على Laravel</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1725</guid><pubDate>Sun, 02 Oct 2022 16:01:00 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x645;&#x643;&#x62A;&#x628;&#x629; Fractal &#x641;&#x64A; &#x625;&#x637;&#x627;&#x631;&#x64A; &#x627;&#x644;&#x639;&#x645;&#x644; Laravel &#x648; Lumen &#x644;&#x625;&#x646;&#x634;&#x627;&#x621; &#x627;&#x633;&#x62A;&#x62C;&#x627;&#x628;&#x627;&#x62A; &#x644;&#x644;&#x648;&#x627;&#x62C;&#x647;&#x627;&#x62A; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629;</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-fractal-%D9%81%D9%8A-%D8%A5%D8%B7%D8%A7%D8%B1%D9%8A-%D8%A7%D9%84%D8%B9%D9%85%D9%84-laravel-%D9%88-lumen-%D9%84%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D8%B3%D8%AA%D8%AC%D8%A7%D8%A8%D8%A7%D8%AA-%D9%84%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r575/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_12/17.png.904a0638c815ddb41753493e6f933f1e.png" /></p>

<p>
	اكتشفت مؤخرًا المتعة الكبيرة في استخدام مكتبة [Fractal المقدّمة من PHP League] لإنشاء استجابات للواجهات البرمجية التي تعطي مخرجات من نوع JSON وذلك عند العمل على نماذج Eloquent في إطاري العمل Laravel و Lumen للحصول على المخرجات التي أرغب بها. هذه الحزمة مشابهة إلى حدٍّ كبير لمكتبة ActiveModel Serializer في إطار العمل Rails، إذ إنّها تتيح لك التحكّم الدقيق بالمخرجات التي ترغب في وصولها إلى المستخدم، إضافة إلى أنّها تفصل الشيفرة المسؤولة عن إنشاء كائن JSON عن نموذج Eloquent وهذا أمر في غاية الأهمية.
</p>

<p>
	والآن بعد أن أتيح لي تطوير عدد من الواجهات البرمجية لفترة زمنية لا بأس بها، خطر لي أن أتحدّث عن الطرق التي اتبعتها في ربط Fractal مع تطبيقات Laravel و Lumen (تختلف طريقة الربط في إطار Lumen لأنّه لا يدعم ماكروات <code>Response</code>).
</p>

<h2 id="المسلسلات-المخصصة-costum-serializers">
	المُسَلسِلات المخصّصة Costum Serializers
</h2>

<p>
	بادئ ذي بدء، تدعم Fractal <a href="http://fractal.thephpleague.com/serializers/" rel="external nofollow">عددًا من المُسَلسِلات Serializers</a> لتكوين بنية خاصة بالاستجابة، وتستخدم بصورة افتراضية المسَلسِل الذي يدعى بـ <code>DataArraySerializer</code> والذي يضيف مفتاح جذر root key يحمل الاسم <code>data</code> إلى الاستجابة، لذا إن كنت لا تمانع من استخدام هذا المُسَلسِل فيمكنك تجاوز هذه الخطوة. أما لو كنت ترغب في استخدام مُسَلسِل آخر فعليك تسجيل الصنف <code>Manager</code> مع حاوية IoC في مزوّد الخدمة <code>AppServiceProvider</code> أو في <a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%85%D8%B2%D9%88%D8%AF-%D8%AE%D8%AF%D9%85%D8%A9-service-provider-%D9%81%D9%8A-laravel-r326/" rel="">مزوّد خدمة آخر</a> إن كنت ترى أنّه يناسبك أكثر، ولكن عليك الانتباه إلى أنّ دعم <code>JSON-<abbr title="Application Programming Interface | واجهة برمجية">API</abbr></code> غير مكتمل حتى الآن (المقالة الأصلية نشرت سنة 2015. (المترجم)).
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1728_7" style="">
<span class="pln">    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="kwd">register</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $this</span><span class="pun">-&gt;</span><span class="pln">app</span><span class="pun">-&gt;</span><span class="pln">bind</span><span class="pun">(</span><span class="str">'League\Fractal\Manager'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$app</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $manager </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \League\Fractal\Manager</span><span class="pun">;</span><span class="pln">

        </span><span class="com">// Use the serializer of your choice.</span><span class="pln">
        $manager</span><span class="pun">-&gt;</span><span class="pln">setSerializer</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> \App\Http\Serializers\RootSerializer</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> $manager</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="إنشاء-المحولات-transformers">
	إنشاء المحوّلات Transformers
</h2>

<p>
	بعد ذلك سنحتاج إلى إنشاء بعض المحوّلات - محوّل لكل نوع من أنواع نماذج Eloquent التي ترغب في تخريجها بواسطة الواجهة البرمجية - وفي مثالنا هذا سأستخدم مدوّنة حيث يضمّ النموذج <code>AppUser</code> عددًا من نماذج <code>AppPost</code> وسنعرض المستخدم مع المقالات الخاصّة به. أنشأت مجلّدً للتحويلات داخل مجلّد <code>Http</code>: <code>app/Http/Transoformers</code>، والآن يمكنني إنشاء محوّلين، الأول لنموذج <code>User</code> والثاني لنموذج <code>Post</code>.
</p>

<p>
	محوّل المستخدمين <code>User</code> سيكون سهلًا، إذ أنّه سيُرجع الحقول المطلوبة من قبل واجهتي البرمجية. في هذا المثال، يمتلك النموذج <code>User</code> خاصّية <code>is_admin</code> وهي عبارة عن قيمة منطقية boolean. ويمكنني التعبير عن ذلك في المحوّل بواسطة العبارة <code>(bool) $user-&gt;is_admin</code> ولكن اعتبارًا من الإصدار 5.0 وما بعده من Laravel أصبح بالإمكان استخدام خاصّية <code>$casts</code> في النموذج وسيكون Eloquent قادرًا بعدها على معالجة عملية الوصف بالنيابة عنك. يستحسن معالجة مثل هذه الأمور ضمن النموذج لأنّها ستكون متاحة في التطبيق برمّته.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1728_7" style="">
<code class="hljs xml"><span class="php"><span class="hljs-preprocessor"><span class="pun">&lt;?</span><span class="pln">php</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">namespace</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">App</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Http</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Transformers</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">App</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">User</span></span><span class="pun">;</span><span class="pln">
</span><span class="hljs-keyword"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">League</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">Fractal</span></span><span class="pln">\</span><span class="hljs-title"><span class="pln">TransformerAbstract</span></span><span class="pun">;</span><span class="pln">

</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">UserTransformer</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">extends</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">TransformerAbstract</span></span><span class="pln">
</span><span class="pun">{</span></span><span class="pln">
    </span><span class="hljs-comment"><span class="com">/**
     * Turn this item object into a generic array.
     *
     *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  \App\User  $user
     *</span><span class="hljs-phpdoc"><span class="com"> @return</span></span><span class="com"> array
     */</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">transform</span></span><span class="hljs-params"><span class="pun">(</span><span class="typ">User</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$user</span></span><span class="pun">)</span></span><span class="pln">
    </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="pun">[</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'id'</span></span><span class="pln">         </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$user</span></span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'first_name'</span></span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$user</span></span><span class="pun">-&gt;</span><span class="pln">first_name</span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'last_name'</span></span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$user</span></span><span class="pun">-&gt;</span><span class="pln">last_name</span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'email'</span></span><span class="pln">      </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$user</span></span><span class="pun">-&gt;</span><span class="pln">email</span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'is_admin'</span></span><span class="pln">   </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$user</span></span><span class="pun">-&gt;</span><span class="pln">is_admin</span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'created_at'</span></span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$post</span></span><span class="pun">-&gt;</span><span class="pln">created_at</span><span class="pun">-&gt;</span><span class="pln">toDateTimeString</span><span class="pun">(),</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'updated_at'</span></span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$post</span></span><span class="pun">-&gt;</span><span class="pln">updated_at</span><span class="pun">-&gt;</span><span class="pln">toDateTimeString</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></span></code></pre>

<p>
	بما أنّ خصائص التاريخ في نماذج Eloquent هي نسخ من مكتبة <a href="http://carbon.nesbot.com/" rel="external nofollow">Carbon</a> يمكن إذًا استخدام الدوال المساعدة التي تقدّمها هذه المكتبة لإرجاع التاريخ بالصيغة التي نرغب بها. وفي مثالنا سنستخدم الدالة <code>toDateTimeString()</code> وسيكون التاريخ بالصيغة التالية: <code>Y-m-d H:i:s</code> (السنة - الشهر - اليوم الساعة:الدقائق:الثواني).
</p>

<p>
	والآن سنحتاج إلى محوّل لأجل نموذج <code>Post</code>، وسيكون هذا المحوّل مختلفًا عن السابق لأنّنا نرغب في تضمين النموذج <code>User</code> المرتبط بنموذج <code>Post</code> مع هذه الاستجابة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1728_7" style="">
<code class="hljs scala"><span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Transforers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Post</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">League</span><span class="pln">\Fractal\TransformerAbstract</span><span class="pun">;</span><span class="pln">

</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">PostTransformer</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">extends</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">TransformerAbstract</span></span></span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="hljs-javadoc"><span class="com">/**
     * List of resources possible to include
     *
     * </span><span class="hljs-javadoctag"><span class="com">@var</span></span><span class="com"> array
     */</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> $availableIncludes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'user'</span></span><span class="pun">];</span><span class="pln">

    </span><span class="hljs-javadoc"><span class="com">/**
     * List of resources to automatically include.
     *
     * </span><span class="hljs-javadoctag"><span class="com">@var</span></span><span class="com"> array
     */</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> $defaultIncludes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'user'</span></span><span class="pun">];</span><span class="pln">

    </span><span class="hljs-javadoc"><span class="com">/**
     * Turn this item object into a generic array.
     *
     * </span><span class="hljs-javadoctag"><span class="com">@param</span></span><span class="com">  \App\Post  $post
     * </span><span class="hljs-javadoctag"><span class="com">@return</span></span><span class="com"> array
     */</span></span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> transform</span><span class="pun">(</span><span class="typ">Post</span><span class="pln"> $post</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="pun">[</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'id'</span></span><span class="pln">           </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">id</span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'title'</span></span><span class="pln">        </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">title</span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'content'</span></span><span class="pln">      </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">content</span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'created_at'</span></span><span class="pln">   </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">created_at</span><span class="pun">-&gt;</span><span class="pln">toDateTimeString</span><span class="pun">(),</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'updated_at'</span></span><span class="pln">   </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">updated_at</span><span class="pun">-&gt;</span><span class="pln">toDateTimeString</span><span class="pun">(),</span><span class="pln">
            </span><span class="hljs-string"><span class="str">'published_at'</span></span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $post</span><span class="pun">-&gt;</span><span class="pln">published_at</span><span class="pun">-&gt;</span><span class="pln">toDateTimeString</span><span class="pun">()</span><span class="pln">
        </span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="hljs-javadoc"><span class="com">/**
     * Include user.
     *
     * </span><span class="hljs-javadoctag"><span class="com">@param</span></span><span class="com">  \App\Post  $post
     * </span><span class="hljs-javadoctag"><span class="com">@return</span></span><span class="com"> League\Fractal\ItemResource
     */</span></span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> includeLevels</span><span class="pun">(</span><span class="typ">Post</span><span class="pln"> $post</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> $</span><span class="hljs-keyword"><span class="pln">this</span></span><span class="pun">-&gt;</span><span class="pln">item</span><span class="pun">(</span><span class="pln">$post</span><span class="pun">-&gt;</span><span class="pln">user</span><span class="pun">,</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">new</span></span><span class="pln"> </span><span class="typ">UserTransformer</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></code></pre>

<p>
	لاحظ أنّه بالإمكان إرجاع <code>$this-&gt;collection</code> داخل المحوّل إن كنت ترغب في ربط مجموعة بدل من عنصر واحد.
</p>

<h2 id="إنشاء-الاستجابات-في-laravel">
	إنشاء الاستجابات في Laravel
</h2>

<p>
	عادة ما أنشئ مزوّد خدمة Fractal <code>FractalServiceProvider</code> والذي يضمّ التابع <code>register()</code> الذي قمت بوصفه سابقًا، ثم أسجّل بعض الماكروات في التابع <code>boot()</code> كما تلاحظ هنا. سيؤدي ذلك إلى إضافة تابعين إضافيين إلى معمل (factory) <code>Response</code> في Laravel وسيسهّل إرجاع الاستجابات على هيئة عناصر أو مجموعات.
</p>

<p>
	لاحظ أنّي حدّدت نوع (type hint) المحوّل ليكون نسخة من الصنف <code>TransformerAbstract</code> وذلك لأنّي أنشئ دائمًا المحوّلات من الاستجابات بدلًا من صيغة الدالة المغلقة closure لأنّي أرى بأنّ هذه الطريقة ستحافظ على ترتيب الشيفرات التي أكتبها. لكن إن كنت تفضل استخدام الدوال المغلقة بدلًا من المحوّلات فيمكنك بكل ساطة أن لا تحدد نوع المحوّل ضمن المعاملات.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1728_7" style="">
<code class="hljs php"><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">boot</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">{</span></span><span class="pln">
    </span><span class="hljs-variable"><span class="pln">$fractal</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">app</span><span class="pun">-&gt;</span><span class="pln">make</span><span class="pun">(</span><span class="hljs-string"><span class="str">'League\Fractal\Manager'</span></span><span class="pun">);</span><span class="pln">

    response</span><span class="pun">()-&gt;</span><span class="pln">macro</span><span class="pun">(</span><span class="hljs-string"><span class="str">'item'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-params"><span class="pun">(</span><span class="hljs-variable"><span class="pln">$item</span></span><span class="pun">,</span><span class="pln"> \League\Fractal\TransformerAbstract </span><span class="hljs-variable"><span class="pln">$transformer</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">200</span></span><span class="pun">,</span><span class="pln"> array </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[])</span></span><span class="pln"> </span><span class="hljs-title"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-params"><span class="pun">(</span><span class="hljs-variable"><span class="pln">$fractal</span></span><span class="pun">)</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">new</span></span><span class="pln"> \League\Fractal\Resource\Item</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$item</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$transformer</span></span><span class="pun">);</span><span class="pln">

        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">
            </span><span class="hljs-variable"><span class="pln">$fractal</span></span><span class="pun">-&gt;</span><span class="pln">createData</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pun">)-&gt;</span><span class="pln">toArray</span><span class="pun">(),</span><span class="pln">
            </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pln">
        </span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">

    response</span><span class="pun">()-&gt;</span><span class="pln">macro</span><span class="pun">(</span><span class="hljs-string"><span class="str">'collection'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-params"><span class="pun">(</span><span class="hljs-variable"><span class="pln">$collection</span></span><span class="pun">,</span><span class="pln"> \League\Fractal\TransformerAbstract </span><span class="hljs-variable"><span class="pln">$transformer</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">200</span></span><span class="pun">,</span><span class="pln"> array </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[])</span></span><span class="pln"> </span><span class="hljs-title"><span class="kwd">use</span></span><span class="pln"> </span><span class="hljs-params"><span class="pun">(</span><span class="hljs-variable"><span class="pln">$fractal</span></span><span class="pun">)</span></span><span class="pln"> </span><span class="pun">{</span></span><span class="pln">
        </span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">new</span></span><span class="pln"> \League\Fractal\Resource\Collection</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$collection</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$transformer</span></span><span class="pun">);</span><span class="pln">

        </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">
            </span><span class="hljs-variable"><span class="pln">$fractal</span></span><span class="pun">-&gt;</span><span class="pln">createData</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pun">)-&gt;</span><span class="pln">toArray</span><span class="pun">(),</span><span class="pln">
            </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pun">,</span><span class="pln">
            </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pln">
        </span><span class="pun">);</span><span class="pln">
    </span><span class="pun">});</span><span class="pln">
</span><span class="pun">}</span></code></pre>

<p>
	والآن أصبح من السهل إنشاء استجابة واحدة (لمستخدم واحد مثلًا) ومجموعة من الاستجابات (لجميع مقالات المدوّنة مثلًا).
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1728_7" style="">
<code class="hljs java"><span class="hljs-javadoc"><span class="com">/**
 * GET /users/1
 *
 *</span><span class="hljs-javadoctag"><span class="com"> @param</span></span><span class="com">  int  $userId
 *</span><span class="hljs-javadoctag"><span class="com"> @return</span></span><span class="com"> \Illuminate\Http\Response
 */</span></span><span class="pln">
</span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="hljs-title"><span class="pln">showUser</span></span><span class="pun">(</span><span class="pln">$userId</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $user </span><span class="pun">=</span><span class="pln"> \App\User</span><span class="pun">::</span><span class="pln">findOrFail</span><span class="pun">(</span><span class="pln">$userId</span><span class="pun">);</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">item</span><span class="pun">(</span><span class="pln">$user</span><span class="pun">,</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">new</span></span><span class="pln"> \App\Http\Transformers\UserTransformer</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="hljs-javadoc"><span class="com">/**
 * GET /posts
 *
 *</span><span class="hljs-javadoctag"><span class="com"> @return</span></span><span class="com"> \Illuminate\Http\Response
 */</span></span><span class="pln">
</span><span class="hljs-keyword"><span class="kwd">public</span></span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="hljs-title"><span class="pln">showPosts</span></span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $posts </span><span class="pun">=</span><span class="pln"> \App\Post</span><span class="pun">::</span><span class="kwd">with</span><span class="pun">(</span><span class="hljs-string"><span class="str">'user'</span></span><span class="pun">)-&gt;</span><span class="kwd">get</span><span class="pun">();</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">collection</span><span class="pun">(</span><span class="pln">$posts</span><span class="pun">,</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">new</span></span><span class="pln"> \App\Http\Transformers\PostTransformer</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></code></pre>

<p>
	إن كنت ترغب في استخدام حالة استجابة HTTP أخرى مثل <code>201</code> (تم الإنشاء) أو <code>204</code> (لا يوجد محتوى) يمكنك وبكل سهولة تمرير رمز الحالة كمعامل ثالث إلى الماكرو.
</p>

<h2 id="إنشاء-الاستجابات-في-lumen">
	إنشاء الاستجابات في Lumen
</h2>

<p>
	يتطلّب إنشاء الاستجابات في Lumen اتباع أسلوب مختلف قليلًا؛ ذلك لأنّ Lumen لا يدعم الماكروات في معمل <code>Response</code>؛ لذا سأضيف هذه التوابع إلى المتحكّم الرئيسي في الواجهة البرمجية.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1728_7" style="">
<code class="hljs php"><span class="hljs-comment"><span class="com">/**
 * Create the response for an item.
 *
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  mixed                                $item
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  \League\Fractal\TransformerAbstract  $transformer
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  int                                  $status
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  array                                $headers
 *</span><span class="hljs-phpdoc"><span class="com"> @return</span></span><span class="com"> Response
 */</span></span><span class="pln">
</span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">buildItemResponse</span></span><span class="hljs-params"><span class="pun">(</span><span class="hljs-variable"><span class="pln">$item</span></span><span class="pun">,</span><span class="pln"> \League\Fractal\TransformerAbstract </span><span class="hljs-variable"><span class="pln">$transformer</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">200</span></span><span class="pun">,</span><span class="pln"> array </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[])</span></span><span class="pln">
</span><span class="pun">{</span></span><span class="pln">
    </span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">new</span></span><span class="pln"> \League\Fractal\Resource\Item</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$item</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$transformer</span></span><span class="pun">);</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">buildResourceResponse</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="hljs-comment"><span class="com">/**
 * Create the response for a collection.
 *
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  mixed                                $collection
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  \League\Fractal\TransformerAbstract  $transformer
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  int                                  $status
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  array                                $headers
 *</span><span class="hljs-phpdoc"><span class="com"> @return</span></span><span class="com"> Response
 */</span></span><span class="pln">
</span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">buildCollectionResponse</span></span><span class="hljs-params"><span class="pun">(</span><span class="hljs-variable"><span class="pln">$collection</span></span><span class="pun">,</span><span class="pln"> \League\Fractal\TransformerAbstract </span><span class="hljs-variable"><span class="pln">$transformer</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">200</span></span><span class="pun">,</span><span class="pln"> array </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[])</span></span><span class="pln">
</span><span class="pun">{</span></span><span class="pln">
    </span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">new</span></span><span class="pln"> \League\Fractal\Resource\Collection</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$collection</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$transformer</span></span><span class="pun">);</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="pun">-&gt;</span><span class="pln">buildResourceResponse</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="hljs-comment"><span class="com">/**
 * Create the response for a resource.
 *
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  \League\Fractal\Resource\ResourceAbstract  $resource
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  int                                        $status
 *</span><span class="hljs-phpdoc"><span class="com"> @param</span></span><span class="com">  array                                      $headers
 *</span><span class="hljs-phpdoc"><span class="com"> @return</span></span><span class="com"> Response
 */</span></span><span class="pln">
</span><span class="hljs-keyword"><span class="kwd">protected</span></span><span class="pln"> </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">function</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">buildResourceResponse</span></span><span class="hljs-params"><span class="pun">(</span><span class="pln">\League\Fractal\Resource\ResourceAbstract </span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">200</span></span><span class="pun">,</span><span class="pln"> array </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[])</span></span><span class="pln">
</span><span class="pun">{</span></span><span class="pln">
    </span><span class="hljs-variable"><span class="pln">$fractal</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> app</span><span class="pun">(</span><span class="hljs-string"><span class="str">'League\Fractal\Manager'</span></span><span class="pun">);</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">
        </span><span class="hljs-variable"><span class="pln">$fractal</span></span><span class="pun">-&gt;</span><span class="pln">createData</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$resource</span></span><span class="pun">)-&gt;</span><span class="pln">toArray</span><span class="pun">(),</span><span class="pln">
        </span><span class="hljs-variable"><span class="pln">$status</span></span><span class="pun">,</span><span class="pln">
        </span><span class="hljs-variable"><span class="pln">$headers</span></span><span class="pln">
    </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></code></pre>

<p>
	يمكنك الآن استدعاء أي تابع من هذه التوابع في أي متحكّم موروث من هذا المتحكّم لإنشاء نفس الاستجابات التي أنشأناها مع Laravel.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1728_7" style="">
<code class="hljs lasso"><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="pln">buildItemResponse</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$user</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-literal"><span class="kwd">new</span></span><span class="pln"> </span><span class="hljs-subst"><span class="pln">\</span></span><span class="pln">App</span><span class="hljs-subst"><span class="pln">\</span></span><span class="pln">Http</span><span class="hljs-subst"><span class="pln">\</span></span><span class="pln">Transformers</span><span class="hljs-subst"><span class="pln">\</span></span><span class="pln">UserTransformer</span><span class="pun">);</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">return</span></span><span class="pln"> </span><span class="hljs-variable"><span class="pln">$this</span></span><span class="hljs-subst"><span class="pun">-&gt;</span></span><span class="pln">buildCollectionResponse</span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$posts</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-literal"><span class="kwd">new</span></span><span class="pln"> </span><span class="hljs-subst"><span class="pln">\</span></span><span class="pln">App</span><span class="hljs-subst"><span class="pln">\</span></span><span class="pln">Http</span><span class="hljs-subst"><span class="pln">\</span></span><span class="pln">Transformers</span><span class="hljs-subst"><span class="pln">\</span></span><span class="pln">PostTransformer</span><span class="pun">);</span></code></pre>

<p>
	ترجمة - وبتصرّف - للمقال <a href="https://www.neontsunami.com/posts/using-fractal-with-laravel-and-lumen" rel="external nofollow">Using Fractal with Laravel and Lumen</a> لصاحبه Dwight Conrad Watson.
</p>
]]></description><guid isPermaLink="false">575</guid><pubDate>Sun, 17 Dec 2017 11:12:00 +0000</pubDate></item><item><title>&#x625;&#x646;&#x634;&#x627;&#x621; &#x648;&#x627;&#x62C;&#x647;&#x629; &#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629; &#x628;&#x633;&#x64A;&#x637;&#x629; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x625;&#x637;&#x627;&#x631; &#x627;&#x644;&#x639;&#x645;&#x644; &#x627;&#x644;&#x645;&#x635;&#x63A;&#x651;&#x631; Lumen</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D8%A7%D9%84%D9%85%D8%B5%D8%BA%D9%91%D8%B1-lumen-r571/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_12/10.png.2e47523dffa1601f04414ac1398c3f60.png" /></p>

<p>
	Lumen هو إطار عمل مصغّر Micro-framework مبني باستخدام إطار العمل Laravel، وهما من صنع Taylor Otwell. صُمّم Lumen لتطوير الخدمات المصغّرة مثل التطبيقات الصغيرة أو خدمات الويب، والهدف من تطويره هو الحصول على أقصى قدر من السرعة، فقد تم استبدال مكوّن التوجيه Symfony في Laravel بـ FastRoute في Lument لتحسين الأداء وزيادة السرعة. في هذا الدرس سننشئ واجهة برمجية بنمط RESTful، وستعمل هذه الواجهة البرمجية على تخزين وعرض المعلومات الخاصّة بالكتب.
</p>

<h2 id="تثبيت-lumen">
	تثبيت Lumen
</h2>

<p>
	سنستخدم Composer لتثبيت lumen، لذا سنتحقّق من وجود هذه المكتبة في النظام، وذلك بكتابة الأمر التالي في الطرفية أو في سطر الأوامر:
</p>

<pre class="ipsCode" id="ips_uid_6570_7">
composer</pre>

<p>
	إن ظهرت أوامر Composer فهذا يعني أنّه مثبت في الجهاز، أمّا في حالة عدم تثبيت Composer يمكنك الاطلاع على طريقة التثبيت في <a href="https://academy.hsoub.com/programming/php/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D9%82%D8%B5%D9%8A%D8%B1%D8%A9-%D9%81%D9%8A-composer-r559/" rel="">هذا المقال</a>. بعد تثبيت composer توجّه إلى المجلّد الجذر في الخادوم:
</p>

<pre class="ipsCode" id="ips_uid_6570_9">
cd /var/www/html </pre>

<p>
	لمستخدمي نظام ويندوز سنفترض أن المستخدم يمتلك نسخة من خادوم Wamp في الجهاز، لذا يمكن التوجّه إلى المجلّد الجذر في الخادوم بواسطة الأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_6570_11">
cd wamp\www</pre>

<p>
	والآن سنخبر composer بأنّ ينشئ مشروع Lumen باسم “lumen_rest_ce” باستخدام حزمة “laravel/lumen”:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6570_13" style="">
<span class="pln">composer create</span><span class="pun">-</span><span class="pln">project laravel</span><span class="pun">/</span><span class="pln">lumen lumen_rest_ce</span></pre>

<p>
	سينشئ هذا الأمر مجلّدًا باسم “lumen_rest_ce” ويثبت جميع ملفّات إطار العمل Lumen إضافة إلى جميع الاعتماديات المتعلّقة به. أداة Artisan موجودة في Lumen كما هو الحال في Laravel، ولكنّها تدعم عددًا أقلّ من الأوامر، ويمكنك الاطلاع على قائمة الأوامر بكتابة الأمر التالي في سطر الأوامر:
</p>

<pre class="ipsCode" id="ips_uid_6570_15">
php artisan</pre>

<p>
	لاحظ أنّ الأمر serve والمسؤول عن تشغيل التطبيق على الخادوم غير متوفّر في Lumen لذا سنستعين بخادوم التطوير الخاصّ بلغة PHP لتشغيل Lumen وكما يلي:
</p>

<pre class="ipsCode" id="ips_uid_6570_17">
php -S localhost:8000 -t public</pre>

<p>
	افتح المتصفّح الآن وتوجّه إلى العنوان localhost:8000. إن ظهر لك رقم الإصدار الخاص بـ Lumen فهذا يعني أنّ عملية التثبيت قد تمّت بنجاح.
</p>

<h2 id="الإعدادات">
	الإعدادات
</h2>

<p>
	أنشئ قاعدة بيانات mysql باستخدام phpmyadmin أو أي عميل Mysql آخر، ثمّ عدّل ملف إعدادات Lumen في مجلد المشروع والذي يحمل الاسم <code>“lumen_rest_ce/.env”</code> بالصورة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6570_19" style="">
<span class="pln">DB_CONNECTION</span><span class="pun">=</span><span class="pln">mysql
DB_HOST</span><span class="pun">=</span><span class="pln">localhost
DB_DATABASE</span><span class="pun">=</span><span class="pln">lumen_rest_ce
DB_USERNAME</span><span class="pun">=</span><span class="pln">root
DB_PASSWORD</span><span class="pun">=</span><span class="pln">your_password</span></pre>

<p>
	افتح الملف <code>lumen_rest_ce/bootstrap/app.php</code> وأزل علامات التعليق من السطرين التاليين:
</p>

<pre class="ipsCode" id="ips_uid_6570_21">
$app-&gt;withFacades();

$app-&gt;withEloquent();</pre>

<p>
	إزالة التعليق عن هذين السطرين يسمح لنا باستخدام فئة Facade و Eloquent ORM في مشروعنا.
</p>

<h2 id="التهجير-migration">
	التهجير Migration
</h2>

<p>
	سنكتب الآن مخطّط قاعدة البيانات ونهيّئه لعملية التهجير، حيث سننشئ جدولًا باسم <code>book</code> يتضمّن ستة أعمدة. المعرّف id (قيمته رقمية int وتتزايد تلقائيًا)، العنوان title (من نوع varchar) الكاتب author (من نوع varchar)، الرقم المعياري الدولي للكتاب isbn (من نوع varchar) وحقلي تاريخ الإنشاء وتاريخ التعديل. سنستخدم عملية التهجير والتي هي بمثابة نظام إدارة نسخ خاصّ بقواعد البيانات.
</p>

<p>
	اكتب الأمر التالي في سطر الأوامر:
</p>

<pre class="ipsCode" id="ips_uid_6570_23">
php artisan make:migration create_books_table --create=books</pre>

<p>
	سينشئ هذا الأمر ملف تهجير في المجلد <code>dbaatase/migration</code>. يتضمّن هذا الملف صنفًا يحمل الاسم <code>CreateBooksTable</code> والذي يضمّ بدوره تابعين الأول هو <code>up</code> حيث سنكتب مخطّط البيانات، أما الآخر فهو <code>down</code> وهو التابع المسؤول عن حذف الجدول.
</p>

<p>
	عدّل الملف ليصبح بالصورة التالية:
</p>

<pre class="ipsCode" id="ips_uid_6570_25">
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateBooksTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('books', function(Blueprint $table)
        {
            $table-&gt;increments('id');
            $table-&gt;string('title');
            $table-&gt;string('author');
            $table-&gt;string('isbn');
            $table-&gt;timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('books');
    }

}</pre>

<p>
	لإنشاء الجدول في قاعدة البيانات سنحتاج إلى تهجير أو تنفيذ ملف التهجير الذي أنشأناه قبل قليل وذلك بواسطة الأمر التالي:
</p>

<pre class="ipsCode" id="ips_uid_6570_27">
php artisan migrate</pre>

<h2 id="النموذج-model">
	النموذج Model
</h2>

<p>
	أنشئ الآن نموذج Book ضمن الملف <code>app/Book.php</code> وأضف إليه الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6570_29" style="">
<span class="pun">&lt;?</span><span class="pln">php </span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Database\Eloquent\Model</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Book</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Model</span><span class="pln">
</span><span class="pun">{</span><span class="pln">

     </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'title'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'author'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'isbn'</span><span class="pun">];</span><span class="pln">

</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	أنشئ كذلك ملفّ المتحكّم <code>BookController.php</code> في المجلد <code>app/Http/Controllers</code> وأضف إليه الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6570_31" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Book</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\Controller</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BookController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pun">{</span><span class="pln">

 </span><span class="pun">.....</span><span class="pln">
 </span><span class="pun">.....</span><span class="pln">

</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<h2 id="التوجيه-routing">
	التوجيه Routing
</h2>

<p>
	افتح الملف <code>web.php</code> في المجلد <code>routes</code> وستجد أنّه يتضمن مسارًا معرّفًا مسبقًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6570_33" style="">
<span class="pln">$app</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">use</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$app</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></pre>

<p>
	لغرض كتابة واجهة برمجية بنمط RESTful سنحتاج إلى كتابة المزيد من المسارات وتوابع المتحكّمات المرتبطة بها، وحسب الجدول التالي:
</p>

<center>
	<table border="1"><tbody>
<tr>
<td style="background-color: rgb(251,141,108); color: rgb(255,255,255); padding: 5px 10px; text-align: center;">
					التابع
				</td>
				<td style="background-color: rgb(251,141,108); color: rgb(255,255,255); padding: 5px 10px; text-align: center;">
					عنوان Url
				</td>
				<td style="background-color: rgb(251,141,108); color: rgb(255,255,255); padding: 5px 10px; text-align: center;">
					Controller@method
				</td>
				<td style="background-color: rgb(251,141,108); color: rgb(255,255,255); padding: 5px 10px; text-align: center;">
					 
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: left;">
					GET
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					BookController@index
				</td>
				<td style="padding: 5px 10px;">
					جميع الكتب
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: left;">
					GET
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					{<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book/{id
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					BookController@getbook
				</td>
				<td style="padding: 5px 10px;">
					إحضار الكتاب حسب المعرّف id
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: left;">
					POST
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					BookController@createBook
				</td>
				<td style="padding: 5px 10px;">
					إنشاء سجل جديد في الجدول
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: left;">
					PUT
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					{<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book/{id
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					BookController@updateBook
				</td>
				<td style="padding: 5px 10px;">
					تحديث الكتاب حسب المعرّف id
				</td>
			</tr>
<tr>
<td style="padding: 5px 10px; text-align: left;">
					DELETE
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					{<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book/{id
				</td>
				<td style="padding: 5px 10px; text-align: left;">
					BookController@deleteBook
				</td>
				<td style="padding: 5px 10px;">
					حذف الكتاب حسب المعرّف id
				</td>
			</tr>
</tbody></table>
</center>

<p>
	لاحظ أنّنا أضفنا <code>v1</code> إلى جميع المسارات ونقصد به الإصدار الأول، وهذا من الممارسات التي ينصح باتباعها عند إنشاء خدمات الويب.
</p>

<p>
	حسب الجدول السابق فإن ملف web.php سيبدو كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6570_35" style="">
<span class="pln">$app</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">use</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$app</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="str">'Lumen RESTful <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> By Hsoub Academy  (&lt;a class="vglnk" href="https://academy.hsoub.com" rel="nofollow"&gt;&lt;span&gt;https&lt;/span&gt;&lt;span&gt;://&lt;/span&gt;&lt;span&gt;academy.hsoub&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;com&lt;/span&gt;&lt;/a&gt;)'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span><span class="pln">


$app</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book'</span><span class="pun">,</span><span class="str">'App\Http\Controllers\BookController@index'</span><span class="pun">);</span><span class="pln">

$app</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book/{id}'</span><span class="pun">,</span><span class="str">'App\Http\Controllers\BookController@getbook'</span><span class="pun">);</span><span class="pln">

$app</span><span class="pun">-&gt;</span><span class="pln">post</span><span class="pun">(</span><span class="str">'<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book'</span><span class="pun">,</span><span class="str">'App\Http\Controllers\BookController@createBook'</span><span class="pun">);</span><span class="pln">

$app</span><span class="pun">-&gt;</span><span class="pln">put</span><span class="pun">(</span><span class="str">'<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book/{id}'</span><span class="pun">,</span><span class="str">'App\Http\Controllers\BookController@updateBook'</span><span class="pun">);</span><span class="pln">

$app</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">(</span><span class="str">'<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book/{id}'</span><span class="pun">,</span><span class="str">'App\Http\Controllers\BookController@deleteBook'</span><span class="pun">);</span></pre>

<p>
	يمكننا كذلك تجميع المسارات حسب لاحقة معيّنة أو حسب نطاقات الأسماء، وبهذا لن نكون بحاجة إلى إضافة <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/vi</code> ولا إلى كتابة <code>App\Http\Controllers</code> في جميع المسارات.
</p>

<p>
	عدّل الشيفرة السابقة لتصبح بالصورة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6570_37" style="">
<span class="pln">$app</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">use</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$app</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="str">'Lumen RESTful <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> By Hsoub Academy  (&lt;a class="vglnk" href="https://academy.hsoub.com" rel="nofollow"&gt;&lt;span&gt;https&lt;/span&gt;&lt;span&gt;://&lt;/span&gt;&lt;span&gt;academy.hsoub&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;com&lt;/span&gt;&lt;/a&gt;)'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span><span class="pln">

$app</span><span class="pun">-&gt;</span><span class="kwd">group</span><span class="pun">([</span><span class="str">'prefix'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1'</span><span class="pun">,</span><span class="str">'namespace'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'App\Http\Controllers'</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$app</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $app</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'book'</span><span class="pun">,</span><span class="str">'BookController@index'</span><span class="pun">);</span><span class="pln">

    $app</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'book/{id}'</span><span class="pun">,</span><span class="str">'BookController@getbook'</span><span class="pun">);</span><span class="pln">

    $app</span><span class="pun">-&gt;</span><span class="pln">post</span><span class="pun">(</span><span class="str">'book'</span><span class="pun">,</span><span class="str">'BookController@createBook'</span><span class="pun">);</span><span class="pln">

    $app</span><span class="pun">-&gt;</span><span class="pln">put</span><span class="pun">(</span><span class="str">'book/{id}'</span><span class="pun">,</span><span class="str">'BookController@updateBook'</span><span class="pun">);</span><span class="pln">

    $app</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">(</span><span class="str">'book/{id}'</span><span class="pun">,</span><span class="str">'BookController@deleteBook'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">});</span></pre>

<h2 id="المتحكم">
	المتحكّم
</h2>

<p>
	والآن عدّل الملف BookController.php وأضف إليه التوابع التي عرّفناها في ملف web.php السابق:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6570_39" style="">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Book</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\Http\Controllers\Controller</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Http\Request</span><span class="pun">;</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BookController</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Controller</span><span class="pun">{</span><span class="pln">


    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> index</span><span class="pun">(){</span><span class="pln">

        $Books  </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Book</span><span class="pun">::</span><span class="pln">all</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$Books</span><span class="pun">);</span><span class="pln">

    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> getBook</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">){</span><span class="pln">

        $Book  </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Book</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$Book</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> createBook</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">){</span><span class="pln">

        $Book </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Book</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="pln">$request</span><span class="pun">-&gt;</span><span class="pln">all</span><span class="pun">());</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$Book</span><span class="pun">);</span><span class="pln">

    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> deleteBook</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">){</span><span class="pln">
        $Book  </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Book</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
        $Book</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="str">'deleted'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> updateBook</span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">,</span><span class="pln">$id</span><span class="pun">){</span><span class="pln">
        $Book  </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Book</span><span class="pun">::</span><span class="pln">find</span><span class="pun">(</span><span class="pln">$id</span><span class="pun">);</span><span class="pln">
        $Book</span><span class="pun">-&gt;</span><span class="pln">title </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'title'</span><span class="pun">);</span><span class="pln">
        $Book</span><span class="pun">-&gt;</span><span class="pln">author </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'author'</span><span class="pun">);</span><span class="pln">
        $Book</span><span class="pun">-&gt;</span><span class="pln">isbn </span><span class="pun">=</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">input</span><span class="pun">(</span><span class="str">'isbn'</span><span class="pun">);</span><span class="pln">
        $Book</span><span class="pun">-&gt;</span><span class="pln">save</span><span class="pun">();</span><span class="pln">

        </span><span class="kwd">return</span><span class="pln"> response</span><span class="pun">()-&gt;</span><span class="pln">json</span><span class="pun">(</span><span class="pln">$Book</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span></pre>

<h2 id="اختبار-الواجهة-البرمجية">
	اختبار الواجهة البرمجية
</h2>

<p>
	أصبحت الواجهة البرمجية جاهزة الآن للاختبار، وسنستخدم الأداة CURL لإجراء الاختبار:
</p>

<pre class="ipsCode" id="ips_uid_6570_41">
curl -I &lt;a class="vglnk" href="http://localhost:8000/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book" rel="nofollow"&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;://&lt;/span&gt;&lt;span&gt;localhost&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;8000&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;book&lt;/span&gt;&lt;/a&gt;

curl -v -H "Accept:application/json" &lt;a class="vglnk" href="http://localhost:8000/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book/2" rel="nofollow"&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;://&lt;/span&gt;&lt;span&gt;localhost&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;8000&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;book&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/a&gt;

curl -i -X POST -H "Content-Type:application/json" &lt;a class="vglnk" href="http://localhost:8000/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book" rel="nofollow"&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;://&lt;/span&gt;&lt;span&gt;localhost&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;8000&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;book&lt;/span&gt;&lt;/a&gt; -d '{"title":"Test Title","author":"test author","isbn":"12345"}'

curl -v -H "Content-Type:application/json" -X PUT &lt;a class="vglnk" href="http://localhost:8000/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book" rel="nofollow"&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;://&lt;/span&gt;&lt;span&gt;localhost&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;8000&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;book&lt;/span&gt;&lt;/a&gt; -d '{"title":"Test updated title","author":"test upadted author","isbn":"1234567"}'

curl -i -X DELETE &lt;a class="vglnk" href="http://localhost:8000/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/v1/book/2" rel="nofollow"&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;://&lt;/span&gt;&lt;span&gt;localhost&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;8000&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;book&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/a&gt;</pre>

<p>
	تتيح الإضافة <a href="https://www.getpostman.com/" rel="external nofollow">Postman</a> إجراء الاختبارات على الواجهات البرمجية بنمط RESTful وبسهولة. بعد تثبيت هذه الإضافة توجّه في متصفح Chrome إلى العنوان <code>chrome://apps/</code> لعرض الإضافات المثبّتة وتشغيل POSTMAN.
</p>

<h2 id="ختاما">
	ختامًا
</h2>

<p>
	ها قد أصبحت الواجهة البرمجية البسيطة التي أنشأناها جاهزة، ولكن لا زال ينقصها الكثير من الخصائص كالاستثياق والتحقّق من البيانات ومعالجة الأخطاء وغير ذلك الكثير.
</p>

<p>
	ترجمة - وبتصرّف - للمقال <a href="https://coderexample.com/restful-api-in-lumen-a-laravel-micro-framework/" rel="external nofollow">RESTful <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> in Lumen, A Laravel Micro Framework</a> لصاحبه Arkaprava Majumder.
</p>
]]></description><guid isPermaLink="false">571</guid><pubDate>Sun, 10 Dec 2017 15:04:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x628;&#x627;&#x62F;&#x626; &#x627;&#x644;&#x623;&#x633;&#x627;&#x633;&#x64A;&#x651;&#x629; &#x644;&#x625;&#x637;&#x627;&#x631; &#x627;&#x644;&#x639;&#x645;&#x644; Eloquent ORM</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D9%85%D8%A8%D8%A7%D8%AF%D8%A6-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D9%91%D8%A9-%D9%84%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-eloquent-orm-r410/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_03/laravel3.png.2db6873d2429789de6450df89e54add0.png" /></p>

<p>
	يحدُث كثيراً أن ينقسم مجتمع المطوّرين حول تقنيّات يراها بعضهم غير ذات جدوى أو على الأقل ليست بالأهميّة التي يروّج لها مؤيّدوها. تنطبق هذه الملاحظة على أطر العمل التي تعمل على ربط العلاقات بالكائنات <a href="https://academy.hsoub.com/tags/orm/" rel="">Object relational mapping</a> (أو ORM اختصارا)، ومن بينها Eloquent الذي يُستخدَم مبدئيًّا في <a href="https://academy.hsoub.com/programming/php/laravel/" rel="">Laravel</a>؛ دون أن يعني ذلك عدم إمكانيّة استخدامه خارج Laravel كما سنرى في هذه السّلسلة.<br>
	ليست أطر عمل ORM بالتقنيّة الجديدة، فهي توجد منذ سنين وأصبحت جزءًا من عمليّة التطوير بالنسبة للكثير من المبرمجين؛ كما أنها حسّنت من أدائها وتغلّبت على الكثير من النواقص مع الزمن. يتناول هذا الدّرس، الأوّل من سلسلة دروس عن الإطار Eloquent ORM، الأسباب التي أدّت إلى ظهور أطر عمل ORM والهدف من ورائها.
</p>

<p style="text-align: center;">
	<img alt="laravel3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="22205" data-unique="7nwqcrxc3" src="https://academy.hsoub.com/uploads/monthly_2017_03/laravel3.png.2aee6a1a787847a239ce09bdd2fbf830.png"></p>

<h1 id="التصور-البرمجي-programming-paradigm-وإدارة-البيانات-العلاقية">
	التصوّر البرمجي Programming paradigm وإدارة البيانات العلاقيّة
</h1>

<p>
	تُكتَب أغلب تطبيقات PHP الحديثة بأسلوب ذي تصوّر Paradigm كائنيّ التوجّه Object oriented، بينما تستخدم قواعدَ بيانات علاقيّة لإدارة البيانات وتخزينها. دور أُطُر عمل ORM هو تسهيل الانتقال بين هذيْن العالميْن أثناء تشغيل التطبيق.
</p>

<h2 id="البرمجة-كائنية-التوجه">
	البرمجة كائنية التوجّه
</h2>

<p>
	تعتمد لغات البرمجة على أفكار ونُظُم تحدّد طريقة عملها وأساليب كتابة البرامج التي تعمل بها. تُسمّى هذه الأساليب والقواعد بالتصورات البرمجيّة. يمكن للغةِ برمجة أن تُصنَّف في أكثر من تصوّر؛ إلّا أن كل لغة تركّز غالبًا على بضعة تصوّرات، ممّا يجعل كتابة برامج وفقَ هذه التصوّر ات أسهل بالنسبة لمبرمجي اللغة.
</p>

<p>
	تدعم لغة PHP البرمجيّة ميزات من تصوّرات برمجيّة عدّة؛ إلا أنها تُركّز على تصوّريْن:
</p>

<ul>
<li>
		التصوّر الإجرائي Procedural الذي يمكن عدّه التصوّر الأساسي للغة منذ بداياتها.
	</li>
	<li>
		التصوّر كائنيّ التوجه Object oriented الذي اعتمده مصمّمو لغة البرمجة - فعليًّا - في الإصدار الخامس (سنة 2004).
	</li>
</ul>
<p>
	يُؤسَّس التصوّر الإجرائي على التصريح بكيفيّة إجراء العمليّات، خطوة بخطوة، واستخدام <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-loops-%D9%81%D9%8A-php-r278/" rel="">الحلقات Loops</a>، <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AC%D9%85%D9%84-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-%D9%81%D9%8A-php-r238/" rel="">العبارات الشرطيّة</a> Conditions وتجميع الأوامر في <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-functions-%D9%81%D9%8A-php-r295/" rel="">سياقات محليّة</a> Local context أو ضمن <a href="https://academy.hsoub.com/programming/php/%D8%AA%D9%88%D8%B2%D9%8A%D8%B9-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-php-%D8%B9%D9%84%D9%89-%D8%B9%D8%AF%D8%A9-%D9%85%D9%84%D9%81%D8%A7%D8%AA-r332/" rel="">وحدات Modules</a> يمكن استدعاءها عند الحاجة. أما <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%83%D8%A7%D8%A6%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%87-object-oriented-programming-%D9%81%D9%8A-php-r316/" rel="">التصوّر كائنيّ التوجه</a> فيقوم على جمع البيانات والإجراءات (الدوالّ) ضمن كائن Object واحد يمكنه تطبيق الإجراءات المضمَّنة فيه على البيانات التي تخصّه.
</p>

<h2 id="أنظمة-قواعد-بيانات-العلاقية">
	أنظمة قواعد بيانات العلاقيّة
</h2>

<p>
	يعتمد النموذج العلاقي على نظريّة المجموعات Set theory والمنطق الرياضي من أجل تجميع البيانات ضمن جداول Tables؛ هي في الواقع علاقات Relations وفق التعريف الرياضي، ومنه التسميّة.
</p>

<p>
	يهدف النموذج العلاقي إلى تقديم طريقة تمكّن المستخدمين من تحديد البيانات المُعدّة للتخزين في قاعدة البيانات وتلك التي يريدون الحصول عليها من القاعدة، دون الاهتمام بالكيفيّة التي يستخدمها نظام الإدارة للإجابة على هذه الطلبات. يسمّى التصوّر البرمجي الذي يهتمّ بماهيّة المهمّة دون التركيز كثيرًا على كيفيّة أدائها بالتصوّر التقريري Declarative paradigm.
</p>

<p>
	يمكن عدّ لغة الاستعلام <a href="https://academy.hsoub.com/tags/sql/" rel="">SQL</a> تطبيقًا عمليًّا للنموذج العلاقي، وإن كانت تنحرف أحيانًا عن هذا النموذج.
</p>

<h1 id="ربط-العلاقات-بالكائنات-object-relational-mapping">
	ربط العلاقات بالكائنات Object relational mapping
</h1>

<p>
	تنبني شفرة التطبيقات التي تعتمد على تصوّر كائنيّ التوجه على أسس نظريّة تختلف عن تلك التي تُبنى عليها قواعد البيانات (النموذج العلاقي)؛ وهو ما يعني أنه على المطورين إيجاد طريقة للتخاطب مع قاعدة البيانات انطلاقًا من الشفرة البرمجيّة.
</p>

<p>
	يستخدم المبرمجون عادةً كائنًا مخصّصًا - يُسمّى كائن الوصول إلى البيانات Data access object، أو DAO اختصارا - لتخزين البيانات في القاعدة أو جلبها منها ثم تقديمها لبقيّة التطبيق بصيغة تناسبه. تُكتَب في هذا الصّنف استعلامات SQL المطلوب تنفيذها للتخاطب مع قاعدة البيانات، إما مباشرة أو عبر مكتبة وسيطة.
</p>

<p>
	يُساعد استخدام كائن DAO على الفصل بين أجزاء التطبيق واحترام مبادئ نمط التطوير <a href="https://academy.hsoub.com/programming/php/laravel/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-laravel-5-r218/#%D8%A8%D9%86%D9%8A%D8%A9-mvc" rel="">Model-Vue-Controller</a> (أو MVC اختصارا)؛ إلا أنّ كائنات DAO تتطلّب الكثير من الوقت، إذ يتحتّم على المطوِّر كتابة الكثير من التعليمات لتخزين البيانات في القاعدة أو جلبها منها. تأتي أطُر عمل ORM - ومن بينها Eloquent - للتخفيف من عبء هذه المهمّة.
</p>

<h2 id="إطار-العمل-eloquent-orm">
	إطار العمل Eloquent ORM
</h2>

<p>
	يسعى Laravel إلى أن يكون إطار عمل سهلَ الاستخدام يوفّر على المطوّرين الوقت ويرفع من إنتاجيّتهم؛ لذا جعل من Eloquent إطار عمل ORM الذي يستخدمه مبدئيًّا، لما يتميّز به من سهولة الاستخدام ووضوح آليّة العمل. طُوِّر Eloquent وفقا لنمط التسجيلة النشطة Active record الذي يقوم على وجود صنف Class لكلّ جدول في قاعدة البيانات، بحيث يُنشَأ كائن من هذا الصّنف لكل تسجيلة (سطر في الجدول). يعني هذا أن بيانات الكائن تحمل نسخة طبق الأصل من تسجيل الجدوَل.
</p>

<p>
	يُسمِّى Eloquent الصّنفَ الذي يطابق الجدول بالنموذج Model. يحوي كلّ كائن من هذا الصنف خاصيّات Attributes بعدد وأسماء توافق حقول (أعمدة) الجدول؛ وتمكّن الدوالّ التي يوفّرها من القيام بعمليّات من قبيل <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%B1%D8%AC%D8%B9%D8%A7%D8%AA-accessors-%D9%88%D8%A7%D9%84%D9%85%D8%B9%D8%AF%D9%84%D8%A7%D8%AA-mutators-%D9%81%D9%8A-laravel-r365/" rel="">إدراج التسجيلة، التعديل عليها أو حذفها</a>. إذا كان لدينا - مثلا - جدول في قاعدة البيانات باسم <code>Address</code> نحتفظ فيه بعناوين أشخاص، فإن إدراج عنوان جديد في قاعدة البيانات سيكافئ إنشاء كائن من الصنف (النموذج) <code>Address</code> وملئه بالبيانات التي نريد ثم استدعاء دالة التخزين في هذا الكائن. يضيف Eloquent وظائف مساعدة مثل التحقّق من أن الكائنات تحترم قواعد معيّنة قبل تخزينها في الجدول؛ وهو ما يعني التقليل من الأخطاء على مستوى قاعدة البيانات.
</p>

<p>
	قد تجد نفسك أمام حالات معقّدة لا تؤدّي فيها هذه الطريقة (تطبيق الدوالّ على الصنف المماثل لجدول قاعدة البيانات) النتيجة المطلوبة؛ يمكنك في هذه الحالة استخدام <a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D8%B4%D8%A6-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-query-builder-%D9%84%D9%84%D8%AA%D8%AE%D8%A7%D8%B7%D8%A8-%D9%85%D8%B9-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-laravel-r398/" rel="">منشئ الاستعلامات Query builder</a> وكتابة استعلامات SQL مباشرة. يُنصَح بتجنّب Eloquent عند تنفيذ سلسلة طويلة من المهامّ تلقائيًّا، دون تدخّل يدوي. يُناسب Eloquent المعاملات Transactions، وهي مجموعة إجراءات تُنفَّذ في قاعدة البيانات على أنّها وِحدة لا تتجزّأ: إما أن تُطبَّق جميع الإجراءات الموجودة في المعاملة أو لا تُطبَّق أي منها.
</p>
]]></description><guid isPermaLink="false">410</guid><pubDate>Tue, 25 Apr 2017 10:16:17 +0000</pubDate></item><item><title>&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; Passport &#x644;&#x625;&#x639;&#x62F;&#x627;&#x62F; &#x62E;&#x627;&#x62F;&#x648;&#x645; Oauth &#x639;&#x644;&#x649; Laravel</title><link>https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-passport-%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%AE%D8%A7%D8%AF%D9%88%D9%85-oauth-%D8%B9%D9%84%D9%89-laravel-r394/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2017_04/laravel.png.429a421502916d61c143db48760747ca.png" /></p>

<p>
	لطالما وفّر إطار العمل Laravel <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D8%B3%D8%AA%D9%8A%D8%AB%D8%A7%D9%82-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D9%8A%D9%86-user-authentication-%D9%81%D9%8A-laravel-5-r229/" rel="">آليات سهلة للاستيثاق</a> Authentication بالطرق التقليدية مثل استمارات Forms تسجيل الدخول في واجهة الوِب؛ إلا أن الأمر لم يكن سهلا بما فيه الكفاية بالنسبة للاستيثاق من الطلبات القادمة عبر واجهة تطبيقات برمجية. يأتي الإصدار 5.3 بحزمة جديدة، تُسمّى Passport، تهتم بتيسير استخدام Laravel لضبط خادوم Oauth وإعداده. يتناول هذا الدرس كيفية إعداد Laravel ليوفّر وظيفة خادوم Oauth اعتمادا على حزمة Passport.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="22376" data-unique="fuw4q99rb" src="https://academy.hsoub.com/uploads/monthly_2017_04/laravel.png.69621664c2bfb1c994e88a842ab5ee12.png" alt="laravel.png"></p>

<h2 id="خادوم-oauth">
	خادوم Oauth
</h2>

<p>
	من المحتمل جدّا أنه سبق لك التعامل مع خادوم Oauth؛ مثلا عند استخدام حسابات على الشبكات الاجتماعية (فيس بوك، تويتر، … إلخ) للتسجيل في موقع على الشبكة. الفكرة التي تنبني عليها آلية الاستيثاق هذه هي تفويض عمليّة الاستيثاق إلى خادوم Oauth. نفترض مثلا أن لديك موقعا يستخدم هذه الآلية؛ عند تسجيل دخول الموقع عن طريق الحساب على فيس بوك فإن ما يحدُث هو التالي:
</p>

<ul>
<li>
		يلج المستخدم إلى الموقع ويختار طريقة تسجيل الدخول (فيس بوك).
	</li>
	<li>
		يُنقَل المستخدم إلى صفحة تسجيل الدخول في فيس بوك حيثُ يُطلَب منه تسجيل الدخول إن لم يكن سبق له ذلك ثم يؤكّد سماحه لموقعك باستخدام حسابه على فيس بوك.
	</li>
	<li>
		يُعاد توجيه المستخدم إلى الموقع مع تسجيل دخوله إليه.
	</li>
</ul>
<p>
	يفترض هذا الدرس أن لديك إلماما بكيفية عمل خواديم Oauth للتصريح بالدخول. يمكن الاطّلاع على مقال <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-oauth-2-r72/" rel="">مدخل إلى OAuth 2</a> للمزيد عن هذا الموضوع. إن كنتَ تبحث عن كيفية تسجيل الدخول إلى تطبيقك باستخدام حساب على موقع يوفّر وظيفة Oauth فراجع درس <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-%D8%A7%D9%84%D8%AF%D8%AE%D9%88%D9%84-%D8%B9%D8%A8%D8%B1-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%AC%D8%AA%D9%85%D8%A7%D8%B9%D9%8A%D8%A9-%D9%81%D9%8A-laravel-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-socialite-r275/" rel=""> تسجيل الدخول عبر الشبكات الاجتماعية في Laravel باستخدام Socialite</a>.
</p>

<h2 id="إعداد-خادوم-oauth-على-laravel-53">
	إعداد خادوم Oauth على Laravel 5.3
</h2>

<p>
	يحتاج إعداد Passport على Laravel لتنفيذ بضعة أوامر وتحرير ملفات إعداد؛ إلا أن العملية عموما سهلة. ابدأ بتثبيت الإصدار 5.3 من Laravel:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_7">
<span class="pln">composer create</span><span class="pun">-</span><span class="pln">project </span><span class="pun">--</span><span class="pln">prefer</span><span class="pun">-</span><span class="pln">dist laravel</span><span class="pun">/</span><span class="pln">laravel laravel53oauth </span><span class="str">"5.3.*"</span></pre>

<p>
	نستخدم <code>composer</code> لإضافة حزمة Passport إلى متطلبات المشروع:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_9">
<span class="pln">composer </span><span class="kwd">require</span><span class="pln"> laravel</span><span class="pun">/</span><span class="pln">passport</span></pre>

<p>
	نسجّل <a href="https://academy.hsoub.com/programming/php/laravel/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%85%D8%B2%D9%88%D8%AF-%D8%AE%D8%AF%D9%85%D8%A9-service-provider-%D9%81%D9%8A-laravel-r326/" rel="">مزوّد الخدمة</a> <code>Passport</code> في ملفّ الإعداد <code>config/app.php</code>. افتح الملف ثم أضف السطر التالي إلى مصفوفة <code>providers</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_11">
<span class="typ">Laravel</span><span class="pln">\Passport\PassportServiceProvider</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">,</span></pre>

<p>
	تأكّد من <a href="https://academy.hsoub.com/programming/php/laravel/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-laravel-5-%D9%88%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D9%87-%D8%B9%D9%84%D9%89-windows-%D9%88ubuntu-r212/#%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA" rel="">إعدادات قاعدة البيانات</a> ثمّ نفّذ أمر التهجير Migration التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_13">
<span class="pln">php artisan migrate</span></pre>

<p>
	ستلاحظ تنفيذ تهجيرات إضافية علاوة على تلك التي تأتي مبدئيّا مع Laravel:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_15">
<span class="typ">Migration</span><span class="pln"> table created successfully</span><span class="pun">.</span><span class="pln">
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2014</span><span class="pln">_10_12_000000_create_users_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2014</span><span class="pln">_10_12_100000_create_password_resets_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">_06_01_000001_create_oauth_auth_codes_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">_06_01_000002_create_oauth_access_tokens_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">_06_01_000003_create_oauth_refresh_tokens_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">_06_01_000004_create_oauth_clients_table
</span><span class="typ">Migrated</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2016</span><span class="pln">_06_01_000005_create_oauth_personal_access_clients_table</span></pre>

<p>
	يأتي مزوّد الخدمة <code>Passport</code> مع تهجيرات لإنشاء جداول تخزّن عملاء Client التطبيق ومعلومات رموز الوصول Access tokens. ثم ننفّذ الأمر التالي الذي سيولّد مفاتيح <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7%D9%84%D9%81%D8%B1%D9%82-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%AA%D8%B1%D9%85%D9%8A%D8%B2-encoding%D8%8C-%D8%A7%D9%84%D8%AA%D8%B9%D9%85%D9%8A%D8%A9-encryption%D8%8C-%D8%A7%D9%84%D8%AA%D8%AC%D8%B2%D8%A6%D8%A9-hashing-%D9%88%D8%A7%D9%84%D8%AA%D8%B4%D9%88%D9%8A%D8%B4-obfuscation%D8%9F-r308/#%D8%A7%D9%84%D8%AA%D8%B9%D9%85%D9%8A%D8%A9" rel="">التعميّة</a> Encryption keys الخاصّة بمشروع كما أنه ينشئ رموز الوصول ويخزّنها في جدول البيانات المناسب:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_17">
<span class="pln">php artisan passport</span><span class="pun">:</span><span class="pln">install</span></pre>

<p>
	ننتقل الآن إلى نموذج المستخدم <code>User</code> ونضيف إليه <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%AC%D8%B1%D9%8A%D8%AF-abstraction%C2%A0%D9%88%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-interfaces-%D9%88%D8%A7%D9%84%D8%B3%D9%85%D8%A7%D8%AA-traits-%D9%81%D9%8A-php-r317/" rel="">السّمة Trait</a> المسمّاة <code>HasApiTokens</code>. يُصبح النموذج على النحو التالي (بعد نزع التعليقات للاختصار):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_19">
<span class="pun">&lt;?</span><span class="pln">php

</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">App</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Notifications\Notifiable</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Illuminate</span><span class="pln">\Foundation\Auth\User </span><span class="kwd">as</span><span class="pln"> </span><span class="typ">Authenticatable</span><span class="pun">;</span><span class="pln">
</span><span class="com">// استيراد السّمة</span><span class="pln">
</span><span class="kwd">use</span><span class="pln"> </span><span class="typ">Laravel</span><span class="pln">\Passport\HasApiTokens</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">User</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Authenticatable</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// استخدام السمة</span><span class="pln">
    </span><span class="kwd">use</span><span class="pln"> </span><span class="typ">HasApiTokens</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Notifiable</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">protected</span><span class="pln"> $fillable </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'name'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'email'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'password'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">

    </span><span class="kwd">protected</span><span class="pln"> $hidden </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
        </span><span class="str">'password'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'remember_token'</span><span class="pun">,</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	توفّر هذه السّمة مجموعة من <a href="https://academy.hsoub.com/tags/%D8%AF%D9%88%D8%A7%D9%84%20%D9%85%D8%B3%D8%A7%D8%B9%D8%AF%D8%A9/" rel="">الدوال المساعدة</a> التي تتيح الحصول على رموز الوصول الخاصّة بالمستخدمين ومدى الصلاحيّات Permissions scope المتاح للعميل.
</p>

<p>
	الخطوة المواليّة هي استدعاء الدالة <code>Passport::routes</code> ضمن الدالة <code>boot</code> الموجودة في مزوّد خدمة الاستيثاق <code>app/Providers/AuthServiceProvider.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_21">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> boot</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $this</span><span class="pun">-&gt;</span><span class="pln">registerPolicies</span><span class="pun">();</span><span class="pln">

    </span><span class="typ">Passport</span><span class="pun">::</span><span class="pln">routes</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا تنس استدعاء الصنف <code>Laravel\Passport\Passport</code> في مزوّد خدمة الاستيثاق:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_23">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">Laravel</span><span class="pln">\Passport\Passport</span><span class="pun">;</span></pre>

<p>
	يمكنك ملاحظة المسارات الجديدة التي أضافتها الدالة <code>Passport::routes</code> بتنفيذ أمر Artisan التالي الذي يسرُد لائحة بالمسارات الموجودة في المشروع:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_25">
<span class="pln">php artisan route</span><span class="pun">:</span><span class="pln">list</span></pre>

<p>
	الخطوة الأخيرة هي تعديل ملف الإعداد <code>config/auth.php</code> وتحديد قيمة <code>driver</code> في المصفوفة <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr></code> لتصبح <code>passport</code> بدلا من <code>token</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_27">
<span class="str">'<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'driver'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'passport'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'provider'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'users'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">],</span></pre>

<p>
	يعتمد Laravel مبدئيا على رموز للاستيثاق من الطلبات القادمة عبر واجهة التطبيقات البرمجية؛ إلا أن هذه الرموز المبدئية لا تتيح إلا القليل من الخيارات، عكس ما يوفّره Passport.
</p>

<p>
	بهذا نكون أنهينا إعداد Laravel لأداء وظيفة خادوم Oauth.
</p>

<h2 id="اختبار-خادوم-oauth">
	اختبار خادوم Oauth
</h2>

<p>
	المرحلة المواليّة بعد إعداد Laravel ليعمل خادوم Oauth هي اختبار ما أعددناه. سنحتاج لعميل نجرّب عن طريقه الاستيثاق من الخادوم. نعيد النظر، قبل الانتقال للجانب التطبيقي من الاختبار، في كيفية الاستيثاق من مستخدم في خادوم Oauth.
</p>

<p>
	تضمّ العمليّة ثلاثة أطراف: المستخدِم، الخادوم والعميل. يريد المستخدِم تسجيل الدخول إلى العميل بالاعتماد على معلوماته الموجودة في الخادوم:
</p>

<ul>
<li>
		ينقُل العميل المستخدِم إلى صفحة تسجيل الدخول على الخادوم.
	</li>
	<li>
		يُسجّل المستخدم الدخول إلى حسابه على الخادوم عن طريق بريده الإلكتروني وكلمة السّر.
	</li>
	<li>
		يتحقّق الخادوم من بيانات المستخدِم، ثم ينشئ - إذا كانت البيانات صحيحة - رمز وصول خاصًّا بالمستخدِم ويعيده إلى العميل.
	</li>
	<li>
		يستعمل العميل رمز الوصول الذي أرسله إليه الخادوم في طلباته المقبلة للتدليل على أن المستخدم فوّضه التعامل باسمه مع الخادوم.
	</li>
</ul>
<h3 id="إنشاء-مستخدمين-للاختبار">
	إنشاء مستخدمين للاختبار
</h3>

<p>
	نبدأ بإنشاء مستخدمين لتجربة الاستيثاق. ننفذ أمر Artisan التالي لإنشاء صنف <a href="https://academy.hsoub.com/tags/%D8%A8%D8%B0%D8%B1/" rel="">بذر Seed</a> جديد:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_29">
<span class="pln">php artisan make</span><span class="pun">:</span><span class="pln">seeder </span><span class="typ">UsersTableSeeder</span></pre>

<p>
	ثم نعدّل الدالة <code>run</code> لإنشاء مستخدمَيْن جديديْن:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_31">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">

    $user1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Med Ahmed Eyil'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'email'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'medeyil@laravel.com'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'password'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Hash</span><span class="pun">::</span><span class="pln">make</span><span class="pun">(</span><span class="str">'1234'</span><span class="pun">),</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
    $user2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'Fatima Benziane'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'email'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'fbenziane@laravel.com'</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'password'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">Hash</span><span class="pun">::</span><span class="pln">make</span><span class="pun">(</span><span class="str">'4567'</span><span class="pun">),</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">

    </span><span class="typ">User</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="pln">$user1</span><span class="pun">);</span><span class="pln">
    </span><span class="typ">User</span><span class="pun">::</span><span class="pln">create</span><span class="pun">(</span><span class="pln">$user2</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لا تنس استيراد النموذج <code>User</code>:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_33">
<span class="kwd">use</span><span class="pln"> </span><span class="typ">App</span><span class="pln">\User</span><span class="pun">;</span></pre>

<p>
	ثم نعتمد صنف البذر بتعديل الدالة <code>run</code> في الصنف <code>DatabaseSeeder</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_35">
<span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> run</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $this</span><span class="pun">-&gt;</span><span class="pln">call</span><span class="pun">(</span><span class="typ">UsersTableSeeder</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ثم ننفذ أمر البذر:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_37">
<span class="pln">php artisan db</span><span class="pun">:</span><span class="pln">seed</span></pre>

<p>
	جهّزنا الآن طرفيْن من الأطراف الثلاثة التي تحدثنا عنها، بقي العميل.
</p>

<h3 id="إعداد-العميل">
	إعداد العميل
</h3>

<p>
	يوفّر Laravel بواسطة Passport مسارات من بينها المسار <code>oauth/token/</code> الذي يمكّن من الحصول على رمز وصول. ينتظر المسار المعطيَات التاليّة:
</p>

<ul>
<li>
		طريقة منح الصلاحيّة <code>grant_type</code>.
	</li>
	<li>
		معرّف المستخدم <code>client_id</code>.
	</li>
	<li>
		عبارة سر العميل <code>client_secret</code>.
	</li>
</ul>
<p>
	يحدّد المعطى <code>grant_type</code> طريقةَ توليد رموز الوصول. بما أننا نريد أن يطلُب الخادوم من المستخدم بريده الإلكتروني وكلمة السّر لكي يولّد رمز وصول للتطبيق العميل، فإن هذا المعطى سيأخذ القيمة <code>password</code>. يمكن لهذا المعطى أن يأخذ قيما أخرى حسب الطريقة التي تريد للتطبيقات العميلة أن تصل بها إلى موارد محميّة على خادومك. يعيّن المعطى الثاني معرّف العميل الذي نريد الاستيثاق منه؛ أما عبارة السّر فمهمتها إثبات أن العميل لديه ترخيص للاستيثاق بخادوم Oauth الذي أعددناه. سنحتاج أيضا لتمرير بريد المستخدم الإلكتروني وكلمة سره، بما أننا اخترنا طريقة <code>password</code> لتوليد الرموز.
</p>

<p>
	نعود لمشروع Laravel حيث يوجد الخادوم ثم ننفذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_39">
<span class="pln">php artisan passport</span><span class="pun">:</span><span class="pln">client </span><span class="pun">--</span><span class="pln">password
    </span><span class="typ">What</span><span class="pln"> should we name the password grant client</span><span class="pun">?</span><span class="pln"> </span><span class="pun">[</span><span class="typ">Laravel</span><span class="pln"> </span><span class="typ">Password</span><span class="pln"> </span><span class="typ">Grant</span><span class="pln"> </span><span class="typ">Client</span><span class="pun">]:</span><span class="pln">
    </span><span class="pun">&gt;</span><span class="pln"> </span><span class="typ">Academy</span><span class="pln"> </span><span class="typ">Password</span><span class="pln"> </span><span class="typ">Client</span><span class="pln">

    </span><span class="typ">Password</span><span class="pln"> grant client created successfully</span><span class="pun">.</span><span class="pln">
    </span><span class="typ">Client</span><span class="pln"> ID</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pln">
    </span><span class="typ">Client</span><span class="pln"> </span><span class="typ">Secret</span><span class="pun">:</span><span class="pln"> </span><span class="lit">17ZNjWn5A1I3mYOhGXZQFNACTdyt9Nwxup9jXG4M</span></pre>

<p>
	يطلُب الأمر أعلاه إنشاء تصريح لعميل للاستيثاق بخادوم Oauth ويحدّد طريقة توليد رموز الوصول بـ<code>password</code>. يطلُب الأمر اسمًا للعميل ثم بعد كتابته وتأكيده يمنحنا معرّفا للعميل وعبارة سرّ.
</p>

<p>
	<strong>ملحوظة:</strong> رمز الوصول المولَّد فريد Unique، القيمة التي ستظهر لديك مختلفة حتما عن القيمة الظاهرة هنا.
</p>

<p>
	نعرّج قليلا، قبل الانتقال إلى العميل، على قاعدة البيانات وننظر في الجدول <code>oauth_clients</code>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="20012" href="https://academy.hsoub.com/uploads/monthly_2016_12/01_oauth_clients.png.3159af07e7b96238adbc53b27c57f03f.png" rel=""><img alt="01_oauth_clients.png" class="ipsImage ipsImage_thumbnailed" data-fileid="20012" data-unique="bmzmettlk" src="https://academy.hsoub.com/uploads/monthly_2016_12/01_oauth_clients.thumb.png.4a49d7d420b952ad755ce0262fe51894.png"></a>
</p>

<p>
	لاحظ في الجدول وجود العميل الذي أنشأناه للتو، إضافة إلى عميليْن آخرين؛ أنشأهما الأمر <code>passport:install</code> عندما نفّذناه. تمكن ملاحظة أن قيمة العمود <code>password_client</code> بالنسبة للعميل الذي أنشأناه هي <code>1</code> للدلالة على أنه من نوع <code>password</code>.
</p>

<p>
	نأتي الآن للعميل، الذي يمكن أن يكون تطبيق وِب، تطبيقا للأجهزة المحمولة أو غيره. بالنسبة لي سأختار إضافة <a href="https://www.getpostman.com/" rel="external nofollow">Postman</a> على متصفح Chrome، وهي إضافة تمكّن من اختبار واجهات التطبيقات البرمجية.
</p>

<h3 id="إرسال-الطلبات">
	إرسال الطلبات
</h3>

<p>
	نشغّل خادوم Passport بتنفيذ الأمر:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_41">
<span class="pln">php artisan serve</span></pre>

<p>
	ثم نفتح واجهة Postman ونعطيه المسار <code>oauth/token/</code> ونمرّر له المعطيات التي تحدّثنا عنها سابقا. نحدّد نوع الإجراء بـ <code>POST</code>، ونختار تبويب <code>Body</code> لأننا في صدد ذكر بيانات جسم الطلب، ونختار <code>x-www-form-urlencode</code> للترميز. يؤدي استخدام <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7%D9%84%D9%81%D8%B1%D9%82-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%AA%D8%B1%D9%85%D9%8A%D8%B2-encoding%D8%8C-%D8%A7%D9%84%D8%AA%D8%B9%D9%85%D9%8A%D8%A9-encryption%D8%8C-%D8%A7%D9%84%D8%AA%D8%AC%D8%B2%D8%A6%D8%A9-hashing-%D9%88%D8%A7%D9%84%D8%AA%D8%B4%D9%88%D9%8A%D8%B4-obfuscation%D8%9F-r308/#%D8%A7%D9%84%D8%AA%D8%B1%D9%85%D9%8A%D8%B2" rel="">الترميز</a> <code>x-www-form-urlencode</code> إلى إرسال البيانات بنفس الطريقة التي تُرسَل بها بيانات استمارة Form على موقع وِب باستخدام الإجراء <code>POST</code>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="20013" href="https://academy.hsoub.com/uploads/monthly_2016_12/02_postman_get_token.png.fd4696c4f0aa83877e9907b82e041131.png" rel=""><img alt="02_postman_get_token.png" class="ipsImage ipsImage_thumbnailed" data-fileid="20013" data-unique="ipur95vmw" src="https://academy.hsoub.com/uploads/monthly_2016_12/02_postman_get_token.thumb.png.07858e5255e0955101617c5b2295f647.png"></a>
</p>

<p>
	إن كنتَ تُفضّل سطر الأوامر فبإمكانك تنفيذ أمر <code>curl</code> التالي والذي يؤدي نفس المهمّة (الخيار <code>d-</code> لاستخدام الترميز <code>x-www-form-urlencode</code>):
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_43">
<span class="pln">curl </span><span class="pun">-</span><span class="pln">d </span><span class="str">"grant_type=password&amp;client_id=3&amp;client_secret=17ZNjWn5A1I3mYOhGXZQFNACTdyt9Nwxup9jXG4M&amp;username=medeyil@laravel.com&amp;password=1234"</span><span class="pln"> http</span><span class="pun">:</span><span class="com">//localhost:8000/oauth/token</span></pre>

<p>
	نحصُل بعد ذكر المعطيات الصحيحة وتنفيذ الطلب على الرد التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_45">
<span class="pun">{</span><span class="pln">
</span><span class="str">"token_type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Bearer"</span><span class="pun">,</span><span class="pln">
</span><span class="str">"expires_in"</span><span class="pun">:</span><span class="pln"> </span><span class="lit">31536000</span><span class="pun">,</span><span class="pln">
</span><span class="str">"access_token"</span><span class="pun">:</span><span class="str">"رمز طويل هنا"</span><span class="pln"> </span><span class="pun">,</span><span class="pln">
</span><span class="str">"refresh_token"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"رمز طويل هنا"</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="20014" href="https://academy.hsoub.com/uploads/monthly_2016_12/03_postman_get_token.png.b6f382db046d04fe93441737b1a9f266.png" rel=""><img alt="03_postman_get_token.png" class="ipsImage ipsImage_thumbnailed" data-fileid="20014" data-unique="gofoxxzkd" src="https://academy.hsoub.com/uploads/monthly_2016_12/03_postman_get_token.thumb.png.8579b2f4fa7fdc8244ea99c6e91657f9.png"></a>
</p>

<p>
	تتضمن الإجابة أربعة حقول:
</p>

<ul>
<li>
		نوعية الرمز <code>token_type</code>. يعني النوع <code>bearer</code> أن بإمكان الرمز منح الوصول إلى الخادوم دون الحاجة لذكر معلومات إضافية (مثل مفاتيح التعمية).
	</li>
	<li>
		مدة صلاحيّة الرمز <code>expires_in</code>. يحدّد مدّة صلاحيّة الرمز، بالثواني. يحدّد Laravel مبدئيا مدة طويلة (حوالي سنة)؛ إلا أنه يمكن تغيير هذه المدة.
	</li>
	<li>
		رمز الوصول <code>access_token</code>.
	</li>
	<li>
		رمز التحديث <code>refresh_token</code>. يُستخدَم لطلب رمز وصول جديد عند انتهاء مدة صلاحية رمز الوصول الحالي.
	</li>
</ul>
<p>
	حصلنا على رمز الوصول؛ سنرى الآن كيفية استخدامه للوصول إلى موارد على الخادوم.
</p>

<p>
	يُرسِل العميل من الآن فصاعدا رمزَ الوصول الذي حصل عليه مع كل طلب موجّه للخادوم يحتاج للاستيثاق. إن نظرت في ملفّ مسارات واجهة التطبيقات البرمجية <code>routes/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>.php</code> فستجد أن المسار <code>user/</code> محميّ بـ <code>auth:<abbr title="Application Programming Interface | واجهة برمجية">api</abbr></code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_47">
<span class="typ">Route</span><span class="pun">::</span><span class="kwd">get</span><span class="pun">(</span><span class="str">'/user'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Request</span><span class="pln"> $request</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> $request</span><span class="pun">-&gt;</span><span class="pln">user</span><span class="pun">();</span><span class="pln">
</span><span class="pun">})-&gt;</span><span class="pln">middleware</span><span class="pun">(</span><span class="str">'auth:<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>'</span><span class="pun">);</span></pre>

<p>
	يعني هذا أنه يتوجّب على المستخدم تقديم بيانات الاستيثاق الخاصّة بواجهة التطبيقات، التي جعلناها تعتمد على التعريف <code>passport</code>، حتى يتمكن من الحصول على المورِد (الذي هو في المثال أعلاه بيانات المستخدم الذي أرسل الطلب).
</p>

<p>
	نعود لـPostman لطلب المسار <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/user/</code> مع تقديم رمز الوصول الذي حصلنا عليه سابقا.
</p>

<p>
	<strong>ملحوظة:</strong> تنبغي إضافة <code><abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/</code> إلى جميع <a href="https://academy.hsoub.com/programming/php/laravel/%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D9%8A%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%8A-%D8%B7%D8%B1%D8%A3%D8%AA-%D8%B9%D9%84%D9%89-%D9%87%D9%8A%D9%83%D9%84%D8%A9-%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-laravel-%D9%81%D9%8A-%D8%A7%D9%84%D8%A5%D8%B5%D8%AF%D8%A7%D8%B1-53-r388/#%D9%85%D9%84%D9%81-%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B1%D8%A7%D8%AA-routes" rel="">المسارات المعرّفة في الملف</a> <code>routes/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>.php</code>.
</p>

<p>
	نحدّد في خانة الترويسة Headers طبيعة المعلومات التي نريد تقديمها إلى المسار والإجراء <code>GET</code> المعرَّف في المسار <code>user/</code> الخاص بواجهة التطبيقات. الترويسة التي نريد تحديد قيمتها هي <code>Authorization</code> (طلب استيثاق) وقيمتها هي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_49">
<span class="typ">Bearer</span><span class="pln"> access_token</span></pre>

<p>
	حيث <code>access_token</code> رمز الوصول الذي حصلنا عليه في الخطوة السابقة، مسبوقا بنوع الرمز (<code>Bearer</code>). نحصُل على معلومات المستخدِم الذي قدّم الطلب.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="20015" href="https://academy.hsoub.com/uploads/monthly_2016_12/03_postman_use_token.png.737e4e29ea5cd5ffa1727c9cb19d5c10.png" rel=""><img alt="03_postman_use_token.png" class="ipsImage ipsImage_thumbnailed" data-fileid="20015" data-unique="qaqjayjk0" src="https://academy.hsoub.com/uploads/monthly_2016_12/03_postman_use_token.thumb.png.69dcb7c7d3e18c89b68f71939e9b06a7.png"></a>
</p>

<p>
	يمكن الحصول على نفس النتيجة بأمر <code>curl</code> التالي:
</p>

<pre>
 </pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8891_51">
<span class="pln">curl </span><span class="pun">-</span><span class="pln">H </span><span class="str">"Authorization: Bearer access_token"</span><span class="pln"> http</span><span class="pun">:</span><span class="com">//localhost:8000/<abbr title="Application Programming Interface | واجهة برمجية">api</abbr>/user</span></pre>

<p>
	يعني الخيار <code>H-</code> أننا نريد تضمين الترويسة التاليّة له في الطلب.
</p>

<p>
	نلاحظ أن الإجابات التي نحصُل عليها من خادوم Passport مهيّأة بصيغة JSON، وهو ما يجعل التعامل معها سهلا في التطبيقات العميلة على الأجهزة المحمولة والمتصفّحات.
</p>

<p>
	الخلاصة هي أننا استخدمنا بيانات المستخدم (البريد وكلمة السر) للحصول على رمز وصول من خادوم Passport ثم استخدمنا رمز الوصول هذا للاطلاع على موارد محميّة على الخادوم.
</p>
]]></description><guid isPermaLink="false">394</guid><pubDate>Mon, 03 Apr 2017 10:05:07 +0000</pubDate></item></channel></rss>
