3. مبانی PHP
3.1. ساختار دایرکتوری اسکریپت

3.2. پیکربندی PHP
PHP از طریق یک فایل متنی به نام [php.ini] از پیش پیکربندی شده است. تمام این تنظیمات را میتوان بهصورت برنامهای تغییر داد. پیکربندی PHP تأثیر قابلتوجهی بر اجرای اسکریپت دارد. بنابراین درک آن اهمیت دارد. اسکریپت زیر، [phpinfo.php]، به شما این امکان را میدهد:
نظرات
- خط ۳: تابع [phpinfo] پیکربندی PHP را نمایش میدهد؛
نتایج اجرا
تابع [phpinfo] در اینجا بیش از ۸۰۰ خط پیکربندی را نمایش میدهد. ما روی آنها توضیحی نخواهیم داد، زیرا بیشترشان به کاربردهای پیشرفته PHP مربوط میشوند. یک خط مهم، خط ۱۳ بالا است: این خط مشخص میکند که کدام فایل [php.ini] برای پیکربندی فایل PHP که برای اجرای اسکریپتهای خود استفاده خواهید کرد، به کار رفته است. اگر میخواهید پیکربندی اجرای PHP را تغییر دهید، این فایلی است که باید ویرایش کنید. در این فایل توضیحات متعددی وجود دارد که نقش گزینههای پیکربندی مختلف را توضیح میدهد.
3.3. یک مثال اول
3.3.1. کد
در زیر برنامهای با نام [bases-01.php] آمده است که ویژگیهای پایهای PHP را نشان میدهد.
<?php
//این یک نظر است
// متغیر بدون اعلام قبلی استفاده شده است
$nom = "dupont";
//یک نمایش صفحه
print "nom=$nom\n";
// یک آرایه با عناصر از انواع مختلف
$tableau = array("un", "deux", 3, 4);
// تعداد عناصر آن
$n = count($tableau);
//یک حلقه
for ($i = 0; $i < $n; $i++) {
print "tableau[$i]=$tableau[$i]\n";
}
// ابتداییسازی دو متغیر با محتویات یک آرایه
list($chaine1, $chaine2) = array("chaine1", "chaine2");
//الحاق دو رشته
$chaine3 = $chaine1 . $chaine2;
// نمایش نتیجه
print "[$chaine1,$chaine2,$chaine3]\n";
// استفاده از یک تابع
affiche($chaine1);
// نوع یک متغیر ممکن است مشخص باشد
afficheType("n", $n);
afficheType("chaine1", $chaine1);
afficheType("tableau", $tableau);
// نوع یک متغیر میتواند در زمان اجرا تغییر کند
$n = "a changé";
afficheType("n", $n);
// یک تابع میتواند یک نتیجه بازگرداند
$res1 = f1(4);
print "res1=$res1\n";
//یک تابع میتواند یک آرایه از مقادیر را بازگرداند
list($res1, $res2, $res3) = f2();
print "(res1,res2,res3)=[$res1,$res2,$res3]\n";
//این مقادیر میتوانستند در یک آرایه بازیابی شده باشند
$t = f2();
for ($i = 0; $i < count($t); $i++) {
print "t[$i]=$t[$i]\n";
}
// آزمایشها
for ($i = 0; $i < count($t); $i++) {
// فقط رشتهها را نمایش میدهد
if (getType($t[$i]) === "string") {
print "t[$i]=$t[$i]\n";
}
}
// عملگرهای مقایسه == و ===
if("2"==2){
print "avec l'opérateur ==, la chaîne 2 est égale à l'entier 2\n";
}else{
print "avec l'opérateur ==, la chaîne 2 n'est pas égale à l'entier 2\n";
}
if("2"===2){
print "avec l'opérateur ===, la chaîne 2 est égale à l'entier 2\n";
}
else{
print "avec l'opérateur ===, la chaîne 2 n'est pas égale à l'entier 2\n";
}
// آزمایشهای بیشتر
for ($i = 0; $i < count($t); $i++) {
// فقط اعداد صحیح بزرگتر از ۱۰ را نمایش میدهد
if (getType($t[$i]) === "integer" and $t[$i] > 10) {
print "t[$i]=$t[$i]\n";
}
}
//یک حلقه while
$t = [8, 5, 0, -2, 3, 4];
$i = 0;
$somme = 0;
while ($i < count($t) and $t[$i] > 0) {
print "t[$i]=$t[$i]\n";
$somme += $t[$i]; //$somme=$somme+$t[$i]
$i++; //$i=$i+1
}//در حالی که
print "somme=$somme\n";
//پایان برنامه
exit;
//----------------------------------
function affiche($chaine) {
//نمایش میدهد $chaine
print "chaine=$chaine\n";
}
//نمایش میدهد
//----------------------------------
function afficheType($name, $variable) {
// نوع $variable را نمایش میدهد
print "type[variable $" . $name . "]=" . getType($variable) . "\n";
}
//afficheType
//----------------------------------
function f1($param) {
// عدد ۱۰ را به $param اضافه میکند
return $param + 10;
}
//----------------------------------
function f2() {
// سه مقدار برمیگرداند
return array("un", 0, 100);
}
?>
نتایج:
nom=dupont
tableau[0]=un
tableau[1]=deux
tableau[2]=3
tableau[3]=4
[chaine1,chaine2,chaine1chaine2]
chaine=chaine1
type[variable $n]=integer
type[variable $chaine1]=string
type[variable $tableau]=array
type[variable $n]=string
res1=14
(res1,res2,res3)=[un,0,100]
t[0]=un
t[1]=0
t[2]=100
t[0]=un
avec l'opérateur ==, la chaîne 2 est égale à l'entier 2
avec l'opérateur ===, la chaîne 2 n'est pas égale à l'entier 2
t[2]=100
t[0]=8
t[1]=5
somme=13
توضیحات
- خط ۵: در PHP، نوع متغیرها اعلام نشده است. این متغیرها دارای نوع پویا هستند که ممکن است در طول زمان تغییر کند. $nom متغیری با شناسهی 'nom' را نشان میدهد؛
- خط ۷: برای خروجی گرفتن به صفحه، میتوانید از دستور print یا دستور echo استفاده کنید؛
- خط ۹: کلمه کلیدی array برای تعریف یک آرایه استفاده میشود. متغیر $nom[$i] نمایانگر عنصر $i از آرایه $tableau است؛
- خط ۱۱: تابع count($tableau) تعداد عناصر آرایه $tableau را برمیگرداند؛
- خطوط ۱۳–۱۵: یک حلقه. از آنجایی که این حلقه تنها شامل یک دستور است، استفاده از پرانتزهای منحنی اختیاری است. در بقیه این سند، ما صرفنظر از تعداد دستورات، همیشه از پرانتزهای منحنی استفاده خواهیم کرد؛
- خط ۱۴: رشتههای کاراکتری در علامتهای نقل قول " یا گیومه تک ' محصور میشوند. درون علامتهای نقل قول، متغیرهای $variable ارزیابی میشوند، اما درون گیومه تک این اتفاق نمیافتد؛
- خط ۱۷: تابع list به متغیرها اجازه میدهد تا در یک لیست گروهبندی شده و با یک عملیات تخصیص واحد، مقداری به آنها اختصاص داده شود. در اینجا، $chaine1="string1" و $chaine2="string2" هستند؛
- خط ۱۹: عملگر . عملگر الحاق رشتهها است؛
- خطوط ۸۳–۸۶: کلمه کلیدی function یک تابع را تعریف میکند. یک تابع ممکن است از طریق دستور return مقادیری را بازگرداند یا بازنگرداند. کد فراخوانی میتواند نتایج یک تابع را نادیده بگیرد یا بازیابی کند. یک تابع را میتوان در هر نقطهای از کد تعریف کرد.
- خط 92: تابع از پیش تعریف شده getType($variable) یک رشته کاراکتری را بازمیگرداند که نمایانگر نوع $variable است. این نوع ممکن است در طول زمان تغییر کند؛
- خط ۴۵: عملگر === یک مقایسهٔ سختگیرانه بین دو عنصر انجام میدهد: آنها باید از یک نوع باشند تا با هم مقایسه شوند. عملگر == سختگیری کمتری دارد: دو عنصر میتوانند بدون اینکه از یک نوع باشند، برابر باشند. این موضوع توسط دستورات در خطوط ۵۰–۶۰ نشان داده شده است. در مورد اپراتور ==، مقایسه پس از آنکه هر دو عنصر مورد مقایسه به یک نوع تبدیل شدند، انجام میشود. سپس تبدیلهای ضمنی رخ میدهند. نادیده گرفتن وجود این تبدیلهای ضمنی بسیار آسان است و در نتیجه ممکن است به نتایج غیرمنتظرهای رسید، مانند اینکه ببینید یک شرط زمانی که انتظار داشتید نادرست باشد، درست از آب درآمده است. برای اجتناب از این تله، ما بهطور سیستماتیک از عملگر مقایسه === استفاده خواهیم کرد؛
- خط ۶۴: عملگرهای بولی «or» و «!» نیز میتوانند استفاده شوند؛
- خط ۶۹: به جای نشانهٔ array() میتوانید از نشانهٔ [] برای مقداردهی اولیهٔ یک آرایه از PHP7 استفاده کنید؛
- خط ۸۰: تابع از پیش تعریفشده exit از اجرای اسکریپت جلوگیری میکند؛
- خط ۱۰۷: تگ ؟> پایان اسکریپت PHP را مشخص میکند. این تگ ضروری نیست. علاوه بر این، در یک محیط وب، اگر پس از آن فاصلهها یا خطوط جدید قرار گیرند، میتواند مشکلساز شود، زیرا تشخیص آنها دشوار است و در ویرایشگر متن قابل مشاهده نیستند. بنابراین، در بقیه این سند، ما این تگ را به طور سیستماتیک حذف خواهیم کرد؛
توجه: در این سند، از کلیدواژه [print] برای نمایش متن در کنسول استفاده خواهیم کرد. روش دیگری برای انجام همین کار استفاده از کلیدواژه [echo] است. تفاوتهای جزئی بین این دو کلیدواژه وجود دارد، اما در زمینهٔ این سند هیچ تفاوتی نخواهد بود. بنابراین اگر ترجیح میدهید از [echo] استفاده کنید، حتماً این کار را انجام دهید.
3.3.2. استفاده از NetBeans
NetBeans هشدارهای مختلفی را نمایش میدهد که بررسی آنها ارزش دارد. بیایید مثال اسکریپت [bases-01.php] را در نظر بگیریم:

