PDA

View Full Version : رفتار دردسرساز switch



eshpilen
سه شنبه 03 دی 1392, 09:56 صبح
تست:

<?php

$v=0;

switch($v) {

case 'hello':
echo 'hello';
break;
case 'goodbye':
echo 'goodbye';
break;
default:
echo 'default';
break;

}

?>
خروجی: hello

این رفتار غیرمنتظره switch دیشب در برنامم یه باگ ایجاد کرده بود که قدم به قدم تست کردم تا رسیدم به switch و فهمیدم جریان چیه!

من switch رو به این شکل تغییر دادم تا دیگه نظیر چنین مواردی رخ ندن:

<?php

$v=0;

switch("$v") {

case 'hello':
echo 'hello';
break;
case 'goodbye':
echo 'goodbye';
break;
default:
echo 'default';
break;

}

?>

colors
سه شنبه 03 دی 1392, 10:19 صبح
این if و else هم همین مشکل رو دارن!

colors
سه شنبه 03 دی 1392, 10:21 صبح
البته با عملگر == این مشکل رو داره نه با ===

eshpilen
سه شنبه 03 دی 1392, 10:40 صبح
من نمیخواستم از === استفاده کنم، چون گاهی ممکن بود یک رشته بهش بدم و گاهی هم مثل همین مثال یک عدد باشه. یعنی اینطوری انعطاف بیشتری داره.


این if و else هم همین مشکل رو دارن!راست میگی عجیبه ها!

var_dump('hello'==0);
true میده!

بنظر میرسه دوباره PHP گند زده :لبخند:
من تنها چیزی به این عجیبی و بدی که یادم هست ویژگی «رجیستر گلوبالز» بود.
اون زمان وقتی این ویژگی احمقانه رو دیدم و با دردسرهای امنیتی بزرگی که ایجاد میکرد مواجه شدم، مطمئن شدم که طراحانش یجورایی ناشی بودن!
الانم ظاهرا همون داستان داره به شکل دیگری تکرار میشه.
آخه چه وضعشه، انعطاف و زبان سطح بالا و دینامیک تایپ درست، ولی دیگه نه در این حد چیزهای عجیب و غیرمنتظره که میتونن براحتی باگ و مسائل امنیتی پنهان ایجاد کنن!

آدم به زبان برنامه نویسی هم نتونه اعتماد کنه دیگه سنگ روی سنگ بند نمیشه!!

colors
سه شنبه 03 دی 1392, 11:04 صبح
چه میکنه این php, مسی...

$v = 1;
$v = settype($v, 'null'); // object - float - integer ... (only for 0)

if($v == 'hello'){
echo 'hello';
}
elseif($v === 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}

