طی جلسات قبلی، در مورد متغیرها و انواع آنها تا حد مناسبی، صحبت کردیم. اما جلسه ی تکمیلی برای بحث متغیرها و همچنین معرفی ثابت ها(Constants) را بعد از جلسه ی توابع، ادامه خواهیم داد. ولی در این بخش، قرار است عملگرهای زبان PHP را معرفی کنیم.
احتمالاً با اکثر این عملگرها آشنایی دارید یا اینکه در طی جلسات قبلی، بعضاً به چشمتان خورده است.
در این جلسه قصد داریم، عملگرهای زبان PHP را با جزئیات کامل، معرفی کنیم.
* عملگرهای ریاضی: (Arithmetic Operators)
عملیات پایه ی محاسبات ریاضی، مانند جمع و تفریق را در نظر بگیرید، علامت (+) یا علامت (-) هرکدامشان بسته به جایی که استفاده شود، میتواند یک عملگر ریاضی محسوب شود. بطور مثال اگر علامت (+) قبل از عدد یا بین دو عدد بیاید، عملگر ریاضی بشمار میرود و پردازش میشود اما اگر این علامت، داخل یک رشته بیاید، بعنوان یک کاراکتر از آن رشته بحساب میآید و هیچ پردازشی صورت نمیگیرد.
لیست کامل عملگرهای ریاضی را در زیر ببینید:
Example | Name
---------------------------------------
+$a Identity
-$a Negation
$a + $b Addition
$a - $b Subtraction
$a * $b Multiplication
$a / $b Division
$a % $b Modulo
$a ** $b Exponentiation
$a
و $b
یک عملوند(Operand) میگویند.خط 1 و 2: علامت + و - قبل از متغیر، متغیر را به عددی(integer یا float) مثبت و منفی تبدیل میکند. حتی اگر متغیر یک string باشد.
خط 6: نتیجه ی تقسیم $a / $b
عددی از نوع float میباشد مگر اینکه هر دو عملوند از نوع integer باشند(اگر string باشند بصورت اتوماتیک یه integer تبدیل میشوند) و قابل تقسیم باشند که در اینصورت، نتیجه integer خواهد بود.
<?php
echo gettype(5 / 2); // double
//------------------------------//
echo gettype(10 / 2); // integer
همچنین اگر میخواهید فقط قسمت صحیح یک تقسیم را داشته باشید، میتوانید از تابع intdiv()
برای تقسیم استفاده کنید. یا اینکه نتیجه ی تقسیم را به عدد صحیح cast کنید:
<?php
$a = 15;
$b = 2;
$c = intdiv($a, $b);
var_dump($c); // int(7)
//------------------------------//
$a = 15;
$b = 2;
$c = (int) ($a / $b);
var_dump($c); // int(7)
خط 7: علامت % بین دو متغیر یا دو عدد، برابر است با باقیمانده ی تقسیم آن دو عدد:
<?php
$a = 5;
$b = 2;
echo $a % $b; // 1
// because 2 * 2 + 1 = 5
نکته: عملگر % باعث میشود عملوند ها(در مثال بالا $a
و $b
) به integer تبدیل شوند. پس اگر میخواهید باقیمانده ی تقسیم دو عدد اعشاری را بدست بیاورید، میتوانید از تابع fmod()
استفاده کنید:
<?php
$a = 10.75;
$b = 5.2;
$c = fmod($a, $b);
var_dump($c); // int(float 0.35)
// because 2 * 5.2 + 0.35 = 10.75
نکته: علامت نتیجه ی باقیمانده ی تقسیم دو عدد(%) با علامت مقسوم(عملوند اول) یکسان است، یعنی نتیجه ی $a % $b
هم علامت است با $a
:
<?php
echo (5 % 3) . '<br>'; // 2
echo (5 % -3) . '<br>'; // 2
echo (-5 % 3) . '<br>'; // -2
echo (-5 % -3) . '<br>'; // -2
خط 8: $a ** $b
یعنی $a
بتوان $b
:
<?php
$a = 5;
$b = 2;
echo $a ** $b; // 25
* عملگر رشته: (String Operator)
توسط عملگر .
میتوانید رشته ها را به یکدیگر، بچسبانید.
<?php
$result = 2;
echo 'Result: ' . $result . PHP_EOL; // Result: 2
* عملگر انتساب: (Assignment Operators)
عملگر انتساب یا اختصاص دادن، علامت =
است. البته توضیح خاصی ندارد ولی دقت داشته باشید این علامت برای چک کردن تساوی دو مقدار نمیباشد و فقط عبارت سمت راست مساوی را در عملوند سمت چپش میریزد. یعنی در دستور $a = 5;
مقدار 5 به متغیر $a
اختصاص داده میشود.
به مثال زیر توجه کنید:
<?php
$a = 5;
$c = ($b = 3) + $a;
echo $a . '<br>'; // 5
echo $b . '<br>'; // 3
echo $c . '<br>'; // 8
خط 3: همانطور که گفتیم، عبارت سمت راست علامت (=) اختصاص داده میشود به عملوند سمت چپ که اینجا متغیر $c
است.
اما عبارت سمت راست چیست؟
در سمت راست داخل پرانتز، مجددا یک عمل انتساب داریم، بنابراین با اجرا $b = 3
مقدار 3 به متغیر $b
اختصاص داده میشود. حالا اگر $b + $a
شود، حاصل جمع این دو متغیر، برابر است با 8، در نهایت مقدار 8 به متغیر $c
اختصاص داده میشود.
همچنین میتوانید چندین انتساب را پشت سرهم انجام دهید:
<?php
$level = $score = $time = $i = 0;
متغیرهای تعریف شده در مثال بالا، مقدار 0 دارند.
نکته: میتوانید عملگر انتساب را بصورت ترکیبی با عملگرهای ریاضی و عملگر رشته، استفاده کنید.
مثلاً زمانی که دستور شما $sum = $sum + 5;
است، میتوانید خلاصه ی آن، یعنی $sum += 5;
را بنویسید. هر دو دستور، مثل هم هستند.
روش های استفاده از عملگرهای ترکیبی را در زیر ببینید:
Example
---------------------------------------
$a += 1; // $a = $a + 1;
$a += $b; // $a = $a + $b;
$a += $b + 2; // $a = $a + $b + 2;
$a -= $b; // $a = $a - $b;
$a *= $b; // $a = $a * $b;
$a /= $b; // $a = $a / $b;
$a %= $b; // $a = $a % $b;
$a **= $b; // $a = $a ** $b;
---------------------------------------
$a .= '<br>'; // $a = $a . '<br>';
$a .= $b . PHP_EOL; // $a = $a . $b . PHP_EOL;
* عملگرهای مقایسه: (Comparison Operators)
تا پایان این جلسه، تمام عملگرهای مقایسه ای را معرفی میکنیم و بقیه ی عملگرها به جلسات بعدی موکول میشود.
عملگرهایی از قبیل ( >
و <
و ==
و ...) که دو مقدار را با یکدیگر مقایسه میکنند. حالا اگر مقایسه برقرار باشد، نتیجه ی آن TRUE یا 1 خواهد بود اما اگر مقایسه برقرار نباشد، نتیجه ی آن FALSE یا 0 یا هیچی خواهد بود.
echo true;
میبینید در خروجی، عدد 1 چاپ میشود اما اگر بنویسید echo false;
در خروجی هیچ چیزی چاپ نمیشود.حالا برای مثال عبارت 5 > 2
را در نظر بگیرید.
آیا شرط 5 > 2
صحیح است؟
طبیعتا این شرط برقرار است پس اگر بنویسید echo 5 > 2;
در خروجی، عدد 1 چاپ خواهد شد.
اما اگر بنویسید echo 5 < 2;
چیزی در صفحه، چاپ نمیشود. دلیلش اینست که شرط مقایسه برقرار نیست و نتیجه ی آن FALSE است.
در لیست زیر، عملگرهای مقایسه ای را ببینید:
Example | Name
---------------------------------------
$a == $b Equal
$a === $b Identical
$a != $b Not equal
$a <> $b Not equal
$a !== $b Not identical
$a < $b Less than
$a > $b Greater than
$a <= $b Less than or equal to
$a >= $b Greater than or equal to
$a <=> $b Spaceship
+ مقایسه اول $a == $b
: علامت ==
چک میکند که آیا $a
مساوی است با $b
بدنیست بدانید، در جلسه ی Type Casting گفتیم، در بسیاری از قسمت ها، عمل casting بصورت اتوماتیک انجام میشود. یکی از آن قسمت ها، اینجاست. برای مثال، اگر یک string را با یک عدد مقایسه کنید، آن string تبدیل به عدد خواهد شد. این مطلب را برای یادآوری گفتم تا بدانید علت true و false در بعضی از قسمت ها، برای چیست.
بنابراین در عملگرهای مقایسه ای، ابتدا type casting صورت میپذیرد و سپس مقایسه انجام میشود.(بجز دو عملگر که در ادامه میگوییم.)
برای اینکه کامل متوجه قضایا شوید، مثال های زیر بهمراه توضیحاتی که درباره یشان در پایین آورده ام، با دقت توجه کنید:
<?php
var_dump(0 == 'a'); // 0 == 0 -> true
var_dump('0' == 'a'); // '0' == 'a' -> false
//------------------------------//
var_dump('1' == '01'); // 1 == 1 -> true
var_dump('1' == '1a'); // '1' == '1a' -> false
//------------------------------//
var_dump('10' == '1e1'); // 10 == 10 -> true
var_dump(100 == '1e2'); // 100 == 100 -> true
//------------------------------//
var_dump('1000abcd' == 1e3); // 1000 == 1000 -> true
var_dump('1000abcd' == '1e3'); // '1000abcd' == '1e3' -> false
//------------------------------//
var_dump('mohsen' == 'mohsen'); // 'string' == 'mohsen' -> true
var_dump('mohsen' == 'MOHSEN'); // 'string' == 'MOHSEN' -> false
خط 2 var_dump(0 == 'a'); // true
: در مقایسه رشته و عدد، آن رشته تبدیل به عدد میشود. بنابراین رشته ی 'a'
به علت اینکه با عدد شروع نشده است به عدد 0 تبدیل میشود. در نتیجه 0 == 0
برابر true خواهد بود.
خط 3 var_dump('0' == 'a'); // false
: دو رشته داریم که رشته ی اول مقدارش عددی است و برابر 0 میباشد ولی رشته ی دوم حاوی کاراکتر میباشد، بنابراین این دو مقدار بصورت رشته ای مقایسه میشوند و تبدیلی صورت نمیگیرد. در نتیجه '0' == 'a'
برابر false خواهد بود.
خط 7 var_dump('1' == '01'); // ture
: دو رشته داریم که هر دو رشته مقدارشان عددیست و هیچ کاراکتری ندارند. بنابراین بصورت اتومات به مقدار عددی تبدیل میشوند. درنتیجه 1 == 1
برابر true خواهد بود.
خط 8 var_dump('1' == '1a'); // false
: دو رشته داریم که رشته اول مقدارش عددی است و برابر 1 میباشد اما در داخل رشته ی دوم، کاراکتر a
وجود دارد بنابراین چون دو رشته بصورت کامل عددی نیستند در نتیجه بصورت رشته ای مقایسه میشوند و هیچ تبدیلی صورت نمیگرد. پس '1' == '1a'
برابر false خواهد بود.
خط 12 var_dump('10' == '1e1'); // true
: دو رشته ی کاملا عددی داریم، بنابراین به جفتشان به عدد تبدیل میشوند. درنتیجه 10 == 10
برابر true خواهد بود.
نکته: 1e1
برابر عدد 10 میباشد. ( 1 * 10^1
)
خط 13 var_dump(100 == '1e2'); // true
: یک عدد و یک رشته داریم، پس رشته تبدیل به عدد خواهد شد. درنتیجه 100 == 100
برابر true خواهد بود.
خط 17 var_dump('1000abcd' == 1e3); // true
: یک رشته و یک عدد داریم، پس رشته تبدیل به عدد خواهد شد. در نتیجه 1000 == 1000
برابر true خواهد بود.
خط 18 var_dump('1000abcd' == '1e3'); // false
: دو رشته داریم که رشته ی اول بجز عدد، حاوی کاراکترهای abcd
میباشد و رشته ی دوم فقط عدد است. پس بخاطر وجود کاراکترهایی بغیر از عدد، این دو مقدار بصورت رشته ای مقایسه میشوند و هیچ تبدیلی صورت نمیگیرد. در نتیجه '1000abcd' == '1000
برابر false خواهد بود.
خط 23 var_dump('mohsen' == 'Mohsen'); // false
: دو رشته داریم، که برنامه این دو رشته را کاراکتر به کاراکتر بررسی میکند. اولین کاراکتر مقدار اول m
با اولین کاراکتر مقدار دوم M
برابر نیستند(کاراکتر M
در مقدار دوم، uppercase است و مقدار باینری آن با مقدار باینری m
تفاوت دارد) در نتیجه بقیه ی کاراکتر ها، مقایسه نخواهد شد و نتیجه ی این مقایسه false خواهد بود.
حالا ادامه ی عملگرهای مقایسه ای را بررسی کنیم.
+ مقایسه دوم $a === $b
: میگوید هم مقدارشان برابر باشد و هم type شان.(یعنی عیناً مثل هم باشند) بنابراین اگر مقدار و نوع برابر باشد، نتیجه ی مقایسه true خواهد بود.
===
)، دیگر تایپ ها بصورت اتوماتیک تبدیل نمیشوند(اصطلاحاً cast نمیشوند) مگر اینکه خودتان عمل cast را دستی انجام دهید.نکته: عملگرهایی که type را هم چک میکنند عمل casting را بصورت اتوماتیک انجام نمیدهند، مگر اینکه خودتان، دستی عمل cast را انجام دهید. پس به علت اینکه مرحله ی cast در این عملگر وجود ندارد، درنتیجه، سرعت این عملگر (یعنی
===
) کمی بیشتر از عملگر ==
میباشد.<?php
var_dump(0 === 'a'); // false
var_dump(0 === '0'); // false
var_dump('123' === 123); // false
var_dump('123' === '123'); // true
خط 1 var_dump(0 === 'a'); // false
: مقدارشان مساوی نیست و نوع اولی integer و دومی string است. در نتیجه false خواهد بود.
خط 2 var_dump(0 === '0'); // false
: مقدارشان مساوی است، اما نوعشان، اولی integer و دومی string است. در نتیجه false خواهد بود.
خط 3 var_dump('123' === 123); // false
: مقدارشان مساوی است، اما نوعشان، اولی string و دومی integer است. در نتیجه false خواهد بود.
خط 4 var_dump('123' === '123'); // true
: مقدارشان مساوی است و نوع جفتشان string است. در نتیجه true خواهد بود.
+ مقایسه سوم $a != $b
: اگر $a
نامساوی باشد با $b
نتیجه true خواهد بود. (این علامت متضاد عملگر ==
میباشد.)
<?php
var_dump(1 != 2); // true
var_dump('1' != '1a'); // true
var_dump(1 != '1a'); // false
var_dump('mohsen' != 'movahed'); // true
خط 4 var_dump(1 != '1a'); // false
: یک عدد و یک رشته، در نتیجه رشته تبدیل به عدد میشود، بنابراین 1 != 1
برابر false خواهد بود.
+ مقایسه چهارم $a <> $b
: مانند عملگر !=
میباشد.
+مقایسه پنجم $a !== $b
: اگر $a
نامساوی با $b
باشد یــــا نوع $a
با نوع $b
یکسان نباشد، نتیجه ی آن true خواهد بود. ( این عملگر متضاد است با عملگر ===
)
===
گفتیم، در این عملگر هم ، type عملوند ها بصورت اتوماتیک cast نخواهد شد. بدلیل اینکه دو عملوند باید عیناً مثل هم باشند.<?php
var_dump(1 !== '1'); // true
var_dump('mohsen' !== 'mohsen'); // false
var_dump(1 !== 1.); // true
خط 2: مقدار یکی است ولی نوعشان، اولی integer و دومی string است. نتیجه true خواهد بود.
خط 3: مقدار و توعشان یکسان است پس نتیجه false خواهد بود.
خط 4: مقدار یکی است ولی نوعشان یکی integer و دیگری float است. نتیجه true میباشد.
+ مقایسه ششم $a < $b
: اگر $a
کوچکتر از $b
باشد، نتیجه true خواهد بود.
+ مقایسه هفتم $a > $b
: اگر $a
بزرگتر از $b
باشد، نتیجه true خواهد بود.
+ مقایسه هشتم $a <= $b
: اگر $a
کوچکتر از $b
باشد یا $a
مساوی $b
باشد، نتیجه true خواهد بود.
+ مقایسه نهم $a >= $b
: اگر $a
بزرگتر از $b
باشد یا $a
مساوی $b
باشد، نتیجه true خواهد بود.
<?php
var_dump(1 < 2); // true
var_dump(1 < '2a'); // true
//------------------------------//
var_dump(1 > 2); // false
var_dump('a' > 'z'); // false
//------------------------------//
var_dump(1 <= '1bithub'); // true
var_dump(1 <= 1.); // true
//------------------------------//
var_dump(1 >= '1'); // true
var_dump('a' >= 'a'); // true
دیگه الان باید بدونید که بصورت اتوماتیک چطور عملیات type casting انجام میشود و علت جواب های true و false چیست.
+ مقایسه دهم $a <=> $b
: اگر $a
به ترتیب کوچکتر یا مساوی یا بزرگتر از $b
باشد، نتیجه ی آن -1(کوچکتر) و 0(مساوی) و 1(بزرگتر) خواهد بود.
<?php
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
//------------------------------//
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
//------------------------------//
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1
نکـات باقیمانده:
..1.. اگر یک عملوند NULL باشد و دیگری string، عملوند NULL به یک رشته ی خالی cast میشود.
<?php
var_dump(null == ''); // true
var_dump(null == '0'); // false
..2.. اگر عملوندی (نوعش مهم نیست) با یک عملوند از نوع boolean مقایسه شود، آن عملوند به boolean تبدیل خواهد شد.
نکته: در جلسه Type Casting گفتیم که یک آرایه خالی وقتی به boolean تبدیل میشود، آن آرایه تبدیل به false میشود.
<?php
var_dump(false < true); // true
var_dump(null < true); // false < true -> (true)
//------------------------------//
var_dump('true' == true); // true
var_dump('0' == false); // true
var_dump('false' == false); // false
//------------------------------//
$array1 = [];
$array2 = [1, 2];
var_dump($array1 == false); // true
var_dump($array2 == true); // true
خط 9 var_dump('false' == false); // false
: تبدیل رشته ی 'false'
به boolean، برابر true خواهد بود. در نتیجه true == false
برابر false خواهد بود.
به یک مثال مهم دیگر توجه کنید:
<?php
var_dump('bithub' != 0); // 0 != 0 -> (false)
var_dump('bithub' != false); // true != false -> (true)
خط 2: مقایسه ی string و integer است، بنابراین همانطور که قوانین را گفتیم، string به integer یعنی عدد 0 تبدیل میشود.(چون با عدد شروع نشده است.)
خط 3: مقایسه بین یک string و یک boolean انجام شده است. همانطور که گفتیم در مقایسه هر نوعی با boolean، هر دو به boolean تبدیل میشوند. بنابراین رشته ی 'bithub'
به true تبدیل میشود.
..3.. اگر NULL با یک عملوند از هر نوعی (بجز string که در نکته 1 گفتیم تبدیل به رشته خالی میشود) مقایسه شود، هر دو عملوند به boolean تبدیل میشوند.
<?php
var_dump(null == 0); // false == false -> (true)
var_dump(null < -1); // false < true -> (true)
var_dump(null == array()); // false == false -> (true)
var_dump(null == array(1, 2)); // false == true -> (false)
//------------------------------//
var_dump(null == 'bithub'); // '' == 'bithub' -> (false)
var_dump(null == '0'); // '' == '0' -> (false)
..4.. اگر عملوندی از نوع resource با عملوندی از نوع integer مقایسه شود، عملوند resource به integer تبدیل خواهد شد.
<?php
$a = fopen('file1', 'r'); // Resource id #3
var_dump(3 == $a); // 3 == 3 -> true
وقتی resource تبدیل میشود به integer، عدد آیدی آن میماند.
..5.. در مقایسه ی دو آرایه، طول و مقادیر و همچنین ایندکس هایشان چک میشود، اگر یکی باشد، باهم برابر اند.
<?php
$a = [1, 2, 3];
$b = [1, 2, '3'];
var_dump($a == $b); // true
var_dump($a === $b); // false
همانطور که در مثال میبینید، در ===
بین دو آرایه، جدای ازینکه جفتهای key/value باید یکسان باشند، type هم چک میشود.
نکته: اگر دو آرایه را با هم جمع($array1 + $array2
) کنید، آرایه ی سمت راست(یعنی $array2
) به آرایه ی سمت چپ عملگر(یعنی $array1
) اضافه میشود. اگر مقدار ایندکس برابر در دو آرایه وجود داشته باشد، آن خانه از آرایه ی دوم نادیده گرفته میشود و از عنصر آرایه ی اول استفاده میشود.
<?php
$a = [1, 2, 3, 'bithub' => 4];
$b = [5, 6, 7, 10 => 8, 'bithub' => 9, 10];
$c = $a + $b;
echo '<pre>' . print_r($c, true) . '</pre>';
/*
* Output:
* Array
* (
* [0] => 1
* [1] => 2
* [2] => 3
* [bithub] => 4
* [10] => 8
* [11] => 10
* )
*/
البته جمع دو آرایه، ارتباطی با عملگرهای مقایسه ای ندارد و در دسته ی عملگرهای آرایه قرار میگیرد، ولی چون نکته ی 5 را در دسته ی عملگرهای مقایسه ای بیان کردم، این را هم همینجا گفتم تا موضوعش تکمیل بشه و دسته ای جدا باز نکنیم.
..6.. در مقایسه بین دو عملوندی که یکی از نوع آرایه باشد و دیگری از هر نوعی(بجز boolean و null که در نکته 2 و 3 بالاتر توضیح دادیم)، عملوند آرایه بزرگتر خواهد بود.
<?php
$array = []; // empty
var_dump(22 < $array); // true
var_dump('bithub' < $array); // true
var_dump(true < $array); // false
var_dump(null < $array); // false < false -> (false)
var_dump(false < $array); // false < false -> (false)
var_dump(true == $array); // true == false -> (false)
var_dump(null == $array); // false == false -> (true)
var_dump(false == $array); // false == false -> (true)
خط 4 var_dump(22 < $array); // true
: عملوند آرایه یا یک integer مقایسه شده، پس فرقی نمیکند که آرایه خالی یا پر باشد، عملوند آرایه بزرگتر است.
خط 5 var_dump('bithub' < $array); // true
: باز هم مانند قبلی، آرایه بزرگتر از string خواهد بود.
خط 7 var_dump(true < $array); // ture < false -> (false)
: با توجه به نکته ی 2(بالاتر توضیح دادم) در مقایسه ی هر نوعی با boolean، آن نوع هم تبدیل به boolean میشود. در اینجا آرایه ی خالی به false تبدیل میشود و در نتیجه true < false
برقرار نخواهد بود و نتیجه ی شرط false است.
خط 8 var_dump(null < $array); // false < false -> (false)
: با توجه به نکته ی 3(چند خط بالاتر توضیح دادم)، جفت عملوندها به boolean تبدیل میشوند. بنابراین false < false
برقرار نخواهد بود و نتیجه ی شرط false خواهد بود.
در پایان این بخش، دو عملگر مقایسه ای دیگر را معرفی میکنیم و معرفی بقیه ی عملگرهای زبان PHP را به جلسات بعدی موکول میکنیم.
عملگر سه گانه یا سه تایی: (Ternary Operator)
این عملگر از سه قسمت تشکیل شده است. فرمش به شکل (expr1) ? (expr2) : (expr3)
میباشد.
قسمت اول، شرط را مشخص میکند.
اگر شرط برقرار باشد(true باشد) عبارت بعد از ?
اجرا خواهد شد، اما اگر شرط برقرار نباشد، عبارت بعد از علامت :
اجرا خواهد شد.
<?php
$valid = 20;
$x = $valid == 20 ? 'yes' : 'no';
echo $x; // yes
//------------------------------//
$var = 5;
$result = ($var > 2 ? true : false); // true
همچنین میتوانید از این عملگر، بصورت توو در توو استفاده کنید:
<?php
$a = 2;
$b = 10;
echo $a == true ? ($b > $a ? ($a / $b > 0 ? 'yes' : '3') : '2') : '1'; // yes
نکته: در PHP اگر متغیری تعریف نشده باشد، مقدارش null
میباشد. به مثال زیر توجه کنید:
<?php
var_dump($bithub); // null
حالا اگر بخواهیم، چک کنیم اگر متغیری وجود داشت، یک سری از کارها انجام شود و در غیر اینصورت کار دیگری انجام شود، میتوانیم با ساختار شرطی سه گانه، بصورت زیر بنویسیم:
<?php
$x = $bithub !== null ? $bithub : 0;
الان با توجه به نکاتی که گفته ایم، باید بدانید با توجه به نوع متغیرها، در شرط چه اتفاقی می افتد.
$bithub != false
یا $bithub != 0
یا $bithub != null
بنویسیم. توجه داشته باشید که در این سه شرط !=
آمده است پس ابتدا type casting صورت میگیرد و سپس مقایسه انجام میشود ولی اگر مثلا $bithub !== false
بنویسید و یک متغیر وجود نداشته باشد، به علت اینکه در !==
عمل type casting صورت نمیگیرد، شرط $bithub !== false
برابر true خواهد بود که مقصود ما، این نیست.حالا با توجه به مثال بالا، اگر شرط برقرار باشد، $x = $bithub
خواهد بود و گرنه $x = 0
میشود.
البته، یک مشکل وجود دارد. این مشکل را در چند خط پایینتر میگویم.
این شرط سه گانه را میتوانیم، کوتاهتر هم بنویسیم:
<?php
$x = $bithub ?: 0;
میبینید که جمله ی بین علامت ?
و :
را حذف کرده ایم. با اینکار اگر $bithub
وجود داشته باشد، $x = $bithub
میشود.
سؤال: چرا شرط !== null
حذف شده؟
پاسخ: اگر مینوشتیم $bithub !== null
و شرط برقرار میشد(یعنی متغیر وجود داشت)، چیزیکه در متغیر $x
ریخته میشد، نتیجه ی شرط بود، یعنی $x = true
میشد، چون نتیجه $bithub !== null
برابر true بود.
نکته: وقتی شرطی را بدون هیچ مقایسه ای مینوسیم(مانند این مثال)، در درونش != 0
دارد.(میتوانید == true
و != false
هم تعبیر کنید.)
<?php
$bithub = 22;
$x = $bithub != false ?: 0;
var_dump($x); // true
//------------------------------//
$bithub = 22;
$x = $bithub ?: 0;
var_dump($x); // int 22
اما آن مشکلی که چند خط بالاتر گفتیم، چیست؟
وقتی متغیری وجود نداشته باشد، خطای Notice تولید میشود تا برنامه نویس، در جریان باشد که این متغیر وجود ندارد: Notice: Undefined variable: bithub
یک راه حل، استفاده از تابع isset()
میباشد. این تابع چک میکند، اگر متغیری که این تابع میدهیم، مقدارش null
نبود(یا وجود نداشت)، نتیجه اش true خواهد بود وگرنه false میدهد.
حالا اگر بخواهیم مثالی از این تابع بنویسیم، به شکل زیر میشود:
<?php
$x = isset($bithub) ? $bithub : 0;
با استفاده از isset()
اگر متغیری وجود نداشته باشد، دیگ خطایی چاپ نمیشه!!
حالا اگر بخواهیم با استفاده از این تابع، ساختار Ternary را بصورت کوتاهتر بنویسیم، به مشکل میخوریم:
<?php
$bithub = 22;
$x = isset($bithub) ?: 0;
علت مشکل اینست که (در بالا گفتیم) اگر شرط برقرار باشد و متغیر $bithub
وجود داشته باشد، نتیجه ی isset($bithub)
که true است، داخل $x
ریخته میشود.
برای کوتاه نویسی، PHP 7 عملگری اضافه کرده است که در زیر آن را معرفی میکنیم.
عملگر Null Coalescing:
اما PHP 7، عملگر Null Coalescing را معرفی کرده که میتواند جایگزینی برای کوتاه سازی شرط بالا باشد.
فرم این عملگر به شکل (expr1) ?? (expr2)
میباشد.
اگر شرط expr1
برقرار نباشد، عبارت expr2
اجرا خواهد شد وگرنه اگر شرط expr1
برقرار بود، همان عبارت expr1
اجرا خواهد شد.
حالا مثال بالا را با این عملگر، انجام میدهیم:
<?php
$a = 123;
echo $a ?? false; // 123
اگر $a
وجود نداشت، این عملگر، درست مثل isset()
خطایی نشان نمیدهد.
نکته: از این عملگر میتوان بصورت توو در توو استفاده نمود.
<?php
$a = null;
$b = null;
$c = 1;
$d = 2;
echo $a ?? $b ?? $c ?? $d; // 1
با توجه به شرط بالا، متغیرهای $a
و $b
وجود ندارند، بنابراین $c
چاپ میشود.
مثال: یک مثال توو در توو هم برای عملگر Ternary بصورت کوتاه سازی شده، مینویسیم:
<?php
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 1 ?: 0 ?: 3 ?: 2; //1
echo 2 ?: 1 ?: 0 ?: 3; //2
echo 3 ?: 2 ?: 1 ?: 0; //3
نکته پایانی: در این جلسه، از آرایه ها فقط دو نکته گفتیم. اکثر مقایسه ها در آرایه ها، بین مقادیر خانه های آرایه انجام میگیرد و از آنجایی که خانه های آرایه، مقادیری از نوع string و integer و boolean و ... خواهند داشت، پس تمام گفته های این جلسه برای خانه های آرایه هم صدق میکند. بقیه مقایسه ها بیشتر با توابع مخصوص آرایه شکل میگیرد که در جلسات آینده، به آنها میپردازیم.
<?php
$array = [null, true, -2, 'bithub'];
var_dump($array[0] == false); // false == false -> (true)
var_dump($array[1] == $array[2]); // true == ture -> (true)
var_dump($array[2] == $array[3]); // -2 == 0 -> (false)
var_dump($array[3] == $array[0]); // "bithub" == "" -> (false)
var_dump($array[0] == 0); // false == false -> (true)
مطالب سایت را بدون ذکر منبع (http://bithub.ir) در جایی منتشر نکنید. با تیشکر.