در خط ۵، NetBeans هشداری صادر میکند که بیان میدارد این فایل با توصیه PSR-1 (توصیههای استاندارد شماره ۱ PHP) مطابقت ندارد. توصیههای PSR برای تولید کد استاندارد طراحی شدهاند و بدین ترتیب تعاملپذیری و نگهداری کدی را که توسط افراد مختلف نوشته شده است، تسهیل میکنند. دریافت هشدارها میتواند آزاردهنده باشد اگر بخواهید عمداً از استانداردها انحراف کنید، برای مثال به این دلیل که تیم پروژه استانداردهای متفاوتی را پذیرفته است. آنچه میخواهید NetBeans بررسی کند – یا بررسی نکند – قابل پیکربندی است:

- در [5]، عناصری را که میخواهید با NetBeans بررسی کنید، پیدا خواهید کرد؛
- در [6]، سطح شدت اختصاصیافته به خطایی که توسط NetBeans گزارش میشود؛

در [7]، میتوانیم ببینیم که ما یک بررسی را درخواست کردهایم تا اطمینان حاصل شود که کد با توصیههای PSR-0 و PSR-1 مطابقت دارد. هیچکدام از این موارد اجباری نیست. در حین یادگیری زبان، توصیه میشود تا حد امکان گزینههای ارائهشده توسط NetBeans را بررسی کنید. این یک روش عالی برای یادگیری است. سپس میتوانید این بررسیهای NetBeans را با استانداردهای کدنویسی تیم پروژه خود تطبیق دهید.
بیایید به استانداردهای کدنویسی PSR-1 و [8, 9] نگاهی بیندازیم:
گزینه | بررسی |
| ثوابت کلاس MUST باید به صورت حروف بزرگ و با جداکنندههای زیرخطی (underscore) اعلام شوند. مثلاً: const TAUX_TVA |
| نام متدهایی مانند MUST باید درون camelCase() اعلام شوند. مثال: public function executeBatchImpots{} |
| نامهای ویژگی مانند SHOULD باید در $StudlyCaps، $camelCase یا $under_score (بهطور یکنواخت در یک دامنه) اعلام شوند مثلاً: public SalaireAnnuel (StudlyCaps), public salaireAnnuel (camelCase), public salaire_annuel (under_score) |
| یک فایل SHOULD نمادهای جدیدی را اعلام میکند و هیچ اثر جانبی دیگری ندارد، یا آن SHOULD منطقی را با اثرات جانبی اجرا میکند، اما SHOULD NOT هر دو را انجام میدهد. |
| نامهای نوع MUST باید در StudlyCaps اعلام شوند (کدی که برای 5.2.x و نسخههای قبلی SHOULD نوشته شده است، از قرارداد نامگذاری فضای نام Vendor_ برای پیشافزودن پیشوندها بر نام انواع استفاده میکند). هر نوع در یک فایل جداگانه قرار دارد و در یک فضای نام با حداقل یک سطح قرار دارد: نام فروشنده در سطح بالا. برای مثال: class EtudiantBoursier {} |
توصیه PSR-1 / 4 بیان میکند که یک فایل PHP باید شامل موارد زیر باشد:
- یا یک اعلان نوع (کلاسها، رابطها)؛
- یا کد اجرایی بدون اعلان انواع جدید؛
توصیههای PHP دیگری نیز وجود دارند که توسط NetBeans بررسی نمیشوند: PSR-3, PSR-4, PSR-6، PSR-7 و PSR-13.
بهمنظور سادگی، همه مثالهای این سند با توصیه PSR-1 مطابقت ندارند، زیرا این امر مستلزم تقسیم کد کلاسها و اینترفیسها به فایلهای جداگانه است که برای مثالهای پایه بسیار دستوپاگیر است. بنابراین، قرار دادن همه چیز در یک فایل واحد آسانتر است. برای اپلیکیشن مثالی ارائهشده بهعنوان موضوع اصلی این سند، ما تلاش کردهایم تا حد امکان به توصیه PSR-1 پایبند باشیم.
برخی هشدارهای NetBeans به یک خطای احتمالی اشاره میکنند:

هشدار [Unitialized Variables] نشاندهنده یک خطای محتمل، که اغلب یک اشتباه تایپی در نام یک متغیر است. همین امر در مورد هشدار [Unused Variables] نیز صدق میکند.
در نهایت، توصیه میشود تمام هشدارهای NetBeans را که با یک پنل در حاشیه سمت چپ کد و یک خط زرد در حاشیه سمت راست نشان داده میشوند، بررسی کنید:


