پس یعنی این this به معنای اینه که میگه بعد از اینکه مثلا فلان اسم رو ست کردی، حالا بیا و خود کلاس رو هم برگردون
ولی آخه چه ربطی داره به این که ما بتونیم به صورت chaining متدهارو ست بکنیم؟؟؟؟
من نمیتونم درکش کنم.
محمدجوکار۰۷ بهمن ۱۴۰۱، ۱۲:۵۰
بذار اینجوری توضیح بدم.
شما این کدو در نظر بگیرید:
$mobile->setname()->setoperating()->setfamily();
$mobile یک instance از کلاس Mobile شماست. اولین دستوری که اجرا میشه در کد بالا:
$mobile->setname()
اگر بخوایم به متد setoperation دسترسی داشته باشیم با آبجکتی از نوع کلاس Mobile میتونیم دسترسی بگیریم. داخل کلاس Mobile متغیر $this به آبجکت ساخته شده اشاره میکنه بنابراین اگر return اش کنیم خروجی میشینه جای عبارت. وقتی setname اجرا میشه return $this باعث میشه انگار مجدد خود $mobile رو خارج از کلاس داشته باشیم یعنی ادامه دستور بالا بعد setname به این شکل در میاد:
$mobile->setoperating()->setfamily();
در این مرحله setoperation اجرا میشه و مجدد return $this اجرا میشه و جایگزی میشه و این مرحله رو خواهیم داشت:
$mobile->setfamily();
و به همین صورت آخری اجرا میشه و تمام. بنابراین هرکجا خواستیم زنجیره وار کردن متد رو پیاده کنیم مثل query builder در دیتابیس و ... در نهایت باید خروجی به این شکل باشه که اون آبجکتو داشته باشیم چون فقط با آبجکتی که میسازیمه که میتونیم به بقیه متدها و همچنین propertyها دسترسی داشته باشیم. property چون اسمشو اوردم این معمولا بعنوان آخرین قطعه از زنجیر میاد ولی میتونه به طریقی پیاده شه که هر جایی بیاد. بعنوان مثال دو تا میارم:
class Test
{
public $obj;
public function __construct()
{
$this->obj = $this;
}
public function setname()
{
echo 'name' . PHP_EOL;
return $this;
}
public function setage()
{
echo 'age' . PHP_EOL;
return $this;
}
}
$test = new Test();
$test->setname()->obj->setage();
class Test2
{
public $obj;
public function __construct()
{
$this->obj = new Test3();
}
}
class Test3
{
public $obj;
public function end()
{
echo 'end';
}
}
$test2 = new Test2();
$test2->obj->end();
محسن موحد۰۷ بهمن ۱۴۰۱، ۱۲:۵۲
من اینطوری متوجه شدم:
$mobile->setname()->setoperating()->setfamily();
یعنی در ابتدا setName اجرا میشه
بعد به خاطر ریترن کردن this، در setName، یه آبجکت دیگه از نوع موبایل، انگار قرار میگیره توی setName و ما میتونیم دوباره بگیم از اون آبجکت، حالا setOperating رو صدا بزن.
به همین نحو، setOerating هم به خاطر وجود this درون خودش، حامل یک شی از کلاس خودش میشه و ما ازهمین استفاده میکنیم و متد setFamily اون رو صدا میزنیم.
در صورت درست بودن حرفهای بالام، یه سوال برای من پیش میاد:
در construct گفتید که پراپرتی obj برابر با کلاس خودشه. و به همین خاطره که میشه بعد از اون هم دوباره به یک متد اشاره کرد.
ولی حالا ما چطوری باید خود اون پراپرتی obj رو مقدار دهیش کنیم؟؟؟
محمدجوکار۰۷ بهمن ۱۴۰۱، ۱۶:۲۸
داخل setName قرار نمیگیره بلکه هر کدی که داخل این متد هستو ابتدا تفسیر میکنه و بعد $this رو برمیگردونه و انگار خودش حذف میشه و زنجیر از $mobile مسیرش ادامه پیدا میکنه به setOerating که بعدی اجرا بشه.(البته احتمالا منظور شما هم همین جمله ایه که من نوشتم منتها خواستم از لحاظ نگارشی هم درستش کنم)
چرا باید مقدار دهیش کنیم؟ پراپرتی هارو خودمون با هدفی که در ذهن داریم، پیاده میکنیم. هدف من از ساخت obj این بوده که آبجکت رو نگه داره اگر نیاز به نگه داشتن متغیرهای دیگه ای دارم، پراپرتیهای دیگه ای میسازم. ببینید براساس هدفی که داریم همه چیز رو مینویسیم و اضافه میکنیم و یک سناریو رو میتونیم به روشهای مختلفی پیاده کنیم. بستگی داره چی میخوام پیاده کنم. lیه مثال میارم که همه چیزو باهم قاطی کردم که متوجه بشی هر کاری میشه انجام داد، باید ببینیم چی میخوایم:
نکته: معمولا توو همچین پیاده سازی هایی که setter , getter داریم فیلد $fields بصورت private تعریف میشه که من برای اوردن مثالهای مختلف بصورت public اوردم.
آهااا الان اینجا توی گتر گفتید که اگر t1 درون اون لیست وجود داشت، بیا و ومقدارشو ریترن کن.
انگار گفتیم return $this
ولی اینو نمیفهمم که چی شد که مستقیم تونستیم از $test به t1 دسترسی داشته باشیم.
$test->t1->display();
محمدجوکار۰۷ بهمن ۱۴۰۱، ۱۷:۲۷
جواب سؤالت همینجاست:
"آهااا الان اینجا توی گتر گفتید که اگر t1 درون اون لیست وجود داشت، بیا و ومقدارشو ریترن کن.
انگار گفتیم return $this"
اینهارو ببین براساس getter ای که نوشتم دسترسی دارم:
echo$test->id; // 123echo$test->title; // m1
var_dump($test->t1); // this is an OBJECTecho PHP_EOL;
echo$test->t1 instanceof Test1; // true
در مثال اولی که اوردی یک متغیر داشتی به اسم $mobile الان اگر کلاس Test1 رو کلاس Mobile در نظر بگیریم(فرض کنیم)، این دو عبارت باهم برابرن:
$test->t1 == $mobile
مسئله زمان رو هم در نظر بگیرید، چند روز دیگه این پیاده سازی هارو بهتر از الان درک میکنید.
بازم هرجاییش گنگه بگید تا مثال بیشتری بیارم. (چون خیلی تنوع دادم و چند مدل پیاده سازی رو در کنار هم اوردم ممکنه بعضی چیزا تازگی داشته باشه.)
محسن موحد۰۷ بهمن ۱۴۰۱، ۱۷:۳۴
ممنونم آقای موحد. فکر میکنم متوجهش شدم.
اتفاقا مثالهاتون خیلی عالی بود چیزای جدیدی هم ازش یاد گرفتم.
مجدد تمرین میکنم، اگر اشکالی بود در همین تاپیک میپرسم سوالمو
تشکر که باصبوری پاسخ دادید
احمدرضا جان از شمام ممنونم
محمدجوکار۰۷ بهمن ۱۴۰۱، ۱۷:۴۸
خواهش میکنم. سؤالی بود درخدمتم.
محسن موحد۰۷ بهمن ۱۴۰۱، ۱۷:۵۲
میشه ببینید این ارور برای چیه؟؟؟؟؟؟
البته من ستر رو تعریف نکردم. ربطی داره بهش؟؟؟؟
محمدجوکار۰۷ بهمن ۱۴۰۱، ۱۸:۵۷
شما با آبجکت اومدید مثل یک string برخورد کردید:
لاین 35 عبارتی که return میشه رو با PHP_EOL کانکت کردید. بنابراین مفسر باید آبجکتو به رشته cast کنه که با این خطا روبرو میشه.
شما در این کدی که نوشتید چون داده هاتون انواع مختلفی دارن و Mix هستن باید بصورت خام و ساده return کنید و بیرون از کلاس هرجا نیاز داشتین عبارتو تجزیه کنید.