MMSHFE
سه شنبه 03 دی 1392, 11:07 صبح
این مسئله چیز خاصی نیست و PHP هم به قول شما گند نزده! مسئله اینه که ازنظر عملگر == رشته 'hello' و عدد 0 با هم برابر هستن. چرا؟ چون موقع تبدیل نوع رشته هایی که با عدد شروع نشه، مساوی صفر درنظر گرفته میشه ولی اگه با عدد شروع بشه، تا جایی که بتونه رو جدا میکنه و بقیه رو حذف میکنه. مثلاً '25hello' برابر با عدد 25 میشه. توی سایتش هم اشاره کرده (لینک (http://www.php.net/manual/en/control-structures.switch.php)) :

Note: Note that switch/case does loose comparision (http://www.php.net/manual/en/types.comparisons.php#types.comparisions-loose).
بهتره برای موارد اینچنین، از عملگر === استفاده کنید یا اینکه قبلش با یک if جداگانه، درصورت عددی بودن متغیر، اصلاً وارد switch نشین یا هر راهکار دیگه که مدنظرتونه.

ابوذر محمودی
سه شنبه 03 دی 1392, 11:26 صبح
خب حالت جا اومد ؟ :بامزه: تا تو باشی یه متغیر رشته ای رو با 0 مقدار دهی نکنی :لبخند:
اینم میشد :
$v="";

colors
سه شنبه 03 دی 1392, 11:30 صبح
جناب شهرکی پس اینی که مقدارش 1 میشه چی؟

$v = 1;
$v = settype($v, 'null');
echo $v.'<br>';

if($v == 'hello'){
echo 'hello';
}
elseif($v === 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}
1 و hello که برابر نیست!

eshpilen
سه شنبه 03 دی 1392, 11:34 صبح
این مسئله چیز خاصی نیست و PHP هم به قول شما گند نزده! مسئله اینه که ازنظر عملگر == رشته 'hello' و عدد 0 با هم برابر هستن. چرا؟ چون موقع تبدیل نوع رشته هایی که با عدد شروع نشه، مساوی صفر درنظر گرفته میشه ولی اگه با عدد شروع بشه، تا جایی که بتونه رو جدا میکنه و بقیه رو حذف میکنه. مثلاً '25hello' برابر با عدد 25 میشه. توی سایتش هم اشاره کرده (لینک (http://www.php.net/manual/en/control-structures.switch.php)) :

مهندس اینا که گفتی همه توجیه بودن و یجورایی انگار طرز پیاده سازیش رو گفتید یا اینکه انگار یه محدودیت فنی در این زمینه وجود داره.
ما در سطح منطقی و انتظار برنامه نویس و امنیت برنامه باید بهش نگاه کنیم، و این زبان برنامه نویسی است که باید خودش رو با این انتظار تطبیق بده. شاید بخصوص که یک زبان برنامه نویسی سطح بالا باشه!

شما در کدام زبان دیگری چنین چیز عجیبی میبینید؟
چرا واسه اونا محدودیتی نبوده؟
چرا اونا رو به این شکل طراحی نکردن؟

مثلا در جاوااسکریپت، که همین الان با تست دارم بهتون میگم، و اونم یک زبان داینامیک تایپ و سطح بالا و مربوط به وب است و با داده های مشابهی سروکار داره:
<script>
document.write('0'==0);
</script>
خروجی: true
اما این:
<script>
document.write('hello'==0);
</script>

خروجی: false

جاوااسکریپت از این نظر و از نظر کاربرد به PHP خیلی شبیه است. اون عملگر === رو هم داره. ولی در همچین موردی چنین کاری نکرده و البته کسی هم انتظار نداره! همین غیرمنتظره بودن و عدم درک منطق از سوی برنامه نویس هست که درست نیست. اگر منطقی داره، باید برنامه نویس هم بفهمه و انتظار داشته باشه. ما از منطق و انتظار منطقی صحبت میکنیم، نه محدودیت های فنی و نحوهء پیاده سازی. درواقع هیچ محدودیت فنی و مشکل پیاده سازی در این مورد وجود نداره و میتونستن از منطقی مشابه بقیهء زبانهای دینامیک و سطح بالا و وبی پیروی کنن. اینطوری از این نظر که بین زبانها سازگاری وجود داشت هم خوب بود، و از این نظر که برنامه نویس گیج نشه و خطا نکنه هم خوب بود. یعنی حتی اگر منطقی برای این رفتار بنظرشون میرسید (که تاحالا ندیدم)، بازهم ممکن بود وزن این سازگاری و هماهنگی یادگیری و کار، بر اون منطق و فایده بچربه.

MMSHFE
سه شنبه 03 دی 1392, 11:39 صبح
اتفاقاً هست! اگه قبل از if با gettype نوع v$ رو نگاه کنید میبینید که نوشته bool و پر واضحه که ازنظر == هر مقداری بجز 0 و null و '' و امثال اون، برابر با true هست. درمقابل 1 هم وقتی بعنوان bool نگاه بشه، یعنی true پس شرط اول درسته. دقت کنید که توی settype نمیشه نوع متغیر رو null بگذاریم. اگه میخواین واقعاً null بشه باید بگین ;v = null$

colors
سه شنبه 03 دی 1392, 11:41 صبح
حرفتون درست.
پس این چیه؟

$v = "Colors";
echo $v.'<br>';
$v = settype($v, 'string');
echo $v.'<br>';

if($v === 'hello'){
echo 'hello';
}
elseif($v == 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}
یکی این چند خطتو تحلیل کنه!

//

$v = 95;
echo $v.'<br>';
$v = settype($v, 'integer');
echo $v.'<br>';

if($v === 'hello'){
echo 'hello';
}
elseif($v == 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}

MMSHFE
سه شنبه 03 دی 1392, 11:45 صبح
خوب این برمیگرده به معماری داخلی و نحوه پیاده سازی Implicit Type Casting داخلی PHP که البته حق با شماست (ازنظر من) و هیچکس هم ادعا نکرده PHP بدون نقصه. پیشنهاد میکنم بعنوان bug گزارش کنید تا توی minor upgrade بعدی اصلاح بشه.

ابوذر محمودی
سه شنبه 03 دی 1392, 11:54 صبح
حرفتون درست.
پس این چیه؟

$v = "Colors";
echo $v.'<br>';
$v = settype($v, 'string');
echo $v.'<br>';

if($v === 'hello'){
echo 'hello';
}
elseif($v == 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}
یکی این چند خطتو تحلیل کنه!

//

$v = 95;
echo $v.'<br>';
$v = settype($v, 'integer');
echo $v.'<br>';

if($v === 'hello'){
echo 'hello';
}
elseif($v == 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}

این مدلیشو دیگه تا حالا ندیده بودم ، که تایپو استرینگ تعریف کنی ، بعد تو gettype ؛ bool برگردونه

eshpilen
سه شنبه 03 دی 1392, 12:06 عصر
هیچ زبانی اندازهء PHP اینقدر بی بند و بار نیست :لبخند:

دیدید که جاوااسکریپت در این مورد اینطور فکر و عمل نمیکنه.
و البته فکر نمیکنم هیچ زبانی جز PHP هم چنین کاری کرده باشه. شاید حتی در کل تاریخ برنامه نویسی چنین موردی نبوده!!

راستی الان با پایتون هم اومدم تست کنم.
پایتون هم داینامیک تایپ هست، اما حتی 0=='0' رو هم به رسمیت نمیشناسه!

print(0=='0')
خروجی: False

eshpilen
سه شنبه 03 دی 1392, 12:11 عصر
البته من شخصا PHP رو خیلی دوست دارم.
بقول یارو، این حرفا چیزی از ارزشهاش کم نمیکنه :لبخند:
آلترناتیو مناسبی سراغ ندارم که بتونه جای PHP رو بگیره.
یک زبان بازمتن، مجانی، با این همه انعطاف و راحتی و امکانات.
میگن دندون اسب پیشکشی رو که نمیشمارن!
درکل چیز خوبیه.
ولی این موارد رو باید قبول کرد که اشتباهات طراحی هستن.
یا حداقل باید نسبت بهشون خیلی مشکوک بود.
هرچیزی باید منطقی داشته باشه.
و باید تمامی جوانبش رو درنظر گرفت.

اگر این موارد رو توش اصلاح کنن خب زبان بهتری میشه!
ولی اینکه نه یک بار، بلکه چند بار نظیر چنین تصمیماتی در طراحی گرفته و اجرا میشن، آدم رو به یه فکرهایی و وحشت میندازه :لبخند:

MMSHFE
سه شنبه 03 دی 1392, 12:38 عصر
حرفتون درست.
پس این چیه؟

$v = "Colors";
echo $v.'<br>';
$v = settype($v, 'string');
echo $v.'<br>';

if($v === 'hello'){
echo 'hello';
}
elseif($v == 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}
یکی این چند خطتو تحلیل کنه!

//

$v = 95;
echo $v.'<br>';
$v = settype($v, 'integer');
echo $v.'<br>';

if($v === 'hello'){
echo 'hello';
}
elseif($v == 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}
آقا درست صحبت کنین یعنی چی PHP بی بند و باره؟ من تعصب دارم روش ها! کدتون اشتباهه. settype رو که اینطوری صدا نمیزنن. باید بنویسید:


$v = "Colors";
settype($v, 'string');
if($v === 'hello'){
echo 'hello';
}
elseif($v == 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}
//output: no

یعنی اینکه خروجی settype رو دوباره توی متغیر v$ نگذارین. چون اینطوری باعث میشه نتیجه تبدیل که true (تونسته تبدیل کنه) یا false (نتونسته تبدیل کنه) توی v$ ذخیره بشه و طبیعیه که نوع متغیر v$ میشه boolean !

eshpilen
سه شنبه 03 دی 1392, 12:40 عصر
میدونی چی میگم مهندس!

موضوع اینه که از نظر برنامه نویس وقتی اینطور مقایسه ها رو داریم انجام میدیم بطور معمول دنبال مقایسه بر اساس ارزش عددی اونا نیستیم.

ارزش عددی یک رشته، یعنی تبدیلش به عدد، توابع صریح خودش رو داره و بعضی وقتا که نیاز داریم انجام میدیم.
ولی اینکه PHP این رفتار و موارد معدود رو به کل مقایسه ها تعمیم بده، جالب نیست! چون در عمل احتمالش خیلی کمه که منظور ما از اون مقایسه همونی بوده باشه که PHP داره بر اساسش عمل میکنه، و احتمال اینکه اینطور مقایسه مفید باشه و به نتیجهء منطقی درستی در برنامه منجر بشه خیلی کمه.

اینکه یه عدد توی یه رشته باشه اگر کاراکترهای عددی به تنهایی باشن خب یه چیزی، ولی وقتی کاراکترهای دیگری هم هستن، یا در مثال ما اصلا هیچ کاراکتر رقم توی رشته نیست، خیلی احتمالش کمه که منظور مقایسهء بر اساس ارزش عددی بوده باشه.
در اینطور موارد باید مقایسهء رشته ای باید صورت بگیره و اون عدد به رشته تبدیل بشه و با رشتهء دیگر مقایسه بشه، نه اینکه رشته به عدد تبدیل بشه!

واقعا در منطق و الگوریتم برنامهء شما چقدر احتمال مقایسهء معنا دار چنین مواردی میره؟!
منظورم اینه که یک رشته رو بخواید بر اساس ارزش عددیش با عدد مقایسه کنید. البته در موارد عادی ما این کار رو زیاد انجام میدیم، اما در اینطور موارد خود اون رشته هم محتوی یک عدده. خیلی کم پیش میاد که کاراکترهای غیررقمی هم درش باشن و منظور ما مقایسه بر اساس ارزش عددی باشه، و بازهم کمتر از این پیش میاد که اصلا هیچ کاراکتر رقمی توش نباشه و منظور ما مقایسه بر اساس ارزش عددی بوده باشه.
منکه چیزی به ذهنم نمیرسه.
طبیعتا احتمالش کمه و احتمال بیشتر مقایسهء رشته ایه.
بقیهء زبانهای داینامیک هم از همین پیروی میکنن.
بعضیا حتی سختگیرتر هم هستن.
خود داینامیک تایپ بودن توسط بعضیا مورد انتقاده و از دید و جنبه هایی یجورایی بی بند و باری و مایهء ایجاد باگ و برنامه نویسی بی دقت تلقی میشه، بعد PHP اومده رفتار سلیقه ای و غیرمنتظره رو به حد اعلی رسونده؛ بخاطر همین میگم که خیلی بی بند و باره :لبخند:
البته من اعتقادی ندارم که داینامیک تایپ بودن خوب نیست، بلکه بنظر من حداقل در حیطهء زبانها و کاربردهای خاص خودش خیلی هم چیز خوبیه (مزایاش از معایبش خیلی بیشتره)، ولی PHP دیگه دنده خلاص رو زده رفته یجایی که اصلا معلوم نیست کجاست و چرا! داره خلاف زبانهای هم خانواده دیگر عمل میکنه، و منطقش هم مشخص نیست!

colors
سه شنبه 03 دی 1392, 13:03 عصر
یعنی اینکه خروجی settype رو دوباره توی متغیر v$ نگذارین. چون اینطوری باعث میشه نتیجه تبدیل که true (تونسته تبدیل کنه) یا false (نتونسته تبدیل کنه) توی v$ ذخیره بشه و طبیعیه که نوع متغیر v$ میشه boolean !
بله درسته حق با شماست. ولی در هرصورت تونسته تبدیل کنه و مقدار درست (1) رو داره برمیگردونه و اینجا بازم مقدار boolean رو داره با رشته goodbye برابر تشخیص میده!

ابوذر محمودی
سه شنبه 03 دی 1392, 13:08 عصر
$v = "Colors";
settype($v, 'string');
if($v === 'hello'){
echo 'hello';
}
elseif($v == 'goodbye'){
echo 'goodbye';
}
else{
echo 'no';
}
//output: no

یعنی اینکه خروجی settype رو دوباره توی متغیر v$ نگذارین. چون اینطوری باعث میشه نتیجه تبدیل که true (تونسته تبدیل کنه) یا false (نتونسته تبدیل کنه) توی v$ ذخیره بشه و طبیعیه که نوع متغیر v$ میشه boolean !

خدا وکیلی اینقدر که محو دستوارت شده بودیم ، منم اصلا متوجه تعریف غلط settype نشده بودم "مثل همین دستوارت که من غلط نوشتم و درستش دستورات هست" ولی متوجه نشدید :لبخند:

هیچ زبانی اندازهء PHP اینقدر بی بند و بار نیست
نه اینطورم نیست ، اتفاقاَ چون متغیرها صریح تعریف نمیشن و php بر اساس محتوی نوع رو مشخص میکنه این رفتار ها طبیعی هست ، چون تا جایی که ممکنه سعی میکنه نوع رو به هم تبدیل کنه ، خب البته حقم داره ، هی شما گیجش میکنین یه طرف عدد میدین یه طرف رشته ، طفلی تو رو دروایسی گیر میکنه !
مثلا مگه شما جرات دارین تو سی شارپ بگین(if ("0" == 0 :لبخند:
مظلوم گیر آوردین؟:لبخند:
به نظر من اینا خصوصیات خوبیه ،به شرطی که درست استفاده شه، ایراد نیست.
Type Juggling (http://www.php.net/manual/en/language.types.type-juggling.php)
Comparison Operators (http://php.net/manual/en/language.operators.comparison.php)

MMSHFE
سه شنبه 03 دی 1392, 13:11 عصر
بله درسته حق با شماست. ولی در هرصورت تونسته تبدیل کنه و مقدار درست (1) رو داره برمیگردونه و اینجا بازم مقدار boolean رو داره با رشته goodbye برابر تشخیص میده!
بله درسته که تونسته تبدیل کنه ولی دقت کنید که elseif با == مقایسه کرده نه با ===
همه چیز با وجود اینکه بنظر میاد بی نظمی داره، از یک منطق خاص (که بهرحال ممکنه بنظر برخی درست نیاد) پیروی میکنه و اینطور نیست که کلاً منطق نداشته باشه.

ابوذر محمودی
سه شنبه 03 دی 1392, 13:12 عصر
بله درسته حق با شماست. ولی در هرصورت تونسته تبدیل کنه و مقدار درست (1) رو داره برمیگردونه و اینجا بازم مقدار boolean رو داره با رشته goodbye برابر تشخیص میده!
از نظر php هر چیز غیر صفر و تهی، true میشه.



$a == $b //Equal TRUE if $a is equal to $b after type juggling.
$a === $b //Identical TRUE if $a is equal to $b, and they are of the same type.

دقت کنین که برای عملگر == اینطوریه که اول Type Juggling انجام میشه بعد شرط برابر بودن بررسی میشه ، ولی تو === Type Juggling نداریم.
یعنی به قول آقای شهرکی همه چیز با وجود اینکه بنظر میاد بی نظمی داره، از یک منطق خاص پیروی میکنه ، در واقع این ما هستیم که داریم بی نظمی ایجاد میکنیم و میخوایم همه چیز اونطور که ما میخوایم انجام شه در صورتی که تو خود مستندات php اینارو کامل توضیح داده.


$a=true;
$b="hello";
if($a==$b) //Type Juggling anjam mishe
echo "One";

if($a===$b) // Type Juggling anjam Nemishe , type ha check mishe bad mohtava
echo "Two";

//
//output: One
//

colors
سه شنبه 03 دی 1392, 14:21 عصر
ا

$a=true;
$b="hello";
if($a==$b) //Type Juggling anjam mishe
echo "One";

if($a===$b) // Type Juggling anjam Nemishe , type ha check mishe bad mohtava
echo "Two";

//
//output: One
//


منطق جالبی نیست!
به نظرم مث بیشتر زبانهای دیگه نباید اینطور باشه!!

MMSHFE
سه شنبه 03 دی 1392, 14:26 عصر
خوب اگه قرار نبود اینطوری باشه، عملگر === رو میشه بگین دقیقاً برای چی گذاشتن؟ یکی از امکانات خوب PHP همین بحث تبدیل خودکار نوع متغیرهاست و البته حساس نبودن به نوع متغیرها. حالا گفته اگه جایی خواستین به نوع هم حساس باشین، اینهم عملگرشه. کجاش جالب نیست؟

colors
سه شنبه 03 دی 1392, 14:42 عصر
خوب اگه قرار نبود اینطوری باشه، عملگر === رو میشه بگین دقیقاً برای چی گذاشتن؟ یکی از امکانات خوب PHP همین بحث تبدیل خودکار نوع متغیرهاست و البته حساس نبودن به نوع متغیرها. حالا گفته اگه جایی خواستین به نوع هم حساس باشین، اینهم عملگرشه. کجاش جالب نیست؟

حق با شماست

eshpilen
چهارشنبه 04 دی 1392, 11:13 صبح
به نظر من اینا خصوصیات خوبیه ،به شرطی که درست استفاده شه، ایراد نیست.
Type Juggling (http://www.php.net/manual/en/language.types.type-juggling.php)
Comparison Operators (http://php.net/manual/en/language.operators.comparison.php)

همه چیز با وجود اینکه بنظر میاد بی نظمی داره، از یک منطق خاص (که بهرحال ممکنه بنظر برخی درست نیاد) پیروی میکنه و اینطور نیست که کلاً منطق نداشته باشه. بحث نظر نیست. باید دلیل منطقی و فایدهء کافی داشته باشه.
چرا زبانهای دیگه اینطور عمل نمیکنن؟ حتی زبانهای هم خانواده.
چیزهایی که شما تاحالا گفتی فقط اشاره به طرز کارکرد و منطق داخلی پیاده سازی خاص PHP برای اینطور عملیات بود. یعنی شما میگی PHP به هر شکلی که پیاده کرده بود و هرطور اون پیاده سازی کار میکرد، منطقی است و برنامه نویسان هم باید بپذیرن؟
همچین چیزی نیست!
این زبان برنامه نویسی و نحوهء پیاده سازی اونه که متاثر از منطق و انتظار و فایده در سطوح بالاتره. زبان برنامه نویسی است که بر اساس اون منطق و انتظارات باید طراحی بشه.
در سطح برنامه نویسی بگید این مورد خاص چه منطق و فایده ای داره جز اینکه غیرمنطقی و غیرمنتظره بنظر میاد و احتمال بیشترش اینه که با منظور برنامه نویس و منطق برنامه تطابق نداشته باشه و در نتیجه ایجاد باگ بکنه.
یه زمانی رجیسترگلوبالز رو هم با یکسری توجیهات خودشون طراحی کردن، و تا مدتها روش اصرار داشتن خیلی ها و هنوزم قبول نمیکردن و بعضیا همین الان هم قبول ندارن که یک طراحی اشتباه بود، ولی دست آخر مجبور شدن حذفش کنن! اگر واقعا طراحی درست و عاقلانه و سودمندی بود، پس چرا در عمل مجبور شدن حذفش کنن؟ کم چیزی نیست یک چنین تغییر اساسی بعد از مدتها در یک زبان برنامه نویسی.

----------------------------------------------------------


از نظر php هر چیز غیر صفر و تهی، true میشه.
...
یعنی به قول آقای شهرکی همه چیز با وجود اینکه بنظر میاد بی نظمی داره، از یک منطق خاص پیروی میکنه ، در واقع این ما هستیم که داریم بی نظمی ایجاد میکنیم و میخوایم همه چیز اونطور که ما میخوایم انجام شه در صورتی که تو خود مستندات php اینارو کامل توضیح داده.اون منطق نیست. یه راه حل و پیاده سازی رو خودشون فرض کردن و پیاده کردن بعد بهش میگن منطق؟
منم اینطوری میتونم یه منطق دیگه از خودم اختراع کنم و در یک زبان برنامه نویسی پیاده سازیش کنم، بعد برنامه نویسان باید بپذیرن و عاقلانه بدونن؟
و چرا زبانهای دیگر اینطور عمل نمیکنن؟ یعنی سلیقه ای بوده؟ اگر سلیقه ای نیست، پس منطق و معیارش چیه در هر موردی؟ نمیشه که در هر زبانی یک منطق متفاوت داشته باشه و به طرز کاملا متفاوتی رفتار کنه! حداقل بطور معمول اینطور نیست!!
در هیچ زبانی ‎‎'hello'==0 شرطی درست فرض نمیشه.
مگر زبانهای دیگری دینامیک تایپ نیستن و Implicit type conversion و این حرفا رو ندارن؟ پس چرا PHP یه طرفه و همهء زبانهای دیگه یه طرف دیگه؟ یعنی PHP خیلی نابغه بوده و نگرش جدید و مفیدتری رو ارائه کرده در این زمینه؟ منکه فکر نمیکنم!
----------------------------------------------------------

خوب اگه قرار نبود اینطوری باشه، عملگر === رو میشه بگین دقیقاً برای چی گذاشتن؟ یکی از امکانات خوب PHP همین بحث تبدیل خودکار نوع متغیرهاست و البته حساس نبودن به نوع متغیرها. حالا گفته اگه جایی خواستین به نوع هم حساس باشین، اینهم عملگرشه. کجاش جالب نیست؟

مهندس بحث من اون یک مورد خاص بود، نه اینکه کلا با تبدیل خودکار نوع متغییرها و حساس نبودن به نوع مخالف باشن. زبانهای مشابه در این زمینه هستن که کم و بیش این کارها رو انجام میدن؛ مثل جاوااسکریپت که مثال زدم. ولی در تمام اون زبانها خیلی چیزها در این زمینه یکسان یا مشابه هستن یا حداقل منطقشون خیلی راحتتر قابل درک و قابل انتظاره برای برنامه نویس و کدی که توی برنامه کار میکنه در اکثر موارد منظورش همون نوع مقایسه است و درست عمل میکنه، ولی این یک مورد خاص در PHP که بر اساسش ‎‎'hello'==0 میشه، در هیچ زبانی مشابهش وجود نداره (شخصا سراغ ندارم) و چیزی در این حد غیرمنتظره و بدون منطق قابل درک در سطح برنامه نویس ندیدم تاحالا در این زمینه و احتمال بیشتر در منظور و منطق کدهای برنامه زمانی که چنین مقایسه هایی بخوان صورت بگیره بر خلاف چیزی است که PHP برای مقایسه درنظر میگیره.

eshpilen
چهارشنبه 04 دی 1392, 11:23 صبح
بحث تبدیل نوع خودکار و اینها برای کمک به برنامه نویسی راحتتر و سریعتر وجود دارن.
این تبدیل ها طوری هستن و بر اساس منطقی عمل میکنن که احتمال بیشتر در برنامه در کدها اونه که منظور همون بوده باشه و منطق برنامه به این شکل درست اجرا بشه. همینطور کشکی نیامدن یه فرضی بکنن و درستش کنن. سلیقه ای نیست که! در نهایت هم برنامه نویس سطح بالا میخواد با اون زبان کار بکنه و این ویژگیها باید قابل درک و انتظار و مفید برای برنامه نویس سطح بالا باشن، نه اینکه بیایم دلیل در سطح دودویی براش بیاریم که بله چون اینطور فرض کردن و اینطور پیاده سازی کردن پس اینطوری شده و منطقش اینه!!


خوب اگه قرار نبود اینطوری باشه، عملگر === رو میشه بگین دقیقاً برای چی گذاشتن؟عملگر === در زبانهای دیگر هم هست. مثل جاوااسکریپت. ولی اونا ‎‎'hello'==0 رو درست فرض نمیکنن!
یعنی اگر ‎‎'hello'==0 نشه، اونوقت باید همه این بند و بساط رو جمع کنن؟
یعنی این چیزا در زبان دیگری وجود نداره؟

یجوری صحبت میکنید انگار فقط در PHP دینامیک تایپ و تبدیل نوع و این چیزها رو داریم!
اگر قبول دارید در زبانهای دیگری هم این چیزها هست، پس منطق اونا چی بوده و چطور پیاده سازیش کردن که هیچکدام از اونا ‎‎'hello'==0 رو درست نمیگیرن؟

در PHP هم بنظر من اگر شده باید یه استثناء برای این مورد بذارن.
مثلا موقع مقایسهء رشته با عدد، اگر رشته واقعا محتوی یک عدد بود بیاد و رشته رو تبدیل به عدد بکنه و با عدد دیگر مقایسه کنه، ولی اگر رشته محتوی عدد نبود، دیگه نباید دو طرف رو برابر فرض کنه.
این قاعده ایه که در جاوااسکریپت اعمال شده. مثالش رو هم براتون گذاشتم.

بهزاد علی محمدزاده
چهارشنبه 04 دی 1392, 11:55 صبح
این اشکالی که شما پیدا کردی به نظر من دقیقا اسمش باگ هست و اشکال هم هست . قابل توجیه کردن هم نیست . و حدس میزنم این یه سرنخ بود که دستت اومد و من منتظر باگ های بعدی هم هستم . چون توجهت رو به این مساله جلب کرده امکانش هست که بازم موارد اینچنینی رو بهش برخورد کنی .

من یه نکته ایی رو می خوام یادآوری کنم به کسانی که در حال یادگیری هستند و احیانا اینجا رو می خونن :

این تاپیک داره به دوستانی که مثل من تازه کار هستند میگه که لطفا زبانی رو که باهاش برنامه می نویسید و مطالعه کنید و بشناسید . نه فقط کار با دیتابیس . بلکه زبان رو مطالعه باید کرد و گاهی باید تحقیقاتی رو در زمینه زبان های برنامه سازی مثل مدیریت حافظه ... مفسر ... نوع های داینامیک و ( اینکه اینها چه هستند و مزایاو معایب اونها رو باید درک کرد ... ) رو داشته باشید . گاهی آسیب پذیری ها (http://cert.um.ac.ir/index.php?r=Vulner/index) رو دنبال کنید . مقالات پیشرفته تر ... مباحثی که نکات ( Tips ) ها رو بیان می کنند و دنبال کنید تا برنامه های بهینه بنویسید و مزایا و معایب زبان برنامه نویسی تون رو بشناسید .

MMSHFE
چهارشنبه 04 دی 1392, 12:40 عصر
این حرف شما کاملاً صحیحه. امتیاز اصلی PHP که اینهم داریم میگیم Open Source هست هم همینه که میشه جزئیات طراحی داخلیش رو هم خوند و فقط با سعی و خطا مشکلات رو پیدا نکنیم! من هیچ جا نگفتم منطق PHP در این مورد درسته. فقط گفتم منطق و روش پیاده سازیش اینه و اینطور نیست که همینطوری رو هوا و هربار Random یک چیزی رو ارزیابی کنه. حالا اگه ازنظر من و شما این منطق پشت پرده، درست نیست، خوب میتونیم گزارش کنیم. مهمترین حسن جامعه Open Source هم همینه که به Bug Report اهمیت زیادی میدن و واقعاً رفع میکنن (فقط من گفتم منطقش چیه که موقتاً تا وقتی که بخواد رفع بشه، بدونید از چه سیستمی داره برای کار استفاده میکنه تا بتونید خودتون با سایر ابزارها توی کدهاتون جلوی بروز مشکلات احتمالی رو بگیرین). توی مدرک تخصصی ZCE هم بخاطر همین قبیل مسائله که یکسری از مفاهیم Core زبان PHP مطرح میشه و صرفاً توانایی تولید سایت با PHP مدنظر نیست.

ابوذر محمودی
چهارشنبه 04 دی 1392, 12:41 عصر
از نظر php هر چیز غیر صفر و تهی، true میشه.
اون منطق نیست. یه راه حل و پیاده سازی رو خودشون فرض کردن و پیاده کردن بعد بهش میگن منطق؟

اگه دقت کنی توی زبان سی هم ما بولین نداریم ، ولی اتفاقا خوبشو داریم یعنی هر چیز صفر و تهی F و بقیه T ، جاوا اسکریپتم همینطوره ، پس این مورد رو php از خودش در نیاورده.


اگر قبول دارید در زبانهای دیگری هم این چیزها هست، پس منطق اونا چی بوده و چطور پیاده سازیش کردن که هیچکدام از اونا ‎‎'hello'==0 رو درست نمیگیرن
برای این مورد که میگی ‎‎'hello'==0 باید همه زبان هایی که دینامیک تایپ دارن رو بررسی کرد .

خب الان چرا تو سی وقتی متغیر کاراکتری x رو که توش حرف a داره رو با 97 تست میکنی باید برابر باشه؟ مگه a با 97 برابره؟
حالا a رو میگیم کد اسکیش برایر 97 هست ، ali چی؟
چرا به C این اشکال وارد نیست ولی الان به PHP این اشکال وارده؟

ابوذر محمودی
چهارشنبه 04 دی 1392, 12:54 عصر
این اشکالی که شما پیدا کردی به نظر من دقیقا اسمش باگ هست و اشکال هم هست
دقیقا باگه؟ شما اینجا رو بررسی کنین :


<?php
$foo = "0"; // $foo is string (ASCII 48)
$foo += 2; // $foo is now an integer (2)
$foo = $foo + 1.3; // $foo is now a float (3.3)
$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
$foo = 5 + "10 Small Pigs"; // $foo is integer (15)
?>


foo = 5 + "10 Small Pigs"; شما مستندات php رو مطالعه کردین که میگین باگه؟ بعد چطور بقیه رو توصیه می کنید که اول زبان رو مطالعه کنند؟

برای کسی که درست استفاده نکنه و آشنا نباشه با نوع طراحی اون زبان ، بله دقیقاَ باگ هست.

البته نه این که فکر کنید من تعصب خاصی دارم روش ، نه ، همه ما تو PL خوندیم که اینا جزو مسایل اولیه هست که تو طراحی زبان پیش میاد ، و صرف دانش کممون از تئوری های یک زبان نمیتونیم بگیم این ایراده ، باگه ، مشکله و ...

ابوذر محمودی
چهارشنبه 04 دی 1392, 13:03 عصر
خیلی وقتا پیش میاد که ما تو شرط ها گاهی از == و گاهی هم از === استفاده می کنیم ، اگه یک بار از خودمون میپرسیدیم فرق == با === چیه ، بعد به مستندات php رجوع میکردیم الان این مساله ای که خود php بهش با مثال اشاره کرده رو منسوب به باگ خطرناک نمیکردیم.

این مساله همین الان کشف نشده که بهش لقب کشف باگ میدیم ، کسان دیگه ای هم بودن که به این مساله برخوردن :
مثلا :
why-does-0-hello-return-true-in-php (http://stackoverflow.com/questions/5894350/why-does-0-hello-return-true-in-php)

eshpilen
چهارشنبه 04 دی 1392, 18:24 عصر
اگه دقت کنی توی زبان سی هم ما بولین نداریم ، ولی اتفاقا خوبشو داریم یعنی هر چیز غیر صفر و تهی F و بقیه T ، جاوا اسکریپتم همینطوره ، پس این مورد رو php از خودش در نیاورده.
فکر کنم باید اون «غیر» رو حذف کنی!
بعدشم خب اینا چه ربطی به مورد ما داره؟
من بحثم یه چیزی مثل ‎‎'hello'==0 هست که هیچ معنی منطقی نمیده و فایده ای در برنامه نویسی نداره که بعکس منشاء مشکل و باگ میشه.
اتفاقا اینکه زبانهای دیگر هم باوجود این شباهت ها، ‎‎'hello'==0 رو قبول ندارن نشون میده که این مورد به موارد دیگری که ذکر کردی ربطی نداره و اگر موارد دیگر به اون شکل بود دلیل نمیشه اینطور موارد اینطوری باشه.


برای این مورد که میگی ‎‎'hello'==0 باید همه زبان هایی که دینامیک تایپ دارن رو بررسی کرد .بعید میدونم زبان دیگری پیدا کنید که اینطور باشه.
چون از نظر منطقی و فایدهء برنامه نویسی دلیل موجهی براش دیده نمیشه.
شما موردی پیدا کردید خبرمون کنید!
اگر خودتون هم منطق و فایده ای بنظرتون میرسه براش خب مطرح کنید!
من قبلا برای خلافش دلیل آوردم. استدلالهای بنده بنظرتون نادرست بود؟


خب الان چرا تو سی وقتی متغیر کاراکتری x رو که توش حرف a داره رو با 97 تست میکنی باید برابر باشه؟ مگه a با 97 برابره؟
حالا a رو میگیم کد اسکیش برایر 97 هست ، ali چی؟
چرا به C این اشکال وارد نیست ولی الان به PHP این اشکال وارده؟ تاجاییکه یادمه، در سی کاراکتر و رشته دو نوع مجزا هستن.
رشته رو که اصلا نمیتونی بصورت مستقیم مقایسه کنی، و باید از توابع مخصوصش برای این کار استفاده کنی (فکر کنم اسم یکیش strcmp بود).
اونم که شما رشتهء ali رو مقایسه کردی نمیدونم عملا تست کردی و جواب میده یا نه، ولی بهرحال مقایسهء رشته با عدد بوسیلهء عملگر == یه چیز استاندارد و مشخص شده و معناداری نیست در زبان سی. احتمالا بخاطر همین فقط کاراکتر اولش رو دیده و به همون صورت تک کاراکتر اولش مقایسه کرده.
بعدم سی خب یک زبان سطح پایین و سیستمی است و مقایسش با زبان سطح بالا و وبی مثل PHP فکر نمیکنم زیاد جالب باشه! بهتره PHP رو با زبانهای هم خانواده و هم سطح خودش مقایسه کنیم. بهرحال سی هم زبان قدیمی ای است و از اون زمان خیلی چیزها بهتر شدن و اضافه شدن و تغییر کردن و سینتاکس و رفتار سی لزوما معیار و اثبات کلی برای تمام زبانها و تمام سطوح و کاربردها و تمام زمانها نیست.


مگه a با 97 برابره؟
حالا a رو میگیم کد اسکیش برایر 97 هستبله دیگه سی کاراکتر رو با عدد، بر اساس کد اسکی کاراکتر مقایسه میکنه. و این در سی خیلی کاربرد داره.
درحالیکه اینطور مقایسه ها در PHP بر اساس کد اسکی نیستن، پس باید یه منطق و فایدهء دیگری داشته باشن.

eshpilen
چهارشنبه 04 دی 1392, 19:02 عصر
ببین سی فکر میکنم اصلا داستانش از اساس فرق داره.
سی که مثل زبانهای سطح بالا نیست.
در سی شما شاید در ظاهر بیای و رشته رو با عدد مقایسه کنی، که حتی شاید تابع strcmp رو هم بتونی واسه این استفاده کنی و خطایی هم نده.
ولی موضوع اینه که سی خودش اصلا ایده ای در اینطور موارد نداره و اینطور مقایسه ها براش تعریف نشدن و معنا و استانداردی ندارن.
مقایسهء رشته و عدد در سی تعریف نشده و بی معناست.
مقایسهء رشته با عدد در زبانهای برنامه نویسی سطح بالا معنی داره، ولی در سی نه.
سی یک زبان سطح پایینه که یکسری چیزها رو اصلا چک نمیکنه. یعنی میخوام بگم اینکه وقتی به خیال خودتون عدد و رشته رو مقایسه میکنید خطایی نمیده، دلیل بر این نمیشه که اینطور مقایسه در سی تعریف شده و معنا و منطقی داره.
در سی مثلا شما میتونید براحتی از محدودهء یک آرایه هم خارج بشید و داده های شما با همدیگر و با کد اجرایی برنامه تداخل کنن؛ سی در زمان کامپایل و زمان اجرا به شما خطایی در این زمینه نمیده و فقط زمانی متوجه میشید مشکلی وجود داره که برنامه بطور غیرعادی/اشتباه عمل میکنه و جوابهای غلط میده و کارهای اشتباه میکنه یا اینکه کلا crash میکنه!

ولی بحثی که درمورد PHP داریم قضیش متفاوته و درمورد چیزهای تعریف شده و معنا دار و از قبل درنظر گرفته شده و فکر شده و طراحی شده است که PHP در زمان اجرا نسبت به اونا آگاهی و کنترل داره، و باید منطق و استانداری براشون وجود داشته باشه.

پس این مورد در سی و PHP فقط در ظاهر مشابه هستن، و در باطن از نظر ماهیتی قابل مقایسه نیستن.
رفتار سی در این مورد (مقایسهء رشته و عدد) تصادفی است، اما رفتار PHP از قبل پیشبینی شده و منطق و هدفی داره.

تازه اون مقایسهء کاراکتر و عدد هم که در سی معنا داره، بر اساس کد اسکی صورت میگیره و در برنامه های سی کاربرد زیادی داره. و یک خصیصهء اساسی اون کاراکتر با عدد واقعا با هم برابره که شرط درست درمیاد.

ابوذر محمودی
چهارشنبه 04 دی 1392, 19:30 عصر
فکر کنم باید اون «غیر» رو حذف کنی!
خوب شد گفتی :لبخند: اشتباه تایپی بود
حالا مابقیش باشه بعداَ الان باید برم جایی وقت نیست تایپ کنم:گل:

ابوذر محمودی
چهارشنبه 04 دی 1392, 22:05 عصر
اونم که شما رشتهء ali رو مقایسه کردی نمیدونم عملا تست کردی و جواب میده یا نه، ولی بهرحال مقایسهء رشته با عدد بوسیلهء عملگر == یه چیز استاندارد و مشخص شده و معناداری نیست در زبان سی. احتمالا بخاطر همین فقط کاراکتر اولش رو دیده و به همون صورت تک کاراکتر اولش مقایسه کرده.
درسته اصلا نمیشه و فقط کاراکتر اول رو میگیره ، البته من ali رو تست نکردم ab رو تست کردم و به صورت char s='ab' تعریف کردم.


که بعکس منشاء مشکل و باگ میشه.
اینو دیگه یکم منصف باش ، مشکل و باگ از طرف کاربر ایجاد میشه ، اونم به خاطر عدم آشنایی با اون زبان ، وگرنه اینو که خود سایت php با مثال گفته دیگه.


$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
$foo = 5 + "10 Small Pigs"; // $foo is integer (15)

ببین عدد رو با رشته جمع کرده ، یعنی تا جایی که تو رشته عدد بوده تبدیل کرده مابقی رو نه ، خب موقع مقایسه هم همین امر هست. چون تو مستندات ذکر شده که برای == نوع چک نمیشه ، اول تبدیل نوع انجام میشه به یک نوع قابل قیاس بعد شرط بررسی میشه و گفته اگه میخواین نوع هم مقایسه بشه از === استفاده شه.


بعدم سی خب یک زبان سطح پایین و سیستمی است و مقایسش با زبان سطح بالا و وبی مثل PHP فکر نمیکنم زیاد جالب باشه! بهتره PHP رو با زبانهای هم خانواده و هم سطح خودش مقایسه کنیم.
اون که آره ، ولی خب یکم از مقایسه با جاوا اسکریپت آبرومندتره :لبخند:

بهزاد علی محمدزاده
چهارشنبه 04 دی 1392, 22:18 عصر
دوست گرامی این مثال شما ربطی به نمونه ایی که بالا گذاشتن نداره ! این از صحبت ما جداست :


<?php

$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
$foo = 5 + "10 Small Pigs"; // $foo is integer (15)
?>

در اینجا از از 10 به بعد نادیده گرفته میشه . در جاوا اسکریپت هم همینه و اصلا بحثی رو این نیست و ربطی به موضوع ما نداره .


?php

$v=0;

switch($v) {

case 'hello':
echo 'hello';
break;
case 'goodbye':
echo 'goodbye';
break;
default:
echo 'default';
break;

}

?>

من به عنوان برنامه نویس اگر این کد رو بهم بدن و بگن کدام بخش اجرا میشه ؟ انتظارم و جواب echo default هست . شما همین و ببر توی جاوا اسکریپت و اجرا کن :


var v=0;

switch(v) {

case 'hello':
alert('hello');
break;
case 'goodbye':
alert('goodbye');
break;
default:
alert('default');
break;

}

حداقل در تستی که من انجام دادم بخش default اجرا شد و انتظار من و برآورده کرد ... حالا این دوستمون امتحان کرده و hello‌ اجرا شده !!! و ما میگیم اشکال هست و واقعا هم در برنامه اشکال به وجود میاره ... شما هم انتظار همچین اجرایی رو ندارین .

دقت کن که منظور ما این مثال هایی که شما آوردی نیست .

ابوذر محمودی
چهارشنبه 04 دی 1392, 22:35 عصر
سی که مثل زبانهای سطح بالا نیست.
:متفکر:

سی یک زبان سطح پایینه
:متفکر:
اون حدیثت یادته؟


یعنی میخوام بگم اینکه وقتی به خیال خودتون عدد و رشته رو مقایسه میکنید خطایی نمیده، دلیل بر این نمیشه که اینطور مقایسه در سی تعریف شده و معنا و منطقی داره.
یعنی پس به قول دوستان یک عدد باگ کشف شد:چشمک:

حالا حرف من چیه ؛ ما که از تئوری و دلایل تیمی که php رو طراحی کردن آگاهی کامل نداریم و صرفا فقط از خود زبان داریم استفاده میکنیم و کمی به مستنداتش آگاهی داریم.
اینکه من بیام چند تا مطلب تو سطح دانش خودم بگم و شما هم متقابلاَ ، چیزی رو تغییر نمیده ؛ درسته در این وسط خیلی چیزا به چالش کشیده میشه و جالبم هست ، ولی خروجی در آخر نخواهد داشت .
مگه اینکه گزارش کنین .

بهزاد علی محمدزاده
چهارشنبه 04 دی 1392, 22:45 عصر
یه مجری رادیو می گفت : تپق زدن بین حرف حق سخنران هست . ۰ یعنی کسی که مجری هست و مدام حرف می زنه یا سخنران هست حالا ممکنه یه لحظه توی حرف زدنش اشکالی پیش بیاد ) .

به نظر من باگ هم حق برنامه نویسه ... اگر زبانی طراحی نشه ! یا برنامه ایی نوشته نشه باگی هم به وجود نمیاد !!! ولی وقتی طراحی و نوشته شد بله باگ هم داره .

ابوذر محمودی
چهارشنبه 04 دی 1392, 22:46 عصر
دوست گرامی این مثال شما ربطی به نمونه ایی که بالا گذاشتن نداره ! این از صحبت ما جداست :



در اینجا از از 10 به بعد نادیده گرفته میشه . در جاوا اسکریپت هم همینه و اصلا بحثی رو این نیست و ربطی به موضوع ما نداره .



من به عنوان برنامه نویس اگر این کد رو بهم بدن و بگن کدام بخش اجرا میشه ؟ انتظارم و جواب echo default هست . شما همین و ببر توی جاوا اسکریپت و اجرا کن :


var v=0;

switch(v) {

case 'hello':
alert('hello');
break;
case 'goodbye':
alert('goodbye');
break;
default:
alert('default');
break;

}

حداقل در تستی که من انجام دادم بخش default اجرا شد و انتظار من و برآورده کرد ... حالا این دوستمون امتحان کرده و hello‌ اجرا شده !!! و ما میگیم اشکال هست و واقعا هم در برنامه اشکال به وجود میاره ... شما هم انتظار همچین اجرایی رو ندارین .

دقت کن که منظور ما این مثال هایی که شما آوردی نیست .

بهزاد عزیز اتفاقاَ داره دیگه ، چون این بخشی از تبدیل نوعش هست یا به قول خودشون type-juggling ، یک طرف نوع عددی هست و طرف دیگه نوع رشته که اولش هم عدده ، خب برای جمع باید دو طرف به نوع عددی تبدیل شه دیگه مگه نه؟
خب پیش فرض تو نوع عددی صفره دیگه ، وقتی پیدا نمیکنه پیش فرض 0 در نظر میگیره. خب موقع مقایسه با == هم اول تبدبل میکنه بعد مقایسه
من بحثم اینه که این باگ نیست چون تو مستندات سایت PHP برای == به همه این شبهه ها جواب داده.
اگه قراره باگ تلقی شه ، برای وقتی هست که برنامه نویس بدون آگاهی به type-juggling و == و === بیاد برنامه بنویسه.

ابوذر محمودی
چهارشنبه 04 دی 1392, 22:54 عصر
یه مجری رادیو می گفت : تپق زدن بین حرف حق سخنران هست . ۰ یعنی کسی که مجری هست و مدام حرف می زنه یا سخنران هست حالا ممکنه یه لحظه توی حرف زدنش اشکالی پیش بیاد ) .

به نظر من باگ هم حق برنامه نویسه ... اگر زبانی طراحی نشه ! یا برنامه ایی نوشته نشه باگی هم به وجود نمیاد !!! ولی وقتی طراحی و نوشته شد بله باگ هم داره .
صدرصد.
تصحیح میکنم باگ حق مسلم ماست.:چشمک:

من که زیاد وقت ندارم بیام انجمن ، هر ماه یه دو سه روز میام ، ولی اگه کسی میخواد شرکت کنه خوبه مثل بقیه بحث های مشابه به جنجال کشیده نشه.
پیشاپیش ، پساپیش از کلیه عزیزان و همراهان گرامی ، اگه مطلبی گفتم که ناراحت شدن ، یا به نحوی دلخور شدن عذرخواهم.

eshpilen
پنج شنبه 05 دی 1392, 08:27 صبح
درسته اصلا نمیشه و فقط کاراکتر اول رو میگیره ، البته من ali رو تست نکردم ab رو تست کردم و به صورت char s='ab' تعریف کردم.
شما برای مقدار کاراکتر فقط یک کاراکتر باید بذارید.
معلومه که وقتی مقدارش رو char تعریف کردید فقط کاراکتر اول رو میگیره.
بعد اومدی میگی رشته ali رو با عدد 97 مقایسه کردی!؟


اینو دیگه یکم منصف باش ، مشکل و باگ از طرف کاربر ایجاد میشه ، اونم به خاطر عدم آشنایی با اون زبان ، وگرنه اینو که خود سایت php با مثال گفته دیگه.


$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
$foo = 5 + "10 Small Pigs"; // $foo is integer (15)

ببین عدد رو با رشته جمع کرده ، یعنی تا جایی که تو رشته عدد بوده تبدیل کرده مابقی رو نه ، خب موقع مقایسه هم همین امر هست. چون تو مستندات ذکر شده که برای == نوع چک نمیشه ، اول تبدیل نوع انجام میشه به یک نوع قابل قیاس بعد شرط بررسی میشه و گفته اگه میخواین نوع هم مقایسه بشه از === استفاده شه.
اکثر زبانهای داینامیک تایپ تبدیل های خودکار و موارد مشابهی دارن، ولی نه دیگه درحد PHP به این شکلهای افراطی و غیرمنتظره (بخصوص مورد ‎‎'hello'==0).
مواردی که زبانهای دیگه دارن عملا در برنامه نویسی کاربرد زیاد دارن و وقتی چنان کدی در برنامه وجود داره، احتمال زیاد منظور برنامه نویس هم همون بوده از نظر منطقی و آماری.
الان این کدی که شما میاری کاربردش در برنامه نویس چقدره؟ اگر نگیم هیچی، ولی خیلی کمه. فرض کن طرف دوم یک متغییر بود که توش اون رشته در برنامه در زمان اجرا جای گرفته (میتونسته مقادیر دیگری هم داشته باشه)؛ در چنین مواردی بسیار محتمل است که مشکلی در برنامه وجود داشته که چنان مقداری در اون متغییر قرار گرفته و داره با یک عدد مقایسه یا جمع میشه. در زبانهای دیگر این منجر به خطا میشه، و به این شکل برنامه نویس یا کاربر مطلع میشه و از زیردست دررفتن و منجر به خسارت بیشتر شدن چنین مواردی جلوگیری میشه.
ربطی هم به این نداره که بگیم خب باید حتما عملگر === رو استفاده میکرد و تقصیر برنامه نویس بوده، وگرنه در تمام موارد باید از === استفاده کنیم چون در تمام موارد ممکنه چنین باگ و مشکلی در هرجایی از برنامه پیش بیاد. تمام باگها و اهمیتشون رو که نمیشه از قبل و با اطمینان زیاد پیشبینی کرد!

البته == میتونه تا یک حدی ناامن باشه، که هست. اصولا چیزهایی مثل داینامیک تایپ بودن و implicit type conversion مقداری ریسک دارن و میتونن باعث برنامه نویسی کم دقت تر و از زیردست در رفتن باگها بشن، ولی این ریسک درمقابل مزایا و راحتی و سرعتی که در برنامه نویسی ایجاد میکنن کمتره.
ولی این حدی که PHP اون رو ناامن کرده، اونم بخاطر مواردی که در برنامه نویسی کاربرد غالبی ندارن، دیگه نوبره! یعنی توی فکرم که طراحان PHP اینقدر کم دانش و بصیرت بودن که فقط دوتا جزییات و منطق فنی سطح پایین رو دیدن و فکر کردن چون زبانهای دینامیک از این کارها میکنن پس میشه تاهر حدی در این زمینه پیش رفت و هرکاری کرد همینطوری!!
قضاوت و استدلالهای اونا شاید مثل قضاوت و استدلالهای شماست. یعنی افرادی که در این زمینه ها هیچگونه دانش و تخصص و صلاحیتی ندارن. من باز حداقل چیزهایی در این موارد و در زبانهای مختلف خوندم تاحالا و متوجه شدم. چیزی که من تاحالا دیدم و برداشت کردم، همون موارد و استدلالهایی هست که تاحالا براتون گفتم.


اون که آره ، ولی خب یکم از مقایسه با جاوا اسکریپت آبرومندتره :لبخند: جاوااسکریپت مگه چشه؟
جاوااسکریپت زبانی با شباهت های ساختاری و نزدیکی کاربرد است که به بحث ما ارتباط دارن. ضمنا استاندارد و تشکیلاتی هم داره واسه خودش! جاوااسکریپت کوچکتر و کم کاربردتر از PHP هست، ولی از نظر ساختاری و استاندارد شدگی و علمی بودن فکر میکنم سرتر از PHP باشه! منم بخاطر همین مسائل و همچنین بلد بودن و در دسترس بودنش ازش بعنوان مثال استفاده کردم.

سی درمقابل، میتونه مقایسهء خیلی دورتری باشه. سی یک زبان برنامه نویسی سیستمی و قدیمی و سطح پایینه (و دیدید که حتی نمیشه مثال و مقایسهء درست و حسابی با PHP ازش درآورد!). درحالیکه PHP یک زبان جدیدتر و سطح بالا برای برنامه نویسی وب است.
از این نظرها جاوااسکریپت نزدیکی بیشتری به PHP داره تا سی.
اصولا هم چون صفحات و برنامه های وب ترکیبی از PHP و JS هستند، از نظر سازگاری کاربردی و یادگیری و برنامه نویسی این یک مزیت است که بین این دو زبان شباهت و رابطهء دوستانه ای برقرار باشه. یعنی طراحان PHP بجای اینکه ور دارن یک چنان چیزهایی رو اونطور باهاش رفتار کنن، اگر یجوری طراحی میکردن که از منطق و رفتار جاوااسکریپت تقلید کنه، میتونست در عمل خیلی مفیدتر باشه. مثلا من خیالم راحت باشه که یه چیزی رو اگر هم در سمت کلاینت و هم در سمت سرور باهاش سروکار دارم، منطق و رفتارشون شبیه همه و میتونم هردو رو به شکل یکسانی پیاده کنم و وقتی بین دو زبان سویچ میکنم مشکل یادگیری و گیج شدن و اشتباه کردن هم کمتر دارم.

eshpilen
پنج شنبه 05 دی 1392, 08:44 صبح
در اینجا از از 10 به بعد نادیده گرفته میشه . در جاوا اسکریپت هم همینه و اصلا بحثی رو این نیست و ربطی به موضوع ما نداره.
خیر در جاوااسکریپت میاد و عدد رو به رشته تبدیل میکنه و دو رشته رو بهم میچسبونه:
<script>
alert(5+"10 Little Piggies");
</script>
البته مقایسه در این نمونه بین جاوااسکریپت و PHP مشکله و شاید بی معنی باشه، چون در جاوااسکریپت + عملگر الصاق رشته ای هم هست، ولی در PHP برای این کار یک عملگر دیگر (.) داره.


حالا حرف من چیه ؛ ما که از تئوری و دلایل تیمی که php رو طراحی کردن آگاهی کامل نداریم و صرفا فقط از خود زبان داریم استفاده میکنیم و کمی به مستنداتش آگاهی داریم.مگه PHP زبان بازمتن نیست؟
یعنی منبعی در این مورد نیست؟
یعنی استدلالشون رو بیان نکردن؟
یعنی به کسی ربطی نداشته و دیکتاتوری بوده؟
بعد چطور استدلال و نبوغ برتری داشتن که به ذهن هیچکس دیگری نمیرسه؟
بگردید پیدا کردید خبر بدید خب!
توی یک سایتی مقاله ای بود که از طراحی PHP انتقاد کرده بود و این موارد رو پیش کشیده بود؛ باید روی این مقاله هم حداقل افراد ذیصلاح و حتی مراجع رسمی PHP میامدن و یک بحث و پاسخی میذاشتن. ترجیحا باید بحثی میبود که مخالفان هم بتونن توش شرکت کنن.


چون این بخشی از تبدیل نوعش هست یا به قول خودشون type-juggling ، یک طرف نوع عددی هست و طرف دیگه نوع رشته که اولش هم عدده ، خب برای جمع باید دو طرف به نوع عددی تبدیل شه دیگه مگه نه؟
خب پیش فرض تو نوع عددی صفره دیگه ، وقتی پیدا نمیکنه پیش فرض 0 در نظر میگیره. خب موقع مقایسه با == هم اول تبدبل میکنه بعد مقایسه
من بحثم اینه که این باگ نیست چون تو مستندات سایت PHP برای == به همه این شبهه ها جواب داده.
اگه قراره باگ تلقی شه ، برای وقتی هست که برنامه نویس بدون آگاهی به type-juggling و == و === بیاد برنامه بنویسه. یه چیزی درست کردن به اسم type-juggling، بعد میگن دلیل و استدلالش اینه؟!
چطور در زبانهای هم خانوادهء دیگر چنین چیزی نداریم؟
منطق و فایدش چیه اونوقت؟
در زبانهای دیگر هم دینامیک تایپ و تبدیل نوع خودکار داریم، ولی نه دیگه به این صورت عجیب!
اصولا در زبانهای سطح بالا محدودیت های فنی و شکل پیاده سازی معنی ندارن در چنین مواردی؛ بلکه هدف باید منطق روشن و قابل انتظار در سطح برنامه نویسی و احتمال و فایده در اون سطح باشه.
الان چنین مواردی در برنامه نویسی کاربرد خیلی کمی دارن و بعکس چون برای برنامه نویسان منطق اونا روشن و قابل انتظار نیست، باعث بالا رفتن آمار باگ میشن.

هرچه حجم و دشواری یادگیری یک زبان کمتر باشه، و موقع برنامه نویسی نیاز به دقت کمتری برای تامین صحت و امنیت برنامه باشه، اون زبان بهتریه. شک دارید؟

اینا اومدن این چیز عجق وجق رو گذاشتن، فقط حجم و دشواری یادگیری رو زیاد کردن و احتمال باگزایی در برنامه ها رو!
باید بری این قضیه رو حتما بخونی هضم کنی و موقع برنامه نویسی هم مدام حواست باشه و دقت کنی بخاطرش که یوقت باعث ایجاد باگ نشه! این تا اینجا هزینه هاش؛ خب حالا بگید فایده هاش کجاست و چقدره اونوقت؟!

میتونستن براحتی وقتی عددی داره با رشته مقایسه بشه یک چک و شرطی بذارن که اگر رشته حاوی یک عدد نبود، نتیجهء مقایسه false بشه.
اگر این کار رو میکردن چه مشکلی پیش میامد کجای دنیا روی سرمون خراب میشد؟
اتفاقا دیگه یادگیری و آگاهی و دقت نمیخواست و باگهای کمتری در برنامه ها بوجود میامد.

MMSHFE
پنج شنبه 05 دی 1392, 09:08 صبح
اینطور نیست که به انتقادها و مشکلات جواب ندن. اگه اینطوری بود که قسمتی به اسم bugs.php.net نداشتیم. من خودم این باگ رو گزارش کردم و گفتن درحال بررسی هستن و تا یکی دو روز دیگه جواب میدن. یکبار دیگه هم قبلاً یک باگ رو گزارش کرده بودم که توی Minor Upgrade بعدی، رفع شد و یک License نرم افزار Zend Studio هم بهم هدیه دادن. بهرحال هیچ برنامه ای کامل نیست. مهم اینه که تیم توسعه PHP به گزارشات کاربران اهمیت میده. نه اینکه مثل مایکروسافت باشه که تا وقتی شرکتی به بزرگی گوگل نباشی، جواب ایمیلهای پشتیبانیت رو هم نمیده.

eshpilen
پنج شنبه 05 دی 1392, 09:38 صبح
ببین این موردی که من مطرح کردم باگ نیست که توی قسمت باگ و به شکل و با محدودیت های گزارش باگ گزارش کنی.
این یه تصمیمگیری و طراحیه، که استدلال و هدفی پشتش بوده و باید باشه، و نیاز به بحث آزاد و ادامه دار تا مدتی داره، مثل همین کاری که ما اینجا کردیم.
اونا دلایل و اسناد خودشون رو میارن، ما میخونیم، بعد اگر قانع نشدیم دلایل و اسناد و ایرادها و سوالات و ابهامات خودمون رو مطرح میکنیم، و به همین شکل بحث ادامه پیدا میکنه تا یک زمانی به امید اینکه یک طرف قانع بشه یا از موضع خودش مقداری تغییر و اصلاح پیدا کنه، یا شاید هم دو طرف هردو مقداری تغییر و اصلاح بدن مواضع خودشون رو و این وسط به نتیجه و راه حل و تصمیم مشترک دیگری برسن.

خلاصه این یه بحثه. مثل بحث پارلمانی میمونه برای طراحی و تصویب یک قانون جدید، یا زیرسوال بردن و لغو یا اصلاح یک قانون موجود. باید بحث روش صورت بگیره. طرفداران و مخالفان آزادانه درش شرکت کنن. نیاز به زمان و آزادی و محیط و شرایط خودش داره. یوقتهایی نیاز میشه دیگرانی هم مطالبی بیارن، تحقیق بیشتری صورت بگیره و نتیجش ارائه بشه، و غیره. کار راحت و سریعی نیست مسلما!
اگر یک بحث در جای مناسب بصورت آزاد صورت بگیره، فرضا دیگران هم که استدلالها و اسناد دیگری دارن بتونن شرکت کنن، خیلی بهتر میشه. مثلا من از چندتا زبانی که میشناختم مثالهایی آوردم، اما یکی دیگه ممکنه زبانها و مثالهای بهتری رو بشناسه، یکی ممکنه اصلا متخصص طراحی زبانهای برنامه نویسی باشه یا بهرصورت اطلاعاتی از نحوهء تفکر و تصمیمگیری در این موارد داشته باشه و شاید دسترسی به منابع و اسنادی که ما ازشون خبر نداریم.
منهم دیگه در اون حد متخصص این کار نبودم، اما یه چیزایی در طول زمان خونده بودم دیده بودم فهمیده بودم گفتم و از عقل و منطق خودم هم کمک گرفتم.

eshpilen
پنج شنبه 05 دی 1392, 09:42 صبح
من خودم این باگ رو گزارش کردم و گفتن درحال بررسی هستن و تا یکی دو روز دیگه جواب میدن
کدوم باگ رو؟!
من منطق رفتار PHP در مواردی مثل ‎‎'hello'==0 رو میگم.
مسلمه که اگر اینو بعنوان باگ گزارش کنی جواب میدن که این یک باگ نیست و خودمون میدونستیم و بر اساس طراحی و منطق خود زبان PHP است.
بحث ما بحث طراحی و منطق اشتباه یا حداقل غیربهینه است، نه باگ.

eshpilen
پنج شنبه 05 دی 1392, 09:53 صبح
حالا من اشاره به متخصصان طراحی زبانهای برنامه نویسی کردم، یه فکری بنظرم رسید!
میگم میشه سرچ و تحقیق کرد و یکسری متخصصان طراحی زبانهای برنامه نویسی رو پیدا کنیم و بهشون در این مورد ایمیل بزنیم و نظرشون رو بخوایم.
احتمال زیادی میدم که نظر اونها هم تاحد زیادی با نظر بنده شباهت داشته باشه!
بعید نمیدونم جوابهایی که میدن حال همتون رو بگیره!!
مثلا یکیشون میگه: PHP یک زبان بازمتن است که ابتدا بعنوان یک ابزار شخصی توسط یک فرد غیرمتخصص در امر طراحی زبانهای برنامه نویسی ایجاد شد و سپس به نحو بی قاعده و غیرعلمی ای توسعه پیدا کرد. رفتار این زبان معیاری برای طراحی زبانهای برنامه نویسی نیست و با اصول علمی این رشته سازگاری کافی ندارد!

:لبخند:

جون تو آدمای کار درست و دانشگاه دیده همینطوری صحبت میکنن!
من اینقدر دیدم تاحالا که خوب آشنا هستم با منطق و طرز صحبتشون.
چنین آدمایی کاری ندارن که PHP توسط 90 درصد وبسایتهای دنیا داره استفاده میشه و اینطور حرفا، و فقط از روی علم و منطق حرف میزنن.
اول و آخرش هم به احتمال زیاد داستان همینه.
ولی تمام اینا نباید شما PHP کاران و بازمتن دوستان عزیز رو ناامید کنه، چون در دنیای واقعی بیشتر چیزها ایدئال و بدون ضعف و نقص نیست.
مثلا ممکنه دات نت و زبانهایی مثل سی شارپ در کل بیشتر علمی و روی این اصول باشن، ولی در عمل و در دنیای واقعی اونا هم محدودیت ها و معایب خودشون رو دارن (که گاهی مستقیما به خود زبان هم مربوط نمیشه). محدودیت و عیب که فقط روی بحث طراحی نیست! و خیلی چیزها باوجود بی نقص نبودن کاملا مفید هستن و استفاده میشن، بخصوص که در خیلی شرایط اصلا جایگزین مناسب تری هم براشون وجود نداره.

MMSHFE
پنج شنبه 05 دی 1392, 09:55 صبح
ببینید، گزارش Bug صرفاً به معنای وجود خطا در طراحی و نحوه کاربرده. من هم بعنوان SPL Problem گزارش کردم و گفتم این رفتار، اون چیزی که اغلب برنامه نویسان انتظار دارن نیست و ممکنه منجر به باگهای امنیتی توی برنامه های کاربران بشه. نه اینکه خودش یک باگه. توصیه هم کردم که switch لااقل مثل بقیه زبانهای Loose Type از strong type comparison استفاده کنه یا یک پارامتر دوم بهش اضافه کنن که هروقت کاربر خواست، بتونه نحوه عملکردش رو تنظیم کنه. اینم متن گزارشیه که فرستادم:


[2013-12-26 06:18 UTC] mmshfe at gmail dot com

Description:
------------
As mentioned in docs, switch statement is a loose type comparison tool. But this may be lead to a serious bug in user products. It would be really better to force it to use strong type comparison (or have an option such as an optional 2nd argument let the users to do so). In the real world, we have no other loose type languages that behaves like this. For example, in JavaScript, the result is fine. I mean, although being a loose type language is a good feature for PHP in overall; It should not be led to unexpected results those not shown in any other language (even the other loose type ones).

Test script:
---------------
$v = 0;
switch($v) {
case 'hello':
echo 'Hello';
break;
case 'Goodbye':
echo 'Goodbye';
break;
default:
echo 'Error';
break;
}

Expected result:
----------------
Error

Actual result:
--------------
Hello

--------------

[2013-12-26 06:29 UTC] mmshfe at gmail dot com

I really now the process flow. It uses if, elseif, else statements like this:

if($v == 'hello') {
echo 'Hello';
}
elseif($v == 'Goodbye') {
echo 'Goodbye';
}
else {
echo 'Error';
}

And 'hello' is converted to integer (with intval('hello') or anything similar) and because it does not contain an integer value at the beginning, it uses the default integer value (zero) and so, the first case becomes true. All I want to say is that this behavior is incorrect because approximately always it's not the behavior that the developer expected.

MMSHFE
پنج شنبه 05 دی 1392, 10:02 صبح
نه اتفاقاً به استدلالهای دیگران هم کاملاً گوش میدن و اگه درست باشه، عمل هم میکنن. یک قسمت توی نوع گزارش هست که میشه بجای گزارش Bug بگین Feature Change Request هست و دلایلتون رو هم مطرح کنید.

eshpilen
پنج شنبه 05 دی 1392, 10:09 صبح
ایول قشنگ براشون توضیح دادی!
خوشم اومد.
ولی بنظر من کلا اینطور شرطها نباید true بشن، نه فقط در switch، بلکه در if هم چنین شرطی نباید true بشه.
عملا switch و if چندان فرقی با هم ندارن و میشه در خیلی موارد اونا رو بجای همدیگر استفاده کرد (در عمل هم میبینیم که در این زمینه برنامه نویسان انتخابهای متفاوت دارن).
بقول خودت این loose type comparison در هیچ زبان دیگری دیگه اینقدر بی بند و بار نیست که ‎‎'hello'==0 رو true فرض کنه. نمونه ای سراغ داری خلاف این؟
توضیح رو اگر کلی میدادی، نه اینکه بگی فقط برای switch است و برای سویچ استثناء یا آپشن بذارید، شاید بهتر بود.
گرچه فکر کنم اگر یه جو عقل درست و حسابی داشته باشن همین توضیحات شما هم باید جرقه رو براشون بزنه که بیشتر روی این قضیه از این دیدگاه که مطرح کردی فکر کنن.
ولی من این سابقه رو در یاروهای PHP قبلا احساس کردم که زیاد اهل پذیرفتن و اعتراف به اشتباهات خودشون نیستن. چون درمورد رجیستر گلوبالز دیده بودم این قضیه رو که هیچوقت به اینکه از اساس منطق و طراحی اشتباهی بوده اعتراف نکردن و تا آخر ازش دفاع میکردن!
هرچند امیدوارم حداقل در عمل دیگه اینقدر لجباز و خودبین نباشن و دست به تجدید نظر و اصلاح بزنن.

MMSHFE
پنج شنبه 05 دی 1392, 10:20 صبح
حالا بحث if رو میشه با توجه به وجود عملگر === توجیه کرد و کاربر هم قطعاً اگه مستندات رو خوب خونده باشه، میدونه که چرا hello'==0' نتیجه true میده ولی انتظار از switch واقعاً type specific بودن هست.

eshpilen
پنج شنبه 05 دی 1392, 10:25 صبح
آره نکتهء خوبی بود، ولی بازم بنظر من تفسیر PHP از اساس مشکل داره و وجود === دلیل کافی برای نادیده گرفتنش نمیشه.
== هم بالاخره منطق و محدودیت بیشتری نیاز داره.
راستی خوب بود به این نکته هم در گزارشی که دادی اشاره میکردی.

colors
پنج شنبه 05 دی 1392, 11:47 صبح
چرا PHP هنگام تبدیل یه سری اولیت ها مدنظر قرار میده و آیا این اولیت ها درست هست یا نه؟
مثلا در مثال زیر میاد و رشته hello رو به عدد تبدیل میکنه (که میشه 0) و بعد با مقدار 0 مقایسه میکنه و شرط درست میشه؟

$a = 0;

if($a == 'hello'){
echo 'hello';
}
else{
echo 'error';
}
// output : hello
حالا چرا نمیاد عدد رو رشته کنه و بعد مقایسه رو انجام بده؟ این چه منطقیه که باید رشته اول تبدیل بشه و بعد عدد؟ اصلا عدد رو تبدیل میکنه یا ...؟

$a = 0;
settype($a, 'string');

if($a == 'hello'){
echo 'hello';
}
else{
echo 'error';
}
// output : error

MMSHFE
پنج شنبه 05 دی 1392, 11:56 صبح
چون این متغیره که داره مورد ارزیابی قرار میگیره نه مقدار. پس باید مقدار به نوع عدد تبدیل بشه و بعد، عمل مقایسه انجام بشه. بهرحال مسئله اینجا ترتیب تبدیل نیست. مسئله اینه که اینجا اصلاً تبدیل نوع صحیح نیست و نباید انجام بشه.

eshpilen
چهارشنبه 11 دی 1392, 08:26 صبح
<?php

//u should know, we can specify sort column(s) by column number in a query.

$sort_columns=Array(2, 3, 5);
//the most safe validation method: white list! seems completely safe! not?

$user_input='2';

if(!in_array($user_input, $sort_columns)) echo "'$user_input': <span style='color: red'>illegal sort column!</span>";
else echo "'$user_input': <span style='color: green'>input validated.</span>";

echo '<div>&nbsp;</div>';

$user_input='7';

if(!in_array($user_input, $sort_columns)) echo "'$user_input': <span style='color: red'>illegal sort column!</span>";
else echo "'$user_input': <span style='color: green'>input validated.</span>";

echo '<div>&nbsp;</div>';

$user_input='sql injection';

if(!in_array($user_input, $sort_columns)) echo "'$user_input': <span style='color: red'>illegal sort column!</span>";
else echo "'$user_input': <span style='color: green'>input validated.</span>";

//so far, everything seems ok/expected!

//but see what type juggling can do for us (indeed for hackers!)...

echo '<div>&nbsp;</div>';

$user_input='2 sql injection';

if(!in_array($user_input, $sort_columns)) echo "'$user_input': <span style='color: red'>illegal sort column!</span>";
else echo "'$user_input': <span style='color: green'>input validated.</span>";

$query="select * from table order by $user_input ...";

//of course, there r many other cases that type juggling can help us in writing more secure and reliable (bug free) programs!!
//and not only that, type juggling helps us write programs much more fast and easily too. but i leave it up to u to show some examples about that matter.
//lol

?>

eshpilen
چهارشنبه 11 دی 1392, 11:35 صبح
اینم متن گزارشیه که فرستادم
من گزارشش رو پیدا نمیکنم.
کجاست؟ جوابش چی شد؟
بعدم گفتم که اینطور چیزها بهتره یا اصلا لازمه در محیط بازتر و عمومی تری روش بحث و تبادل نظر آزاد صورت بگیره.
اینکه فقط بخونن و خودشون بتونن نظر بدن و حکم رو هم بزنن روش که نشد!
-----------------
ویرایش: آهان با گوگل پیداش کردم: https://bugs.php.net/bug.php?id=66361

eshpilen
چهارشنبه 11 دی 1392, 13:35 عصر
in_array پارامتر سوم رو باید true بکنی تا دیگه loose comparison اتفاق نیفته.
بنظر من اگر بخوایم برنامهء بدون باگ و امنی بنویسیم، اصلا در بیشتر یا حتی تمام جاهای دیگر هم بجای == باید از === استفاده کنیم (یا ترفندهای دیگری بزنیم بهرصورت یا چکهای اضافی و غیره). چون بهرصورت با این رفتاری که PHP در تبدیل و تفسیر سرخود رشته ها به عدد داره آدم خیلی سخت میتونه مطمئن باشه جایی باگ یا حفرهء امنیتی به همین دلیل بوجود نیامده باشه.
موضوع اینه که اینقدر در این تبدیلات افراط کردن و سرخود عمل کردن که از تعادل امنیتی و انتظار و احتمالات بیشتر در برنامه ها هم تاحد زیادی فاصله گرفته.


کاربرد همین که گفتم بود دیگه. کد نویسی کمتر. مسئله امنیتی منظورم نیست. به هر حال اگر هواست نباشه می تونه دچار مسئله امنیتی بشه ولی کاربردش هم اینه که نیازی به تبدیل نداره.
آخه عزیزم کاربرد تبدیل '3dllldddd ddff ---ddd' به عدد 3 بصورت ضمنی چیه مثلا؟ چقدره کاربرد و فایدهء چنین چیزهایی در برنامه نویسی؟
تبدیل '3' به عدد 3 درسته خیلی کاربرد داره و مفیده، ولی رشته هایی که صرفا عددی نیستن کجاها مثلا اینقدر نیاز هست که به زور به عدد تبدیل بشن؟ کجا کاربر یجا رشته ای محتوی چیزهای دیگر غیر از عدد هم وارد میکنه بعد شما میخوای یه عدد از توش بکشی بیرون؟ کجای برنامت خودت همچین مقدارهایی داری که میخوای تبدیل به عدد کنی؟
یه جاهایی هم نیاز باشه موارد خاص و معدودی هست به علت خاصی میخوای اون کار رو بکنی خب با توابع صریح مخصوص میتونی این کار رو بکنی. اینطوری کدت امن تر و خواناتر هم هست و خودت ببینی یا دیگرن نگاه کنن تاحد زیادی قابل حدسه که انتظار چنین رشته های ترکیبی ای رو (هم) داشتی.
اینا اومدن یک رفتار و کاری رو که در شرایط و موارد خاص و معدودی کاربرد داره تعمیم دادن و پیشفرض تبدیلات توی کدهای روتین گذاشتن، خب خیلی کار اشتباهیه!
تازه حتی همون توابع صریح که واسه اینطور موارد هست، اگر نگیم در تمام ولی در اکثر زبانهای دیگر (حداقل اونایی که بنده شخصا دیدم) باز رفتار دقیقتر و امن تری از خودشون نشون میدن و یک رشته ای مثل 'hello' رو که توش هیچ عددی نیست تبدیل به عدد 0 نمیکنن!
باز اینم خودش مشکل داره. شاید قرار بوده کاربر یجا عدد وارد کنه اشتباه گرفته یه چیز اشتباهی وارد کرده اونوقت با اونی که آگاهانه عدد 0 رو وارد کرده یکی فرض میشه؟


حالا تو داری میگی که اصلا قبول نمی کردن ولی اونجور که من مثلا از کتاب php power programming که توسط خود توسعه دهنده های اصلی php نوشته شده رجیستر گلوبالز رو یک ویژگی که باعث مشکل امنیتی میشه می دونستن
خیلی زحمت کشیدن این رو که همه میدونستن پس بخاطر چی مجبور شدن حذفش کنن!
منظور من اینه که بصورت صریح اعتراف نکردن که یک طراحی از اولش هم اشتباه بوده؛ و بنظر نمیاد هنوزم ذهنیت و این تفکر سطحی و بچه گانه خودشون دربارهء طراحی feature های زبان رو زیاد تغییر داده باشن.
اصولا چنین چیزی رو هیچ متخصصی از همون اول هم طراحی نمیکنه، چون بقدر کافی مشخصه که روی اصول نیست؛ اصلا نیازی نبود اینقدر تجربه بشه و در عمل خسارت ببار بیاره تا تازه بتونن واقعیت موجود رو ببینن. اونم تازه اعتراف به این نیست که از اول ذهنیت اشتباهی داشتن و طراحی اشتباه انجام دادن. یعنی اعتراف نکردن که در این زمینه ناشی بودن! واقعا این یک طراحی ناشیانه ای بود. مسئله ای نبود که کس دیگری جز ناشی ها احتمال قابل توجهی داشته باشه که مرتکب بشه.


راستی حالا که این مسئله پیش اومده یه review روی بعضی از کدها انداختم (البته من همیشه دیدگاه loose comparison رو داشتم و همیشه با این دید کد نوشتم ولی حقیقتا روی مثالی که گفته بودی هیچ وقت بهش برنخوردم) و دیدم که همه ورودی هایی که از کاربر می گیرم رو از فیلترها و validator ها عبور میدم
خب شانس آوردی.
من از white list به همین فرم بعضی جاها استفاده کردم. البته خوشبختانه بجای شماره ستون از اسم ستون استفاده کردم که باعث میشه این مشکل پیش نیاد. ولی بهرحال بدیهی هست که اگر در موردی میخواستم از شماره ستون استفاده کنم متوجه این موضوع نمیشدم و احتمالش خیلی زیاد بود که مشابه همین کد حفره دار رو بنویسم و طبیعی هم بود که چون این رفتار غیرمنتظره است با چنان نمونهء خاصی از ورودی کاربر تستش نمیکردم به احتمال زیاد (همون چندتای قبلیش رو تست میکردم مطمئن میشدم که کدم درست کار میکنه).
حتی اگرم اون موقع نسبت به این مسئله آگاهی الان رو داشتم، بازم احتمالش کم نیست که آدم از زیر دستش در بره.
خیلی برنامه ها و خیلی افراد ممکنه چنین خطاهایی داشته باشن. لزومی هم نداره فقط به این شکل و در این موارد مثل switch و white list باشه. ممکنه به خیلی شکلها و در خیلی جاهای دیگر هم وجود داشته باشه.

eshpilen
چهارشنبه 11 دی 1392, 13:53 عصر
in_array پارامتر سوم رو باید true بکنی تا دیگه loose comparison اتفاق نیفته.
اونطوری که کد من اصلا کار نمیکنه. چون من ستونها بصورت عددی توی آرایه گذاشتم. ورودیهای کاربر همیشه نوع رشته ای دارن.
کاری که میتونم بکنم اینه که بجای ‎‎$sort_columns=Array(2, 3, 5)‎ بنویسم ‎$sort_columns=Array('2', '3', '5')‎.

eshpilen
چهارشنبه 11 دی 1392, 14:17 عصر
تا قبل از اینکه با PHP کار کنم این بنظرم بدیهی و بدون تردید بود که در تمام زبانهای برنامه نویسی، محیط درونی برنامه محیطی امن محسوب میشه و کسی نمیتونه توش نفوذ کنه مگر از طریق کدها و منطق خود برنامه نویس؛ یعنی مثلا فقط متغییرهایی که برنامه نویس خودش تعریف کرده در برنامه بوجود میان و فقط مقدارهایی رو دارن که خود برنامه در اونها قرار داده.
و فکر میکنم نیاز به این امنیت لازم باشه.
مثل اینکه شما میخواید خونه بسازید خب باید حداقل زمین زیرش محکم باشه یا نه؟
اگر قرار باشه زمین هم زمین نباشه و معلوم نباشه فردا تبدیل به ماست میشه یا یجاش یهو یه درخت درمیاد یجای دیگش نشست میکنه گود میشه، دیگه نمیشه به سبکی که الان ساختمون درست میکنیم ساختمون درست کرد و کار ساختمان سازی روی چنین زمینی خیلی سخت تر میشه به گمانم.

آره خلاصه من تا اون موقع اینطور فکر میکردم و خیالم راحت بود.
تا اینکه چشممون به جمال PHP روشن شد و قضیهء رجیسترگلوبالز!
یهو فهمیدم ای داد بیداد کاربر از اون سر اینترنت با تایپ چند کاراکتر به راحتی بدون هیچ چیز دیگه ای میاد داخل محیط درونی برنامهء من و انگار که اونم داره برنامهء من رو مینویسه یا تغییرش میده هر متغییری رو که میخواد توش ایجاد میکنه!! چه میخواد متغییرهای جدیدی باشه چه متغییرهایی که در برنامهء خودت استفاده کردی و چه متغییرهایی که PHP خودش قبل از شروع اجرای برنامت ست میکنه.

آدم یاد داستانهای جن و پری میفته.
انگار از آسمون هم ممکنه یه چیزی یهو بیفته پایین!
انگار کاربر هم مستقیما همون وسط برنامه و کدهای شماست و میتونه چیزی واردش کنه!!

واقعا من همون موقع نخندیدم، بلکه بسیار عصبانی شدم از این مصیبت بزرگی که به برنامه نویسان و برنامه نویسی وارد کردن با این کارشون.
خداییش عصبانی شدم.
چرا؟ چون تا اون وقت ما حداقل یک فرض و اطمینان در این مورد داشتیم که البته بدیهی هم بنظر میامد و اینطوری نیازی نبود نگران این باشیم که این مسئله رو هم تحت کنترل و نظارت دائمی داشته باشیم و حواس و تمرکزمون رو صرفش کنیم. خب نیازی هم نبود! مثل اینکه شما شب که میخوای بخوابی درب و پنجرهء خونت باید قفل باشه، نه اینکه نتونی قفل کنی و باز بمونه و بعد بگن خب حالا بجاش دزدگیر و تله و این حرفا بذار یا درهای داخلی داخل خونت بذار خودت که دزد اومد داخل نتونه کاری بکنه!!
من میگم دزد اصلا نباید بتونه از دروازه رد بشه، دلیلی نداره، نه اینکه راحت بیاد داخل و بعد در داخل شما بخوای گیرش بندازی یا جلوش رو بگیری با ساختن دربهای داخلی اضافی و قفل و دزدگیر و تله و اینطور چیزها!
ولی طراحان PHP اینطور دلیلی داشتن واسه خودشون: بخاطر راحتی شما شهروندان گرامی ما درها رو باز میذاریم تا افرادی که به خونهء شما میان تا پشت درب اتاق خواب شما بیان و بعد اونجا شما باید حواستون باشه که اگر آشنا و فرد درستی بود اون رو راه بدید، ولی اگر دزدی چیزی بود خودتون باید حواستون باشه و دربهای داخلی گذاشته باشید و قفل کرده باشید که طرف نتونه بیاد داخل و آسیبی به شما برسونه!

موضوع اینه که اون راحتی رو نخواستم بابا. راحتی اینکه بدون اجازه و عمل صریح خودت دروازه های ورودی بسته باشن و توی خونت بتونی آزادانه و بی خیال و بدون ترس اینور و اونور بری و مدام نیاز نباشه حواست جمع باشه و پشت سرت درها رو قفل کنی، از راحتی اونکه چند قدم تا دم درب خروجی منزل تشریف ببرید و ببینید کی اومده آیا آشناست یا دزده، خیلی مهمتر و بیشتره.

محیط داخلی برنامه مثل خونهء برنامه نویس میمونه که باید توش راحت و امن باشه. تا خودش چیزی رو به داخل راه نداده چیزی نیاد داخل و تغییری نکنه. نه اینکه نیاز باشه مدام شش دانگ حواسم توی خونهء خودم هم جمع باشه مثلا یه گلدان دیدم داخل خونه در یک مکانی شک کنم و برم بررسیش کنم ببینم واقعا اون رو خودم خریدم و خودم اونجا گذاشتم یا نه! لابد باید روی همهء اشیاء یک برچسب هلوگرام و پلمپ بزنم تا کس دیگری نتونه بدون متوجه شدن من اونا رو تغییر بده یا جعلی جاشون بذاره!!

eshpilen
چهارشنبه 11 دی 1392, 18:40 عصر
چون این متغیره که داره مورد ارزیابی قرار میگیره نه مقدار. پس باید مقدار به نوع عدد تبدیل بشه و بعد، عمل مقایسه انجام بشه.
مهندس فکر نمیکنم به متغییر و مقدار بودن باشه ها.
میتونید اون مقدار رو هم توی متغییر بذارید و بعد دو طرف متغییر مقایسه کنید.
آیا نتیجه تفاوتی میکنه؟

metal gear solid 4
چهارشنبه 11 دی 1392, 21:02 عصر
این تاپیک خیلی جالبه. خروجی اشتباه به خاطر کم دقتی در کد باعث شده به PHP ایراد بگیرند!!
شاید بی ربط باشه اما پیشنهاد میکنم یک مطالعه ای راجع به ارزیابی مدار کوتاه هم داشته باشید. دو روز دیگه تاپیک نزنید بگید شرط switch و if من کار نمیکنه. PHP مشکل داره !! :D

eshpilen
شنبه 14 دی 1392, 08:24 صبح
کم دقتی در کد؟
چیزی که در PHP شما بهش میگید کم دقتی در کد چطور در بقیهء زبانهای مشابه موجب این خروجی اشتباه نمیشه و نیازی به این دقت نیست؟
مسئله اینست که PHP اومده تفسیر و ساختاری رو پیاده کرده که نیاز برنامه نویس به آگاهی و دقت رو بالا برده، بدون اینکه کاربردهای زیاد و مفید کافی داشته باشه که بتونن این افزایش نیاز به دقت و صرف وقت و انرژی بیشتر رو توجیه کنن.
داستانی که درمورد رجیسترگلوبالز هم رخ داد چیز مشابهی بود. این رو که دیگه فقط من نمیگم و تجربهء قبلی بود و خودشون هم معترف شدن که مشکل امنیتی ایجاد میکنن و مجبور به حذفش هم شدن!
طراحی تا طراحی فرق میکنه. یوقت شما به خیال خودت یک feature در زبان میذاری و یک طراحی اشتباه انجام میدی که دست آخر معلوم میشه طراحی مناسبی نبوده و بیشتر از اونکه فایده داشته باشه منجر به خسارت میشه.
وگرنه بله اگر برنامه نویسان آگاهی و دقت بی نقصی داشته باشن، مشکلی پیش نمیاد. ولی مسئله اینه که آگاهی و تمرکز و دقت برنامه نویس هزینه بر است و تازه انسانها هرچقدر هم که دقت کنن و وقت و مایه بذارن بازهم از غفلت و خطا مصون نیستن و نمیتونن 100% تضمین کنن که چیزی از زیر دستشون در نرفته یا متوجه همه چیز بودن؛ حتی بهترین برنامه نویسان (تاحالا کدوم برنامه نویسی در تاریخ اومده که از بروز باگ در برنامه هاش مصون بوده؟). بخاطر همین هرچقدر زبان طوری طراحی شده باشه که نیاز به این آگاهی به مسائل فنی و جزییات سطح پایین کمتر باشه و موقع برنامه نویس نیاز به پرداختن و توجه و تمهید کردن برای جزییات کمتری باشه، اون زبان زبان بهتری بحساب میاد. حداقل در زبانهای سطح بالا که اینطوره! اصولا یک هدف اصلی زبانهای سطح بالا همینه که برنامه نویسی رو راحتتر و سریعتر کنن و بقولی میگن که برنامه نویس تا حد ممکن فقط روی منطق و الگوریتم اصلی برنامهء خودش متمرکز بشه. هرچی هم این تمرکز سطح بالاتر باشه بهتره طبیعتا. یعنی اینطور میشه برنامه ها رو سریعتر و راحتتر درست کرد.

eshpilen
شنبه 14 دی 1392, 08:28 صبح
شما توی حیاط خونهء خودت همینطوری مین نمیذاری روی زمین بعد بگی خب باید آگاه بود و دقت کرد!
شاید برای گذاشتن اون مین ها توجیهی هم داشته باشی برای خودت. مثلا بگی برای دزدها کار میذارم!! ولی باید ببینی نسبت به هزینه و ریسکی که داره می ارزه یا نه! آیا در مجموع و در کل زمانها، دلیل و سند بقدر کافی روشن و محکمی وجود داره که بیشتر از اونچه که هزینه و خسارت ببار بیاره سودمند خواهد بود یا خیر.

متوجه اصل بحث نشدی مثل اینکه. احتمالا همینطور سرسری فقط یه عنوان و دو سه تا خط این تاپیک رو خوندی بعد اومدی این اظهار نظر بی ربط رو کردی.
واقعا خودت عجب دقت و اصولی داری ها :چشمک:
خوب شد به ما هم یاد دادی که مشکل از کم دقتی خودمون بوده و باید بیشتر دقت کنیم.

من نمیگم برنامه نویس نباید آگاهی و دقت داشته باشه.
میگم چرا PHP اومده یه چیزهایی سرخود درست کرده که موارد و میزان نیاز به این آگاهی و دقت رو بالا برده، بدون اینکه کاربرد و سود کافی درش بنظر بیاد که بتونه این هزینه رو توجیه کنه.
زبان برنامه نویسی باید تاحد ممکن طبق انتظار و منطق کار کنه و میزان احتمال کاربرد و وقوع موارد رو درنظر بگیره در طراحی. حتی باید عامل خطای انسانی رو هم بحساب بیاره.

اگر چندتا زبان دیگر هم بودن که در این موارد خاص همینطور عمل میکردن آدم میگفت خب بقیه هم به همین طراحی رسیدن. اما حتی یکی هم کسی نتونست معرفی کنه. فقط PHP هست که اینقدر توی این مسئلهء تبدیل های خودکار افراط کرده.

metal gear solid 4
شنبه 14 دی 1392, 08:53 صبح
وقتی عامل و باعثِ اینکه خروجی اشتباه حاصل میشه شما باشی. یعنی دقیقاً کم دقتی شما. این همه سفسطه هم لازم نیست.

eshpilen
شنبه 14 دی 1392, 09:08 صبح
زمانی خیلی افراد درمورد رجیسترگلوبالز هم همین استدلال شما رو داشتن.
میگفتن خب برنامه نویس باید آگاه باشه و دقت کنه!
منم میگم بله شما اگر مدام دقت کامل داشته باشی و با این آگاهی و احتیاط کدنویسی کنی، رجیسترگلوبالز مشکل امنیتی ایجاد نمیکرد.
این درست.
کسی این رو رد نمیکنه.
روشن است.
اما این نیاز به آگاهی و دقت و احتیاط و تمهیدات خاص، هزینه ای هست که به برنامه نویس تحمیل میشه، و ریسک خطای انسانی رو بالا میبره.
و همهء اینا بخاطر چی؟
بخاطر اینکه برنامه نویس دلش خوش باشه که میتونه بجای چیزی مثل ‎$_POST['username']‎ بنویسه ‎$username.
این همه هزینه و ریسک بخاطر همین!
بنظر شما می ارزه؟
بنظر من کد روش اول خوانایی بیشتری هم داره و بصورت صریح و با دید اول مشخص میشه که این username داره از سمت کاربر از یک درخواست POST از یک فرم سابمیت شده میاد (و این برای دقت، خوانایی، و self document بودن کد خیلی خوبه - فقط با دیدن یک متغییر میتونی متوجه این همه جزییات بشی). ضمنا ممکن بود فیلد مورد نظر چیزی به روشنی username نباشه و مثلا یک اطلاعات دیگری باشه که در خود برنامه هم ممکنه برنامه نویس خودش تعریف کرده یا از جای دیگری مثل دیتابیس آورده باشه؛ بنابراین امکان تفکیک بصری و سریع و راحت این موارد از هم، به خوانایی و جلوگیری از خطای انسانی و راحتی و سرعت برنامه نویسی کمک میکنه.

اما طراحان PHP اومدن بخاطر دو خط کد کمتر نوشتن، ریسک امنیتی ایجاد کردن، نیاز به دقت بیشتر، و افزایش امکان باگ در اثر خطای انسانی.
برنامه نویسان PHP فقط یک جنبهء سطحی از کدنویسی رو مد نظر قرار دادن: تایپ چند کاراکتر کمتر!
و متغییری که معلوم نیست دیتاش از POST اومده یا GET یا کوکی!!
و به این میگن یک طراحی اشتباه اونم از نوع کاملا ناشیانه!
شک داری؟
تجربه و گذشت زمان هم این مسئله رو ثابت کرد، وگرنه مجبور نمیشدن چنین feature عمومی ای رو بعد از مدتها جا افتادگی حذف کنن.
اگر این یک طراحی اشتباه و یک feature ای که در عمل بیش از اونچه که مفید باشه خسارت ببار میاورد نبود، پس چی بود، چرا مجبور به حذفش شدن؟ پس برای چی از اول طراحی شد؟ چرا بهتر دیدن که نباشه؟ اونم با از بین بردن Backward compatibility و طرفداران زیادی که داشت. فکر کنم طرفدارانش هم آدمهایی با طرز تفکر و استدلال شما بودن :چشمک:
ولی من روز اول که فهمیدم رجیسترگلوبالز چیه حالم ازش بهم خورد! گفتم وه بابا این عجب چیز ابلهانه ایه!! کدوم نادانی چنین چیزی رو طراحی کرده!! عمرا توی هیچ زبان دیگری همچین چیزی طراحی نکردن و نمیکنن!

امروزه میبینیم که اسامی اشیاء و متدها در زبانهای برنامه نویسی در کل کوتاه نشده و بلکه طولانی تر هم شده. چون خوانایی و وضوح و دقت بصری کدها مهمتر از تایپ چند کاراکتر کمتره. بخصوص که ادیتورهای برنامه نویسی با ویژگیهای autocomplete و این حرفها میتونن این نیاز به تایپ رو از بین ببرن.

پس متوجه منظور من چیه دوست عزیز!
لطفا دوباره حرف بی ربط نزن.
اول بحث رو کامل و دقیق بخون و روشن شو ببین منظور چیه دقیقا مشکل سر چیه، بعد اظهار نظر کن.

eshpilen
شنبه 14 دی 1392, 09:18 صبح
وقتی عامل و باعثِ اینکه خروجی اشتباه حاصل میشه شما باشی. یعنی دقیقاً کم دقتی شما. این همه سفسطه هم لازم نیست.
کم آوردی خودت رو میزنی به اون راه؟
بقدر کافی توضیح دادم.
استدلال ها هم روشن و محکم هستند.
حرف حساب نداری دیگه حرف بیخود نزن.
دیگران میخونن و قضاوت میکنن.
شما جواب منطقی داری مطرح کن.
مثلا بگو همون رجیسترگلوبالز اگر مشکل از دقت برنامه نویسان بوده که باعث حفره های امنیتی میشده، پس چرا حذفش کردن؟ و چیزی که طراحی میکنن و خیلی از برنامه نویسان و برنامه ها بهش اتکا میکنن، بعد حذفش میکنن، طراحی اشتباه نبوده؟
لابد میگی بازم مشکل از بیشتر مردم دنیاست که دقت کافی ندارن :قهقهه:
بله اینطوری بخوای نگاه کنی پس هر طوری طراحی کنن هرچقدر که برنامه نویسی امن رو پیچیده و سخت کنن، مشکل از طراحی زبان نیست و از برنامه نویسان است!!

metal gear solid 4
شنبه 14 دی 1392, 09:20 صبح
حرف بی ربطی نیست. رجیستر گلوبالز یک باگ امنیتی بود و بهش اعتراف کردند. من هم مثل شما قبول دارم. اما چه دلیلی داره به هر مشکلی که میرسیم بزنیم خود زبان رو مورد حمله قرار بدیم.
خوشبختانه تبدیل نوع دستی در PHP به خوبی پشتیبانی میشه. برای بررسی هم از === استفاده میشه.
اگر فکر میکنی اینها ایرادات PHP هستن پس به سبک قدیم پیش برید. به سخت گیری زبان هایی مثل C++. قبل از هرکاری خودتون تبدیل نوع انجام بدید تا از صحت خروجی مطمئن باشید. وقتی هم از یکی از ویژگی های زبان PHP که تبدیل انواع خودکار هست بهره میبرید این صحبتها جاش نیست.
این چیزهایی که شما اشاره میکنید باگ نیستند. کم دقتی برنامه نویس به شمار میرن. خیلی بیشتر از این موردی که اشاره کردی از طریق ارزیابی مدار کوتاه (http://en.wikipedia.org/wiki/Short-circuit_evaluation) سوتی های وحشتناکی داده شده که اصلاً ربطی به باگ در زبان برنامه نویسی نیست. به طراحی اون زبان برمیگرده.

eshpilen
شنبه 14 دی 1392, 09:30 صبح
بحث رو کامل و دقیق نخوندی.
من با موارد خیلی خاصی کار داشتم، مواردی که فقط در PHP اینطور طراحی شدن و کار میکنن و نه در هیچ زبان سطح بالا و سطح پایین و هم خانواده و غیر هم خانوادهء دیگری. مواردی که عملا در برنامه نویسی کاربردهای خیلی محدودی دارن و بعکس در موارد بیشتری مورد انتظار برنامه نویس و مطابق با منطق برنامه نیستن.
وگرنه تبدیل نوع خودکار در زبانهای دیگر هم هست و مفیده. ولی تبدیل خودکار اونها در یک حد تعادل بهینه میان امنیت و راحتی و با درنظر گرفتن میزان کاربرد و احتمال در عموم برنامه ها طرحی شده.
معمولا هم زبانها رو سعی میکنن تاحد امکان سازگار و شبیه هم طراحی کنن. چون این هم از نظر سهولت و سرعت یادگیری و هم از نظرهای کاربردی (مثلا تبادل و تبدیل کد و دیتا بین زبانها) و هم از نظر جلوگیری از قاطی کردن و خطای انسانی در برنامه نویسی، مفیده.
PHP اومده تمام این موارد رو زیرپا گذاشته، بازم بخاطر یک مقدار کد نوشتن کمتر، اونم این بار برای مواردی که در برنامه نویسی واقعی کاربردشون خیلی کمه.
من از چیزهایی مثل true شدن hello==0 صحبت میکنم. چیزی که در هیچ زبان دیگری نمونش رو نمی بینید. و چیزی که احتمال اینکه در برنامه کاربرد مفید داشته باشه خیلی کمه.


رجیستر گلوبالز یک باگ امنیتی بود و بهش اعتراف کردند.رجیستر گلوبالز باگ نبود.
بلکه در درجهء اول طراحی اشتباه بود.
باگ بطور معمول به چیزی میگن که بطور تصادفی و با ناآگاهی و از زیر دست در رفتن در برنامه ها بوجود میاد.
اما رجیسترگلوبالز یک ساختار طراحی و یک feature بود که نسبت بهش آگاهی داشتن.

مثال رجیسترگلوبالز رو هم برای این آوردم که بگم هرجوری که زبان رو طراحی میکنن لزوما صحیح نیست. ممکنه در طراحی اشتباه بشه.
اگر رجیسترگلوبالز خودش باگ بود، پس چطور میشه با صرف دقت و کار کافی باوجودش برنامه های بدون باگ و حفره نوشت؟


اما چه دلیلی داره به هر مشکلی که میرسیم بزنیم خود زبان رو مورد حمله قرار بدیم
من به هر مشکلی گیر ندادم.
مواردی که مطرح کردم موارد خیلی خاص و استثنایی هستن.
مواردی که در هیچ زبان دیگری نظیرشون دیده نشده و مورد انتظار نیست.
برای مشکل داشتن طراحی اونا هم دلیل آوردم.

metal gear solid 4
شنبه 14 دی 1392, 09:36 صبح
رجیستر گلوبالز باگ نبود.
حق با شماست. منظور من نتیجه ش بود که به عنوان یک باگ امنیتی ازش یاد شد.

راجع به سایر صحبت هات باید بگم شما Documentation های PHP رو به خوبی مطالعه نکردید. باز هم ایراد از شماست. در مستندات دقیقاً این موارد ذکر شده ;)

eshpilen
شنبه 14 دی 1392, 09:38 صبح
ضمنا این مسائل و موارد خاص و گیر دادن به طراحی رو فقط بنده مطرح نکردم.
بطور مثال در این مقاله هم به این قضیه و یکسری ویژگیهای دیگر PHP بعنوان طراحی بد اشاره شده: http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/

eshpilen
شنبه 14 دی 1392, 09:43 صبح
راجع به سایر صحبت هات باید بگم شما Documentation های PHP رو به خوبی مطالعه نکردید. باز هم ایراد از شماست. در مستندات دقیقاً این موارد ذکر شده ;)
من این همه روضه میخونم باز تو میگی لیلی زن بود یا مرد!
عزیزم بحث روی این نیست.
بحث ربطی به دقت و کد من بعنوان یک نمونهء منفرد نداره.
بحث کلی هست دربارهء طراحی زبان.
اینکه معیارش چیه و آیا این موارد رفتار خاص در PHP که در هیچ زبان دیگری نظیرش دیده نشده، طراحی درست و مفیدی هستند یا خیر.
رجیسترگلوبالز هم مستندات روشن داشت و مطالب راجع به روش پرهیز از باگ و حفره بخاطر اون هم در نت پر بود. ولی با این حال یک طراحی اشتباه بود و در عمل بیشتر خسارت ببار میاورد تا اینکه سود داشته باشه.
پس اینکه بگید مستنداتش هست و نخوندی، لزوما چیزی رو ثابت نمیکنه. بحث ما دربارهء این نیست که مستندات هست یا نیست و برنامه نویس مرتکب خطا شده یا نه. بحث اینه که چرا باید چیزی طوری طراحی بشه که امکان خطای برنامه نویس رو بالا ببره؟ چه توجیه و چه سودی داره که این هزینه و ریسک رو پوشش بده؟ آیا ارزشش رو داره؟ چرا باید چیزی طوری طراحی بشه که نیاز باشه برنامه نویسان چیزهای بیشتری یاد بگیرن و در موقع برنامه نویسی دقت بیشتری بکنن؟

MMSHFE
شنبه 14 دی 1392, 10:08 صبح
در این مورد بنظر من هم حق با eshpilen هست. مسئله اینه که بجز PHP زبانهای Loose Type دیگه هم داریم ولی هیچکدوم در این مورد خاص، اینطوری عمل نکردن. من چند روز پیش داشتم با راسموس درباره این مسئله صحبت میکردم و این مورد رو هم بهش گفتم که حتی اگه بخوایم Loose Type عمل کنیم، اون چیزی که برنامه نویس تو کد زیر انتظار داره:


$a = 0;

switch($a) {
case 'hello':
echo 'hello';
break;
case 'bye':
echo 'goodbye';
break;
default:
echo 'error';
break;
}
// output : hello

اینه که چون caseها از نوع string هستن، a$ تبدیل به string بشه و مقایسه انجام بشه (چون متغیره) نه اینکه ثابتهای case رو بیاد تبدیل نوع کنه! نمیشه که به یکی بگیم اگه فلانی گفت سلام، بهش پولو بده و اگه گفت خداحافظ، فرار کن و اونوقت اون طرف بهش بگه چطوری؟ اونم پولو بده و بیاد بگه فکر کردم منظورش سلامه!

eshpilen
شنبه 14 دی 1392, 10:35 صبح
مهندس اصلا یه جور استدلال دیگر هم میتونیم بکنیم. البته این یک استدلال خاص و موردی هست و بحث کلی این تاپیک درمورد اشتباه بودن کلی این طراحی بجای خودش باقیست.
من میگم اصلا وقتی یک متغییر رو با یک رشتهء hardcode شده در برنامه مقایسه میکنیم، این متغییر هست که باید به رشته تبدیل و مقایسه بشه، نه اینکه اون رشته به زور به نوع متغییره تبدیل بشه!
چون ما خودمون رشته رو صریحا اون شکلی نوشتیم. پس اگر نوشتیم 'hello' مشخصه که منظورمون 0 نبوده، وگرنه میتونستیم بجاش بنویسیم 0.
ولی PHP طوری عمل میکنه که بجای hello اگر goodbye هم نوشته باشیم، باز فرقی نمیکنه!!
حتی اگر ما نوشته بودیم '0hello'، بازم PHP نباید اون رو تبدیل به 0 میکرد، چون دلیلی نداشت اونطور بنویسیم! اگر منظور ما صفر بود پس چرا نوشتیم '0hello'؟
خل که نبودیم!
PHP اینقدر رفتارش متناقض و غیرمنطقیه که میاد اون چیزی که برنامه نویس بطور صریح در برنامه نوشته رو به زور تبدیل میکنه به چیز دیگری که برنامه نویس صریحا مشخص نکرده! بنظر من این منطق مشکل داره! باید بعکس باشه.

MMSHFE
شنبه 14 دی 1392, 10:42 صبح
دقیقاً. من هم همین مسئله رو گفتم. متغیر اسمش روشه و اونه که باید تغییر کنه نه مقادیر ثابت و Hard code شده.

eshpilen
شنبه 14 دی 1392, 10:58 صبح
البته تبدیل چیزی مثل '3' یا حتی ' 3 ' به عدد مشکلی نداره و در زبانهای دیگر هم انجام میشه.
مثلا در همون جاوااسکریپت هم تست کنید، white space رو نادیده میگیره.
این رفتار حداقل توجیه شده تر هست و خطرش هم خیلی کمتره. مثلا نمیشه از این طریق حفرهء sql injection ایجاد بشه یا بهرحال ورودیهای خطرناکی به داخل برنامه بیان.