3.4. دامنه متغیر
3.4.1. مثال ۱
اسکریپت [bases-02.php] به شرح زیر است:
<?php
// دامنهٔ متغیرها
function f1() {
// متغیر سراسری $i استفاده میشود
global $i;
$i++;
$j = 10;
print "f1[i,j]=[$i,$j]\n";
}
function f2() {
// متغیر سراسری $i استفاده میشود
global $i;
$i++;
$j = 20;
print "f2[i,j]=[$i,$j]\n";
}
function f3() {
//یک متغیر محلی $i استفاده میشود
$i = 4;
$j = 30;
print "f3[i,j]=[$i,$j]\n";
}
// آزمایشها
$i = 0;
$j = 0; // این دو متغیر برای تابع f ناشناختهاند
// مگر اینکه صراحتاً آنها را با دستور `global` اعلام کند
// که میخواهد از آنها استفاده کند
f1();
f2();
f3();
print "test[i,j]=[$i,$j]\n";
نتایج:
نظرات
- خطوط ۲۹–۳۰: دو متغیر $i و $j را در برنامهٔ اصلی تعریف کنید. این متغیرها در داخل توابع شناسایی نمیشوند. بنابراین، در خط ۹، متغیر $j در تابع f1 یک متغیر محلی تابع f1 است و با متغیر $j در برنامه اصلی متفاوت است. یک تابع میتواند از طریق کلمه کلیدی «global» به متغیر $variable در برنامه اصلی دسترسی داشته باشد؛
- در خط ۷، این عبارت به متغیر سراسری $i در برنامه اصلی اشاره میکند؛
3.4.2. مثال ۳
اسکریپت [bases-03.php] به شرح زیر است:
<?php
// دامنه یک متغیر در بلوکهای کد، سراسری است
$i = 0; {
$i = 4;
$i++;
}
print "i=$i\n";
نتایج:
توضیحات
در برخی زبانها، متغیری که درون کروشههای منحنی تعریف میشود، دامنهای محدود به آن کروشهها دارد: خارج از آنها قابل دسترسی نیست. نتایج بالا نشان میدهد که در PHP اینگونه نیست. متغیر $i که در خط ۵ درون کروشهها تعریف شده، همان متغیری است که در خطوط ۴ و ۸ بیرون از آنها استفاده شده است.
3.5. تغییرات نوع
متغیرها در PHP نوع ثابتی ندارند. این نوع ممکن است بسته به مقداری که به متغیر اختصاص داده میشود، در زمان اجرا تغییر کند. در عملیاتهای شامل دادههایی با انواع مختلف، تفسیرگر PHP تبدیلهای ضمنی را برای یکسانسازی نوع عملوندها انجام میدهد. این تبدیلهای ضمنی، اگر برای توسعهدهنده ناشناخته باشند، میتوانند منشأ خطاهایی باشند که ردیابی آنها دشوار است. در زیر اسکریپتی از [bases-04.php] آورده شده است که تبدیلهای ضمنی و صریح را نشان میدهد:
<?php
// نوعیابی سختگیرانه در ارسال پارامتر
declare(strict_types=1);
//تبدیلهای ضمنی نوع
// نوع --> بول
print "Conversion vers un booléen------------------------------\n";
showBool("abcd", "abcd");
showBool("", "");
showBool("[1, 2, 3]", [1, 2, 3]);
showBool("[]", []);
showBool("NULL", NULL);
showBool("0.0", 0.0);
showBool("0", 0);
showBool("4.6", 4.6);
function showBool(string $prefixe, $var) : void {
print "(bool) $prefixe : ";
//تبدیل $var به یک مقدار بولی بهطور خودکار در تست زیر انجام میشود
if ($var) {
print "true";
} else {
print "false";
}
print "\n";
}
توضیحات
- خط ۴: نیاز به بررسی دقیق نوع پارامترهای یک تابع هنگامی که نوع مشخص شده باشد؛
- خط ۱۸: هدف تابع [showBool] نشان دادن تبدیل ضمنی (خودکار) است که توسط تفسیرگر PHP هنگام نیاز به تبدیل یک مقدار از هر نوعی به یک مقدار بولی (خط ۲۱) انجام میشود؛
- خط ۱۸: پارامتر $var هیچ نوع مشخصی ندارد. بنابراین پارامتر واقعی میتواند از هر نوعی باشد. از سوی دیگر، پارامتر $prefixe باید از نوع string باشد. تابع showBool هیچ ارزشی بر نمیگرداند (void);
- خط ۲۱: در عبارت if($var)، مقدار $var باید به بولین تبدیل شود تا بتوان if را ارزیابی کرد. به طور شگفتآور، تفسیرگر PHP برای هر نوع مقداری که به آن داده میشود، یک نتیجه بازمیگرداند؛
- خطوط ۹–۱۶: مقدار پارامتر تابع برای [showBool] به ترتیب زیر خواهد بود:
- خط ۹: یک رشته غیرخالی: نتیجه TRUE (بزرگ/کوچک بودن حروف مهم نیست، TRUE=true);
- خط ۱۰: یک رشته خالی: نتیجه FALSE;
- خط ۱۱: یک آرایه غیرخالی: نتیجه TRUE;
- خط ۱۲: یک آرایه خالی: نتیجه FALSE;
- خط 14: عدد حقیقی 0: نتیجه FALSE;
- خط ۱۵: عدد صحیح ۰: نتیجه FALSE;
- خط ۱۶: یک عدد حقیقی (یا صحیح) غیر از ۰: نتیجه TRUE;
این امر با خروجیهای صفحه نمایش حاصل شده نشان داده میشود:
Conversion vers un booléen------------------------------
(bool) abcd : true
(bool) : false
(bool) [1, 2, 3] : true
(bool) [] : false
(bool) NULL : false
(bool) 0.0 : false
(bool) 0 : false
(bool) 4.6 : true
بیایید با کد اسکریپت ادامه دهیم:
//
//تبدیلهای ضمنی از رشته به نوع عددی
// رشته --> عدد
print "Conversion chaîne vers nombre------------------------------\n";
showNumber("12");
showNumber("45.67");
showNumber("abcd");
function showNumber(string $var) : void {
$nombre = $var + 1;
var_dump($nombre);
print "($var): $nombre\n";
}
توضیحات
- خط ۹: تابع [showNumber] یک پارامتر رشتهای را میپذیرد و هیچ نتیجهای بر نمیگرداند (void)؛
- خط ۱۰: این پارامتر در یک عملیات حسابداری استفاده میشود که باعث میشود تفسیرگر PHP تلاش کند $var را به یک عدد تبدیل کند؛
- خط ۵: رشته «12» را به عدد صحیح ۱۲ تبدیل میکند؛
- خط ۶: رشته «45.67» را به عدد حقیقی 45.67 تبدیل میکند؛
- خط ۷: یک هشدار صادر میکند اما همچنان رشته «abcd» را به عدد 0 تبدیل میکند؛
در اینجا نتایج اجرای برنامه آمده است:
بیایید با کد اسکریپت ادامه دهیم:
//تبدیلات صریح نوع
// به int
showInt("12.45");
showInt(67.8);
showInt(TRUE);
showInt(NULL);
function showInt($var) : void {
print "paramètre : ";
var_dump($var);
print "\n";
print "résultat de la conversion : ";
var_dump((int) $var);
print "\n";
}
توضیحات
- خط ۲۱: تابع [showInt] پارامتری از هر نوع را میپذیرد و هیچ نتیجهای بازنمیگرداند. این تابع در خط ۲۶ تلاش میکند پارامتر $var را به یک عدد صحیح تبدیل کند. بهطور کلی، برای تبدیل یک متغیر $var به نوع T، باید نوشت (T) $var، که در آن T میتواند باشد: int, integer, bool, boolean, float, double, real, string, array, object, unset;
- خط ۱۶: رشته «12.45» را به عدد صحیح ۱۲ تبدیل میکند؛
- خط ۱۷: عدد حقیقی ۶۷.۸ را به عدد صحیح ۶۷ تبدیل میکند؛
- خط ۱۸: مقدار بولین TRUE را به عدد صحیح ۱ تبدیل میکند (بولین FALSE به عدد صحیح ۰ تبدیل میشود)؛
- خط ۱۹: نشانگر NULL را به عدد صحیح ۰ تبدیل میکند؛
این موضوع در خروجیهای صفحه نمایش نشان داده شده است:
ما تحلیل خود را از اسکریپت با تبدیل صریح مقادیر به نوع </span>**<span style="color: #000000">float** ادامه میدهیم:
// به ممیز شناور
showFloat("12.45");
showFloat(67);
showFloat(TRUE);
showFloat(NULL);
function showFloat($var) : void {
print "paramètre : ";
var_dump($var);
print "\n";
print "résultat de la conversion : ";
var_dump((float) $var);
print "\n";
}
توضیحات
- خط ۳۵: تابع [showFloat] پارامتری از هر نوعی را میپذیرد و هیچ نتیجهای بر نمیگرداند؛
- خط ۴۰: مقدار این پارامتر صراحتاً به float تبدیل میشود؛
- خط ۳۰: رشته «12.45» به عدد حقیقی ۱۲.۴۵ تبدیل میشود؛
- خط ۳۱: عدد صحیح ۶۷ به عدد حقیقی ۶۷ تبدیل میشود؛
- خط ۳۲: مقدار بولی TRUE به عدد حقیقی ۱ تبدیل میشود (مقدار FALSE به عدد ۰ تبدیل میشود)؛
- خط ۳۳: نشانگر NULL به عدد حقیقی ۰ تبدیل میشود؛
این موضوع در خروجی صفحه نمایش نشان داده شده است:
ما بررسی خود از اسکریپت را با بررسی تبدیلها به نوع رشتهای ادامه میدهیم:
// به رشته
showstring(5);
showString(6.7);
showString(FALSE);
showString(NULL);
function showString($var) : void {
print "paramètre : ";
var_dump($var);
print "\n";
print "résultat de la conversion : ";
var_dump((string) $var);
print "\n";
}
- خط ۴۹: تابع [showString] پارامتری از هر نوعی را میپذیرد و هیچ نتیجهای بر نمیگرداند؛
- خط ۵۴: مقدار پارامتر به یک رشته تبدیل میشود؛
- خط ۴۴: عدد صحیح ۵ به رشته «۵» تبدیل خواهد شد؛
- خط ۴۵: عدد ممیزدار ۶.۷ به رشته «۶.۷» تبدیل خواهد شد؛
- خط ۴۶: مقدار بولی FALSE به یک رشته خالی تبدیل خواهد شد؛
- خط ۴۷: نشانگر NULL به یک رشته خالی تبدیل میشود؛
در اینجا نتایج صفحه نمایش آورده شده است:
3.6. آرایهها
3.6.1. آرایههای یکبعدی استاندارد
اسکریپت [bases-05.php] به شرح زیر است:
<?php
// آرایههای استاندارد
// ابتداییسازی
$tab1 = array(0, 1, 2, 3, 4, 5);
// تکرار - 1
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// تکرار - ۲
print "tab1 a " . count($tab1) . " éléments\n";
reset($tab1);
while (list($clé, $valeur) = each($tab1)) {
print "tab1[$clé]=$valeur\n";
}
// افزودن عناصر
$tab1[] = $i++;
$tab1[] = $i++;
// تکرار – ۳
print "tab1 a " . count($tab1) . " éléments\n";
$i = 0;
foreach ($tab1 as $élément) {
print "tab1[$i]=$élément\n";
$i++;
}
//حذف آخرین عنصر
array_pop($tab1);
//تکرار - ۴
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
//حذف اولین عنصر
array_shift($tab1);
// تکرار - ۵
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// افزودن به انتهای آرایه
array_push($tab1, -2);
// تکرار - ۶
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
//افزودن به ابتدای آرایه
array_unshift($tab1, -1);
//تکرار - ۷
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
نتایج:
tab1 a 6 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1 a 6 éléments
Deprecated: The each() function is deprecated. This message will be suppressed on further calls in C:\Data\st-2019\dev\php7\php5-exemples\exemples\exemple_04.php on line 14
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1 a 8 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1[7]=7
tab1 a 7 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1 a 6 éléments
tab1[0]=1
tab1[1]=2
tab1[2]=3
tab1[3]=4
tab1[4]=5
tab1[5]=6
tab1 a 7 éléments
tab1[0]=1
tab1[1]=2
tab1[2]=3
tab1[3]=4
tab1[4]=5
tab1[5]=6
tab1[6]=-2
tab1 a 8 éléments
tab1[0]=-1
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1[7]=-2
نظرات
برنامهٔ بالا عملیات مربوط به دستکاری یک آرایه از مقادیر را نشان میدهد. در PHP دو نشانه برای آرایهها وجود دارد:
آرایه ۱ یک آرایه نامیده میشود و آرایه ۲ یک دیکشنری یا آرایه asociative است که در آن عناصر به صورت کلید => مقدار نشان داده میشوند. نشانه $contraires["beau"] به مقداری که با کلید «beautiful» مرتبط است اشاره دارد. در این مورد، این مقدار رشته «ugly» است. آرایه 1 صرفاً یک نوع از دیکشنری است و میتواند به صورت زیر نوشته شود:
بنابراین ما داریم $tableau[2] = "three". در نهایت، تنها دیکشنریها وجود دارند. در مورد یک آرایه استاندارد از عناصر n، کلیدها اعداد صحیح در بازه [0,n-1] هستند.
- خط ۱۴: تابع each($tableau) برای تکرار روی یک دیکشنری استفاده میشود. در هر فراخوانی، یک جفت (کلید، مقدار) از دیکشنری بازمیگرداند. همانطور که در خط ۱۰ نتایج نشان داده شده است، تابع each اکنون در PHP 7 منسوخ شده است؛
- خط ۱۳: تابع reset($dictionnaire) تابع each را روی اولین زوج (کلید، مقدار) در دیکشنری تنظیم میکند.
- خط 14: حلقه while زمانی متوقف میشود که تابع each در پایان دیکشنری یک جفت خالی بازگرداند. یک تبدیل ضمنی در اینجا رخ میدهد: جفت خالی به بولین FALSE تبدیل میشود؛
- خط ۱۸: نشانه $tableau[]=value عنصر valeur را به عنوان آخرین عنصر $tableau اضافه میکند؛
- خط ۲۳: آرایه با استفاده از یک foreach پیمایش میشود. این عنصر نحوی اجازه میدهد تا یک دیکشنری – و در نتیجه یک آرایه – با استفاده از دو نحوی مختلف پیمایش شود:
سینتکس اول در هر تکرار یک جفت (clé,valeur) را بازمیگرداند، در حالی که سینتکس دوم تنها عنصر valeur را از دیکشنری بازمیگرداند.
- خط ۲۸: تابع array_pop($tableau) عنصر آخر را از $tableau حذف میکند؛
- خط ۳۵: تابع array_shift($tableau) اولین عنصر را از $tableau حذف میکند؛
- خط ۴۲: تابع array_push($tableau,value) عنصر آخر valeur را به $tableau اضافه میکند؛
- خط ۴۹: تابع array_unshift($tableau,value) عنصر valeur را به عنوان اولین عنصر $tableau اضافه میکند؛
3.6.2. واژهنامه یا آرایهٔ انجمنی
اسکریپت [bases-06.php] به شرح زیر است:
<?php
// فرهنگها
$conjoints = ["Pierre" => "Gisèle", "Paul" => "Virginie", "Jacques" => "Lucette", "Jean" => ""];
// تکرار - ۱
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
//مرتبسازی فرهنگ لغت بر اساس کلید
ksort($conjoints);
// تکرار - ۲
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
// فهرست کلیدهای دیکشنری
$clés = array_keys($conjoints);
for ($i = 0; $i < count($clés); $i++) {
print "clés[$i]=$clés[$i]\n";
}
// فهرست مقادیر فرهنگ لغت
$valeurs = array_values($conjoints);
for ($i = 0; $i < count($valeurs); $i++) {
print "valeurs[$i]=$valeurs[$i]\n";
}
//جستجو برای یک کلید
existe($conjoints, "Jacques");
existe($conjoints, "Lucette");
existe($conjoints, "Jean");
// حذف یک جفت کلید-مقدار
unset($conjoints["Jean"]);
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
foreach ($conjoints as $clé => $valeur) {
print "conjoints[$clé]=$valeur\n";
}
// پایان
exit;
function existe($conjoints, $mari) {
//بررسی میکند که آیا کلید $mari در فرهنگ لغت $conjoints وجود دارد یا خیر
if (isset($conjoints[$mari])) {
print "La clé [$mari] existe associée à la valeur [$conjoints[$mari]]\n";
} else {
print "La clé [$mari] n'existe pas\n";
}
}
نتایج:
Nombre d'éléments du dictionnaire : 4
Deprecated: The each() function is deprecated. This message will be suppressed on further calls in C:\Data\st-2019\dev\php7\php5-exemples\exemples\exemple_05.php on line 8
conjoints[Pierre]=Gisèle
conjoints[Paul]=Virginie
conjoints[Jacques]=Lucette
conjoints[Jean]=
conjoints[Jacques]=Lucette
conjoints[Jean]=
conjoints[Paul]=Virginie
conjoints[Pierre]=Gisèle
clés[0]=Jacques
clés[1]=Jean
clés[2]=Paul
clés[3]=Pierre
valeurs[0]=Lucette
valeurs[1]=
valeurs[2]=Virginie
valeurs[3]=Gisèle
La clé [Jacques] existe associée à la valeur [Lucette]
La clé [Lucette] n'existe pas
La clé [Jean] existe associée à la valeur []
Nombre d'éléments du dictionnaire : 3
conjoints[Jacques]=Lucette
conjoints[Paul]=Virginie
conjoints[Pierre]=Gisèle
توضیحات
کد بالا همان کاری را که قبلاً برای یک آرایه ساده دیدیم را بر روی یک دیکشنری اعمال میکند. ما فقط در مورد ویژگیهای جدید توضیح میدهیم:
- خط ۱۲: تابع ksort (ترتیب کلید) یک دیکشنری را بر اساس ترتیب طبیعی کلیدها مرتب میکند؛
- خط ۱۹: تابع array_keys($dictionnaire) لیست کلیدهای دیکشنری را به صورت یک آرایه بازمیگرداند؛
- خط ۲۴: تابع array_values($dictionnaire) لیست مقادیر دیکشنری را به صورت یک آرایه بازمیگرداند؛
- خط ۴۳: تابع isset($variable) مقدار TRUE را در صورتی که متغیر $variable تعریف شده باشد برمیگرداند، و در غیر این صورت مقدار FALSE را برمیگرداند؛
- خط ۳۳: تابع unset($variable) متغیر $variable را حذف میکند.
3.6.3. آرایههای چندبعدی
اسکریپت [bases-07.php] به شرح زیر است:
<?php
// جدولهای چندبعدی کلاسیک
// ابتداییسازی
$multi = array(array(0, 1, 2), array(10, 11, 12, 13), array(20, 21, 22, 23, 24));
// تکرار
for ($i1 = 0; $i1 < count($multi); $i1++) {
for ($i2 = 0; $i2 < count($multi[$i1]); $i2++) {
print "multi[$i1][$i2]=" . $multi[$i1][$i2] . "\n";
}
}
// فرهنگهای چندبعدی
// ابتداییسازی
$multi = array("zéro" => array(0, 1, 2), "un" => array(10, 11, 12, 13), "deux" => array(20, 21, 22, 23, 24));
// تکرار
foreach ($multi as $clé => $valeur) {
for ($i2 = 0; $i2 < count($valeur); $i2++) {
print "multi[$clé][$i2]=" . $multi[$clé][$i2] . "\n";
}
}
نتایج:
multi[0][0]=0
multi[0][1]=1
multi[0][2]=2
multi[1][0]=10
multi[1][1]=11
multi[1][2]=12
multi[1][3]=13
multi[2][0]=20
multi[2][1]=21
multi[2][2]=22
multi[2][3]=23
multi[2][4]=24
multi[zéro][0]=0
multi[zéro][1]=1
multi[zéro][2]=2
multi[un][0]=10
multi[un][1]=11
multi[un][2]=12
multi[un][3]=13
multi[deux][0]=20
multi[deux][1]=21
multi[deux][2]=22
multi[deux][3]=23
multi[deux][4]=24
توضیحات
- خط ۵: عناصر آرایه $multi خودشان آرایهاند؛
- خط ۱۴: آرایه $multi به یک دیکشنری (clé,valeur) تبدیل میشود که در آن هر valeur یک آرایه است؛
3.7. رشتههای کاراکتری
3.7.1. نشانهگذاری
اسکریپت [bases-08.php] به شرح زیر است:
<?php
// نمایش رشتهای
$chaine1 = "un";
$chaine2 = 'un';
print "[$chaine1,$chaine2]\n";
?>
نتایج:
3.7.2. مقایسه
اسکریپت [bases-09.php] به شرح زیر است:
<?php
// رعایت دقیق انواع پارامترهای تابع
declare(strict_types=1);
//تابع مقایسه
function compareModele2Chaine(string $chaine1, string $chaine2): void {
//رشتهی1 و رشتهی2 را مقایسه میکند
if ($chaine1 === $chaine2) {
print "[$chaine1] est égal à [$chaine2]\n";
} else {
print "[$chaine1] est différent de [$chaine2]\n";
}
}
// آزمونهای مقایسهٔ رشتهای
compareModele2Chaine("abcd", "abcd");
compareModele2Chaine("", "");
compareModele2Chaine("1", "");
exit;
نتایج:
[abcd] est égal à [abcd]
[] est égal à []
[1] est différent de []
توضیحات
- خط ۹ کد: میتوانست به جای === از عملگر مقایسه == استفاده شود. عملگر دوم محدودکنندهتر است زیرا نیاز دارد که هر دو operand از یک نوع باشند. توجه داشته باشید که در اینجا میتوانست با عملگر == جایگزین شود، زیرا نوع هر دو پارامتر در امضای تابع به عنوان string مشخص شده است؛
3.7.3. ارتباطات بین رشتهها و آرایهها
اسکریپت [bases-10.php] به شرح زیر است:
<?php
// تبدیل رشته به آرایه
$chaine = "1:2:3:4";
$tab = explode(":", $chaine);
// حلقه برای مرور آرایه
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
}
// آرایه به رشته
$chaine2 = implode(":", $tab);
print "chaine2=$chaine2\n";
//بیایید یک فیلد خالی اضافه کنیم
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// حلقه روی آرایه
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // ما اکنون ۵ عنصر داریم که آخرین آنها خالی است
//بیایید یک فیلد خالی دیگر اضافه کنیم
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// تکرار آرایه
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // اکنون ۶ عنصر داریم که دو عنصر آخر آن خالی هستند
نتایج:
tab a 4 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
chaine2=1:2:3:4
chaîne=1:2:3:4:
tab a 5 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
tab[4]=
chaîne=1:2:3:4::
tab a 6 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
tab[4]=
tab[5]=
توضیحات
- خط ۵: تابع `explode($séparateur,$chaine)` فیلدهای `$chaine` را که با `$séparateur` از هم جدا شدهاند، بازیابی میکند. بنابراین، تابع `explode(":", $chaine)`، عناصر `$chaine` را که با رشته «:» از هم جدا شدهاند، به صورت یک آرایه بازگردانده میکند؛
- خط ۱۲: تابع implode($séparateur,$tableau) عملیات معکوس تابع explode را انجام میدهد. این تابع رشتهای را بازمیگرداند که شامل عناصر $tableau است و با $séparateur از هم جدا شدهاند؛
3.7.4. بیانهای منظم
اسکریپت [bases-11.php] به شرح زیر است:
<?php
// نوعدهی سختگیرانه برای پارامترهای تابع
declare (strict_types=1);
// بیانهای منظم در PHP
// استخراج فیلدهای مختلف از یک رشته
//الگو: دنبالهای از ارقام که توسط هر کاراکتری احاطه شده باشد
// ما فقط میخواهیم دنباله ارقام را استخراج کنیم
$modèle = "/(\d+)/";
// ما رشته را با الگو مقایسه میکنیم
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
//الگو: دنبالهای از اعداد که توسط هر کاراکتری احاطه شده است
// ما میخواهیم دنبالهٔ ارقام و همچنین فیلدهایی را که قبل و بعد از آن میآیند، استخراج کنیم
$modèle = "/^(.*?)(\d+)(.*?)$/";
// ما رشته را با الگو مطابقت میدهیم
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
//الگو – یک تاریخ در قالب dd/mm/yy
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
compareModele2Chaine($modèle, "10/05/97");
compareModele2Chaine($modèle, " 04/04/01 ");
compareModele2Chaine($modèle, "5/1/01");
//الگو – یک عدد اعشاری
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
compareModele2Chaine($modèle, "187.8");
compareModele2Chaine($modèle, "-0.6");
compareModele2Chaine($modèle, "4");
compareModele2Chaine($modèle, ".6");
compareModele2Chaine($modèle, "4.");
compareModele2Chaine($modèle, " + 4");
//پایان
exit;
// --------------------------------------------------------------------------
function compareModele2Chaine(string $modèle, string $chaîne): void {
// ریسمان $chaîne را با قالب $modèle مقایسه میکند
// رشته با قالب مقایسه میشود
$champs = [];
$correspond = preg_match($modèle, $chaîne, $champs);
// نمایش نتایج
print "\nRésultats($modèle,$chaîne)\n";
if ($correspond) {
for ($i = 0; $i < count($champs); $i++) {
print "champs[$i]=$champs[$i]\n";
}
} else {
print "La chaîne [$chaîne] ne correspond pas au modèle [$modèle]\n";
}
}
نتایج:
Résultats(/(\d+)/,xyz1234abcd)
champs[0]=1234
champs[1]=1234
Résultats(/(\d+)/,12 34)
champs[0]=12
champs[1]=12
Résultats(/(\d+)/,abcd)
La chaîne [abcd] ne correspond pas au modèle [/(\d+)/]
Résultats(/^(.*?)(\d+)(.*?)$/,xyz1234abcd)
champs[0]=xyz1234abcd
champs[1]=xyz
champs[2]=1234
champs[3]=abcd
Résultats(/^(.*?)(\d+)(.*?)$/,12 34)
champs[0]=12 34
champs[1]=
champs[2]=12
champs[3]= 34
Résultats(/^(.*?)(\d+)(.*?)$/,abcd)
La chaîne [abcd] ne correspond pas au modèle [/^(.*?)(\d+)(.*?)$/]
Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/,10/05/97)
champs[0]=10/05/97
champs[1]=10
champs[2]=05
champs[3]=97
Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/, 04/04/01 )
champs[0]= 04/04/01
champs[1]=04
champs[2]=04
champs[3]=01
Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/,5/1/01)
La chaîne [5/1/01] ne correspond pas au modèle [/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/]
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,187.8)
champs[0]=187.8
champs[1]=
champs[2]=187.8
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,-0.6)
champs[0]=-0.6
champs[1]=-
champs[2]=0.6
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,4)
champs[0]=4
champs[1]=
champs[2]=4
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,.6)
champs[0]=.6
champs[1]=
champs[2]=.6
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,4.)
champs[0]=4.
champs[1]=
champs[2]=4.
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/, + 4)
champs[0]= + 4
champs[1]=+
champs[2]=4
توضیحات
- در اینجا از عبارتهای منظم برای استخراج فیلدهای مختلف از یک رشته استفاده میکنیم. عبارتهای منظم به ما امکان میدهند محدودیتهای تابع implode را پشت سر بگذاریم. اصل کار مقایسه یک رشته با رشتهای دیگر به نام modèle با استفاده از تابع preg_match است:
$correspond = preg_match($modèle, $chaîne, $champs);
توابع preg_match و TRUE مقدار بولی TRUE را برمیگردانند اگر modèle در chaîne یافت شود. در این صورت، $champs[0] زیر رشتهای را که با قالب مطابقت دارد، نشان میدهد. علاوه بر این، اگر modèle شامل زیرمدلها در کروشهها باشد، $champs[1] بخشی از $chaîne است که به اولین زیرمدل مربوط میشود، $champs[2] بخشی از $chaîne است که به زیرالگوی دوم مربوط میشود، و به همین ترتیب…
بیایید مثال اول را در نظر بگیریم. الگو در خط ۱۰ تعریف شده است: این الگو با یک دنباله از یک یا چند رقم (+) (\d) که در هر نقطهای از یک رشته قرار دارد، مطابقت دارد. علاوه بر این، الگو یک زیرالگو را که در کروشهها قرار دارد، تعریف میکند؛
- خط ۱۲: الگوی /(\d+)/ (یک دنباله از یک یا چند رقم در هر نقطهای از رشته) با رشته "xyz1234abcd" مقایسه میشود. میبینیم که زیررشته 1234 با الگو مطابقت دارد. بنابراین داریم $champs[0] برابر با «1234». علاوه بر این، الگو حاوی زیرالگوهایی در داخل پرانتز است. ما داریم $champs[1] = "1234";
- خط ۱۳: الگوی /(\d+)/ با رشته «۱۲ ۳۴» مقایسه میشود. میبینیم که زیررشتههای ۱۲ و ۳۴ با الگو مطابقت دارند. مقایسه در اولین زیررشتهای که با الگو مطابقت دارد متوقف میشود. بنابراین ما داریم $champs[0]=12 و $champs[1]=12;
- خط ۱۴: الگوی /(\d+)/ با رشته "abcd" مقایسه میشود. تطابقی یافت نمیشود؛
بیایید الگوهای مورد استفاده در بقیه کد را توضیح دهیم:
$modèle = "/^(.*?)(\d+)(.*?)$/";
با شروع رشته (^)، سپس صفر یا چند کاراکتر دلخواه (*) (.), سپس یک یا چند رقم (+)، و در نهایت صفر یا چند کاراکتر دلخواه (*) (.) مطابقت دارد. الگوی (.*) نشاندهنده صفر یا تعداد بیشتری از کاراکترهای دلخواه است. چنین الگویی با هر رشتهای مطابقت خواهد داشت. بنابراین، الگوی /^(.*)(\d+)(.*)$/ هرگز مطابقت داده نخواهد شد زیرا الگوی فرعی اول (.*) کل رشته را در بر میگیرد. الگوی (.*?)(\d+) صفر یا تعداد بیشتری از هر کاراکتر را تا زیرالگوی بعدی (?)، در این مورد \d+، مطابقت میدهد. در نتیجه، اعداد دیگر توسط الگوی (.*) مطابقت داده نمیشوند. بنابراین، الگوی بالا با [début de chaîne (^), une suite de caractères quelconques (.*?), une suite d'un ou plusieurs chiffres (\d+), une suite de caractères quelconques (.*?), la fin de la chaîne ($)] مطابقت دارد.
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
با [début de chaîne (^), 2 chiffres (\d\d), le caractère / (\/), 2 chiffres, /, 2 chiffres, une suite de 0 ou plusieurs espaces (\s*), la fin de chaîne ($)] مطابقت دارد.
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
با شروع رشته (^) مطابقت دارد، ۰ یا چند فضای خالی (?*)، یک علامت + یا - [+|-] که ۰ یا ۱ بار رخ میدهد (؟)، یک دنباله از ۰ یا چند فضای خالی (?*)، ۱ یا چند رقم به دنباله یک ممیز اعشاری و سپس صفر یا چند رقم (\d+\.\d*) یا (|) یک ممیز اعشاری (\.) به دنباله یک یا چند رقم (\d+) یا (|) یک یا چند رقم (\d+)، یک دنباله از صفر یا چند فاصله (\s*)].
توجه: عبارت [espace] در عبارتهای منظم به مجموعهای از کاراکترها اشاره دارد: فضای خالی، خط جدید \n، تب \t، بازگشت کاراکتری \r، فرستنده فرم \f…
3.8. توابع
3.8.1. حالت ارسال پارامتر
اسکریپت [base-12.php] به شرح زیر است:
<?php
// نحوه ارسال پارامترها به یک تابع
// پابندی سختگیرانه به انواع پارامترها
declare(strict_types=1);
function f(int &$i, int $j): void {
// $i به صورت ارجاعی ارسال خواهد شد
// $j به صورت مقدار پاس خواهد شد
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
// آزمایشها
$i = 0;
$j = 0;
//و $i و $j به تابع f پاس میشوند
f($i, $j);
print "test[i,j]=[$i,$j]\n";
نتایج:
توضیحات
کد بالا دو روش ارسال پارامتر به یک تابع را نشان میدهد. بیایید مثال زیر را در نظر بگیریم:
- خط ۱: پارامترهای شکلی $a و $b را برای تابع f تعریف میکند. این تابع این دو پارامتر شکلی را پردازش کرده و یک نتیجه را بازمیگرداند؛
- خط ۷: تابع f را با دو پارامتر حقیقی، $i و $j، فراخوانی میکند. روابط بین پارامترهای فرمال ($a, $b) و پارامترهای حقیقی ($i, $j) توسط خطوط ۱ و ۷ تعریف میشوند:
- &$a: نماد & نشان میدهد که پارامتر شکلی $a مقدار آدرس پارامتر حقیقی $i را خواهد گرفت. به عبارت دیگر، $a و $i دو اشاره به یک مکان حافظه یکسان هستند. دستکاری پارامتر فرمی $a معادل دستکاری پارامتر حقیقی $i است. این موضوع با اجرای کد نشان داده میشود. این حالت ارسال برای پارامترهای خروجی و مجموعههای داده بزرگ مانند آرایهها و دیکشنریها مناسب است. این حالت ارسال به عنوان «ارسال ارجاعی» (pass-by-reference) شناخته میشود.
- $b: پارامتر اسمی $b مقدار پارامتر حقیقی $j را به خود اختصاص خواهد داد. این یک ارسال به صورت مقدار است. پارامترهای اسمی و حقیقی دو متغیر متفاوت هستند. دستکاری پارامتر اسمی $b هیچ تأثیری بر پارامتر حقیقی $j ندارد. این موضوع با اجرای کد نشان داده میشود. این حالت ارسال برای پارامترهای ورودی مناسب است.
- تابع échange را در نظر بگیرید که دو پارامتر اسمی دارد: $a و $b. این تابع مقادیر این دو پارامتر را با هم جابجا میکند. بنابراین، در هنگام فراخوانی swap ($i, $j)، کد فراخوان انتظار دارد که مقادیر دو پارامتر حقیقی با هم جابجا شوند. از این رو، اینها پارامترهای خروجی هستند (آنها تغییر مییابند). بنابراین، به این صورت مینویسیم:
اسکریپت زیر، [base-13.php]، مثالهای بیشتری را نشان میدهد:
<?php
// انواع در حالت سختگیرانه
// declare(strict_types = 1);
// حالت ارسال پارامتر
function f(&$i, $j) {
// $i به صورت ارجاعی ارسال خواهد شد
// $j به صورت مقدار ارسال خواهد شد
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
function g(int &$i, int $j) : void {
// $i به صورت ارجاعی ارسال خواهد شد
//$j توسط مقدار به دست میآید
$i++;
$j++;
print "g[i,j]=[$i,$j]\n";
}
// آزمایشها
$i = 0;
$j = 0;
// $i و $j به تابع f پاس داده میشوند
f($i, $j);
print "test[i,j]=[$i,$j]\n";
// $i و $j به تابع g ارسال میشوند
g($i, $j);
print "test[i,j]=[$i,$j]\n";
//پارامترهای نادرست به f ارسال میشوند
$a=5.3;
$b=6.2;
f($a, $b);
print "test[a,b]=[$a,$b]\n";
//پارامترهای نادرست به f ارسال میشوند
$a=5.3;
$b=6.2;
g($a, $b);
print "test[a,b]=[$a,$b]\n";
توضیحات
- خطوط ۸–۱۴: تابع f که در پاراگراف قبلی مورد بحث قرار گرفت، اما پارامترها نوعدهی نشدهاند؛
- خطوط 16–22: تابع g همانند تابع f عمل میکند، اما نوع پارامترهای مورد انتظار مشخص شده است – این یک ویژگی جدید PHP 7 است. دو پارامتر از نوع int مورد انتظار است. میخواهیم ببینیم وقتی پارامتر واقعی ارسالشده به تابع از نوع مورد انتظار تابع نباشد چه اتفاقی میافتد؛
- خطوط ۲۵–۲۶: $i و $j دو عدد صحیح هستند؛
- خطوط ۲۸–۲۹: فراخوانی تابع f با پارامترهایی از نوع مورد انتظار؛
- خطوط ۳۱–۳۲: تابع g با پارامترهایی از نوع مورد انتظار فراخوانی میشود؛
- خطوط ۳۴–۳۵: متغیرهای $a و $b از نوع float هستند؛
- خطوط ۳۶–۳۷: فراخوانی تابع f با پارامترهایی که از نوع مورد انتظار نیستند؛
- خطوط ۴۱–۴۲: فراخوانی تابع g با پارامترهایی که از نوع مورد انتظار نیستند؛
نتایج
- خطوط ۵–۶ نشان میدهند که تابع f هر دو پارامتر را از نوع float پذیرفته و آنها را پردازش کرده است؛
- خطوط ۷–۸ نشان میدهند که تابع g هر دو پارامتر را از نوع float پذیرفته اما آنها را به نوع int تبدیل کرده است (خط ۷);
اکنون بیایید خط ۴ را از حالت نظر خارج کنیم:
این دستور مشخص میکند که باید از نوع پارامترهای صوری پیروی شود. اگر اینطور نباشد، خطایی گزارش میشود. نتایج اجرای آن به صورت زیر خواهد بود:
- خطوط ۹–۱۰: تفسیرگر PHP 7 یک استثنا (exception) به وجود آورد تا نشان دهد که اولین پارامتر ارسالشده به تابع g از نوع اشتباه بوده است. توصیه میشود تا حد امکان در مورد انواع پارامترها سختگیر بود تا خطاهای فراخوانی تابع را شناسایی کرد؛
3.8.2. نتایج بازگرداندهشده توسط یک تابع
اسکریپت [base-15.php] به شرح زیر است:
<?php
// انواع در حالت سختگیرانه
declare(strict_types=1);
// مقادیر بازگشتی یک تابع
// یک تابع ممکن است چندین مقدار را در یک آرایه بازگرداند
list($res1, $res2, $res3) = f1(10);
print "[$res1,$res2,$res3]\n";
$res = f1(10);
for ($i = 0; $i < count($res); $i++) {
print "f1 : res[$i]=$res[$i]\n";
}
//یک تابع میتواند یک شیء را بازگرداند
$res = f2(10);
print "f2 : [$res->res1,$res->res2,$res->res3]\n";
// چه نوع ابجکتی؟
print "nature de l'objet : ";
var_dump($res);
print "\n";
// ما همین کار را با تابع f3 انجام میدهیم
$res = f3(10);
print "f3 : [$res->res1,$res->res2,$res->res3]\n";
// چه نوع ابجکتی؟
print "nature de l'objet : ";
var_dump($res);
print "\n";
// end
exit;
// تابع f1
function f1(int $valeur): array {
//یک آرایه را بازمیگرداند ($valeur+1,$valeur+2,$valeur+3)
return array($valeur + 1, $valeur + 2, $valeur + 3);
}
// تابع f2
function f2(int $valeur): object {
//یک شیء را بازمیگرداند ($valeur+1,$valeur+2,$valeur+3)
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// شیء را بازمیگرداند
return $res;
}
//تابع f3 – همانند تابع f2 عمل میکند
function f3(int $valeur): object {
//یک شیء را بازمیگرداند ($valeur+1,$valeur+2,$valeur+3)
$res = new stdclass();
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
//شیء را بازمیگرداند
return $res;
}
نتایج
[11,12,13]
f1 : res[0]=11
f1 : res[1]=12
f1 : res[2]=13
Warning: Creating default object from empty value in C:\Data\st-2019\dev\php7\php5-exemples\exemples\bases\base-15.php on line 43
f2 : [11,12,13]
nature de l'objet : object(stdClass)#1 (3) {
["res1"]=>
int(11)
["res2"]=>
int(12)
["res3"]=>
int(13)
}
f3 : [11,12,13]
nature de l'objet : object(stdClass)#2 (3) {
["res1"]=>
int(11)
["res2"]=>
int(12)
["res3"]=>
int(13)
}
توضیحات
- برنامه قبلی نشان میدهد که تابع PHP میتواند به جای یک نتیجه واحد، مجموعهای از نتایج را در قالب یک آرایه یا یک شیء بازگرداند. مفهوم شیء در ادامه با جزئیات بیشتری توضیح داده شده است؛
- خطوط ۳۵–۳۸: تابع f1 چندین مقدار را به صورت یک آرایه بازمیگرداند؛
- خطوط ۴۱–۴۸: تابع f2 مقادیر چندگانه را به شکل یک شیء بازمیگرداند؛
- خطوط ۵۱–۵۹: تابع f3 با تابع f2 یکسان است، با این تفاوت که در خط ۵۳ صراحتاً یک شیء ایجاد میکند؛
- خط ۶ نتایج، هشداری را نمایش میدهد که نشان میدهد PHP مجبور به ایجاد یک شیء پیشفرض در خط ۴۳ کد شده است، یعنی هنگام استفاده از نشانه [$res→res1]. تابع var_dump در خط ۲۰ کد دسترسی به نوع و محتوای شیء را فراهم میکند. در نتایج، میتوانیم ببینیم که:
- خط ۸: ابجکت ایجادشده بهصورت پیشفرض از نوع stdClass است؛
- خطوط ۹–۱۰: ویژگی res1 از نوع entier است و مقدار ۱۱ را دارد؛
- و غیره…
- برای جلوگیری از هشدار در خط ۶ نتایج، ما صراحتاً در خط ۵۳ تابع f3، یک شیء از نوع stdClass ایجاد میکنیم؛
3.9. فایلهای متنی
اسکریپت [bases-16.php] به شرح زیر است:
<?php
// پابندی سختگیرانه به انواع پارامترهای تابع
declare (strict_types=1);
//پردازش متوالی یک فایل متنی
// این شامل مجموعهای از خطوط در قالب login:pwd:uid:gid:infos:dir:shell است
// هر خط در یک دیکشنری به شکل login => uid:gid:infos:dir:shell ذخیره میشود
//نام فایل تنظیم میشود
$INFOS = "infos.txt";
// آن را برای نوشتن باز میکنیم
if (!$fic = fopen($INFOS, "w")) {
print "Erreur d'ouverture du fichier $INFOS en écriture\n";
exit;
}
// ما محتوای دلخواه تولید میکنیم
for ($i = 0; $i < 100; $i++) {
fputs($fic, "login$i:pwd$i:uid$i:gid$i:infos$i:dir$i:shell$i\n");
}
// بستن فایل
fclose($fic);
// سوءاستفاده کنید – fgets نشانگر پایان خط را حفظ میکند
// این اطمینان را میدهد که هنگام خواندن یک خط خالی، یک رشتهٔ خالی بازگردانده نشود
// فایل را برای خواندن باز کنید
if (!$fic = fopen($INFOS, "r")) {
print "Erreur d'ouverture du fichier $INFOS en lecture\n";
exit;
}
//خطوط کمتر از ۱۰۰۰ کاراکتر طول دارند
// خواندن خط در نشانگر پایان خط متوقف میشود
//یا نشانگر پایان فایل
while ($ligne = fgets($fic, 1000)) {
// علامت پایان خط در صورت وجود حذف میشود
$ligne = cutNewLineChar($ligne);
//ما خط را در یک جدول قرار میدهیم
$infos = explode(":", $ligne);
//بازیابی ورود
$login = array_shift($infos);
// ما رمز عبور را نادیده میگیریم
array_shift($infos);
// ایجاد یک مدخل در فرهنگ لغت
$dico[$login] = $infos;
}
// آن را ببندید
fclose($fic);
// سوءاستفاده از دیکشنری
afficheInfos($dico, "login10");
afficheInfos($dico, "X");
// پایان
exit;
// --------------------------------------------------------------------------
function afficheInfos(array $dico, string $clé): void {
//مقدار مرتبط با کلید را در فرهنگ لغت $dico نمایش میدهد اگر وجود داشته باشد
if (isset($dico[$clé])) {
//مقدار وجود دارد – آیا آرایه است؟
$valeur = $dico[$clé];
if (is_array($valeur)) {
print "[$clé," . join(":", $valeur) . "]\n";
} else {
// $valeur یک آرایه نیست
print "[$clé,$valeur]\n";
}
} else {
// $clé کلید در فرهنگ لغت $dico نیست
print "la clé [$clé] n'existe pas\n";
}
}
// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne): string {
// علامت پایان خط برای $ligne در صورت وجود حذف میشود
$L = strlen($ligne); // طول خط
while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// پایان
return($ligne);
}
فایل infos.txt:
نتایج:
[login10,uid10:gid10:infos10:dir10:shell10]
la clé [X] n'existe pas
نظرات
- خط ۱۲: fopen(nom_fichier, "w") فایل nom_fichier را برای نوشتن (w=write) باز میکند. اگر فایل وجود نداشته باشد، ایجاد میشود. اگر وجود داشته باشد، محتویات آن پاک میشود. اگر ایجاد با موفقیت انجام نشود، fopen مقدار false را برمیگرداند. در عبارت if (!$fic = fopen($INFOS, "w")) {…}, دو عملیات متوالی وجود دارد: ۱) $fic = fopen(..) ۲) if (!$fic) {…};
- خط ۱۸: `fputs($fic, $chaîne)` مقدار `chaîne` را در فایل `$fic` مینویسد. $chaine با کاراکتر پایان خط \n در انتها نوشته میشود؛
- خط ۲۱: `fclose($fic)` فایل $fic را میبندد؛
- خط ۲۶: fopen(nom_fichier,"r") فایل nom_fichier را برای خواندن باز میکند (r=read). اگر باز کردن فایل ناموفق باشد (برای مثال، اگر فایل وجود نداشته باشد)، fopen مقدار false را برمیگرداند؛
- خط ۳۴: تابع `fgets($fic, 1000)` خط بعدی را از فایل میخواند و آن را به ۱۰۰۰ کاراکتر محدود میکند. در حلقه while ($ligne = fgets($fic, 1000)) {…}, دو عملیات متوالی وجود دارد: 1) $ligne = fgets(…) ۲) while ( ! $ligne). به محض اینکه آخرین کاراکتر فایل خوانده شود، تابع fgets مقدار false را برمیگرداند و حلقه while خاتمه مییابد. تابع fgets در اینجا تلاش میکند حداکثر ۱۰۰۰ کاراکتر را بخواند اما به محض برخورد با کاراکتر پایان خط متوقف میشود. از آنجایی که تمام خطوط اینجا کمتر از ۱۰۰۰ کاراکتر دارند، [fgets] یک خط متن را به همراه کاراکتر پایان خط میخواند. تابع cutNewLineChar در خطوط ۷۵ تا ۸۴ هرگونه کاراکتر پایان خط را حذف میکند؛
- خط ۷۷: تابع `strlen($chaîne)` تعداد کاراکترهای موجود در `$chaîne` را برمیگرداند؛
- خط ۷۸: تابع substr($ligne, $position, $taille) کاراکترهای $taille را از $ligne، از کاراکتر با شماره $position بازمیگرداند، که در آن کاراکتر اول شماره 0 را دارد. در سیستمعامل ویندوز، نشانگر پایان خط «\r\n» است. در سیستمعامل یونیکس، این رشته «\n» است؛
- خط ۴۰: تابع array_shift($tableau) اولین عنصر را از $tableau حذف کرده و آن را به عنوان نتیجه برمیگرداند. نتیجه بازگشتی array_shift در اینجا نادیده گرفته میشود؛
- خط ۶۲: تابع is_array($variable) اگر $variable یک آرایه باشد، true را برمیگرداند و در غیر این صورت، false را برمیگرداند؛
- خط ۶۳: تابع join همان کاری را انجام میدهد که تابع implode قبلاً انجام داده است؛
3.10. کدگذاری / رمزگشایی jSON

