<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: PHP</title><link>https://academy.hsoub.com/programming/php/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: PHP</description><language>ar</language><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x631;&#x628;&#x637; &#x642;&#x627;&#x639;&#x62F;&#x629; &#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; MariaDB &#x628;&#x62A;&#x637;&#x628;&#x64A;&#x642; &#x644;&#x627;&#x631;&#x627;&#x641;&#x64A;&#x644; Laravel</title><link>https://academy.hsoub.com/programming/php/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%B1%D8%A8%D8%B7-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mariadb-%D8%A8%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D9%84%D8%A7%D8%B1%D8%A7%D9%81%D9%8A%D9%84-laravel-r2580/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2025_05/10037213.-----MariaDB---Laravel.png.81a595faedfc4a100dd6498951274209.png" /></p>
<p>
	يوفّر MariaDB نظام إدارة قواعد بيانات مفتوح المصدر أداءً عاليًا وأمانًا متقدمًا ومرونة في الضبط، مما يجعله مثاليًا لتطبيقات الويب القوية خصوصًا عند دمجه مع إطار عمل لارافيل Laravel و PHP المستخدمان على نطاق واسع بين المطورين.
</p>

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

<h2 id="-mariadb">
	قاعدة بيانات MariaDB
</h2>

<p>
	هو نظام مفتوح المصدر لإدارة قواعد البيانات العلاقية، وهو فرع من <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>، حيث توفر ميزات متقدمة مثل تحسين الأداء والأمان والمرونة في الضبط.
</p>

<p>
	يستخدم <a href="https://wiki.hsoub.com/SQL" rel="external">لغة SQL</a> لإدارة البيانات مع توافق كامل مع MySQL المعروفة والشهيرة بين المطورين، ويتعامل بكفاءة مع العمليات الكبيرة، لذا تناسب مختلف المشاريع من الصغيرة إلى المؤسسية.
</p>

<h2 id="-mariadb">
	مزايا MariaDB
</h2>

<p>
	يدعم عدة أنواع من محركات التخزين مثل InnoDB و Spider و Aria، ويقدم كل منها مزايا مختلفة تغطي معظم المتطلبات ما يوفر مرونة أكبر في التعامل مع البيانات.
</p>

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

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

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

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

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

<h2 id="-cloudways">
	إعداد خادم قاعدة البيانات على منصة Cloudways
</h2>

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

<p>
	نبدأ بإنشاء حساب و<a href="https://platform.cloudways.com/login" rel="external nofollow">تسجيل الدخول</a> إلى المنصة، ثم بالنقر على رابط <strong>عرض جميع الخوادم View all Servers</strong> نختار الخادم الذي نريده.
</p>

<p>
	<a data-fileext="gif" data-fileid="172375" href="https://academy.hsoub.com/uploads/monthly_2025_05/001__.gif.a647f2d31aac063e4ade98b6513bef22.gif" rel=""><img alt="001 خادم لارافيل" data-fileid="172375" src="https://academy.hsoub.com/uploads/monthly_2025_05/001__.thumb.gif.cb3864c4f12463e5e71db2249c655f60.gif"></a>
</p>

<p>
	 
</p>

<p>
	بعدها ننتقل لقسم <strong>الإعدادات والحزم Settings &amp; Packages</strong> من شريط القائمة الأيسر، وننقر على تبويب <strong>الحزم Packages</strong>، هنا نختار إصدار MariaDB الذي نحتاجه من الخيارات الموجودة، وننقر على <strong>حفظ التغييرات Save Changes</strong>.
</p>

<p>
	 
</p>

<p>
	<a data-fileext="jpg" data-fileid="172376" href="https://academy.hsoub.com/uploads/monthly_2025_05/002_mariadb__.jpg.7f5cfb1a9799b5cb6223b3d3f1968ff2.jpg" rel=""><img alt="002 mariadb مع لارافيل" data-fileid="172376" src="https://academy.hsoub.com/uploads/monthly_2025_05/002_mariadb__.thumb.jpg.8ab38222b4dcf161c9551e91c11960c1.jpg"></a>
</p>

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

<h2 id="-mariadb">
	ربط تطبيق لارافيل مع قاعدة بيانات MariaDB
</h2>

<p>
	نبدأ بإنشاء التطبيق من داخل طرفية Terminal جديدة نتأكد من تثبيت أداة إنشاء المشاريع الجديدة Laravel Installer عالميًا على الجهاز باستخدام Composer بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_7" style=""><span class="pln">composer global require laravel/installer</span></pre>

<p>
	باستخدام الأداة ننشئ مشروعًا جديدًا بأي اسم نريد باستبدل <code>YourProjectName</code> في الأمر التالي باسم المشروع:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_9" style=""><span class="pln">laravel new YourProjectName</span></pre>

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

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_11" style=""><span class="pln">cd YourProjectName</span></pre>

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

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

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_19" style=""><span class="pln">DB_CONNECTION = mysql
DB_HOST = 127.0.0.1
DB_PORT = 3306
DB_DATABASE = your_database_name
DB_USERNAME = your_database_username
DB_PASSWORD = your_database_password</span></pre>

<h3 id="-">
	تعريف وإنشاء جداول قاعدة البيانات
</h3>

<p>
	يستخدم لارافيل ملفات التهجير لإدارة والتعريف بمخطط قاعدة البيانات، ونبدأ ذلك بإنشاء ملف تهجير ضمن المجلد <code>database/migrations</code> ونموذج ضمن المجلد <code>app/Models</code> لكيان معين مثل <code>Post</code> من خلال تشغيل الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_21" style=""><span class="pln">php artisan make:model Post -m</span></pre>

<p>
	نعرّف حقول الجدول الجديد كما نحتاج ضمن ملف التهجير والذي سيكون اسمه مشابه للاسم <code>xxxx_xx_xx_create_posts_table.php</code> داخل المجلد <code>database/migrations</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_23" style=""><span class="pln">public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table-&gt;id();
        $table-&gt;string('title');
        $table-&gt;text('content');
        $table-&gt;timestamps();
    });
}</span></pre>

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

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_25" style=""><span class="pln">php artisan migrate</span></pre>

<h3 id="-">
	إضافة البيانات إلى قاعدة البيانات
</h3>

<p>
	يمكن استخدام مولّد البيانات Seeder أو إضافة البيانات يدويًا باستخدام الأمر <code>tinker</code> في <code>artisan</code> والذي يبدأ جلسة صدفة Shell جديدة يمكننا فيها تنفيذ أسطر برمجية باستخدام شيفرة التطبيق بتنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_27" style=""><span class="pln">php artisan tinker</span></pre>

<p>
	نستخدم نموذج المنشورات الذي أنشأناه سابقًا لإنشاء منشور جديد وتعيين قيم الحقول له ثم تسجيله ضمن قاعدة البيانات باستدعاء الدالة <code>()save</code> وتكرار هذه الخطوات لإنشاء عدة منشورات ثم الخروج من الجلسة بتنفيذ الأمر <code>exit</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_29" style=""><span class="pln">$post = new App\Models\Post;
$post-&gt;title = 'Sample Title';
$post-&gt;content = 'Sample Content';
$post-&gt;save();
exit;</span></pre>

<h3 id="-">
	عرض البيانات عبر التطبيق
</h3>

<p>
	ننشئ ملف عرض Blade جديد بالاسم <code>posts.blade.php</code> ضمن المجلد <code>resources/views</code> وفيه سنعرف طريقة عرض محتويات المنشورات بصيغة HTML ليكون الملف كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6493_33" style=""><span class="tag">&lt;h1&gt;</span><span class="pln">Posts</span><span class="tag">&lt;/h1&gt;</span><span class="pln">

@forelse($posts as $post)
    </span><span class="tag">&lt;div</span><span class="pln"> </span><span class="atn">style</span><span class="pun">=</span><span class="atv">"</span><span class="kwd">border</span><span class="pun">:</span><span class="lit">1px</span><span class="pln"> solid </span><span class="lit">#ccc</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">margin</span><span class="pun">:</span><span class="lit">10px</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">padding</span><span class="pun">:</span><span class="lit">10px</span><span class="pun">;</span><span class="atv">"</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;h2&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&gt;</span><span class="pln">{{ $post-&gt;content }}</span><span class="tag">&lt;/p&gt;</span><span class="pln">
        </span><span class="tag">&lt;small&gt;</span><span class="pln">تاريخ المنشور: {{ $post-&gt;created_at }}</span><span class="tag">&lt;/small&gt;</span><span class="pln">
    </span><span class="tag">&lt;/div&gt;</span><span class="pln">
@empty
    </span><span class="tag">&lt;p&gt;</span><span class="pln">لا يوجد منشورات بعد.</span><span class="tag">&lt;/p&gt;</span><span class="pln">
@endforelse</span></pre>

<p>
	ننشئ المتحكم Controller الخاص بالمنشورات بالاسم <code>PostController</code> ضمن المجلد <code>app/HTTP</code> باستخدام الأمر <code>artisan</code> بتنفيذ الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_35" style=""><span class="pln">php artisan make:controller PostController</span></pre>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6493_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">\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">\Http\Request</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="pun">{</span><span class="pln">
        </span><span class="com">// جلب المنشورات من قاعدة البيانات</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="com">// عرض المنشورات في ملف العرض</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> view</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> compact</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>
	يبقى تعريف الموجّه Route لعرض المنشورات المخزنة ضمن جدول المنشورات ضمن قاعدة البيانات وتعيين المتحكم المقابل لها بإضافة السطر التالي داخل الملف <code>routes/web.php</code>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6493_41" style=""><span class="pln">Route::get('/posts', 'PostController@index');</span></pre>

<p>
	نشغل خادم التطبيق ونذهب للرابط <a href="http://localhost:8000/posts" rel="external nofollow">http://localhost:8000/posts</a> ضمن المتصفح وسنرى عرض لجميع المنشورات المسجلة في قاعدة البيانات بتنفيذ أمر التشغيل:
</p>

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

<h2 id="-mariadb">
	الإصدارات المدعومة من MariaDB
</h2>

<p>
	تدعم منصة Cloudways العديد من إصدارات MariaDB، بما في ذلك 10.0 و 10.1 و 10.2 و 10.3 و 10.4 و 10.5 و 10.6، ولكن يجب ملاحظة أن الخوادم الأحدث والخوادم التي تعمل باستخدام توزيعة Debian 10 تأتي مع MariaDB 10.4 افتراضيًا والتالي جدول قابلية الترقية من قاعدة بيانات من نوع MySQL إلى ما يقابلها:
</p>

<table>
	<thead>
		<tr>
			<th>
				إصدار قاعدة البيانات
			</th>
			<th>
				قابلة للترقية إلى
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				MySQL 5.5
			</td>
			<td>
				الإصدارات MariaDB 10.0 و MariaDB 10.1 و MariaDB 10.2 و MariaDB 10.3.
			</td>
		</tr>
		<tr>
			<td>
				MySQL 5.6
			</td>
			<td>
				الإصدارات MariaDB 10.1 و MariaDB 10.2 و MariaDB 10.3.
			</td>
		</tr>
		<tr>
			<td>
				MySQL 5.7
			</td>
			<td>
				الإصدارات MariaDB 10.2 و MariaDB 10.3.
			</td>
		</tr>
		<tr>
			<td>
				MariaDB 10.0
			</td>
			<td>
				الإصدارات MariaDB 10.1 و MariaDB 10.2 و MariaDB 10.3.
			</td>
		</tr>
		<tr>
			<td>
				MariaDB 10.1
			</td>
			<td>
				الإصدارات MariaDB 10.2 و MariaDB 10.3.
			</td>
		</tr>
		<tr>
			<td>
				MariaDB 10.2
			</td>
			<td>
				الإصدار MariaDB 10.3 والإصدارات الأحدث.
			</td>
		</tr>
		<tr>
			<td>
				MariaDB 10.3
			</td>
			<td>
				الإصدار MariaDB 10.4 والإصدارات الأحدث.
			</td>
		</tr>
		<tr>
			<td>
				MariaDB 10.4
			</td>
			<td>
				الإصدار MariaDB 10.5 والإصدارات الأحدث.
			</td>
		</tr>
		<tr>
			<td>
				MariaDB 10.5
			</td>
			<td>
				الإصدار MariaDB 10.6 والإصدارات الأحدث.
			</td>
		</tr>
		<tr>
			<td>
				MariaDB 10.6
			</td>
			<td>
				سيكون من الممكن ترقيته إلى أيّ إصدار جديد من MariaDB عند توفّره على منصة Cloudways.
			</td>
		</tr>
	</tbody>
</table>

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

<p>
	رأينا في هذا المقال سهولة ربط قاعدة بيانات MariaDB بتطبيق لارافيل عن طريق تعديل ملف <code>.env</code> في لارافيل لضبط الاتصال وتشغيل عمليات الـتهجير لإنشاء الجداول الأساسية وتعريف البيانات ضمنها، واستخدمنا منصة Cloudways التي توفر خيارًا سهلاً وسريعًا لاستضافة وإعداد قواعد البيانات.
</p>

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

<p>
	ترجمة -وبتصرّف- للقسم <a href="https://www.cloudways.com/blog/connect-mariadb-to-laravel/" rel="external nofollow">How to Connect MariaDB Database to Laravel Application</a> لصاحبه Inshal Ali.
</p>

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

<ul>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%A3%D9%85%D9%8A%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-mysql-mariadb-%D8%B9%D9%84%D9%89-%D8%AE%D9%88%D8%A7%D8%AF%D9%8A%D9%85-%D9%84%D9%8A%D9%86%D9%83%D8%B3-r54/" rel="">كيفية تأمين قواعد البيانات MySQL ,MariaDB على خواديم لينكس</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/mysql/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D9%8A%D8%B1%D8%A7%D8%AF-%D9%88%D8%AA%D8%B5%D8%AF%D9%8A%D8%B1-%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mysql-%D8%A3%D9%88-mariadb-r361/" rel="">كيفية استيراد وتصدير قواعد بيانات MySQL أو MariaDB</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%BA%D9%8A%D9%8A%D8%B1-%D9%85%D8%AC%D9%84%D8%AF-%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-mariadb-%D8%A5%D9%84%D9%89-%D9%85%D9%83%D8%A7%D9%86%D9%8D-%D8%A2%D8%AE%D8%B1-r349/" rel="">كيفية تغيير مجلد تخزين بيانات MariaDB إلى مكانٍ آخر</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>
</ul>
]]></description><guid isPermaLink="false">2580</guid><pubDate>Fri, 20 Jun 2025 16:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x623;&#x62E;&#x637;&#x627;&#x621; &#x627;&#x644;&#x639;&#x634;&#x631;&#x629; &#x627;&#x644;&#x623;&#x643;&#x62B;&#x631; &#x634;&#x64A;&#x648;&#x639;&#x64B;&#x627; &#x641;&#x64A; &#x634;&#x64A;&#x641;&#x631;&#x629; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D8%B9%D8%B4%D8%B1%D8%A9-%D8%A7%D9%84%D8%A3%D9%83%D8%AB%D8%B1-%D8%B4%D9%8A%D9%88%D8%B9%D9%8B%D8%A7-%D9%81%D9%8A-%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-php-r2434/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2024_10/PHP.png.5b5e1e68a906ca76e288dd5c8bf3e7de.png" /></p>
<p>
	تُعدّ لغة PHP من أكثر اللغات استخدامًا في تطوير مواقع الويب لأنها سهلة وتتيح بناء تطبيقات الويب بسرعة. لكن رغم سهولتها إلا أنها تطورت وأصبحت تضم العديد من المميزات والفروق الرئيسية والدقيقة التي يمكن أن يخطئ بها المطورون بالرغم من سهولة استخدامها، فقد يقع المطورون في أخطاء بسبب هذه التفاصيل الدقيقة في اللغة، مما يستغرق منهم وقتًا طويلًا لإصلاحها. في هذا المقال. سنسلط الضوء في هذا المقال على 10 من الأخطاء الأكثر شيوعًا التي يجب على مطوري PHP توخّي الحذر منها.
</p>

<h2 id="1referencesforeach">
	الخطأ 1: ترك مراجع References المصفوفة معلّقة بعد انتهاء حلقات foreach
</h2>

<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="">حلقات foreach</a> مفيدًا إذا أردتَ العمل على كل عنصر من المصفوفة التي تمر عليها، فليكن لدينا مثلًا ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_7" style=""><span class="pln">$arr </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</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">$arr </span><span class="kwd">as</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">$value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $value </span><span class="pun">=</span><span class="pln"> $value </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// $arr is now array(2, 4, 6, 8)</span></pre>

<p>
	ولكن إن لم تكن حذرًا، فقد يكون لهذه المراجع بعض الآثار الجانبية والعواقب غير المرغوب فيها، فمثلًا سيبقى المتغير <code>‎$value</code> ضمن النطاق Scope وسيحتفظ بمرجع إلى العنصر الأخير من المصفوفة بعد تنفيذ الشيفرة البرمجية في المثال السابق، وبالتالي قد تؤدي العمليات اللاحقة المُطبَّقة على المتغير <code>‎$value</code> إلى تعديل العنصر الأخير في المصفوفة عن غير قصد.
</p>

<p>
	تذكّر أن حلقة <code>foreach</code> لا تنشئ نطاقًا، وبالتالي يُعَد المتغير <code>‎$value</code> في المثال السابق مرجعًا ضمن النطاق العلوي للسكريبت، حيث تضبط حلقة <code>foreach</code> المرجع للإشارة إلى العنصر التالي من المصفوفة <code>‎$arr</code> في كل تكرار، ويبقى المتغير <code>‎$value</code> يؤشّر إلى العنصر الأخير من المصفوفة <code>‎$arr</code>، ويبقى ضمن النطاق بعد اكتمال الحلقة.
</p>

<p>
	إليك فيما يلي مثال عن نوع الأخطاء المربكة التي يمكن أن تؤدي إلى هذه المشكلة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_9" style=""><span class="pln">$array </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"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">];</span><span class="pln">
echo implode</span><span class="pun">(</span><span class="str">','</span><span class="pun">,</span><span class="pln"> $array</span><span class="pun">),</span><span class="pln"> </span><span class="str">"\n"</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">$array </span><span class="kwd">as</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">$value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">    </span><span class="com">// من خلال المرجع</span><span class="pln">
echo implode</span><span class="pun">(</span><span class="str">','</span><span class="pun">,</span><span class="pln"> $array</span><span class="pun">),</span><span class="pln"> </span><span class="str">"\n"</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">$array </span><span class="kwd">as</span><span class="pln"> $value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">     </span><span class="com">// من خلال القيمة (أي النسخة‫)</span><span class="pln">
echo implode</span><span class="pun">(</span><span class="str">','</span><span class="pun">,</span><span class="pln"> $array</span><span class="pun">),</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span></pre>

<p>
	وسيكون خرج الشيفرة البرمجية السابقة ما يلي:
</p>

<pre class="ipsCode">1,2,3
1,2,3
1,2,2
</pre>

<p>
	هذا ليس خطأ مطبعيًا، فالقيمة الأخيرة في السطر الأخير هي 2 وليست 3، والسبب هو بقاء المصفوفة <code>‎$array</code> دون تغيير بعد المرور على حلقة <code>foreach</code> الأولى، ولكن يُترَك المتغير <code>‎$value</code> بوصفه مرجعًا مُعلَّقًا للعنصر الأخير في المصفوفة <code>‎$array</code> لأن حلقة <code>foreach</code> وصلت إلى المتغير <code>‎$value</code> من خلال المرجع، لذا ستحدث أشياء غريبة عندما نمر على حلقة <code>foreach</code> الثانية، حيث تنسخ حلقة <code>foreach</code> كل عنصر تسلسلي من عناصر المصفوفة <code>‎$array</code> إلى المتغير <code>‎$value</code> في كل خطوة من الحلقة بسبب الوصول إلى هذا المتغير من خلال القيمة (أي من خلال النسخة). إليك ما يحدث في كل خطوة من حلقة <code>foreach</code> الثانية:
</p>

<ul>
	<li>
		<strong>تمرير القيمة 1</strong>: يؤدي إلى نسخ العنصر الأول من المصفوفة <code>‎$array[0]‎</code> (أي القيمة "1") إلى المتغير <code>‎$value</code> (وهو مرجع إلى العنصر <code>‎$array[2]‎</code>)، لذا سيساوي <code>‎$array[2]‎</code> الآن القيمة 1، وستحتوي المصفوفة <code>‎$array</code> على العناصر ‎[1, 2, 1]‎.
	</li>
	<li>
		<strong>تمرير القيمة 2</strong>: يؤدي إلى نسخ العنصر الثاني من المصفوفة <code>‎$array[1]‎</code> (أي القيمة "2") إلى المتغير <code>‎$value</code> (وهو مرجع إلى العنصر <code>‎$array[2]‎</code>)، لذا سيساوي <code>‎$array[2]‎</code> الآن القيمة 2، وستحتوي المصفوفة <code>‎$array</code> على العناصر ‎[1, 2, 2]‎.
	</li>
	<li>
		<strong>تمرير القيمة 3</strong>: يؤدي إلى نسخ العنصر الثالث من المصفوفة <code>‎$array[2]‎</code> (الذي يساوي القيمة "2" الآن) إلى المتغير <code>‎$value</code> (وهو مرجع إلى العنصر <code>‎$array[2]‎</code>)، لذلك لا يزال العنصر <code>‎$array[2]‎</code> يساوي القيمة 2، وستحتوي المصفوفة <code>‎$array</code> الآن على العناصر ‎[1, 2, 2]‎.
	</li>
</ul>

<p>
	يمكن الاستفادة من استخدام المراجع في حلقات <code>foreach</code> دون التعرض لخطر هذه الأنواع من المشاكل من خلال استدعاء الدالة <code>unset()‎</code> مع المتغير بعد حلقة <code>foreach</code> مباشرةً لإزالة المرجع كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_11" style=""><span class="pln">$arr </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</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">$arr </span><span class="kwd">as</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">$value</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $value </span><span class="pun">=</span><span class="pln"> $value </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
unset</span><span class="pun">(</span><span class="pln">$value</span><span class="pun">);</span><span class="pln">   </span><span class="com">// لم يَعُد المتغير‫ ‎$value مرجعًا إلى العنصر ‎$arr[3]‎</span></pre>

<h2 id="2isset">
	الخطأ 2: سوء فهم سلوك الدالة isset()‎
</h2>

<p>
	تعيد<a href="https://wiki.hsoub.com/PHP/isset" rel="external"> الدالة isset()‎</a> القيمة <code>false</code> في حالة عدم وجود عنصر، وتعيد أيضًا <code>false</code> للقيم <code>null</code>، حيث يُسبّب هذا السلوك مشكلات، فليكن لدينا المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_14" style=""><span class="pln">$data </span><span class="pun">=</span><span class="pln"> fetchRecordFromStorage</span><span class="pun">(</span><span class="pln">$storage</span><span class="pun">,</span><span class="pln"> $identifier</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">isset</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">[</span><span class="str">'keyShouldBeSet'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// افعل شيئًا هنا عند عدم ضبط‫ 'keyShouldBeSet'</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُفترَض أننا نريد التحقق ممّا إذا كان <code>keyShouldBeSet</code> مضبوطًا في <code>‎$data</code>، ولكن ستعيد الدالة <code>isset($data['keyShouldBeSet'])‎</code> أيضًا القيمة <code>false</code> حتى عند ضبط <code>‎$data['keyShouldBeSet']‎</code> على القيمة <code>null</code>، وبالتالي يوجد تناقض مع ما ذكرناه سابقًا.
</p>

<p>
	إليك أيضًا المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_16" style=""><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">[</span><span class="str">'active'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $postData </span><span class="pun">=</span><span class="pln"> extractSomething</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="com">// ...</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$postData</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">'post not active'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تفترض الشيفرة البرمجية السابقة أنه إذا أعادت <code>‎$_POST['active']‎</code> القيمة <code>true</code>، فسيكون <code>postData</code> مضبوطًا، وبالتالي ستعيد الدالة <code>isset($postData)‎</code> القيمة <code>true</code>، وتفترض أيضًا أن الطريقة الوحيدة التي ستعيد بها الدالة <code>isset($postData)‎</code> القيمة <code>false</code> هي إذا أعادت <code>‎$_POST['active']‎</code> القيمة <code>false</code>، ولكن ستعيد الدالة <code>isset($postData)‎</code> القيمة <code>false</code> عند ضبط <code>‎$postData</code> على القيمة <code>null</code>، وبالتالي يمكن أن تعيد الدالة <code>isset($postData)‎</code> القيمة <code>false</code> حتى إذا أعادت <code>‎$_POST['active']‎</code> القيمة <code>true</code>، لذا يوجد تناقض مع ما ذكرناه سابقًا.
</p>

<p>
	إذا كان الهدف من الشيفرة البرمجية السابقة هو التحقق مما إذا كانت <code>‎$_POST['active']‎</code> تعيد القيمة <code>true</code>، فسيكون الاعتماد على الدالة <code>isset()‎</code> لذلك قرارًا برمجيًا سيئًا على أيّة حال، لذا يُفضَّل إعادة التحقق من <code>‎$_POST['active']‎</code> بدلًا من ذلك كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_18" style=""><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">[</span><span class="str">'active'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $postData </span><span class="pun">=</span><span class="pln"> extractSomething</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="com">// ...</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">[</span><span class="str">'active'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">'post not active'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يُعَد استخدام التابع ‎<code>array_key_exists()</code>‎ حلًا أكثر قوة بالنسبة للحالات التي يكون فيها من المهم التحقق مما إذا كان المتغير مضبوطًا فعليًا، أو للتمييز بين متغير غير مضبوط ومتغير مضبوط على القيمة <code>null</code>، فمثلًا يمكننا إعادة كتابة المثال الأول من المثالين السابقين كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_20" style=""><span class="pln">$data </span><span class="pun">=</span><span class="pln"> fetchRecordFromStorage</span><span class="pun">(</span><span class="pln">$storage</span><span class="pun">,</span><span class="pln"> $identifier</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"> array_key_exists</span><span class="pun">(</span><span class="str">'keyShouldBeSet'</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">// افعل ذلك عند عدم ضبط‫ 'keyShouldBeSet'</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا جمعنا بين التابعين <code><a href="https://wiki.hsoub.com/PHP/array_key_exists" rel="external">array_key_exists()</a>‎</code> و <code>get_defined_vars()‎</code>، فيمكننا التحقق بطريقة موثوقة من ضبط متغير ضمن النطاق الحالي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_22" style=""><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">array_key_exists</span><span class="pun">(</span><span class="str">'varShouldBeSet'</span><span class="pun">,</span><span class="pln"> get_defined_vars</span><span class="pun">()))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫المتغير ‎$varShouldBeSet موجود في النطاق الحالي</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="3">
	الخطأ 3: الخلط بين الإعادة باستخدام المرجع وإعادتها باستخدام القيمة
</h2>

<p>
	ليكن لدينا مقطع الشيفرة البرمجية التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_32" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Config</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $values </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"> getValues</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">values</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$config </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Config</span><span class="pun">();</span><span class="pln">

$config</span><span class="pun">-&gt;</span><span class="pln">getValues</span><span class="pun">()[</span><span class="str">'test'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">;</span><span class="pln">
echo $config</span><span class="pun">-&gt;</span><span class="pln">getValues</span><span class="pun">()[</span><span class="str">'test'</span><span class="pun">];</span></pre>

<p>
	إذا شغّلتَ الشيفرة البرمجية السابقة، فستحصل على ما يلي:
</p>

<pre class="ipsCode">PHP Notice:  Undefined index: test in /path/to/my/script.php on line 21
</pre>

<p>
	تكمن المشكلة في أن هذه الشيفرة البرمجية تخلط بين إعادة <a href="https://wiki.hsoub.com/PHP/array" rel="external">المصفوفات</a> باستخدام المرجع وإعادتها باستخدام القيمة، حيث إن لم تخبر لغةَ PHP صراحةً بإعادة المصفوفة باستخدام <a href="https://wiki.hsoub.com/PHP/references" rel="external">المرجع</a> (أي باستخدام <code>&amp;</code>)، فستعيد لغة PHP المصفوفة باستخدام القيمة افتراضيًا، وهذا يمثّل إعادة نسخة من المصفوفة، وبالتالي لن تتمكّن الدالة المُستدعاة والمستدعِي من الوصول إلى النسخة نفسها من المصفوفة.
</p>

<p>
	يعيد استدعاء الدالة <code>getValues()‎</code> السابق نسخة من المصفوفة <code>‎$values</code> بدلًا من إعادة مرجع إليها. إذًا لنعيد النظر إلى السطرين الرئيسيين من المثال السابق:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_36" style=""><span class="com">// تعيد الدالة‫ getValues()‎ نسخة من المصفوفة ‎$values، مما يؤدي إلى إضافة عنصر 'test'</span><span class="pln">
</span><span class="com">// إلى نسخة من المصفوفة‫ ‎$values، وليس إلى المصفوفة ‎$values نفسها</span><span class="pln">
$config</span><span class="pun">-&gt;</span><span class="pln">getValues</span><span class="pun">()[</span><span class="str">'test'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">;</span><span class="pln">

</span><span class="com">// تعيد الدالة‫ getValues()‎ مرة أخرى نسخة أخرى من المصفوفة ‎$values، ولا تحتوي هذه النسخة</span><span class="pln">
</span><span class="com">// ‫على عنصر 'test'، ولذلك نحصل على رسالة فهرس غير مُعرَّف "undefined index"</span><span class="pln">
echo $config</span><span class="pun">-&gt;</span><span class="pln">getValues</span><span class="pun">()[</span><span class="str">'test'</span><span class="pun">];</span></pre>

<p>
	أحد الحلول الممكنة لهذه المشكلة هو حفظ النسخة الأولى من المصفوفة <code>‎$values</code> التي تعيدها الدالة <code>getValues()‎</code>، ثم العمل على تلك النسخة لاحقًا كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_38" style=""><span class="pln">$vals </span><span class="pun">=</span><span class="pln"> $config</span><span class="pun">-&gt;</span><span class="pln">getValues</span><span class="pun">();</span><span class="pln">
$vals</span><span class="pun">[</span><span class="str">'test'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">;</span><span class="pln">
echo $vals</span><span class="pun">[</span><span class="str">'test'</span><span class="pun">];</span></pre>

<p>
	ستعمل هذه الشيفرة البرمجية بنجاح، أي أنها ستعطي <code>test</code> دون إنشاء أيّ رسالة فهرس غير مُعرَّف "undefined index"، ولكن قد يكون هذا الأسلوب مناسبًا أو غير مناسب اعتمادًا على ما تحاول تحقيقه، إذ لن تعدّل هذه الشيفرة البرمجية المصفوفة <code>‎$values</code> الأصلية، لذا إذا أردتَ أن تؤثر تعديلاتك (مثل إضافة عنصر <code>test</code>) على المصفوفة الأصلية، فيجب أن تعدّل الدالة <code>getValues()‎</code> لإعادة مرجع إلى المصفوفة <code>‎$values</code> نفسها. يمكن تحقيق ذلك من خلال إضافة <code>&amp;</code> قبل اسم الدالة، مما يشير إلى أنها يجب أن تعيد مرجعًا كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_40" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Config</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $values </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">

    </span><span class="com">// إعادة مرجع إلى المصفوفة‫ ‎$values الفعلية</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">&amp;</span><span class="pln">getValues</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">values</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$config </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Config</span><span class="pun">();</span><span class="pln">

$config</span><span class="pun">-&gt;</span><span class="pln">getValues</span><span class="pun">()[</span><span class="str">'test'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">;</span><span class="pln">
echo $config</span><span class="pun">-&gt;</span><span class="pln">getValues</span><span class="pun">()[</span><span class="str">'test'</span><span class="pun">];</span></pre>

<p>
	وسيكون الخرج <code>test</code> كما هو متوقع.
</p>

<p>
	لنجعل الآن الأمور أكثر إرباكًا كما في مقتطف الشيفرة البرمجية التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_42" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Config</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $values</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// استخدام كائن مصفوفة‫ ArrayObject بدلًا من المصفوفة</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">values </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArrayObject</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"> getValues</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">values</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$config </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Config</span><span class="pun">();</span><span class="pln">

$config</span><span class="pun">-&gt;</span><span class="pln">getValues</span><span class="pun">()[</span><span class="str">'test'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'test'</span><span class="pun">;</span><span class="pln">
echo $config</span><span class="pun">-&gt;</span><span class="pln">getValues</span><span class="pun">()[</span><span class="str">'test'</span><span class="pun">];</span></pre>

<p>
	إذا اعتقدتَ أن هذه الشيفرة البرمجية ستؤدي إلى خطأ "undefined index" نفسه الموجود في مثال المصفوفة <code>array</code> السابق، فأنت مخطئ، إذ ستعمل هذه الشيفرة البرمجية بنجاح، والسبب هو أن لغة PHP تمرّر الكائنات من خلال المرجع دائمًا على عكس المصفوفات، فالكائن <code>ArrayObject</code> هو كائن من مكتبة PHP المعيارية -أو كائن SPL- يحاكي استخدام المصفوفات، ولكنه يعمل بوصفه كائنًا.
</p>

<p>
	ليس من الواضح دائمًا في لغة PHP ما إذا كنت تتعامل مع نسخة أو مرجع كما توضح هذه الأمثلة، لذلك يجب أن تفهم هذه السلوكيات الافتراضية مثل تمرير المتغيرات والمصفوفات من خلال القيمة وتمرير الكائنات من خلال المرجع، ويجب التحقق بعناية من توثيق واجهة برمجة التطبيقات <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> الخاصة بالدالة التي تستدعيها لمعرفة ما إذا كانت تعيد قيمة، أو نسخة من مصفوفة، أو مرجعًا إلى مصفوفة، أو مرجعًا إلى كائن.
</p>

<p>
	يجب أيضًا تجنب ممارسة إعادة مرجع إلى مصفوفة أو كائن <code>ArrayObject</code>، لأنه يوفر للمستدعِي القدرة على تعديل البيانات الخاصة للنسخة، وهذا يناقض مفهوم التغليف <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="">Encapsulation</a>، لذا يُفضَّل استخدام النمط القديم للجوالب Getters والضوابط Setters كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_44" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Config</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $values </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"> setValue</span><span class="pun">(</span><span class="pln">$key</span><span class="pun">,</span><span class="pln"> $value</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">values</span><span class="pun">[</span><span class="pln">$key</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $value</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"> getValue</span><span class="pun">(</span><span class="pln">$key</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">values</span><span class="pun">[</span><span class="pln">$key</span><span class="pun">];</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$config </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Config</span><span class="pun">();</span><span class="pln">

$config</span><span class="pun">-&gt;</span><span class="pln">setValue</span><span class="pun">(</span><span class="str">'testKey'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'testValue'</span><span class="pun">);</span><span class="pln">
echo $config</span><span class="pun">-&gt;</span><span class="pln">getValue</span><span class="pun">(</span><span class="str">'testKey'</span><span class="pun">);</span><span class="pln">    </span><span class="com">// echos 'testValue'</span></pre>

<p>
	تمنح هذه الطريقة المستدعِي القدرةَ على ضبط أو جلب أيّ قيمة من المصفوفة دون توفير وصول عام إلى المصفوفة <code>‎$values</code> الخاصة نفسها.
</p>

<h2 id="4">
	الخطأ 4: إجراء الاستعلامات ضمن حلقة
</h2>

<p>
	يمكن أن تصادف شيئًا كما يلي إذا كانت شيفرة PHP لا تعمل لديك:
</p>

<pre class="ipsCode prettyprint lang-perl prettyprinted" id="ips_uid_4442_47" style=""><span class="pln">$models </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="pln">$inputValues as $inputValue</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $models</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $valueRepository</span><span class="pun">-&gt;</span><span class="pln">findByValue</span><span class="pun">(</span><span class="pln">$inputValue</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	قد لا يكون هناك أيّ شيء خاطئ، ولكن إذا اتبعت المنطق الموجود في هذه الشيفرة البرمجية، فقد تجد أن الاستدعاء البسيط السابق <code>‎$valueRepository-&gt;findByValue()‎</code> يؤدي في النهاية إلى استعلامٍ من نوعٍ ما كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_49" style=""><span class="pln">$result </span><span class="pun">=</span><span class="pln"> $connection</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">"SELECT `x`,`y` FROM `values` WHERE `value`="</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $inputValue</span><span class="pun">);</span></pre>

<p>
	لذا سيؤدي كل تكرار للحلقة السابقة إلى استعلام منفصل لقاعدة البيانات، فمثلًا إذا زوّدتَ الحلقة بمصفوفةٍ مكونة من 1000 قيمة، فستنشئ 1000 استعلام منفصل للمورد، وإذا اُستدعِي مثل هذا السكربت ضمن خيوط Threads متعددة، فيُحتمَل أن يؤدي ذلك إلى توقف النظام بأكمله، لذا يجب معرفة متى تُجري شيفرتك البرمجية الاستعلامات وجمع القيم ثم تشغيل استعلام واحد لجلب جميع النتائج كلما أمكن ذلك.
</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="">استعلام SQL</a> منفصل لكل معرّف لاسترداد بيانات السجل الكاملة لكل معرّف من هذه المعرّفات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_51" style=""><span class="pln">$data </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="pln">$ids </span><span class="kwd">as</span><span class="pln"> $id</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> $connection</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">"SELECT `x`, `y` FROM `values` WHERE `id` = "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $id</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"> $result</span><span class="pun">-&gt;</span><span class="pln">fetch_row</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ولكن يمكن تحقيق الشيء نفسه بفعالية أكبر في استعلام SQL واحد كما يلي:
</p>

<pre class="ipsCode prettyprint lang-sql prettyprinted" id="ips_uid_4442_54" style=""><span class="pln">$data </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">count</span><span class="pun">(</span><span class="pln">$ids</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> $connection</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">"SELECT `x`, `y` FROM `values` WHERE `id` IN ("</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">','</span><span class="pun">,</span><span class="pln"> $ids</span><span class="pun">));</span><span class="pln">
    </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> $result</span><span class="pun">-&gt;</span><span class="pln">fetch_row</span><span class="pun">())</span><span class="pln"> </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"> $row</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

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

<h2 id="5">
	الخطأ 5: تزييف استخدام الذاكرة وعدم كفاءتها
</h2>

<p>
	يكون جلب العديد من السجلات في وقت واحد أكثر كفاءة من تشغيل استعلام واحد لجلب كل صف، ولكن يمكن أن يؤدي هذا النهج إلى حالة "نفاد الذاكرة Out of Memory" في مكتبة <code>libmysqlclient</code> عند استخدام إضافة PHP التي هي <code>mysql</code>. ليكن لدينا مثلًا مربع اختبار مع موارد محدودة (512 ميجابايت من ذاكرة RAM) وقاعدة بيانات MySQL وواجهة سطر الأوامر <code>php-cli</code>، حيث سنهيّئ جدول قاعدة بيانات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4442_56" style=""><span class="com">// الاتصال بقاعدة بيانات‫ mysql</span><span class="pln">
$connection </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> mysqli</span><span class="pun">(</span><span class="str">'localhost'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'username'</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">'database'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// إنشاء جدول مؤلّف من 400 عمود</span><span class="pln">
$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">'CREATE TABLE `test`(`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT'</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$col </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $col </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">400</span><span class="pun">;</span><span class="pln"> $col</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $query </span><span class="pun">.=</span><span class="pln"> </span><span class="str">", `col$col` CHAR(10) NOT NULL"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
$query </span><span class="pun">.=</span><span class="pln"> </span><span class="str">');'</span><span class="pun">;</span><span class="pln">
$connection</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="pln">$query</span><span class="pun">);</span><span class="pln">

</span><span class="com">// كتابة 2 مليون صف</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$row </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $row </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">2000000</span><span class="pun">;</span><span class="pln"> $row</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $query </span><span class="pun">=</span><span class="pln"> </span><span class="str">"INSERT INTO `test` VALUES ($row"</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$col </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $col </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">400</span><span class="pun">;</span><span class="pln"> $col</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $query </span><span class="pun">.=</span><span class="pln"> </span><span class="str">', '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> mt_rand</span><span class="pun">(</span><span class="lit">1000000000</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9999999999</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    $query </span><span class="pun">.=</span><span class="pln"> </span><span class="str">')'</span><span class="pun">;</span><span class="pln">
    $connection</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="pln">$query</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لنتحقّق الآن من استخدام الموارد كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_4442_58" style=""><span class="com">// الاتصال بقاعدة بيانات‫ mysql</span><span class="pln">
$connection </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> mysqli</span><span class="pun">(</span><span class="str">'localhost'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'username'</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">'database'</span><span class="pun">);</span><span class="pln">
echo </span><span class="str">"Before: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> memory_get_peak_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">

$res </span><span class="pun">=</span><span class="pln"> $connection</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">'SELECT `x`,`y` FROM `test` LIMIT 1'</span><span class="pun">);</span><span class="pln">
echo </span><span class="str">"Limit 1: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> memory_get_peak_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">

$res </span><span class="pun">=</span><span class="pln"> $connection</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="str">'SELECT `x`,`y` FROM `test` LIMIT 10000'</span><span class="pun">);</span><span class="pln">
echo </span><span class="str">"Limit 10000: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> memory_get_peak_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span></pre>

<p>
	ويكون الخرج كما يلي:
</p>

<pre class="ipsCode">Before: 224704
Limit 1: 224704
Limit 10000: 224704
</pre>

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

<pre class="ipsCode">PHP Warning:  mysqli::query(): (HY000/2013):
              Lost connection to MySQL server during query in /root/test.php on line 11
</pre>

<p>
	المشكلة هنا هي الطريقة التي تعمل بها وحدة <code>mysql</code> الخاصة بلغة PHP، فهي مجرد وكيل لمكتبة <code>libmysqlclient</code>، والتي تذهب إلى الذاكرة مباشرةً عند تحديد جزء من البيانات. لا يدير مدير PHP الذاكرة، وبالتالي لن تعرض الدالة <code>memory_get_peak_usage()‎</code> أيّ زيادة في استخدام الموارد عندما نزيد الحد الأقصى في استعلامنا. يؤدي ذلك إلى ظهور مشاكل مثل المشكلة السابقة، إذ سنُخدَع من خلال الاعتقاد بأن إدارة ذاكرتنا جيدة، ولكنها سيئة فعليًا وسنواجه مثل هذه المشكلة.
</p>

<p>
	يمكنك تجنب هذا التزييف من خلال استخدام الوحدة <code>mysqlnd</code> بدلًا من ذلك، بالرغم من أنها لن تؤدي إلى تحسين استخدام الذاكرة، حيث تُصرَّف Compiled هذه الوحدة بوصفها إضافةً أصيلة Native للغة PHP وتستخدم مدير ذاكرة PHP، لذلك إذا أجرينا الاختبار السابق باستخدام الوحدة <code>mysqlnd</code> بدلًا من الوحدة <code>mysql</code>، فسنحصل على صورة أكثر واقعية لاستخدام ذاكرتنا.
</p>

<pre class="ipsCode">Before: 232048
Limit 1: 324952
Limit 10000: 32572912
</pre>

<p>
	تستخدم الوحدة <code>mysql</code> ضعف عدد الموارد التي تستخدمها الوحدة <code>mysqlnd</code> لتخزين البيانات وفقًا لتوثيق PHP، لذا يستخدم السكربت الأصلي الذي يستخدم وحدة <code>mysql</code> ذاكرةً أكبر مما هو موضّح هنا فعليًا (حوالي ضعف ذلك).
</p>

<p>
	يمكن تجنب مثل هذه المشاكل من خلال تحديد حجم استعلاماتك واستخدام حلقة ذات عدد صغير من التكرارات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_60" style=""><span class="pln">$totalNumberToFetch </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">;</span><span class="pln">
$portionSize </span><span class="pun">=</span><span class="pln"> </span><span class="lit">100</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">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"> ceil</span><span class="pun">(</span><span class="pln">$totalNumberToFetch </span><span class="pun">/</span><span class="pln"> $portionSize</span><span class="pun">);</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $limitFrom </span><span class="pun">=</span><span class="pln"> $portionSize </span><span class="pun">*</span><span class="pln"> $i</span><span class="pun">;</span><span class="pln">
    $res </span><span class="pun">=</span><span class="pln"> $connection</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="pln">
                         </span><span class="str">"SELECT `x`,`y` FROM `test` LIMIT $limitFrom, $portionSize"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

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

<h2 id="6unicodeutf8">
	الخطأ 6: تجاهل مشكلات الترميز Unicode/UTF-8
</h2>

<p>
	تُعَد هذه المشكلة خاصة بلغة PHP بحد ذاتها أكثر من كونها مشكلة قد تظهر أثناء تنقيح أخطاء شيفرة PHP، ولكن هذه المشكلة لم تُعالَج بطريقة كافية، إذ كان من المقرر جعل نواة PHP 6 متوافقةً مع الترميز الموحّد Unicode، وجرى تعليق ذلك عند تعليق تطوير PHP 6 في عام 2010، ولكن ذلك لا يعفي المطور بأيّ حال من الأحوال من تقديم ترميز UTF-8 بطريقة صحيحة وتجنب الافتراض الخاطئ بأن جميع السلاسل النصية ستكون "نصًا عاديًا قديمًا يستخدم معيار ASCII". تشتهر الشيفرة البرمجية التي تفشل في معالجة السلاسل النصية التي ليست ASCII بإدخال أخطاء هايزنبغ Heisenbug المعقدة في شيفرتك البرمجية، إذ قد تسبّب حتى استدعاءات <code>strlen($_POST['name'])‎</code> البسيطة مشكلات إذا حاول شخص يحمل اسم عائلة مثل "Schrödinger" التسجيل في نظامك.
</p>

<p>
	إليك فيما يلي قائمة صغيرة لتجنب مثل هذه المشكلات في شيفرتك البرمجية:
</p>

<ul>
	<li>
		إذا كنت لا تعرف الكثير عن <span ipsnoautolink="true">ترميز Unicode و UTF-8</span>، فيجب أن تتعلّم الأساسيات على الأقل.
	</li>
	<li>
		تأكد من استخدام دوال <code>mb_*‎</code> دائمًا بدلًا من دوال السلاسل النصية القديمة، وتأكد من تضمين إضافة "تعدد البايتات multibyte" في إصدار PHP الخاص بك.
	</li>
	<li>
		تأكد من ضبط قاعدة البيانات والجداول الخاصة بك لاستخدام ترميز Unicode، إذ لا تزال العديد من إصدارات MySQL تستخدم معيار <code>latin1</code> افتراضيًا.
	</li>
	<li>
		تذكّر أن الدالة <code>json_encode()‎</code> تحوّل الرموز التي ليست رموز ASCII، حيث تحوّل السلسلة النصية "Schrödinger" إلى "Schr\u00f6dinger" مثلًا، ولكن التابع <code>serialize()‎</code> لا يفعل ذلك.
	</li>
	<li>
		تأكّد من أن ملفات شيفرة PHP البرمجية الخاصة بك مشفَّرة أيضًا باستخدام ترميز UTF-8 لتجنب التعارض عند ضم السلاسل النصية مع ثوابت السلاسل النصية المكتوبة أو المضبوطة.
	</li>
</ul>

<p>
	اطّلع على مقال <a href="https://academy.hsoub.com/programming/php/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%85%D8%B2%D8%A9-%D8%A8%D8%AA%D8%B1%D9%85%D9%8A%D8%B2-utf-8-%D9%81%D9%8A-php-r1125/" rel="">معالجة الملفات والبيانات المرمزة بترميز UTF-8 في PHP</a> لمزيدٍ من المعلومات.
</p>

<h2 id="7d_postpost">
	الخطأ 7: افتراض أن المصفوفة ‎$_POST ستحتوي على بيانات POST الخاصة بك دائمًا
</h2>

<p>
	لن تحتوي المصفوفة <code>‎$_POST</code> على بيانات POST الخاصة بك دائمًا على عكس ما يدل عليه اسمها، إذ يمكن أن تكون فارغة. لنفترض مثلًا أننا أنشأنا طلب خادم باستخدام استدعاء التابع <code>jQuery.ajax()‎</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_64" style=""><span class="com">// js</span><span class="pln">
$</span><span class="pun">.</span><span class="pln">ajax</span><span class="pun">({</span><span class="pln">
    url</span><span class="pun">:</span><span class="pln"> </span><span class="str">'http://my.site/some/path'</span><span class="pun">,</span><span class="pln">
    method</span><span class="pun">:</span><span class="pln"> </span><span class="str">'post'</span><span class="pun">,</span><span class="pln">
    data</span><span class="pun">:</span><span class="pln"> JSON</span><span class="pun">.</span><span class="pln">stringify</span><span class="pun">({</span><span class="pln">a</span><span class="pun">:</span><span class="pln"> </span><span class="str">'a'</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">:</span><span class="pln"> </span><span class="str">'b'</span><span class="pun">}),</span><span class="pln">
    contentType</span><span class="pun">:</span><span class="pln"> </span><span class="str">'application/json'</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	لاحظ نوع المحتوى <code>contentType: 'application/json'‎</code> هنا، حيث نرسل البيانات بتنسيق JSON، وهو أمر شائع جدًا لواجهات برمجة التطبيقات، وهو الإعداد الافتراضي للنشر في خدمة AngularJS التي هي <code>‎$http</code> مثلًا.
</p>

<p>
	نفرّغ معلومات محتوى المصفوفة <code>‎$_POST</code> من طرف الخادم في مثالنا كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_66" style=""><span class="com">// php</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">);</span></pre>

<p>
	والمفاجأة أن النتيجة ستكون كما يلي:
</p>

<pre class="ipsCode">array(0) { }
</pre>

<p>
	لم تظهر سلسلة JSON النصية الخاصة بنا <code>‎{a: 'a', b: 'b'}‎</code>، حيث تحلّل لغة PHP حِمل طلب POST تلقائيًا عندما يكون نوع المحتوى <code>application/x-www-form-urlencoded</code> أو <code>multipart/form-data</code> فقط، إذ كان هذان النوعان من المحتوى هما النوعان الوحيدان المُستخدَمان منذ سنوات عند تنفيذ المصفوفة <code>‎$_POST</code> الخاصة بلغة PHP، لذا لا تحمّل لغة PHP حِمل طلب POST تلقائيًا مع أيّ نوع محتوى آخر حتى الأنواع التي تحظى بشعبية كبيرة اليوم مثل <code>application/json</code>.
</p>

<p>
	تُعَد المصفوفة <code>‎$_POST</code> ذات نطاق عام عالي Superglobal، لذا إذا عدّلناها مرة واحدة (ويُفضَّل أن يكون ذلك في وقت مبكر من السكربت)، فستكون القيمة المُعدَّلة (بما في ذلك حِمل طلب POST) قابلةً للإشارة إليها من شيفرتنا البرمجية. يُعَد ذلك أمرًا مهمًا، لأن أطر عمل PHP وجميع السكربتات المخصَّصة تقريبًا تستخدم المصفوفة <code>‎$_POST</code> استخدامًا شائعًا لاستخراج بيانات الطلب وتحويلها.
</p>

<p>
	نحتاج إلى تحليل محتويات الطلب يدويًا (أي فك تشفير بيانات JSON) وتعديل المتغير <code>‎$_POST</code> عند معالجة حِمل طلب POST مع نوع المحتوى <code>application/json</code> مثلًا كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_68" style=""><span class="com">// php</span><span class="pln">
$_POST </span><span class="pun">=</span><span class="pln"> json_decode</span><span class="pun">(</span><span class="pln">file_get_contents</span><span class="pun">(</span><span class="str">'php://input'</span><span class="pun">),</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">);</span></pre>

<p>
	إذا فرّغنا معلومات محتوى المصفوفة <code>‎$_POST</code> بعد ذلك، فسنرى أنها تتضمّن حِمل طلب POST الصحيح كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_70" style=""><span class="pln">array</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">[</span><span class="str">"a"</span><span class="pun">]=&gt;</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="str">"a"</span><span class="pln"> </span><span class="pun">[</span><span class="str">"b"</span><span class="pun">]=&gt;</span><span class="pln"> </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="str">"b"</span><span class="pln"> </span><span class="pun">}</span></pre>

<h2 id="8phpcharacter">
	الخطأ الشائع 8: الاعتقاد بأن لغة PHP تدعم نوع بيانات المحارف Character
</h2>

<p>
	اطّلع على الشيفرة البرمجية التالية وحاول تخمين ما سينتج:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_72" style=""><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$c </span><span class="pun">=</span><span class="pln"> </span><span class="str">'a'</span><span class="pun">;</span><span class="pln"> $c </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="str">'z'</span><span class="pun">;</span><span class="pln"> $c</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $c </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذا أجبت أنها ستطبع المحارف من 'a' إلى 'z'، فقد تتفاجأ عندما تعرف أنك مخطئ، حيث أنها ستطبع المحارف من 'a' إلى 'z'، ولكنها ستطبع أيضًا 'aa' إلى 'yz'، إذ لا يوجد نوع البيانات <code>char</code> في لغة PHP، بينما يوجد نوع بيانات السلاسل النصية <code>string</code> فقط، وبالتالي سينتج عن زيادة السلسلة النصية <code>z</code> بمقدار واحد في لغة PHP السلسلة النصية <code>aa</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_74" style=""><span class="pln">php</span><span class="pun">&gt;</span><span class="pln"> $c </span><span class="pun">=</span><span class="pln"> </span><span class="str">'z'</span><span class="pun">;</span><span class="pln"> echo </span><span class="pun">++</span><span class="pln">$c </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
aa</span></pre>

<p>
	ولكن تُعَد السلسلة النصية <code>aa</code> أصغر من <code>z</code> من معجميًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_76" style=""><span class="pln">php</span><span class="pun">&gt;</span><span class="pln"> var_export</span><span class="pun">((</span><span class="kwd">boolean</span><span class="pun">)(</span><span class="str">'aa'</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="str">'z'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">true</span></pre>

<p>
	لذلك تطبع الشيفرة البرمجية الحروف من <code>a</code> إلى <code>z</code>، ولكنها تطبع أيضًا بعد ذلك من <code>aa</code> إلى <code>yz</code>، وتتوقف عندما تصل إلى <code>za</code>، وهي القيمة الأولى الأكبر من <code>z</code> التي تصادفها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_78" style=""><span class="pln">php</span><span class="pun">&gt;</span><span class="pln"> var_export</span><span class="pun">((</span><span class="kwd">boolean</span><span class="pun">)(</span><span class="str">'za'</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="str">'z'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">false</span></pre>

<p>
	لذا استخدم الطريقة التالية للمرور ضمن حلقة على القيم من 'a' إلى 'z' في لغة PHP بصورة صحيحة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_80" style=""><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i </span><span class="pun">=</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">);</span><span class="pln"> $i </span><span class="pun">&lt;=</span><span class="pln"> ord</span><span class="pun">(</span><span class="str">'z'</span><span class="pun">);</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo chr</span><span class="pun">(</span><span class="pln">$i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</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_4442_82" style=""><span class="pln">$letters </span><span class="pun">=</span><span class="pln"> range</span><span class="pun">(</span><span class="str">'a'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'z'</span><span class="pun">);</span><span class="pln">

</span><span class="kwd">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"> count</span><span class="pun">(</span><span class="pln">$letters</span><span class="pun">);</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo $letters</span><span class="pun">[</span><span class="pln">$i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="9">
	الخطأ 9: تجاهل قواعد ومعايير كتابة الشيفرة البرمجية
</h2>

<p>
	لا يؤدي تجاهل <a href="https://academy.hsoub.com/programming/general/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D8%A8%D8%B3%D8%A7%D8%B7%D8%A9-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-r1870/" rel="">قواعد كتابة الشيفرة البرمجية</a> مباشرةً إلى الحاجة إلى تنقيح أخطاء شيفرة PHP، ولكنه لا يزال أحد أهم الأشياء التي يجب مناقشتها، إذ قد يؤدي تجاهل هذه المعايير إلى حدوث عدد كبير من المشكلات في المشروع مثل الحصول على شيفرة برمجية غير متناسقة في أحسن الأحوال لأن كل مطور ينجز عمله بطريقته الخاصة، أو الحصول على شيفرة PHP لا تعمل أو من الصعب -أو من المستحيل في بعض الأحيان- التنقل ضمنها، مما يصعّب تنقيح أخطائها وتحسينها وصيانتها في أسوأ الأحوال. يؤدي ذلك إلى تخفيض إنتاجية فريقك بما في ذلك الكثير من الجهد الضائع أو غير الضروري.
</p>

<p>
	توجد توصية لمعايير PHP أو PHP Standards Recommendation -أو PSR اختصارًا، والتي تتألف من المعايير الخمسة التالية:
</p>

<ul>
	<li>
		<a href="https://www.php-fig.org/psr/psr-0/" rel="external nofollow">PSR-0</a>: معيار التحميل التلقائي.
	</li>
	<li>
		<a href="https://www.php-fig.org/psr/psr-1/" rel="external nofollow">PSR-1</a>: معيار كتابة الشيفرة البرمجية الأساسي.
	</li>
	<li>
		<a href="https://www.php-fig.org/psr/psr-2/" rel="external nofollow">PSR-2</a>: دليل تنسيق كتابة الشيفرة البرمجية.
	</li>
	<li>
		<a href="https://www.php-fig.org/psr/psr-3/" rel="external nofollow">PSR-3</a>: واجهة المسجِّل.
	</li>
	<li>
		<a href="https://www.php-fig.org/psr/psr-4/" rel="external nofollow">PSR-4</a>: المحمِّل التلقائي.
	</li>
</ul>

<p>
	لقد أُنشِئت معايير PSR بناءً على مدخلات من المشرفين على المنصات الأشهر في السوق لتوفر إرشادات وممارسات موحدة لتنظيم كتابة الأكواد في PHP. وقد وُضعت هذه المعايير من قبل مجموعة من المطورين والمشرفين على أبرز المنصات <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> الشهيرة مثل Zend و <a href="https://academy.hsoub.com/apps/web/drupal/" rel="">Drupal</a> و Symfony و <a href="https://academy.hsoub.com/apps/web/%D8%AA%D8%B9%D9%84%D9%8A%D9%85-%D8%AC%D9%88%D9%85%D9%84%D8%A7-joomla-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D8%AE%D8%B7%D9%88%D8%A9-%D8%A8%D8%AE%D8%B7%D9%88%D8%A9-r901/" rel="">Joomla</a> وغيرها في هذه المعايير، وتتبع هذه المنصات تلك المعايير، ويشارك الآن إطار عمل PEAR الذي حاول أن يكون معيارًا لسنوات قبل ذلك في وضع معايير PSR.
</p>

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

<h2 id="10empty">
	الخطأ 10: استخدام الدالة empty()‎ استخدامًا خاطئًا
</h2>

<p>
	يفضِّل بعض مطوري PHP استخدام الدالة <code><a href="https://wiki.hsoub.com/PHP/empty" rel="external">empty()</a>‎</code> لإجراء عمليات فحص منطقية لكل شيء تقريبًا، ولكن توجد حالات يمكن أن يؤدي فيها ذلك إلى الارتباك.
</p>

<p>
	أولًا، إذا عُدنا إلى المصفوفات ونُسخ كائن المصفوفة <code>ArrayObject</code> (الذي يحاكي المصفوفات)، فمن السهل افتراض أن المصفوفات ونسخ الكائن <code>ArrayObject</code> ستتصرف بطريقة مماثلة بسبب تشابههما، ولكنه افتراض خطير كما هو موضّح فيما يلي في الإصدار PHP 5.0:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_89" style=""><span class="com">// ‫PHP 5.0 أو بعد‫:</span><span class="pln">
$array </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">empty</span><span class="pun">(</span><span class="pln">$array</span><span class="pun">));</span><span class="pln">        </span><span class="com">// ‫خرجها bool(true)‎ </span><span class="pln">
$array </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArrayObject</span><span class="pun">();</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">empty</span><span class="pun">(</span><span class="pln">$array</span><span class="pun">));</span><span class="pln">        </span><span class="com">// ‫خرجها bool(false)‎</span><span class="pln">
</span><span class="com">// لماذا لا ينتج كلاهما الخرج نفسه؟</span></pre>

<p>
	وستكون النتائج مختلفة في الإصدارات التي قبل الإصدار PHP 5.0:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_91" style=""><span class="com">//  الإصدارات التي قبل الإصدار‫ PHP 5.0:</span><span class="pln">
$array </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">empty</span><span class="pun">(</span><span class="pln">$array</span><span class="pun">));</span><span class="pln">        </span><span class="com">// ‫خرجها bool(false)‎ </span><span class="pln">
$array </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArrayObject</span><span class="pun">();</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">empty</span><span class="pun">(</span><span class="pln">$array</span><span class="pun">));</span><span class="pln">        </span><span class="com">// ‫خرجها bool(false)‎</span></pre>

<p>
	تحظى هذه الطريقة بشعبية كبيرة لسوء الحظ، فمثلًا هذه هي الطريقة التي يعيد بها كائن <code>Zend\Db\TableGateway</code> في إطار عمل Zend Framework 2 البيانات عند استدعاء الدالة <code>current()‎</code> مع نتيجة الدالة <code>TableGateway::select()‎</code>، ويمكن للمطور أن يصبح بسهولة ضحيةً لهذا الخطأ مع مثل هذه البيانات.
</p>

<p>
	يمكن تجنب هذه المشكلات من خلال التحقق من وجود بنى مصفوفات فارغة باستخدام الدالة <code><a href="https://wiki.hsoub.com/PHP/count" rel="external">count()‎</a></code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_94" style=""><span class="com">// ‫لاحظ أن ما يلي يعمل في جميع إصدارات PHP (سواء قبل أو بعد الإصدار 5.0):</span><span class="pln">
$array </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[];</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">count</span><span class="pun">(</span><span class="pln">$array</span><span class="pun">));</span><span class="pln">        </span><span class="com">// ‫خرجها int(0)‎</span><span class="pln">
$array </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ArrayObject</span><span class="pun">();</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">count</span><span class="pun">(</span><span class="pln">$array</span><span class="pun">));</span><span class="pln">        </span><span class="com">// ‫خرجها int(0)‎</span></pre>

<p>
	تحوّل لغة PHP القيمة <code>0</code> إلى <code>false</code>، فيمكن أيضًا استخدام الدالة <code>count()‎</code> ضمن شروط <a href="https://wiki.hsoub.com/PHP/if" rel="external">تعليمة if</a><code> </code>للتحقق من المصفوفات الفارغة. تجدر الإشارة أيضًا إلى أن الدالة ‎<code>count()‎</code>‎ في PHP لها <a href="https://academy.hsoub.com/programming/advanced/%D8%A7%D9%84%D8%AE%D9%88%D8%A7%D8%B1%D8%B2%D9%85%D9%8A%D8%A7%D8%AA/#algorithms-complexity" rel="">تعقيد ثابت Constant Complexity (أو O(1)‎)</a> على المصفوفات، مما يوضّح أنه الاختيار الصحيح.
</p>

<p>
	يوجد مثال آخر لذلك عندما تمثّل الدالة <code>empty()‎</code> خطرًا من خلال دمجها مع دالة الأصناف السحرية <code>‎__get()‎</code>. لنعرّف مثلًا صنفين Class مع وجود الخاصية <code>test</code> في كليهما، حيث نعرّف أولًا الصنف <code>Regular</code> الذي يتضمن الخاصية العادية <code>test</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_101" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Regular</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $test </span><span class="pun">=</span><span class="pln"> </span><span class="str">'value'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نعرّف بعد ذلك الصنف <code>Magic</code> الذي يستخدم <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-%D8%A7%D9%84%D8%B3%D8%AD%D8%B1%D9%8A%D8%A9-magic-methods-%D9%81%D9%8A-php-r1124/" rel="">التابع السحري</a> <code>‎__get()‎</code> للوصول إلى الخاصية <code>test</code> الخاصة به كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_103" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Magic</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $values </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'test'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'value'</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"> __get</span><span class="pun">(</span><span class="pln">$key</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">isset</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">values</span><span class="pun">[</span><span class="pln">$key</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">values</span><span class="pun">[</span><span class="pln">$key</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>test</code> لكل صنف كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_106" style=""><span class="pln">$regular </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Regular</span><span class="pun">();</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$regular</span><span class="pun">-&gt;</span><span class="pln">test</span><span class="pun">);</span><span class="pln">    </span><span class="com">// ‫خرجها string(4) "value"‎</span><span class="pln">
$magic </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Magic</span><span class="pun">();</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$magic</span><span class="pun">-&gt;</span><span class="pln">test</span><span class="pun">);</span><span class="pln">      </span><span class="com">// ‫خرجها string(4) "value"‎</span></pre>

<p>
	يبدو كل شيء على ما يرام حتى الآن، ولكن لنرى الآن ما يحدث عندما نستدعي الدالة <code>empty()‎</code> مع كل منهما كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_108" style=""><span class="pln">var_dump</span><span class="pun">(</span><span class="pln">empty</span><span class="pun">(</span><span class="pln">$regular</span><span class="pun">-&gt;</span><span class="pln">test</span><span class="pun">));</span><span class="pln">    </span><span class="com">// ‫خرجها bool(false)‎</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">empty</span><span class="pun">(</span><span class="pln">$magic</span><span class="pun">-&gt;</span><span class="pln">test</span><span class="pun">));</span><span class="pln">      </span><span class="com">// خرجها‫ bool(true)‎</span></pre>

<p>
	إذا اعتمدنا على الدالة <code>empty()‎</code>، فيمكن تضليلنا للاعتقاد بأن الخاصية <code>test</code> الخاصة بالصنف <code>‎$magic</code> فارغة، بينما هي مضبوطة على القيمة <code>'value'</code>.
</p>

<p>
	لسوء الحظ، إذا استخدم الصنفُ التابع السحري <code>‎__get()‎</code> لاسترداد قيمة خاصيةٍ ما، فلا توجد طريقة مضمونة للتحقق مما إذا كانت قيمة الخاصية فارغة أم لا. يمكنك خارج نطاق الصنف التحقق فقط من إعادة القيمة <code>null</code>، وهذا لا يعني بالضرورة عدم ضبط المفتاح المقابل، لأنه كان من الممكن ضبطه على القيمة <code>null</code>.
</p>

<p>
	إذا حاولنا الإشارة إلى خاصية غير موجودة لنسخة من الصنف <code>Regular</code>، فستظهر ملاحظة مشابهة لما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4442_110" style=""><span class="typ">Notice</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Undefined</span><span class="pln"> </span><span class="kwd">property</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Regular</span><span class="pun">::</span><span class="pln">$nonExistantTest </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">/</span><span class="pln">path</span><span class="pun">/</span><span class="pln">to</span><span class="pun">/</span><span class="pln">test</span><span class="pun">.</span><span class="pln">php on line </span><span class="lit">10</span><span class="pln">

</span><span class="typ">Call</span><span class="pln"> </span><span class="typ">Stack</span><span class="pun">:</span><span class="pln">
    </span><span class="lit">0.0012</span><span class="pln">     </span><span class="lit">234704</span><span class="pln">   </span><span class="lit">1.</span><span class="pln"> </span><span class="pun">{</span><span class="pln">main</span><span class="pun">}()</span><span class="pln"> </span><span class="pun">/</span><span class="pln">path</span><span class="pun">/</span><span class="pln">to</span><span class="pun">/</span><span class="pln">test</span><span class="pun">.</span><span class="pln">php</span><span class="pun">:</span><span class="lit">0</span></pre>

<p>
	لاحظ أنه يجب استخدام التابع <code>empty()‎</code> بحذر لأنه قد يؤدي إلى نتائج مربكة ومضللة.
</p>

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

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

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

<p>
	ترجمة -وبتصرُّف- للمقال <a href="https://www.toptal.com/php/10-most-common-mistakes-php-programmers-make" rel="external nofollow">Buggy PHP Code: The 10 Most Common Mistakes PHP Developers Make</a> لصاحبه Ilya Sanosian.
</p>

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

<ul>
	<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>
	<li>
		<a href="https://academy.hsoub.com/php/" rel="">تعلم لغة PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%88%D8%A7%D8%B6%D9%8A%D8%B9-%D9%85%D8%AA%D9%81%D8%B1%D9%82%D8%A9-%D9%85%D9%87%D9%85%D8%A9-%D9%84%D9%83%D9%84-%D9%85%D8%A8%D8%B1%D9%85%D8%AC-php-r1177/" rel="">اصطلاحات ومواضيع متفرقة مهمة لكل مبرمج PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-php-r1202/" rel="">التعامل مع الأخطاء في PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D8%B9%D8%B4%D8%B1%D8%A9-%D8%A7%D9%84%D8%A3%D9%83%D8%AB%D8%B1-%D8%B4%D9%8A%D9%88%D8%B9%D9%8B%D8%A7-%D9%81%D9%8A-%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-python-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r2429/" rel="">الأخطاء العشرة الأكثر شيوعًا في شيفرة بايثون Python البرمجية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2434</guid><pubDate>Mon, 21 Oct 2024 15:01:01 +0000</pubDate></item><item><title>&#x62A;&#x639;&#x631;&#x641; &#x639;&#x644;&#x649; &#x644;&#x63A;&#x629; PHP</title><link>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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_08/learn-php-for-beginners.png.9334f34e1fe8704f2f21b1287321cfd6.png" /></p>
<p>
	في مقال اليوم سوف نكتشف معًا لغة PHP بدءًا من التعرف على ماهية لغة PHP وطريقة عملها وأبرز مميزاتها وخطوات تعلمها وصولًا لكتابة البرنامج الأول باستخدامها. فسواء كانت لديك خبرة مسبقة في إحدى لغات البرمجة أو كنت مبتدئًا و<a href="https://academy.hsoub.com/learn-programming/" rel="">تتعلم البرمجة</a> للتو فإن هذا الدليل بمثابة نقطة انطلاق رئيسية في رحلة تعلم لغة PHP.
</p>

<h2>
	ما هي لغة PHP؟
</h2>

<p>
	<a href="https://wiki.hsoub.com/PHP" rel="external">لغة PHP</a> هي لغة برمجة قوية مفتوحة المصدر طورها المبرمج الدنماركي راسموس ليردورف عام 1994 ويأتي اسمها من اختصار عبارة PHP: Hypertext Preprocessor وهي <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%85%D9%86-%D8%B7%D8%B1%D9%81-%D8%A7%D9%84%D8%AE%D8%A7%D8%AF%D9%85-r783/" rel="">لغة برمجة تعمل من طرف الخادم</a> Server-side وهذا يعني أن كل الشيفرات البرمجية المكتوبة بهذه اللغة لن تنفذ على جهاز الحاسوب المحلي الخاص بالمستخدم والذي يسمى العميل Client بل تنفذ على جهاز حاسوب بعيد يسمى الخادم Server يخزن صفحات موقع الويب المكتوبة بلغة PHP ويرسلها للمستخدم عند الطلب.
</p>

<p>
	تطورت لغة PHP بشكل كبير منذ إطلاقها لأول مرة وهي تتحسن باستمرار وتضاف لها الكثير من الميزات مع كل إصدار، -أحدث إصدار PHP لحظة كتابة هذا المقال هو PHP is 8.2 الصادر في مايو 2023- وهي اليوم واحدة من أشهر لغات البرمجة المستخدمة في تطوير مواقع وتطبيقات الويب الديناميكية فما يزيد عن 77% من مواقع الإنترنت بحسب <a href="https://w3techs.com/technologies/details/pl-php" rel="external nofollow">W3tech</a> تستخدم لغة PHP، وتستخدمها شركات كبرى في تطوير مواقعها مثل شبكة التواصل الاجتماعي الشهيرة فيسبوك وويكيبيديا وجامعة هارفارد مما يدل على مدى قوتها ويعزز مصداقيتها.
</p>

<h2>
	مصطلحات أساسية تحتاجها قبل تعلم PHP
</h2>

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

<p>
	<strong>موقع الويب Website</strong>: هو عبارة عن مجموعة من الصفحات الإلكترونية المرتبطة مع بعضها البعض والتي تتضمن محتوى مختلف كالنصوص والروابط والصور وغيرها. ويتكون أي موقع إلكتروني من واجهة أمامية تشمل كل ما تراه على الموقع وتتفاعل معه من صور ونصوص وأزرار وواجهة خلفية مخفية تكون مسؤولة عن تخزين بيانات الموقع واستردادها وعرضها وهي التي تجعل الموقع يعمل بشكل صحيح، يمكن استخدام عدة لغات في <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8/" rel="">برمجة مواقع الويب</a>، وبعد الانتهاء من برمجته تخزن كافة ملفاته على استضافة أو بمعنى أدق على خوادم الويب التي توفرها الاستضافة وبهذا يمكن الوصول إليه من قبل المستخدمين وعرضه باستخدام متصفحات الإنترنت.
</p>

<p>
	<strong>المتصفح Browser</strong>: هو برنامج أو تطبيق مثبت على جهاز المستخدم (العميل) يستخدم لتصفح الإنترنت وعرض صفحات الويب، فهو المسؤول عن إرسال طلب عرض صفحات الويب إلى الخادم من خلال كتابة <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>خادم الويب Server</strong>: هو عبارة عن جهاز حاسوب بمواصفات خاصة يخزن محتوى مواقع الويب ويكون مسؤولًا عن تشغيلها وعرضها عند الطلب، توجد أنواع عديدة من خوادم الويب مثل خادم <a href="https://academy.hsoub.com/devops/servers/web/apache/%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-apache-r407/" rel="">Apache</a> و <a href="https://academy.hsoub.com/devops/servers/web/nginx/%D8%AA%D9%86%D8%B5%D9%8A%D8%A8%D8%8C-%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D9%88%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-nginx-%D9%83%D8%AE%D8%A7%D8%AF%D9%88%D9%85-%D9%88%D9%8A%D8%A8-r1/" rel="">Nginx</a> وخادم IIS من مايكروسوفت.
</p>

<p>
	<strong>بروتوكولات الإنترنت Internet protocols: </strong>هي آلية تسمح بنقل البيانات عبر الإنترنت وأشهرها <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> المستخدم لتبادل البيانات بين المتصفح والخادم والذي يعتبر بمثابة لغة يستخدمها المتصفح والخادم للتواصل مع بعضهما لعرض صفحات الويب عبر الإنترنت، وبروتوكول HTTPS الآمن الذي يشفر البيانات قبل نقلها.
</p>

<p>
	كانت هذه أهم المصطلحات التي تحتاج لمعرفتها قبل البدء بتعلم أساسيات لغة PHP، ولمزيد من التفاصيل حول آلية عمل الويب أنصح بمطالعة مقال <a href="https://academy.hsoub.com/devops/servers/%D8%A7%D9%84%D9%81%D8%B1%D9%82-%D8%A8%D9%8A%D9%86-%D8%B5%D9%81%D8%AD%D8%A9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%88%D9%85%D9%88%D9%82%D8%B9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%88%D8%AE%D8%A7%D8%AF%D9%85-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%88%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D8%A8%D8%AD%D8%AB-r572/" rel="">الفرق بين صفحة الويب وموقع الويب وخادم الويب ومحرك البحث</a> ومقال <a href="https://academy.hsoub.com/devops/networking/%D8%A2%D9%84%D9%8A%D8%A9-%D8%B9%D9%85%D9%84-%D8%B4%D8%A8%D9%83%D8%A9-%D8%A7%D9%84%D8%A5%D9%86%D8%AA%D8%B1%D9%86%D8%AA-r571/" rel="">آلية عمل شبكة الانترنت</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>
	كيفية عمل لغة PHP
</h2>

<p>
	PHP هي <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%85%D9%86-%D8%B7%D8%B1%D9%81-%D8%A7%D9%84%D8%AE%D8%A7%D8%AF%D9%85-r783/" rel="">لغة برمجة تعمل من طرف الخادم</a> كما ذكرنا مسبقًا، لذا تحتاج لفهم آلية عمل الخادم نفسه كي تفهم طريقة عرض صفحات الويب المكتوبة بلغة PHP، بداية يجب أن يملك الخادم تطبيقًا خاصًا قادرًا على فهم ومعالجة أكواد PHP يسمى هذا التطبيق PHP interpreter، أما من طرف العميل فيجب توفر متصفح ويب واتصال بالإنترنت.
</p>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="132276" href="https://academy.hsoub.com/uploads/monthly_2023_08/how-php-works.png.ba3e4b89033728c579d35bb25ab5e9db.png" rel=""><img alt="how-php-works.png" class="ipsImage ipsImage_thumbnailed" data-fileid="132276" data-ratio="56.29" data-unique="dnkyx6s6t" style="width: 700px; height: auto;" width="900" src="https://academy.hsoub.com/uploads/monthly_2023_08/how-php-works.thumb.png.456eae67aca166c5645a40baf6aee98c.png"></a>
</p>

<p>
	كما تلاحظ من الصورة أعلاه تتم معالجة طلب العميل بالطريقة التالية:
</p>

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

<h2>
	ما استخدامات PHP؟
</h2>

<p>
	قد تتساءل ما الذي يمكنني عمله عند تعلم لغة PHP؟ في الواقع يمكن من خلال تعلم لغة PHP إنجاز العديد من المهام ومن بينها:
</p>

<ul>
	<li>
		تطوير مختلف أنواع المواقع وتطبيقات الويب الديناميكية بدءًا من المدونات البسيطة وصولًا للمتاجر الإلكترونية الضخمة.
	</li>
	<li>
		أتمتة المهام المتكررة مثل تحميل بيانات من الإنترنت أو تنفيذ كود معين دوريًا كأخذ نسخة احتياطية من البيانات أو غيرها من المهام.
	</li>
	<li>
		إدارة الخوادم ومعالجة الملفات المخزنة عليها.
	</li>
	<li>
		التحقق من صحة بيانات نماذج الويب <a href="https://academy.hsoub.com/programming/html/%D8%A7%D9%84%D9%86%D9%85%D8%A7%D8%B0%D8%AC-forms-%D9%81%D9%8A-html5-r370/" rel="">forms </a>ومعالجتها وتخزينها.
	</li>
	<li>
		إدارة البيانات المخزنة في قاعدة بيانات الموقع.
	</li>
	<li>
		تشفير البيانات وحمايتها أثناء النقل أو التخزين من وإلى الخادم.
	</li>
	<li>
		تطوير مواقع متعددة المستخدمين وضبط صلاحيات وصول كل مستخدم لمتحوى محدد من الموقع.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D8%B1%D8%B3%D8%A7%D9%84-%D8%A8%D8%B1%D9%8A%D8%AF-%D8%A5%D9%84%D9%83%D8%AA%D8%B1%D9%88%D9%86%D9%8A-%D9%81%D9%8A-php-r1174/" rel="">إرسال رسائل البريد الإلكتروني</a> بسهولة بفضل ما توفره من مكتبات خاصة بالبريد الإلكتروني.
	</li>
</ul>
<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			أنشئ موقع احترافي لأعمالك وعزّز حضورك الرقمي
		</p>

		<p class="banner-subtitle">
			صمم موقع إلكتروني فريد وجذاب لعملائك في دقائق دون خبرة برمجية باستخدام سنديان منشئ المواقع العربي
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://sndian.com/?utm_source=academy.hsoub.com&amp;utm_medium=referral&amp;utm_campaign=cademy.hsoub.com-CTA-Block" rel="external">أطلق موقعك الآن</a>
		</div>
	</div>
</div>



<h2>
	إيجابيات وسلبيات PHP
</h2>

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

<h2>
	إيجابيات لغة PHP
</h2>

<p>
	فيما يلي قائمة بأبرز المميزات والفوائد التي تتميز بها لغة PHP:
</p>

<ul>
	<li>
		بسيطة وسهلة التعلم للمبتدئين.
	</li>
	<li>
		لغة حرة ومفتوحة المصدر.
	</li>
	<li>
		توفر مجتمع دعم كبير جاهز لمساعدتك في حال واجهتك أي مشكلة.
	</li>
	<li>
		سريعة ومع كل إصدار جديد تصبح PHP أسرع من ذي قبل.
	</li>
	<li>
		مليئة بالميزات الرائعة التي تجعلها من اللغات القوية المنافسة للغات الأخرى مثل بايثون أو جافا، خصوصًا في الإصدارات الحديثة مثل PHP 8.
	</li>
	<li>
		تصلح لتطوير كافة أنواع المواقع بدءًا من المدونات البسيطة وصولًا للمتاجر الإلكترونية الضخمة.
	</li>
	<li>
		متوافقة مع كل خوادم الويب وأنظمة التشغيل.
	</li>
	<li>
		متوافقة مع جميع <a href="https://academy.hsoub.com/devops/servers/databases/%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%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/" rel="">أنواع قواعد البيانات</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="">أطر العمل</a> مثل لارافيل Laravel وكود إغنيتر CodeIgniter التي تسهل عمل المطورين وتسرع عملهم.
	</li>
	<li>
		تستخدم في تطوير أشهر أنظمة إدارة المحتوى CMS مثل ووردبريس <a href="https://academy.hsoub.com/apps/web/wordpress/%D8%AF%D9%84%D9%8A%D9%84-%D8%AA%D8%B9%D9%84%D9%85-%D9%88%D9%88%D8%B1%D8%AF%D8%A8%D8%B1%D9%8A%D8%B3-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-r788/" rel="">WordPress</a> ودروبال <a href="https://academy.hsoub.com/apps/web/drupal/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AF%D8%B1%D9%88%D8%A8%D8%A7%D9%84-drupal-9-r669/" rel="">Drupal</a>.
	</li>
</ul>

<h2>
	 سلبيات لغة PHP
</h2>

<p>
	فيما يلي قائمة ببعض الجوانب السلبية التي تؤخذ على لغة PHP:
</p>

<ul>
	<li>
		لغة PHP لغة مخصصة بتطوير الواجهات الخلفية لمواقع الويب، وصحيح أنك تستطيع تطوير تطبيقات عامة بسيطة، لكن هنالك لغات أفضل منها تسهل عليك العمل في مجالات عامة مثل تطوير تطبيقات سطح المكتب أو التعامل مع مكتبات تعلم الآلة.
	</li>
	<li>
		لا تناسب لغة PHP تطوير الواجهات الأمامية لمواقع الويب لذا تحتاج لتعلم لغات وتقنيات أخرى في حال رغبت في العمل كمطور ويب كامل Full-stack developer.
	</li>
	<li>
		بالرغم من كون لغة PHP آمنة إلا أن كونها لغة شائعة الاستخدام ومفتوحة المصدر يشجع على استغلالها قبل المخترقين الذين يستغلون أي ثغرات أمنية تؤثر على تطبيقات PHP لتنفيذ الهجمات على المواقع، لذا من المهم إبقاء مواقعك محدثة إلى آخر الإصدارات من PHP.
	</li>
	<li>
		تعد من اللغات ضعيفة التنميط weakly-typed بمعنى أنك قادر على تخزين رقم في متغير ما ثم تخزين نص في نفس المتغير وهذا الأمر يجعل اللغة أكثر مرونة لكنه قد يسبب أخطاء غير متوقعة في التطبيقات. أضافت الإصدارات الحديثة بدءًا من PHP 7 إمكانية تحديد أنواع المتغيرات والقيم الممررة إلى الدوال والمعادة منها، يمكن للمطورين الاستفادة من هذه الميزات لتحسين تطبيقاتهم الجديدة.
	</li>
</ul>

<h2>
	ما الفرق بين PHP و Laravel؟
</h2>

<p style="text-align: center;">
	<img alt="php-vs-laravel.png" class="ipsImage ipsImage_thumbnailed" data-fileid="132273" data-unique="f2iolgc8e" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2023_08/php-vs-laravel.thumb.png.2add4392be66d951367e1d31b4e5dc51.png">
</p>

<p>
	الجواب باختصار هو أن PHP هي لغة برمجة أما <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="">لارافيل Laravel</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، بمعنى آخر تعد PHP لغة برمجة لتطوير تطبيقات الويب الديناميكة من طرف الخادم وباستخدامها ستكون مسؤولًا عن كتابة كامل الشيفرات البرمجية لتحقيق كافة وظائف الموقع مثل أكواد الاتصال مع قواعد البيانات والتحقق من هوية المستخدم وغيرها من المهام من الصفر.
</p>

<p>
	أما لارافيل Laravel فهو إطار عمل مفتوح المصدر مبني باستخدام لغة PHP يسهل عليك عملية تطوير مواقع وتطبيقات الويب بشكل كبير فهو يوفر الكثير من المكونات والحزم الجاهزة التي يمكنك استخدامها لتسريع عملك بدلًا من كتابة كل شيء من الصفر، فمن خلال استخدام لارافيل لن تحتاج على سبيل المثال إلى كتابة أكواد طويلة ومفصلة للتحقق من هوية المستخدم فهو يوفر نظام مصادقة مدمج كما يوفر واجهات برمجية سهلة للاتصال بسهولة مع قواعد البيانات والتفاعل معها.
</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="">تعرف على مفهوم إطار العمل Framework وأهميته في البرمجة</a>.
</p>

<h2>
	كتابة أول برنامج PHP
</h2>

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

<ol>
	<li>
		استخدام أحد برامج تحرير النصوص لكتابة أكواد PHP، يمكنك استخدام أي محرر بسيط كالمفكرة أو أو اعتماد محرر أكواد مخصص مثل فيجوال ستوديو كود VSCode أو ++Notepad أو أي محرر مناسب يساعدك على كتابة الشيفرات البرمجية للغة PHP بسرعة وكفاءة.
	</li>
	<li>
		تثبيت محرك للغة PHP Engine على حاسوبك لتشغيل شيفرات PHP.
	</li>
	<li>
		تثبيت برنامج خادم مثل أباتشي Apache ليحول حاسوبك إلى <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> قادر على معالجة طلبات عرض الصفحات.
	</li>
	<li>
		تثبيت برنامج مخصص لإدارة قواعد البيانات باستخدام لغة مثل MySQL لإنشاء قاعدة بيانات الموقع وتخزين المعلومات بشكل دائم وعرضها عند الطلب.
	</li>
	<li>
		يمكنك بدلًا من تثبيت البرامج الثلاثة الأخيرة الاعتماد على بيئة تطوير محليةمتكاملة مثل XAMPP المتوافق مع كافة أنظمة التشغيل أو WAMP المخصص لأنظمة ويندوز أو MAMP المخصص لأنظمة تشغيل ماك والتي تمكنك من تشغيل البرامج المكتوبة بلغة PHP بكل سهولة، حيث ستوفر لك بيئة التطوير البرامج مفسر للغة البرمجة PHP وخادم أباتشي محلي وقاعدة بيانات MySQL وتجمعها في حزمة واحدة، يمكنك مطالعة المزيد من التفاصيل حول تثبيت بيئة تطوير PHP على مختلف أنظمة التشغيل من خلال مقال <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>.
	</li>
</ol>

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

<p>
	تكتب ملفات PHP ضمن المجلد الجذر للخادم لتمكين الوصول لها من قبل المتصفح، وهذا المجلد يختلف من تطبيق لآخر على سبيل المثال في حال تثبيت الخادم XAMPP في المسار C:\xampp ستجد المجلد في المسار C:\xampp\htdocs وفي حال كنت تستخدم WAMP سيكون اسم المجلد الجذر هو www، انتقل للمجلد الجذر لخادمك وأنشئ ضمنه مجلد بأي اسم تختاره وليكن learnphp ضمن هذا المجلد ستضع كافة ملفات PHP الخاصة بموقعك.
</p>

<p>
	أنشئ ضمن هذا المجلد ملف باسم helloworld.php وحرره باستخدام محرر النصوص المفضل لديك واكتب بداخله الكود التالي:
</p>

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

echo </span><span class="str">"Hello World!&lt;br&gt;"</span><span class="pun">;</span><span class="pln">

echo </span><span class="str">"هذا هو البرنامج الأول في تعلم لغة بي إتش بي"</span><span class="pun">;</span></pre>

<p>
	كما تلاحظ في الكود أعلاه تكتب أكواد PHP عادة بين الوسمين <code>‎&lt;?‎php</code> و <code>‎?&gt;‎</code> لكن انتبه لأن كتابة وسم إغلاق PHP الأخير <code>‎?&gt;‎</code> في حال كان موقعه في نهاية الملف هو أمر اختياري، وينصح بحذفه لتجنب قيام محرر النصوص بإلحاق حرف خاص مخفي بعد هذا العلامة ويتسبب بعرض فراغات أو رموز غير مقصودة بعد وسم إغلاق PHP
</p>

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

<pre class="ipsCode">http://localhost/learnphp/helloworld.php
أو
http://127.0.0.1/learnphp/helloworld.php
</pre>

<p>
	الآن اضغط على مفتاح Enter للانتقال للعنوان المطلوب، ستظهر لك النتيجة بالشكل التالي
</p>

<p style="text-align: center;">
	<img alt="تشغيل-كود-php.png" class="ipsImage ipsImage_thumbnailed" data-fileid="132274" data-unique="hyhrqagsv" style="width: 800px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2023_08/--php.thumb.png.48e3c74a78ce98d82f23c3d4ac6a7b1f.png">
</p>

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

<p>
	على سبيل المثال دعنا نعدل كود الملف السابق وندمج كود PHP مع كود HTML كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8459_11" style=""><span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">

</span><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">PHP and HTML</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">

      </span><span class="pun">&lt;?</span><span class="pln">php

      echo </span><span class="str">"Hello World!&lt;br&gt;"</span><span class="pun">;</span><span class="pln">

      echo </span><span class="str">"هذا هو البرنامج الأول في تعلم لغة بي إتش بي"</span><span class="pun">;</span><span class="pln">

      </span><span class="pun">?&gt;</span><span class="pln">

    </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>
	عندما تتم معالجة كود PHP أعلاه من قبل الخادم سينشئ الخادم صفحة HTML مع تضمين المحتوى الديناميكي بداخلها ويرسل HTML الذي تم إنشاؤه إلى متصفح الويب الخاص بالمستخدم لعرض النتيجة النهائية كما في الصورة التالية:
</p>

<p style="text-align: center;">
	<img alt="دمج-كود-html-مع-php.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="132275" data-unique="5wlfzkd0u" style="width: 800px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2023_08/--html--php.PNG.05bf0745a81ae212a08391fc7b1664a8.PNG">
</p>

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

<h2>
	كيفية تعلم لغة برمجة PHP
</h2>

<p>
	قبل أن تقرر البدء بتعلم لغة برمجة PHP يجب عليك أن تمتلك معرفة أساسية بلغات الويب الأساسية HTML و CSS وجافا سكريبت JavaScript التي تعمل من طرف العميل لأن هذه اللغات كما ذكرنا مسبقًا تدمج مع أكواد PHP، بعدها يمكن أن تباشر رحلة تعلم لغة PHP من خلال اتباع الخطوات التالية:
</p>

<ul>
	<li>
		تعرف على طريقة تحويل حاسوبك المحلي إلى خادم وكيفية تثبيت PHP عليه وطريقة كتابة أكواد PHP وتنفيذها.
	</li>
	<li>
		تعلم ما هي <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AB%D9%88%D8%A7%D8%A8%D8%AA-%D9%81%D9%8A-php-r1040/" rel="">الثوابت والمتغيرات في PHP</a> ومتى نستخدم كل منها.
	</li>
	<li>
		تعرف على <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> مثل البيانات الرقمية والنصية والمنطقية.
	</li>
	<li>
		تعرف على طريقة <a href="https://academy.hsoub.com/programming/php/%D8%B7%D8%A8%D8%A7%D8%B9%D8%A9-%D8%A7%D9%84%D9%82%D9%8A%D9%85-%D9%88%D8%B9%D8%B1%D8%B6%D9%87%D8%A7-%D9%81%D9%8A-php-r1042/" rel="">طباعة قيم المتغيرات</a> في PHP.
	</li>
	<li>
		تعرف على <a href="https://academy.hsoub.com/programming/php/%D8%A3%D9%87%D9%85-%D8%A7%D9%84%D8%B9%D9%88%D8%A7%D9%85%D9%84-operators-%D8%A7%D9%84%D9%85%D9%88%D8%AC%D9%88%D8%AF%D8%A9-%D9%81%D9%8A-php-r1043/" rel="">المعاملات Operators في PHP</a> وأنواعها المختلفة وأولوية تنفيذها.
	</li>
	<li>
		تعرف على <a href="https://academy.hsoub.com/programming/php/%D8%A8%D9%86%D9%89-%D8%A7%D9%84%D8%AA%D8%AD%D9%83%D9%85-%D9%88%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-%D9%81%D9%8A-php-r1048/" rel="">بنى التحكم والحلقات التكرارية في PHP</a> وكيف تساعدك على التحكم في سير تنفيذ الأكواد البرمجية.
	</li>
	<li>
		تعرف على مفهوم <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="">الدوال في PHP</a> وما هي أهم الدوال المدمجة في PHP وكيف تكتب دوال مخصصة واستدعاءها في الكود.
	</li>
	<li>
		تعرف على بنى معطيات أكثر تقدمًا مثل <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-arrays-%D9%81%D9%8A-php-r1045/" rel="">المصفوفات</a> و<a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-arrays-%D9%88%D8%AD%D9%84%D9%82%D8%A9-foreach-%D9%81%D9%8A-php-r294/" rel="">المصفوفات الترابطية</a> وكيفية التعامل معها واستخدامها في تطبيقات عملية.
	</li>
	<li>
		تعلم كيفية معالجة نماذج HTML باستخدام لغة PHP والتحقق من صحة بياناتها وطريقة تخزينها في قواعد البيانات.
	</li>
	<li>
		تعلم طريقة التعامل مع <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AC%D9%84%D8%B3%D8%A7%D8%AA-%D9%88%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7-%D9%88%D9%85%D9%83%D8%AA%D8%A8%D8%A9-curl-%D9%81%D9%8A-php-r1081/" rel="">الجلسات وملفات تعريف الارتباط في PHP</a>.
	</li>
	<li>
		كيف تستخدم <a href="https://academy.hsoub.com/programming/php/%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-php-mysqli-%D9%88%D9%86%D8%B8%D8%A7%D9%85-%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-sqlite3-r1131/" rel="">قواعد البيانات في PHP</a>.
	</li>
	<li>
		تعلم <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> في PHP</a> وكيفية إنشاء الأصناف والكائنات البرمجية.
	</li>
	<li>
		تعرف على مفهوم إدارة الحزم والمكتبات وطريقة إدارتها باستخدام <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</a>.
	</li>
	<li>
		ابدأ بتطوير مواقع ويب بسيطة متكاملة تتضمن عدة صفحات ولوحة تحكم باستخدام PHP مع قواعد البيانات MySQL.
	</li>
	<li>
		تعلم طريقة مفهوم واجهة برمجة تطبيقات وكيف تنشئ واجهة REST بسيطة تمكنك من ربط تطبيقات PHP الخاصة بك بخدمات وأنظمة أخرى.
	</li>
	<li>
		تعلم طريقة تطوير التطبيقات باستخدام نموذج التصميم MVC وكيفية استخدام أحد أطر عمل PHP التي تتبع هذا النموذج مثل مثل لارافيل Laravel وكود إغنيتر CodeIgniter وابدأ بتطوير مواقع وتطبيقات احترافية باستخدامه.
	</li>
	<li>
		طور مهاراتك باستمرار وتعلم كيف تحسن الكود البرمجي وتتتبع أفضل الممارسات البرمجية لتنتج تطبيقات آمنة وعالية الجودة.
	</li>
</ul>

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

<h2>
	مصادر تعلم لغة PHP
</h2>

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

<p>
	لكن كثرة المصادر وتنوعها على أهميته إلا أنه قد يصيبك بالتشتت لذا إذا كنت تبحث عن مصدر واحد يوفر لك كل ما تحتاجه لتعلم لغة PHP ودخول سوق العمل فيمكنك الاطلاع على <a href="https://academy.hsoub.com/learn/php-web-application-development/" rel="">دورة تطوير تطبيقات الويب باستخدام لغة PHP</a> من أكاديمية حسوب التي توفر لك محتوى فيديو غني يبدأ معك من أساسيات PHP وينتهي بك بتطوير مواقع احترافية بأشهر أطر عملها لارافيل Laravel وأشهر نظام إدارة المحتوى ووردبريس WordPress، تتوزع الدورة على أكثر من 10 مسارات شاملة ومتنوعة تعلمك كل ما تحتاجه لتدخل سوق العمل بزمن قياسي، فهي تركز على التطبيق العملي إلى جانب الشرح النظري كما توفر لك فريقًا من المدربين يتابعك طيلة فترة التعلم ويجيب على أي تساؤل أو مشكلة تعترضك، أضف إلى ذلك ستحصل في نهاية الدورة على شهادة معتمدة من أكاديمية حسوب تضاف إلى سيرتك الذاتية وتعزز فرصتك في سوق العمل.
</p>

<p>
	كما يمكنك الاطلاع على <a href="https://wiki.hsoub.com/PHP" rel="external">توثيق PHP في موسوعة حسوب</a> التي توفر لك شرحًا متكاملًا باللغة العربية يعرفك على ماهية لغة PHP وأهم مميزاتها ويشرح لك كل ما يتعلق باللغة وكتابة شيفراتها البرمجية بدءًا من تعلم المتغيرات وأنواع البيانات والشروط والحلقات وصولًا للمواضيع البرمجية المتقدمة.
</p>

<p>
	هل تريد المزيد، ستجد في أكاديمية حسوب الكثير من <a href="https://academy.hsoub.com/programming/php/" rel="">الدروس والمقالات</a> والسلاسل التعلمية المتكاملة حول PHP إلى جانب <a href="https://academy.hsoub.com/files/" rel="">كتب البرمجة</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_540_6" src="https://academy.hsoub.com/applications/core/interface/index.html" title="لغة البرمجة PHP" width="800" data-embed-src="https://www.youtube.com/embed/HLQ194A9KOo"></iframe>
</p>

<h2>
	الخلاصة
</h2>

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

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

<ul>
	<li>
		<a href="https://academy.hsoub.com/php/" rel="">تعلم PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD%D8%A7%D8%AA-%D9%88%D9%85%D9%88%D8%A7%D8%B6%D9%8A%D8%B9-%D9%85%D8%AA%D9%81%D8%B1%D9%82%D8%A9-%D9%85%D9%87%D9%85%D8%A9-%D9%84%D9%83%D9%84-%D9%85%D8%A8%D8%B1%D9%85%D8%AC-php-r1177/" rel="">اصطلاحات ومواضيع متفرقة مهمة لكل مبرمج PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-php-r1202/" rel="">التعامل مع الأخطاء في PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D9%85%D9%85%D8%A7%D8%B1%D8%B3%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D9%85%D9%86-%D9%88%D8%A7%D9%84%D8%AD%D9%85%D8%A7%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-php-r1205/" rel="">ممارسات الأمن والحماية في تطبيقات PHP</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%A3%D9%88%D9%91%D9%84-r363/" rel="">دليل مطوّري PHP للبدء في بناء تطبيقات Laravel</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2040</guid><pubDate>Fri, 04 Aug 2023 16:00:00 +0000</pubDate></item><item><title>&#x62A;&#x637;&#x648;&#x64A;&#x631; &#x62A;&#x637;&#x628;&#x64A;&#x642; '&#x648;&#x635;&#x641;&#x629;' &#x644;&#x627;&#x642;&#x62A;&#x631;&#x627;&#x62D; &#x627;&#x644;&#x648;&#x62C;&#x628;&#x627;&#x62A; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; ChatGPT &#x648; DALL-E &#x641;&#x64A; PHP</title><link>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/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_06/------ChatGPT--DALLE--PHP.png.0d0bd4d529f2c05871dd5510dc2b051e.png" /></p>
<p>
	كثيرًا ما نحتار في اختيار وجبة طعام اليوم لتحضيرها، أو قد تتوفر لدينا بعض المكونات التي نريد تحضير وصفة ما منها ونحتار في اختيار الوصفة المناسبة، فيمكننا البحث عبر الإنترنت عن وصفات معينة واختيار الأنسب منها، لكن ماذا لو استطاع الذكاء الاصطناعي اختيار الوجبة لنا ووصف طريقة تحضيرها بل وحتى تخيل شكل الطبق النهائي، ففي هذا المقال سنستفيد من قدرات الذكاء الاصطناعي في فهم اللغة الطبيعية وقدرته على توليد المحتوى النصي والبصري لبناء تطبيق نُخبره بالمكونات الموجودة لدينا ومن أي مطبخ نُفضل أن تكون الوصفة وسيقترح لنا وصفة مناسبة مع شرح طريقة تحضيرها، حيث سنستخدم لتطويره لغة PHP وبعض نماذج الذكاء الاصطناعي التي توفرها شركة OpenAI.
</p>

<h2>
	نماذج الذكاء الاصطناعي واستخداماتها
</h2>

<p>
	تتميز <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%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/" rel="">نماذج الذكاء الاصطناعي</a> بسرعة معالجة وتحليل المعلومات والطيف الواسع من القدرات الكامنة ضمنها، حيث يمكن للنموذج بعد تدريبه تكوين فهمًا جيدًا عن البيانات وبالتالي يستطيع توليد أو التعامل مع بيانات جديدة لم يراها سابقًا، فمثلًا نموذج GPT (اختصارًا لعبارة المحول التوليدي مسبق التدريب Generative Pre-Trained Transformer) المطور من قبل شركة <a href="https://openai.com/" rel="external nofollow">OpenAI</a> دُرّب على كمية كبيرة من البيانات النصية فكون فهم جيد عن اللغات البشرية بدءًا من صياغتها إلى تراكيب الجمل وصولًا إلى المعنى وراء النص، فأصبح بإمكانه إكمال كتابة النصوص كما لو كان من كتبها إنسان وهي وظيفته الأساسية، ونموذج <a href="https://openai.com/dall-e" rel="external nofollow">DALL-E</a> المطور من قبل نفس الشركة تم تدريبه على كمية كبيرة من الصور وتوصيفاتها فتكون ضمنه فهم وربط بين النصوص ومحتوى الصور، وبذلك أصبح قادرًا على توليد صور أقرب ما تكون إلى الطبيعية بناءً على توصيف نصي لها.
</p>

<p>
	في هذا المقال سنحاول حل مشكلة الحيرة في اختيار وجبة الطعام عبر تطوير تطبيق لاقتراح الوصفات باستخدام <a href="https://academy.hsoub.com/php/" rel="">لغة البرمجة PHP</a>، وسنستفيد من النموذج <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> في اقتراح الوصفة على المستخدم بحسب ما يريد وشرح طريقة تحضيرها، ومن النموذج DALL-E لتوليد صورة تخيلية لطبق من تلك الوصفة، أي سيكون محتوى التطبيق مولّد بالكامل من قبل نماذج الذكاء الاصطناعي.
</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>
	سنحتاج بدايةً لبيئة PHP مثبتة وتعمل على نظام التشغيل، ويمكن تنزيل النسخة المناسبة من <a href="https://www.php.net/downloads.php" rel="external nofollow">الموقع الرسمي لها</a> ثم تثبيته على الجهاز، وللتأكد من صحة التثبيت يمكن تنفيذ الأمر التالي ضمن سطر الأوامر للتحقق من رقم النسخة المثبتة:
</p>

<pre class="ipsCode">php -v
</pre>

<p>
	سيظهر معلومات عن رقم النسخة، ويفضل استخدام النسخة 7.4 أو أعلى، ونبدأ بإنشاء ملف جديد سيحتوي على ملفات المشروع وليكن بالاسم recipe-php، وننشئ ضمنه الملفات التالية:
</p>

<ul>
	<li>
		index.php ملف الصفحة الرئيسية
	</li>
	<li>
		suggestion.php ملف صفحة عرض النتيجة
	</li>
	<li>
		style.css ملف تنسيقات CSS
	</li>
</ul>

<p>
	لتكون بنية المجلد والملفات ضمنه كالتالي:
</p>

<pre class="ipsCode">recipe-php/
├─ index.php
├─ suggestion.php
├─ style.css
</pre>

<p>
	<strong>ملاحظة</strong>: تحتاج إلى أن تملك خبرة أساسية بلغة PHP، وإن كنت جديدًا عليها، فارجع إلى مقال <a href="https://academy.hsoub.com/programming/php/%D8%AA%D9%85%D9%87%D9%8A%D8%AF-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-php-r235/" rel="">تمهيد إلى لغة PHP</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> للتعرف على أساسيات اللغة.
</p>

<p>
	نبدأ ببناء صفحة الموقع الرئيسية ضمن الملف index.php، وفيها سنطلب من المستخدم إدخال معلومات حول الوصفة، كاختيار المطبخ الذي تنتمي إليه وكتابة بعض المكونات التي قد تكون لدى مستخدم التطبيق ويريد تحضير وجبة طعامه منها، ونبدأ بربط ملف التنسيقات style.css في بداية الملف باستخدام العنصر <a href="https://wiki.hsoub.com/HTML/link" rel="external"><code>link</code></a>، ثم نموذجًا باستخدام العنصر <a href="https://wiki.hsoub.com/HTML/form" rel="external"><code>form</code></a> سيرسل محتوياته إلى ملف صفحة النتيجة suggestion.php بالطريقة POST، ويحوي على حقل اسم المطبخ للوجبة المقترحة نضع فيها خيارات مسبقة مثل (سعودي - سوري - مغربي - يمني - مصري)، ثم حقل نصي اختياري يدخل فيه المستخدم المكونات التي لديه وز لإرسال الطلب، ليصبح ملف الصفحة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3778_7" style=""><span class="com">&lt;!-- index.php --&gt;</span><span class="pln">
</span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="com">&lt;!-- استيراد ملف التنسيقات --&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="com">&lt;!-- عنوان الصفحة --&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;/head&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">"logo"</span><span class="tag">&gt;</span><span class="pln"><span class="ipsEmoji">??‍?</span></span><span class="tag">&lt;/div&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">"suggestion.php"</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">dir</span><span class="pun">=</span><span class="atv">"rtl"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="com">&lt;!-- اختيار المطبخ --&gt;</span><span class="pln">
    </span><span class="tag">&lt;fieldset&gt;</span><span class="pln">
        </span><span class="tag">&lt;legend&gt;</span><span class="pln">المطبخ</span><span class="tag">&lt;/legend&gt;</span><span class="pln">

        </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"radio"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"cuisine"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"cuisine_SA"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"سعودي"</span><span class="pln"> </span><span class="atn">required</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"cuisine_SA"</span><span class="tag">&gt;</span><span class="pln"><span class="ipsEmoji">??</span> سعودي</span><span class="tag">&lt;/label&gt;</span><span class="pln">

        </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"radio"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"cuisine"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"cuisine_SY"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"سوري"</span><span class="pln"> </span><span class="atn">required</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"cuisine_SY"</span><span class="tag">&gt;</span><span class="pln"><span class="ipsEmoji">??</span> سوري</span><span class="tag">&lt;/label&gt;</span><span class="pln">

        </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"radio"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"cuisine"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"cuisine_MA"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"مغربي"</span><span class="pln"> </span><span class="atn">required</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"cuisine_MA"</span><span class="tag">&gt;</span><span class="pln"><span class="ipsEmoji">??</span> مغربي</span><span class="tag">&lt;/label&gt;</span><span class="pln">

        </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"radio"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"cuisine"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"cuisine_YE"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"يمني"</span><span class="pln"> </span><span class="atn">required</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"cuisine_YE"</span><span class="tag">&gt;</span><span class="pln"><span class="ipsEmoji">??</span> يمني</span><span class="tag">&lt;/label&gt;</span><span class="pln">

        </span><span class="tag">&lt;input</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"radio"</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"cuisine"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"cuisine_EG"</span><span class="pln"> </span><span class="atn">value</span><span class="pun">=</span><span class="atv">"مصري"</span><span class="pln"> </span><span class="atn">required</span><span class="tag">&gt;</span><span class="pln">
        </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"cuisine_EG"</span><span class="tag">&gt;</span><span class="pln"><span class="ipsEmoji">??</span> مصري</span><span class="tag">&lt;/label&gt;</span><span class="pln">
    </span><span class="tag">&lt;/fieldset&gt;</span><span class="pln">

    </span><span class="com">&lt;!-- مكونات الوصفة --&gt;</span><span class="pln">
    </span><span class="tag">&lt;div&gt;</span><span class="pln">
        </span><span class="tag">&lt;label</span><span class="pln"> </span><span class="atn">for</span><span class="pun">=</span><span class="atv">"ingredients"</span><span class="tag">&gt;</span><span class="pln">المكونات</span><span class="tag">&lt;/label&gt;</span><span class="pln">
        </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">"ingredients"</span><span class="pln"> </span><span class="atn">id</span><span class="pun">=</span><span class="atv">"ingredients"</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;/div&gt;</span><span class="pln">

    </span><span class="com">&lt;!-- إرسال المدخلات --&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 class="ipsEmoji">?</span></span><span class="tag">&lt;/button&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

<p>
	نتوجه الآن لملف عرض النتيجة suggestion.php ونحضر فيه قالب عرض النتيجة، المكون من اسم الوصفة المقترحة وصورة لها ووصف سيحوي على المكونات وطريقة التحضير، وفي النهاية زر للرجوع للصفحة الرئيسية في حال رغب المستخدم اقتراح وصفة جديدة، ولا ننسى <a href="https://academy.hsoub.com/programming/css/%D9%87%D9%8A%D9%83%D9%84%D9%8A%D8%A9-%D9%84%D8%BA%D8%A9-css-r2002/" rel="">ربط ملف التنسيقات</a> style.css في بداية الصفحة كما فعلنا سابقًا، ونحضر بعض المتغيرات الفارغة مبدأيًا سنضع فيها محتويات الصفحة بعد أن تولدها لنا نماذج الذكاء الاصطناعي في الفقرة التالية، ليصبح ملف صفحة النتيجة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3778_9" style=""><span class="com">&lt;!-- suggestion.php --&gt;</span><span class="pln">

</span><span class="pun">&lt;?</span><span class="pln">php
$name </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln"> </span><span class="com">// اسم الوصفة</span><span class="pln">
$recipe </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln"> </span><span class="com">// المكونات وطريقة التحضير</span><span class="pln">
$image_url </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln"> </span><span class="com">// رابط صورة الوصفة</span><span class="pln">
</span><span class="pun">?&gt;</span><span class="pln">

</span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="com">&lt;!-- استيراد ملف التنسيقات --&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="com">&lt;!-- عنوان الصفحة --&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;/head&gt;</span><span class="pln">

</span><span class="tag">&lt;main</span><span class="pln"> </span><span class="atn">class</span><span class="pun">=</span><span class="atv">"suggestion"</span><span class="tag">&gt;</span><span class="pln">
    </span><span class="com">&lt;!-- اسم الوصفة --&gt;</span><span class="pln">
    </span><span class="tag">&lt;h2&gt;</span><span class="pun">&lt;?=</span><span class="pln"> $name </span><span class="pun">?&gt;</span><span class="tag">&lt;/h2&gt;</span><span class="pln">

    </span><span class="com">&lt;!-- صورة للوصفة  --&gt;</span><span class="pln">
    &lt;img src="</span><span class="pun">&lt;?=</span><span class="pln"> $image_url </span><span class="pun">?&gt;</span><span class="pln">" /&gt;

    </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">"recipe"</span><span class="pln"> </span><span class="atn">dir</span><span class="pun">=</span><span class="atv">"rtl"</span><span class="tag">&gt;</span><span class="pun">&lt;?=</span><span class="pln"> $recipe </span><span class="pun">?&gt;</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="com">&lt;!-- زر الرجوع للصفحة الرئيسية  --&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;button&gt;</span><span class="pln">وصفة جديدة <span class="ipsEmoji">??‍?</span></span><span class="tag">&lt;/button&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;/main&gt;</span></pre>

<p>
	أما ملف التنسيقات style.css يهتم بالخطوط والألوان وتنسيق العناصر ضمن الصفحات ليجعلها أجمل ويحوي التالي:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_3778_11" style=""><span class="com">/* تنسيق الخطوط */</span><span class="pln">

</span><span class="kwd">@import</span><span class="pln"> </span><span class="kwd">url</span><span class="pun">(</span><span class="str">"https://fonts.googleapis.com/css2?family=Noto+Kufi+Arabic:wght@400;500;700&amp;family=Noto+Naskh+Arabic:wght@400;500;700&amp;display=swap"</span><span class="pun">);</span><span class="pln">

</span><span class="pun">@</span><span class="pln">font-face </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="str">"Flags"</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">font-style</span><span class="pun">:</span><span class="pln"> normal</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">font-weight</span><span class="pun">:</span><span class="pln"> </span><span class="lit">400</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">font-display</span><span class="pun">:</span><span class="pln"> swap</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">src</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">url</span><span class="pun">(</span><span class="str">https://fonts.gstatic.com/s/notocoloremoji/v24/Yq6P-KqIXTD0t4D9z1ESnKM3-HpFabsE4tq3luCC7p-aXxcn.0.woff2</span><span class="pun">)</span><span class="pln">
    format</span><span class="pun">(</span><span class="str">"woff2"</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">unicode-range</span><span class="pun">:</span><span class="pln"> U</span><span class="pun">+</span><span class="lit">1f1e6</span><span class="pun">-</span><span class="lit">1f1ff</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">:</span><span class="pln">root </span><span class="pun">{</span><span class="pln">
  </span><span class="pun">--</span><span class="kwd">font-heading</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Noto Kufi Arabic"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Flags"</span><span class="pun">,</span><span class="pln"> sans-serif</span><span class="pun">;</span><span class="pln">
  </span><span class="pun">--</span><span class="kwd">font-body</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Noto Naskh Arabic"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Flags"</span><span class="pun">,</span><span class="pln"> sans-serif</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">font-family</span><span class="pun">:</span><span class="pln"> var</span><span class="pun">(--</span><span class="pln">font-body</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

h1</span><span class="pun">,</span><span class="pln">
h2</span><span class="pun">,</span><span class="pln">
button</span><span class="pun">,</span><span class="pln">
label</span><span class="pun">,</span><span class="pln">
legend </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">font-family</span><span class="pun">:</span><span class="pln"> var</span><span class="pun">(--</span><span class="pln">font-heading</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">/* تنسيقات عامة  */</span><span class="pln">

body </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">justify-content</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">min-height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">90vh</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="kwd">rgb</span><span class="pun">(</span><span class="lit">237</span><span class="pun">,</span><span class="pln"> </span><span class="lit">240</span><span class="pun">,</span><span class="pln"> </span><span class="lit">244</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="pun">}</span><span class="pln">

</span><span class="com">/* تنسيق عناصر الصفحة الرئيسية */</span><span class="pln">

fieldset </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">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">.</span><span class="pln">logo </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">border-radius</span><span class="pun">:</span><span class="pln"> </span><span class="lit">999rem</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">background-color</span><span class="pun">:</span><span class="pln"> seagreen</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">width</span><span class="pun">:</span><span class="pln"> </span><span class="lit">11rem</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">11rem</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">line-height</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2em</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="lit">6rem</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">1.5rem</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

label</span><span class="pun">,</span><span class="pln">
legend </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">display</span><span class="pun">:</span><span class="pln"> block</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">margin-bottom</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1rem</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">type</span><span class="pun">=</span><span class="str">"radio"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">~</span><span class="pln"> label </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">font-family</span><span class="pun">:</span><span class="pln"> var</span><span class="pun">(--</span><span class="pln">font-body</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">display</span><span class="pun">:</span><span class="pln"> inline-block</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">margin-bottom</span><span class="pun">:</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">

button</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="lit">1.2rem</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">type</span><span class="pun">=</span><span class="str">"text"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">display</span><span class="pun">:</span><span class="pln"> block</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">width</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">}</span><span class="pln">

button </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">background-color</span><span class="pun">:</span><span class="pln"> seagreen</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">color</span><span class="pun">:</span><span class="pln"> white</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="lit">1.5rem</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">transition</span><span class="pun">:</span><span class="pln"> all </span><span class="lit">150ms</span><span class="pln"> ease-in-out</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">button</span><span class="pun">:</span><span class="pln">hover </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">background-color</span><span class="pun">:</span><span class="pln"> darkgreen</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">suggestion </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">margin</span><span class="pun">:</span><span class="pln"> </span><span class="lit">7rem</span><span class="pln"> </span><span class="lit">3rem</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">50ch</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">.</span><span class="pln">suggestion h2 </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">color</span><span class="pun">:</span><span class="pln"> </span><span class="lit">#28774a</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">.</span><span class="pln">suggestion img </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">object-fit</span><span class="pun">:</span><span class="pln"> cover</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">1rem</span><span class="pln"> solid white</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">aspect-ratio</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</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">suggestion </span><span class="pun">.</span><span class="pln">description </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">background-color</span><span class="pun">:</span><span class="pln"> white</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">border</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1px</span><span class="pln"> solid darkgray</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">

</span><span class="pun">.</span><span class="pln">suggestion a button </span><span class="pun">{</span><span class="pln">
  </span><span class="kwd">width</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">}</span></pre>

<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> ويأتي مثبتًا معها، وذلك بتنفيذ الأمر <code>php</code> داخل مجلد المشروع مع الخيار <code>S-</code> ونمرر له عنوان الخادم ورقم المنفذ الذي سيتمع إليه، ويمكننا استخدام العنوان المحلي localhost ورقم المنفذ الافتراضي لخوادم الويب 80 ليصبح الأمر كالتالي:
</p>

<pre class="ipsCode">php -S localhost:80
</pre>

<p>
	يمكننا الآن زيارة العنوان <a href="http://localhost:80" ipsnoembed="false" rel="external nofollow">http://localhost:80</a> من المتصفح ليعالج الخادم افتراضيًا ملف الصفحة الرئيسية index.php ويرسله لنا لنرى التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="128872" href="https://academy.hsoub.com/uploads/monthly_2023_06/index.png.3154d5bea2d4c53e1d450cfa4d4d99e1.png" rel=""><img alt="index.png" class="ipsImage ipsImage_thumbnailed" data-fileid="128872" data-unique="yczl0pqpj" src="https://academy.hsoub.com/uploads/monthly_2023_06/index.thumb.png.c0158b1226346e408ccd7bc78545483d.png"> </a>
</p>

<p>
	ولمعاينة صفحة النتيجة نختار خيار عشوائي ونضغط "اقترح وصفة"، ويمكننا مؤقتًا إسناد قيم لمتغيرات المتحوى ضمن صفحة suggestion.php لنتمكن من معاينة تنسيقها كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3778_13" style=""><span class="com">&lt;!-- suggestion.php --&gt;</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php
$name </span><span class="pun">=</span><span class="pln"> </span><span class="str">'اسم الوصفة'</span><span class="pun">;</span><span class="pln">
$description </span><span class="pun">=</span><span class="pln"> </span><span class="str">'شرح الوصفة...'</span><span class="pun">;</span><span class="pln">
$image_url </span><span class="pun">=</span><span class="pln"> </span><span class="str">'#'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	لتظهر لنا الصفحة بالمظهر التالي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="128866" href="https://academy.hsoub.com/uploads/monthly_2023_06/result-page-template.png.c21fb1f6e7008be60b5f42cf241aa5ec.png" rel=""><img alt="result-page-template.png" class="ipsImage ipsImage_thumbnailed" data-fileid="128866" data-unique="dv2x6rejz" src="https://academy.hsoub.com/uploads/monthly_2023_06/result-page-template.thumb.png.2c68967707e479a0116772554b1aef6b.png"> </a>
</p>

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

<h2>
	توليد مفتاح الواجهة البرمجية <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> والوصول إليه
</h2>

<p>
	يحتاج تطبيقنا للتواصل مع نماذج الذكاء الاصطناعي المختلفة لتوليد وطلب المحتوى، ويتم ذلك عبر الواجهة البرمجية <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> التي توفرها الشركة صاحبة تلك النماذج، لذا نحتاج بدايةً لإنشاء حساب على <a href="https://platform.openai.com/" rel="external nofollow">منصتها</a> وإعداد وسيلة الدفع على الحساب لنتمكن من التعامل مع خدماتها المدفوعة، بعدها علينا توليد مفتاح استيثاق خاص لتطبيقنا من <a href="https://platform.openai.com/account/api-keys" rel="external nofollow">صفحة إعداد المفاتيح</a> ليتمكن من إرسال الطلبات، ويمكن تسمية ذلك المفتاح للتعرف عليه لاحقًا، وبعدها سيظهر لنا المفتاح الجديد لمرة واحدة فقط، لذا يجب التأكد من نسخه وحفظه في مكان آمن حيث سنحتاج لتمريره إلى تطبيقنا.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="128871" href="https://academy.hsoub.com/uploads/monthly_2023_06/openai-create-api-key.png.13f43c616833a736acdd291fe047458d.png" rel=""><img alt="openai-create-api-key.png" class="ipsImage ipsImage_thumbnailed" data-fileid="128871" data-unique="rz958bn4e" src="https://academy.hsoub.com/uploads/monthly_2023_06/openai-create-api-key.png.13f43c616833a736acdd291fe047458d.png"> </a>
</p>

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

<pre class="ipsCode">set OPENAI_API_KEY=المفتاح
</pre>

<p>
	وضمن نظام التشغيل <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> أو ماك بتنفيذ الأمر export كالتالي:
</p>

<pre class="ipsCode">export OPENAI_API_KEY=المفتاح
</pre>

<p>
	<strong>ملاحظة</strong>: لم نضع قيمة هذا المفتاح في ملف env. فحينذاك سنضطر للاعتماد على مكتبة لتحميل هذا الملف، لذا حاولت أن يكون التطبيق بسيطًا جدًا بلا مكتبات ما أمكن.
</p>

<p>
	بعد تنفيذ ذلك الأمر وحصرًا ضمن نفس جلسة سطر الأوامر أي في نفس النافذة يمكن تشغيل خادم الويب، لنتمكن ضمن تطبيقنا في PHP الوصول لذلك المفتاح عبر التابع <code>getenv</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3778_16" style=""><span class="pln">getenv</span><span class="pun">(</span><span class="str">'OPENAI_API_KEY'</span><span class="pun">);</span><span class="pln"> </span><span class="com">// قيمة المفتاح من متغير البيئة</span></pre>

<p>
	حيث يجب إرسال قيمة ذلك المفتاح مع كل طلب HTTP للواجهة البرمجية، وضمن الترويسة <code>Authorization</code> قيمتها الكلمة <code>Bearer</code> ثم مسافة وبعدها قيمة المفتاح، ويمكن بناء نص تلك الترويسة في PHP عبر استخراج قيمة المفتاح من متغير البيئة كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3778_18" style=""><span class="str">"Authorization: Bearer "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> getenv</span><span class="pun">(</span><span class="str">'OPENAI_API_KEY'</span><span class="pun">);</span></pre>

<p>
	وبذلك أصبحنا جاهزين لإرسال الطلبات عبر الواجهة البرمجية <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> للتخاطب مع نماذج الذكاء الاصطناعي لتوليد المحتوى لتطبيقنا وهو ما سنتعرف عليه ضمن الفقرة التالية.
</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>
	توليد الوصفة وصورة لها
</h2>

<p>
	سنبدأ بتعريف بعض التوابع ضمن صفحة النتيجة suggestion.php سنستدعيها لاحقًا لإسناد قيم المحتوى التي ستولده نماذج الذكاء الاصطناعي إلى المتغيرات التي جهزناها سابقًا لعرضها ضمن قالب الصفحة، ونبدأ بتعريف تابع توليد النصوص <code>chatGPT</code> والذي يقبل متغير التعليمة النصية <code>prompt$</code> كمعامل له سيرسلها ضمن طلب HTTP ليطلب من نموذج بالاسم <code>gpt-3.5-turbo</code> توليد جواب نصي من تلك التعليمة، يمكن التعامل مع هذا النموذج بصيغة دردشة بين المستخدم والنموذج، في حالتنا لن نحتاج سوى لرسالة واحدة من طرف المستخدم سنبنيها بناءًا على مدخلات المستخدم لاقتراح وصفة وشرح عنها.
</p>

<p>
	يرسل الطلب مع ترويسة الاستيثاق التي تحوي مفتاح <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 | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr></a> كما تعرفنا سابقًا، وترويسة للتعريف بنوع المحتوى بجسم الطلب <code>Content-type</code> وهو <code>application/json</code>، وبالطريقة POST ويحوي جسم الطلب على اسم النموذج ضمن الحقل <code>model</code> ومصفوفة رسائل الدردشة الحالية بين المستخدم والنموذج ضمن الحقل <code>messages</code> ، حيث تحتوي كل رسالة على اسم صاحب الرسالة ضمن الحقل <code>role</code> ومحتوى الرسالة ضمن <code>content</code>، وفي حالتنا نحتاج لرسالة واحدة فقط من طرف المستخدم أي <code>user</code> ومحتواها هو التعليمة المٌمررة للتابع ضمن المتغير <code>prompt$</code> ، وبالاستفادة من التابعين <code>file_get_contents</code> و <code>stream_context_create</code> في PHP يمكننا إرسال طلب HTTP دون الحاجة لأي مكتبات إضافية، أما صيغة الجواب فهي JSON بالشكل التالي وما يهمنا منها هو رسالة النموذج:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3778_21" style=""><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
  </span><span class="str">"choices"</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">"message"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
      </span><span class="str">"role"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"assistant"</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">"..."</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><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكننا استخراجها بعد تمرير جواب الطلب للتابع <code>json_decode</code> لتحويله لكائن PHP نستخرج منه القيمة التي نريدها، ليصبح التابع كاملًا كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3778_23" style=""><span class="com">/**
 * توليد نص باستخدام نموذج الدردشة
 * @param string $prompt التعليمة
 * @return string النص المُولد 
 */</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> chatGPT</span><span class="pun">(</span><span class="pln">$prompt</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> file_get_contents</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="kwd">false</span><span class="pun">,</span><span class="pln"> stream_context_create</span><span class="pun">([</span><span class="pln">
        </span><span class="str">'http'</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">'header'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"Content-type: application/json\r\n"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"Authorization: Bearer "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> getenv</span><span class="pun">(</span><span class="str">'OPENAI_API_KEY'</span><span class="pun">),</span><span class="pln">
            </span><span class="str">'method'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'POST'</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"> json_encode</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="com">// اسم النموذج</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"> $prompt</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><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">return</span><span class="pln"> json_decode</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">)-&gt;</span><span class="pln">choices</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]-&gt;</span><span class="pln">message</span><span class="pun">-&gt;</span><span class="pln">content</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ولتوليد الصور سنعرف التابع <code>dalle</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> بالطريقة <code>POST</code> لمسار توليد الصور الخاص، حيث نحتاج فقط ضمن جسم الطلب لتمرير توصيف الصورة ضمن الحقل <code>prompt</code> ولتحديد قياس الصورة في حالتنا هو <code>512x512</code> وعدد الصور التي نحتاجها في حالتنا يكفي صورة واحدة لذا نحدد قيمة <code>n</code> بواحد، ولا ننسى ترويستي الاستيثاق ونوع جسم الطلب، أما عن شكل جواب الطلب فهو بصيغة <a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B9%D9%84%D9%85-json-r604/" rel="">JSON</a> يهمنا منه رابط الصورة التي تم توليدها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3778_25" style=""><span class="pun">{</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">
  </span><span class="str">"data"</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">"url"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"https://..."</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><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نمرره أيضًا للتابع <code>json_decode</code> لتحويلها لكائن PHP ونستخرج منه رابط الصورة التي تم توليدها ليصبح التابع كاملًا كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3778_27" style=""><span class="com">/**
 * توليد صورة باستخدام نموذج توليد الصور
 * @param string $prompt وصف للصورة 
 * @return string رابط للصورة المُولّدة
 */</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> dalle</span><span class="pun">(</span><span class="pln">$prompt</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> file_get_contents</span><span class="pun">(</span><span class="str">'https://api.openai.com/v1/images/generations'</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> stream_context_create</span><span class="pun">([</span><span class="pln">
        </span><span class="str">'http'</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">'header'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"Content-type: application/json\r\n"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"Authorization: Bearer "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> getenv</span><span class="pun">(</span><span class="str">'OPENAI_API_KEY'</span><span class="pun">),</span><span class="pln">
            </span><span class="str">'method'</span><span class="pln">  </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'POST'</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"> json_encode</span><span class="pun">([</span><span class="pln">
                </span><span class="str">"n"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="com">// عدد الصور</span><span class="pln">
                </span><span class="str">"size"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"512x512"</span><span class="pun">,</span><span class="pln"> </span><span class="com">// قياس الصورة</span><span class="pln">
                </span><span class="str">'prompt'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $prompt</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><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"> json_decode</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">)-&gt;</span><span class="pln">data</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]-&gt;</span><span class="pln">url</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

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

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		اقترح وصفة من وصفات المطبخ &lt;اسم المطبخ&gt; [يمكن تحضيرها بالمكونات &lt;المكونات&gt;] اذكر اسم الوصفة ثم المكونات ثم طريقة التحضير
	</p>
</blockquote>

<p>
	بحيث نبدل اسم المطبخ والمكونات بالقيم الممررة للتابع، ونمرر تلك التعليمة للتابع <code>chatGPT</code> الذي عرفناه سابقًا، ليعيد لنا اقتراح النموذج، نعالج ذلك الاقتراح باستخراج اسم الوصفة من أول سطر منه بعد تقسيمه باستخدام التابع <code>explode</code> وبقية الأسطر ستحوي على شرح مكونات وطريقة تحضير الوصفة نحددها باستخدام التابع <code>array_slice</code> ونجمعها مجددًا باستخدام التابع <code>implode</code>، ونعيد هاتين القيمتين بعد تمريرهما للتابع <code>trim</code> لإزالة أي محارف ومسافات زائدة، كنتيجة لاستدعاء التابع تحوي الحقل <code>name</code> اسم الوصفة والحقل <code>description</code> شرح الوصفة ليكون التابع كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3778_29" style=""><span class="com">/**
 * اقتراح وصفة
 * @param string $cuisine اسم المطبخ الذي تنتمي إليه الوصفة
 * @param string|null $ingredients مكونات اختيارية تتضمنها الوصفة
 * @return array اسم وشرح الوصفة 
 */</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> recipe</span><span class="pun">(</span><span class="pln">$cuisine</span><span class="pun">,</span><span class="pln"> $ingredients</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// التوصيف</span><span class="pln">
    $rules </span><span class="pun">=</span><span class="pln"> implode</span><span class="pun">(</span><span class="str">' '</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="str">"من وصفات المطبخ ال"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $cuisine </span><span class="pun">.</span><span class="pln"> </span><span class="str">" المشهورة"</span><span class="pun">,</span><span class="pln">
        </span><span class="com">// شرط المكونات</span><span class="pln">
        $ingredients </span><span class="pun">?</span><span class="pln">
</span><span class="str">"يمكن تحضيرها بالمكونات "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $ingredients </span><span class="pun">:</span><span class="pln"> </span><span class="com">// المكونات</span><span class="pln">
</span><span class="str">""</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">
    $recipe_prompt </span><span class="pun">=</span><span class="pln"> </span><span class="str">"اقترح وصفة $rules
    اذكر اسم الوصفة ثم المكونات ثم طريقة التحضير"</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// توليد الاقتراح</span><span class="pln">
    $suggestion </span><span class="pun">=</span><span class="pln"> chatGPT</span><span class="pun">(</span><span class="pln">$recipe_prompt</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// تقسيم الاقتراح لأسطر</span><span class="pln">
    $lines </span><span class="pun">=</span><span class="pln"> explode</span><span class="pun">(</span><span class="str">"\n"</span><span class="pun">,</span><span class="pln"> $suggestion</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="com">// استخراج اسم الوصفة</span><span class="pln">
        </span><span class="str">'name'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> trim</span><span class="pun">(</span><span class="pln">str_replace</span><span class="pun">(</span><span class="str">"اسم الوصفة:"</span><span class="pun">,</span><span class="pln"> </span><span class="str">""</span><span class="pun">,</span><span class="pln"> $lines</span><span class="pun">[</span><span class="lit">0</span><span class="pun">])),</span><span class="pln">

        </span><span class="com">// استخراج المكونات والتفاصيل</span><span class="pln">
        </span><span class="str">'description'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> trim</span><span class="pun">(</span><span class="pln">implode</span><span class="pun">(</span><span class="str">"\n"</span><span class="pun">,</span><span class="pln"> array_slice</span><span class="pun">(</span><span class="pln">$lines</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="pun">}</span></pre>

<p>
	ولتوليد صورة للوصفة المقترحة يجب أن نصف بصريًا ماذا تحوي تلك الصورة، فنذكر المكونات التي تظهر والطبق والمشهد ونمرر ذلك الوصف للتابع <code>dalle</code> الذي عرفناه سابقًا، لكن المشكلة أننا نحتاج لكتابة توصيف خاص بكل وصفة مقترحة من أين سنأتي بذلك التوصيف؟ بما أن التوصيف عبارة عن نص لما لا نطلب ذلك من GPT حيث نمرر له اسم الوصفة مع شرحها، مع الأخذ بالاعتبار أن التوصيف يجب أن يكون باللغة الإنكليزية حيث لحين تاريخ كتابة هذا المقال لا يفهم DALL-E سوى التعليمات باللغة الإنكليزية، فنرسل التعليمة التالية لتوليد وصف للصورة:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		write a two sentence description of a dish that contains the following recipe [name] [description]
	</p>
</blockquote>

<p>
	وترجمتها هي التالي:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		اكتب توصيفًا بجملتين لطبق يحوي الوصفة [اسم الوصفة] [شرح الوصفة]
	</p>
</blockquote>

<p>
	نعرف التابع <code>recipeImage</code> الذي يقبل اسم وشرح الوصفة ويطلب من GPT شرح لصورة تحوي طبق منها، ثم يمرر ذلك الوصف إلى DALL-E لتوليد الصورة والحصول على رابطها ونعيده كنتيجة لتنفيذ التابع كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3778_31" style=""><span class="com">/**
 * توليد صورة من اسم وتفاصيل وصفة
 * @param mixed $name اسم الوصفة
 * @param mixed $description شرح الوصفة
 * @return string رابط صورة للوصفة
 */</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> recipeImage</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">,</span><span class="pln"> $description</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// توليد وصف للصورة</span><span class="pln">
    $image_desc </span><span class="pun">=</span><span class="pln"> chatGPT</span><span class="pun">(</span><span class="str">"write a two sentence description of a dish that contains the following recipe \n $name \n $description"</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"> dalle</span><span class="pun">(</span><span class="pln">$image_desc</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أصبحت جميع التوابع اللازمة جاهزة، لنستخدمها لتوليد المحتوى وإسناد القيم لمتغيرات واجهة المستخدم لعرضها، حيث يمكن استخراج القيم التي أدخلها المستخدم من المتغير العام <code>POST_$</code> بحسب اسم الحقول في الصفحة الرئيسية، ونمرر تلك القيم بداية للتابع <code>recipe</code> لاقتراح وصفة جديدة، ثم نستخرج اسم وشرح الوصفة ونسندها للمتغيرات <code>name$</code> و <code>description$</code>، ولتوليد الصورة نمرر تلك المتغيرات للتابع <code>recipeImage</code> ونسند قيمة رابط الصورة المولدة التي سيعيدها للمتغير <code>image_url$</code> كالتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3778_33" style=""><span class="com">// اقتراح وصفة من مدخلات المستخدم</span><span class="pln">
$recipe </span><span class="pun">=</span><span class="pln"> recipe</span><span class="pun">(</span><span class="pln">$_POST</span><span class="pun">[</span><span class="str">'cuisine'</span><span class="pun">],</span><span class="pln"> $_POST</span><span class="pun">[</span><span class="str">'ingredients'</span><span class="pun">]);</span><span class="pln">

$name </span><span class="pun">=</span><span class="pln"> $recipe</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">
$description </span><span class="pun">=</span><span class="pln"> $recipe</span><span class="pun">[</span><span class="str">'description'</span><span class="pun">];</span><span class="pln"> </span><span class="com">// شرح الوصفة</span><span class="pln">
$image_url </span><span class="pun">=</span><span class="pln"> recipeImage</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">,</span><span class="pln"> $description</span><span class="pun">);</span><span class="pln"> </span><span class="com">// رابط صورة الوصفة</span></pre>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="128870" href="https://academy.hsoub.com/uploads/monthly_2023_06/result-1.png.cfce70b47c8bc15019c9684686edb1b6.png" rel=""><img alt="result-1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="128870" data-unique="iwfenw16q" src="https://academy.hsoub.com/uploads/monthly_2023_06/result-1.thumb.png.1fed6c84329898cafe72fbe4d2aa2aa4.png"> </a>
</p>

<p>
	وصفة فتة حمص بالطحينة
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="128869" href="https://academy.hsoub.com/uploads/monthly_2023_06/result-2.png.e07f449a931218b5bb38afeeafa31817.png" rel=""><img alt="result-2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="128869" data-unique="2m5xyylfx" src="https://academy.hsoub.com/uploads/monthly_2023_06/result-2.thumb.png.587e54dd605da2af40c3b64aef512cae.png"> </a>
</p>

<p>
	وصفة الكبسة ونلاحظ الأجواء العربية ضمن الصورة
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="128868" href="https://academy.hsoub.com/uploads/monthly_2023_06/result-3.png.7c726fb19e429eea00e1bbc2bade9c98.png" rel=""><img alt="result-3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="128868" data-unique="aadyflum8" src="https://academy.hsoub.com/uploads/monthly_2023_06/result-3.thumb.png.4b3a38341f25333d20a0b8455e2c0973.png"> </a>
</p>

<p>
	وصفة الطاجين المغربي
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="128867" href="https://academy.hsoub.com/uploads/monthly_2023_06/result-4.png.089f5af5d50aa0065848e1d3788853d6.png" rel=""><img alt="result-4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="128867" data-unique="0d1o739xc" src="https://academy.hsoub.com/uploads/monthly_2023_06/result-4.thumb.png.470d5baedbc787982607ec482d58759e.png"> </a>
</p>

<p>
	وصفة الكشري
</p>

<p>
	وبعض صور الوجبات التي استطاع توليدها:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="128865" href="https://academy.hsoub.com/uploads/monthly_2023_06/results.png.31304506440bb3ebb9e10836f96fe668.png" rel=""><img alt="results.png" class="ipsImage ipsImage_thumbnailed" data-fileid="128865" data-unique="p2x70ij68" src="https://academy.hsoub.com/uploads/monthly_2023_06/results.thumb.png.51a97a6de4aedbda2dd25be34844965b.png"> </a>
</p>

<h2>
	تطويرات إضافية ممكنة ونقاط الضعف الحالية
</h2>

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

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

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

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

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%B4%D8%A8%D9%83%D8%A9-%D8%B9%D8%B5%D8%A8%D9%8A%D8%A9-%D8%B5%D9%86%D8%B9%D9%8A%D8%A9-%D9%88%D8%AA%D8%AF%D8%B1%D9%8A%D8%A8%D9%87%D8%A7-%D9%84%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%88%D9%87-r1198/" rel="">إعداد شبكة عصبية صنعية وتدريبها للتعرف على الوجوه</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%B4%D8%AE%D8%B5%D9%8A%D8%A7%D8%AA-%D8%A8%D8%A7%D9%84%D8%A7%D8%B9%D8%AA%D9%85%D8%A7%D8%AF-%D8%B9%D9%84%D9%89-%D8%AA%D8%BA%D8%B1%D9%8A%D8%AF%D8%A7%D8%AA%D9%87%D9%85-%D8%A7%D9%84%D8%B9%D8%B1%D8%A8%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%B9%D9%85%D9%8A%D9%82-r1630/" rel="">تصنيف الشخصيات بالاعتماد على تغريداتهم العربية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">2005</guid><pubDate>Tue, 13 Jun 2023 15:00:00 +0000</pubDate></item><item><title>&#x645;&#x642;&#x627;&#x631;&#x646;&#x629; &#x628;&#x64A;&#x646; PHP &#x648; NodeJS</title><link>https://academy.hsoub.com/programming/php/%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%A8%D9%8A%D9%86-php-%D9%88-nodejs-r1599/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2022_06/6297c3a5e6bec_--PHP--Node-JS.jpg.5165c0dd98291ac480a8df422ce2a451.jpg" /></p>
<p>
	في بداية كل تطبيق أو موقع إلكتروني تظهر إشكالية متكررة دومًا بغض النظر عن المشروع وهي نوع التكنولوجيا المناسبة لبناء الموقع (سواء لغة البرمجة أو إطار العمل) لأن الاختيار المناسب سيلعبُ دورًا مهمًا في نجاح المشروع فإذا اتُخذ قرار خاطئ فيمكن أن يفشل كل شيء في بداية المشروع أو في مراحل متقدمة منه، ولذلك يكون اختيار التكنولوجيا مهمة شاقة للشركات الصغيرة والناشئة التي تعمل عادةً بخبرات وموارد مالية محدودة، وكلما كانت الشركة أصغر كان تأثير القرار السيئ أكثر مأساوية لموارد الشركة.
</p>

<p>
	يتضمن أي موقع إلكتروني جانبين أساسيين وهما جانب العميل Front-end وهو الجانب المرئي من الموقع ويتضمن شيفرة برمجية من اللغة الهيكلية <a href="https://wiki.hsoub.com/HTML" rel="external">HTML</a> و <a href="https://wiki.hsoub.com/CSS" rel="external">CSS</a> لتنسيق الصفحات والعرض و<a href="https://wiki.hsoub.com/JavaScript" rel="external">لغة جافاسكربت</a>، وجانب الخادم Back-end وهو غير مرئي للمستخدمين ويتضمن لغة برمجية لبرمجة منطلق الموقع وقاعدة بيانات لاستيراد البيانات وخادم وهو حاسوب لتشغيل الموقع أو التطبيق. تشغّل مواقع الويب عبر الكثير من <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> ومن بينها <a href="https://wiki.hsoub.com/Node.js" rel="external">Node.js</a> و <a href="https://wiki.hsoub.com/PHP" rel="external">PHP</a> وهما من أكثر التقنيات المستخدمة من جانب الخادم، ويمكن لكليهما تشغيل تطبيقات الويب بغض النظر عن تعقيد المشروع، وفي الوقت نفسه فإن الاختلافات بينها كبيرة لأن كل واحدة منها مبنية على مفاهيم وبنيات مختلفة. لنستكشف معًا من الأقوى في هذه المعركة المحتدمة بين <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> مقابل Node.js.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix" data-gramm="false">
		<p>
			<strong>ملاحظة</strong>: نسعى لتجنب التحيز ولكن بالتأكيد هناك بعض المشاريع التي تناسب لغة معينة أكثر من الأخرى وهذا أمر طبيعي.
		</p>
	</div>
</blockquote>

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

<h2>
	نبذة موجزة عن لغة PHP و Node.js
</h2>

<p>
	قبل الغوص في التفاصيل وذكر الميزات والعيوب والمقارنة بينها لا بدّ لنا من التوقف قليلًا والتأمل في نقطة مهمة عند المقارنة بين PHP و Node.js إذ أنه لا يخفى على الجميع بأن PHP هي لغة برمجة ولكن ما هي Node.js هل هي لغة؟ أم مكتبة؟ أم <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>؟ أم ماذا؟ في الحقيقة جميع تخميناتنا خاطئة لأن Node.js ما هي إلا <strong>بيئة تشغيل تسمح بتشغيل الشيفرة البرمجية للغة جافاسكربت</strong>، ومع ذلك بعض المبتدئين يسمونها لغة Node.js، وعمومًا يمكننا النظر إلى هذه المقارنة على أنها مقارنة بين مزايا لغة جافاسكربت ولغة PHP ولكن بطريقة غير مباشرة.
</p>

<h3>
	ما هي Node.js
</h3>

<p>
	تعتمد بيئة تشغيل جافاسكربت Node.js بصورة أساسية على محرك <a href="https://en.wikipedia.org/wiki/V8_(JavaScript_engine)" rel="external nofollow">Chrome V8</a>، وهو محرك جافاسكربت و WebAssembly عالي الأداء ومفتوح المصدر طورته شركة غوغل (اسمها حاليًا ألفابت)، والشيفرة البرمجية لهذا المحرك مكتوبٌ بلغة C++‎، ويُستخدم لتشغيل لغة جافاسكربت على متصفح الإنترنت كروم Chrome. توفر بيئة Node.js تطبيقات ذات أداء واستقرار عاليين. كما أنها تتيح إمكانية إنشاء خوادم قابلة للتطوير دون استخدام الخيوط Thread، باستخدام نموذج مبسط من البرمجة القائمة على الأحداث Event-driven Programming، والتي تستخدم عمليات رد النداء <a href="https://academy.hsoub.com/programming/javascript/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-%D8%B1%D8%AF%D9%88%D8%AF-%D8%A7%D9%84%D9%86%D8%AF%D8%A7%D8%A1-callbacks-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r914/" rel="">callback</a> للإشارة إلى اكتمال المهمة، كما تبسط بيئة Node.js عملية التطوير لآلاف المبرمجين إذ jمكّنهم من إنشاء موقع أو تطبيق ويب من خلال لغة جافاسكربت سواء من جانب الخادم أو العميل.
</p>

<p>
	تسمح بيئة Node.js للمطورين بناء تطبيقات بسرعة بفضل مشاركة اللغة بين الواجهات الأمامية والخلفية الأمر الذي يزيد من الكفاءة والإنتاجية للمطورين. كما يساعد هذا المزيج على بناء تطبيق قوي ومكتمل الميزات بأقل استثمار من وقت وجهد، بالإضافة إلى ذلك تنخفض تكاليف الصيانة وتزداد سهولة اكتشاف الأخطاء والقدرة على استخدام لغة <a href="https://wiki.hsoub.com/TypeScript" rel="external">TypeScript</a> مع التي تتيح المزيد من القوة وقابلية الاستخدام للشيفرة البرمجية. كما أن لغة جافاسكربت هي الأساس للعديد من أطر العمل للواجهات الأمامية الشائعة مثل React أو Vue وهذه الأطر أساسية لمعظم تطبيقات الويب الحديثة.
</p>

<p>
	تتيح أيضًا بيئة Node.js بناء تطبيقات بالزمن الحقيقي Real-time بفضل تجربة تدفق البيانات في الوقت الفعلي باستخدام لغة جافاسكربت المقادة بالأحداث، إذ يمكنك بسهولة إنشاء حلول برمجية عالية الأداء مع ميزات متقدمة مثل الدردشات وخدمات البث الحي للفيديوهات أو الصوت والمعاملات وما إلى ذلك. في الحقيقة هذه المرونة العالية للتغييرات وقابلية التوسع جعلت بيئة Node.js قوية في سوق تطبيقات الويب ذات الطبيعة السريعة والمتقلبة لأن الوجود في الأسواق يفرض على الشركات تظل مرنًة وأن تكون قادرةً على تغيير تطبيقاتها لتلبية متطلبات العملاء المتغيرة وزيادة إمكانية الوصول إلى سقف توقعات المستخدمين. كما أن لغة جافاسكربت تعدّ من اللغات الأساسية في تطوير الويب ولذلك فإن المبرمجين سيتعلمونها حتمًا خلال رحلتهم في تطوير الويب، وسيصبح من الأسهل عليهم اختيار بيئة Node.js <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%AE%D9%84%D9%81%D9%8A%D8%A9-backend-web-development/" rel="">للواجهة الخلفية</a> بدلًا من <a href="https://academy.hsoub.com/php/" rel="">تعلم لغة PHP </a>مما يسرع رحلة التعلم للمبتدئين.
</p>

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

<h3>
	لغة PHP
</h3>

<p>
	لغة PHP وهي اختصار لعبارة Hypertext Preprocessor أنشأها راسموس ليردورف Rasmus Lerdorf في عام 1994. وهي لغة برمجة نصية مفتوحة المصدر من جانب الخادم مصممة خصيصًا لتطوير تطبيقات ومواقع الويب، كما أنها تستخدم أيضًا كلغة برمجة نصية للأغراض العامة، وتكون ملفات PHP لها امتداد ‎.php ويمكن أن تحتوي على شيفرة <a href="https://wiki.hsoub.com/JavaScript" rel="external">جافاسكربت</a> و <a href="https://wiki.hsoub.com/HTML" rel="external">HTML</a> و <a href="https://wiki.hsoub.com/CSS" rel="external">CSS</a> وحتى نصوص عادية أيضًا.
</p>

<p>
	وتعد لغة PHP واحدة من أفضل لغات الخادم في العالم. أظهر <a href="https://w3techs.com/technologies/comparison/pl-js,pl-PHP" rel="external nofollow">استطلاع</a> أجراه موقع W3Tech جاء فيه أن 78.1% من مواقع الويب في العالم تستخدم لغة PHP للواجهات الخلفية بالمقارنة مع 1.8٪ من المواقع التي تستخدم جافاسكربت وبيئة Node.js. تحتوي لغة PHP أيضًا على دعم كبير لأطر العمل مثل Laravel و Symfony و Codeigniter و CakePHP، وجميع هذه الأطر مفتوحة المصدر ويمكن لأي شخص استخدامها أو تعديلها وتطويرها.
</p>

<p>
	كما أن لغة PHP بحد ذاتها قابلة جدًا للتخصيص وبمجرد أن يزدهر تطبيق الويب ويتوسع ستجد أن اللغة تلبي جميع احتياجاتك والتغييرات التي تتطلع لها. يعد الحصول على درجة عالية من التخصيص في تحسين وظائف موقع الويب الخاص بك ميزة تنافسية كبيرة وهذه الميزة توفرها لغة PHP لأنها تحتوي على جميع الوظائف اللازمة للعمل مع HTML والخوادم و<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>، كما تتميز اللغة بمستوى عال من الأمان والمرونة وخصيصًا في النسخ الحديثة منها ومع مشاهدتنا لشركات تخسر مبالغ كبيرة من المال بسبب هجمات القراصنة، تزداد الحاجة لحلول مستقرة وقوية بل لإجراءات وقائية أيضًا وهذا ما توفره لغة PHP. تعد شيفرتها البرمجية آمنة نسبيًا وذات كما توفر أدوات لحماية البيانات المرسلة إلى قواعد البيانات. بالإضافة إلى ذلك، تشتهر لغة PHP بمرونتها وتوافقها عبر أنظمة التشغيل الأساسية مثل ويندوز ولينكس Linux وماك MacOS وما إلى ذلك. علاوة على ذلك تمنحك لغة PHP توافق مع مجموعة واسعة من الخوادم مثل Apache و iPlanet و Netscape وما إلى ذلك، بالإضافة إلى التكامل مع قواعد البيانات مثل MongoDB و MySQL وغيرها.
</p>

<p>
	ولكن كما أن لها مزايا لها عيوب أيضًا فمثلًا تكون عملية كتابة وحدات الاختبار البرمجي Unit Testing طويلة نسبيًا بسبب سوء معالجتها للأخطاء كما أن بعض المبرمجين ينظرون إلى أن نموذج خادم العميل الذي تتبعه لغة PHP عفا عليه الزمن لأن طريقة عمله التي تطلبُ الصفحة أولًا ومن ثم الاتصال بقاعدة البيانات وتعالج البيانات وتعرض النتائج في صفحة HTML. الأمر الذي يؤدي خسائر في السرعة والفعالية، ولكن من الجدير بالذكر أنه يمكن التغلب على عيب PHP بمساعدة Memcached هو نظام ذاكرة تخزين مؤقت موزع للأغراض العامة، ويستخدم لتسريع مواقع الويب الديناميكية التي تعتمد على قواعد البيانات عن طريق تخزين البيانات والكائنات في ذاكرة الوصول العشوائي مؤقتًا لتقليل عدد المرات التي يتطلب فيها الموقع قراءة البيانات من مصادر خارجية مثل قواعد البيانات، وبالرغم من ذلك هذا الأمر سيخلق تبعية إضافية لتطبيق الويب وهذه مشكلة أيضًا.
</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>
	مقارنة بين PHP vs NodeJS
</h2>

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

<h3>
	المجتمع والتطوير
</h3>

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

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

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="100427" href="https://academy.hsoub.com/uploads/monthly_2022_06/6297c3a6a03cd_Activesoftwaredevelopers.png.dbe6471b24338a31aba97c55e154b739.png" rel=""><img alt="Active software developers.png" class="ipsImage ipsImage_thumbnailed" data-fileid="100427" data-unique="rurk6lx0t" src="https://academy.hsoub.com/uploads/monthly_2022_06/6297c3a6a03cd_Activesoftwaredevelopers.png.dbe6471b24338a31aba97c55e154b739.png"></a>
</p>

<p>
	أما من ناحية عدد المطورين فوفقًا <a href="https://www.slashdata.co/free-resources/developer-economics-state-of-the-developer-nation-19th-edition?" rel="external nofollow">لاستطلاع</a> أجراه موقع Slashdata في عام 2020 جاء فيه أنه يوجد أكثر 12.4 مليون مطور للغة جافاسكربت (اللغة الأساسية لبيئة Node.js) حول العالم بالمقابل 6 ملايين مطور للغة PHP. مما يظهر تفوق واضح للغة جافاسكربت ويجعلها خيارًا جيدًا للشركات الناشئة لأن هنالك عدد كبير من المرشحين لوظيفة مطور لغة جافاسكربت.
</p>

<h3>
	الشيفرة البرمجية
</h3>

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

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

<p>
	بالمقابل صممت لغة PHP لبناء ومعالجة صفحات الويب وجعلها ديناميكية كما تعتمد لغة PHP على شيفرة HTML لجعل كل الصفحات ثابتة في طرف المخدم بعد توليدها وتجهيزها ثم إرسالها إلى متصفح المستخدم أي لن يكون هنالك أي عمليات برمجية تُنفذ في طرف العميل (المتصفح غالبًا)، وبناءً على ذلك فإن تحميل صفحات الويب ستكون أخف على أجهزة المستخدمين ولن تحتاج لقوة معالجة أجهزتهم. كما أن اللغة تتطلب سطورًا أقل من التعليمات البرمجية لأداء وظيفة ما وبالتالي فهي أسهل، وعمومًا من السهولة فهم الشيفرة البرمجية سواء للغة PHP أو Node.js ولن يستغرق المطور المبتدئ وقتًا كبيرًا لإتقان أيًا من اللغتين.
</p>

<h3>
	السرعة والأداء
</h3>

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

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

<p>
	بالرغم من أن لغة PHP متزامنة ولكن هناك بعض واجهات برمجة التطبيقات <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> تعمل بصورة غير متزامنة. هذا ما يجعل استجابة الموقع أبطأ وانتظار المستخدم في نهاية المطاف. في الحقيقة هذه المشكلة موجودة في معظم اللغات والتقنيات القديمة. والخوف الدائم في هكذا نوع من اللغات يكمن في تعطل البرنامج في انتظار الرد والذي يسمى <strong>"جحيم رد الاتصال Callback Hell"</strong> فإذا كانت هناك حاجة إلى ربط الكثير من الدوال ببعضها بعضًا ويتطلب التطبيق نقل البيانات من دالّة إلى أخرى فيجب الحذر عندها من الوقوع في هذه المشكلة.
</p>

<h3>
	أطر العمل
</h3>

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

<p>
	شهدت Node.js توسعًا كبيرًا في أطر العمل الخاصة بها في فترة قصيرة نسبيًا ومن بعض أطر العمل المشهورة نذكر Meteor و Total و Express و Sails وغيرها. بالرغم من حداثة هذه الأطر إلا أنها واعدة ومتطورة باستمرار وبالتأكيد تعزز الإنتاجية وتُقلل وقت التطوير واستهلاك الموارد ولكن أطر عمل لغة PHP تفوقها عددًا بهامش ضخم نظرًا لأقدمية لغة PHP وعمرها الذي يزيد عن 27 عامًا فهي تمتلك أطر عمل غنية جدًا وعادة ما تركز شركات تطوير تطبيقات الويب الحديثة على استخدام واعتماد على هذه الأطر في عملها ومشاريعها أي أنها أصبحت من مُسلمات <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A7%D8%AA/" rel="">تطوير البرمجيات</a> في الوقت الحالي ومن بعض أطر العمل المشهورة نذكر Laravel و CodeIgniter و CakePHP و Phalcon.
</p>

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

<h3>
	التعامل مع قواعد البيانات
</h3>

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

<p>
	يمكن لبيئة Node.js العمل بسهولة مع قواعد بيانات المختلفة مثل NoSQL و MongoDB و CouchDB وغيرها كما أن لديها مكتبات كبيرة للوصول إلى قواعد بيانات SQL.
</p>

<p>
	نظرًا لقدم لغة PHP فهي مصممة للعمل مع قواعد البيانات العلائقية والتقليدية مثل MySQL و MariaDB بقوة في حين أنه من الممكن استيراد مكتبات للعمل مع قواعد بيانات NoSQL ولكن عملية التكامل مع هذه المكتبات طويلة وتستهلك جزءًا كبيرًا من وقت المعالجة.
</p>

<h3>
	معالجة الطلبات
</h3>

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

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

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

<h3>
	التعامل مع الوحدات Modules
</h3>

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

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

<h3>
	النظام البيئي Ecosystem
</h3>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="100426" href="https://academy.hsoub.com/uploads/monthly_2022_06/2008-vs-2021.png.68461b1bcc228c553d24952a3597d479.png" rel=""><img alt="2008-vs-2021.png" class="ipsImage ipsImage_thumbnailed" data-fileid="100426" data-unique="zpcwgk1mv" style="width: 600px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2022_06/2008-vs-2021.thumb.png.60745a8acf5d8493cf55baf808ddb6db.png"></a>
</p>

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

<h2>
	أيهما أفضل PHP أم Node.js؟
</h2>

<p>
	بمجرد أن تفهم لغة جافاسكربت ستصبح اللغات الأخرى غير فعالة بالمقارنة معها لأنك تعلمت لغة واحدة وركزت كل مجهودك عليها فستكون النتائج أسرع وسيتعمقُ فهمك لكيفية سير العمل. يمكن لمطوري الويب الشاملين full stack web developers كتابة شيفرة مشروع كامل من جانب العميل والخادم بلغة جافاسكربت ولم تعد هنالك حاجة إلى التبديل بين اللغات أو التقنيات. كلما تعلمت لغة جافاسكربت زادت استمتاعك بها، وهذا الأمر لا ينطبق على لغة PHP.
</p>

<p>
	من الأفضل اختيار بيئة Node.js عند إنشاء تطبيقات ديناميكية أحادية الصفحة SPA أو Single Page Application باستخدام إطارات جافاسكربت للواجهة الأمامية مثل <a href="https://academy.hsoub.com/programming/javascript/angular/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%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-%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-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-angular-%D9%88%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-firestore-r1409/" rel="">Angular</a> أو <a href="https://academy.hsoub.com/programming/javascript/react/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r1071/?tab=comments" rel="">React</a> أو <a href="https://academy.hsoub.com/programming/javascript/vuejs/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-vuejs-r989/" rel="">Vue.js</a>. أما من جهة الخادم Node.js. يمكن لبيئة Node.js دعم أجهزة إنترنت الأشياء IoT بمفردها مثل أجهزة تتبع اللياقة البدنية والطائرات بدون طيار وحتى الروبوتات بالإضافة إلى منصات تدفق البيانات الثقيلة كونها قادرة على إدارة العديد من العمليات المتزامنة. بعض التوجهات في المشاريع في السوق تعتمد على مطوري MERN وهي اختصارًا (Node.js و React و Express.js و MongoDB) وبعض المشاريع تستخدم إطار Angular بدلًا من إطار React فتصبح MEAN ويمكن استعمال Vue.js ليصبح الاختصار MEVN. بالمقابل تعدُ لغة PHP اختيارًا جيدًا لمدونة أو مشروع تجارة إلكترونية وخصيصًا عندما يتطلب المشروع العديد من عمليات الدمج.
</p>

<h2>
	الخاتمة
</h2>

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

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

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

<p>
	يمكنك الإطلاع على توثيق <a href="https://wiki.hsoub.com/PHP" rel="external">لغة PHP</a> وتوثيق <a href="https://wiki.hsoub.com/Node.js" rel="external">بيئة Node.js</a> على موسوعة حسوب لمزيد من التفصيل حولهما.
</p>

<h2>
	المصادر
</h2>

<ul>
	<li>
		مقال <a href="https://doit.software/blog/nodejs-vs-php#screen18" rel="external nofollow">Node.js vs PHP: In-depth Comparison With Pros &amp; Cons [2021]</a> لكاتبه Serhii Osadchuk.
	</li>
	<li>
		مقال <a href="https://bambooagile.eu/insights/node-js-vs-php/" rel="external nofollow">Node.js vs PHP: Which One is Better for Backend Development</a> لكاتبته Anastasia Kushnir.
	</li>
	<li>
		مقال <a href="https://www.simform.com/blog/nodejs-vs-php/" rel="external nofollow">Node.js vs PHP: A Honest Comparative Study With All The Answers</a> لكاتبه Tejas Kaneriya.
	</li>
	<li>
		مقال <a href="https://www.geeksforgeeks.org/php-vs-node-js/" rel="external nofollow">PHP vs. Node.js - GeeksforGeeks</a> لكاتبه Parikshit Hooda.
	</li>
</ul>

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

<ul>
	<li>
		<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>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/javascript/nodejs/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-nodejs-r1463/" rel="">مقدمة إلى Node.js</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1599</guid><pubDate>Thu, 16 Jun 2022 15:07:00 +0000</pubDate></item><item><title>&#x636;&#x628;&#x637; &#x645;&#x62D;&#x631;&#x643; &#x627;&#x644;&#x642;&#x648;&#x627;&#x644;&#x628; &#x62A;&#x648;&#x64A;&#x63A; &#x648;&#x62A;&#x648;&#x633;&#x64A;&#x639; &#x639;&#x645;&#x644;&#x647;</title><link>https://academy.hsoub.com/programming/php/%D8%B6%D8%A8%D8%B7-%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%AA%D9%88%D9%8A%D8%BA-%D9%88%D8%AA%D9%88%D8%B3%D9%8A%D8%B9-%D8%B9%D9%85%D9%84%D9%87-r1231/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_05/60a752b4582c8_-----.png.4dd050a7cacdfc7fb192ab9c3c54588a.png" /></p>

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

<h2>
	خيارات بيئة العمل في تويغ
</h2>

<p>
	عند استدعاء تويغ فإننا نكتب السطر التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_6" style="">
<span class="pln">$options </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">();</span><span class="pln">
$twig </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Twig\Environment</span><span class="pun">(</span><span class="pln">$loader</span><span class="pun">,</span><span class="pln"> $options</span><span class="pun">);</span></pre>

<p>
	يحوي الوسيط الثاني <code>options</code> خيارات التحكم بطريقة عمل تويغ مثلا لتفعيل وضع تصحيح الأخطاء:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_8" style="">
<span class="pln">$options </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'debug'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">];</span><span class="pln"> </span></pre>

<p>
	حيث تخزن خيارات بيئة العمل على شكل مصفوفة كل عنصر منها يشمل خيارًا محددًا هي:
</p>

<ul>
<li>
		<code>debug</code>: تفعيل وضع تصحيح الأخطاء، القيمة الافتراضية غير مفعل <code>false</code>، وفي حال استخدام تويغ مع ووردبريس فيرتبط بتفعيل الخيار <code>wp_denug</code> في ووردبريس.
	</li>
	<li>
		<code>charset</code>: تحديد طريقة ترميز الأحرف القيمة الافتراضية <code>utf8</code>.
	</li>
	<li>
		<code>cache</code>: فيه نجد المسار الذي سوف نخزن به ملفات PHP الناتجة عن القالب أو نستعمل القيمة <code>false</code> في حال عدم رغبتنا بتخزينها وهذا هو الوضع الافتراضي.
	</li>
	<li>
		<code>auto_reload</code>: يطلب من محرك القالب أن يعيد توليد أو تصريف ملف PHP الناتج عن القالب كل مرة حتى في حال عدم تغير القالب.
	</li>
	<li>
		<code>strict_variables</code>: في حال كون قيمته <code>true</code>، فإن تويغ يعطي خطأ في حال استخدام اسم متغير غير موجود أما في حال ضبطه على <code>false</code> وهو الوضع الافتراضي فإن تويغ يعيد قيمة فارغة في حال لم يعثر على المتغير المطلوب.
	</li>
	<li>
		<code>autoescape</code>: يطلب من تويغ القيام بعملية تهريب آمنة مناسبة عند إخراج أي متغير.
	</li>
</ul>
<h3>
	استخدام الدالة dump في وضع تصحيح الأخطاء
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_10" style="">
<span class="pun">{{</span><span class="pln"> </span><span class="kwd">dump</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_1747_12" style="">
<span class="pun">{{</span><span class="pln"> </span><span class="kwd">dump</span><span class="pun">(</span><span class="pln"> user </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_1747_14" style="">
<span class="pun">{{</span><span class="pln"> post</span><span class="pun">.</span><span class="pln">title </span><span class="pun">}}</span></pre>

<p>
	فإننا يمكن أن نعدل الكود ليصبح على الشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_18" style="">
<span class="pun">{{</span><span class="pln"> post</span><span class="pun">.</span><span class="pln">title </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{{</span><span class="pln"> </span><span class="kwd">dump</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="pun">{#</span><span class="pln"> the </span><span class="kwd">last</span><span class="pln"> line output</span><span class="pun">:</span><span class="pln">
 </span><span class="kwd">object</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">public</span><span class="pln"> </span><span class="pun">‘</span><span class="pln">title</span><span class="pun">’</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">‘’</span><span class="pln"> 
 </span><span class="kwd">public</span><span class="pln"> content </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> </span><span class="pun">‘</span><span class="kwd">my</span><span class="pln"> post</span><span class="pun">’</span><span class="pln"> 
</span><span class="com">#}</span></pre>

<p>
	لاحظ أن الدالة السابقة تعيد جميع خصائص الكائن post مع نوع كل خاصية مما يسهل تتبع الأخطاء.
</p>

<h2>
	توسيع عمل تويغ
</h2>

<p>
	يهدف توسيع تويغ إلى تمكين المستخدِم من العديد من التقنيات غير المتوفرة بشكل افتراضي في تويغ.
</p>

<h3>
	التوسيع بواسطة مكتبات جاهزة
</h3>

<p>
	Twig مرن جدا بحيث يسمح للمطور بسهول بتعريف مرشحات ودوال خاصة، كما توجد العديد من المكتبات الجاهزة التي تدعم تويغ وتضيف له العديد من المرشحات والدوال الإضافية مثلا يمكن الاطلاع من <a data-ss1622300064="1" data-ss1625245242="1" href="https://github.com/twigphp" rel="external nofollow">هذه الصفحة</a> على قائمة ببعض المكتبات الشهيرة وتحميلها.
</p>

<h3>
	استخدام التوسعات Extensions
</h3>

<p>
	توسعات Twig هي حزم تضيف مزايا جديدة إليه، وتستطيع تسجيل توسعة من خلال التابع <code>addExtension()‎</code>:
</p>

<ul>
<li>
		عند العمل بدون composer
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_20" style="">
<span class="pln">$twig</span><span class="pun">-&gt;</span><span class="pln">addExtension</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ExtensionClassName</span><span class="pun">());</span></pre>

<ul>
<li>
		كما يمكن أن يتم تسجيل التوسعة من خلال composer:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_22" style="">
<span class="pln">$ composer </span><span class="kwd">require</span><span class="pln"> twig</span><span class="pun">/</span><span class="pln">extension</span><span class="pun">-</span><span class="pln">file</span></pre>

<p>
	بعد إضافة توسعة إلى تويغ يمكن استخدام الدوال أو المرشحات الجديدة التي تحتويها، مثلا المكتبة <a data-ss1622300064="1" data-ss1625245242="1" href="https://github.com/twigphp/markdown-extra" rel="external nofollow">markdown-extra</a> تضيف عددًا من المرشحات التي تتعامل مع نصوص من نوع ماركدون:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_27" style="">
<span class="pun">{%</span><span class="pln"> apply html_to_markdown </span><span class="pun">%}</span><span class="pln">
    </span><span class="str">&lt;h2&gt;</span><span class="typ">Title</span><span class="pln"> </span><span class="lit">2</span><span class="pun">&lt;/</span><span class="pln">h2</span><span class="pun">&gt;</span><span class="pln">
    </span><span class="str">&lt;h3&gt;</span><span class="typ">Title</span><span class="pln"> </span><span class="lit">3</span><span class="pun">&lt;/</span><span class="pln">h3</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endapply </span><span class="pun">%}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> output</span><span class="pun">:</span><span class="pln"> 
</span><span class="com">## Title 2 </span><span class="pln">
</span><span class="com">### Title 3 </span><span class="pln">
</span><span class="com">#}</span></pre>

<h3>
	التوسيع بواسطة الشيفرة الجامعة macro
</h3>

<p>
	أن أبسط طريقة لتوسيع تويغ هو استخدام تويغ نفسه ويتم ذلك من خلال الوسم <code><a data-ss1622300064="1" data-ss1625245242="1" href="https://wiki.hsoub.com/Twig/macro" rel="external">macro</a></code> حيث يمكننا من تعريف شيفرة جامعة خاصة بنا يمكننا إعادة استخدامها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_29" style="">
<span class="pun">{%</span><span class="pln"> macro </span><span class="typ">EcoHello</span><span class="pun">(</span><span class="pln"> student </span><span class="pun">)</span><span class="pln"> </span><span class="pun">%}</span><span class="pln"> 
    </span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> student </span><span class="pun">}}!</span><span class="pln"> 
</span><span class="pun">{%</span><span class="pln"> endmacro </span><span class="pun">%}</span><span class="pln">
</span><span class="pun">{{</span><span class="pln"> _self</span><span class="pun">.</span><span class="typ">EcoHello</span><span class="pun">(</span><span class="str">'Ziad'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> output</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln"> </span><span class="typ">Ziad</span><span class="pun">!</span><span class="pln"> </span><span class="com">#}</span></pre>

<p>
	يمكن تعريف الشيفرات الجامعة في ملف تويغ منفصل ثم استيراده في الملف الحالي، مثلا ننشأ ملف اسمه macros.twig، ونكتب به ما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_32" style="">
<span class="pun">{#</span><span class="pln"> macros</span><span class="pun">.</span><span class="pln">twig </span><span class="com">#}</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> macro </span><span class="typ">EcoHello</span><span class="pun">(</span><span class="pln"> student </span><span class="pun">)</span><span class="pln"> </span><span class="pun">%}</span><span class="pln">
</span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> student </span><span class="pun">}}!</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endmacro </span><span class="pun">%}</span></pre>

<p>
	ثم عند الرغبة في استخدام هذا الماكرو نستورد الملف على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_35" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> </span><span class="str">"macros.twig"</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> mymacros </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"> mymacros</span><span class="pun">.</span><span class="typ">EcoHello</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">defined</span><span class="pln"> </span><span class="pun">%}</span><span class="pln">
    </span><span class="pun">{{</span><span class="pln"> mymacros</span><span class="pun">.</span><span class="typ">EcoHello</span><span class="pun">(</span><span class="str">'Ziad'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endif </span><span class="pun">%}</span><span class="pln">
</span><span class="pun">{{</span><span class="pln"> mymacros</span><span class="pun">.</span><span class="typ">EcoHello</span><span class="pun">(</span><span class="str">'Ziad'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> output</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln"> </span><span class="typ">Ziad</span><span class="pun">!</span><span class="pln"> </span><span class="com">#}</span></pre>

<p>
	كما لا حظنا في المثال السابق يمكن أن نتحقق من وجود شيفرة جامعة قبل استخدامها للتأكد من أنها مُعرَّفة في الملف الذي استوردته.
</p>

<p>
	ملاحظة: يمكن كتابة السطر الأول على النحو التالي وذلك يؤدي نفس الهدف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_39" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> </span><span class="str">"macros.twig"</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> mymacros </span><span class="pun">%}</span></pre>

<h3>
	المتغيرات العامة
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_37" style="">
<span class="pln">$twig </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Twig_Environment</span><span class="pun">(</span><span class="pln">$loader</span><span class="pun">);</span><span class="pln">
$twig</span><span class="pun">-&gt;</span><span class="pln">addGlobal</span><span class="pun">(</span><span class="str">'MyWebsite'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'example.com'</span><span class="pun">);</span></pre>

<p>
	بعد ذلك يمكن استعمال المغير السابق في أي قالب على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_42" style="">
<span class="pun">{{</span><span class="pln"> </span><span class="typ">MyWebsite</span><span class="pln"> </span><span class="pun">}}</span></pre>

<h2>
	إنشاء مرشحات مخصصة
</h2>

<p>
	لإضافة أي مرشح إلى تويغ نقوم بتعديل الملف الذي نستدعيه لتثيبت تويغ أو لإخراج القالب ونضيف المرشح عليه، ويمكنك مراجعة <a data-ss1622300064="1" data-ss1625245242="1" href="https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%AA%D9%88%D9%8A%D8%BA-twig-r1227/" rel="">المقال الأول لمعرفة المزيد عن تثبيت تويغ</a>. مثلا في الأسطر الثلاث الأخيرة من الشيفرة التالية سوف نلاحظ أننا قمنا بتعريف مرشح ثم أضفناه إلى تويغ ثم أعطينا الأمر بإخراج المستند المنسق:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_44" style="">
<span class="pun">&lt;?</span><span class="pln">php
spl_autoload_register</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$classname</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $filename </span><span class="pun">=</span><span class="pln"> </span><span class="str">'./'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> str_replace</span><span class="pun">(</span><span class="str">'\\'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> $classname</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="str">'.php'</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">file_exists</span><span class="pun">(</span><span class="pln">$filename</span><span class="pun">))</span><span class="pln"> require_once $filename</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
require_once </span><span class="str">'Twig\Loader\FilesystemLoader.php'</span><span class="pun">;</span><span class="pln">
$loader </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Twig</span><span class="pln">\Loader\FilesystemLoader</span><span class="pun">(</span><span class="str">'.'</span><span class="pun">);</span><span class="pln">
$twig </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Twig</span><span class="pln">\Environment</span><span class="pun">(</span><span class="pln">$loader</span><span class="pun">);</span><span class="pln">
$filter </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Twig</span><span class="pln">\TwigFilter</span><span class="pun">(</span><span class="str">'countchars'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'count_chars'</span><span class="pun">);</span><span class="pln">
$twig</span><span class="pun">-&gt;</span><span class="pln">addFilter</span><span class="pun">(</span><span class="pln">$filter</span><span class="pun">);</span><span class="pln">
echo $twig</span><span class="pun">-&gt;</span><span class="pln">render</span><span class="pun">(</span><span class="str">'template.twig'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'var1'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'value1'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'var2'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'value2'</span><span class="pun">]);</span></pre>

<p>
	لقد أضفنا مرشح أسميناه countchars يستدعي هذا المرشح دالة PHP موجدة اسمها count_chars وهي تعيد عدد الأحرف في نص ما و لاستدعاء هذا المرشح في ملف تويغ نستعمله مثل أي مرشح آخر قد تم استدعائها في القالب التالي عند كتابة اسم المرشح الذي اضفناه <code>countchars</code> مسبوقا بـ | :
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_46" style="">
<span class="pun">{{</span><span class="pln"> </span><span class="str">'Ziad'</span><span class="pun">|</span><span class="pln">countchars </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> output</span><span class="pun">:</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="com">#}</span></pre>

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

<p>
	قد تكون تلك الدوال مبية في لغة PHP وقد تكون دوال من إنشاء المطور نفسه.
</p>

<h2>
	إضافة دوال خاصة
</h2>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_49" style="">
<span class="pln">$function </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Twig\TwigFunction</span><span class="pun">(</span><span class="str">'SayHello'</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"> </span><span class="str">'Hello'</span><span class="pun">;</span><span class="pln"> </span><span class="pun">});</span><span class="pln">
$twig</span><span class="pun">-&gt;</span><span class="pln">addFunction</span><span class="pun">(</span><span class="pln">$function</span><span class="pun">);</span></pre>

<p>
	بعد ذلك يمكن استدعائها في أي قالب على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1747_51" style="">
<span class="pun">{{</span><span class="pln"> </span><span class="typ">SyaHello</span><span class="pun">()</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> output</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln"> </span><span class="com">#}</span></pre>

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

<h2>
	كلمة الختام
</h2>

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

<p>
	بهذا القدر من المفترض بك عزيزي القارئ أن تكون قد وصلت فكرة واضحة عن تويغ بحيث يمكن الانطلاق بقوة في العمل مع تويغ وفي حال رغبتك بالمزيد من التفاصيل يمكنك مراجعة الترجمة العربية لل<a data-ss1622300064="1" data-ss1625245242="1" href="https://wiki.hsoub.com/Twig" rel="external">توثيق الرسمي لتويغ</a> في موسوعة حسوب.
</p>
]]></description><guid isPermaLink="false">1231</guid><pubDate>Sat, 29 May 2021 15:00:00 +0000</pubDate></item><item><title>&#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x639;&#x645;&#x644;&#x64A;&#x629; &#x639;&#x644;&#x649; &#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x62A;&#x648;&#x64A;&#x63A;</title><link>https://academy.hsoub.com/programming/php/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%B9%D9%84%D9%89-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%AA%D9%88%D9%8A%D8%BA-r1230/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_05/60a74f7d5bdf7_----.png.318b5f0f16332abe47e5a3862e0060e8.png" /></p>

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

<h2>
	تطبيقات شهيرة تستخدم تويغ
</h2>

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

<h3>
	سيمفوني
</h3>

<p>
	يُعَدّ <a data-ss1622300102="1" data-ss1622300354="1" data-ss1625245239="1" href="https://symfony.com/" rel="external nofollow">سيمفوني symfony </a>أحد إطارات العمل المتكاملة التي توفر العديد من المزايا لمصممي تطبيقات الويب المتكاملة حيث يوفر على المبرمج الوقت والجهد يستخدم سيمفوني تويغ لتوليد قوالب الصفحات.
</p>

<h3>
	دروبال
</h3>

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

<p>
	في دروبال تم اعتماد تويغ في تصميم القوالب بدءًا من الإصدار الثامن، لمزيد من المعلومات يمكنك الرجوع إلى <a data-ss1622300102="1" data-ss1622300354="1" data-ss1625245239="1" href="https://www.drupal.org/docs/theming-drupal/twig-in-drupal" rel="external nofollow">هذه الصفحة</a>.
</p>

<h3>
	بلوت
</h3>

<p>
	بلوت Bolt هو نظام إدارة محتوى خفيف وقد اعتمد تويغ لتصميم قوالب الصفحات، الفرق بين بلوت و ووردبرس هو أن بلوت لا يستهلك إلا القليل جدا من موارد النظام يمكنك الرجوع إلى <a data-ss1622300102="1" data-ss1622300354="1" data-ss1625245239="1" href="https://docs.bolt.cm/4.0/twig-components" rel="external nofollow">هذه الصفحة</a> لمزيد من المعلومات.
</p>

<h3>
	ووردبرس
</h3>

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

<h2>
	تصميم قوالب فرعية في ووردبريس
</h2>

<p>
	نظرا لشعبية ووردبريس فلقد اخترنا أن ننشئ قالبًا فرعيا في ووردبريس كتطبيق عملي على تويغ ولكن ما هو القالب الفرعي؟
</p>

<h3>
	القالب والقالب الفرعي في ووردبريس
</h3>

<p>
	لنسأل أنفسنا، ما هو القالب في ووردبريس WordPress Theme؟
</p>

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

<p>
	في ووردبريس لست مضطرًا لتبدأ من الصفر عند تصميم أي قالب ووردبريس خاص بك، ويمكنك الانطلاق من قالب ووردبرس موجود مع تعديل بعض الصفحات أو الخصائص به بما يناسبك، وهذه التعديلات والإضافات التي تجرى تدخل ضمن ما يسمى <a data-ss1622300102="1" data-ss1622300354="1" data-ss1625245239="1" href="https://academy.hsoub.com/programming/php/wordpress/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%B4%D8%A6-%D9%82%D8%A7%D9%84%D8%A8-%D9%88%D9%88%D8%B1%D8%AF%D8%A8%D8%B1%D9%8A%D8%B3-%D9%81%D8%B1%D8%B9%D9%8A-r107/" rel="">بالقالب الفرعي أو الابن</a> WordPress Child Theme.
</p>

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

<p>
	اتبع الخطوات التالية التي اخترناها لك في هذا المقال لتصميم قالب فرعي خاصة بك:
</p>

<ol>
<li>
		كامل الكود الناتج متوفر <a data-fileid="68073" data-ss1622300354="1" data-ss1625245239="1" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=68073" rel="">للتحميل بشكل مباشر</a> في نهاية المقال
	</li>
	<li>
		من خلال مدير الملفات في خطة الاستضافة الخاصة بك اذهب إلى المجلد الحاوي على ووردبريس ثم انتقل إلى المجلد التالي: /wp-content/themes/
	</li>
	<li>
		ضمن المجلد السابق أنشئ مجلد فرعيًا وسمه باسم twig-child-theme أو أي اسم تريده بشرط أن لا يحوي مسافات فيه
	</li>
	<li>
		في المجلد السابق أنشئ الملفين التاليين: style.css وfunctions.php
	</li>
	<li>
		أضف أية ملفات أخرى تحتاجها: في مثالنا نحتاج ثلاث ملفات إضافية هي: single.php وsingle.twig وmain-file.twig
	</li>
</ol>
<p>
	المحتويات الأساسية لملفات القالب الفرعي:
</p>

<ul>
<li>
		الملف style.css:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_6298_7" style="">
<span class="lit">@charset</span><span class="pln"> </span><span class="str">"UTF-8"</span><span class="pun">;</span><span class="pln">
</span><span class="com">/*
Theme Name:  Twig Child Theme
Template:    twentytwentyone
Version:     1.0
Text Domain: twig-child-theme
*/</span></pre>

<ul>
<li>
		الملف functions.php:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5499_8" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">//functions.php</span><span class="pln">
add_action</span><span class="pun">(</span><span class="pln"> </span><span class="str">'wp_enqueue_scripts'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'enqueue_parent_styles'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> enqueue_parent_styles</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   wp_enqueue_style</span><span class="pun">(</span><span class="pln"> </span><span class="str">'parent-style'</span><span class="pun">,</span><span class="pln"> get_template_directory_uri</span><span class="pun">().</span><span class="str">'/style.css'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	ووردبريس و تويغ
</h3>

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

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

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

<h3>
	تنصيب تويغ ضمن ووردبريس
</h3>

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

<p>
	يرجى ملاحظة أن timber هي إضافة ووردبريس عادية مثل أي اضافة أخرى يمكن تركيبها مثل أي إضافة أخرى وهي متوفرة عبر الرابط التالي <a data-ss1622300102="1" data-ss1622300354="1" data-ss1625245239="1" href="https://wordpress.org/plugins/timber-library/" rel="external nofollow">Timber</a>.
</p>

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

<h3>
	بناء القالب الفرعي
</h3>

<p>
	أي قالب ووردبرس مستقل يجب أن يحوي على الأقل ملفين أساسيين:
</p>

<ol>
<li>
		ملف style.css
	</li>
	<li>
		ملف index.php
	</li>
</ol>
<p>
	أما في القوالب الفرعية، فيمكن الاستغناء عن الملف الثاني حيث يُستخدم الملف index.php الموجود في القالب الأب نفسه.
</p>

<p>
	عندما يظهر ووردبريس أي صفحة فإنه يبحث في ملفات القالب عن أنسب ملف لعرض تلك الصفحة وفق مبدأ أولية الملفات، يُعَدّ الملف index.php الخيار الأخير حيث يتم اختياره فقط في حال عدم توفر أي ملف أكثر تحديدا وأكثر ملائمةً للمقال.
</p>

<p>
	قد يحتوي قالب ووردبريس على ملف مخصص لعرض الصفحات الثابتة وآخر لعرض المقالات وآخر لعرض الأرشيف مثلا عن الرغبة بعرض مقال ما فإن ووردبرس يبحث عن ملف single.php هو يعني مقال مفرد، اختصار للاسم single-post، فإذا وجده استخدمه لعرض المقال أما عندما لا يجده فإنه يبحث عن ملف singular.php وهو يعني مقال أو صفحة ثابتة فإذا وجد الملف singular.php فإنه يستخدمه، أخيرا في حال لم يجد أي من الملفين السابقين فإن ووردبرس يستخدم الخيار الأخير وهو index.php.
</p>

<p>
	لقد اصطلح ووردبريس ذلك التسلسل وتلك الأسماء في بنيته الداخلية ويمكن مراجعة ملفات قوالب ووردبريس عبر الرابط التالي <a data-ss1622300102="1" data-ss1622300354="1" data-ss1625245239="1" href="https://developer.wordpress.org/themes/template-files-section/post-template-files" rel="external nofollow">WordPress Post Template Files</a>.
</p>

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

<p>
	لمعرفة تفاصيل أكثر عن ملفات القالب في ووردبرس يمكن زيارة الرابط التالي <a data-ss1622300102="1" data-ss1622300354="1" data-ss1625245239="1" href="https://developer.wordpress.org/themes/template-files-section/" rel="external nofollow">Template Files Section</a>.
</p>

<p>
	يحوي ووردبرس على متغير عام اسمه posts يحوي جميع المقالات الموجود في الدليل أو الأرشيف الحالي ويمكن استخدامه في حلقات <code>for</code>.
</p>

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

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5499_10" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">/**
 * file name: single.php
 * The Template for displaying all single posts 
 */</span><span class="pln">
$context         </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Timber</span><span class="pun">::</span><span class="pln">context</span><span class="pun">();</span><span class="pln">
$timber_post     </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Timber</span><span class="pun">::</span><span class="pln">get_post</span><span class="pun">();</span><span class="pln">
$context</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"> $timber_post</span><span class="pun">;</span><span class="pln">
</span><span class="typ">Timber</span><span class="pun">::</span><span class="pln">render</span><span class="pun">(</span><span class="pln"> </span><span class="str">'single.twig'</span><span class="pun">,</span><span class="pln"> $context </span><span class="pun">);</span></pre>

<p>
	أما ملف تويغ single.twig فسوف يحوي تعليمات تويغ التي نريدها لإظهار القالب، وفي مثال على ذلك، لدينا الآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5499_12" style="">
<span class="pln">{# single.twig #}
</span><span class="dec">&lt;!doctype html&gt;</span><span class="pln">
</span><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;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">name</span><span class="pun">=</span><span class="atv">"description"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"{{ site.description }}"</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">href</span><span class="pun">=</span><span class="atv">"{{ site.theme.link }}/style.css"</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="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;article&gt;</span><span class="pln">
        </span><span class="tag">&lt;h1&gt;</span><span class="pln">{{ post.title }}</span><span class="tag">&lt;/h1&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">"{{ post.thumbnail.src }}"</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">"article-body"</span><span class="tag">&gt;</span><span class="pln"> {{post.content}} </span><span class="tag">&lt;/div&gt;</span><span class="pln">
    </span><span class="tag">&lt;/article&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>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5499_14" style="">
<span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"description"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"{{ site.description }}"</span><span class="tag">&gt;</span></pre>

<p>
	تم الطلب من محرك القالب أن يخرج قيمة وصف الموقع حيث لدينا متغير اسم <code>site</code> وهذا المتغير يحتوي على عدة معلومات فرعية أو خصائص منها <code>description</code> ومن أجل وصف الموقع قمنا بكتابة <code>{{ site.description }}</code>.
</p>

<p>
	في السطر السابع تم استخدام عبارة مشابهة لإخراج المسار الكامل للقالب الذي نعمل به وربط ملف css بالموقع، وقد تم استخدام الشيفرة <code>{{ post.title }}</code> لإظهار عنوان المقال وبطريقة مشابهة تم إظهار صورة المقال ومحتوياته.
</p>

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

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

<h3>
	الكتل ووراثة القوالب في تويغ
</h3>

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

<p>
	لتعريف كتلة ما نقوم باستخدام الصيغة <code>{% %}</code> التي تخبر محرك القالب أن عليه أن يفعل شيئًا ما وفي حالتنا هو تعريف كتلة محددة. تبدأ كل كتلة بعبارة من الشكل <code>{% block name %}</code> حيث نضع اسم الكتلة بعد الكلمة <code>block</code>، وتنتهي كل كتلة بعبارة <code>{% endblock %}</code>، وتخزن التعليمات داخل الكتلة واستدعائها عند الحاجة.
</p>

<p>
	تعمل الكتل ووراثة القوالب بشكل متناغم في تويغ فنحن نقوم عادة بتعريف الكتل في القالب الأب ثم نعدل محتويات الكتلة في القوالب المشتقة منه ويفدينا ذلك بشكل كبير في تقسيم الملفات مما يسهل العمل.
</p>

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

<p>
	لنطبق ذلك، يمكن تقسيم ملف تويغ الذي ذُكِر بالفقرة السابقة إلى قسمين: الأول الملف الرئيسي ويحوي البنية الأساسية للملفات مع وضع تعريف للكتل في مكانها الصحيح:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5499_16" style="">
<span class="pln">{# main-file.twig #}
</span><span class="dec">&lt;!doctype html&gt;</span><span class="pln">
</span><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;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">name</span><span class="pun">=</span><span class="atv">"description"</span><span class="pln"> </span><span class="atn">content</span><span class="pun">=</span><span class="atv">"{{ site.description }}"</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">href</span><span class="pun">=</span><span class="atv">"{{ site.theme.link }}/style.css"</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="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">
    {% block content %}{% endblock %}
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	أما الملف الفرعي الثاني فهو يحوي الإشارة إلى الملف الرئيسي مع تعريف محتويات الكتل فيه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_5499_18" style="">
<span class="pun">{#</span><span class="pln"> single</span><span class="pun">.</span><span class="pln">twig </span><span class="com">#}</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="str">"main-file.twig"</span><span class="pln"> </span><span class="pun">%}</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> block content </span><span class="pun">%}</span><span class="pln">
</span><span class="str">&lt;article&gt;</span><span class="pln">
   </span><span class="str">&lt;h1&gt;</span><span class="pun">{{</span><span class="pln"> post</span><span class="pun">.</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">img src</span><span class="pun">=</span><span class="str">"{{ post.thumbnail.src }}"</span><span class="pln"> alt</span><span class="pun">=</span><span class="str">"{{ post.thumbnail.alt }}"</span><span class="pln"> </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">"article-body"</span><span class="pun">&gt;{{</span><span class="pln"> post</span><span class="pun">.</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">article</span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endblock </span><span class="pun">%}</span></pre>

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

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

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

<p>
	لمزيد من المعلومات عن الكتل والوراثة في تويغ يمكن زيارة قسم <a data-ss1622300102="1" data-ss1622300354="1" data-ss1625245239="1" href="https://wiki.hsoub.com/Twig/templates#.D9.88.D8.B1.D8.A7.D8.AB.D8.A9_.D8.A7.D9.84.D9.82.D9.88.D8.A7.D9.84.D8.A8" rel="external">وراثة القوالب في Twig</a> في موسوعة حسوب.
</p>

<h2>
	الخلاصة
</h2>

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

<p>
	في المقال القادم سوف نلقي نظرةً على بنية تويغ وطريقة تخصيص بيئة العمل الخاصة به.
</p>

<p>
	<a class="ipsAttachLink" data-fileid="68073" data-ss1622300354="1" data-ss1625245239="1" href="https://academy.hsoub.com/applications/core/interface/file/attachment.php?id=68073" rel="">twig-child-theme-main.zip</a>
</p>
]]></description><guid isPermaLink="false">1230</guid><pubDate>Thu, 27 May 2021 15:08:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x628;&#x646;&#x627;&#x621; &#x627;&#x644;&#x642;&#x648;&#x627;&#x644;&#x628; &#x639;&#x628;&#x631; &#x62A;&#x648;&#x64A;&#x63A; Twig</title><link>https://academy.hsoub.com/programming/php/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A8%D9%86%D8%A7%D8%A1-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%B9%D8%A8%D8%B1-%D8%AA%D9%88%D9%8A%D8%BA-twig-r1229/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_05/60a748483630f_-----Twig.png.0ee56d13abcb3027775de75116b50b62.png" /></p>

<p>
	يقدم تويغ تقنيات أكثر بكثير مما تم شرحه في المقالين السابقين، <a data-ss1621948291="1" data-ss1625245236="1" href="https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%AA%D9%88%D9%8A%D8%BA-twig-r1227/" rel="">مدخل إلى محرك القوالب تويغ Twig</a>، و<a data-ss1621948291="1" data-ss1625245236="1" href="https://academy.hsoub.com/programming/php/%D8%A7%D9%86%D8%B7%D9%84%D8%A7%D9%82%D8%A9-%D8%B3%D8%B1%D9%8A%D8%B9%D8%A9-%D9%85%D8%B9-%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%AA%D9%88%D9%8A%D8%BA-r1228/" rel="">انطلاقة سريعة مع محرك القوالب تويغ</a>. إذ يتألف القالب في تويغ من أربع فئات أساسية هي: الوسوم والمرشحات والدوال والاختبارات، وهو ما سنتحدث عنه في هذا المقال.
</p>

<h2>
	الوسوم Tags في تويغ
</h2>

<p>
	الوسوم في Twig هي الأوامر التي تستخدم في صيغة افعل شيئا ما
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_6" style="">
<span class="pun">{%</span><span class="pln">    </span><span class="pun">%}</span></pre>

<p>
	وهي بنيات تحكم، تتحكم في طريقة عمل القوالب وسيرها، فيعد كل من <code>if</code> و <code>for</code> التي تحدثنا عنها في المقال السابق انطلاقة سريعة مع محرك القوالب تويغ، نوعًا من الوسوم في تويغ ولكنها ليست الوحيدة المتاحة هناك حوالي 20 وسمًا مختلفًا في تويغ يمكنك الاطلاع عليها في <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/tags" rel="external">الرابط التالي</a> ولن نتناول كل تلك الوسوم فالهدف من هذه المقالات هو تمكين القارئ من المضي قدمًا في تويغ وليس الإحاطة بكل ما فيه من تقنيات.
</p>

<p>
	نذكر أن كل وسم في تويغ يحتاج إلى كتلة إغلاق للوسم وتتكون وتكون كتلة الإغلاق:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_8" style="">
<span class="pun">{%</span><span class="pln"> endtag </span><span class="pun">%}</span></pre>

<p>
	حيث تتبع <code>end</code> باسم الوسم دون فراغ. مثلا يحتاج الوسم <code>if</code> إلى كتلة الإغلاق <code>{% endif %}</code> ويحتاج الوسم <code>for</code> إلى كتلة الإغلاق <code>{% endfor %}</code> وهكذا.
</p>

<h3>
	الوسم set والمتغيرات الداخلية في القالب
</h3>

<p>
	يمكننا أن نعرف متغير ما داخل القالب نفسه باستخدام الوسم <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/set" rel="external"><code>set</code></a> مثلا في السطر التالي تم تعريف المتغير <code>student،</code> وتم إسناد القيمة ziad له:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_10" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> student </span><span class="pun">=</span><span class="pln"> </span><span class="str">'ziad'</span><span class="pln"> </span><span class="pun">%}</span><span class="pln">
    </span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> student </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> output</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln"> ziad </span><span class="com">#}</span></pre>

<p>
	يمكن للمتغير أن يكون رقما أو نصا أو مصفوفة، مثل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_13" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> age </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="pun">{%</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> colors </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'red'</span><span class="pun">,</span><span class="pln"> yellow</span><span class="str">'] %}</span></pre>

<p>
	هناك طريقة ثانية في تويغ لإسناد قيمة للمتغير وهي على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_17" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> student </span><span class="pun">%}</span><span class="pln">
    </span><span class="typ">Ziad</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endset </span><span class="pun">%}</span></pre>

<p>
	لاحظ في الطريقة الأولى أننا تضع علامة المساواة بعد اسم المتغير ثم نضع بعدها قيمة المتغير أما في الطريقة الثانية فإننا نغلق تعليمة تعريف المتغير ثم نكتب قيمته ثم نضع عبارة <code>{% endset %}</code>.
</p>

<h3>
	الوسم include
</h3>

<p>
	يُستخدَم الوسم <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/include" rel="external"><code>include</code></a> لإدراج محتويات قالب آخر ضمن القالب الحالي مما يتيح لنا تقسيم الملفات أو إعادة استخدام أجزاء منها، فيمكن أيضا إدراج محتويات أي ملف نصي عادي أيضًا وليس فقط ملف تويغ.
</p>

<p>
	لنفرض مثلًا أننا نريد أن نكتب صفحات ويب ونريد اختصار الجهد بتفادي كتابة ترويسة html في كل صفحة عندها ننشئ ملف نسميه header.twig:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8195_19" style="">
<span class="pln">{# file name: header.twig #}
</span><span class="dec">&lt;!doctype html&gt;</span><span class="pln">
</span><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;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;title&gt;</span><span class="pln">{{ title }}</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">{{ title }}</span><span class="tag">&lt;/h1&gt;</span></pre>

<p>
	بعد ذلك يمكننا كتابة أي صفحة نريدها على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8195_21" style="">
<span class="pln">{# كتابة صفحة بطريقة سريعة #}
{% include ‘header.twig’ %}
My 1st article
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يمكننا أيضا أن نمرر متغير إلى ملف الترويسة بحيث نحدد عنوان صفحة ويب:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8195_23" style="">
<span class="pln">{# تمرير متغير إلى الملف المطلوب إدراجه #}
{% include ‘header.twig’ with {'title': 'My 1st page'} %}
My 1st article
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_26" 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="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="pun">{%</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> description </span><span class="pun">%}</span><span class="pln">
    </span><span class="pun">{%</span><span class="pln"> include </span><span class="pun">‘</span><span class="pln">description</span><span class="pun">.</span><span class="pln">txt</span><span class="pun">’</span><span class="pln"> </span><span class="pun">%}</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endset </span><span class="pun">%}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> </span><span class="com">#}</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> description </span><span class="pun">=</span><span class="pln"> include</span><span class="pun">(</span><span class="str">'description.txt'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%}</span></pre>

<p>
	لمزيد من المعلومات عن الوسوم في تويغ يمكن زيارة صفحة <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/tags" rel="external">الوسوم</a> على موسوعة حسوب.
</p>

<h2>
	ما هي المرشحات في تويغ
</h2>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_28" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> student </span><span class="pun">=</span><span class="pln"> </span><span class="str">'ziad'</span><span class="pln"> </span><span class="pun">%}</span><span class="pln">
</span><span class="typ">Welcome</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> student</span><span class="pun">|</span><span class="pln">upper </span><span class="pun">}}</span><span class="pln">
</span><span class="typ">Hello</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> student </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> outputs</span><span class="pun">:</span><span class="pln">
   </span><span class="typ">Welcome</span><span class="pln"> ZIAD
   </span><span class="typ">Hello</span><span class="pln"> ziad </span><span class="com">#}</span></pre>

<p>
	المثال السابق يُستخدم المرشح <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/upper" rel="external"><code>upper</code></a> لجعل الأحرف كبيرة قبل إظهار قيمة المتغير <code>name</code>، مع ملاحظة أن القيم المخزنة في المتغير لم تتغير بل بقيت كما هي عندما تم استدعائها مرة ثانية دون المرشح السابق.
</p>

<p>
	يمكننا أيضا استخدام الوسم <code>apply</code> للتعامل مع المرشحات على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_34" style="">
<span class="pun">{%</span><span class="pln"> apply upper </span><span class="pun">%}</span><span class="pln">
    </span><span class="typ">Hello</span><span class="pln"> ziad
</span><span class="pun">{%</span><span class="pln"> endapply </span><span class="pun">%}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> output</span><span class="pun">:</span><span class="pln"> HELLO ZIAD </span><span class="com">#}</span></pre>

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

<h3>
	المرشحات upper وlower وcapitalizes
</h3>

<p>
	لقد شاهدنا أن المرشح <code>upper</code> يقوم بتحويل النص إلى الحروف الكبيرة بينما المرشح <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/lower" rel="external"><code>lower</code></a> يعطي النص مكتوبًا بالحروف الصغيرة أما <code>capitalizes</code> فهو يحول أول حرف من الجملة فقط إلى حرف كبير:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_32" style="">
<span class="pun">{{</span><span class="pln"> </span><span class="str">'my first car'</span><span class="pun">|</span><span class="pln">capitalize </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> outputs </span><span class="str">'My first car'</span><span class="pln"> </span><span class="com">#}</span></pre>

<h3>
	مرشح التنسيق Format
</h3>

<p>
	يقوم المرشح <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/format" rel="external"><code>format</code></a> بوضع نص محدد بدلا عن نائب النص <code>s%</code> انظر مثلًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_36" style="">
<span class="pun">{{</span><span class="pln"> </span><span class="str">"Hello student %s"</span><span class="pun">|</span><span class="pln">format</span><span class="pun">(</span><span class="str">'Ziad'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> output</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Hello</span><span class="pln"> student </span><span class="typ">Ziad</span><span class="pln"> </span><span class="com">#}</span></pre>

<h3>
	مرشح هروب الأمان Escape
</h3>

<p>
	يعد من أهم المرشحات حيث يستخدم للتخلص من أية وسوم قد تسبب مشاكل في الإظهار ويفضل استخدامه دوما مع المتغيرات النصية. يمكن اختصار استخدام المرشح <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/escape" rel="external"><code>escape</code></a> إلى <code>e</code> حيث يمكن كتابته على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_38" style="">
<span class="pun">{#</span><span class="pln"> escape </span><span class="kwd">for</span><span class="pln"> </span><span class="typ">Html</span><span class="pln"> safty </span><span class="com">#}</span><span class="pln">
</span><span class="str">&lt;div&gt;</span><span class="pun">{{</span><span class="pln"> description</span><span class="pun">|</span><span class="pln">e </span><span class="pun">}}&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span></pre>

<p>
	كما يمكن كتابته على النحو التالي أيضًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_40" style="">
<span class="pun">{#</span><span class="pln"> escape </span><span class="kwd">for</span><span class="pln"> </span><span class="typ">Html</span><span class="pln"> safty </span><span class="com">#}</span><span class="pln">
</span><span class="str">&lt;div&gt;</span><span class="pun">{{</span><span class="pln"> description</span><span class="pun">|</span><span class="pln">escape </span><span class="pun">}}&lt;/</span><span class="pln">div</span><span class="pun">&gt;</span></pre>

<p>
	يمكن تمرير وسيط للمرشح السابق لتحديد نوع يناسب المكان الذي سوف يظهر به المتغير مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_42" style="">
<span class="pun">{#</span><span class="pln"> escape </span><span class="kwd">for</span><span class="pln"> js safety </span><span class="com">#}</span><span class="pln">
</span><span class="str">&lt;script&gt;</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> getDescription</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"> description</span><span class="pun">|</span><span class="pln">e</span><span class="pun">(</span><span class="str">'js'</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">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span><span class="pln">

</span><span class="pun">{#</span><span class="pln"> escape </span><span class="kwd">for</span><span class="pln"> css safety </span><span class="com">#}</span><span class="pln">
</span><span class="str">&lt;style&gt;</span><span class="pln">
    </span><span class="pun">{{</span><span class="pln"> mystyles</span><span class="pun">|</span><span class="pln">e</span><span class="pun">(</span><span class="str">'css'</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">style</span><span class="pun">&gt;</span></pre>

<p>
	لمزيد من المعلومات عن هذا المرشح وبقية المرشحات، يمكن زيارة توثيق <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/filters" rel="external">المرشحات</a> في موسوعة حسوب.
</p>

<h2>
	الدوال في تويغ
</h2>

<p>
	الدوال في تويغ هي مجموعة من التعليمات البرمجية التي تؤدي مهمة ما ينتج عنها قيمة. يمكن استدعاء الدالة وإعادة استخدامها عدة مرات.
</p>

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

<p>
	كمثال الدالة <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/range" rel="external"><code>range</code></a> تعيد مصفوفة تحتوي على أعداد صحيحة محصورة بين رقمين:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_45" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%}</span><span class="pln">
    </span><span class="pun">{{</span><span class="pln"> i </span><span class="pun">}},</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endfor </span><span class="pun">%}</span><span class="pln">
</span><span class="pun">{#</span><span class="pln"> outputs </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="com">#}</span></pre>

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

<h3>
	الوسم والدالة block
</h3>

<p>
	في تويغ يمكن أن يكون لدينا دالة لها ذات الاسم المستخدم للوسم، فالكلمة block في تويغ قد تشير إلى الوسم <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/block" rel="external"><code>block</code></a>، كما قد تشير إلى الدالة <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/block_function" rel="external"><code>block</code></a> ويمكن التمييز بين الحالتين بسهولة عبر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8195_47" 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">
{% block title %}
    Hello Twig
{% endblock %}
</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">{{ block('title') }}</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>
	نلاحظ أن الوسم يكون ضمن صيغة افعل شيئا ما <code>{% %}</code> ويستخدم لتعريف الكتلة وتحديد محتوياتها بينما الدالة تكون ضمن صيغة أظهر شيئا ما <code>{{ }}</code> يتم اتباعها بقوسين يوجد بينهما وسيط يمرر للدالة حيث تستخدم الدالة <code>block</code> لإظهار محتويات كتلة سبق أن تم تعريفها بالوسم <code>block</code>.
</p>

<h3>
	المرشح والدالة date
</h3>

<p>
	يقوم المرشح date بتغير تنسيق التاريخ عند إظهار قيمة متغير ما حسب الصيغة المعطاة له
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_49" style="">
<span class="pun">{{</span><span class="pln"> birth</span><span class="pun">|</span><span class="pln">date</span><span class="pun">(</span><span class="str">"m/d/Y"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	أما الدالة date فإنها تعيد التاريخ الحالي عند استدعائها بدون وسطاء:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_51" style="">
<span class="pun">{{</span><span class="pln"> date</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="com">#}</span></pre>

<p>
	يمكن أن تمرر وسيط للدالة date ويمكن لقيمة الوسيط أن تكون تعبير نصي عن التاريخ مثلا النص "2022/01/01" يحول إلى التاريخ المقابل له كما يمكن أن يكون فرق بالتاريخ عن التاريخ الحالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_53" style="">
<span class="pun">{{</span><span class="pln"> date</span><span class="pun">(</span><span class="str">'2022/01/01'</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="lit">2022</span><span class="pun">/</span><span class="lit">01</span><span class="pun">/</span><span class="lit">01</span><span class="pln"> </span><span class="com">#}</span><span class="pln">
</span><span class="pun">{{</span><span class="pln"> date</span><span class="pun">(</span><span class="str">'-2days'</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><span class="pln"> </span><span class="pun">منه</span><span class="pln"> </span><span class="pun">يومين</span><span class="pln"> </span><span class="com">#}</span></pre>

<p>
	يمكن أن نمرر لها وسيطين حيث يحوي الوسيط الثاني على المنطقة الزمنية التي سوف يكون التاريخ فيها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_55" style="">
<span class="pun">{{</span><span class="pln"> date</span><span class="pun">(</span><span class="str">'-2days'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Europe/Paris'</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_8195_57" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> post</span><span class="pun">.</span><span class="pln">date </span><span class="pun">&gt;</span><span class="pln"> date</span><span class="pun">(</span><span class="str">'-30days'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%}</span><span class="pln">
    </span><span class="typ">This</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> a </span><span class="kwd">new</span><span class="pln"> post
</span><span class="pun">{%</span><span class="pln"> endif </span><span class="pun">%}</span></pre>

<h2>
	الفرق بين المرشح والدالة
</h2>

<p>
	تتصف المرشحات في تويغ بالخصائص التالية:
</p>

<ul>
<li>
		المرشحات مخصصة لمعالجة البيانات
	</li>
	<li>
		المرشح يعيد قيمة دوما
	</li>
	<li>
		القيمة التي يعيدها المرشح تكون نص دومًا
	</li>
	<li>
		يأخذ المرشح وسيط واحد أو أكثر
	</li>
	<li>
		يكتب الوسيط الأول قبل المرشح ويوضع بينهما <code>|</code> مثال:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_60" style="">
<span class="pun">{{</span><span class="pln"> student</span><span class="pun">|</span><span class="pln">upper </span><span class="pun">}}</span></pre>

<ul>
<li>
		عندما يحتاج إلى وسيط واحد لا يتم إتباعها بأقواس
	</li>
	<li>
		عندما يحتاج أكثر من وسيط يتم اضافة قوسين بعد اسم المرشح مع وضع الوسيط بينهما
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_64" style="">
<span class="pun">{{</span><span class="pln"> description</span><span class="pun">|</span><span class="pln">escape</span><span class="pun">(</span><span class="str">'html'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">}}</span></pre>

<p>
	يرجى ملاحظة أن الوسيط الأول هو المتغير نفسه الذي يأتي قبل علامة <code>|</code> أما ما بين ' ' فهو الوسيط الثاني.
</p>

<p>
	أما الدوال، فتتصف بالخصائص التالية:
</p>

<ul>
<li>
		الدوال مخصصة لإعادة قيمة غير مرتبطة بالبيانات عادة
	</li>
	<li>
		يمكن أن تكون القيمة تعيدها الدالة نصا أو رقما أو تاريخا أو مصفوفة
	</li>
	<li>
		الدوال في تويغ تعيد قيمة دوما وهذا يختلف عن تعريف الدوال في لغات البرمجة
	</li>
	<li>
		يمكن للدوال أن لا تأخذ أي وسيط ويمكن أن تأخذ وسيط واحد أو أكثر
	</li>
	<li>
		حتى عندما لا تأخذ الدالة أي وسيط فإنها تتبع بأقواس
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_66" style="">
<span class="pun">{{</span><span class="pln"> date</span><span class="pun">()</span><span class="pln"> </span><span class="pun">}}</span></pre>

<ul>
<li>
		عندما تحتاج الدالة إلى وسيط واحد أكثر فإنها تمرر إليها بين الأقواس:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_68" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">set</span><span class="pln"> list </span><span class="pun">=</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%}</span></pre>

<h2>
	الاختبارات في تويغ
</h2>

<p>
	الاختبارات في تويغ هي عبارة عن عوامل تختبر قيمة متغير ما وتستخدم على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_70" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> line </span><span class="kwd">is</span><span class="pln"> odd </span><span class="pun">%}</span><span class="pln">
</span><span class="pun">.......</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endif </span><span class="pun">%}</span></pre>

<p>
	حيث تستخدم مع عبارة <code>is</code> و تتحق من كون المتغير يحقق شرط محدد والاختبارات المعرفة مسبقا في تويغ هي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8195_72" style="">
<span class="kwd">defined</span><span class="pun">,</span><span class="pln"> divisible </span><span class="kwd">by</span><span class="pun">,</span><span class="pln"> even</span><span class="pun">,</span><span class="pln"> iterable</span><span class="pun">,</span><span class="pln"> odd</span><span class="pun">,</span><span class="pln"> same </span><span class="kwd">as</span></pre>

<p>
	لمزيد من المعلومات عن الاختبارات يمكن الرجوع إلى <a data-ss1621948291="1" data-ss1625245236="1" href="https://wiki.hsoub.com/Twig/tests" rel="external">صفحة الاختبارات</a> في موسوعة حسوب.
</p>

<h2>
	ختامًا
</h2>

<p>
	لقد تحدثنا في هذا المقال عن مكونات تويغ من وسوم ومرشحات ودوال واختبارات وهي المكونات الأساسية التي يقوم عليها القالب، وفي <a data-ss1621948291="1" data-ss1625245236="1" href="https://academy.hsoub.com/programming/php/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%B9%D9%84%D9%89-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%AA%D9%88%D9%8A%D8%BA-r1230/" rel="">المقال القادم</a> سوف نقوم بالتطبيق العملي على ما تعلمناه حيث نتعلم إنشاء قالب فرعي لووردبرس باستخدام تويغ.
</p>
]]></description><guid isPermaLink="false">1229</guid><pubDate>Tue, 25 May 2021 15:00:00 +0000</pubDate></item><item><title>&#x627;&#x646;&#x637;&#x644;&#x627;&#x642;&#x629; &#x633;&#x631;&#x64A;&#x639;&#x629; &#x645;&#x639; &#x645;&#x62D;&#x631;&#x643; &#x627;&#x644;&#x642;&#x648;&#x627;&#x644;&#x628; &#x62A;&#x648;&#x64A;&#x63A;</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%86%D8%B7%D9%84%D8%A7%D9%82%D8%A9-%D8%B3%D8%B1%D9%8A%D8%B9%D8%A9-%D9%85%D8%B9-%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%AA%D9%88%D9%8A%D8%BA-r1228/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_05/60a650990700d_-----.png.75ab17a745d3687a94aca5e5530b04b4.png" /></p>

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

<h2>
	متطلبات تويغ للعمل
</h2>

<p>
	يمكن استعمال بيئة عمل سحابية على الويب أو بيئة عمل محلية على الحاسوب مباشرة:
</p>

<ul>
<li>
		<strong>على استضافة ويب</strong>: تحتاج إلى خطة استضافة تدعم تشغيل PHP وأن يكون الإصدار المركب فيها 7.3 أو إصدار أعلى تقريبا جميع الاستضافات تدعم ذلك بما في الاستضافات المجانية.
	</li>
	<li>
		<strong>على الحاسوب المحلي</strong>: إن كنت سوف تستخدم استضافة فلست بحاجة لتركيب أي شيء على حاسوب محلي لكن يمكن أن تجعل من كمبيوترك المحلي مخدم ويب وتركيب عليه تويغ وفي هذه الحالة تحتاج إلى خادم ويب يدعم PHP مثلًا XAMPP لمزيد من المعلومات يمكن الرجوع إلى المقال <a data-ss1621948127="1" data-ss1622300187="1" data-ss1625245233="1" 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>.
	</li>
</ul>
<h2>
	تثبيت تويغ
</h2>

<p>
	يتوفر خياران لتثبيت تويغ وهو إما التثبيت المباشر من خلال تنزيله وتركيبه يدويًا أو من خلال كومبوزر composer وسنشرح كلا الطريقتين تاليًا.
</p>

<h3>
	التثبيت المباشر
</h3>

<ol>
<li>
		تحميل الإصدار الأخير من تويغ وذلك من خلال الرابط <a data-ss1621948127="1" data-ss1622300187="1" data-ss1625245233="1" href="https://php-download.com/package/twig/twig" rel="external nofollow">التالي</a> أو من خلال <a data-ss1621948127="1" data-ss1622300187="1" data-ss1625245233="1" href="https://github.com/twigphp/Twig" rel="external nofollow">GitHub</a>
	</li>
	<li>
		فك المجلد المضغوط السابق على الحاسوب المحلي ثم افتح المجلد الناتج وهو Twig-3.x في حالتي الآن أثناء كتابة المقال
	</li>
	<li>
		في داخل المجلد السابق يوجد مجلد اسمه src أعد تسميته إلى Twig ثم قم برفعه إلى المجلد العام www أو public_html في الاستضافة الخاصة بك.
	</li>
	<li>
		في المجلد public_html لموقعك أنشئ ملفًا باسم index.php وأضف له النص التالي
	</li>
</ol>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_6" style="">
<span class="pln">ini_set</span><span class="pun">(</span><span class="str">'display_errors'</span><span class="pun">,</span><span class="lit">1</span><span class="pun">);</span><span class="pln"> </span><span class="com"># comment if you do not need debugging</span><span class="pln">
spl_autoload_register</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$classname</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $dir </span><span class="pun">=</span><span class="pln"> </span><span class="str">'.'</span><span class="pun">;</span><span class="pln">
    $filename </span><span class="pun">=</span><span class="pln"> $dir </span><span class="pun">.</span><span class="pln"> str_replace</span><span class="pun">(</span><span class="str">'\\'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'/'</span><span class="pun">,</span><span class="pln"> $classname</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="str">'.php'</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">file_exists</span><span class="pun">(</span><span class="pln">$filename</span><span class="pun">))</span><span class="pln"> require_once $filename</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span><span class="pln">
require_once </span><span class="str">'\Twig\Loader\FilesystemLoader.php'</span><span class="pun">;</span></pre>

<p>
	كل ما سبق من خطوات يمكن اختصارها في حال التركيب من خلال composer
</p>

<h3>
	التثبيت بواسطة composer
</h3>

<p>
	ثبت <a data-ss1621948127="1" data-ss1622300187="1" data-ss1625245233="1" href="https://getcomposer.org/download" rel="external nofollow">Composer</a> وشغل الأمر التالي في الطرفية من أجل الحصول على الإصدار الأخير:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_8" style="">
<span class="pln">composer </span><span class="kwd">require</span><span class="pln"> </span><span class="str">"twig/twig"</span></pre>

<h2>
	البدء باستخدام تويغ
</h2>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_10" style="">
<span class="pln">$loader </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Twig\Loader\FilesystemLoader</span><span class="pun">(</span><span class="str">'.'</span><span class="pun">);</span><span class="pln">
$twig </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Twig\Environment</span><span class="pun">(</span><span class="pln">$loader</span><span class="pun">);</span><span class="pln">
echo $twig</span><span class="pun">-&gt;</span><span class="pln">render</span><span class="pun">(</span><span class="str">'template1.twig'</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"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'سامر'</span><span class="pun">]);</span></pre>

<p>
	في ذات المجلد public_html أنشئ ملفًا آخر باسم template1.twig واكتب العبارة التالية فيه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_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"> </span><span class="pun">{{</span><span class="pln"> name </span><span class="pun">}}</span></pre>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_14" 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="pun">{{</span><span class="pln"> name </span><span class="pun">}}</span></pre>

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

<h2>
	بنية قالب تويغ وصيغ التعبيرات فيه
</h2>

<p>
	لفهم تويغ يتوجب علينا معرفة دلالة ثلاث صيغ فقط هي <code>{{ }}</code>، <code>{% %}</code>، <code>{# #}</code> سنشرحها بالترتيب:
</p>

<h3>
	1- صيغة إخراج المتغيرات وإظهار النتائج
</h3>

<p>
	الصيغة الأولى المهمة من صيغ Twig التي عليك تعلمها هي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_16" style="">
<span class="pun">{{</span><span class="pln"> </span><span class="pun">}}</span></pre>

<p>
	تستخدم هذه الصيغة لإظهار نتيجة ما للمستخدم مثلا قيمة متغير أو ناتج دالة ما.
</p>

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

<p>
	لإخراج أي متغير في القالب يكفي أن يتم وضع اسم المتغير بين قوسين مقوسين على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_18" style="">
<span class="pun">{{</span><span class="pln"> name </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{{</span><span class="pln"> foo</span><span class="pun">.</span><span class="pln">bar </span><span class="pun">}}</span></pre>

<p>
	انتبه من المثال أنه يمكن استخدام النقطة (.) للوصول إلى عناصر المصفوفة أو خصائص كائن ما.
</p>

<p>
	لمعرفة المزيد عن المتغيرات في تويغ يمكن زيارة قسم <a data-ss1621948127="1" data-ss1622300187="1" data-ss1625245233="1" href="https://wiki.hsoub.com/Twig/templates#.D8.A7.D9.84.D9.85.D8.AA.D8.BA.D9.8A.D8.B1.D8.A7.D8.AA" rel="external">المتغيرات</a> من صفحة محرك تويغ لمصممي القوالب في موسوعة حسوب.
</p>

<h3>
	2- صيغة التعليقات
</h3>

<p>
	من المهم في كثير من الأحيان أن نكتب ملاحظة لكننا لا نريدها أن تظهر في المستند المنسق ولتحقيق ذلك يكفي أن نكتب تلك الملاحظة أو التعليق بالصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_20" style="">
<span class="pun">{#</span><span class="pln"> </span><span class="pun">ملاحظة</span><span class="pln"> </span><span class="com">#}</span></pre>

<p>
	لمعرفة المزيد عن الملاحظات في تويغ يمكن زيارة قسم <a data-ss1621948127="1" data-ss1622300187="1" data-ss1625245233="1" href="https://wiki.hsoub.com/Twig/templates#.D8.A7.D9.84.D8.AA.D8.B9.D9.84.D9.8A.D9.82.D8.A7.D8.AA" rel="external">التعليقات</a> من صفحة محرك تويغ لمصممي القوالب في موسوعة حسوب.
</p>

<h3>
	3- صيغة افعل شيئا ما
</h3>

<p>
	يستخدم التركيب التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_22" style="">
<span class="str">`{% ...... %}</span></pre>

<p>
	للطلب من محرك القالب القيام بشيء محدد مثل التحقق من شرط ما أو تنفيذ تكرار ما. لا يظهر التركيب السابق نتائج للمستخدم لفم التركيب السابق بشكل جيد سوف نأخذ مثالين هما <code>if</code> و <code>for</code>.
</p>

<h4>
	الشروط والحالات الشرطية
</h4>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_25" 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="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="pun">{%</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> mark </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">90</span><span class="pln"> </span><span class="pun">%}</span><span class="pln">
     </span><span class="typ">Hello</span><span class="pln"> smart student </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><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="pun">{%</span><span class="pln"> endif </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><span class="pln"> </span><span class="pun">كلمة</span><span class="pln"> </span><span class="pun">واحدة</span><span class="pln"> </span><span class="com">#}</span></pre>

<p>
	في السطر الأول يتحقق تويغ من علامة الطالب التي يمثلها المتغير <code>mark</code> فإن كانت أكثر من 90 فإنه ينتقل للسطر التالي حيث يظهر رسالة الترحيب أما السطر الأخير <code>endif</code> فهو يغلق الشرط.
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_27" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> agent </span><span class="pun">%}</span><span class="pln">
    </span><span class="typ">We</span><span class="pln"> have an agent </span><span class="kwd">in</span><span class="pln"> your area
    </span><span class="typ">Our</span><span class="pln"> agent</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{{</span><span class="pln"> agent </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endif </span><span class="pun">%}</span></pre>

<p>
	مثال آخر؛ دعنا نقول أن لدينا متغير يسمى السعر. نريد عرض نص إذا كان السعر صفرًا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_29" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> price </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="typ">This</span><span class="pln"> product </span><span class="kwd">is</span><span class="pln"> free 
</span><span class="pun">{%</span><span class="pln"> elseif price </span><span class="pun">&gt;</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">This</span><span class="pln"> product </span><span class="kwd">is</span><span class="pln"> cheap  
</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">
   </span><span class="typ">You</span><span class="pln"> have to pay </span><span class="pun">{{</span><span class="pln"> price </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">{%</span><span class="pln"> endif </span><span class="pun">%}</span></pre>

<p>
	يرجى ملاحظة أننا نستخدم العامل التالي == للتحقق من المساواة وأننا يمكننا التحقق من أكثر من حالة للشرط باستعمال <code>elseif</code> ووضع حالة أخيرة للشرط إن لم تتحقق أي حالة من الحالات السابقة عبر <code>else</code>.
</p>

<p>
	استخدم دائمًا <code>{% endif %}</code> لإغلاق شرط <code>if</code> السابق، فكل عبارة <code>if</code> يجب أن تغلقها عبارة <code>endif</code>.
</p>

<p>
	للمزيد من المعلومات عن استخدام اطلع على صفحة <a data-ss1621948127="1" data-ss1622300187="1" data-ss1625245233="1" href="https://wiki.hsoub.com/Twig/if" rel="external">الوسم if</a> في توثيق تويغ العربي.
</p>

<h3>
	الحلقات التكرارية وتكرار أمر ما
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_4486_32" style="">
<span class="pun">{%</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> name </span><span class="kwd">in</span><span class="pln"> names_list </span><span class="pun">%}</span><span class="pln">
   </span><span class="typ">Hello</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">
</span><span class="pun">{%</span><span class="pln"> endfor </span><span class="pun">%}</span></pre>

<p>
	حيث <code>names_list</code> هو اسم المصفوفة أما <code>name</code> فهو اسم تم إطلاقه على كل عنصر من عناصر المصفوفة.
</p>

<p>
	في السطر التالي يتم تنفيذ الأوامر التي بين <code>for</code> وبين <code>edfor</code> على كل عناصر المصفوفة وبالتالي في مثالنا السابق تظهر عبارة ترحيب لكل اسم من الأسماء التي تحتويها المصفوفة، أما السطر الأخير فهو لإغلاق الحلقة وإعلام محرك القالب أن عليه المتابعة بشكل اعتيادي لباقي تعليمات القالب اي أن التعليمات التي تأتي بعد <code>{% endfor %}</code> لن تكون خاصة بالحلقة.
</p>

<p>
	كل عبارة <code>for</code> يجب حتما أن تنتهي بعبارة <code>{% endfor %}</code> ويرجى ملاحظة أن <code>endfor</code> هي كلمة واحدة وليس كلمتين.
</p>

<h3>
	ماذا بعد؟
</h3>

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

<p>
	نقدم لك فيما يلي نموذج لقالب تويغ لعرض قائمة منتجات مع سعرها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8401_15" 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;title&gt;</span><span class="pln">Products</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">Products</span><span class="tag">&lt;/h1&gt;</span><span class="pln">
{# This is a comment and will not render #}
{% for product in products %}
        Product name: {{ product.name }}</span><span class="tag">&lt;br&gt;</span><span class="pln">
        {% if product.price == 0 %}
              Free 
       {% else %}
             Procust price {{ product.price }}
      {% endif %}
{% endfor %}
</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<h2>
	الخلاصة
</h2>

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

<p>
	في <a data-ss1621948127="1" data-ss1622300187="1" data-ss1625245233="1" href="https://academy.hsoub.com/programming/php/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A8%D9%86%D8%A7%D8%A1-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%B9%D8%A8%D8%B1-%D8%AA%D9%88%D9%8A%D8%BA-twig-r1229" rel="">المقال التالي</a> سوف نتعمق أكثر ونتحدث عن الوسوم، المرشحات، والاختبارات.
</p>
]]></description><guid isPermaLink="false">1228</guid><pubDate>Sat, 22 May 2021 15:06:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x645;&#x62D;&#x631;&#x643; &#x627;&#x644;&#x642;&#x648;&#x627;&#x644;&#x628; &#x62A;&#x648;&#x64A;&#x63A; Twig</title><link>https://academy.hsoub.com/programming/php/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%AA%D9%88%D9%8A%D8%BA-twig-r1227/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_05/60a64b5fb0c7e_-----Twig.png.7eda5250c50bc4fa0ec3cce4f3fc027c.png" /></p>

<p>
	لا نهدف في هذه المقالات إلى ترجمة الموقع الرسمي لمحرك قوالب Twig والتي تجدها في موسوعة حسوب، <a data-ss1621948120="1" data-ss1625245108="1" href="https://wiki.hsoub.com/Twig" rel="external">توثيق Twig</a>، لكننا نهدف إلى توليد فهم عميق وبسيط لهذه التقنية يمكنك من الاستفادة القصوى منها، بحيث يكون مفيدًا للمبتدئين وممتعًا للمتقدمين.
</p>

<h2>
	مفهوم محرك القالب وعمله
</h2>

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

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

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

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

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		مرحبا بالطالب المجد {{ name }}
	</p>
</blockquote>

<ol>
<li>
		نسمي العبارة السابقة بالقالب
	</li>
	<li>
		نسمي أسماء الطلاب المتمثلة بالحقل <code>name</code> بالبيانات
	</li>
	<li>
		أما عبارات الترحيب الناتجة فهي المستند المنسق وأخيرًا فإن محرك القالب هو البرنامج الحاسوبي الذي قام بدمج القالب السابق مع البيانات والتي هي أسماء الطلاب في مثالنا حيث يتم استبدال اسم الطالب في موضعه حسب الحاجة.
	</li>
</ol>
<p>
	ناتج القالب السابق إن كان لدينا قائمة باسمي طالبين ما يلي:
</p>

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

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>عمل محرك القالب:</strong> بيانات + قالب ⇐ مستندات منسقة
	</p>
</blockquote>

<h2>
	أشهر محركات القوالب المستخدمة في برمجة صفحات الويب
</h2>

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

<p>
	تؤمن لغة البرمجة بي إتش بي PHP آليات سهلة لمعالجة القوالب حيث يمكن كتابة القالب بلغة PHP على النحو التالي مثلًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_83_16" style="">
<span class="typ">Hello</span><span class="pln"> student </span><span class="pun">&lt;?</span><span class="pln">php echo  $student</span><span class="pun">;</span><span class="pln"> </span><span class="pun">?&gt;</span></pre>

<p>
	بالرغم من كون PHP تؤمن خصائص محرك القالب إلا أنها من النادر أن تستخدم لهذا الغرض من قبل المبتدئين وينحصر استخدامها من قبل من يتقن تلك اللغة.
</p>

<p>
	لقد تنوعت التقنيات وتقدمت كثيرا ويوجد الكثير من محركات القوالب سوف نذكر أشهر محركات القوالب:
</p>

<ul>
<li>
		سمارتي <a data-ss1621948120="1" data-ss1625245108="1" href="https://www.smarty.net/" rel="external nofollow">Smarty</a>: محرك قالب شهير سهل التركيب مكتوب بلغة PHP وهو يأتي في المرتبة الثانية بعد تويغ من حيث شيوع الاستخدام
	</li>
	<li>
		بليت <a data-ss1621948120="1" data-ss1625245108="1" href="https://platesphp.com/" rel="external nofollow">Plates</a>: محرك قالب له طريقة كتابة معقدة بعض الشيء وهو أقل قابلية للقراءة من قبل المبتدئين
	</li>
	<li>
		فولت <a data-ss1621948120="1" data-ss1625245108="1" href="https://docs.phalcon.io/4.0/en/volt" rel="external nofollow">Volt</a>: محرك قالب مكتوب بلغة سي وطريقة كتابة القالب به تشبه تويغ
	</li>
	<li>
		تويغ <a data-ss1621948120="1" data-ss1625245108="1" href="https://twig.symfony.com/" rel="external nofollow">Twig</a> محرك قالب سريع ومرن وشائع جدا مكتوب بلغة بي اتش بي
	</li>
</ul>
<h2>
	الفرق بين محرك القالب والقالب ولغة القالب
</h2>

<p>
	نود أن نوضح شيئا مهما يوضح الفرق بين المفاهيم المتداخلة، محرك القالب والقالب ولغة القالب:
</p>

<ul>
<li>
		محرك القالب templating engine هو برنامج كتبته الشركة التي صممت محرك القالب ويمكن تحميله من الموقع الرسمي للشركة.
	</li>
	<li>
		القالب template هو أوامر التنسيق أو الإخراج التي التي نكتبها نحن ونقدمها إلى محرك القالب مثلا الملف single.twig يدعى قالب.
	</li>
	<li>
		لغة القالب template syntax فهي طريقة الكتابة التي يطلب منا محرك القالب الالتزام بها ليفهم ما نكتبه. أي القواعد التي علينا مراعاتها عند كتابة القالب مثلا طريقة اخراج المتغيرات وطريقة استدعاء الدوال والمرشحات وغيرها من التقنيات التي يوفرها القالب مثلا يمكن القول بأن لغة القالب فولت تشابه كثيرا لغة القالب تويغ.
	</li>
</ul>
<p>
	لكل محرك قالب طريقة خاصة به لكتابة القوالب عادة تسمى باسم محرك القالب نفسه ونحن هنا لا نقصد لاحقة الملف بل نقصد طريقة الكتابة ضمن الملف نفسه أي template syntax.
</p>

<h2>
	تعريف تويغ Twig ومزاياه
</h2>

<p>
	يُعَدّ تويغ Twig محرك قالب مجاني، مفتوح المصدر، سريع، آمن، مرن وسهل التعلم وهو مبني على لغة PHP ويتم استخدامه بشكل أساسي لإخراج صفحات HTML، ولكن يمكن استخدامه أيضًا لإخراج أي تنسيق نصي آخر. ويعتبر تويغ Twig مكون مستقل يمكن دمجه بسهولة في أي مشروع PHP، ويتمتع تويغ Twig بالمزايا التالية:
</p>

<h3>
	السرعة
</h3>

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

<h3>
	الحفاظ على البيانات
</h3>

<p>
	عندما يستخدم مصمم السمة أو pack end تويغ فإنه يمكن من المسؤول عن شكل الموقع أو front end أن يقوم هو بتعديل القوالب حسب ما يراه مناسبا دون المخاطرة بالبيانات حيث أن التعليمات المكتوبة في قوالب تويغ تكون آمنة وهي تستخدم لقراءة البيانات وإظهارها وليس لتعديلها
</p>

<h3>
	لا للتعليمات الخطرة والأخطاء الحرجة
</h3>

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

<p>
	هل توقف موقعك عن العمل نتيجة كود بي اتش بي خاطئ؟ يحتوي Twig على وضع صندوق الاختبار (Sandbox) من أجل تقييم شيفرات القوالب غير الموثوق بها قبل تنفيذها.
</p>

<h3>
	شيوع الاستخدام
</h3>

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

<h3>
	المرونة ودعم الوراثة
</h3>

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

<h2>
	مقارنة بين تويغ ومحركات القوالب الأخرى
</h2>

<p>
	سوف نقوم بمقارنة محركات القالب من حيث سهولة الاستخدام وشيوع محرك القالب وسرعة التنفيذ
</p>

<h3>
	سهولة القراءة والتعلم
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_83_19" style="">
<span class="pun">{#</span><span class="pln"> </span><span class="typ">Twig</span><span class="pln"> </span><span class="com">#}</span><span class="pln">
</span><span class="pun">{{</span><span class="pln"> name </span><span class="pun">}}</span><span class="pln"> </span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_83_21" style="">
<span class="pln">volt
</span><span class="pun">{#</span><span class="pln"> volt </span><span class="com">#}</span><span class="pln">
</span><span class="pun">{{</span><span class="pln"> name </span><span class="pun">}}</span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_83_23" style="">
<span class="pln">smarty
</span><span class="pun">{*</span><span class="pln"> smarty </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"> </span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_83_25" style="">
<span class="pun">&lt;?</span><span class="pln">php echo $name</span><span class="pun">;</span><span class="pln"> </span><span class="pun">?&gt;</span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_83_27" style="">
<span class="com">&lt;!-- plate --&gt;</span><span class="pln">
Hello </span><span class="pun">&lt;?=</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">e</span><span class="pun">(</span><span class="pln">$name</span><span class="pun">)?&gt;</span></pre>

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

<h3>
	الاستخدام الشائع بين المطورين
</h3>

<p>
	بهدف اختبار شيوع استخدام كل من محركات القالب الثلاث، فقد تمت موازنة ترتيب أليكسا للموقع الرسمي لكل من محركات القالب باستثناء PHP؛ أما بالنسبة إلى PHP، فإن شهرتها باعتبارها لغة برمجة تجعل ترتيب موقعها في أليكسا لا يعطي انطباعًا صحيحًا عن مدى شهرتها كمحرك قالب يقيم إليكسا المواقع بالاعتماد على مدى شيوعها وعدد الزوار شهريا للموقع فمثلا يحتل غوغل الرقم 1، وكلما كان عدد زوار الموقع أكبر كان ترتيب الموقع أقل وبمعنى آخر هناك 56000 ألف موقع تتفوق على سمارتي من حيث عدد الزوار أما بالنسبة لموقع تويغ الرسمي فهناك 13000 موقع فقط تتفوق عليه من حيث عدد الزوار أما تقيم alexa فأن الموقع الرسمي لـ تويغ يحتل فهر يسبق جميع محركات القالب المذكورة حيث كان <a data-ss1621948120="1" data-ss1625245108="1" href="https://www.alexa.com/siteinfo/symfony.com" rel="external nofollow">13000</a> بينما يحتل سمارتي المركز الثاني <a data-ss1621948120="1" data-ss1625245108="1" href="https://www.alexa.com/siteinfo/smarty.net" rel="external nofollow">56000</a>. في المنزلة قبل الأخيرة تأتي فولت بتقييم <a data-ss1621948120="1" data-ss1625245108="1" href="https://www.alexa.com/siteinfo/phalcon.io" rel="external nofollow">127000</a> أما محرك القالب بلوت فكان له التريب التالي في إليكسا وهو أقل محركات القوالب السابقة شيوعا بتقييم <a data-ss1621948120="1" data-ss1625245108="1" href="https://www.alexa.com/siteinfo/platesphp.com" rel="external nofollow">1,600,000</a>.
</p>

<h3>
	السرعة عند الاستخدام
</h3>

<p>
	تقوم محركات القالب بتوليد شيفرة PHP مقابل للقالب ثم تقوم تنفيذ الشفرة الناتجة مما يجعل سرعة الأداء متقاربة.
</p>

<p>
	لقد تم الرجوع إلى الموقع المختص بمقارنة الأداء phpbenchmarks.com فكانت سرعة الإصدار الأخير من محركات القالب الشهيرة متقاربة جدا عند عند استخدامها مع الإصدار 7.3 من PHP.
</p>

<h3>
	سهولة التركيب
</h3>

<p>
	في هذه النقطة تتفوق سمارتي Smarty على Twig حيث يتم تركيب سمارتي بصفته مكون مستقل أما تويغ طريقة تنصيبه الرسمية تتضمن استعمال composer وعادة ما يكون جزءًا من مشروع آخر . لكن في <a data-ss1621948120="1" data-ss1625245108="1" href="https://academy.hsoub.com/programming/php/%D8%A7%D9%86%D8%B7%D9%84%D8%A7%D9%82%D8%A9-%D8%B3%D8%B1%D9%8A%D8%B9%D8%A9-%D9%85%D8%B9-%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%AA%D9%88%D9%8A%D8%BA-r1228" rel="">المقال التالي</a> سوف نقوم بتقديم طريقة سهلة لتركيب تويغ بشكل مستقل وبدون استخدام composer بحيث يصبح الفرق أقل أهمية. أما PHP فهي لا تحتاج إلى أي تركيب حيث تكون ممكنة مسبقًا على مختلف مواقع الويب المبنية فيها.
</p>

<h2>
	كلمة أخيرة
</h2>

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

<p>
	لقد تطرقنا في هذا المقال إلى مدخل سريع عن تويغ وتم بيان عدد من مزاياه مثل السرعة والحفاظ على البيانات وغيرها كما أجرينا مقارنة بين عدد من محركات البحث وفي النهاية قمنا بشرح الفرق بين محرك القالب والقالب ولغة القالب وفي <a data-ss1621948120="1" data-ss1625245108="1" href="https://academy.hsoub.com/programming/php/%D8%A7%D9%86%D8%B7%D9%84%D8%A7%D9%82%D8%A9-%D8%B3%D8%B1%D9%8A%D8%B9%D8%A9-%D9%85%D8%B9-%D9%85%D8%AD%D8%B1%D9%83-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%84%D8%A8-%D8%AA%D9%88%D9%8A%D8%BA-r1228" rel="">المقال الثاني</a> سوف نقوم بانطلاقة سريعة مع تويغ تهدف إلى تعريفنا بمتطلبات العمل وبطريقة تثبيت تويغ مع لمحة سريعة عن طريقة استخدامه.
</p>
]]></description><guid isPermaLink="false">1227</guid><pubDate>Thu, 20 May 2021 15:08:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x634;&#x641;&#x64A;&#x631; &#x648;&#x627;&#x644;&#x62A;&#x642;&#x637;&#x64A;&#x639; hashing &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-%D9%88%D8%A7%D9%84%D8%AA%D9%82%D8%B7%D9%8A%D8%B9-hashing-%D9%81%D9%8A-php-r1206/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_04/607e7ea946e44_passwordN.png.5519ec2753fa5f52417cd7232117644e.png" /></p>

<h2 id="-openssl">
	التشفير وفك التشفير المتناظر لملفات كبيرة باستخدام OpenSSL
</h2>

<p>
	لا توفر PHP دالة مضمنة لتشفير وفك تشفير الملفات الكبيرة، يمكن استخدام الدالة <code>openssl_encrypt</code> لتشفير السلاسل النصية لكن يعد تحميل ملف كبير جدًا في الذاكرة فكرةً سيئةً، لذا يجب كتابة دالة تقوم بهذا العمل، يستخدم هذا المثال خوارزمية <a href="https://stackoverflow.com/questions/33121619/is-there-any-difference-between-aes-128-cbc-and-aes-128-encryption" rel="external nofollow">AES-128-CBC</a> المتناظرة لتشفير أجزاء صغيرة من ملف كبير وكتابتها في ملف آخر.
</p>

<h3>
	تشفير الملفات
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1796_7" style="">
<span class="com">// (1)</span><span class="pln">
define</span><span class="pun">(</span><span class="str">'FILE_ENCRYPTION_BLOCKS'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10000</span><span class="pun">);</span><span class="pln">

</span><span class="com">/**
* ‫تشفير الملف الممرر وحفظ النتيجة في ملف جديد باللاحقة "‎.enc"
*
* @param string $source مسار الملف الذي نريد تشفيره
* @param string $key المفتاح المستخدم للتشفير
* @param string $dest اسم الملف الذي نريد أن نكتب فيه الملف المشفَّر
* @return string|false 
* ‫تعيد هذه الدالة اسم الملف المنشأ أو FALSE إذا حدث خطأ
*/</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> encryptFile</span><span class="pun">(</span><span class="pln">$source</span><span class="pun">,</span><span class="pln"> $key</span><span class="pun">,</span><span class="pln"> $dest</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $key </span><span class="pun">=</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">sha1</span><span class="pun">(</span><span class="pln">$key</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">);</span><span class="pln">
    $iv </span><span class="pun">=</span><span class="pln"> openssl_random_pseudo_bytes</span><span class="pun">(</span><span class="lit">16</span><span class="pun">);</span><span class="pln">
    $error </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</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">$fpOut </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="pln">$dest</span><span class="pun">,</span><span class="pln"> </span><span class="str">'w'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ضع شعاع التهيئة في بداية الملف‬</span><span class="pln">
        fwrite</span><span class="pun">(</span><span class="pln">$fpOut</span><span class="pun">,</span><span class="pln"> $iv</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">$fpIn </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="pln">$source</span><span class="pun">,</span><span class="pln"> </span><span class="str">'rb'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">feof</span><span class="pun">(</span><span class="pln">$fpIn</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                $plaintext </span><span class="pun">=</span><span class="pln"> fread</span><span class="pun">(</span><span class="pln">$fpIn</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> FILE_ENCRYPTION_BLOCKS</span><span class="pun">);</span><span class="pln">
                $ciphertext </span><span class="pun">=</span><span class="pln"> openssl_encrypt</span><span class="pun">(</span><span class="pln">$plaintext</span><span class="pun">,</span><span class="pln"> </span><span class="str">'AES-128-CBC'</span><span class="pun">,</span><span class="pln"> $key</span><span class="pun">,</span><span class="pln"> OPENSSL_RAW_DATA</span><span class="pun">,</span><span class="pln">$iv</span><span class="pun">);</span><span class="pln">
                </span><span class="com">// ‫استخدم أول 16 بايت من النص المشفر كشعاع التهيئة التالي</span><span class="pln">
                $iv </span><span class="pun">=</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">$ciphertext</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">);</span><span class="pln">
                fwrite</span><span class="pun">(</span><span class="pln">$fpOut</span><span class="pun">,</span><span class="pln"> $ciphertext</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            fclose</span><span class="pun">(</span><span class="pln">$fpIn</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">
            $error </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">
        fclose</span><span class="pun">(</span><span class="pln">$fpOut</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">
        $error </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">return</span><span class="pln"> $error </span><span class="pun">?</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> $dest</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نحدد في الموضع (1) عدد الكتل التي يجب قراءتها من الملف المصدري من أجل كل جزء، بحيث تتألف كل كتلة من 16 بايت من أجل الخوارزمية الآتية:
</p>

<pre class="ipsCode" id="ips_uid_9064_7">
 'AES-128-CBC'
</pre>

<p>
	لهذا، فإذا قرأنا 10000 كتلة نحمّل 160 كيلوبايت في الذاكرة، يمكنك تعديل هذه القيمة لقراءة/كتابة أجزاء أصغر/أكبر.
</p>

<h3>
	فك تشفير الملفات
</h3>

<p>
	يمكنك استخدام هذه الدالة لفك تشفير الملفات المشفرة بالدالة السابقة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1796_21" style="">
<span class="com">/**
* ‫فك تشفير الملف الممرر وحفظ النتيجة في ملف جديد مع حذف آخر 4 محارف من اسم الملف
* @param string $source مسار الملف الذي نريد فك تشفيره
* @param string $key ‫المفتاح المستخدم لفك التشفير (ويجب أن يكون نفس المفتاح المستخدم للتشفير)
* @param string $dest اسم الملف حيث يجب أن نكتب الملف الجديد بعد فك التشفير
* @return string|false
* ‫تعيد هذه الدالة اسم الملف المنشأ أو FALSE إذا حدث خطأ
*/</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> decryptFile</span><span class="pun">(</span><span class="pln">$source</span><span class="pun">,</span><span class="pln"> $key</span><span class="pun">,</span><span class="pln"> $dest</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $key </span><span class="pun">=</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">sha1</span><span class="pun">(</span><span class="pln">$key</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">),</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">);</span><span class="pln">
    $error </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</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">$fpOut </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="pln">$dest</span><span class="pun">,</span><span class="pln"> </span><span class="str">'w'</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">$fpIn </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="pln">$source</span><span class="pun">,</span><span class="pln"> </span><span class="str">'rb'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// الحصول على شعاع التهيئة من بداية الملف</span><span class="pln">
            $iv </span><span class="pun">=</span><span class="pln"> fread</span><span class="pun">(</span><span class="pln">$fpIn</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">feof</span><span class="pun">(</span><span class="pln">$fpIn</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
                $ciphertext </span><span class="pun">=</span><span class="pln"> fread</span><span class="pun">(</span><span class="pln">$fpIn</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">FILE_ENCRYPTION_BLOCKS </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">));</span><span class="pln">
                </span><span class="com">// يجب أن نقرأ كتلة واحدة زيادة عن التشفير لفك التشفير</span><span class="pln">
                $plaintext </span><span class="pun">=</span><span class="pln"> openssl_decrypt</span><span class="pun">(</span><span class="pln">$ciphertext</span><span class="pun">,</span><span class="pln"> </span><span class="str">'AES-128-CBC'</span><span class="pun">,</span><span class="pln"> $key</span><span class="pun">,</span><span class="pln"> OPENSSL_RAW_DATA</span><span class="pun">,</span><span class="pln">$iv</span><span class="pun">);</span><span class="pln">
                </span><span class="com">// ‫استخدم أول 16 بايت من النص المشفر كشعاع التهيئة التالي</span><span class="pln">
                $iv </span><span class="pun">=</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">$ciphertext</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">);</span><span class="pln">
                fwrite</span><span class="pun">(</span><span class="pln">$fpOut</span><span class="pun">,</span><span class="pln"> $plaintext</span><span class="pun">);</span><span class="pln">
            </span><span class="pun">}</span><span class="pln">
            fclose</span><span class="pun">(</span><span class="pln">$fpIn</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">
            $error </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">
        fclose</span><span class="pun">(</span><span class="pln">$fpOut</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">
        $error </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">return</span><span class="pln"> $error </span><span class="pun">?</span><span class="pln"> </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> $dest</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	طريقة الاستخدام
</h3>

<p>
	إليك الشيفرة التالية لتعرف كيفية استخدام الدوال السابقة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1796_19" style="">
<span class="pln">$fileName </span><span class="pun">=</span><span class="pln"> __DIR__</span><span class="pun">.</span><span class="str">'/testfile.txt'</span><span class="pun">;</span><span class="pln">
$key </span><span class="pun">=</span><span class="pln"> </span><span class="str">'my secret key'</span><span class="pun">;</span><span class="pln">
file_put_contents</span><span class="pun">(</span><span class="pln">$fileName</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Hello World, here I am.'</span><span class="pun">);</span><span class="pln">
encryptFile</span><span class="pun">(</span><span class="pln">$fileName</span><span class="pun">,</span><span class="pln"> $key</span><span class="pun">,</span><span class="pln"> $fileName </span><span class="pun">.</span><span class="pln"> </span><span class="str">'.enc'</span><span class="pun">);</span><span class="pln">
decryptFile</span><span class="pun">(</span><span class="pln">$fileName </span><span class="pun">.</span><span class="pln"> </span><span class="str">'.enc'</span><span class="pun">,</span><span class="pln"> $key</span><span class="pun">,</span><span class="pln"> $fileName </span><span class="pun">.</span><span class="pln"> </span><span class="str">'.dec'</span><span class="pun">);</span></pre>

<p>
	ستنشئ هذه الشيفرة ثلاثة ملفات:
</p>

<ul>
<li>
		<div>
			<code>testfile.txt </code>وفيه النص الأصلي.
		</div>
	</li>
	<li>
		<code>testfile.txt.enc</code> فيه الملف المشفر.
	</li>
	<li>
		<code>testfile.txt.dec</code> فيه الملف بعد فك تشفيره ويجب أن يكون نفس محتويات الملف <code>testfile.txt</code>.
	</li>
</ul>
<h2 id="-">
	التشفير المتناظر
</h2>

<p>
	يوضح هذا المثال التشفير المتناظر باستخدام خوارزمية AES 256 بالنمط CBC وهو اختصار لـ Cipher Block Chaining، نحتاج شعاع تهيئة لذا نولّد واحدًا باستخدام دالة openssl، ويستخدم المتغير <code>‎$strong</code> لتحديد فيما إذا كان شعاع التهيئة المولَّد قويًا من ناحية التشفير.
</p>

<h3>
	التشفير
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1796_17" style="">
<span class="com">// طريقة التشفير</span><span class="pln">
$method </span><span class="pun">=</span><span class="pln"> </span><span class="str">"aes-256-cbc"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// الحصول على طول شعاع التهيئة المطلوب</span><span class="pln">
$iv_length </span><span class="pun">=</span><span class="pln"> openssl_cipher_iv_length</span><span class="pun">(</span><span class="pln">$method</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫ضبط للقيمة false من أجل السطر التالي</span><span class="pln">
$strong </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">

</span><span class="com">// توليد شعاع التهيئة</span><span class="pln">
$iv </span><span class="pun">=</span><span class="pln"> openssl_random_pseudo_bytes</span><span class="pun">(</span><span class="pln">$iv_length</span><span class="pun">,</span><span class="pln"> $strong</span><span class="pun">);</span><span class="pln">

</span><span class="com">/*
‫يحتاج شعاع التهيئة للاسترجاع لاحقًا لذا خزنه في قاعدة البيانات لكن لا تعيد استخدام نفس شعاع التهيئة لتشفير بيانات مرةً أخرى
*/</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(!</span><span class="pln">$strong</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">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">"IV not cryptographically strong!"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// الرسالة السرية</span><span class="pln">
$data </span><span class="pun">=</span><span class="pln"> </span><span class="str">"This is a message to be secured."</span><span class="pun">;</span><span class="pln">
</span><span class="com">// كلمة المرور</span><span class="pln">
$pass </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Stack0verfl0w"</span><span class="pun">;</span><span class="pln">

</span><span class="com">/* ‫يجب أن تُرسل كلمة المرور بالطريقة POST عبر جلسة HTTPS، قمنا بتخزينها في متغير هنا لأغراض توضيحية *
*/</span><span class="pln">
</span><span class="com">// التشفير</span><span class="pln">
$enc_data </span><span class="pun">=</span><span class="pln"> openssl_encrypt</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">,</span><span class="pln"> $method</span><span class="pun">,</span><span class="pln"> $password</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> $iv</span><span class="pun">);</span></pre>

<h3>
	فك التشفير
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1796_15" style="">
<span class="com">// ‫استعادة شعاع التهيئة من قاعدة البيانات وكلمة المرور من الطلب POST</span><span class="pln">
</span><span class="com">// فك التشفير</span><span class="pln">
$dec_data </span><span class="pun">=</span><span class="pln"> openssl_decrypt</span><span class="pun">(</span><span class="pln">$enc_data</span><span class="pun">,</span><span class="pln"> $method</span><span class="pun">,</span><span class="pln"> $pass</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> $iv</span><span class="pun">);</span></pre>

<h3>
	التشفير وفك التشفير بالأساس 64
</h3>

<p>
	إذا كانت البيانات المشفرة تحتاج للإرسال أو التخزين في نص قابل للطباعة عندها يمكن استخدام الدالتين <code>()base64_encode</code>، و <code>()base64_decode</code> على الترتيب.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1796_13" style="">
<span class="com">// تشفير الترميز بالأساس 64</span><span class="pln">
$enc_data </span><span class="pun">=</span><span class="pln"> base64_encode</span><span class="pun">(</span><span class="pln">openssl_encrypt</span><span class="pun">(</span><span class="pln">$data</span><span class="pun">,</span><span class="pln"> $method</span><span class="pun">,</span><span class="pln"> $password</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> $iv</span><span class="pun">));</span><span class="pln">

</span><span class="com">// فك الترميز وفك التشفير</span><span class="pln">
$dec_data </span><span class="pun">=</span><span class="pln"> openssl_decrypt</span><span class="pun">(</span><span class="pln">base64_decode</span><span class="pun">(</span><span class="pln">$enc_data</span><span class="pun">),</span><span class="pln"> $method</span><span class="pun">,</span><span class="pln"> $password</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">,</span><span class="pln"> $iv</span><span class="pun">);</span></pre>

<h2 id="-">
	دوال تعمية كلمة المرور
</h2>

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

<h3 id="-">
	إنشاء كلمة مرور معماة
</h3>

<p>
	ننشئ نسخة معماة لكلمة المرور باستخدام الدالة <a href="https://www.php.net/manual/en/function.password-hash.php" rel="external nofollow">password_hash()‎</a> لاستخدام تعمية معيارية بأفضل ممارسة للصناعة الحالية أو لاشتقاق المفتاح، في وقت كتابة هذا النص المعيار هو <a href="https://en.wikipedia.org/wiki/Bcrypt" rel="external nofollow">bcrypt</a> مما يعني أنّ <code>PASSWORD_DEFAULT</code> له نفس قيمة <code>PASSWORD_BCRYPT</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1796_11" style="">
<span class="pln">$options </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'cost'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">12</span><span class="pun">,</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

$hashedPassword </span><span class="pun">=</span><span class="pln"> password_hash</span><span class="pun">(</span><span class="pln">$plaintextPassword</span><span class="pun">,</span><span class="pln"> PASSWORD_DEFAULT</span><span class="pun">,</span><span class="pln"> $options</span><span class="pun">);</span></pre>

<p>
	المعامل الثالث ليس إجباريًا.
</p>

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

<p>
	<strong>في</strong> الإصدارات السابقة للإصدار 5.5، الدوال <code>password_*‎</code> غير متوفرة، يجب أن تستخدم <a data-ss1619530882="1" data-ss1619530992="1" data-ss1619608774="1" data-ss1619609077="1" href="https://github.com/ircmaxell/password_compat" rel="external nofollow">حزمة التوافق</a> للحصول على بديل لهذه الدوال، لاحظ أنّ حزمة التوافق تتطلب الإصدار PHP 5.3.7 أو أعلى أو إصدار يحتوي على التصحيح <code>‎$2y</code> (مثل ريدهات).
</p>

<p>
	إذا لم تكن قادرًا على استخدامها فيمكنك تنفيذ عملية تعمية على كلمة المرور باستخدام الدالة <a href="https://wiki.hsoub.com/PHP/crypt" rel="external">crypt()‎</a>، وبما أنّ <code>password_hash()‎</code> تُنفَّذ كغلاف حول الدالة <code>crypt()‎</code> فلن تحتاج لفقدان أي وظيفة.
</p>

<p>
	المثال التالي هو تنفيذ بسيط للتعمية بالمعيار <code>bcrypt</code> والتوافق مع <code>password_hash()‎</code> ومن غير المضمون أن يحافظ على نفس قوة تشفير التنفيذ الكامل للدالة <code>password_hash()‎</code>.<code> </code>
</p>

<h3>
	إضافة غُفْل في عملية تعمية كلمة المرور
</h3>

<p>
	على الرغم من موثوقية خوارزمية التشفير إلا أنّه ما يزال يوجد ثغرة تستهدف <a data-ss1619530882="1" data-ss1619530992="1" data-ss1619608774="1" data-ss1619609077="1" href="https://en.wikipedia.org/wiki/Rainbow_table" rel="external nofollow">جداول قوس قزح</a> ولذا ينصح باستخدام غُفْل salt، والغفل بالعربية هو شيء ما يُضاف لكلمة المرور قبل تعميتها لجعل السلسلة النصية المصدر فريدة (انظر كتاب «علم التعمية واستخراج المعمى عند العرب»)، بالنظر إلى كلمتي مرور متطابقتين فإنّ نتيجة التعمية لهما ستكون فريدة أيضًا لأن الأغْفَال المضافة إليها فريدة.
</p>

<p>
	يعد إضافة الأغفال العشوائية أحد أهم أجزاء أمان كلمة المرور الخاصة بك، وهذا يعني أنّه حتى مع جدول البحث lookup table لكلمات المرورة المعماة المعروفة فإنّ المهاجم لن يتمكن من مطابقة كلمة المرور المعماة الخاصة بالمستخدم مع كلمة المرور المعماة في قاعدة البيانات بسبب استخدام أغفال مختلفة، يجب أن تستخدم دائمًا أغفال عشوائية وقوية من ناحية التشفير <a data-ss1619530882="1" data-ss1619530992="1" data-ss1619608774="1" data-ss1619609077="1" href="https://www.springer.com/us/book/9781484221198" rel="external nofollow">اقرأ المزيد</a>.
</p>

<p>
	باستخدام خوارزمية bcrypt ودالة password_hash()‎ تُخزَّن أغفال النص الأصلي وأغفال النص المعمى الناتج مما يعني أنّه يمكن نقل النص المعمى عبر أنظمة ومنصات مختلفة وستبقى متطابقة مع كلمة المرور الأصلية.
</p>

<p>
	في الإصدارات السابقة للإصدار 7.0 يمكنك استخدام الخيار <code>salt</code> لتعريف الأغفال العشوائية الخاصة بك على الرغم من عدم التشجيع على هذا الإجراء.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_471_7" style="">
<span class="pln">$options </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'salt'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> $salt</span><span class="pun">,</span><span class="pln">
</span><span class="pun">];</span></pre>

<p>
	<strong>ملاحظة</strong>: إذا أهملت هذا الخيار ستولّد الدالة password_hash()‎ غُفْلًا عشوائيًا لكل كلمة مرور مقطعة.
</p>

<p>
	بدءًا من الإصدار PHP 7.0.0 <a data-ss1619530882="1" data-ss1619530992="1" data-ss1619608774="1" data-ss1619609077="1" href="http://php.net/manual/ru/function.password-hash.php" rel="external nofollow">أُهمل</a> خيار إضافة الغُفْل ومن المفضل الآن استخدام الغُفْل المولّد افتراضيًا.
</p>

<h3 id="-">
	ترقية كلمة مرور معماة موجودة إلى خوارزمية أقوى
</h3>

<p>
	إذا كنت تستخدم طريقة <code>PASSWORD_DEFAULT</code> لتجعل النظام يختار الخوارزمية الأفضل لتعمية كلمات المرور بها، مع زيادة قوة الخوارزمية الافتراضية قد ترغب في إعادة تعمية كلمات المرور القديمة عندما يسجل المستخدمون الدخول.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_322_27" style="">
<span class="pun">&lt;?</span><span class="pln">php
</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">password_verify</span><span class="pun">(</span><span class="pln">$plaintextPassword</span><span class="pun">,</span><span class="pln"> $hashedPassword</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">password_needs_rehash</span><span class="pun">(</span><span class="pln">$hashedPassword</span><span class="pun">,</span><span class="pln"> PASSWORD_DEFAULT</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// أنشئ كلمة معماة جديدة مع الخوارزمية الافتراضية الجديدة</span><span class="pln">
        $newHashedPassword </span><span class="pun">=</span><span class="pln"> password_hash</span><span class="pun">(</span><span class="pln">$plaintextPassword</span><span class="pun">,</span><span class="pln"> PASSWORD_DEFAULT</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// ثم احفظه في مخزن بياناتك</span><span class="pln">
        </span><span class="com">// $db-&gt;update(...);</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>

<p>
	إذا لم تكن الدوال <code>password_*‎</code> متوفرةً في نظامك ولا تستطيع استخدام حزمة التوافق، فعندها يمكنك تحديد الخوارزمية واستخدامها لإنشاء التعمية الأصلية بطريقة مشابهة للتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_322_29" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">substr</span><span class="pun">(</span><span class="pln">$hashedPassword</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">'$2y$'</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> strlen</span><span class="pun">(</span><span class="pln">$hashedPassword</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">60</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">'Algorithm is Bcrypt'</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// ‫يحدد "cost" مدى قوة إصدار Bcrypt </span><span class="pln">
    preg_match</span><span class="pun">(</span><span class="str">'/\$2y\$(\d+)\$/'</span><span class="pun">,</span><span class="pln"> $hashedPassword</span><span class="pun">,</span><span class="pln"> $matches</span><span class="pun">);</span><span class="pln">
    $cost </span><span class="pun">=</span><span class="pln"> $matches</span><span class="pun">[</span><span class="lit">1</span><span class="pun">];</span><span class="pln">
    echo </span><span class="str">'Bcrypt cost is '</span><span class="pun">.</span><span class="pln">$cost</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<h3 id="-">
	التحقق من كلمة المرور مقابل كلمة معماة
</h3>

<p>
	توفر الدالة <code>password_verify()‎</code> المدمجة بدءًا من الإصدار PHP 5.5، إمكانية التحقق من صحة كلمة مرور مقابل كلمة معماة مقابلة لها، أو غير مقابلة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_322_31" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">password_verify</span><span class="pun">(</span><span class="pln">$plaintextPassword</span><span class="pun">,</span><span class="pln"> $hashedPassword</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">'Valid Password'</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">
    echo </span><span class="str">'Invalid Password.'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	تخزن كل خوارزميات عملية التعمية المدعومة معلومات تحدد آلية التعمية المستخدمة، لذا لا حاجة للإشارة إلى الخوارزمية المستخدمة لتعمية كلمة المرور الأصلية.
</p>

<p>
	إذا لم تكن الدوال <code>password_*‎</code> متوفرةً في نظامك ولا تستطيع استخدام حزمة التوافق، فيمكنك التحقق من كلمة المرور باستخدام الدالة <code>crypt()‎</code>، لاحظ أنه يجب اتخاذ احتياطات محددة لتجنب <a data-ss1619530882="1" data-ss1619530992="1" data-ss1619608774="1" data-ss1619609077="1" href="https://en.wikipedia.org/wiki/Timing_attack" rel="external nofollow">هجمات التوقيت</a>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_322_33" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// ‫غير مضمون أن يحافظ على نفس قوة تشفير تنفيذ password_hash()‎ الكامل</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">CRYPT_BLOWFISH </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="com">// ‫تتجاهل crypt()‎ كل المحارف التي تتجاوز طول الغفل، لذا يمكننا تمرير ?كامل كلمة المرور المعماة</span><span class="pln">
    $hashedCheck </span><span class="pun">=</span><span class="pln"> crypt</span><span class="pun">(</span><span class="pln">$plaintextPassword</span><span class="pun">,</span><span class="pln"> $hashedPassword</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// ‫هذه موازنة وقت ثابت أساسية تعتمد على التنفيذ الكامل المستخدم في `password_hash()`</span><span class="pln">
    $status </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$i</span><span class="pun">=</span><span class="lit">0</span><span class="pun">;</span><span class="pln"> $i</span><span class="pun">&lt;</span><span class="pln">strlen</span><span class="pun">(</span><span class="pln">$hashedCheck</span><span class="pun">);</span><span class="pln"> $i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $status </span><span class="pun">|=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ord</span><span class="pun">(</span><span class="pln">$hashedCheck</span><span class="pun">[</span><span class="pln">$i</span><span class="pun">])</span><span class="pln"> </span><span class="pun">^</span><span class="pln"> ord</span><span class="pun">(</span><span class="pln">$hashedPassword</span><span class="pun">[</span><span class="pln">$i</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">$status </span><span class="pun">===</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">
        echo </span><span class="str">'Valid Password'</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">
        echo </span><span class="str">'Invalid 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">?&gt;</span></pre>

<p>
	ترجمة -وبتصرف- للفصول Cryptography - Password Hashing Functions من كتاب <a data-ss1619530882="1" data-ss1619530992="1" data-ss1619608774="1" data-ss1619609077="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>
]]></description><guid isPermaLink="false">1206</guid><pubDate>Sat, 01 May 2021 09:02:00 +0000</pubDate></item><item><title>&#x645;&#x645;&#x627;&#x631;&#x633;&#x627;&#x62A; &#x627;&#x644;&#x623;&#x645;&#x646; &#x648;&#x627;&#x644;&#x62D;&#x645;&#x627;&#x64A;&#x629; &#x641;&#x64A; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; PHP</title><link>https://academy.hsoub.com/programming/php/%D9%85%D9%85%D8%A7%D8%B1%D8%B3%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D9%85%D9%86-%D9%88%D8%A7%D9%84%D8%AD%D9%85%D8%A7%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-php-r1205/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_04/security.png.d3f80d8a50c23b44662f0e03c6a0d967.png" /></p>
<p>
	إنّ أمن التطبيقات موضوع مهم لمطوري PHP لحماية المواقع والبيانات والعملاء بما أنّ أغلب المواقع تستخدم PHP، يغطي هذا الموضوع أفضل ممارسات الأمان في PHP والثغرات ونقاط الضعف الشائعة مع أمثلة لكيفية إصلاحها.
</p>

<h2 id="-php">
	تسريب إصدار PHP
</h2>

<p>
	بشكل افتراضي تُخبر <a href="https://wiki.hsoub.com/PHP" rel="external">PHP </a>الآخرين بالإصدار الذي تستخدمه مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_6" style=""><span class="pln">X</span><span class="pun">-</span><span class="typ">Powered</span><span class="pun">-</span><span class="typ">By</span><span class="pun">:</span><span class="pln"> PHP</span><span class="pun">/</span><span class="lit">5.3</span><span class="pun">.</span><span class="lit">8</span></pre>

<p>
	لإصلاح ذلك يمكنك إما تغييره في ملف <code>php.ini</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_8" style=""><span class="pln">expose_php </span><span class="pun">=</span><span class="pln"> off</span></pre>

<p>
	أو تغيير الترويسة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_10" style=""><span class="pln">header</span><span class="pun">(</span><span class="str">"X-Powered-By: Magic"</span><span class="pun">);</span></pre>

<p>
	أو استخدام طريقة htaccess:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_12" style=""><span class="typ">Header</span><span class="pln"> unset X</span><span class="pun">-</span><span class="typ">Powered</span><span class="pun">-</span><span class="typ">By</span></pre>

<p>
	إذا لم تعمل كل الطرق السابقة يمكنك استخدام الدالة <a href="https://www.php.net/header_remove" rel="external nofollow">header_remove()‎</a> التي توفر لك قابلية حذف الترويسة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_14" style=""><span class="pln">header_remove</span><span class="pun">(</span><span class="str">'X-Powered-By'</span><span class="pun">);</span></pre>

<p>
	إذا عرف المهاجمون أنك تستخدم PHP والإصدار الذي تستخدمه فيكون من السهل عليهم استغلال خادمك.
</p>

<h2 id="-xss-">
	هجمات البرمجة عبر المواقع (XSS)
</h2>

<h3>
	المشكلة
</h3>

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

<p>
	مثلًا إذا كان لدينا طرف ثالث يحتوي على ملف جافاسكربت:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8359_16" style=""><span class="com">// http://example.com/runme.js</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"I'm running"</span><span class="pun">);</span></pre>

<p>
	وتطبيق PHP يعرض مباشرةً سلسلة نصية ممررة إليه:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_18" style=""><span class="pun">&lt;?</span><span class="pln">php
echo </span><span class="str">'&lt;div&gt;'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">'input'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">'&lt;/div&gt;'</span><span class="pun">;</span></pre>

<p>
	إذا تضمن معامل <code>GET</code> غير المُتحقق منه، ما يلي:
</p>

<pre class="ipsCode" id="ips_uid_8359_103"> ‎&lt;script src="http://example.com/runme.js"&gt;&lt;/script&gt;‎ </pre>

<p>
	فسيكون خرج سكربت PHP:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_20" style=""><span class="tag">&lt;div&gt;&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"http://example.com/runme.js"</span><span class="tag">&gt;&lt;/script&gt;&lt;/div&gt;</span></pre>

<p>
	سيُنفَّذ ملف جافاسكربت من طرف ثالث وسترى العبارة "I'm running" على صفحة الويب.
</p>

<h3>
	الحل
</h3>

<p>
	عمومًا، يجب ألا تثق أبدًا بالمدخلات من طرف العميل، إذ أنّ قيمة <code>GET</code> أو <code>POST</code> أو ملف تعريف ارتباط cookie يمكن أن تكون أي شيء لذا يجب التحقق من صحتها، عند عرض أي من هذه القيم اهرب بها حتى لا تُقيَّم بطريقة غير متوقعة، وتذكر أنّ البيانات يمكن أن تُنقل حتى في أبسط التطبيقات وسيكون من الصعب تتبع جميع المصادر لذا من المناسب دائمًا أن تهرِّب القيم عند الإخراج، توفر PHP عدة طرق لتهرِّب الخرج بالاعتماد على السياق.
</p>

<h3>
	الدوال المرشحة
</h3>

<p>
	تسمح <a href="https://www.php.net/manual/en/ref.filter.php" rel="external nofollow">دوال الترشيح في PHP</a> <a href="https://www.php.net/manual/en/filter.filters.sanitize.php" rel="external nofollow">بتعقيم</a> أو <a data-ss1619609895="1" data-ss1619610813="1" href="https://www.php.net/manual/en/filter.filters.validate.php" rel="external nofollow">التحقق من صحة</a> البيانات المُدخلة إلى سكربت PHP <a data-ss1619609895="1" data-ss1619610813="1" href="https://www.php.net/manual/en/filter.filters.php" rel="external nofollow">بعدة طرق</a>. وهي مفيدة عند حفظ أو عرض دخل المستخدم.
</p>

<h3>
	ترميز HTML
</h3>

<p>
	تحوّل <code>htmlspecialchars</code> أي محارف HTML خاصة إلى ترميزات HTML الخاصة بها، مما يعني أنّها لن تُعالَج بعدها كترميز HTML المعياري، نستخدم التابع التالي لإصلاح مثالنا السابق:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8359_37" style=""><span class="pun">&lt;?</span><span class="pln">php
echo </span><span class="str">'&lt;div&gt;'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> htmlspecialchars</span><span class="pun">(</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">'input'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">'&lt;/div&gt;'</span><span class="pun">;</span><span class="pln">
</span><span class="com">// أو</span><span class="pln">
echo </span><span class="str">'&lt;div&gt;'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> filter_input</span><span class="pun">(</span><span class="pln">INPUT_GET</span><span class="pun">,</span><span class="pln"> </span><span class="str">'input'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_SPECIAL_CHARS</span><span class="pun">)</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">'&lt;/div&gt;'</span><span class="pun">;</span></pre>

<p>
	الخرج:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8359_39" style=""><span class="tag">&lt;div&gt;</span><span class="pln">&amp;lt;script src=&amp;quot;http://example.com/runme.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;</span><span class="tag">&lt;/div&gt;</span></pre>

<p>
	كل ما هو داخل وسم <code>&lt;div&gt;</code> لن يفسّره المتصفح كوسم جافاسكربت وإنّما كعقدة نصية بسيطة وسيرى المستخدم بأمان:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8359_41" style=""><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"http://example.com/runme.js"</span><span class="tag">&gt;&lt;/script&gt;</span></pre>

<h3>
	ترميز الرابط
</h3>

<p>
	توفر PHP الدالة <code>urlencode</code> لإخراج روابط صحيحة بأمان عند عرض رابط متولِّد ديناميكيًا. لذا إذا كان المستخدم قادرًا على إدخال بيانات تصبح جزءًا من معامل <code>GET</code> آخر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_43" style=""><span class="pun">&lt;?</span><span class="pln">php
$input </span><span class="pun">=</span><span class="pln"> urlencode</span><span class="pun">(</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">'input'</span><span class="pun">]);</span><span class="pln">
</span><span class="com">// أو</span><span class="pln">
$input </span><span class="pun">=</span><span class="pln"> filter_input</span><span class="pun">(</span><span class="pln">INPUT_GET</span><span class="pun">,</span><span class="pln"> </span><span class="str">'input'</span><span class="pun">,</span><span class="pln"> FILTER_SANITIZE_URL</span><span class="pun">);</span><span class="pln">
echo </span><span class="str">'&lt;a href="http://example.com/page?input="'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $input </span><span class="pun">.</span><span class="pln"> </span><span class="str">'"&gt;Link&lt;/a&gt;'</span><span class="pun">;</span></pre>

<p>
	سيُحوَّل أي دخل ضار إلى معامل رابط مُرمَّز.
</p>

<h3>
	استخدام مكتبات خارجية متخصصة أو قوائم OWASP AntiSamy
</h3>

<p>
	قد تحتاج أحيانًا إلى إرسال شيفرة HTML أو نوع شيفرة آخر مُدخل، عندها يجب أن تحتفظ بقائمة من الكلمات المصرَّح بها (قائمة بيضاء) وقائمة بالكلمات غير المصرَّح بها (قائمة سوداء)، يمكنك تحميل القوائم المعيارية المتوفرة في موقع OWASP AntiSamy، وهي اختصار إلى ‏Open Web Application Security Project، تناسب كل قائمة نوع محدد من التفاعل (واجهة برمجة تطبيقات eBay، محرر النصوص tinyMCE وغير ذلك) وهي مفتوحة المصدر.
</p>

<p>
	يوجد مكتبات لترشيح شيفرة HTML ومنع هجمات XSS في الحالة العامة وتؤدي على الأقل نفس أداء قوائم AntiSamy مع استخدام سهل جدًا. لديك مثلًا <a href="http://htmlpurifier.org/" rel="external nofollow">منقي HTML</a>.
</p>

<h2 id="-cross-site-request-forgery-">
	هجمات تزوير الطلب عبر المواقع (Cross-Site Request Forgery)
</h2>

<h3>
	المشكلة
</h3>

<p>
	يمكن أن يفرض هجوم تزوير الطلب عبر الموقع CSRF المستخدم النهائي على توليد طلبات ضارة إلى خادم الويب بدون علمه، يمكن استغلال هذا الهجوم في طلبات <code>POST</code> و<code>GET</code>، لنفرض مثلًا أنّ رابط نقطة النهاية <code>‎/delete.php?accnt=12‎</code> يحذف الحساب الممرر عبر المعامل <code>accnt</code> في الطلب <code>GET</code>، إذا واجه الآن المستخدم الموثوق السكربت التالي في أي تطبيق آخر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_45" style=""><span class="tag">&lt;img</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"http://domain.com/delete.php?accnt=12"</span><span class="pln"> </span><span class="atn">width</span><span class="pun">=</span><span class="atv">"0"</span><span class="pln"> </span><span class="atn">height</span><span class="pun">=</span><span class="atv">"0"</span><span class="pln"> </span><span class="atn">border</span><span class="pun">=</span><span class="atv">"0"</span><span class="tag">&gt;</span></pre>

<p>
	سيُحذف الحساب.
</p>

<h3>
	الحل
</h3>

<p>
	الحل الشائع لهذه المشكلة هو استخدام مفاتيح CSRF (‏CSRF tokens)، تُضمَّن هذه المفاتيح في الطلبات بحيث يمكن لتطبيق الويب أن يثق أنّ الطلب قادم من مصدر متوقع كجزء من تدفق العمل العادي للتطبيق، يقوم المستخدم أولًا ببعض الإجراءات مثل عرض نموذج يبدأ بإنشاء مفتاح فريد، مثال بسيط لذلك:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_48" style=""><span class="tag">&lt;form</span><span class="pln"> </span><span class="atn">method</span><span class="pun">=</span><span class="atv">"get"</span><span class="pln"> </span><span class="atn">action</span><span class="pun">=</span><span class="atv">"/delete.php"</span><span class="tag">&gt;</span><span class="pln">
    </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">"accnt"</span><span class="pln"> </span><span class="atn">placeholder</span><span class="pun">=</span><span class="atv">"accnt number"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
    &lt;input type="hidden" name="csrf_token" value="</span><span class="tag">&lt;randomToken&gt;</span><span class="pln">" /&gt;
    </span><span class="tag">&lt;input</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="tag">/&gt;</span><span class="pln">
</span><span class="tag">&lt;/form&gt;</span></pre>

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

<h3>
	مثال
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_50" style=""><span class="com">// ‫الشيفرة التالية لتوليد مفتاح CSRF وتخزينه</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php
    session_start</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">function</span><span class="pln"> generate_token</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="pun">(!</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$_SESSION</span><span class="pun">[</span><span class="str">"csrf_token"</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="com">// لا يوجد مفتاح لذا ولّد واحدًا جديدًا</span><span class="pln">
            $token </span><span class="pun">=</span><span class="pln"> random_bytes</span><span class="pun">(</span><span class="lit">64</span><span class="pun">);</span><span class="pln">
            $_SESSION</span><span class="pun">[</span><span class="str">"csrf_token"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $token</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">
            </span><span class="com">// أعد استخدام المفتاح</span><span class="pln">
            $token </span><span class="pun">=</span><span class="pln"> $_SESSION</span><span class="pun">[</span><span class="str">"csrf_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"> $token</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">
</span><span class="str">&lt;body&gt;</span><span class="pln">
    </span><span class="pun">&lt;</span><span class="pln">form method</span><span class="pun">=</span><span class="str">"get"</span><span class="pln"> action</span><span class="pun">=</span><span class="str">"/delete.php"</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"> name</span><span class="pun">=</span><span class="str">"accnt"</span><span class="pln"> placeholder</span><span class="pun">=</span><span class="str">"accnt number"</span><span class="pln"> </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">"hidden"</span><span class="pln"> name</span><span class="pun">=</span><span class="str">"csrf_token"</span><span class="pln"> value</span><span class="pun">=</span><span class="str">"&lt;?php echo generate_token();?&gt;"</span><span class="pln"> </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">"submit"</span><span class="pln"> </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">body</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">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php
    session_start</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">$_GET</span><span class="pun">[</span><span class="str">"csrf_token"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> $_SESSION</span><span class="pun">[</span><span class="str">"csrf_token"</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// أعد تعيين المفتاح</span><span class="pln">
        unset</span><span class="pun">(</span><span class="pln">$_SESSION</span><span class="pun">[</span><span class="str">"csrf_token"</span><span class="pun">]);</span><span class="pln">
        </span><span class="kwd">die</span><span class="pun">(</span><span class="str">"CSRF token validation failed"</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">
</span><span class="pun">...</span></pre>

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

<h2 id="-">
	حقن سطر الأوامر
</h2>

<h3>
	المشكلة
</h3>

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

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_53" style=""><span class="tag">&lt;pre&gt;</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php system</span><span class="pun">(</span><span class="str">'ls '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $_GET</span><span class="pun">[</span><span class="str">'path'</span><span class="pun">]);</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln">
</span><span class="tag">&lt;/pre&gt;</span></pre>

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

<p>
	قد تتأمل الحصول على معامل مسار بشكلٍ مشابه للمعامل <code>‎/tmp</code> ولكن بما أنّ أي دخل مسموح به فمن الممكن أن يكون <code>‎; rm -fr /‎</code>، عندها سينفذ خادم الويب الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_55" style=""><span class="pln">ls</span><span class="pun">;</span><span class="pln"> rm </span><span class="pun">-</span><span class="pln">fr </span><span class="pun">/</span></pre>

<p>
	ويحاول حذف كل الملفات من المجلد الجذر للخادم.
</p>

<h3>
	الحل
</h3>

<p>
	يجب أن تُهرَّب جميع وسائط الأمر باستخدام الدالة <code>escapeshellarg()‎</code> أو <code>escapeshellcmd()‎</code> مما يجعلها غير قابلة للتنفيذ كما يجب أن يتم التحقق من صحة كل قيمة مدخلة.
</p>

<p>
	في أبسط الحالات يمكننا تأمين مثالنا بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_57" style=""><span class="tag">&lt;pre&gt;</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php system</span><span class="pun">(</span><span class="str">'ls '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> escapeshellarg</span><span class="pun">(</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">'path'</span><span class="pun">]));</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln">
</span><span class="tag">&lt;/pre&gt;</span></pre>

<p>
	وفقًا للمثال السابق، مع محاولة حذف الملفات يصبح الأمر المنفّذ:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_59" style=""><span class="pln">ls </span><span class="str">'; rm -fr /'</span></pre>

<p>
	وتُمرَّر السلسلة النصية ببساطة كمعامل للأمر <code>ls</code> بدلًا من إنهاء هذا الأمر وتنفيذ الأمر <code>rm</code>.
</p>

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

<p>
	توفر PHP دوالًا متنوعة لتنفيذ أوامر النظام مثل كلّ من:
</p>

<ul>
	<li>
		<code>exec</code>.
	</li>
	<li>
		<code>‏passthru</code>
	</li>
	<li>
		<code>‏proc_open</code>
	</li>
	<li>
		<code>‏‏shell_exec</code>
	</li>
	<li>
		<code>system</code>
	</li>
</ul>

<p>
	حيث يجب التحقق من صحة جميع مدخلاتها وتهريبها.
</p>

<h2 id="-">
	إزالة الوسوم
</h2>

<p>
	إنّ الدالة <a href="https://wiki.hsoub.com/PHP/strip_tags" rel="external">strip_tags</a> دالة قوية جدًا إذا كنت تعرف كيفية استخدامها، وتوجد طرق أفضل لمنع هجمات البرمجة عبر المواقع مثل ترميز المحارف لكن إزالة الوسوم مفيدة في بعض الحالات.
</p>

<p>
	انظر المثال الأساسي التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_62" style=""><span class="pln">$string </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;b&gt;Hello,&lt;&gt; please remove the &lt;&gt; tags.&lt;/b&gt;'</span><span class="pun">;</span><span class="pln">
echo strip_tags</span><span class="pun">(</span><span class="pln">$string</span><span class="pun">);</span></pre>

<p>
	الخرج الخام الناتج:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_64" style=""><span class="typ">Hello</span><span class="pun">,</span><span class="pln"> please remove the tags</span><span class="pun">.</span></pre>

<p>
	بفرض أنك تريد السماح بوجود وسم معين، عندها يجب أن تحدد ذلك في المعامل الثاني للدالة، هذا المعامل اختياري، فمثلًا إذا أردت السماح بمرور الوسم <code>&lt;b&gt;</code> فقط.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_66" style=""><span class="pln">$string </span><span class="pun">=</span><span class="pln"> </span><span class="str">'&lt;b&gt;Hello,&lt;&gt; please remove the &lt;br&gt; tags.&lt;/b&gt;'</span><span class="pun">;</span><span class="pln">
echo strip_tags</span><span class="pun">(</span><span class="pln">$string</span><span class="pun">,</span><span class="pln"> </span><span class="str">'&lt;b&gt;'</span><span class="pun">);</span></pre>

<p>
	الخرج الخام للشيفرة السابقة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_68" style=""><span class="tag">&lt;b&gt;</span><span class="pln">Hello, please remove the tags.</span><span class="tag">&lt;/b&gt;</span></pre>

<p>
	<strong>ملاحظة</strong>: إنّ تعليقات HTML ووسوم PHP تُزال أيضًا وهذا لا يمكن تغييره، وفي الإصدار PHP 5.3.4 والإصدارات اللاحقة تُهمل وسوم XHTML ذاتية الإغلاق وتُستخدم فقط الوسوم غير ذاتية الإغلاق فمثلًا للسماح بالوسمين <code>&lt;br&gt;</code> و<code>&lt;br/&gt;</code> يجب أن تستخدم:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_70" style=""><span class="pun">&lt;?</span><span class="pln">php
strip_tags</span><span class="pun">(</span><span class="pln">$input</span><span class="pun">,</span><span class="pln"> </span><span class="str">'&lt;br&gt;'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<h2 id="-">
	إدراج ملف
</h2>

<h3>
	إدراج ملف بعيد
</h3>

<p>
	يعد إدراج ملف بعيد RFI نوعًا من الثغرات التي تسمح للمهاجم بتضمين ملف بعيد، يحقن هذا المثال ملفًا مستضافًا عن بعد يتضمن شيفرة ضارة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_72" style=""><span class="pun">&lt;?</span><span class="pln">php
include $_GET</span><span class="pun">[</span><span class="str">'page'</span><span class="pun">];</span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2959_9" style=""><span class="str">/vulnerable.php?page=http:/</span><span class="pun">/</span><span class="pln">evil</span><span class="pun">.</span><span class="pln">example</span><span class="pun">.</span><span class="pln">com</span><span class="pun">/</span><span class="pln">webshell</span><span class="pun">.</span><span class="pln">txt</span><span class="pun">?</span></pre>

<h3>
	إدراج ملف محلي
</h3>

<p>
	إدراج ملف محلي LFI في عملية تضمين الملفات على الخادم عبر متصفح الويب.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_74" style=""><span class="pun">&lt;?</span><span class="pln">php
$page </span><span class="pun">=</span><span class="pln"> </span><span class="str">'pages/'</span><span class="pun">.</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">'page'</span><span class="pun">];</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$page</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    include $page</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">
    include </span><span class="str">'index.php'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2959_11" style=""><span class="str">/vulnerable.php?page=../</span><span class="pun">../../../</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">passwd</span></pre>

<h3>
	حل RFI وLFI
</h3>

<p>
	يُنصح بالسماح بتضمين الملفات التي توافق عليها فقط.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_76" style=""><span class="pun">&lt;?</span><span class="pln">php
$page </span><span class="pun">=</span><span class="pln"> </span><span class="str">'pages/'</span><span class="pun">.</span><span class="pln">$_GET</span><span class="pun">[</span><span class="str">'page'</span><span class="pun">].</span><span class="str">'.php'</span><span class="pun">;</span><span class="pln">
$allowed </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'pages/home.php'</span><span class="pun">,</span><span class="str">'pages/error.php'</span><span class="pun">];</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">in_array</span><span class="pun">(</span><span class="pln">$page</span><span class="pun">,</span><span class="pln">$allowed</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    include</span><span class="pun">(</span><span class="pln">$page</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">
    include</span><span class="pun">(</span><span class="str">'index.php'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="-">
	الإبلاغ عن الأخطاء
</h2>

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

<h3>
	حل سريع
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_78" style=""><span class="pun">&lt;?</span><span class="pln">php
    ini_set</span><span class="pun">(</span><span class="str">"display_errors"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"0"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	أو تغيير هذا مباشرةً في ملف <code>php.ini</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_82" style=""><span class="pln">display_errors </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span></pre>

<h3>
	معالجة الأخطاء
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_84" style=""><span class="pln">set_error_handler</span><span class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span class="pln">$errno </span><span class="pun">,</span><span class="pln"> $errstr</span><span class="pun">,</span><span class="pln"> $errfile</span><span class="pun">,</span><span class="pln"> $errline</span><span class="pun">){</span><span class="pln">
    </span><span class="kwd">try</span><span class="pun">{</span><span class="pln">
        $pdo </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> PDO</span><span class="pun">(</span><span class="str">"mysql:host=hostname;dbname=databasename"</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dbuser'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dbpwd'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
            PDO</span><span class="pun">::</span><span class="pln">ATTR_ERRMODE </span><span class="pun">=&gt;</span><span class="pln"> PDO</span><span class="pun">::</span><span class="pln">ERRMODE_EXCEPTION
    </span><span class="pun">]);</span><span class="pln">

        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$stmt </span><span class="pun">=</span><span class="pln"> $pdo</span><span class="pun">-&gt;</span><span class="pln">prepare</span><span class="pun">(</span><span class="str">"INSERT INTO `errors` (no,msg,file,line) VALUES (?,?,?,?)"</span><span class="pun">)){</span><span class="pln">
            </span><span class="kwd">if</span><span class="pun">(!</span><span class="pln">$stmt</span><span class="pun">-&gt;</span><span class="pln">execute</span><span class="pun">([</span><span class="pln">$errno</span><span class="pun">,</span><span class="pln"> $errstr</span><span class="pun">,</span><span class="pln"> $errfile</span><span class="pun">,</span><span class="pln"> $errline</span><span class="pun">])){</span><span class="pln">
                </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">'Unable to execute query'</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">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Exception</span><span class="pun">(</span><span class="str">'Unable to prepare query'</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">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">
        error_log</span><span class="pun">(</span><span class="str">'Exception: '</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $e</span><span class="pun">-&gt;</span><span class="pln">getMessage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> PHP_EOL </span><span class="pun">.</span><span class="pln"> </span><span class="str">"$errfile:$errline:$errno | $errstr"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">});</span></pre>

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

<h2 id="-">
	رفع ملفات
</h2>

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

<h3>
	البيانات المرفوعة
</h3>

<p>
	تحتوي هذه المصفوفة على بيانات مُرسلة من قبل مستخدم وهي ليست معلومات عن الملف، بينما يولّد المتصفح هذه البيانات يمكن للمستخدم إرسال طلب بالطريقة <code>post</code> إلى نفس النموذج باستخدام برنامج.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_86" style=""><span class="pln">$_FILES</span><span class="pun">[</span><span class="str">'file'</span><span class="pun">][</span><span class="str">'name'</span><span class="pun">];</span><span class="pln">
$_FILES</span><span class="pun">[</span><span class="str">'file'</span><span class="pun">][</span><span class="str">'type'</span><span class="pun">];</span><span class="pln">
$_FILES</span><span class="pun">[</span><span class="str">'file'</span><span class="pun">][</span><span class="str">'size'</span><span class="pun">];</span><span class="pln">
$_FILES</span><span class="pun">[</span><span class="str">'file'</span><span class="pun">][</span><span class="str">'tmp_name'</span><span class="pun">];</span></pre>

<ul>
	<li>
		<code>name</code>: تحقق منه بالكامل
	</li>
	<li>
		<code>type</code>: لا تستخدم هذه البيانات أبدًا، يمكن الحصول عليها باستخدام دوال PHP بدلًا من ذلك.
	</li>
	<li>
		<code>size</code>: آمن للاستخدام.
	</li>
	<li>
		<code>tmp_name</code>: آمن للاستخدام.
	</li>
</ul>

<h3>
	استغلال اسم الملف
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_88" style=""><span class="pun">../</span><span class="pln">script</span><span class="pun">.</span><span class="pln">php</span><span class="pun">%</span><span class="lit">00.png</span></pre>

<p>
	تفحّص اسم الملف ويجب أن تلاحظ أمرين:
</p>

<ul>
	<li>
		الأول هو أنّ وجود <code>‎../‎</code> غير منطقي أبدًا في اسم الملف، لكن في نفس الوقت جيد إذا كنت تنقل ملفًا من مجلد إلى آخر.
	</li>
	<li>
		قد تعتقد الآن أنك كنت تتحقق من امتدادات الملف بشكلٍ صحيح في السكربت، لكن يعتمد هذا الاستغلال على فك تشفير الرابط، إذ يترجم <code>‎%00‎</code> إلى المحرف <code>null</code> ويقول لنظام التشغيل أن السلسلة انتهت هنا مما يزيل <code>‎.png</code> من اسم الملف.
	</li>
</ul>

<p>
	حمّلت الآن ملف <code>script.php</code> إلى مجلد آخر بتمرير عمليات تحقق بسيطة إلى امتدادات الملف وبتمرير ملفات <code>‎.htaccess‎</code> مما يمنع تنفيذ السكربتات من ضمن مجلدك المرفوع.
</p>

<h3>
	الحصول على اسم الملف والامتداد بشكلٍ آمن
</h3>

<p>
	يمكنك استخدام الدالة <code>pathinfo()‎</code> لاستقراء الاسم والامتداد بطريقةٍ آمنة، لكننا نحتاج أولًا لاستبدال المحارف غير المرغوب بها في اسم الملف:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_90" style=""><span class="com">// تتضمن هذه المصفوفة قائمة بالمحارف غير المسموح بها في اسم الملف</span><span class="pln">
$illegal </span><span class="pun">=</span><span class="pln"> array_merge</span><span class="pun">(</span><span class="pln">array_map</span><span class="pun">(</span><span class="str">'chr'</span><span class="pun">,</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="lit">31</span><span class="pun">)),</span><span class="pln"> </span><span class="pun">[</span><span class="str">"&lt;"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"&gt;"</span><span class="pun">,</span><span class="pln"> </span><span class="str">":"</span><span class="pun">,</span><span class="pln"> </span><span class="str">'"'</span><span class="pun">,</span><span class="pln"> </span><span class="str">"/"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"\\"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"|"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"?"</span><span class="pun">,</span><span class="str">"*"</span><span class="pun">,</span><span class="pln"> </span><span class="str">" "</span><span class="pun">]);</span><span class="pln">
$filename </span><span class="pun">=</span><span class="pln"> str_replace</span><span class="pun">(</span><span class="pln">$illegal</span><span class="pun">,</span><span class="pln"> </span><span class="str">"-"</span><span class="pun">,</span><span class="pln"> $_FILES</span><span class="pun">[</span><span class="str">'file'</span><span class="pun">][</span><span class="str">'name'</span><span class="pun">]);</span><span class="pln">
$pathinfo </span><span class="pun">=</span><span class="pln"> pathinfo</span><span class="pun">(</span><span class="pln">$filename</span><span class="pun">);</span><span class="pln">
$extension </span><span class="pun">=</span><span class="pln"> $pathinfo</span><span class="pun">[</span><span class="str">'extension'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> $pathinfo</span><span class="pun">[</span><span class="str">'extension'</span><span class="pun">]:</span><span class="str">''</span><span class="pun">;</span><span class="pln">
$filename </span><span class="pun">=</span><span class="pln"> $pathinfo</span><span class="pun">[</span><span class="str">'filename'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> $pathinfo</span><span class="pun">[</span><span class="str">'filename'</span><span class="pun">]:</span><span class="str">''</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(!</span><span class="pln">empty</span><span class="pun">(</span><span class="pln">$extension</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">!</span><span class="pln">empty</span><span class="pun">(</span><span class="pln">$filename</span><span class="pun">)){</span><span class="pln">
    echo $filename</span><span class="pun">,</span><span class="pln"> $extension</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">
    </span><span class="kwd">die</span><span class="pun">(</span><span class="str">'file is missing an extension or name'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	لدينا الآن اسم الملف والامتداد ويمكننا استخدامهما للتخزين، لكن مازلت أفضل تخزين هذه المعلومات في قاعدة البيانات وإعطاء الملف اسمًا مولّدًا له مثل <code>md5(uniqid().microtime())</code>‎.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2959_13" style=""><span class="pun">+----+--------+-----------+------------+------+----------------------------------+----------------</span><span class="pln">
</span><span class="pun">-----+</span><span class="pln">
</span><span class="pun">|</span><span class="pln"> id </span><span class="pun">|</span><span class="pln"> title </span><span class="pun">|</span><span class="pln"> extension </span><span class="pun">|</span><span class="pln"> mime </span><span class="pun">|</span><span class="pln"> size </span><span class="pun">|</span><span class="pln"> filename </span><span class="pun">|</span><span class="pln"> time
</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="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> myfile </span><span class="pun">|</span><span class="pln"> txt </span><span class="pun">|</span><span class="pln"> text</span><span class="pun">/</span><span class="pln">plain </span><span class="pun">|</span><span class="pln"> </span><span class="lit">1020</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">5bcdaeddbfbd2810fa1b6f3118804d66</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">2017</span><span class="pun">-</span><span class="lit">03</span><span class="pun">-</span><span class="lit">11</span><span class="pln">
</span><span class="lit">00</span><span class="pun">:</span><span class="lit">38</span><span class="pun">:</span><span class="lit">54</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>

<h3>
	التحقق من نوع الوسائط mime-type
</h3>

<p>
	التحقق من امتداد الملف لمعرفة ما هو نوع الملف غير كافٍ فقد يكون اسم الملف <code>image.png</code> لكنه يتضمن سكربت PHP، بالتحقق من نوع وسائط الملف المرفوع يمكنك التحقق من إذا كان الملف يتضمن ما يشير إليه اسمه أو لا.
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_92" style=""><span class="kwd">if</span><span class="pun">(</span><span class="pln">$mime </span><span class="pun">==</span><span class="pln"> </span><span class="str">'image/jpeg'</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> $extension </span><span class="pun">==</span><span class="pln"> </span><span class="str">'jpeg'</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> $extension </span><span class="pun">==</span><span class="pln"> </span><span class="str">'jpg'</span><span class="pun">){</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">$img </span><span class="pun">=</span><span class="pln"> imagecreatefromjpeg</span><span class="pun">(</span><span class="pln">$filename</span><span class="pun">)){</span><span class="pln">
        imagedestroy</span><span class="pun">(</span><span class="pln">$img</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">
        </span><span class="kwd">die</span><span class="pun">(</span><span class="str">'image failed to open, could be corrupt or the file contains something     else.'</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك الحصول على نوع الوسائط باستخدام <a data-ss1619609895="1" data-ss1619610813="1" href="https://www.php.net/manual/en/function.mime-content-type.php" rel="external nofollow">دالة</a> مدمجة أو <a data-ss1619609895="1" data-ss1619610813="1" href="https://www.php.net/manual/en/book.fileinfo.php" rel="external nofollow">صنف</a>.
</p>

<h3>
	وجود قائمة بيضاء للملفات المرفوعة
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_94" style=""><span class="kwd">function</span><span class="pln"> isFiletypeAllowed</span><span class="pun">(</span><span class="pln">$extension</span><span class="pun">,</span><span class="pln"> $mime</span><span class="pun">,</span><span class="pln"> array $allowed</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"> isset</span><span class="pun">(</span><span class="pln">$allowed</span><span class="pun">[</span><span class="pln">$mime</span><span class="pun">])</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">
    is_array</span><span class="pun">(</span><span class="pln">$allowed</span><span class="pun">[</span><span class="pln">$mime</span><span class="pun">])</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln">
    in_array</span><span class="pun">(</span><span class="pln">$extension</span><span class="pun">,</span><span class="pln"> $allowed</span><span class="pun">[</span><span class="pln">$mime</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$allowedFiletypes </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
    </span><span class="str">'image/png'</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">'png'</span><span class="pln"> </span><span class="pun">],</span><span class="pln">
    </span><span class="str">'image/gif'</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">'gif'</span><span class="pln"> </span><span class="pun">],</span><span class="pln">
    </span><span class="str">'image/jpeg'</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">'jpg'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'jpeg'</span><span class="pln"> </span><span class="pun">],</span><span class="pln">
</span><span class="pun">];</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">isFiletypeAllowed</span><span class="pun">(</span><span class="str">'jpg'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'image/jpeg'</span><span class="pun">,</span><span class="pln"> $allowedFiletypes</span><span class="pun">));</span></pre>

<h2 id="-remember-me-">
	كتابة دالة تحافظ على تسجيل المستخدم بأفضل أسلوب
</h2>

<p>
	تخزين ملف تعريف الارتباط في ثلاثة أجزاء.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_8359_96" style=""><span class="kwd">function</span><span class="pln"> onLogin</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="com">// ‫توليد مفتاح، يجب أن يكون بين 128 - 256 بت</span><span class="pln">
    $token </span><span class="pun">=</span><span class="pln"> </span><span class="typ">GenerateRandomToken</span><span class="pun">();</span><span class="pln">
    storeTokenForUser</span><span class="pun">(</span><span class="pln">$user</span><span class="pun">,</span><span class="pln"> $token</span><span class="pun">);</span><span class="pln">
    $cookie </span><span class="pun">=</span><span class="pln"> $user </span><span class="pun">.</span><span class="pln"> </span><span class="str">':'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $token</span><span class="pun">;</span><span class="pln">
    $mac </span><span class="pun">=</span><span class="pln"> hash_hmac</span><span class="pun">(</span><span class="str">'sha256'</span><span class="pun">,</span><span class="pln"> $cookie</span><span class="pun">,</span><span class="pln"> SECRET_KEY</span><span class="pun">);</span><span class="pln">
    $cookie </span><span class="pun">.=</span><span class="pln"> </span><span class="str">':'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $mac</span><span class="pun">;</span><span class="pln">
    setcookie</span><span class="pun">(</span><span class="str">'rememberme'</span><span class="pun">,</span><span class="pln"> $cookie</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_8359_98" style=""><span class="kwd">function</span><span class="pln"> rememberMe</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $cookie </span><span class="pun">=</span><span class="pln"> isset</span><span class="pun">(</span><span class="pln">$_COOKIE</span><span class="pun">[</span><span class="str">'rememberme'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> $_COOKIE</span><span class="pun">[</span><span class="str">'rememberme'</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">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$cookie</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        list </span><span class="pun">(</span><span class="pln">$user</span><span class="pun">,</span><span class="pln"> $token</span><span class="pun">,</span><span class="pln"> $mac</span><span class="pun">)</span><span class="pln"> </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"> $cookie</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">hash_equals</span><span class="pun">(</span><span class="pln">hash_hmac</span><span class="pun">(</span><span class="str">'sha256'</span><span class="pun">,</span><span class="pln"> $user </span><span class="pun">.</span><span class="pln"> </span><span class="str">':'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $token</span><span class="pun">,</span><span class="pln"> SECRET_KEY</span><span class="pun">),</span><span class="pln"> $mac</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="kwd">false</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        $usertoken </span><span class="pun">=</span><span class="pln"> fetchTokenByUserName</span><span class="pun">(</span><span class="pln">$user</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">hash_equals</span><span class="pun">(</span><span class="pln">$usertoken</span><span class="pun">,</span><span class="pln"> $token</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            logUserIn</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">
</span><span class="pun">}</span></pre>

<p>
	ترجمة -وبتصرف- للفصول [Security - Secure Remeber Me] من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>
]]></description><guid isPermaLink="false">1205</guid><pubDate>Thu, 29 Apr 2021 09:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x639;&#x627;&#x644;&#x62C;&#x629; &#x627;&#x644;&#x645;&#x62A;&#x639;&#x62F;&#x62F;&#x629; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D9%85%D8%AA%D8%B9%D8%AF%D8%AF%D8%A9-%D9%81%D9%8A-php-r1204/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_04/Multiprocessing.png.bbc47e395f9ebcdae08539a3a53617fc.png" /></p>

<h2 id="-">
	المعالجة المتعددة باستخدام دوال العمليات الفرعية المضمنة
</h2>

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

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

<p>
	ملف <code>master.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1280_8" style="">
<span class="pln">$cmd </span><span class="pun">=</span><span class="pln"> </span><span class="str">"php worker.php 10"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫نستخدم في نظام التشغيل ويندوز popen وpclose</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln">strtoupper</span><span class="pun">(</span><span class="pln">substr</span><span class="pun">(</span><span class="pln">PHP_OS</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="str">'WIN'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    pclose</span><span class="pun">(</span><span class="pln">popen</span><span class="pun">(</span><span class="pln">$cmd</span><span class="pun">,</span><span class="str">"r"</span><span class="pun">));</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">// ‫نستخدم في أنظمة يونكس shell exec مع علامة "&amp;" في النهاية</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">exec</span><span class="pun">(</span><span class="str">'bash -c "exec nohup setsid '</span><span class="pun">.</span><span class="pln">$cmd</span><span class="pun">.</span><span class="str">' &gt; /dev/null 2&gt;&amp;1 &amp;"'</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملف <code>worker.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1280_10" style="">
<span class="com">// إرسال رسائل بريد إلكتروني، تحميل ملفات، تحليل سجلات وغير ذلك</span><span class="pln">
$sleeptime </span><span class="pun">=</span><span class="pln"> $argv</span><span class="pun">[</span><span class="lit">1</span><span class="pun">];</span><span class="pln">
sleep</span><span class="pun">(</span><span class="pln">$sleeptime</span><span class="pun">);</span></pre>

<h2 id="-fork">
	إنشاء عملية ابن باستخدام fork
</h2>

<p>
	يوجد في PHP الدالة المضمنة <code>pcntl_fork</code> لإنشاء عملية ابن، وهي مشابهة للدالة <code>fork</code> في يونكس، لا تأخذ معاملات وترجع عددًا صحيحًا يمكن استخدامه للتمييز بين العملية الأب والعملية الابن، بفرض لدينا الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1280_12" style="">
<span class="pun">&lt;?</span><span class="pln">php
    </span><span class="com">// ‫‎$pid معرّف العملية الابن</span><span class="pln">
    $pid </span><span class="pun">=</span><span class="pln"> pcntl_fork</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">$pid </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"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">die</span><span class="pun">(</span><span class="str">'Error while creating child process'</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="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$pid</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="kwd">else</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">?&gt;</span></pre>

<p>
	كما تلاحظ يدل ‎-1 على حدوث خطأ وعدم إنشاء العملية الابن، عند إنشاء العملية الابن يكون لدينا عمليتان تنفذان ولكل منهما معرِّف عملية <abbr title="Process IDentifier | معرّف العملية أو البرنامج">PID</abbr> مختلف.⁦
</p>

<p>
	يجب أن ننتبه هنا أيضًا إلى العملية الميتة zombie process أو العملية المنقطعة defunct process عندما تنتهي العملية الأب قبل العملية الابن. لمنع العملية الابن الميتة نضيف<code>pcntl_wait($status)‎</code> في نهاية العملية الأب، إذ توقف هذه الدالة تنفيذ العملية الأب حتى تنتهي العملية الابن. ويجب الانتباه أيضًا إلى أنه لا يمكن قتل العملية الميتة باستخدام العلامة <code>SIGKILL</code>.
</p>

<h2 id="-">
	التواصل بين العمليات
</h2>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1280_14" style="">
<span class="pun">&lt;?</span><span class="pln">php
    $descriptor </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">(</span><span class="pln">
        </span><span class="com">// أنبوب من أجل مجرى الدخل القياسي للابن</span><span class="pln">
        </span><span class="lit">0</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> array</span><span class="pun">(</span><span class="str">"pipe"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"r"</span><span class="pun">),</span><span class="pln"> 
        </span><span class="com">// أنبوب من أجل مجرى الخرج القياسي للابن</span><span class="pln">
        </span><span class="lit">1</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> array</span><span class="pun">(</span><span class="str">"pipe"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"w"</span><span class="pun">),</span><span class="pln"> 
    </span><span class="pun">);</span><span class="pln">
    $process </span><span class="pun">=</span><span class="pln"> proc_open</span><span class="pun">(</span><span class="str">"bash"</span><span class="pun">,</span><span class="pln"> $descriptor</span><span class="pun">,</span><span class="pln"> $pipes</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">is_resource</span><span class="pun">(</span><span class="pln">$process</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        fwrite</span><span class="pun">(</span><span class="pln">$pipes</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> </span><span class="str">"pwd"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">);</span><span class="pln">
        fclose</span><span class="pun">(</span><span class="pln">$pipes</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
        echo stream_get_contents</span><span class="pun">(</span><span class="pln">$pipes</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]);</span><span class="pln">
        fclose</span><span class="pun">(</span><span class="pln">$pipes</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]);</span><span class="pln">
        $return_value </span><span class="pun">=</span><span class="pln"> proc_close</span><span class="pun">(</span><span class="pln">$process</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>proc_open</code> أوامر bash مع <code>‎$descriptor</code> كمواصفات للواصف، ونستخدم بعدها <code>is_resource</code> للتحقق من صحة العملية، وعند الانتهاء يمكننا البدء بالتفاعل مع العملية الابن باستخدام <code>‎$pipes</code> الذي يتولد تبعًا لمواصفات الواصف.
</p>

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

<p>
	تذكر دومًا إغلاق العملية الابن باستخدام الدالة <code>proc_close()‎</code> التي ستنهي العملية الابن وتعيد شيفرة حالة الخروج.
</p>

<h2 id="-multi-threading-">
	الإضافة متعددة الخيوط (Multi Threading)
</h2>

<p>
	للبدء مع تعدد الخيوط تحتاج لتثبيت الإضافة <code>pthreads</code> ويمكنك القيام بذلك بكتابة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1280_16" style="">
<span class="pln">$ pecl install pthreads</span></pre>

<p>
	وإضافة المدخل إلى ملف <code>php.ini</code>.
</p>

<p>
	مثال بسيط باستخدام دلالات PHP7:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1280_20" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyThread</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Thread</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">private</span><span class="pln"> $message</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="kwd">string</span><span class="pln"> $message</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">message </span><span class="pun">=</span><span class="pln"> $message</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"> run</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo $this</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="pun">}</span><span class="pln">

</span><span class="com">// ‫تهيئة الكائن MyThread</span><span class="pln">
$myThread </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyThread</span><span class="pun">(</span><span class="str">"Hello from an another thread!"</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ابدأ الخيط، ومن الجيد أيضًا الانضمام إلى الخيط بشكلٍ صريح</span><span class="pln">
</span><span class="com">// ‫نستخدم Thread::start()‎ لتهيئة الخيط</span><span class="pln">
$myThread</span><span class="pun">-&gt;</span><span class="pln">start</span><span class="pun">();</span><span class="pln">

</span><span class="com">// ‫تسبب التعليمة Thread::join()‎ أن ينتظر السياق الخيط حتى انتهاء التنفيذ</span><span class="pln">
$myThread</span><span class="pun">-&gt;</span><span class="pln">join</span><span class="pun">();</span></pre>

<h3 id="-pools-workers-">
	استخدام المجمعات (pools) والتوابع (workers)
</h3>

<p>
	توفر التجميعات مستوى تجريدي أعلى لوظيفة التابع، بما في ذلك إدارة المراجع بالطريقة التي تطلبها pthreads (انظر <a data-ss1619611106="1" data-ss1619611226="1" href="https://www.php.net/manual/en/class.pool.php" rel="external nofollow">هذه الصفحة</a>).
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1280_22" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// (1)</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">AwesomeWork</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Thread</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">private</span><span class="pln"> $workName</span><span class="pun">;</span><span class="pln">
    </span><span class="com">/**
    * @param string $workName
    * اسم العمل الذي سيُعطى لكل عمل
    */</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="kwd">string</span><span class="pln"> $workName</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (2)</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">workName </span><span class="pun">=</span><span class="pln"> $workName</span><span class="pun">;</span><span class="pln">
        printf</span><span class="pun">(</span><span class="str">"A new work was submitted with the name: %s\n"</span><span class="pun">,</span><span class="pln"> $workName</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"> run</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (3)</span><span class="pln">
        $workName </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">workName</span><span class="pun">;</span><span class="pln">
        printf</span><span class="pun">(</span><span class="str">"Work named %s starting...\n"</span><span class="pun">,</span><span class="pln"> $workName</span><span class="pun">);</span><span class="pln">
        printf</span><span class="pun">(</span><span class="str">"New random number: %d\n"</span><span class="pun">,</span><span class="pln"> mt_rand</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">class</span><span class="pln"> </span><span class="typ">AwesomeWorker</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Worker</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"> run</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// (4)</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// (5)</span><span class="pln">
$pool </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Pool</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> \AwesomeWorker</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">);</span><span class="pln">

</span><span class="com">// (6)</span><span class="pln">
$pool</span><span class="pun">-&gt;</span><span class="pln">submit</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> \AwesomeWork</span><span class="pun">(</span><span class="str">"DeadlyWork"</span><span class="pun">));</span><span class="pln">
$pool</span><span class="pun">-&gt;</span><span class="pln">submit</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> \AwesomeWork</span><span class="pun">(</span><span class="str">"FatalWork"</span><span class="pun">));</span><span class="pln">

</span><span class="com">// (7)</span><span class="pln">
$pool</span><span class="pun">-&gt;</span><span class="pln">shutdown</span><span class="pun">();</span></pre>

<ul>
<li>
		في الموضع (1) يوجد العمل الذي سيُنفَّذ من قِبل العامل، يحتاج هذا الصنف أن يرث الصنف <code>‎\Threaded</code> أو <code>‎\Collectable</code> أو <code>‎\Thread</code>.
	</li>
	<li>
		في الموضع (2) كتلة الشيفرة في باني عملك والتي ستُنفَّذ عندما يُرسل عمل إلى مجمعك.
	</li>
	<li>
		في الموضع (3) ستُستدعى هذه الكتلة من الشيفرة من قِبل التابع، وستُنفَّذ كل شيفرة التابع في خيط آخر.
	</li>
	<li>
		في الموضع (4) يمكنك وضع بعض الشيفرة هنا والتي سينفذها العامل قبل بدء العمل.
	</li>
	<li>
		في الموضع (5) إنشاء كائن <code>Pool</code> جديد يقبل معاملين، الأول هو عدد العمال الأعظمي الذي يمكن إنشاؤه في المجمع، والثاني هو اسم صنف العامل.
	</li>
	<li>
		في الموضع (6) تحتاج إلى إرسال أعمالك بدلًا من نسخة الكائنات التي ترث الصنف <code>‎\Threaded</code>.
	</li>
	<li>
		في الموضع (7) نحتاج إلى إيقاف المجمع بشكلٍ صريح وإلا قد يحصل شيء ما غير متوقع.
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصول [Multiprocessing - Multi Threading Extension] من كتاب<a data-ss1619611106="1" data-ss1619611226="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals  book</a>
</p>
]]></description><guid isPermaLink="false">1204</guid><pubDate>Wed, 28 Apr 2021 09:09:00 +0000</pubDate></item><item><title>&#x627;&#x62E;&#x62A;&#x628;&#x627;&#x631; &#x627;&#x644;&#x648;&#x62D;&#x62F;&#x627;&#x62A; &#x648;&#x627;&#x644;&#x623;&#x62F;&#x627;&#x621; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%A3%D8%AF%D8%A7%D8%A1-%D9%81%D9%8A-php-r1203/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_04/unit-testing.png.c7ff4e4f580dd340bde80df98fc03fd9.png" /></p>
<h2 id="-">
	قواعد صنف الاختبار
</h2>

<p>
	بفرض لدينا الصنف <code>LoginForm</code> مع التابع <code>rules()‎</code>، والذي يستخدم في صفحة تسجيل الدخول مثل قالب لإطار العمل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_7" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">LoginForm</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $email</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $rememberMe</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> $password</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// (1)</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> rules</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="com">// البريد الإلكتروني وكلمة السر مطلوبان</span><span class="pln">
            </span><span class="pun">[[</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="str">'required'</span><span class="pun">],</span><span class="pln">
            </span><span class="com">// يجب أن يكون البريد الإلكتروني بصياغة بريد إلكتروني</span><span class="pln">
            </span><span class="pun">[</span><span class="str">'email'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'email'</span><span class="pun">],</span><span class="pln">
            </span><span class="com">// ‫يجب أن يكون الحقل rememberMe قيمة منطقية</span><span class="pln">
            </span><span class="pun">[</span><span class="str">'rememberMe'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'boolean'</span><span class="pun">],</span><span class="pln">
            </span><span class="com">// ‫يجب أن تطابق كلمة السر هذا النمط (أي تحوي أحرف وأرقام فقط)</span><span class="pln">
            </span><span class="pun">[</span><span class="str">'password'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'match'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'pattern'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'/^[a-z0-9]+$/i'</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"> validate</span><span class="pun">(</span><span class="pln">$rule</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $success </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
        list</span><span class="pun">(</span><span class="pln">$var</span><span class="pun">,</span><span class="pln"> $type</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> $rule</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">array</span><span class="pun">)</span><span class="pln"> $var </span><span class="kwd">as</span><span class="pln"> $var</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">switch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$type</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">"required"</span><span class="pun">:</span><span class="pln">
                    $success </span><span class="pun">=</span><span class="pln"> $success </span><span class="pun">&amp;&amp;</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">$var </span><span class="pun">!=</span><span class="pln"> </span><span class="str">""</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">"email"</span><span class="pun">:</span><span class="pln">
                    $success </span><span class="pun">=</span><span class="pln"> $success </span><span class="pun">&amp;&amp;</span><span class="pln"> filter_var</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">$var</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_EMAIL</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">"boolean"</span><span class="pun">:</span><span class="pln">
                    $success </span><span class="pun">=</span><span class="pln"> $success </span><span class="pun">&amp;&amp;</span><span class="pln"> filter_var</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">$var</span><span class="pun">,</span><span class="pln"> FILTER_VALIDATE_BOOLEAN</span><span class="pun">,</span><span class="pln">
FILTER_NULL_ON_FAILURE</span><span class="pun">)</span><span class="pln"> </span><span class="pun">!==</span><span class="pln"> </span><span class="kwd">null</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">"match"</span><span class="pun">:</span><span class="pln">
                    $success </span><span class="pun">=</span><span class="pln"> $success </span><span class="pun">&amp;&amp;</span><span class="pln"> preg_match</span><span class="pun">(</span><span class="pln">$rule</span><span class="pun">[</span><span class="str">"pattern"</span><span class="pun">],</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">$var</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">default</span><span class="pun">:</span><span class="pln">
                    </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \InvalidArgumentException</span><span class="pun">(</span><span class="str">"Invalid filter type passed"</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">return</span><span class="pln"> $success</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في الموضع (1) يعيد التابع <code>rules()‎</code> مصفوفة بمتطلبات كل حقل، يستخدم نموذج تسجيل الدخول البريد الإلكتروني وكلمة المرور لاستيثاق المستخدم.
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_9" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">LoginFormTest</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">TestCase</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $loginForm</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"> setUp</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">loginForm </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">LoginForm</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// (1)</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testRuleValidation</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        $rules </span><span class="pun">=</span><span class="pln"> $this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">rules</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">loginForm</span><span class="pun">-&gt;</span><span class="pln">email </span><span class="pun">=</span><span class="pln"> </span><span class="str">"valid@email.com"</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">password </span><span class="pun">=</span><span class="pln"> </span><span class="str">"password"</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">rememberMe </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">assertTrue</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">validate</span><span class="pun">(</span><span class="pln">$rules</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Should be valid as nothing is invalid"</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// اختبار صحة البريد الإلكتروني</span><span class="pln">
        </span><span class="com">// بما أننا حددنا أن يكون البريد الإلكتروني بصياغة بريد إلكتروني فلا يمكن أن يكون فارغًا­</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">email </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">assertFalse</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">validate</span><span class="pun">(</span><span class="pln">$rules</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Email should not be valid (empty)"</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">loginForm</span><span class="pun">-&gt;</span><span class="pln">email </span><span class="pun">=</span><span class="pln"> </span><span class="str">'invalid.email.com'</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">assertFalse</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">validate</span><span class="pun">(</span><span class="pln">$rules</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Email should not be valid (invalid format)"</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">loginForm</span><span class="pun">-&gt;</span><span class="pln">email </span><span class="pun">=</span><span class="pln"> </span><span class="str">'valid@email.com'</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">loginForm</span><span class="pun">-&gt;</span><span class="pln">password </span><span class="pun">=</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">assertFalse</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">validate</span><span class="pun">(</span><span class="pln">$rules</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Password should not be valid (empty)"</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">loginForm</span><span class="pun">-&gt;</span><span class="pln">password </span><span class="pun">=</span><span class="pln"> </span><span class="str">'ThisIsMyPassword'</span><span class="pun">;</span><span class="pln">

        </span><span class="com">// ‫اختبار صحة الحقل rememberMe</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">rememberMe </span><span class="pun">=</span><span class="pln"> </span><span class="lit">999</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">assertFalse</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">validate</span><span class="pun">(</span><span class="pln">$rules</span><span class="pun">),</span><span class="pln"> </span><span class="str">"RememberMe should not be valid (integer type)"</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// ‫قيمة صحيحة للحقل rememberMe من أجل الاختبار التالي</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">rememberMe </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="pun">}</span></pre>

<p>
	في الموضع (1) يجب أن نستخدم التابع <code>validate()‎</code> للتحقق من صحة قواعدنا، يعود التابع <code>testRuleValidation()‎</code> إلى اختبار الوحدة الخاص بالصنف <code>LoginFormTest</code> ويختبر القواعد المذكورة سابقًا.
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_11" style=""><span class="pun">[</span><span class="str">'password'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'match'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'pattern'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'/^[a-z0-9]+$/i'</span><span class="pun">],</span></pre>

<p>
	إذا نسينا شيئًا واحدًا مهمًا وكتبنا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_13" style=""><span class="pun">[</span><span class="str">'password'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'match'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'pattern'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">'/^[a-z0-9]$/i'</span><span class="pun">],</span></pre>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_15" style=""><span class="com">// التهيئة للتحقق من صحة واختبار البيانات التالية</span><span class="pln">
$this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">email </span><span class="pun">=</span><span class="pln"> </span><span class="str">"valid@email.com"</span><span class="pun">;</span><span class="pln">
$this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">password </span><span class="pun">=</span><span class="pln"> </span><span class="str">"password"</span><span class="pun">;</span><span class="pln">
$this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">rememberMe </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
$this</span><span class="pun">-&gt;</span><span class="pln">assertTrue</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">loginForm</span><span class="pun">-&gt;</span><span class="pln">validate</span><span class="pun">(</span><span class="pln">$rules</span><span class="pun">),</span><span class="pln"> </span><span class="str">"Should be valid as nothing is invalid"</span><span class="pun">);</span></pre>

<p>
	سيمرر هذا الاختبار مثالنا الأول وليس الثاني لأنه لدينا خطأ مطبعي في المثال الثاني (لم نكتب علامة +)، مما يعني أنه سيقبل حرف/رقم واحد فقط.
</p>

<p>
	يمكن تنفيذ اختبار الوحدات في الطرفية باستخدام الأمر <code>phpunit [path_to_file]‎</code>، إذا كان كل شيء صحيحًا، يجب أن نكون قادرين على رؤية الحالة <code>OK</code> لكل الاختبارات وإلا سنرى إما <code>Error</code> لخطأ في الصيغة، أو <code>Fail</code> على الأقل لسطر واحد لم يُمرَّر في ذلك التابع.
</p>

<p>
	يمكننا أيضًا باستخدام معاملات إضافية مثل <code>‎--coverage</code> أن نحصل على عدد الأسطر المُختبرة من الشيفرة في <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%AE%D9%84%D9%81%D9%8A%D8%A9-backend-web-development/" rel="">الواجهة الخلفية backend</a> وأيها نجحَ/فشلَ، يُطبَّق هذا على أي إطار عمل ثبّتَ <a data-ss1621328089="1" href="%E2%80%8Fhttps://phpunit.de/" rel="">PHPUnit</a>.
</p>

<p>
	إليك مثال عن طريقة ظهور اختبار PHPUnit في الطرفية، وهو مثال عام وليس له صلة بمثالنا:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="67106" data-ss1621328089="1" href="https://academy.hsoub.com/uploads/monthly_2021_05/01.png.a4a26b57f9276c22816910c4ed343d4a.png" rel="" data-fileext="png"><img alt="01.png" class="ipsImage ipsImage_thumbnailed" data-fileid="67106" data-unique="yqyv3n1yh" src="https://academy.hsoub.com/uploads/monthly_2021_05/01.thumb.png.842de818ff45907271cacf92e7029f69.png"></a>
</p>

<h2 id="-phpunit">
	مقدمو بيانات PHPUnit
</h2>

<p>
	تحتاج توابع الاختبار عادةً إلى بيانات لتُختَبر بها، ولاختبار بعض التوابع كاملةً تحتاج لتوفير مجموعات بيانات مختلفة لكل حالة اختبار ممكنة، يمكنك القيام بذلك يدويًا باستخدام الحلقات، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_17" 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"> testSomething</span><span class="pun">()</span><span class="pln">
</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">foreach</span><span class="pun">(</span><span class="pln">$data </span><span class="kwd">as</span><span class="pln"> $dataSet</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">assertSomething</span><span class="pun">(</span><span class="pln">$dataSet</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>
	يمكن أن تجد هذه الطريقة مريحة ولكن لها بعض العيوب، أولًا عليك أن تؤدي إجراءات إضافية لاستخراج البيانات إذا كانت دالة الاختبار تقبل عدة معاملات، ثانيًا سيكون من الصعب في حالة الفشل تمييز مجموعة البيانات الخاطئة بدون تنقيح أخطاء ورسائل إضافية، ثالثًا يوفر PHPUnit طريقة تلقائية للتعامل مع مجموعات بيانات الاختبار باستخدام <a data-ss1621328089="1" href="https://phpunit.de/manual/6.5/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers" rel="external nofollow">مقدمي البيانات</a>.
</p>

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

<p>
	لاستخدام مقدم البيانات مع الاختبار نستخدم التوصيف <code>‎@dataProvider</code> مع اسم دالة مقدم البيانات المحددة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_19" style=""><span class="com">/**
* @dataProvider dataProviderForTest
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testEquals</span><span class="pun">(</span><span class="pln">$a</span><span class="pun">,</span><span class="pln"> $b</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">assertEquals</span><span class="pun">(</span><span class="pln">$a</span><span class="pun">,</span><span class="pln"> $b</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"> dataProviderForTest</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="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">],</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">2</span><span class="pun">,</span><span class="lit">2</span><span class="pun">],</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">3</span><span class="pun">,</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="com">//this will fail</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	مصفوفة مصفوفات
</h3>

<p>
	لاحظ أنّ الدالة <code>dataProviderForTest()‎</code> ترجع مصفوفة من مصفوفات، كل مصفوفة متداخلة تحتوي عنصرين سيملآن المعاملات الضرورية للدالة <code>testEquals()‎</code>، إذا لم يكن هناك عناصر كافية سيُرمى خطأ مشابه للخطأ التالي:
</p>

<pre class="ipsCode" id="ips_uid_2553_7"> Missing argument 2 for Test::testEquals()‎ </pre>

<p>
	حيث سيمر PHPUnit تلقائيًا على كل البيانات وينفذ الاختبارات، كما هو ظاهر فيما يأتي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_21" style=""><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> dataProviderForTest</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="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="com">// [0] testEquals($a = 1, $b = 1)</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">2</span><span class="pun">,</span><span class="lit">2</span><span class="pun">],</span><span class="pln"> </span><span class="com">// [1] testEquals($a = 2, $b = 2)</span><span class="pln">
        </span><span class="pun">[</span><span class="lit">3</span><span class="pun">,</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="com">// [2] There was 1 failure: 1) Test::testEquals with data set #2 (3, 4)</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_2185_24" style=""><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> dataProviderForTest</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">'Test 1'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">1</span><span class="pun">],</span><span class="pln"> </span><span class="com">// [0] testEquals($a = 1, $b = 1)</span><span class="pln">
        </span><span class="str">'Test 2'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="lit">2</span><span class="pun">,</span><span class="lit">2</span><span class="pun">],</span><span class="pln"> </span><span class="com">// [1] testEquals($a = 2, $b = 2)</span><span class="pln">
        </span><span class="str">'Test 3'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</span><span class="pun">,</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="com">// [2] There was 1 failure:</span><span class="pln">
        </span><span class="com">// 1) Test::testEquals with data set "Test 3" (3, 4)</span><span class="pln">
    </span><span class="pun">];</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	المكررات
</h3>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_26" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyIterator</span><span class="pln"> </span><span class="kwd">implements</span><span class="pln"> </span><span class="typ">Iterator</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $array </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"> __construct</span><span class="pun">(</span><span class="pln">$array</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">array </span><span class="pun">=</span><span class="pln"> $array</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">function</span><span class="pln"> rewind</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"> reset</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">array</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">function</span><span class="pln"> current</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"> current</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">array</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">function</span><span class="pln"> key</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"> key</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">array</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">function</span><span class="pln"> </span><span class="kwd">next</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="kwd">next</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">array</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="kwd">function</span><span class="pln"> valid</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"> key</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">array</span><span class="pun">)</span><span class="pln"> </span><span class="pun">!==</span><span class="pln"> </span><span class="kwd">null</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">Test</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">TestCase</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * @dataProvider dataProviderForTest
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testEquals</span><span class="pun">(</span><span class="pln">$a</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        $toCompare </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">assertEquals</span><span class="pun">(</span><span class="pln">$a</span><span class="pun">,</span><span class="pln"> $toCompare</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"> dataProviderForTest</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="kwd">new</span><span class="pln"> </span><span class="typ">MyIterator</span><span class="pun">([</span><span class="pln">
            </span><span class="str">'Test 1'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln">
            </span><span class="str">'Test 2'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="kwd">false</span><span class="pun">],</span><span class="pln">
            </span><span class="str">'Test 3'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="kwd">null</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>‎$parameter</code> حتى من أجل معامل واحد.
</p>

<p>
	إذا غيّرنا التابع <code>current()‎</code> الذي يعيد البيانات في كل تكرار، بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_28" style=""><span class="kwd">function</span><span class="pln"> current</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"> current</span><span class="pun">(</span><span class="pln">$this</span><span class="pun">-&gt;</span><span class="pln">array</span><span class="pun">)[</span><span class="lit">0</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_2185_30" style=""><span class="kwd">return</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">MyIterator</span><span class="pun">([</span><span class="pln">
    </span><span class="str">'Test 1'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'Test 2'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln">
    </span><span class="str">'Test 3'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">null</span><span class="pln">
</span><span class="pun">]);</span></pre>

<p>
	سنحصل على خطأ:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_32" style=""><span class="typ">There</span><span class="pln"> was </span><span class="lit">1</span><span class="pln"> warning</span><span class="pun">:</span><span class="pln">
</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Warning</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> data provider specified </span><span class="kwd">for</span><span class="pln"> </span><span class="typ">Test</span><span class="pun">::</span><span class="pln">testEquals </span><span class="kwd">is</span><span class="pln"> invalid</span><span class="pun">.</span></pre>

<p>
	من غير المفيد طبعًا استخدام الكائن <code>Iterator</code> لتكرار محتويات مصفوفة بسيطة، يجب أن ينفّذ بعض المنطق المحدد لحالتك.
</p>

<h3>
	المولدات generators
</h3>

<p>
	لم يُشار إليها بشكلٍ صريح في التوثيق الرسمي لكن يمكنك استخدامها كمقدم بيانات أيضًا­، لاحظ أنّ الصنف <code>Generator</code> ينفّذ الواجهة <code>Iterator</code> فعليًا، إليك مثال عن استخدام <code>DirectoryIterator</code> مع مولِّد:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_34" style=""><span class="com">/**
* @param string $file
*
* @dataProvider fileDataProvider
*/</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> testSomethingWithFiles</span><span class="pun">(</span><span class="pln">$fileName</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ‫‎$fileName متاح هنا</span><span class="pln">
    </span><span class="com">// اختبر هنا</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"> fileDataProvider</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    $directory </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DirectoryIterator</span><span class="pun">(</span><span class="str">'path-to-the-directory'</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">$directory </span><span class="kwd">as</span><span class="pln"> $file</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">$file</span><span class="pun">-&gt;</span><span class="pln">isFile</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> $file</span><span class="pun">-&gt;</span><span class="pln">isReadable</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">yield</span><span class="pln"> </span><span class="pun">[</span><span class="pln">$file</span><span class="pun">-&gt;</span><span class="pln">getPathname</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>

<h2 id="-">
	استثناءات الاختبار
</h2>

<p>
	لنفرض أنك تريد اختبار تابع يرمي استثناءً.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_36" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Car</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/**
    * @throws \Exception
    */</span><span class="pln">
    </span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> drive</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">throw</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Exception</span><span class="pun">(</span><span class="str">'Useful message'</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="pun">}</span></pre>

<p>
	يمكنك القيام بذلك عن طريق تضمين استدعاء التابع في كتلة try/catch وإجراء توكيدات على خاصيات كائن الاستثناء، أو يمكنك استخدام توابع توكيد الاستثناء للمزيد من الملاءمة، يمكنك بدءًا من الإصدار <a data-ss1621328089="1" href="%E2%80%8Fhttps://github.com/sebastianbergmann/phpunit" rel="">PHPUnit 5.2</a> استخدام توابع <code>expectX()‎</code> المتاحة لتأكيد نوع ورسالة وشيفرة الاستثناء.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_38" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">DriveTest</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">PHPUnit_Framework_TestCase</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"> testDrive</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// التحضير</span><span class="pln">
        $car </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Car</span><span class="pun">();</span><span class="pln">
        $expectedClass </span><span class="pun">=</span><span class="pln"> \Exception</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">;</span><span class="pln">
        $expectedMessage </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Useful message'</span><span class="pun">;</span><span class="pln">
        $expectedCode </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</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">expectException</span><span class="pun">(</span><span class="pln">$expectedClass</span><span class="pun">);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">expectMessage</span><span class="pun">(</span><span class="pln">$expectedMessage</span><span class="pun">);</span><span class="pln">
        $this</span><span class="pun">-&gt;</span><span class="pln">expectCode</span><span class="pun">(</span><span class="pln">$expectedCode</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// التنفيذ</span><span class="pln">
        $car</span><span class="pun">-&gt;</span><span class="pln">drive</span><span class="pun">();</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك أن تستخدم التابع <code>setExpectedException</code> بدلًا من <code>expectX()‎</code> إذا كنت تستخدم إصدارًا قديمًا من PHPUnit لكن تذكر أنه تابع مُهمل وسيُحذف في الإصدار 6.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_40" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">DriveTest</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">PHPUnit_Framework_TestCase</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"> testDrive</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// التحضير</span><span class="pln">
        $car </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \Car</span><span class="pun">();</span><span class="pln">
        $expectedClass </span><span class="pun">=</span><span class="pln"> \Exception</span><span class="pun">::</span><span class="kwd">class</span><span class="pun">;</span><span class="pln">
        $expectedMessage </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Useful message'</span><span class="pun">;</span><span class="pln">
        $expectedCode </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</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">setExpectedException</span><span class="pun">(</span><span class="pln">$expectedClass</span><span class="pun">,</span><span class="pln"> $expectedMessage</span><span class="pun">,</span><span class="pln">             $expectedCode</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// التنفيذ</span><span class="pln">
        $car</span><span class="pun">-&gt;</span><span class="pln">drive</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>

<h3 id="-xdebug">
	التحليل مع Xdebug
</h3>

<p>
	تُعَدّ إضافة Xdebug متاحةً للمساعدة في <a data-ss1621328089="1" href="%E2%80%8Fhttps://xdebug.org/docs/profiler" rel="">تحليل تطبيقات PHP</a>، بالإضافة إلى تنقيح الأخطاء وقت التنفيذ، عند تنفيذ المحلل يُكتب الخرج في ملف بصياغة ثنائية تدعى cachegrind. توجد تطبيقات متوفرة على كل منصة لتحليل هذه الملفات.
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_42" style=""><span class="com">// اضبطه إلى 1 لتشغيله عند كل طلب</span><span class="pln">
xdebug</span><span class="pun">.</span><span class="pln">profiler_enable </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

</span><span class="com">// ‫لنستخدم معامل GET/POST لتشغيل المحلِّل</span><span class="pln">
xdebug</span><span class="pun">.</span><span class="pln">profiler_enable_trigger </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

</span><span class="com">// ‫قيمة GET/POST التي سنمررها، فارغة من أجل أي قيمة</span><span class="pln">
xdebug</span><span class="pun">.</span><span class="pln">profiler_enable_trigger_value </span><span class="pun">=</span><span class="pln"> </span><span class="str">""</span><span class="pln">

</span><span class="com">// ‫عرض ملفات الذاكرة cachegrind في المسار ‎/tmp حتى ينظفها النظام لاحقًا</span><span class="pln">
xdebug</span><span class="pun">.</span><span class="pln">profiler_output_dir </span><span class="pun">=</span><span class="pln"> </span><span class="str">"/tmp"</span><span class="pln">
xdebug</span><span class="pun">.</span><span class="pln">profiler_output_name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"cachegrind.out.%p"</span></pre>

<p>
	ثم استخدم عميل ويب يرسل طلبًا إلى رابط التطبيق الذي ترغب بتحليله، مثل:
</p>

<pre class="ipsCode" id="ips_uid_2185_46">http://example.com/article/1?XDEBUG_PROFILE=1</pre>

<p>
	أثناء معالجة الصفحة للطلب سيكتب في ملف له اسم مشابه للتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_49" style=""><span class="str">/tmp/</span><span class="pln">cachegrind</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">.</span><span class="lit">12345</span></pre>

<p>
	لاحظ أنّه سيكتب ملف واحد لكل عملية/طلب PHP يُنفَّذ، لذا إذا أردت تحليل نموذج مُرسل بالطريقة <code>POST</code> سيُكتب تحليل واحد من أجل الطريقة <code>GET</code> لعرض نموذج HTML وستحتاج إلى تمرير المعامل <code>XDEBUG_PROFILE</code> ، من أجل الإقدام على طلب <code>POST</code> اللاحق لتحليل الطلب الثاني الذي يعالج النموذج، لذا فقد يكون من الأسهل تنفيذ مكتبة <code>curl</code> لإرسال نموذج بالطريقة <code>POST</code> مباشرةً عند التحليل.
</p>

<p>
	بمجرد أن يُكتب التحليل، فيمكنك قراءة الذاكرة المخبئية cache بتطبيق مثل KCachegrind:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="67107" data-ss1621328089="1" href="https://academy.hsoub.com/uploads/monthly_2021_05/60a38125c923a_02(1).png.2726c1ba9ae5676084481e4f90a35035.png" rel="" data-fileext="png"><img alt="02 (1).png" class="ipsImage ipsImage_thumbnailed" data-fileid="67107" data-unique="gv1msthb5" src="https://academy.hsoub.com/uploads/monthly_2021_05/60a38128be712_02(1).thumb.png.db776df26f7b01d173af1a50bffbddbb.png"></a>
</p>

<p>
	سيعرض التطبيق معلومات التحليل متضمنةً:
</p>

<ul>
	<li>
		الدوال المنفَّذة
	</li>
	<li>
		وقت استدعاء الدالة بمفردها واستدعاءات الدالة اللاحقة.
	</li>
	<li>
		عدد مرات استدعاء كل دالة.
	</li>
	<li>
		رسوم بيانية للاستدعاء
	</li>
	<li>
		روابط للشيفرة المصدرية
	</li>
</ul>

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

<ul>
	<li>
		يجب ألا ترى استدعاءات متكررة لنفس الدالة، بالنسبة للدوال التي تعالج البيانات وتستعلم عنها قد يكون هناك فرص للتخزين المؤقت.
	</li>
	<li>
		وجود دوال بطيئة التنفيذ، أين يستهلك التطبيق معظم وقته؟ أفضل عائد لضبط الأداء هو التركيز على أجزاء التطبيق التي تستهلك معظم وقته.
	</li>
</ul>

<p>
	<strong>ملاحظة:</strong> إنّ إضافة Xdebug وخاصةً ميزاتها التحليلية مكثّفة للموارد وتبطئ تنفيذ PHP، لذا يُنصح بعدم تنفيذها في بيئة خادم الإنتاج.
</p>

<h3 id="-">
	استخدام الذاكرة
</h3>

<p>
	يُضبط حد ذاكرة زمن تنفيذ PHP باستخدام موجّه INI الـ  <code>‏memory_limit</code>، حيث يمنع هذا الضبط أي تنفيذ PHP مفرد من استخدام الكثير من الذاكرة مما يؤدي إلى استنزافها من أجل السكربتات الأخرى وبرنامج النظام. حد الذاكرة الافتراضي هو 128MB ويمكن أن يتغير في ملف <code>php.ini</code> أو في وقت التنفيذ. يمكن أن يُضبط ليكون غير محدود لكن يعدّ هذا عمومًا ممارسةً سيئة.
</p>

<p>
	يمكن أن يُحدَّد الاستخدام الدقيق للذاكرة أثناء وقت التنفيذ ᠎᠎عن طريق استدعاء الدالة <code>memory_get_usage()‎</code> التي تعيد عدد بايتات الذاكرة المحجوزة للسكربت الحالي المُنفَّذ. بدءًا من الإصدار PHP 5.2 يوجد لهذه الدالة معامل منطقي اختياري للحصول على ذاكرة النظام المحجوزة الكلية على عكس الذاكرة الفعالة التي تستخدمها PHP.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_51" style=""><span class="pun">&lt;?</span><span class="pln">php
echo memory_get_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// ‫الخرج 350688 (أو شيء ما مشابه وهذا يعتمد على النظام وإصدار PHP)</span><span class="pln">

</span><span class="com">// ‫لنستهلك جزءًا من الذاكرة RAM</span><span class="pln">
$array </span><span class="pun">=</span><span class="pln"> array_fill</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">,</span><span class="pln"> </span><span class="str">'abc'</span><span class="pun">);</span><span class="pln">

echo memory_get_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 387704</span><span class="pln">

</span><span class="com">// حذف المصفوفة من الذاكرة</span><span class="pln">
unset</span><span class="pun">(</span><span class="pln">$array</span><span class="pun">);</span><span class="pln">

echo memory_get_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 350784</span></pre>

<p>
	تعطيك الآن الدالة <code>memory_get_usage</code> استخدام الذاكرة في الوقت الذي نُفِّذت فيه، قد تخصص وتلغي تخصيص الكثير من الذاكرة بين استدعاءات الدالة المتلاحقة، يمكنك استخدام الدالة <code>memory_get_peak_usage()‎</code> للحصول على الحجم الأعظمي من الذاكرة المستخدمة حتى نقطة معينة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_53" style=""><span class="pun">&lt;?</span><span class="pln">php
echo memory_get_peak_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 385688</span><span class="pln">
$array </span><span class="pun">=</span><span class="pln"> array_fill</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1000</span><span class="pun">,</span><span class="pln"> </span><span class="str">'abc'</span><span class="pun">);</span><span class="pln">
echo memory_get_peak_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 422736</span><span class="pln">
unset</span><span class="pun">(</span><span class="pln">$array</span><span class="pun">);</span><span class="pln">
echo memory_get_peak_usage</span><span class="pun">()</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="com">// 422776</span></pre>

<p>
	لاحظ أنّ القيمة إما سترتفع أو تبقى ثابتة.
</p>

<h3 id="-xhprof">
	التحليل باستخدام XHProf
</h3>

<p>
	<a data-ss1621328089="1" href="%E2%80%8Fhttps://github.com/phacility/xhprof" rel="">XHProf</a> محلل PHP مكتوب من قِبل شركة فيسبوك لتوفير بديل أخف للإضافة XDebug، يمكن تمكين/تعطيل التحليل بعد تثبيت الوحدة xhprof من شيفرة PHP:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2185_55" style=""><span class="pln">xhprof_enable</span><span class="pun">();</span><span class="pln">
doSlowOperation</span><span class="pun">();</span><span class="pln">
$profile_data </span><span class="pun">=</span><span class="pln"> xhprof_disable</span><span class="pun">();</span></pre>

<p>
	ستحتوي المصفوفة المُرجعة على بيانات حول عدد الاستدعاءات ووقت المعالج واستخدام الذاكرة لكل دالة تم الوصول إليها من داخل <code>doSlowOperation()‎</code>.
</p>

<p>
	يمكن استخدام <code>‎</code>الدالة الموالية على أساس خيار أخف لتسجيل معلومات التحليل لجزء من الطلبات فقط (وبصياغة مختلفة).⁩
</p>

<pre class="ipsCode" id="ips_uid_2553_9">xhprof_sample_enable()/xhprof_sample_disable()</pre>

<p>
	ولهذا يستخدم المحلل بعض الدوال المساعدة (معظمها غير موثَّق) لعرض البيانات (<a data-ss1621328089="1" href="https://github.com/phacility/xhprof/blob/master/examples/sample.php" rel="external nofollow">اطلع على هذا المثال</a>)، أو يمكنك أاستعمال أدوات أخرى لتصورها (يمكنك الاطلاع على <a data-ss1621328089="1" href="https://github.com/phacility/xhprof/blob/master/examples/sample.php" rel="external nofollow">هذا المثال</a> من مدونة platform.sh).
</p>

<p>
	ترجمة -وبتصرف- للفصول Unit Testing - Performance من كتاب <span style="display: none;"> </span><a data-ss1621328089="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a><span style="display: none;"> </span>
</p>
]]></description><guid isPermaLink="false">1203</guid><pubDate>Mon, 26 Apr 2021 09:03:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639; &#x627;&#x644;&#x623;&#x62E;&#x637;&#x627;&#x621; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-php-r1202/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_04/607aa7942680c_Common-ErrorsN.png.19dcbc2bccab3ccafc38ecfde2dc6436.png" /></p>
<h2 id="-">
	أخطاء شائعة
</h2>

<h3 id="-fetch_assoc-">
	استدعاء fetch_assoc على قيمة منطقية
</h3>

<p>
	إذا حصلت على خطأ مشابه للتالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_8" style=""><span class="typ">Fatal</span><span class="pln"> error</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Call</span><span class="pln"> to a member </span><span class="kwd">function</span><span class="pln"> fetch_assoc</span><span class="pun">()</span><span class="pln"> on </span><span class="kwd">boolean</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> C</span><span class="pun">:</span><span class="pln">\xampp\htdocs\stack\index</span><span class="pun">.</span><span class="pln">php on line </span><span class="lit">7</span></pre>

<p>
	تتضمن الاختلافات الأخرى شيئًا ما مثل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2177_7" style=""><span class="pln">mysql_fetch_assoc</span><span class="pun">()</span><span class="pln"> expects parameter </span><span class="lit">1</span><span class="pln"> to be resource</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">boolean</span><span class="pln"> given</span><span class="pun">...</span></pre>

<p>
	تعني هذه الأخطاء أنّه يوجد شيء ما خاطئ إما مع الاستعلام (وهذا خطأ PHP/MySQL) أو مع المرجعية. أُنتج الخطأ السابق بسبب الشيفرة التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_10" style=""><span class="pln">$mysqli </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> mysqli</span><span class="pun">(</span><span class="str">"localhost"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"root"</span><span class="pun">,</span><span class="pln"> </span><span class="str">""</span><span class="pun">);</span><span class="pln">

</span><span class="com">// لاحظ الأخطاء هنا</span><span class="pln">
$query </span><span class="pun">=</span><span class="pln"> </span><span class="str">"SELCT * FROM db"</span><span class="pun">;</span><span class="pln"> 
$result </span><span class="pun">=</span><span class="pln"> $mysqli</span><span class="pun">-&gt;</span><span class="pln">query</span><span class="pun">(</span><span class="pln">$query</span><span class="pun">);</span><span class="pln">

$row </span><span class="pun">=</span><span class="pln"> $result</span><span class="pun">-&gt;</span><span class="pln">fetch_assoc</span><span class="pun">();</span></pre>

<p>
	لإصلاح هذا الخطأ يُنصَح بجعل mysql يرمي استثناءات بدلًا من ذلك:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_12" style=""><span class="com">// أضف هذه الشيفرة في بداية السكربت</span><span class="pln">
mysqli_report</span><span class="pun">(</span><span class="pln">MYSQLI_REPORT_ERROR </span><span class="pun">|</span><span class="pln"> MYSQLI_REPORT_STRICT</span><span class="pun">);</span></pre>

<p>
	ستؤدي هذه الشيفرة إلى رمي استثناء مع رسالة تساعدك كثيرًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2177_11" style=""><span class="typ">You</span><span class="pln"> have an error </span><span class="kwd">in</span><span class="pln"> your SQL syntax</span><span class="pun">;</span><span class="pln"> check the manual that corresponds to your </span><span class="typ">MariaDB</span><span class="pln"> server version </span><span class="kwd">for</span><span class="pln"> the right syntax to </span><span class="kwd">use</span><span class="pln"> near </span><span class="str">'SELCT * FROM db'</span><span class="pln"> at line </span><span class="lit">1</span></pre>

<p>
	مثال آخر يمكن أن ينتج عنه خطأ مشابه، هو عندما تعطي معلومات خاطئة لدالة <code>mysql_fetch_assoc</code> أو لدالة مشابهة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_15" style=""><span class="pln">$john </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
mysqli_fetch_assoc</span><span class="pun">(</span><span class="pln">$john</span><span class="pun">,</span><span class="pln"> $mysqli</span><span class="pun">);</span></pre>

<h3 id="unexpected-end">
	Unexpected $end
</h3>

<p>
	إذا حصلت على خطأ مشابه للخطأ التالي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2177_14" style=""><span class="typ">Parse</span><span class="pln"> error</span><span class="pun">:</span><span class="pln"> syntax error</span><span class="pun">,</span><span class="pln"> unexpected </span><span class="kwd">end</span><span class="pln"> of file </span><span class="kwd">in</span><span class="pln"> C</span><span class="pun">:</span><span class="pln">\xampp\htdocs\stack\index</span><span class="pun">.</span><span class="pln">php on line </span><span class="lit">4</span></pre>

<p>
	أو قد يكون بالشكل <code>unexpected $end</code> وهذا يعتمد على نسخة <a href="https://wiki.hsoub.com/PHP" rel="external">PHP</a>، ستحتاج عندها إلى التأكد من جميع فواصل الاقتباس وكل الأقواس الهلالية والمعقوصة والمعقوفة….
</p>

<p>
	تنتج الشيفرة التالية الخطأ السابق:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_17" style=""><span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"asdf"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

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

<h2 id="-">
	تصريف الأخطاء والتحذيرات
</h2>

<h3 id="parse-error-syntax-error-unexpected-t_paamayim_nekudotayim">
	أخطاء التحميل غير المتوقعة وأخطاء بناء الجملة
</h3>

<p>
	تعني العبارة "Paamayim Nekudotayim" نقطتان مزدوجتان باللغة العبرية، لذا يشير هذا الخطأ إلى الاستخدام غير المناسب للعامل <code>(::)</code>، ويحدث عادةً بسبب محاولة استدعاء تابع ساكن في حين أنّه في الواقع غير ساكن.
</p>

<p>
	الحل الممكن:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_21" style=""><span class="pln">$classname</span><span class="pun">::</span><span class="pln">doMethod</span><span class="pun">();</span></pre>

<p>
	إذا سببت الشيفرة السابقة هذا الخطأ فغالبًا أنت تحتاج إلى تغيير طريقة استدعاء التابع الآتي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_23" style=""><span class="pln">$classname</span><span class="pun">-&gt;</span><span class="pln">doMethod</span><span class="pun">();</span></pre>

<p>
	حيث يفترض المثال الأخير أنّ <code>‎$classname</code> هو كائن من صنف والتابع <code>doMethod()‎</code> ليس تابعًا ساكنًا من هذا الصنف.
</p>

<h3 id="notice-undefined-index">
	إشعار الفهرس غير المعرف Undefined index
</h3>

<ul style="margin-right: 40px;">
	<li>
		<strong>الظهور:</strong> محاولة الوصول إلى مصفوفة عن طريق مفتاح غير موجود في المصفوفة.
	</li>
	<li>
		<strong>الحل الممكن:</strong> التحقق من التوافرية قبل محاولة الوصول وذلك باستخدام:
		<ul>
			<li>
				الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/isset" rel="">isset()‎</a>.
			</li>
			<li>
				الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/array_key_exists%E2%80%8F" rel="">array_key_exists()‎</a>.
			</li>
		</ul>
	</li>
</ul>

<h3 id="warning-cannot-modify-header-information-headers-already-sent">
	تحذير عدم إمكانية التعديل على معلومات الترويسة أو الترويسات المرسلة سلفا
</h3>

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

<ul>
	<li>
		تعليمتي <code>Print</code> و<code>echo</code>: سينهي خرج هاتين التعليمتين فرصة إرسال ترويسات HTTP، يجب إعادة هيكلية تدفق التطبيق لتجنب ذلك.
	</li>
	<li>
		مناطق HTML خام: تعد شيفرة HTML غير المحللة في ملف <code>‎.php</code> خرج مباشر أيضًا، يجب ملاحظة شروط السكربت التي ستشغّل استدعاء <code>header()‎</code> قبل أي كتل خام.
	</li>
</ul>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2213_19" style=""><span class="dec">&lt;!DOCTYPE html&gt;</span><span class="pln">
</span><span class="pun">&lt;?</span><span class="pln">php
    </span><span class="com">// فات أوان إرسال الترويسات</span></pre>

<ul>
	<li>
		المسافة البيضاء قبل <code>‎&lt;?php</code> من أجل التحذير <code>script.php line 1</code>، إذا أشار التحذير إلى الخرج في السطر 1 فغالبًا السبب هو مسافة بيضاء أو نص أو شيفرة HTML قبل وسم الفتح <code>‎&lt;?php</code>.
	</li>
</ul>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_25" style=""><span class="pun">&lt;?</span><span class="pln">php
</span><span class="com"># ‫يوجد مسافة مفردة/سطر جديد قبل ‎&lt;?‎</span></pre>

<h2 id="-error-reporting-">
	معالجة الاستثناءات والإبلاغ عن الأخطاء error reporting
</h2>

<h3 id="-">
	ضبط الإبلاغ عن الأخطاء وأماكن عرضها
</h3>

<p>
	يمكن ضبط الإبلاغ عن الأخطاء بشكلٍ ديناميكي إذا لم يُضبط سابقًا في ملف <code>php.ini</code> وذلك للسماح بعرض معظم الأخطاء.
</p>

<ul>
	<li>
		<strong>الصيغة</strong>
	</li>
</ul>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_27" style=""><span class="kwd">int</span><span class="pln"> error_reporting </span><span class="pun">([</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> $level </span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span></pre>

<ul>
	<li>
		<strong>أمثلة</strong>
	</li>
</ul>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2177_23" style=""><span class="com">// ‫يجب أن تُستخدم دائمًا في الإصدارات السابقة للإصدار 5.4</span><span class="pln">
error_reporting</span><span class="pun">(</span><span class="pln">E_ALL</span><span class="pun">);</span><span class="pln">

</span><span class="com">// (1)</span><span class="pln">
error_reporting</span><span class="pun">(-</span><span class="lit">1</span><span class="pun">);</span><span class="pln">
</span><span class="pun">?</span><span class="com">// بدون ملاحظات</span><span class="pln">
error_reporting</span><span class="pun">(</span><span class="pln">E_ALL </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">~</span><span class="pln">E_NOTICE</span><span class="pun">);</span><span class="pln">

</span><span class="com">// التحذيرات والملاحظات فقط</span><span class="pln">
</span><span class="com">// كمثال فقط، لا يُنصح بالحصول على إبلاغ عن هؤلاء فقط</span><span class="pln">
error_reporting</span><span class="pun">(</span><span class="pln">E_WARNING </span><span class="pun">|</span><span class="pln"> E_NOTICE</span><span class="pun">);</span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_38" style=""> </pre>

<p>
	في الموضع (1) يُظهر الوسيط <code>‎-1</code> كل خطأ محتمل حتى عندما تُضاف ثوابت ومستويات جديدة في إصدارات <a href="https://academy.hsoub.com/php/" rel="">لغة PHP</a> المستقبلية، يقوم الوسيط <code>E_ALL</code> بنفس هذا العمل حتى الإصدار 5.4.
</p>

<p>
	ستُسجَّل الأخطاء افتراضيًا من قِبل PHP في ملف <code>error.log</code> في نفس مستوى الملف الذي يُنفَّذ، ويمكنك أن تعرضهم على الشاشة في بيئة التطوير:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_40" style=""><span class="pln">ini_set</span><span class="pun">(</span><span class="str">'display_errors'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span></pre>

<p>
	ويجب أن تصبح الشيفرة في بيئة الإنتاج:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_42" style=""><span class="pln">ini_set</span><span class="pun">(</span><span class="str">'display_errors'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">);</span></pre>

<p>
	وستظهر رسالة المشكلة بشكلٍ واضح أثناء استخدام معالِج الاستثناء أو الخطأ.
</p>

<h3 id="-">
	تسجيل الأخطاء الفادحة
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_44" style=""><span class="kwd">function</span><span class="pln"> fatalErrorHandler</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// لنحصل على الخطأ الفادح الأخير</span><span class="pln">
    $error </span><span class="pun">=</span><span class="pln"> error_get_last</span><span class="pun">();</span><span class="pln">
    </span><span class="com">// (1)</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">null</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> $error </span><span class="pun">||</span><span class="pln"> E_ERROR </span><span class="pun">!=</span><span class="pln"> $error</span><span class="pun">[</span><span class="str">'type'</span><span class="pun">])</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">return</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="com">// لنفرض أنّ السجلات موجودة في مجلد داخل مجلد التطبيق</span><span class="pln">
    $logFile </span><span class="pun">=</span><span class="pln"> fopen</span><span class="pun">(</span><span class="str">"./app/logs/error.log"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"a+"</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// الحصول على معلومات مفيدة عن الخطأ</span><span class="pln">
    $type </span><span class="pun">=</span><span class="pln"> $error</span><span class="pun">[</span><span class="str">"type"</span><span class="pun">];</span><span class="pln">
    $file </span><span class="pun">=</span><span class="pln"> $error</span><span class="pun">[</span><span class="str">"file"</span><span class="pun">];</span><span class="pln">
    $line </span><span class="pun">=</span><span class="pln"> $error</span><span class="pun">[</span><span class="str">"line"</span><span class="pun">];</span><span class="pln">
    $message </span><span class="pun">=</span><span class="pln"> $error</span><span class="pun">[</span><span class="str">"message"</span><span class="pun">]</span><span class="pln">

    fprintf</span><span class="pun">(</span><span class="pln">
        $logFile</span><span class="pun">,</span><span class="pln">
        </span><span class="str">"[%s] %s: %s in %s:%d\n"</span><span class="pun">,</span><span class="pln">
        date</span><span class="pun">(</span><span class="str">"Y-m-d H:i:s"</span><span class="pun">),</span><span class="pln">
        $type</span><span class="pun">,</span><span class="pln">
        $message</span><span class="pun">,</span><span class="pln">
        $file</span><span class="pun">,</span><span class="pln">
        $line</span><span class="pun">);</span><span class="pln">

    fclose</span><span class="pun">(</span><span class="pln">$logFile</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
register_shutdown_function</span><span class="pun">(</span><span class="str">'fatalErrorHandler'</span><span class="pun">);</span></pre>

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

<ul>
</ul>

<h2 id="-">
	تنقيح الأخطاء
</h2>

<h3 id="-">
	عرض المتغيرات
</h3>

<p>
	تسمح الدالة <a href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/var_dump" rel="">var_dump</a> بعرض محتويات المتغير (النوع والمتغير) لتنقيح الأخطاء.
</p>

<p>
	<strong>مثال</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_46" style=""><span class="pln">$array </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3.7</span><span class="pun">,</span><span class="pln"> </span><span class="str">"string"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">"hello"</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="str">"world"</span><span class="pun">],</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">()];</span><span class="pln">
var_dump</span><span class="pun">(</span><span class="pln">$array</span><span class="pun">);</span></pre>

<p>
	<strong>الخرج</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_48" style=""><span class="pln">array</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="pun">[</span><span class="lit">0</span><span class="pun">]=&gt;</span><span class="pln">
    </span><span class="kwd">float</span><span class="pun">(</span><span class="lit">3.7</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">1</span><span class="pun">]=&gt;</span><span class="pln">
    </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">6</span><span class="pun">)</span><span class="pln"> </span><span class="str">"string"</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">2</span><span class="pun">]=&gt;</span><span class="pln">
    </span><span class="kwd">int</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">3</span><span class="pun">]=&gt;</span><span class="pln">
    array</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="str">"hello"</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="str">"world"</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">4</span><span class="pun">]=&gt;</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pun">(</span><span class="kwd">false</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">[</span><span class="lit">5</span><span class="pun">]=&gt;</span><span class="pln">
    </span><span class="kwd">object</span><span class="pun">(</span><span class="typ">DateTime</span><span class="pun">)#</span><span class="lit">1</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">[</span><span class="str">"date"</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">26</span><span class="pun">)</span><span class="pln"> </span><span class="str">"2016-07-24 13:51:07.000000"</span><span class="pln">
        </span><span class="pun">[</span><span class="str">"timezone_type"</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">int</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">[</span><span class="str">"timezone"</span><span class="pun">]=&gt;</span><span class="pln">
        </span><span class="kwd">string</span><span class="pun">(</span><span class="lit">13</span><span class="pun">)</span><span class="pln"> </span><span class="str">"Europe/Berlin"</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3 id="-">
	عرض الأخطاء
</h3>

<p>
	يجب أن تمكّن الإعداد <a href="%E2%80%8Fhttps://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors" rel="">display_errors</a> إذا أردت عرض الأخطاء التي تحدث وقت التنفيذ runtime errors على الصفحة وذلك إما في ملف <code>php.ini</code> أو باستخدام الدالة <a href="%E2%80%8Fhttps://www.php.net/manual/en/function.ini-set.php" rel="">ini_set</a>.
</p>

<p>
	يمكنك اختيار الأخطاء التي تريد عرضها باستخدام دالة <code>error_reporting</code>، أو في ملف ini والتي تقبل <a href="%E2%80%8Fhttps://www.php.net/manual/en/errorfunc.constants.php" rel="">الثوابت E_*‎</a> مجموعةً باستخدام العوامل الثنائية، ويمكن عرض الأخطاء على شكل نص أو بصيغة HTML وذلك حسب الإعداد <a href="%E2%80%8Fhttps://www.php.net/manual/en/errorfunc.configuration.php#ini.html-errors" rel="">html_errors</a>.
</p>

<ul>
	<li>
		<strong>مثال</strong>
	</li>
</ul>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2213_50" style=""><span class="pln">ini_set("display_errors", true);

// عرض الأخطاء كنص بسيط
ini_set("html_errors", false);

// ‫عرض كل شيء باستثناء E_USER_NOTICE
error_reporting(E_ALL &amp; ~E_USER_NOTICE);

// E_USER_NOTICE
trigger_error("Pointless error");

// E_NOTICE
echo $nonexistentVariable;

// E_ERROR
nonexistentFunction();</span></pre>

<p>
	خرج نصي بسيط: (تختلف صيغة HTML بين التنفيذات)
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2213_52" style=""><span class="pln">Notice: Undefined variable: nonexistentVariable in /path/to/file.php on line 7
Fatal error: Uncaught Error: Call to undefined function nonexistentFunction() in /path/to/file.php:8
Stack trace:
#0 {main}
thrown in /path/to/file.php on line 8</span></pre>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix" data-gramm="false">
		<p>
			<strong>ملاحظة</strong>: إذا كان الإبلاغ عن الخطأ معطلًا في ملف <code>php.ini</code> ومكّنته وقت التنفيذ، فإنّ بعض الأخطاء (مثل الأخطاء التحليلية) لن تُعرض لأنها حدثت قبل تطبيق إعداد وقت التنفيذ.
		</p>
	</div>
</blockquote>

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

<h3 id="phpinfo-">
	phpinfo()‎
</h3>

<div>
	<blockquote class="ipsQuote" data-ipsquote="">
		<div class="ipsQuote_citation">
			اقتباس
		</div>

		<div class="ipsQuote_contents ipsClearfix" data-gramm="false">
			<p>
				 
			</p>

			<div>
				<strong>تحذير</strong>
			</div>

			<div>
				من الضرورري أن تستخدم <code>phpinfo</code> في بيئة التطوير فقط، لا تطلق شيفرة تحوي هذه الدالة في بيئة الإنتاج أبدًا.
			</div>

			<div>
				<strong>مقدمة</strong> يمكن أن تكون دالة <code>phpinfo</code> البسيطة المضمنة في PHP أداةً مفيدة لفهم بيئة PHP (نظام التشغيل، الإعدادات، الإصدارات، المسارات، الوحدات) التي تعمل فيها خاصةً عند متابعة خطأ.
			</div>

			<p>
				 
			</p>
		</div>
	</blockquote>

	<p>
		 
	</p>
</div>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_54" style=""><span class="pln">phpinfo</span><span class="pun">();</span></pre>

<p>
	لهذه الدالة معامل واحد <code>‎$what</code> يسمح بتخصيص الخرج، قيمته الافتراضية <code>INFO_ALL</code> وتسبب عرض كل المعلومات وتُستخدم عادةً أثناء التطوير لمعرفة حالة PHP الحالية، ويمكنك تمرير المعامل <a href="%E2%80%8Fhttps://www.php.net/manual/en/function.phpinfo.php#refsect1-function.phpinfo-parameters" rel="">ثوابت INFO_*‎</a> مجموعةً باستخدام العوامل الثنائية للحصول على قائمة مخصصة، يمكنك تنفيذها في المتصفح للحصول على التفاصيل بتنسيقٍ جيد، وتعمل أيضًا في واجهة سطر أوامر PHP حيث يمكنك نقلها بعرضٍ أفضل.
</p>

<p>
	<strong>مثال</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_56" style=""><span class="pln">phpinfo</span><span class="pun">(</span><span class="pln">INFO_CONFIGURATION </span><span class="pun">|</span><span class="pln"> INFO_ENVIRONMENT </span><span class="pun">|</span><span class="pln"> INFO_VARIABLES</span><span class="pun">);</span></pre>

<p>
	ستعرض هذه الشيفرة قائمة من موجهات PHP (‏<a href="%E2%80%8Fhttps://www.php.net/manual/en/function.ini-get.php" rel="">ini_get</a>)ومتغيرات البيئة (<a href="%E2%80%8Fhttps://www.php.net/manual/en/reserved.variables.environment.php" rel="">‎$_ENV</a>) والمتغيرات <a href="https://www.php.net/manual/en/language.variables.predefined.php" rel="external nofollow">المعرفة مسبقًا</a>.
</p>

<h3 id="xdebug">
	Xdebug
</h3>

<p>
	<a href="%E2%80%8Fhttps://xdebug.org/" rel="">Xdebug</a> إضافة PHP توفر إمكانيات تنقيح الأخطاء والتحليل، تستخدم بروتوكول تحديد الأخطاء DBGp والتي هي اختصار لـ ‏DeBugGer Protocol، من ميزات هذه الإضافة:
</p>

<ul>
	<li>
		مكدس يتتبع الأخطاء.
	</li>
	<li>
		حماية قصوى بمستوى متداخل وتتبع الوقت.
	</li>
	<li>
		بديل مفيد لدالة <code>var_dump()‎</code> المعيارية لعرض المتغيرات.
	</li>
	<li>
		تسمح بتسجيل كل استدعاءات الدالة متضمنةً المعاملات والقيم المُعادة في ملف بتنسيقات مختلفة
	</li>
	<li>
		تحليل تغطية الشيفرة
	</li>
	<li>
		تحليل المعلومات
	</li>
	<li>
		تنقيح الأخطاء عن بعد (توفر واجهة للعملاء منقحي الأخطاء الذين يتفاعلون مع سكربت PHP المُنفَّذ).
	</li>
</ul>

<p>
	إنّ هذه الإضافة مناسبة تمامًا لبيئة التطوير، خاصةً ميزة تنقيح الأخطاء عن بعد التي يمكن أن تساعدك في تنقيح أخطاء شيفرة PHP بدون كتابة العديد من تعليمات <code>var_dump</code> واستخدام عملية تنقيح الأخطاء العادية كما في لغة C++‎ وجافا.
</p>

<p>
	تثبيت هذه الإضافة بسيط جدًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_64" style=""><span class="pln">pecl install xdebug </span><span class="com"># install from pecl/pear</span></pre>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_60" style=""> </pre>

<p>
	وتفعيلها في ملف <code>php.ini</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_66" style=""><span class="pln">zend_extension</span><span class="pun">=</span><span class="str">"/usr/local/php/modules/xdebug.so"</span></pre>

<p>
	يمكنك الاطلاع على هذه <a href="https://xdebug.org/docs/install" rel="external nofollow">التعليمات</a> للحالات الأكثر تعقيدًا. يجب أن تتذكر عند استخدام هذه الأداة <a href="https://stackoverflow.com/questions/3522182/will-enabling-xdebug-on-a-production-server-make-php-slower/3522356#3522356" rel="external nofollow">أنها غير مناسبة لبيئات الإنتاج</a>.
</p>

<h3 id="-">
	الإبلاغ عن الأخطاء
</h3>

<p>
	استخدم الدالتين التاليتين معًا:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_68" style=""><span class="com">// تضبط هذه الدالة خيار الإعداد في بيئتك</span><span class="pln">
ini_set</span><span class="pun">(</span><span class="str">'display_errors'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'1'</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫ستسمح ‎?-1‎ بالإبلاغ عن كل الأخطاء</span><span class="pln">
error_reporting</span><span class="pun">(-</span><span class="lit">1</span><span class="pun">);</span></pre>

<h3 id="phpversion-">
	phpversion()‎
</h3>

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

<p>
	تقبل هذه الدالة معامل اختياري واحد في شكل اسم الإضافة <code>phpversion('extension')‎</code>، إذا ثُبِّتت الإضافة فإنّ الدالة سترجع سلسلة نصية تتضمن قيمة الإصدار وإلا ستُرجع القيمة <code>FALSE</code>، وإذا لم يتوفر اسم الإضافة ستُرجع الدالة إصدار محلل PHP نفسه.
</p>

<p>
	<strong>مثال</strong>
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2213_70" style=""><span class="kwd">print</span><span class="pln"> </span><span class="str">"Current PHP version: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> phpversion</span><span class="pun">();</span><span class="pln">
</span><span class="com">// Current PHP version: 7.0.8</span><span class="pln">

</span><span class="kwd">print</span><span class="pln"> </span><span class="str">"Current cURL version: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> phpversion</span><span class="pun">(</span><span class="pln"> </span><span class="str">'curl'</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="com">// Current cURL version: 7.0.8</span><span class="pln">
</span><span class="com">// أو</span><span class="pln">
</span><span class="com">// false, no printed output if package is missing</span></pre>

<p>
	المراجع:
</p>

<ul>
	<li>
		<a href="http://php.net/manual/en/function.register-shutdown-function.php" rel="external nofollow">http://php.net/manual/en/function.register-shutdown-function.php</a>
	</li>
	<li>
		<a href="http://php.net/manual/en/function.error-get-last.php" rel="external nofollow">http://php.net/manual/en/function.error-get-last.php</a>
	</li>
	<li>
		<a href="http://php.net/manual/en/errorfunc.constants.php" rel="external nofollow">http://php.net/manual/en/errorfunc.constants.php</a>
	</li>
</ul>

<p>
	ترجمة -وبتصرف- للفصول Common Errors ، وCompilation of Errors and Warnings ، وException Handling and Error Reporting  ، وDebugging من كتاب <a href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>
]]></description><guid isPermaLink="false">1202</guid><pubDate>Sun, 25 Apr 2021 09:00:00 +0000</pubDate></item><item><title>&#x623;&#x646;&#x645;&#x627;&#x637; &#x627;&#x644;&#x62A;&#x635;&#x645;&#x64A;&#x645; &#x648;&#x62A;&#x635;&#x631;&#x64A;&#x641; &#x627;&#x644;&#x625;&#x636;&#x627;&#x641;&#x627;&#x62A; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A3%D9%86%D9%85%D8%A7%D8%B7-%D8%A7%D9%84%D8%AA%D8%B5%D9%85%D9%8A%D9%85-%D9%88%D8%AA%D8%B5%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%A5%D8%B6%D8%A7%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-php-r1201/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_04/Design-Patterns---Compile-PHP-Extensions.png.b3732df3a19c27780d94f300c94fc09f.png" /></p>

<p>
	يوفر هذا الجزء أمثلة عن أنماط التصميم المعروفة المُنفَّذة في PHP.
</p>

<h2 id="-php">
	سلسلة التوابع في PHP
</h2>

<p>
	سَلسَلة التوابع هي تقنية موضحة في كتاب <a data-ss1621332152="1" href="https://www.amazon.com/dp/0321712943" rel="external nofollow">لغات محددة للنطاق</a> لصاحبه <code>Martin Fowler</code> وتُلخص بالشكل التالي:
</p>

<p>
	جعل توابع التعديل تُرجع كائن المضيف بحيث يمكن تنفيذ عدة تعديلات في تعبير واحد.
</p>

<p>
	بفرض لدينا هذه الشيفرة النظامية الخالية من السَلسَلة (نُقلت إلى PHP من الكتاب المذكور أعلاه)
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6549_6" style="">
<span class="pln">$hardDrive </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HardDrive</span><span class="pun">;</span><span class="pln">
$hardDrive</span><span class="pun">-&gt;</span><span class="pln">setCapacity</span><span class="pun">(</span><span class="lit">150</span><span class="pun">);</span><span class="pln">
$hardDrive</span><span class="pun">-&gt;</span><span class="pln">external</span><span class="pun">();</span><span class="pln">
$hardDrive</span><span class="pun">-&gt;</span><span class="pln">setSpeed</span><span class="pun">(</span><span class="lit">7200</span><span class="pun">);</span></pre>

<p>
	تسمح لنا سَلسَلة التوابع بكتابة الشيفرة السابقة بطريقةٍ مختصرة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6549_8" style="">
<span class="pln">$hardDrive </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">HardDrive</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setCapacity</span><span class="pun">(</span><span class="lit">150</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">external</span><span class="pun">()</span><span class="pln">
    </span><span class="pun">-&gt;</span><span class="pln">setSpeed</span><span class="pun">(</span><span class="lit">7200</span><span class="pun">);</span></pre>

<p>
	كل ما تحتاجه هو إضافة <code>return $this</code> إلى التابع الذي نريد سَلسَلته.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6549_10" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">HardDrive</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $isExternal </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $capacity </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">protected</span><span class="pln"> $speed </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</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"> external</span><span class="pun">(</span><span class="pln">$isExternal </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">
        $this</span><span class="pun">-&gt;</span><span class="pln">isExternal </span><span class="pun">=</span><span class="pln"> $isExternal</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">;</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"> setCapacity</span><span class="pun">(</span><span class="pln">$capacity</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">capacity </span><span class="pun">=</span><span class="pln"> $capacity</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">;</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"> setSpeed</span><span class="pun">(</span><span class="pln">$speed</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">speed </span><span class="pun">=</span><span class="pln"> $speed</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">;</span><span class="pln"> 
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	متى نستخدم سلسلة التوابع؟
</h3>

<p>
	الحالات الأساسية التي نستخدم فيها سَلسَلة التوابع هي عند بناء لغات خاصة بالنطاق الداخلي، سَلسَلة التابع هي بناء كتلة في <a data-ss1621332152="1" href="https://martinfowler.com/bliki/ExpressionBuilder.html" rel="external nofollow">باني التعبير</a> و<a data-ss1621332152="1" href="https://martinfowler.com/bliki/FluentInterface.html" rel="external nofollow">الواجهات السلسة</a>. إنّها ليست مرادفة لهما لكن أسلوب السَلسلة يمكّنهما كما يذكر <code>Martin Fowler</code>:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<div class="ipsQuote_contents ipsClearfix">
		<p>
			"لاحظت مفهومًا خاطئًا شائعًا وهو أنّ العديد من الأشخاص يوازنون بين الواجهات السلسة (fluent interfaces) وسَلسلة التابع، من المؤكد أنّ السَلسلة هي تقنية شائعة الاستخدام مع الواجهات السَلسة لكن السلاسة الحقيقية أكثر من ذلك بكثير".
		</p>
	</div>
</blockquote>

<p>
	ورغم ذلك يعدّ الكثير من الأشخاص أنّ استخدام سَلسَلة التابع فقط لتجنب كتابة الكائن المضيف <a data-ss1621332152="1" href="https://martinfowler.com/bliki/CodeSmell.html" rel="external nofollow">مشكلة شيفرة</a>، لأنّه يصنع واجهة برمجة تطبيقات <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> غير واضحة خاصةً عند الدمج مع واجهة برمجة تطبيقات خالية من سَلسَلة التوابع.
</p>

<p>
	إليك أيضًا بعض الملاحظات الإضافية:
</p>

<ul>
<li>
		<strong>فصل استعلام الأوامر: </strong> <a data-ss1621332152="1" href="%E2%80%8Fhttps://martinfowler.com/bliki/CommandQuerySeparation.html" rel="">فصل استعلام الأوامر هو مبدأ في التصميم قدّمه Bertrand Meyer</a> وينص على أنّ التوابع التي تغير الحالة (الأوامر) يجب ألا ترجع شيئًا، أما التوابع التي ترجع شيئًا ما (الاستعلامات) يجب ألا تغير الحالة. وهذا يجعل من السهل التفكير في النظام. تنتهك سَلسَلة التوابع هذا المبدأ لأننا التابع يغير الحالة ويُعيد شيئًا ما.
	</li>
	<li>
		<strong>التوابع الجالبة getters</strong>: يجب الانتباه عند استخدام الأصناف التي تنفذ سَلسَلة التوابع إلى استدعاء توابع الجالب (أي التوابع التي تُرجع شيئًا ما غير ‎$this)، بما أنّ الجالب يجب أن يرجع قيمة ما غير <code>‎$this</code> فإنّ سَلسلة تابع إضافي على التابع الجالب يجعل الاستدعاء يُنفَّذ على القيمة التي حُصِل عليها وليس على الكائن الأصلي، إلا أنّ هناك بعض الحالات لسَلسلة التوابع الجالبة قد تجعل الشيفرة أقل قابلية للقراءة.
	</li>
	<li>
		<strong>قانون ديميتر وتأثيره على الاختبار:</strong> لا تنتهك سَلسلة التوابع <a data-ss1621332152="1" href="https://en.wikipedia.org/wiki/Law_of_Demeter" rel="external nofollow">قانون ديميتر</a> كما أنّها لا تؤثر على الاختبار وذلك لأننا نعيد الكائن المضيف وليس بعض المتعاونين. إنّه مفهوم خاطئ شائع عند الأشخاص الذين يخلطون بين سَلسلة التوابع والواجهات السلسة وبناة التعبير، يُنتهك قانون ديميتر فقط عندما تعيد سَلسلة التوابع كائنات أخرى غير الكائن المضيف وينتهي بك الأمر بالحصول على اختبارات وهمية في اختباراتك.
	</li>
</ul>
<h2 id="-php-linux-">
	تصريف إضافات PHP في نظام لينوكس Linux
</h2>

<p>
	يوجد عدة متطلبات لتصريف إضافة PHP في بيئة لينكس نموذجية:
</p>

<ul>
<li>
		مهارات يونكس الأساسية (أن تكون قادرًا على تشغيل الأمر "make" ومصرِّف C).
	</li>
	<li>
		مصرِّف لغة C يدعم المعيار ANSI.
	</li>
	<li>
		الشيفرة المصدرية لإضافة PHP التي تريد تصريفها.
	</li>
</ul>
<p>
	عمومًا، يوجد طريقتين لتصريف إضافة PHP. يمكنك تصريف الإضافة بشكلٍ ساكن إلى الصيغة الثنائية في PHP أو تصريفها كوحدة مشتركة محملة من قِبل الصيغة الثنائية في PHP عند بدء التشغيل. ومن الأفضل استخدام الوحدات المشتركة لأنها تسمح بإضافة أو حذف الإضافات بدون إعادة بناء كامل صيغة PHP الثنائية، يركز هذا المثال على الخيار المشترك.
</p>

<p>
	إذا ثبّت PHP باستخدام مدير الحزم <code>‎(apt-get install, yum install, etc..)‎</code> ستحتاج إلى تثبيت حزمة <code>‎-dev</code> من أجل PHP، والتي ستتضمن ملفات ترويسة PHP وسكربت <code>phpize</code> الضروريين لتعمل بيئة البناء. قد تسمى الحزمة باسم مثل <code>php5-dev</code> أو <code>php7-dev</code> لكن تأكد من استخدام مدير حزمتك للبحث عن الاسم المناسب باستخدام مستودعات التوزيعة الخاصة بك لأنها قد تختلف.
</p>

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

<pre class="ipsCode" id="ips_uid_4331_12">
‎/usr/include أو ‎/usr/local/include</pre>

<h3>
	خطوات التصريف
</h3>

<p>
	بعد أن تتأكد من أنّه لديك كل المتطلبات الضرورية للتصريف يمكنك التوجه إلى <a data-ss1621332152="1" href="%E2%80%8Fhttps://pecl.php.net/" rel="">pecl.php.net</a> واختيار الإضافة التي تريد تصريفها وتحميل ملف tarball الخاص بها.
</p>

<ul>
<li>
		فك ضغط ملف tarball (مثل: tar xfvz yaml-2.0.0RC8.tgz)
	</li>
	<li>
		أدخل المجلد حيث فُكَّ ضغط الأرشيف، ونفّذ الأمر <code>phpize</code>.
	</li>
	<li>
		يجب أن ترى الآن سكربت جديد مُنشأ حديثًا <code>‎.configure</code>، إذا كان كل شيء على ما يرام عندها نفّذ الأمر <code>‎./configure</code>.
	</li>
	<li>
		ستحتاج الآن إلى تنفيذ الأمر <code>make</code> الذي سيصرّف الإضافة.
	</li>
	<li>
		أخيرًا ننفذ الأمر <code>make install</code> التي ستنسخ الملف الثنائي المصرَّف إلى مجلد الإضافة الخاص بك.
	</li>
</ul>
<p>
	سيوفر لك الأمر <code>make install</code> مسار التثبيت الذي نُسخت فيه الإضافة، والذي يكون عادةً في <code>‎/usr/lib/‎</code>، قد يكون مثلًا
</p>

<pre class="ipsCode" id="ips_uid_4331_10">
‎/usr/lib/php5/20131226/yaml.so‎</pre>

<p>
	يعتمد هذا على إعدادات PHP الخاصة بك (مثل ‎--with-prefix) ونسخة واجهة برمجة التطبيقات المحددة. يُضمَّن رقم واجهة برمجة التطبيقات في المسار للحفاظ على الإضافات المبنية لإصدارات واجهات برمجة تطبيقات مختلفة في مواقع مختلفة.
</p>

<h3>
	تحميل الإضافة في PHP
</h3>

<p>
	لتحميل الإضافة في PHP، ابحث عن ملف <code>php.ini</code> المحمَّل من أجل واجهة برمجة التطبيقات للخادم (SAPI) المناسبة، وأضف السطر <code>extension=yaml.so</code> ثم أعد تشغيل PHP وغيّر <code>yaml.so</code> إلى اسم الإضافة المثبّتة الفعلي.
</p>

<p>
	بالنسبة للإضافة Zend فأنت تحتاج إلى توفير المسار الكامل لملف الكائن المشترك، أما في باقي إضافات PHP العادية، فيُشتق هذا المسار من الموجِّه <a data-ss1621332152="1" href="%E2%80%8Fhttps://www.php.net/ini.core#ini.extension-dir" rel="">extension_dir</a> في ملف الإعدادات المحمَّل أو من متغير البيئة <code>‎$PATH</code> أثناء إعداد التهيئة.
</p>

<p>
	ترجمة -وبتصرف- للفصول Design Patterns - Compile PHP Extensions من كتاب <span style="display: none;"> </span><a data-ss1621332152="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a><span style="display: none;"> </span>
</p>
]]></description><guid isPermaLink="false">1201</guid><pubDate>Fri, 23 Apr 2021 22:11:00 +0000</pubDate></item><item><title>&#x62D;&#x627;&#x648;&#x64A;&#x629; &#x62F;&#x648;&#x643;&#x631; Docker &#x648;&#x645;&#x62E;&#x632;&#x646; APCu &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%AD%D8%A7%D9%88%D9%8A%D8%A9-%D8%AF%D9%88%D9%83%D8%B1-docker-%D9%88%D9%85%D8%AE%D8%B2%D9%86-apcu-%D9%81%D9%8A-php-r1200/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_04/docker.png.58bfde22cce3b4756bcf08aedef22c26.png" /></p>

<p>
	يُعَدّ <a data-ss1619594836="1" href="%E2%80%8Fhttps://www.docker.com/" rel="">Docker</a> حاويةً شائعة جدًا تُستخدم على نطاقٍ واسع كحلّ لنشر الشيفرة في بيئات الإنتاج، كما أنها تسهّل إدارة وتوسيع تطبيقات الويب والخدمات الصغيرة.
</p>

<h2 id="-php">
	الحصول على صورة دوكر من أجل php
</h2>

<p>
	لنشر التطبيق على دوكر نحتاج أولًا للحصول على الصورة من السجل registry.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6358_7" style="">
<span class="pln">docker pull php</span></pre>

<p>
	سيوفر لك هذا أحدث إصدار للصورة من مستودع ‏php الرسمي، تُستخدم php بشكلٍ عام لنشر تطبيقات الويب لذا نحتاج إلى خادم http ليتوافق مع الصورة. تأتي الصورة في الإصدار php:7.0 (أو إصدار أحدث) مُثبّتة مسبقًا مع apache لتنشر تطبيقك بدون مشاكل.
</p>

<h2 id="-dockerfile">
	كتابة dockerfile
</h2>

<p>
	يُستخدم <code>Dockerfile</code> لضبط الصورة المخصصة التي سننشئها مع شيفرات تطبيق الويب، ننشئ ملف جديد <code>Dockerfile</code> في المجلد الجذر للمشروع ونضع فيه المحتويات التالية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6358_9" style="">
<span class="pln">FROM php</span><span class="pun">:</span><span class="lit">7.0</span><span class="pun">-</span><span class="pln">apache
COPY </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">php</span><span class="pun">/</span><span class="pln">php</span><span class="pun">.</span><span class="pln">ini </span><span class="pun">/</span><span class="pln">usr</span><span class="pun">/</span><span class="kwd">local</span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">php</span><span class="pun">/</span><span class="pln">
COPY </span><span class="pun">.</span><span class="pln"> </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">html</span><span class="pun">/</span><span class="pln">
EXPOSE </span><span class="lit">80</span></pre>

<p>
	يستخدم السطر الأول لوصف الصورة التي يجب استخدامها لإنشاء صورة جديدة، يمكن تغيير هذا إلى أي إصدار PHP آخر محدد من السجل، والسطر الثاني لتحميل ملف <code>php.ini</code> إلى الصورة ويمكنك تغيير هذا الملف إلى موقع ملف مخصص آخر، وينسخ السطر الثالث الشيفرات في المجلد الحالي إلى <code>‎/var/www/html</code> والذي هو webroot بالنسبة لنا، تذكر أن <code>‎/var/www/html</code> داخل الصورة، أما السطر الأخير فسيفتح المنفذ 80 داخل حاوية دوكر.
</p>

<p>
	قد يكون لديك في بعض الحالات بعض الملفات التي لا تريدها على الخادم مثل ملف إعدادات البيئة، بفرض أنّ إعدادات البيئة موجودة لدينا في ملف <code>‎.env</code> ونريد تجاهله عندها نضيفه إلى <code>‎.dockerignore</code> في المجلد الجذر لشيفرتنا.
</p>

<h2 id="-">
	بناء الصورة
</h2>

<p>
	إنّ بناء الصورة شيء غير محدد في php، لكن لبناء الصورة التي تحدثنا عنها في الأعلى نستخدم مايلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6358_11" style="">
<span class="pln">docker build </span><span class="pun">-</span><span class="pln">t </span><span class="pun">&lt;</span><span class="typ">Image</span><span class="pln"> name</span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">.</span></pre>

<p>
	يمكننا التحقق من بناء الصورة باستخدام:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6358_13" style="">
<span class="pln">docker images</span></pre>

<p>
	سيعطيك هذا الأمر كل الصور المثبتة في نظامك.
</p>

<h2 id="-">
	بدء حاوية التطبيق
</h2>

<p>
	يمكننا البدء بتقديم الخدمة بمجرد أن تصبح الصورة جاهزة، نستخدم ما يلي لإنشاء حاوية من الصورة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6358_15" style="">
<span class="pln">docker run </span><span class="pun">-</span><span class="pln">p </span><span class="lit">80</span><span class="pun">:</span><span class="lit">80</span><span class="pln"> </span><span class="pun">-</span><span class="pln">d </span><span class="pun">&lt;</span><span class="typ">Image</span><span class="pln"> name</span><span class="pun">&gt;</span></pre>

<p>
	ستوجّه <code>‎-p 80:80</code> في الأمر السابق المنفذ 80 الخاص بخادمك إلى المنفذ 80 الخاص بالحاوية، وستخبر الراية <code>‎-d</code> أنّه يجب تنفيذ الحاوية في الخلفية وتصف <code>&lt;Image name&gt;</code> الصورة التي يجب استخدامها لبناء الحاوية.
</p>

<h3>
	التحقق من الحاوية
</h3>

<p>
	نستخدم ما يلي للتحقق من الحاويات قيد التنفيذ:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6358_17" style="">
<span class="pln">docker ps</span></pre>

<p>
	سيعطينا هذا الأمر قائمة بكل الحاويات التي تُنفَّذ.
</p>

<h3>
	سجلات التطبيق
</h3>

<p>
	تعدّ السجلات مهمة جدًا لتنقيح أخطاء التطبيق، وللتحقق منها نستخدم الأمر:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6358_19" style="">
<span class="pln">docker logs </span><span class="pun">&lt;</span><span class="typ">Container</span><span class="pln"> id</span><span class="pun">&gt;</span></pre>

<h2 id="-apcu">
	مخزن APCu
</h2>

<p>
	APCu هو مخزن قيمة-مفتاح للذاكرة المشتركة في PHP، تُشارك الذاكرة بين عملياتPHP-FPM ‎  (أي Fast Process Manager)‎‍ في نفس المجمع pool وتستمر البيانات المخزنة بين العمليات.
</p>

<h3 id="-">
	تكرار محتويات المداخل
</h3>

<p>
	يسمح الصنف <a data-ss1619594836="1" href="%E2%80%8Fhttps://www.php.net/manual/en/class.apcuiterator.php" rel="">APCUIterator</a> بتكرار محتويات المداخل في المخزن المؤقت cache:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1894_9" style="">
<span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">APCUIterator</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $entry</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    print_r</span><span class="pun">(</span><span class="pln">$entry</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_6358_22" style="">
<span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">APCUIterator</span><span class="pun">(</span><span class="pln">$regex</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> $entry</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    print_r</span><span class="pun">(</span><span class="pln">$entry</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_1894_11" style="">
<span class="pln">$key </span><span class="pun">=</span><span class="pln"> </span><span class="str">'…'</span><span class="pun">;</span><span class="pln">
$regex </span><span class="pun">=</span><span class="pln"> </span><span class="str">'(^'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> preg_quote</span><span class="pun">(</span><span class="pln">$key</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">
print_r</span><span class="pun">((</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">APCUIterator</span><span class="pun">(</span><span class="pln">$regex</span><span class="pun">))-&gt;</span><span class="pln">current</span><span class="pun">());</span></pre>

<h3 id="-">
	تخزين واسترجاع بسهولة
</h3>

<p>
	يمكن استخدام <a data-ss1619594836="1" href="%E2%80%8Fhttps://www.php.net/manual/de/function.apcu-store.php" rel="">apcu_store</a> لتخزين قيم و<a data-ss1619594836="1" href="%E2%80%8Fhttps://www.php.net/manual/de/function.apcu-fetch.php" rel="">apcu_fetch</a> لاستعادتها:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1894_13" style="">
<span class="pln">$key </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Hello'</span><span class="pun">;</span><span class="pln">
$value </span><span class="pun">=</span><span class="pln"> </span><span class="str">'World'</span><span class="pun">;</span><span class="pln">
apcu_store</span><span class="pun">(</span><span class="pln">$key</span><span class="pun">,</span><span class="pln"> $value</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">apcu_fetch</span><span class="pun">(</span><span class="str">'Hello'</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// 'World'</span></pre>

<h3 id="-">
	تخزين معلومات
</h3>

<p>
	توفر <a data-ss1619594836="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.apcu-cache-info.php%E2%80%8F" rel="">apcu_cache_info</a> معلومات حول المخزن ومداخله:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_6358_25" style="">
<span class="pln">print_r</span><span class="pun">(</span><span class="pln">apcu_cache_info</span><span class="pun">());</span></pre>

<p>
	لاحظ أنّ استدعاء <code>apcu_cache_info()‎</code> بدون حد سيعيد كل البيانات المخزنة حاليًا، ولهذا نستخدم <code>apcu_cache_info(true)‎</code>، للحصول على البيانات الوصفية فقط، كما أنه من الأفضل استخدام الصنف <code>APCUIterator</code> للحصول على معلومات عن مداخل ذاكرة تخزين مؤقتة محددة.
</p>

<p>
	ترجمة -وبتصرف- للفصل Docker deployment - APCu من كتاب <a data-ss1619594836="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>
]]></description><guid isPermaLink="false">1200</guid><pubDate>Wed, 21 Apr 2021 09:08:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x625;&#x636;&#x627;&#x641;&#x629; BC Math: &#x627;&#x644;&#x622;&#x644;&#x629; &#x627;&#x644;&#x62D;&#x627;&#x633;&#x628;&#x629; &#x627;&#x644;&#x62B;&#x646;&#x627;&#x626;&#x64A;&#x629; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-bc-math-%D8%A7%D9%84%D8%A2%D9%84%D8%A9-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D8%A8%D8%A9-%D8%A7%D9%84%D8%AB%D9%86%D8%A7%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-php-r1199/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_04/Binary-Calculator.png.d0510bd51d4504d4541d1f5a4cafa5d0.png" /></p>

<p>
	يمكن استخدام الآلة الحاسبة الثنائية BC Math للتعامل مع أرقام بأي حجم وبدقة عشرية تصل إلى 2147483647‎-1‎، بتنسيق سلسلة نصية، وهي أدق من الحساب العشري في PHP، وتدعم كلًا من الدوال الآتية:
</p>

<table>
<thead><tr>
<th>
				الدالة
			</th>
			<th>
				الوصف
			</th>
			<th>
				المعاملات
			</th>
		</tr></thead>
<tbody>
<tr>
<td>
				bcadd
			</td>
			<td>
				تضيف هذه الدالة أي رقمين بدقة ما
			</td>
			<td>
				<ul>
<li>
						left_operand: المعامَل اليساري على شكل سلسلة نصية.
					</li>
					<li>
						right_operand: المعامَل اليميني على شكل سلسلة نصية.
					</li>
					<li>
						scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
					</li>
					<br>
</ul>
</td>
		</tr>
<tr>
<td>
				bccomp
			</td>
			<td>
				توازن بين رقمين بدقة ما
			</td>
			<td>
				<ul>
<li>
						left_operand: المعامَل اليساري على شكل سلسلة نصية.
					</li>
					<li>
						right_operand: المعامَل اليميني على شكل سلسلة نصية.
					</li>
					<li>
						scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية والتي ستُستخدم في الموازنة.
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				bcdiv
			</td>
			<td>
				تقسّم رقمين بدقة ما
			</td>
			<td>
				<ul>
<li>
						left_operand: المعامَل اليساري على شكل سلسلة نصية.
					</li>
					<li>
						right_operand: المعامَل اليميني على شكل سلسلة نصية.
					</li>
					<li>
						scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				bcmod
			</td>
			<td>
				تعيد باقي قسمة رقم على رقم آخر ذو دقة ما
			</td>
			<td>
				<ul>
<li>
						left_operand: المعامَل اليساري على شكل سلسلة نصية.
					</li>
					<li>
						divisor: العدد الذي نريد القسمة عليه على شكل سلسلة نصية.
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				bcmul
			</td>
			<td>
				تعيد نتيجة ضرب رقمين بدقةٍ ما
			</td>
			<td>
				<ul>
<li>
						left_operand: المعامَل اليساري على شكل سلسلة نصية.
					</li>
					<li>
						right_operand: المعامَل اليميني على شكل سلسلة نصية.
					</li>
					<li>
						scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				bcpow
			</td>
			<td>
				ترفع رقم ذو دقةٍ ما إلى رقم آخر
			</td>
			<td>
				<ul>
<li>
						left_operand: المعامَل اليساري على شكل سلسلة نصية.
					</li>
					<li>
						right_operand: المعامَل اليميني على شكل سلسلة نصية.
					</li>
					<li>
						scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				bcpowmod
			</td>
			<td>
				ترفع رقم ذو دقةٍ ما إلى رقم آخر، مخفضًا بباقي قسمة محدد
			</td>
			<td>
				<ul>
<li>
						left_operand: المعامَل اليساري على شكل سلسلة نصية.
					</li>
					<li>
						right_operand: المعامَل اليميني على شكل سلسلة نصية.
					</li>
					<li>
						modulus: باقي القسمة على شكل سلسلة نصية.
					</li>
					<li>
						scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				bcscale
			</td>
			<td>
				تضبط معامل القياس الافتراضي لكل دوال الإضافة bc math
			</td>
			<td>
				<ul>
<li>
						scale: عامل القياس.
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				bcsqrt
			</td>
			<td>
				تطرح رقم ذو دقةٍ ما من رقم آخر
			</td>
			<td>
				<ul>
<li>
						operand: المعامَل على شكل سلسلة نصية.
					</li>
					<li>
						scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
					</li>
				</ul>
</td>
		</tr>
<tr>
<td>
				bcsub
			</td>
			<td>
				تضيف هذه الدالة أي رقمين بدقة ما
			</td>
			<td>
				<ul>
<li>
						left_operand: المعامَل اليساري على شكل سلسلة نصية.
					</li>
					<li>
						right_operand: المعامَل اليميني على شكل سلسلة نصية.
					</li>
					<li>
						scale: معامل اختياري لضبط عدد الأرقام بعد الفاصلة العشرية في النتيجة.
					</li>
				</ul>
</td>
		</tr>
</tbody>
</table>
<h2 id="-bcmath-32-">
	<br>
	استخدام bcmath لقراءة/كتابة رقم ثنائي طويل في أنظمة 32 بت
</h2>

<p>
	لا يمكن تخزين الأعداد الصحيحة التي تكون أكبر من 0x7FFFFFFF في أنظمة 32 بت بشكلٍ أساسي، بينما يمكن تخزين الأعداد الصحيحة بين 0x0000000080000000 و0x7FFFFFFFFFFFFFFF في أنظمة 64 بت ولا يمكن تخزينها في أنظمة 32 بت (طويلة جدًا وذات إشارة). ومع ذلك بما أنّ أنظمة 64 بت والعديد من اللغات الأخرى تدعم تخزين الأعداد الصحيحة الطويلة جدًا ذات الإشارة فمن الضروري أحيانًا تخزين هذا المجال من الأعداد الصحيحة بالقيمة الدقيقة. هناك عدة طرق للقيام بذلك مثل إنشاء مصفوفة من رقمين أو تحويل العدد الصحيح إلى صيغته العشرية القابلة للقراءة من قِبل البشر، ولهذا العديد من الميزات مثل الراحة في العرض للمستخدم وقابلية معالجته باستخدام bcmath مباشرةً.
</p>

<p>
	يمكن استخدام التوابع <a data-ss1619595865="1" data-ss1619609158="1" data-ss1621332341="1" href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/pack" rel="">pack</a> و<a data-ss1619595865="1" data-ss1619609158="1" data-ss1621332341="1" href="%E2%80%8Fhttps://wiki.hsoub.com/PHP/unpack" rel="">unpack</a> للتحويل بين البايتات الثنائية والصيغة العشرية للأرقام (كلاهما من النوع سلسلة لكن الأولى ثنائية والثانية بترميز ASCII، لكنهم سيحاولون دائمًا تحويل السلسلة النصية بترميز ASCII إلى عدد صحيح 32 بت في أنظمة 32 بت، توفر الشيفرة التالية بديل:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2049_7" style="">
<span class="com">// ‫استخدم pack("J")‎ أو pack("p")‎⁡ في أنظمة 64 بت</span><span class="pln">
</span><span class="kwd">function</span><span class="pln"> writeLong</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $ascii</span><span class="pun">)</span><span class="pln"> </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">// ‫إذا كان ‎$ascii &lt; 0‎</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">bccomp</span><span class="pun">(</span><span class="pln">$ascii</span><span class="pun">,</span><span class="pln"> </span><span class="str">"0"</span><span class="pun">)</span><span class="pln"> </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"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// 18446744073709551616 = (1 &lt;&lt; 64)</span><span class="pln">
        </span><span class="com">// ‫تذكر إضافة علامات الاقتباس وإلا سيُحلَّل الرقم على أنه عشري</span><span class="pln">
        $ascii </span><span class="pun">=</span><span class="pln"> bcadd</span><span class="pun">(</span><span class="pln">$ascii</span><span class="pun">,</span><span class="pln"> </span><span class="str">"18446744073709551616"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

    </span><span class="com">// ‫"n" لتخزين البتات الأقل أهمية أولًا بصيغة 16 بت بدون إشارة، نستخدم "v" لتخزين البتات الأكثر أهمية أولًا</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> pack</span><span class="pun">(</span><span class="str">"n"</span><span class="pun">,</span><span class="pln"> bcmod</span><span class="pun">(</span><span class="pln">bcdiv</span><span class="pun">(</span><span class="pln">$ascii</span><span class="pun">,</span><span class="pln"> </span><span class="str">"281474976710656"</span><span class="pun">),</span><span class="pln"> </span><span class="str">"65536"</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
        pack</span><span class="pun">(</span><span class="str">"n"</span><span class="pun">,</span><span class="pln"> bcmod</span><span class="pun">(</span><span class="pln">bcdiv</span><span class="pun">(</span><span class="pln">$ascii</span><span class="pun">,</span><span class="pln"> </span><span class="str">"4294967296"</span><span class="pun">),</span><span class="pln"> </span><span class="str">"65536"</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
        pack</span><span class="pun">(</span><span class="str">"n"</span><span class="pun">,</span><span class="pln"> bcdiv</span><span class="pun">(</span><span class="pln">$ascii</span><span class="pun">,</span><span class="pln"> </span><span class="str">"65536"</span><span class="pun">),</span><span class="pln"> </span><span class="str">"65536"</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
        pack</span><span class="pun">(</span><span class="str">"n"</span><span class="pun">,</span><span class="pln"> bcmod</span><span class="pun">(</span><span class="pln">$ascii</span><span class="pun">,</span><span class="pln"> </span><span class="str">"65536"</span><span class="pun">));</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">

</span><span class="kwd">function</span><span class="pln"> readLong</span><span class="pun">(</span><span class="kwd">string</span><span class="pln"> $binary</span><span class="pun">)</span><span class="pln"> </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">
    $result </span><span class="pun">=</span><span class="pln"> </span><span class="str">"0"</span><span class="pun">;</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> bcadd</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">,</span><span class="pln"> unpack</span><span class="pun">(</span><span class="str">"n"</span><span class="pun">,</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">$binary</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)));</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> bcmul</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">,</span><span class="pln"> </span><span class="str">"65536"</span><span class="pun">);</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> bcadd</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">,</span><span class="pln"> unpack</span><span class="pun">(</span><span class="str">"n"</span><span class="pun">,</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">$binary</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)));</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> bcmul</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">,</span><span class="pln"> </span><span class="str">"65536"</span><span class="pun">);</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> bcadd</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">,</span><span class="pln"> unpack</span><span class="pun">(</span><span class="str">"n"</span><span class="pun">,</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">$binary</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)));</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> bcmul</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">,</span><span class="pln"> </span><span class="str">"65536"</span><span class="pun">);</span><span class="pln">
    $result </span><span class="pun">=</span><span class="pln"> bcadd</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">,</span><span class="pln"> unpack</span><span class="pun">(</span><span class="str">"n"</span><span class="pun">,</span><span class="pln"> substr</span><span class="pun">(</span><span class="pln">$binary</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)));</span><span class="pln">

    </span><span class="com">// ‫إذا كان ‎?$binary طويل جدًا ومع إشارة </span><span class="pln">
    </span><span class="com">// ‫9223372036854775808‎ = (1 &lt;&lt; 63)‎ (لاحظ أن هذا التعبير لا يعمل حتى في أنظمة 64 بت)</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">(</span><span class="pln">bccomp</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">,</span><span class="pln"> </span><span class="str">"9223372036854775808"</span><span class="pun">)</span><span class="pln"> </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"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// ‫إذا كان ‎$result &gt;= 9223372036854775807</span><span class="pln">
        $result </span><span class="pun">=</span><span class="pln"> bcsub</span><span class="pun">(</span><span class="pln">$result</span><span class="pun">,</span><span class="pln"> </span><span class="str">"18446744073709551616"</span><span class="pun">);</span><span class="pln">
        </span><span class="com">// $result -= (1 &lt;&lt; 64)</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> $result</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2 id="-bcmath-">
	موازنة بين BCMath والعمليات الحسابية العشرية
</h2>

<ul>
<li>
		bcadd مقابل رقم عشري + رقم عشري:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2049_11" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="str">'10'</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'-9.99'</span><span class="pun">);</span><span class="pln">
</span><span class="com">// float(0.0099999999999998)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="lit">10</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">-</span><span class="lit">9.99</span><span class="pun">);</span><span class="pln">
</span><span class="com">// float(0.0099999999999998)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="lit">10.00</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">-</span><span class="lit">9.99</span><span class="pun">);</span><span class="pln">
</span><span class="com">// float(0.0099999999999998)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">bcadd</span><span class="pun">(</span><span class="str">'10'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'-9.99'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">));</span><span class="pln">
</span><span class="com">// string(22) "0.01000000000000000000"</span></pre>

<ul>
<li>
		bcsub مقابل رقم عشري - رقم عشري:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2049_9" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="str">'10'</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="str">'9.99'</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(0.0099999999999998)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="lit">10</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">9.99</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(0.0099999999999998)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="lit">10.00</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">9.99</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(0.0099999999999998)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">bcsub</span><span class="pun">(</span><span class="str">'10'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9.99'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// string(22) "0.01000000000000000000"</span></pre>

<ul>
<li>
		bcmul مقابل رقم صحيح * رقم صحيح:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2049_13" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="str">'5.00'</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="str">'2.00'</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(10)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="lit">5.00</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">2.00</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(10)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">bcmul</span><span class="pun">(</span><span class="str">'5.0'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'2'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// string(4) "10.0"</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">bcmul</span><span class="pun">(</span><span class="str">'5.000'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'2.00'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// string(8) "10.00000"</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">bcmul</span><span class="pun">(</span><span class="str">'5'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'2'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// string(2) "10"</span></pre>

<ul>
<li>
		bcmul مقابل رقم عشري * رقم عشري:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2049_15" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="str">'1.6767676767'</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="str">'1.6767676767'</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(2.8115498416259)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="lit">1.6767676767</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1.6767676767</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(2.8115498416259)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">bcmul</span><span class="pun">(</span><span class="str">'1.6767676767'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'1.6767676767'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// string(22) "2.81154984162591572289"</span></pre>

<ul>
<li>
		bcdiv مقابل رقم عشري / رقم عشري:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_2049_17" style="">
<span class="pln">var_dump</span><span class="pun">(</span><span class="str">'10'</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="str">'3.01'</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(3.3222591362126)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="lit">10</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">3.01</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(3.3222591362126)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="lit">10.00</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">3.01</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// float(3.3222591362126)</span><span class="pln">

var_dump</span><span class="pun">(</span><span class="pln">bcdiv</span><span class="pun">(</span><span class="str">'10'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'3.01'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">));</span><span class="pln"> 
</span><span class="com">// string(22) "3.32225913621262458471"</span></pre>

<p>
	ترجمة -وبتصرف- للفصل [BC Math (Binary Calculator)‎] من كتاب <a data-ss1619609158="1" data-ss1621332341="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
]]></description><guid isPermaLink="false">1199</guid><pubDate>Sat, 17 Apr 2021 09:04:00 +0000</pubDate></item><item><title>&#x62A;&#x645;&#x647;&#x64A;&#x62F; &#x644;&#x639;&#x645;&#x644;&#x64A;&#x62A;&#x64A; &#x627;&#x644;&#x62A;&#x62D;&#x645;&#x64A;&#x644; &#x648;&#x627;&#x644;&#x62A;&#x646;&#x632;&#x64A;&#x644; &#x627;&#x644;&#x62A;&#x644;&#x642;&#x627;&#x626;&#x64A; &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%AA%D9%85%D9%87%D9%8A%D8%AF-%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%AA%D9%8A-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D9%88%D8%A7%D9%84%D8%AA%D9%86%D8%B2%D9%8A%D9%84-%D8%A7%D9%84%D8%AA%D9%84%D9%82%D8%A7%D8%A6%D9%8A-%D9%81%D9%8A-php-r1181/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/9.png.588994dcb0fe513215f37bd181bb6acb.png" /></p>
<h2>
	التحميل التلقائي (autoloading) كجزء من حل إطار العمل
</h2>

<p>
	ملف <code>autoload.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_7" style=""><span class="pln">spl_autoload_register</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$class</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    require_once </span><span class="str">"$class.php"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	ملف <code>Animal.php</code>:
</p>

<pre class="ipsCode">class Animal {
    public function eats($food) {
        echo "Yum, $food!";
    }
}
</pre>

<p>
	ملف <code>Ruminant.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_9" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Ruminant</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Animal</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"> eats</span><span class="pun">(</span><span class="pln">$food</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="str">'grass'</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> $food</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">eats</span><span class="pun">(</span><span class="pln">$food</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">
            echo </span><span class="str">"Yuck, $food!"</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>Cow.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_11" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Cow</span><span class="pln"> </span><span class="kwd">extends</span><span class="pln"> </span><span class="typ">Ruminant</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملف <code>pasture.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_13" style=""><span class="kwd">require</span><span class="pln"> </span><span class="str">'autoload.php'</span><span class="pun">;</span><span class="pln">
$animal </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Cow</span><span class="pun">;</span><span class="pln">
$animal</span><span class="pun">-&gt;</span><span class="pln">eats</span><span class="pun">(</span><span class="str">'grass'</span><span class="pun">);</span></pre>

<p>
	يمكننا الوصول إلى أي صنف يتبع اصطلاحات التسمية الموجودة في المحمِّل التلقائي وذلك بفضل المحمل التلقائي العام. اصطلاحاتنا في هذا المثال بسيطة: يجب أن يكون للصنف المطلوب ملف في نفس المجلد يُسمّى بنفس اسم الصنف وتُضاف له اللاحقة <code>‎.php</code>، يجب أن يكون اسم الصنف مطابقًا تمامًا لاسم الملف.
</p>

<p>
	بدون التحميل التلقائي، يجب أن نضيف الأصناف الأساسية يدويًا باستخدام <code>require</code>، إذا كنا نبني حديقة حيوانات كاملة سيكون لدينا الآلاف من تعليمات <code>require</code> التي يمكن استبدالها بسهولة بمحمِّل تلقائي واحد.
</p>

<p>
	في التحليل النهائي، يعدّ التحميل التلقائي في <a href="https://wiki.hsoub.com/PHP" rel="external">PHP </a>آلية تساعدك على كتابة شيفرة بآلية أقل لذا يمكنك التركيز على حل مشاكل العمل، كل ماعليك فعله هو تحديد استراتيجية تربط اسم الصنف باسم الملف، يمكنك تنفيذ استراتيجية تحميل تلقائي خاصة بك كما هو الحال هنا، أو يمكنك استخدام أي من المعايير التي تتبناها PHP: <a data-ss1616977283="1" href="%E2%80%8Fhttps://www.php-fig.org/psr/psr-0/" rel="">‏PSR-0</a> أو<a data-ss1616977283="1" href="%E2%80%8Fhttps://www.php-fig.org/psr/psr-4/" rel="">‏PSR-4</a> أو يمكنك استخدام <a data-ss1616977283="1" href="https://getcomposer.org/" rel="external nofollow">المُنشئ</a> لتعريف الاعتماديات وإدارتها بشكلٍ عام.
</p>

<h2>
	تعريف صنف مضمَّن بدون الحاجة للتحميل
</h2>

<p>
	ملف <code>zoo.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_15" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Animal</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"> eats</span><span class="pun">(</span><span class="pln">$food</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">"Yum, $food!"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

$animal </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Animal</span><span class="pun">();</span><span class="pln">
$animal</span><span class="pun">-&gt;</span><span class="pln">eats</span><span class="pun">(</span><span class="str">'meat'</span><span class="pun">);</span></pre>

<p>
	<a href="https://academy.hsoub.com/php/" rel="">تعلم PHP</a> ماهو الصنف <code>Animal</code> قبل تنفيذ التعليمة <code>new Animal</code> لأن PHP تقرأ الملفات المصدرية من الأعلى إلى الأسفل، لكن ماذا لو أردنا إنشاء كائنات من الصنف <code>Animal</code> في عدة أماكن ليس فقط في الملف المصدري الذي عُرِّف فيه، نحتاج للقيام بذلك إلى تحميل تعريف الصنف.
</p>

<h2>
	تحميل يدوي للصنف باستخدام require
</h2>

<p>
	ملف <code>Animal.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_17" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Animal</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"> eats</span><span class="pun">(</span><span class="pln">$food</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">"Yum, $food!"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملف <code>zoo.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_19" style=""><span class="kwd">require</span><span class="pln"> </span><span class="str">'Animal.php'</span><span class="pun">;</span><span class="pln">
$animal </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Animal</span><span class="pun">;</span><span class="pln">
$animal</span><span class="pun">-&gt;</span><span class="pln">eats</span><span class="pun">(</span><span class="str">'slop'</span><span class="pun">);</span></pre>

<p>
	ملف <code>aquarium.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_21" style=""><span class="kwd">require</span><span class="pln"> </span><span class="str">'Animal.php'</span><span class="pun">;</span><span class="pln">
$animal </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Animal</span><span class="pun">;</span><span class="pln">
$animal</span><span class="pun">-&gt;</span><span class="pln">eats</span><span class="pun">(</span><span class="str">'shrimp'</span><span class="pun">);</span></pre>

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

<p>
	يستخدم الملفان الآخران هذا الملف بتضمينه يدويًا، وبما أنّ PHP تقرأ الملف المصدري من الأعلى إلى الأسفل فإنّ تعليمة <code>require</code> ستجد الملف "Animal.php" وتجعل تعريف الصنف <code>Animal</code> متوفرًا قبل استدعاء <code>new Animal</code>.
</p>

<p>
	تخيل الآن أنّه لديك عشرات أو مئات الحالات التي تريد فيها إنشاء كائنات جديدة من الصنف <code>Animal</code> قد يتطلب ذلك الكثير من تعليمات <code>require</code> المملة.
</p>

<h2>
	التحميل التلقائي بديلًا لتحميل تعريف الصنف يدويًا
</h2>

<p>
	ملف <code>autoload.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_23" style=""><span class="pln">spl_autoload_register</span><span class="pun">(</span><span class="kwd">function</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$class</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    require_once </span><span class="str">"$class.php"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">});</span></pre>

<p>
	ملف <code>Animal.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_25" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Animal</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"> eats</span><span class="pun">(</span><span class="pln">$food</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        echo </span><span class="str">"Yum, $food!"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ملف <code>zoo.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_27" style=""><span class="kwd">require</span><span class="pln"> </span><span class="str">'autoload.php'</span><span class="pun">;</span><span class="pln">
$animal </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Animal</span><span class="pun">;</span><span class="pln">
$animal</span><span class="pun">-&gt;</span><span class="pln">eats</span><span class="pun">(</span><span class="str">'slop'</span><span class="pun">);</span></pre>

<p>
	ملف <code>aquarium.php</code>:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_29" style=""><span class="kwd">require</span><span class="pln"> </span><span class="str">'autoload.php'</span><span class="pun">;</span><span class="pln">
$animal </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Animal</span><span class="pun">;</span><span class="pln">
$animal</span><span class="pun">-&gt;</span><span class="pln">eats</span><span class="pun">(</span><span class="str">'shrimp'</span><span class="pun">);</span></pre>

<p>
	وازن هذا المثال مع الأمثلة الأخرى، ولاحظ كيف استبدلنا التعليمة <code>require "Animal.php‎"‎</code> بالتعليمة <code>require "autoload.php"‎</code>، مازلنا نضمن الملف الخارجي في وقت التنفيذ لكن بدلًا من تضمين تعريف صنف معين نضمّن منطق يمكن أن يحتوي على أي صنف وهذا يسهّل عملية التطوير،إذ نكتب تعليمة <code>require</code> واحدة لكل الأصناف بدلًا من كتابتها لكل صنف على حدة.
</p>

<p>
	يحدث السحر باستخدام <a data-ss1616977283="1" href="%E2%80%8Fhttps://www.php.net/manual/en/function.spl-autoload-register.php" rel="">spl_autoload_register</a>، إذ تأخذ هذه الدالة مغلِّف وتضيفه إلى رتل من المغلِّفات، عندما تصادف PHP صنفًا ليس له تعريف فإنها تعطي اسم الصنف إلى كل مغلِّف في الرتل، إذا وِجد الصنف بعد استدعاء مغلِّف ما فإنّ PHP تعود إلى عملها السابق، وإذا لم يوجد الصنف بعد تجربة كامل الرتل تتعطل PHP وتطلق الخطأ "Class 'Whatever' not found.‎"
</p>

<h2>
	التحميل التلقائي مع المُنشِئ
</h2>

<p>
	يولِّد المُنشئ الملف <code>vendor/autoload.php</code>، يمكنك تضمين هذا الملف ببساطة وستحصل على التحميل التلقائي مجانًا.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_31" style=""><span class="kwd">require</span><span class="pln"> __DIR__ </span><span class="pun">.</span><span class="pln"> </span><span class="str">'/vendor/autoload.php'</span><span class="pun">;</span></pre>

<p>
	وهذا يجعل العمل مع اعتماديات من طرف ثالث (third-party dependencies) سهل جدًا، ويمكنك أن تضيف أيضًا شيفرتك الخاصة إلى المحمِّل التلقائي بإضافة قسم تحميل تلقائي إلى <code>composer.json</code>.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_33" style=""><span class="pun">{</span><span class="pln">
    </span><span class="str">"autoload"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="str">"psr-4"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="str">"YourApplicationNamespace\\"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"src/"</span><span class="pun">}</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تحدد في هذا القسم رابط التحميل التلقائي، يربط هذا المثال <a data-ss1616977283="1" href="%E2%80%8Fhttps://www.php-fig.org/psr/psr-4/" rel="">PSR-4</a> فضاء اسم إلى مجلد، يبقى المجلد <code>‎/src</code> في المجلد الجذر لمشاريعك في نفس المستوى الموجود فيه المجلد <code>‎/vendor</code>، يمكن أن يكون لديك اسم الملف <code>src/Foo.php</code> مثلًا والذي يحتوي على الصنف <code>YourApplicationNamespace\Foo</code>.
</p>

<p>
	<strong>ملاحظة:</strong> بعد إضافة مداخل جديدة إلى قسم التحميل التلقائي يجب إعادة تنفيذ الأمر <a data-ss1616977283="1" href="%E2%80%8Fhttps://getcomposer.org/doc/03-cli.md#dump-autoload" rel="">dump-autoload</a> لإعادة توليد وتحديث الملف <code>vendor/autoload.php</code> بالمعلومات الجديدة.
</p>

<p>
	يدعم المُنشئ التحميل التلقائي للمعيار PSR-0 و<code>classmap</code> و<code>files</code> بالإضافة إلى PSR-4، يمكنك الاطلاع على <a data-ss1616977283="1" href="https://getcomposer.org/doc/04-schema.md#autoload" rel="external nofollow">مرجع التحميل التلقائي</a> لمزيد من المعلومات.
</p>

<p>
	عند تضمين الملف <code>vendor/autoload.php</code> ستُرجع نسخة من المحمِّل التلقائي للمُنشئ، يمكنك تخزين القيمة المُرجعة من استدعاء التضمين في متغير وإضافة المزيد من فضاءات الأسماء، يمكن أن يكون هذا مفيدًا في التحميل التلقائي للأصناف في مجموعة الاختبار، مثال:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_35" style=""><span class="pln">$loader </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">'/vendor/autoload.php'</span><span class="pun">;</span><span class="pln">
$loader</span><span class="pun">-&gt;</span><span class="pln">add</span><span class="pun">(</span><span class="str">'Application\\Test\\'</span><span class="pun">,</span><span class="pln"> __DIR__</span><span class="pun">);</span></pre>

<h2>
	إنشاء ملفات PDF في PHP
</h2>

<h3>
	مكتبة PDFlib
</h3>

<p>
	تتطلب الشيفرة التالية استخدام مكتبة <a data-ss1616977283="1" href="%E2%80%8Fhttps://www.php.net/manual/en/ref.pdf.php" rel="">PDFlib</a> لتعمل بشكلٍ صحيح.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_37" style=""><span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// تهيئة كائن جديد</span><span class="pln">
$pdf </span><span class="pun">=</span><span class="pln"> pdf_new</span><span class="pun">();</span><span class="pln">

</span><span class="com">// ‫إنشاء ملف pdf فارغ جديد</span><span class="pln">
pdf_begin_document</span><span class="pun">(</span><span class="pln">$pdf</span><span class="pun">);?</span><span class="pln">
    </span><span class="com">// ضبط معلومات الملف</span><span class="pln">
    pdf_set_info</span><span class="pun">(</span><span class="pln">$pdf</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">"John Doe"</span><span class="pun">);</span><span class="pln">
    pdf_set_info</span><span class="pun">(</span><span class="pln">$pdf</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">"HelloWorld"</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// تحديد طول وعرض الصفحة</span><span class="pln">
    pdf_begin_page</span><span class="pun">(</span><span class="pln">$pdf</span><span class="pun">,</span><span class="pln"> </span><span class="pun">(</span><span class="lit">72</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">8.5</span><span class="pun">),</span><span class="pln"> </span><span class="pun">(</span><span class="lit">72</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">11</span><span class="pun">));</span><span class="pln">

        </span><span class="com">// تحميل خط</span><span class="pln">
        $font </span><span class="pun">=</span><span class="pln"> pdf_findfont</span><span class="pun">(</span><span class="pln">$pdf</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Times-Roman"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"host"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln">
        </span><span class="com">// ضبط الخط</span><span class="pln">
        pdf_setfont</span><span class="pun">(</span><span class="pln">$pdf</span><span class="pun">,</span><span class="pln"> $font</span><span class="pun">,</span><span class="pln"> </span><span class="lit">48</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// تعيين موضع النص</span><span class="pln">
        pdf_set_text_pos</span><span class="pun">(</span><span class="pln">$pdf</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">,</span><span class="pln"> </span><span class="lit">700</span><span class="pun">);</span><span class="pln">

        </span><span class="com">// طباعة النص إلى الموضع المحدد</span><span class="pln">
        pdf_show</span><span class="pun">(</span><span class="pln">$pdf</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Hello_World!"</span><span class="pun">);</span><span class="pln">

    </span><span class="com">// نهاية الصفحة</span><span class="pln">
    pdf_end_page</span><span class="pun">(</span><span class="pln">$pdf</span><span class="pun">);</span><span class="pln">

</span><span class="com">// إغلاق الكائن</span><span class="pln">
pdf_end_document</span><span class="pun">(</span><span class="pln">$pdf</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"> pdf_get_buffer</span><span class="pun">(</span><span class="pln">$pdf</span><span class="pun">);</span><span class="pln">

</span><span class="com">// ‫إيجاد طول ملف PDF وتعيين اسم للملف</span><span class="pln">
$length </span><span class="pun">=</span><span class="pln"> strlen</span><span class="pun">(</span><span class="pln">$document</span><span class="pun">);</span><span class="pln"> $filename </span><span class="pun">=</span><span class="pln"> </span><span class="str">"HelloWorld.pdf"</span><span class="pun">;</span><span class="pln">

header</span><span class="pun">(</span><span class="str">"Content-Type:application/pdf"</span><span class="pun">);</span><span class="pln">
header</span><span class="pun">(</span><span class="str">"Content-Length:"</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $length</span><span class="pun">);</span><span class="pln">
header</span><span class="pun">(</span><span class="str">"Content-Disposition:inline; filename="</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> $filename</span><span class="pun">);</span><span class="pln">

</span><span class="com">// إرسال الملف إلى المتصفح</span><span class="pln">
echo</span><span class="pun">(</span><span class="pln">$document</span><span class="pun">);</span><span class="pln">

</span><span class="com">// مسح الذاكرة</span><span class="pln">
unset</span><span class="pun">(</span><span class="pln">$document</span><span class="pun">);</span><span class="pln"> pdf_delete</span><span class="pun">(</span><span class="pln">$pdf</span><span class="pun">);</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<h3>
	مكتبة YAML
</h3>

<h4>
	تثبيت الإضافة YAML
</h4>

<p>
	لا تأتي إضافة YAML مع تثبيت PHP القياسي، بل يجب تثبيتها كإضافة PECL، ويمكن القيام بذلك في لينوكس/يونكس ببساطة:
</p>

<pre class="ipsCode">pecl install yaml
</pre>

<p>
	لاحظ أنّ الحزمة <code>libyaml-dev</code> يجب أن تكون مثبتة على النظام لأنّ حزمة PECL هي مجرد غلاف لاستدعاءات libYAML.
</p>

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

<h4>
	استخدام YAML لتخزين إعدادات التطبيق
</h4>

<p>
	توفر مكتبة <a data-ss1616977283="1" href="%E2%80%8Fhttps://yaml.org/" rel="">YAML</a> طريقةً لتخزين البيانات المهيكلة، يمكن أن تكون البيانات مجموعة بسيطة من الأزواج اسم-قيمة أو بيانات هرمية معقدة مع قيم أو قد تكون مصفوفات.
</p>

<p>
	بفرض لدينا ملف YAML التالي:
</p>

<pre class="ipsCode">database:
    driver: mysql
    host: database.mydomain.com
    port: 3306
    db_name: sample_db
    user: myuser
    password: Passw0rd
debug: true
country: us
</pre>

<p>
	بفرض أننا حفظناه كملف <code>config.yaml</code>، لقراءة هذا الملف باستخدام PHP نستخدم الشيفرة التالية:
</p>

<pre class="ipsCode">$config = yaml_parse_file('config.yaml');
print_r($config);
</pre>

<p>
	سينتج الخرج التالي:
</p>

<pre class="ipsCode">Array
(
    [database] =&gt; Array
    (
        [driver] =&gt; mysql
        [host] =&gt; database.mydomain.com
        [port] =&gt; 3306
        [db_name] =&gt; sample_db
        [user] =&gt; myuser
        [password] =&gt; Passw0rd
    )
    [debug] =&gt; 1
    [country] =&gt; us
)
</pre>

<p>
	يمكن الآن استخدام معاملات الإعدادات ببساطة باستخدام عناصر المصفوفة:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1270_41" style=""><span class="pln">$dbConfig </span><span class="pun">=</span><span class="pln"> $config</span><span class="pun">[</span><span class="str">'database'</span><span class="pun">];</span><span class="pln">

$connectString </span><span class="pun">=</span><span class="pln"> $dbConfig</span><span class="pun">[</span><span class="str">'driver'</span><span class="pun">]</span><span class="pln">
    </span><span class="pun">.</span><span class="pln"> </span><span class="str">":host={$dbConfig['host']}"</span><span class="pln">
    </span><span class="pun">.</span><span class="pln"> </span><span class="str">":port={$dbConfig['port']}"</span><span class="pln">
    </span><span class="pun">.</span><span class="pln"> </span><span class="str">":dbname={$dbConfig['db_name']}"</span><span class="pln">
    </span><span class="pun">.</span><span class="pln"> </span><span class="str">":user={$dbConfig['user']}"</span><span class="pln">
    </span><span class="pun">.</span><span class="pln"> </span><span class="str">":password={$dbConfig['password']}"</span><span class="pun">;</span><span class="pln">
$dbConnection </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> \PDO</span><span class="pun">(</span><span class="pln">$connectString</span><span class="pun">,</span><span class="pln"> $dbConfig</span><span class="pun">[</span><span class="str">'user'</span><span class="pun">],</span><span class="pln"> $dbConfig</span><span class="pun">[</span><span class="str">'password'</span><span class="pun">]);</span></pre>

<p>
	ترجمة -وبتصرف- للفصول [ Autoloading Primer - Create PDF files in PHP - YAML in PHP‎] من كتاب <a data-ss1616977283="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%A4%D9%82%D8%AA-cache-%D9%88%D9%85%D9%82%D8%A7%D8%A8%D8%B3-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-webscockets-%D9%81%D9%8A-php-r1180/" rel="">التخزين المؤقت (Cache) ومقابس الويب (Webscockets) في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1181</guid><pubDate>Sat, 10 Apr 2021 13:03:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x62E;&#x632;&#x64A;&#x646; &#x627;&#x644;&#x645;&#x624;&#x642;&#x62A; (Cache) &#x648;&#x645;&#x642;&#x627;&#x628;&#x633; &#x627;&#x644;&#x648;&#x64A;&#x628; (Webscockets) &#x641;&#x64A; PHP</title><link>https://academy.hsoub.com/programming/php/%D8%A7%D9%84%D8%AA%D8%AE%D8%B2%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%A4%D9%82%D8%AA-cache-%D9%88%D9%85%D9%82%D8%A7%D8%A8%D8%B3-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-webscockets-%D9%81%D9%8A-php-r1180/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_03/8.png.575dc4d062a57c12ccfdf19f4304866f.png" /></p>

<h2>
	التخزين المؤقت باستخدام memcache
</h2>

<p>
	Memcache هو نظام تخزين مؤقت للأغراض الموزعة يستخدم الزوج قيمة-مفتاح لتخزين البيانات الصغيرة، تحتاج أن تتأكد من أنّ Memcache مثبّتة قبل أن تستدعي شيفرتها في PHP، يمكنك القيام بذلك باستخدام تابع <code>class_exists</code> في PHP. بعد أن تتأكد من أنّها مثبّتة يمكنك الاتصال بنسخة خادم memcache.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_7" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">class_exists</span><span class="pun">(</span><span class="str">'Memcache'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $cache </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Memcache</span><span class="pun">();</span><span class="pln">
    $cache</span><span class="pun">-&gt;</span><span class="pln">connect</span><span class="pun">(</span><span class="str">'localhost'</span><span class="pun">,</span><span class="lit">11211</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="str">"Not connected to cache server"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ستتحقق هذه الشيفرة من أنّ محركات PHP للذاكرة Memcache مثبتة وتتصل إلى نسخة خادم memcache المُنفَّذ على الخادم المحلي. تعمل Memcache بشكلٍ خفي وتدعى memcached.
</p>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_9" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">class_exists</span><span class="pun">(</span><span class="str">'Memcache'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $cache </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Memcache</span><span class="pun">();</span><span class="pln">
    $cache</span><span class="pun">-&gt;</span><span class="pln">addServer</span><span class="pun">(</span><span class="str">'192.168.0.100'</span><span class="pun">,</span><span class="lit">11211</span><span class="pun">);</span><span class="pln">
    $cache</span><span class="pun">-&gt;</span><span class="pln">addServer</span><span class="pun">(</span><span class="str">'192.168.0.101'</span><span class="pun">,</span><span class="lit">11211</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

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

<ul>
<li>
		تخزين البيانات: إضافة بيانات جديدة إلى خادم memcached.
	</li>
	<li>
		الحصول على البيانات: جلب البيانات من خادم memcached.
	</li>
	<li>
		حذف البيانات: حذف بيانات موجودة سابقًا على خادم memcached.
	</li>
</ul>
<h3>
	تخزين البيانات
</h3>

<p>
	يملك كائن الصنف memcached أو <code>‎$cache</code> التابع <code>set</code> الذي يأخذ المعاملات (المفتاح والقيمة والوقت) لحفظ قيمة من أجل زمن الحياة (ttl).
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_11" style="">
<span class="pln">$cache</span><span class="pun">-&gt;</span><span class="kwd">set</span><span class="pun">(</span><span class="pln">$key</span><span class="pun">,</span><span class="pln"> $value</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> $ttl</span><span class="pun">);</span></pre>

<p>
	<code>‎$ttl</code> أو زمن الحياة هنا مقدرًا بالثانية هو الزمن الذي تحتاجه memcache لتخزين الزوج على الخادم.
</p>

<h3>
	الحصول على البيانات
</h3>

<p>
	يملك كائن الصنف memcached أو <code>‎$cache</code> التابع <code>get</code> الذي يأخذ مفتاح ويعيد القيمة المقابلة.
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_13" style="">
<span class="pln">$value </span><span class="pun">=</span><span class="pln"> $cache</span><span class="pun">-&gt;</span><span class="kwd">get</span><span class="pun">(</span><span class="pln">$key</span><span class="pun">);</span></pre>

<p>
	إذا لم توجد قيمة مقابلة للمفتاح ستُرجع القيمة <code>null</code>.
</p>

<h3>
	حذف البيانات
</h3>

<p>
	قد تحتاج أحيانًا إلى حذف بعض القيم من الذاكرة المخبئية، يملك كائن الصنف memcached أو <code>‎$cache</code> التابع <code>delete</code> الذي يُستخدم لهذا الغرض:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_15" style="">
<span class="pln">$cache</span><span class="pun">-&gt;</span><span class="kwd">delete</span><span class="pun">(</span><span class="pln">$key</span><span class="pun">);</span></pre>

<h3>
	سيناريو بسيط للتخزين المؤقت
</h3>

<p>
	بفرض لدينا مدونة بسيطة، ستوجد عدة منشورات في صفحة الهبوط تُجلب من قاعدة البيانات عند كل تحميل للصفحة، يمكننا استخدام memcached لتخزين المنشورات وذلك لتقليل استعلامات sql، إليك تنفيذ بسيط لذلك:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_17" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">class_exists</span><span class="pun">(</span><span class="str">'Memcache'</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    $cache </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Memcache</span><span class="pun">();</span><span class="pln">
    $cache</span><span class="pun">-&gt;</span><span class="pln">connect</span><span class="pun">(</span><span class="str">'localhost'</span><span class="pun">,</span><span class="lit">11211</span><span class="pun">);</span><span class="pln">
    </span><span class="kwd">if</span><span class="pun">((</span><span class="pln">$data </span><span class="pun">=</span><span class="pln"> $cache</span><span class="pun">-&gt;</span><span class="kwd">get</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="kwd">null</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="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// فُقدت ذاكرة التخزين المؤقت، الاستعلام من قاعدة البيانات وحفظ النتائج إلى القاعدة</span><span class="pln">
        </span><span class="com">// ‫بفرض ‎$posts مصفوفة المنشورات المُستعادة من قاعدة البيانات</span><span class="pln">
        $cache</span><span class="pun">-&gt;</span><span class="kwd">set</span><span class="pun">(</span><span class="str">'posts'</span><span class="pun">,</span><span class="pln"> $posts</span><span class="pun">,</span><span class="lit">0</span><span class="pun">,</span><span class="pln">$ttl</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">die</span><span class="pun">(</span><span class="str">"Error while connecting to cache server"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	التخزين المؤقت باستخدام APC
</h2>

<p>
	ذاكرة التخزين المؤقت البديلة في PHP (‏APC) مجانية وشيفرة تشغيل مفتوحة لذاكرة التخزين المؤقت في PHP، هدفها توفير إطار عمل مجاني ومفتوح وقوي لذاكرة التخزين المؤقت وتحسين شيفرة PHP الوسيطة.
</p>

<p>
	طريقة <a data-ss1616976718="1" data-ss1616976917="1" href="https://www.php.net/manual/en/apc.installation.php" rel="external nofollow">التثبيت</a>:
</p>

<pre class="ipsCode">
sudo apt-get install php-apc
sudo /etc/init.d/apache2 restart
</pre>

<p>
	إضافة ذاكرة التخزين المؤقت:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_20" style="">
<span class="pln">apc_add </span><span class="pun">(</span><span class="pln">$key</span><span class="pun">,</span><span class="pln"> $value </span><span class="pun">,</span><span class="pln"> $ttl</span><span class="pun">);</span><span class="pln">
$key </span><span class="pun">=</span><span class="pln"> unique cache key
$value </span><span class="pun">=</span><span class="pln"> cache value
$ttl </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Time</span><span class="pln"> </span><span class="typ">To</span><span class="pln"> </span><span class="typ">Live</span><span class="pun">;</span></pre>

<p>
	حذف ذاكرة التخزين المؤقت:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_24" style="">
<span class="pln">apc_delete</span><span class="pun">(</span><span class="pln">$key</span><span class="pun">);</span></pre>

<p>
	مثال عن ضبط الذاكرة المخبئية:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_26" style="">
<span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">apc_exists</span><span class="pun">(</span><span class="pln">$key</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    echo </span><span class="str">"Key exists: "</span><span class="pun">;</span><span class="pln">
    echo apc_fetch</span><span class="pun">(</span><span class="pln">$key</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">
    echo </span><span class="str">"Key does not exist"</span><span class="pun">;</span><span class="pln">
    apc_add </span><span class="pun">(</span><span class="pln">$key</span><span class="pun">,</span><span class="pln"> $value </span><span class="pun">,</span><span class="pln"> $ttl</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<a data-ss1616976718="1" data-ss1616976917="1" href="https://stackoverflow.com/questions/1794342/memcache-vs-apc-for-a-single-server-site-data-caching" rel="external nofollow">الأداء</a>: APC أسرع من Memcached ب <a data-ss1616976718="1" data-ss1616976917="1" href="https://www.percona.com/blog/2006/09/27/apc-or-memcached/" rel="external nofollow">‏5‏ مرات</a> تقريبًا.
</p>

<h2>
	مقابس الويب (Webscockets)
</h2>

<p>
	ينفّذ استخدام إضافة المقبس (socket) واجهة منخفضة المستوى لدوال اتصال المقبس بالاعتماد على مقابس BSD (‏Berkeley Software Distribution) الشائعة، مما يوفر إمكانية العمل كخادم مقبس وعميل.
</p>

<h3>
	خادم TCP/IP بسيط
</h3>

<p>
	يمكنك أن تجد <a data-ss1616976718="1" data-ss1616976917="1" href="https://www.php.net/manual/en/sockets.examples.php" rel="external nofollow">هنا</a> مثالًا بسيطًا يعتمد على توثيق PHP الرسمي.
</p>

<p>
	أنشئ سكربت مقبس ويب يستمع إلى المنفذ 5000 باستخدام putty والطرفية لتنفيذ الأمر <code>telnet 127.0.0.1 5000</code> (المضيف المحلي)، يرد هذا السكربت بالرسالة التي أرسلتها (كتعقب عكسي):
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_28" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="com">// تعطيل المهلة</span><span class="pln">
set_time_limit</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln"> 
</span><span class="com">// تعطيل التخزين المؤقت للخرج</span><span class="pln">
ob_implicit_flush</span><span class="pun">();</span><span class="pln"> 

</span><span class="com">// الإعدادات</span><span class="pln">
$address </span><span class="pun">=</span><span class="pln"> </span><span class="str">'127.0.0.1'</span><span class="pun">;</span><span class="pln">
$port </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5000</span><span class="pun">;</span><span class="pln">

</span><span class="com">// (1)</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">$socket </span><span class="pun">=</span><span class="pln"> socket_create</span><span class="pun">(</span><span class="pln">AF_INET</span><span class="pun">,</span><span class="pln"> SOCK_STREAM</span><span class="pun">,</span><span class="pln"> SOL_TCP</span><span class="pun">))</span><span class="pln"> </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">
    echo </span><span class="str">"Couldn't create socket"</span><span class="pun">.</span><span class="pln">socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</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="com">// (2)</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">socket_bind</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> $address</span><span class="pun">,</span><span class="pln"> $port</span><span class="pun">)</span><span class="pln"> </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">
    echo </span><span class="str">"Bind Error "</span><span class="pun">.</span><span class="pln">socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(</span><span class="pln">$sock</span><span class="pun">))</span><span class="pln"> </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="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">socket_listen</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </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">
    echo </span><span class="str">"Listen Failed "</span><span class="pun">.</span><span class="pln">socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">do</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">$msgsock </span><span class="pun">=</span><span class="pln"> socket_accept</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">))</span><span class="pln"> </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">
        echo </span><span class="str">"Error: socket_accept: "</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</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="com">/* إرسال رسالة ترحيب */</span><span class="pln">
    $msg </span><span class="pun">=</span><span class="pln"> </span><span class="str">"\nPHP Websocket \n"</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// الاستماع إلى دخل المستخدم</span><span class="pln">
    </span><span class="kwd">do</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="kwd">false</span><span class="pln"> </span><span class="pun">===</span><span class="pln"> </span><span class="pun">(</span><span class="pln">$buf </span><span class="pun">=</span><span class="pln"> socket_read</span><span class="pun">(</span><span class="pln">$msgsock</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2048</span><span class="pun">,</span><span class="pln">         PHP_NORMAL_READ</span><span class="pun">)))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            echo </span><span class="str">"socket read error: "</span><span class="pun">.</span><span class="pln">socket_strerror</span><span class="pun">(</span><span class="pln">socket_last_error</span><span class="pun">(</span><span class="pln">$msgsock</span><span class="pun">))</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">break</span><span class="pln"> </span><span class="lit">2</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">$buf </span><span class="pun">=</span><span class="pln"> trim</span><span class="pun">(</span><span class="pln">$buf</span><span class="pun">))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">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">
        $talkback </span><span class="pun">=</span><span class="pln"> </span><span class="str">"PHP: You said '$buf'.\n"</span><span class="pun">;</span><span class="pln">
        socket_write</span><span class="pun">(</span><span class="pln">$msgsock</span><span class="pun">,</span><span class="pln"> $talkback</span><span class="pun">,</span><span class="pln"> strlen</span><span class="pun">(</span><span class="pln">$talkback</span><span class="pun">));</span><span class="pln">
        </span><span class="com">// طباعة الرسالة على الطرفية</span><span class="pln">
        echo </span><span class="str">"$buf\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
    socket_close</span><span class="pun">(</span><span class="pln">$msgsock</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">);</span><span class="pln">
socket_close</span><span class="pun">(</span><span class="pln">$socket</span><span class="pun">);</span><span class="pln">
</span><span class="pun">?&gt;</span></pre>

<p>
	في الموضع (1) لدينا الدالة <code>socket_create</code> لها الشكل العام <code>( int $domain , int $type , int $protocol )</code>:
</p>

<ul>
<li>
		يمكن أن يكون المتغير <code>‎$domain</code> هو <code>AF_INET</code> أو <code>AF_INET6</code> من أجل <code>IPV6</code> أو <code>AF_UNIX</code> من أجل بروتوكول الاتصال المحلي.
	</li>
	<li>
		يمكن أن يكون المتغير <code>‎$protocol</code> إما <code>SOL_TCP</code> أو <code>SOL_UDP</code> ‏(TCP/UDP) تعيد هذه الدالة القيمة <code>true</code> في حالة النجاح.
	</li>
</ul>
<p>
	في الموضع (2) نستخدم الدالة <code>socket_bind</code> التي تربط هذه الدالة المقبس ليستمع إلى عنوان ومنفذ محددين ولها الشكل العام:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3508_6" style="">
<span class="pun">‎</span><span class="pln">socket_bind </span><span class="pun">(</span><span class="pln"> resource $socket </span><span class="pun">,</span><span class="pln"> </span><span class="kwd">string</span><span class="pln"> $address </span><span class="pun">[,</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> $port </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></pre>

<h3>
	استيثاق HTTP
</h3>

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

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_3114_30" style="">
<span class="pun">&lt;?</span><span class="pln">php
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">isset</span><span class="pun">(</span><span class="pln">$_SERVER</span><span class="pun">[</span><span class="str">'PHP_AUTH_USER'</span><span class="pun">]))</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'WWW-Authenticate: Basic realm="My Realm"'</span><span class="pun">);</span><span class="pln">
    header</span><span class="pun">(</span><span class="str">'HTTP/1.0 401 Unauthorized'</span><span class="pun">);</span><span class="pln">
    echo </span><span class="str">'Text to send if user hits Cancel button'</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">exit</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

echo </span><span class="str">"&lt;p&gt;Hello {$_SERVER['PHP_AUTH_USER']}.&lt;/p&gt;"</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"> $_SERVER</span><span class="pun">[</span><span class="str">'PHP_AUTH_USER'</span><span class="pun">];</span><span class="pln"> 
echo </span><span class="str">"&lt;p&gt;You entered {$_SERVER['PHP_AUTH_PW']} as your password.&lt;/p&gt;"</span><span class="pun">;</span><span class="pln">

</span><span class="com">// ‫حفظ كلمة المرور (يمكن إضافة التشفير اختياريًا)</span><span class="pln">
$pass </span><span class="pun">=</span><span class="pln"> $_SERVER</span><span class="pun">[</span><span class="str">'PHP_AUTH_PW'</span><span class="pun">];</span><span class="pln"> </span><span class="com">//Save the password(optionally add encryption)!</span><span class="pln">
</span><span class="pun">?&gt;</span><span class="pln">
// ‫صفحة html</span></pre>

<p>
	ترجمة -وبتصرف- للفصول [Cache - WebSockets - HTTP Authentication] من كتاب <a data-ss1616976718="1" data-ss1616976917="1" href="https://goalkicker.com/PHPBook/" rel="external nofollow">PHP Notes for Professionals book</a>
</p>

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

<ul>
<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/php/%D8%AA%D9%85%D9%87%D9%8A%D8%AF-%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%AA%D9%8A-%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84-%D9%88%D8%A7%D9%84%D8%AA%D9%86%D8%B2%D9%8A%D9%84-%D8%A7%D9%84%D8%AA%D9%84%D9%82%D8%A7%D8%A6%D9%8A-%D9%81%D9%8A-php-r1181/" rel="">تمهيد لعمليتي التحميل والتنزيل التلقائي في PHP</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A2%D9%84%D8%A9-machine-learning-%D9%81%D9%8A-php-r1179/" rel=""> مدخل إلى تعلم الآلة (Machine learning) في PHP</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1180</guid><pubDate>Tue, 06 Apr 2021 08:54:56 +0000</pubDate></item></channel></rss>
