[font="Tahoma"][rtl]
سلام،
فکر کنم خیلی دوست داری با دم شیر بازی کنی 
البته دوستان خیلی خوب و علمی کاربرد متد attributes در سطح بالای فریم ورک رو گفتند ولی من حدس میزنم جواب سوالت رو نگرفتی!
تو سوالت اینه که فلسفه کارکرد متد attributes چگونست؟
اگر حدس من درست بوده باشه بایستی بگم که سوالت خوب و منطقی بود!
اما جوابش رو شاید توی هیچ راهنما و کتاب YII نمیتونی پیدا کنی، مگر اینکه خودت کدهای فریم ورک رو بخونی.
در یک کلام فریم ورک YII اینکارو به صورت جادویی انجام میده!
سعی میکنم به زبون خیلی ساده بهت بگم چطور! 
از بالا شروع میکنیم به trace برنامه.
اینطور نوشته شده:
[/rtl]
$model=new LoginForm;
$model->attributes=$_POST['LoginForm'];
[rtl]
مدلی از نوع LoginForm ساخته شده و سپس متد attributes اون فراخوانی شده. پس میریم توی مدل LoginForm سراغ متد attributes.
ولی همچین چیزی توش نیست!
اما این مدل از یک کلاس دیگه به نام CFormModel به ارث برده شده (extend شده) پس شاید متد attributes توی اون کلاس باشه. پس میریم سراغ اون کلاس که در framework/web/CFormModel.php قرار داره (اگر از IDE های پیشرفته مثلاً Eclipse استفاده کنی، با نگه داشتن Ctrl و کلیک روی اسم کلاس، مستقیم میری توی فایل اون کلاس)
خب فایل CFormModel.php باز شد ولی اینجا هم خبری از متد attributes نیست! ولی نا امید نمیشیم و ادامه میدیم!
این کلاس هم از CModel ارث بری کرده پس میریم سراغ فایلش یعنی framework/base/CModel.php اما همچنان اینجا هم اثری از متد attributes نیست!
اما یک متد به اسم getAttributes هست! شبیهش هست ولی خودش نیست! پس شاید بهش نزدیک شدیم!
میریم جلوتر…
کلاس CModel هم از کلاس CComponent ارث بری کرده پس به سراغ فایلش framework/base/CComponent.php میریم.
ولی اینجا هم اثری از متد attributes نیست!
پس چی شد؟!
سر کاریم؟!
حالا فهمیدید چرا گفتم فریم ورک YII اینکارو به صورت جادویی انجام میده؟!
برای توضیح این جادو، لازم یکم به جد بزرگ YII یعنی PHP برگردیم! (اینا همه خانوادگی جادوگرن!!!
)
یه کد ساده داریم بدین صورت:
[/rtl]
<?php
class Test {
public $param;
}
$obj = new Test();
$obj->param = "Hello";
echo $obj->param; //output: Hello
?>
[rtl]
خب مشخه یک attribute به نام param که درون سطح کلاس تعریف شده مقدار دهی میشه و چاپ میشه که عبارت Hello در خروجی ظاهر میشه.
اما وقتی که متغییر param در سطح کلاس تعریف نشده، شاید کد بازهم درست کار کنه، یعنی شاید خود PHP به صورت داخلی متغییر رو بسازه و انتساب رو انجام بده. اما شما کنترلی روی این قضیه ندارید. برای اینکه اون رو مدیریت یا سفارشی کنید اینجا از یک متد سیستمی به اسم __set() استفاده میشه.
مثال:
[/rtl]
<?php
class Test {
function __set($name, $value) {
$this->$name = $value * 2;
}
}
$obj = new Test();
$obj->param = 100;
echo $obj->param; //output: 200
$obj->yii = 30;
echo $obj->yii; //output: 60
?>
[rtl]
در این مثال توجه کنید متغییرهای param و yii در سطح کلاس تعریف نشدند ولی نه تنها مقدار میگیرند بلکه حتی در لحظه ای که مقدار میگیرند عملیاتی رو روشون انجام دادیم.
حالا برمیگردیم سر قضیه خودمون!
تا جایی پیش رفتیم که به آخرین کلاس یعنی CComponent رسیدیم، در این کلاس دقت کنید این متد رو میبینید:
[/rtl]
public function __set($name,$value)
{
$setter='set'.$name;
if(method_exists($this,$setter))
return $this->$setter($value);
:
:
:
[rtl]
میبینید که به متغییری که در کلاس مقدار دهی میشه یه set چسبونده بعد با method_exists سعی کرده چک کنه آیا همچین متدی درون کلاس جاری تعریف شده یا نه و اگر وجود داشت اون رو صدا بزنه و البته value رو هم بهش پاس بده تا توی اون یه بلایی به سرش بیاد!
مثلاً اگر ما بنویسیم:
[/rtl]
$model->yii = 'yes it is';
[rtl]
چون yii جزو متغییرهای سطح کلاس نیست (و دقیقاً هم نباید باشه) بنابراین متد __set() وارد عمل میشه و چک میکنه آیا متدی به نام setYii وجود داره یا نه، اگر وجود داشت مقدار ‘yes it is’ رو به همون متد ارسال میکنه.
حالا به اول داستان برمیگردیم. اونجایی که نوشته شده بود:
[/rtl]
$model->attributes = $_POST['LoginForm'];
[rtl]
متدی به نام attributes درسته که وجود نداره اما با این توضیحاتی که دادم، سعی میشه setAttributes پیدا بشه و مقدار $_POST[‘LoginForm’] به همون متد ارسال بشه.
پس از این به بعد بایستی دنبال setAttributes بگردیم. اگر یه مرحله به عقب برگردیم در کلاس CModel میتونیم اون رو پیدا کنیم که $values که ما به صورت یک آرایه بهش پاس دادیم رو گرفته و یک به یک مقادیر رو درون کلیدشون ریخته.
یعنی اگر $_POST[‘LoginForm’] به صورت زیر باشه:
[/rtl]
Array (
'username' => 'iran',
'password' => 'yii',
)
[rtl]
کار setAttributes اینه که این آرایه رو میگیره و iran رو میریزه توی یه متغییر در سطح کلاس به نام username (که در کلاس تعریف نشده) و همینطور yii رو درون password (که در کلاس تعریف نشده) بنابراین پس از اون ما میتونیم به این نحو از اونها استفاده کنیم:
[/rtl]
echo $model->username; //output: iran
echo $model->password; //output: yii
[rtl]
اگر متد attributes در فریم ورک تعریف نمیشد ما مجبور بودیم اینطور مقادیر رو انتساب بدیم:
[/rtl]
$model->username = $_POST['LoginForm']['username'];
$model->password = $_POST['LoginForm']['password'];
[rtl]
که اگر تعداد فیلدها زیاد باشه کار وقت گیر و تکراریه. بنابراین متد attributes با اون داستان پشت پردش رو ساختند تا تنها بنویسیم:
[/rtl]
$model->attributes = $_POST['LoginForm'];
[rtl]
و دیگر هیچ!
ببخشید زیاد حرف زدم.
خواستم موضوع رو زیاد باز کنم تا دوستان مبتدی تر هم بتونن استفاده کنند، چون خیلی از دوستان درمورد نحوه عملکرد پشت پرده فریم ورک پرسیده بودند و به نوعی با این مطلب فکر میکنم روش trace کردن کد رو هم یاد گرفتند تا بقیه چیزها رو خودشون بتونن کشف کنند.
امیدوارم توضیحات مفید واقع شده باشه.
موفق باشید
نبی
[/rtl][/font]