رمزگذاری/رمزگشایی jSON (نمایش شیء JavaScript) چیزی است که ما در تمرینی که موضوع اصلی این سند است، به طور گسترده از آن استفاده خواهیم کرد. اسکریپتهای [json-01.php, json-02.php, json-03.php] آنچه را که برای ادامه سند باید بدانید توضیح میدهند.
اسکریپت [json-01.php] به شرح زیر است:
<?php
$array1 = ["nom" => "séléné", "prénom" => "bénédicte", "âge" => 34];
// کدگذاری JSON آرایه1 با کاراکترهای یونیکد فراری
print "encodage json du tableau array1 avec caractères Unicode échappés\n";
$json1 = json_encode($array1);
print "json1=$json1\n";
//رمزگذاری JSON آرایه1 با کاراکترهای یونیکد بدون فرار
print "encodage json du tableau array1 avec caractères Unicode non échappés\n";
$json2 = json_encode($array1, JSON_UNESCAPED_UNICODE);
print "json2=$json2\n";
// رمزگشایی jSON به یک آرایهٔ انجمنی
print "décodage jSON de json2 dans tableau associatif\n";
$array2 = json_decode($json2, true);
var_dump($array2);
foreach ($array2 as $key => $value) {
print "$key:$value\n";
}
// رمزگشایی jSON به یک شیء
print "décodage jSON de json2 dans objet stdClass\n";
$array2 = json_decode($json2);
var_dump($array2);
print "prénom=$array2->prénom\n";
print "nom=$array2->nom\n";
print "âge=$array2->âge\n";
نتایج
توضیحات
- خط ۶ کد: تابع [json_encode] پارامتر خود را به رشتهٔ کاراکتری jSON تبدیل میکند؛
- خط ۲ نتایج: رشته حاصل jSON. کاراکترهای یونیکد éâ با کدهای یونیکد خود که با \u شروع میشوند، جایگزین شدهاند؛
- خط ۱۰ کد: ما همین فرآیند را تکرار میکنیم، این بار مشخص میکنیم که کاراکترهای یونیکد باید به همان صورت حفظ شوند؛
- خط ۴ نتایج: رشته حاصل jSON. این بسیار خواناتر است؛
- خطوط ۱۴–۱۸ کد: عملیات معکوس را انجام میدهیم. ما رشته jSON را به یک آرایه asociative تبدیل میکنیم؛
- خطوط ۶–۱۳ نتایج: میبینیم که یک آرایهٔ asociative بازیابی کردهایم؛
- خطوط ۱۹–۲۵ کد: ما یک رشته jSON را به یک شی از نوع [stdClass] تبدیل میکنیم؛
- خطوط ۱۸–۲۵ نتایج: میبینیم که یک شیء از نوع [stdClass] بازیابی شده است؛
- خطوط ۲۳–۲۵ کد: ویژگی A یک شیء O با [O→A] نشان داده میشود؛
آرایههای چندسطحی میتوانند در jSON رمزگذاری شوند، همانطور که در اسکریپت [json-02.php] زیر نشان داده شده است:
<?php
$array = ["nom" => "séléné", "prénom" => "bénédicte", "âge" => 34,
"mari" => ["nom" => "icariù", "prénom" => "ignacio", "âge" => 35],
"enfants" => [
["prénom" => "angèle", "age" => 8],
["prénom" => "andré", "age" => 2],
]];
//رمزگذاری آرایه چندسطحی به صورت jSON
print "encodage jSON d'un tableau à plusieurs niveaux\n";
$json = json_encode($array, JSON_UNESCAPED_UNICODE);
print "json=$json\n";
نتایج
encodage jSON d'un tableau à plusieurs niveaux
json={"nom":"séléné","prénom":"bénédicte","âge":34,"mari":{"nom":"icariù","prénom":"ignacio","âge":35},"enfants":[{"prénom":"angèle","age":8},{"prénom":"andré","age":2}]}
نظرات
در رشته jSON:
- آرایههای غیرانجمنی در کروشههای مربعی [] قرار میگیرند؛
- آرایههای asociative در کروشههای منحنی {} قرار میگیرند؛
اسکریپت [json-03.php] نشان میدهد چگونه فایلهای زیر jSON و [famille.json] را پردازش کنید:
{
"épouse": {
"nom": "séléné",
"prénom": "bénédicte",
"âge": 34
},
"mari": {
"nom": "icariù",
"prénom": "ignacio",
"âge": 35
},
"enfants": [
{
"prénom": "angèle",
"age": 8
},
{
"prénom": "andré",
"age": 2
}
]
}
اسکریپت [json-03.php] به شرح زیر است:
<?php
//خواندن فایل jSON
$json = file_get_contents("famille.json");
// رمزگشایی JSON به یک شیء
$famille1 = json_decode($json);
print "----famille1\n";
var_dump($famille1);
// رمزگشایی JSON به یک آرایهٔ asociative
print "----famille2\n";
$famille2 = json_decode($json, true);
var_dump($famille2);
توضیحات
- خط ۴: تابع [file_get_contents] محتویات فایل با نام [famille.json] را میخواند و آنها را در متغیر [$json] ذخیره میکند؛
- سپس این متغیر به یک شیء (خطوط ۵–۸) و یک آرایهٔ asociative (خطوط ۹–۱۲) رمزگشایی میشود؛
نتایج
----famille1
object(stdClass)#2 (3) {
["épouse"]=>
object(stdClass)#1 (3) {
["nom"]=>
string(9) "séléné"
["prénom"]=>
string(11) "bénédicte"
["âge"]=>
int(34)
}
["mari"]=>
object(stdClass)#3 (3) {
["nom"]=>
string(7) "icariù"
["prénom"]=>
string(7) "ignacio"
["âge"]=>
int(35)
}
["enfants"]=>
array(2) {
[0]=>
object(stdClass)#4 (2) {
["prénom"]=>
string(7) "angèle"
["age"]=>
int(8)
}
[1]=>
object(stdClass)#5 (2) {
["prénom"]=>
string(6) "andré"
["age"]=>
int(2)
}
}
}
----famille2
array(3) {
["épouse"]=>
array(3) {
["nom"]=>
string(9) "séléné"
["prénom"]=>
string(11) "bénédicte"
["âge"]=>
int(34)
}
["mari"]=>
array(3) {
["nom"]=>
string(7) "icariù"
["prénom"]=>
string(7) "ignacio"
["âge"]=>
int(35)
}
["enfants"]=>
array(2) {
[0]=>
array(2) {
["prénom"]=>
string(7) "angèle"
["age"]=>
int(8)
}
[1]=>
array(2) {
["prénom"]=>
string(6) "andré"
["age"]=>
int(2)
}
}
}
توضیحات
- خطوط ۱–۳۸: ابجکت حاصل از رمزگشایی فایل jSON [famille.json];
- خطوط ۳۹–۷۶: آرایهٔ asociative resulting resulting از رمزگشایی فایل jSON [famille.json];