پیش از این با نحوهٔ استفاده از حلقهٔ foreach به منظور دستیابی به اِلِمانهای یک آرایه در زبان PHP آشنا شدیم؛ اما گفتیم که به غیر از این ساختار، یکسری لوپ (حلقه) دیگر نیز در این زبان تعبیه شدهاند که با استفاده از آنها میتوان به اعضای یک آرایه دست یافت که عبارتند از:
- for
- while
- do while
آشنایی با ساختار حلقهٔ for
ساختار این نوع حلقه به نسبت دیگر ساختارها تا حدودی پیچیده است و میشود گفت زمانی از این نوع لوپ استفاده میشود که از قبل میدانیم چند بار اسکریپت مد نظر باید اجرا گردد. به عنوان ساختار کلی حلقهٔ for داریم:
for (Initialization; Condition; Step) {
// Code to be executed
}
همانطور که مشاهده میشود، for دارای سه پارامتر ورودی است. Initialization (شروع) متغیری است معمولاً از نوع عددی که نقطهٔ شروع یا به عبارتی مقدار اولیهٔ شمارنده را مشخص میسازد، Condition (شرط) هم در آغاز هر بار اجرای حلقه چک میشود به طوری که اگر True بود حلقه ادامه مییابد و در صورتی هم که برابر با False بود، اجرای این حلقه خاتمه خواهد یافت و در نهایت به Step (گام) میرسیم که در این گام مقدار متغیر Initialization را با هر مقداری که در نظر داشته باشیم تغییر میدهیم اما به یاد داشته باشیم که این تغییر مقدار در پایان هر بار اجرای حلقه صورت میگیرد. فلوچارت مرتبط با نحوهٔ اجرای این نوع لوپ به صورت زیر است:
برای روشنتر شدن نحوهٔ کارکرد حلقهٔ for، در ادامه مثالی میآوریم:
for($i = 1; $i <= 3; $i++) {
echo "The number is " . $i . "<br>";
}
همانطور که مشاهده میشود، به جای Initialization یا به عبارتی متغیری که این وظیفه را دارا است تا نقطهٔ شروع حلقه را مشخص کند، متغیری در نظر گرفتهایم تحت عنوان i$ با مقدار اولیهٔ ۱ سپس یک علامت ; قرار داده و Condition یا شرطی را نوشتهایم که در هر بار اجرای حلقه چک خواهد شد که در این مثال گفتهایم مادامی که مقدار متغیر i$ کوچکتر یا مساوی با ۳ بود، این حلقه ادامه یابد. مجدد یک علامت ; قرار داده و در نهایت Step را نوشتهایم بدین صورت که در هر بار اجرای حلقه، در انتهای اسکریپت یک واحد به متغیر i$ اضافه خواهد شد (علائم ++ منجر به افزایش یک واحد به متغیر عددی i$ خواهد شد.) نیاز به توضیح نیست که داخل حلقه هم اسکریپتی نوشتهایم که مقدار متغیر i$ را چاپ میکند به طوری که به عنوان خروجی این اسکریپت داریم:
The number is 1
The number is 2
The number is 3
به منظور درک بهتر این ساختار، نحوهٔ اجرای اسکریپت فوق را تفسیر میکنیم. در ابتدا متغیری تعریف کردهایم تحت عنوان i$ که مقدار اولیهٔ این متغیر یک عدد صحیح برابر با ۱ است. زمانی که این اسکریپت را اجرا میکنیم، شرط در نظر گرفته شده میسنجد ببیند که آیا مقدار i$ کوچکتر یا مساوی (=>) با عدد ۳ هست یا خیر که اگر جواب این شرط اصطلاحاً Ture (درست) بود، حلقه یک بار اجرا میشود و در پایان اسکریپتهای قرار گرفته داخل این حلقه، یعنی جایی که از دستور echo استفاده کردهایم، پارامتر سوم داخل این حلقه اجرا شده و یک واحد به i$ افزوده میگردد و مقدارش برابر با ۲ میشود. مجدد شرط بررسی شده و کماکان مقدار True است و حلقه یک بار دیگر میچرخد و در پایان اسکریپت مجدد یک واحد به مقدار متغیر i$ اضافه شده و مقدارش برابر با ۳ میشود.
در ادامه، وقتی که شرط بررسی میشود، میبینیم که کماکان True است چرا که علائم => حاکی از آنند که این متغیر باید کوچکتر یا مساوی با عدد ۳ باشد که در این مرحله مقدار متغیر i$ برابر با عدد ۳ است؛ به عبارتی، شرط برقرار است و حلقه یک بار دیگر اجرا میشود تا اینکه در انتهای اسکریپت مقدار متغیر i$ برابر با ۴ شده که مسلماً شرط False شده و این حلقه خاتمه مییابد. در همین راستا، با یک تغییر کوچک در اسکریپت فوق میبینیم که شرط هرگز برقرار نشده و حلقه اجرا نمیگردد:
for($i = 4; $i <= 3; $i++) {
echo "The number is " . $i . "<br>";
}
در واقع، از آنجا که مقدار اولیهٔ در نظر گرفته شده برای متغیر i$ برابر با عدد صحیح ۴ است و در شرط هم گفتهایم که این مقدار باید کوچکتر یا مساوی با عدد ۳ باشد، این شرط هرگز برقرار نشده و اسکریپت ما هم اجرا نخواهد شد.
نکتهٔ دیگری که در ارتباط با پارامتر سوم (Step) باید در نظر گرفت اینکه معمولاً این پارامتر وظیفه دارد تا مقدار متغیر مذکور رو افزایش دهد، اما این در حالی است که در برخی شرایط میتوان این مقدار را کاهش هم داد. به عنوان مثال داریم:
for($i = 20; $i >= 10; $i--) {
echo "The number is " . $i . "<br>";
}
به عنوان خروجی هم داریم:
The number is 20
The number is 19
The number is 18
The number is 17
The number is 16
The number is 15
The number is 14
The number is 13
The number is 12
The number is 11
The number is 10
در واقع، در اسکریپت فوق گفتهایم مادامی که مقدار متغیر i$ بزرگتر یا مساوی با عدد ۱۰ است، حلقه اجرا شده و در پایان هر بار چرخش هم یک واحد از متغیر i$ کم شود (علائم -- حاکی از کم شدن یک واحد از عدد صحیح هستند.) همچنین در پارامتر Step میتوان عمل ضرب و تقسیم هم انجام داد به طوری که در اسکریپت زیر به راحتی مقدار متغیر مذکور را به توان رساندهایم:
for($i = 1; $i < 70; $i *= 2) {
echo "The number is " . $i . "<br>";
}
به عنوان خروجی داریم:
The number is 1
The number is 2
The number is 4
The number is 8
The number is 16
The number is 32
The number is 64
در تفسیر اسکریپت فوق بایستی بگوییم که در اولین باری که حلقه اجرا میشود، شرط برقرار است چرا که عدد ۱ از ۷۰ کوچکتر است. حال پس از اینکه حلقه برای اولین بار اجرا شد، در پایان اجرا مقدار اولیهٔ متغیر i$ که برابر با ۱ بود در عدد ۲ ضرب شده و مجدد داخل همان متغیر i$ ذخیره میشود که از این پس مقدار این متغیر میشود ۲ = ۱ × ۲ و مسلماً زمانی که شرط چک میشود، عدد ۲ از ۷۰ کوچکتر بوده و شراط برابر با True خواهد بود و این حلقه اجرا شده بدین شکل که در ادامه مقدار متغیر i$ که از این پس برابر با ۲ است مجدد در عدد ۲ ضرب شده و مقدارش برابر با ۴ میشود و این کار ادامه مییابد تا جایی که مقدار متغیر i$ بیش از ۷۰ شده و پاسخ شرط اصطلاحاً False میگردد.
اختیاری بودن پارامترهای حلقهٔ For
لازم به ذکر است که هر سه پارامتر ورودی این حلقه Optional (اختیاری) هستند. برای مثال:
$noOne = 1;
$noTwo = 5;
for ( ; $noOne <= $noTwo; $noOne++ ) {
echo "The number is " . $noOne . "<br>";
}
به عنوان خروجی داریم:
The number is 1
The number is 2
The number is 3
The number is 4
The number is 5
در تفسیر اسکریپت فوق بایستی گفت که ابتدا به ساکن دو متغیر تعریف کردهایم تحت عناوین noOne$ و noTwo$ اما این در حالی است که در حلقهٔ for پارامتر اول را درج نکردهایم و صرفاً به بیان Condition و همچنین Step پرداختهایم (البته به خاطر داشته باشید گرچه پارامتر اول نوشته نشده است، اما علامت ; مرتبط با آن میبایست گذاشته شود که در غیر این صورت با ارور مواجه خواهید شد.)
همچنین توجه داشته باشید که اگر پارامتر دوم (Condition) حذف گردد، به صورت پیشفرض مقدار True برای شرط این حلقه در نظر گرفته خواهد شد و نیاز به توضیح نیست که در چنین شرایطی یک حلقهٔ به اصطلاح Infinite (بیپایان) خواهیم داشت. در همین راستا داریم:
for($i = 1; ; $i++) {
echo "The number is " . $i . "<br>";
}
میبینیم که پارامتر وسط، همان پارامتری که مربوط به شرط است، حذف شده است اما کماکان علامت ; سر جایش باقی است. به عنوان خروجی هم داریم:
The number is 1
The number is 2
The number is 3
The number is 4
The number is 5
The number is 6
The number is 7
The number is 8
The number is 9
The number is 10
The number is 11
The number is 12
The number is 13
The number is 14
The number is 15
The number is 16
The number is 17
The number is 18
The number is 19
The number is 20
The number is 21
The number is 22
The number is 23
The number is 24
The number is 25
The number is 26
The number is 27
.
.
.
در واقع، این حلقه تا بینهایت ادامه خواهد یافت تا زمانی که شما اجرا را متوقف نمایید. اگر هم بخواهیم مثالی از حذف هر سه پارامتر بزنیم، خواهیم داشت:
for (; ;) {
$i = rand(1, 10);
echo "The number is " . $i . "<br>";
if ($i == 2) {
break;
}
}
به عنوان خروجی داریم:
The number is 4
The number is 1
The number is 7
The number is 6
The number is 1
The number is 3
The number is 2
در حقیقت، سازوکار حلقهٔ فوق بدین صورت است که کلیهٔ پارامترها را حذف نموده و داخل حلقه متغیری تعریف کردهایم تحت عنوان i$ که مقدارش برابر با تابع از پیش تعریفشدهای در زبان PHP تحت عنوان ()rand است که یک عدد تصادفی تولید میکند بدین صورت که دستور دادهایم تا این عدد رَندوم در بازهٔ ۱ تا ۱۰ باشد. سپس شرطی در نظر گرفتهایم بدین شکل که به محض اینکه مقدار این عدد تصادفی برابر با ۲ شد، از داخل حلقه خارج شویم (دستور break این وظیفه را دارا است تا حلقه را متوقف نماید.)
کاربرد حلقهٔ For در دنیای واقعی
ذکر مثال از کاربردهای این نوع لوپ در توسعهٔ وب اپلیکیشنها، میتواند منجر به درک بهتر کاربردهایش گردد که یکی از آن موارد، ساخت منو به صورت دینامیک (پویا) است. به عنوان مثال داریم:
$menu = ['Java', 'Python', 'PHP', 'NodeJS'];
$count = count($menu);
echo "<ul>";
for ($index = 0; $index < $count; $index++) {
echo "<li><a href='#{$menu[$index]}'>{$menu[$index]}</a></li>";
}
echo "</ul>";
اگر به سورس خروجی اسکریپت فوق نگاه کنیم، خواهیم داشت:
<ul>
<li><a href='#Java'>Java</a></li>
<li><a href='#Python'>Python</a></li>
<li><a href='#PHP'>PHP</a></li>
<li><a href='#NodeJS'>NodeJS</a></li>
</ul>
در تفسیر اسکریپت فوق بایستی بگوییم آرایهای داریم تحت عنوان menu$ که حاوی نام برخی زبانهای برنامهنویسی است (البته نیاز به توضیح نیست که NodeJS زبان برنامهنویسی نیست!) سپس در متغیری تحت عنوان count$ و با استفاده از فانکشن از پیش تعریفشدهای در زبان PHP به نام ()count تعداد اندیسهای آرایهٔ menu$ را درآوردهایم که برابر است با چهار.
در ادامه، از آنجا که قصد داریم یک منو بسازیم، ابتدا با استفاده از دستور echo تگ آغازین <ul> را چاپ کردهایم؛ سپس با استفاده از حلقه اقدام به چاپ کردن عناصر داخل آرایه نمودهایم بدین صورت که شمارندهای تحت عنوان index$ با مقدار اولیهٔ صفر ایجاد کرده، سپس به عنوان شرط این حلقه گفتهایم مادامی که مقدار این شمارنده از مقدار متغیر count$ کوچکتر بود، این حلقه ادامه یافته و به عنوان پارامتر Step نیز دستور دادهایم تا در هر بار Iteration (چرخش) حلقه، یک واحد به مقدار متغیر index$ اضافه گردد.
داخل حلقه هم با استفاده از دستور echo تگهای آغازین و پایانی <li></li> را چاپ کرده و برای اینکه آیتمهای منو لینک باشند، از تگهای آغازین و پایانی <a></a> نیز استفاده نمودهایم. حال برای چاپ کردن اِلِمانهای آرایه ابتدا از علائم { } استفاده کردهایم چرا که پیش از این توضیح دادیم زمانی که بخواهیم مقادیری از یک آرایه که اِسترینگ (رشته) هستند را با استفاده از دستور echo چاپ کنیم، میبایست از این علائم استفاده نمود؛ سپس نام آرایهٔ مذکور (menu$) را نوشته و داخل علائم [ ] مرتبط با این آرایه، شمارندهٔ index$ را قرار دادهایم (همچنین به عنوان مقدار اَتریبیوت href تگ <a> نیز یک # قرار داده و نام زمان مد نظر را چاپ کردهایم.)
در حقیقت، زمانی که اسکریپت فوق اجرا میشود، در اولین Iteration (چرخش) شرط برقرار خواهد بود چرا که مقدار متغیر index$ که برابر با صفر است از مقدار متغیر count$ که برابر با چهار است کوچکتر است؛ لذا دستور echo اجرا شده و اولین لینک از منو (Java) روی صفحه چاپ میشود بدین صورت که با نوشتن [menu[$index$ دستور دادهایم خانهٔ اول (با اندیس صفر) از آرایهٔ menu$ چاپ شود. سپس یک واحد به مقدار متغیر شمارنده اضافه شده و این کار تا زمانی ادامه مییابد تا هر چهار اِلِمان آرایهٔ ما چاپ گردد. در نهایت هم با استفاده از دستور echo تگ پایانی <ul/> را چاپ کرده و منو تکمیل شده است. حال اگر بخواهیم منوی فوق را با تعداد خطوط کمتری بنویسیم، خواهیم داشت:
echo "<ul>";
for ($index = 0, $menu = ['Java', 'Python', 'PHP', 'NodeJS'], $count = count($menu); $index < $count; $index++) {
echo "<li><a href='#{$menu[$index]}'>{$menu[$index]}</a></li>";
}
echo "</ul>";
در واقع، پارامتر Initialization (شروع) میتواند شامل هر تعداد متغیری باشد که مد نظر داریم بدین صورت که آنها را با یک کاما از یکدیگر مجزا سازیم.
استفاده از حلقهٔ For به منظور ایجاد پسورد یا هَش
یکی دیگر از مثالهای کاربردی استفاده از این نوع لوپ (حلقه)، ساخت پسورد و یا اِسترینگی به عنوان هَش است. فرض کنیم قصد داریم برای کاربران سایت یک پسورد رَندوم هشت کاراکتری بسازیم (و یا مثلاً برای ساخت یک لینک بازیابی رمزعبور، نیاز به یک هَش داریم.) برای این منظور، به سادگی از این حلقه میتوانیم به صورت زیر استفاده نماییم:
$password = "";
for ($i = 0; $i < 8; $i++) {
$password .= chr(rand(0, 25) + 97);
}
echo "Your password is: $password";
به عنوان خروجی داریم:
Your password is: zialktrs
و اگر بار دیگر اسکریپت فوق را اجرا کنیم، خواهیم داشت:
Your password is: psarxbtf
میبینیم که پسوردها کاملاً رَندوم تولید شدهاند (البته در عین حال این نکته را هم در نظر داشته باشیم که در شرایط بسیار نادری ممکن است بر حسب تصادف دو پسورد کاملاً یکسان شوند که البته احتمال چنین چیزی بسیار پایین است.)
در تفسیر اسکریپت فوق بایستی بگوییم که ابتدا به ساکن یک متغیر تعریف کردهایم تحت عنوان password$ که خالی است. سپس با استفاده از یک حلقه، دستور دادهایم مادامی که مقدار متغیر i$ کمتر از عدد هشت است، این حلقه ادامه یابد. داخل این حلقه هم متغیری که پیش از این تحت عنوان password$ ساختیم را مقداردهی کردهایم بدین صورت که از دو تابع از پیش تعریف شده در زبان PHP تحت عناوین ()rand و ()chr استفاده کردهایم که به نظر میرسد تا این مرحله از آموزش به خوبی با کاربرد تابع ()rand آشنا شده باشید؛ لذا میپردازیم به کاربرد تابع جدید.
به طور خلاصه، کاربرد تابع ()chr در زبان PHP این است که کاراکتر معادل یک مقدار ASCII را در قالب اِسترینگی تککاراکتری باز میگرداند. در مثال فوق، گفتهایم که تابع ()rand عددی رِندوم مابین ۰ تا ۲۵ در اختیار ما قرار داده، سپس برای آنکه میزان تصادفی بودن آن را بیشتر کنیم، خروجی را با عدد اختیاری همچون ۹۷ جمع کرده و حاصلجمع آنها به عنوان پارامتر ورودی تابع ()chr در نظر گرفتهایم که این تابع هم حرف معادل با آن عدد را باز میگرداند.
پیش از این با مفهوم Concatenation آشنا شدهایم. با در نظر گرفتن این موضوع، در هر بار اجرای حلقهٔ فوق خروجی تابع ()chr را با استفاده از ساختار =. به متغیر password$ الحاق کردهایم (چسباندهایم) تا اینکه در نهایت مقدار این متغیر هشت حرف کاملاً تصادفی خواهد بود.