چند سوال ساده ولی مهم و مفید پیرامون بانک اطلاعاتی در یی

[right]

[font="Tahoma"]

[rtl]

سلام به همه دوستان عزیز

وسط انجام یک پروژه من دچار چند مشکل و یا تردید شدم که کارمو متوقف کرده. ممنون میشم با توجه به تجربه هاتون جواب بدین. برای سایر دوستان هم می تونه مفید باشه این موارد.

1- برای ذخیره سازی تاریخ در بانک اطلاعاتی، شما فیلدهای DateTime در MySQL رو پیشنهاد می کنید یا همون روش ذخیره تاریخ با فورمات یونیکس در فیلد های Integer رو؟

این تاریخ باید در بخش فارسی به شمسی تبدیل و نمایش بشه و در بخش لاتین هم به میلادی

2- خیلی وقت ها ما تنها بخشی از فیلدهای یک جدول رو به روز رسانی می کنیم.

مثلا در ویرایش پروفایل کاربر، ممکنه بخوایم ویرایش رمز عبور و ایمیل در صفحه یا صفحه های جداگانه انجام بشه

در تمام مثال ها چون مقادیر Attribute ها رو massive مقدار دهی کردن

الان برای به روز کردن تنها 2-3 فیلد جدول و نوشتن شکل صحیح تابع هایی مثل update یا saveAttribute دچار مشکل شدم

متاسفانه داخل رفرنس های YII هیچ مثالی در باره شکل استفاده از توابع نیست

ایا جایی مثال سرغ دارید

یا ممکنه همینجا برای نوشتن این دو تابع مثال بنویسید

دستور زیر رو به ده ها شکل مختلف می نوشتم و حالت های مختلف نوشتن دستو update و updateByPk & saveAttributes رو هم امتحان کردم ولی موفق نشدم

[/rtl]

[/font]

[/right]




		// Save $user->u_prof->note values received from a form by post method

		// u_prof is a relation defigned in User model, point to UserProfile model.

		if (isset($_POST['UserProfile'])) {

			$user->u_prof->update (array(

				'condition'=>'uid='.Yii::app()->user->id,

				array('note'=>':note'),

				'params' => array(':note'=>'HelloOo'),

				));

			}



[right][font="Tahoma"][rtl]

در دستور بالا ‘HelloOo’ فقط برای امتحانه

در عمل باید مقدار فیلد $user->u_prof->note از جدول ‘UserProfile’ باید ذخیره بشه

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

3- آیا میشه داخل پروژه MVC که مدل های اکتیو رکورد داره

برای کارهای کوچک داخل کنترلر و یا مثل لاگین کاربر از Query Builder هم استفاده کرد؟ اشکالی پیش نمیاد؟

4- آیا مثال ساده ایی برای انجام یک پروژه MVC در Yii منتها با Query Builder سراغ دارید؟

ممنون

[/rtl]

[/font]

[/right]

[rtl][font="Tahoma"]سلام،

  1. شخصاً هر دو روش رو استفاده کردم، قبلاً گرایشم به روش دوم بود ولی از وقتی با تابع strtotime آشنا شدم دیگه چندان فرقی برام نداره. باید دید خودتون چطور راحتید.

  2. مشکلی نداره چون میتونید همه رو باهم مقدار دهی کنید و یا اینکه تنها چند یا یک مقدار رو مقدار دهی کنید.

مثال:[/rtl]




$model = User::model()->findByPk(1);

$model->email = $_POST['User']['email'];

$model->update();



[/font]

[font="Tahoma"][font="Tahoma"][rtl][/font]3. مثلاً چه مشکلی؟ شما مجازید هر سه روش کار با دیتابیس، استفاده کنید.

  1. پروژه که تغییر نمیکنه! تنها روش ارتباط با دیتابیس رو میخواید عوض کنید. همون پروژه وبلاگ رو درنظر بگیرید، در جاهایی که با اکتیو رکورد با دیتابیس ارتباط برقرار کرده، شما از query builder استفاده کن. سناریوی پروژه که عوض نمیشه.

ممنون

[/font][/rtl]

[rtl][font="Tahoma"]وقتی داشتم پاسخ مینوشتم ظاهراً پستت رو ادیت کردی، درمورد مورد 2 اضافه میکنم:

پارامترهایی که به update ارسال کردی، برای متد updateAll هست، درمورد update فرق میکنه. ورودی ها رو اینجا ببین:

http://www.yiiframew…d#update-detail

اما چرا خودت رو میخوای با updateAll درگیر کنی که مجبور بشی همزمان کوئری بگیری و آپدیت کنی، این خوبه! ولی به نظر من خوانایی کد رو پایین میاره.

اگر من بودم اینطور مینوشتم:

(با توضیح این نکته که نوشتی u_prof یک ریلیشن از مدل User هست که به مدل UserProfile میرسه، پس لزومی نداره مدل User رو بسازی تا از ریلیشنش استفاده کنی، بلکه خود مدل UserProfile رو مستقیم میتونی بسازی و استفاده کنی)

[/rtl]




if (isset($_POST['UserProfile'])) {

	

	//create an instance of UserProfile model for current user 

	$model = UserProfile::model()->findByPk(Yii::app()->user->id);

	

	//set value

	$model->note = $_POST['UserProfile']['note'];

	

	//update value

	$model->update();

	

}



[/font][font="Tahoma"][font="Tahoma"][rtl]

[/font]موفق باشی

[/font][/rtl]

[rtl][font="Tahoma"]

سلام. خیلی ممنون از این که توجه کردید و جواب دادید

در مورد مورد شماره 4 فکر نکنم،

چون منظور من عدم استفاده از اکتیورکورد بود و احتمالا شما متوجه منظورم نشدید.

چون در این حالت مدل ما قرار نیست اکتیورکورد رو extend کنه، خیلی برام جالب شده که اصلا مدل رو چطوری می نویسند

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

در مورد مثال update خیلی ممنون از توضیحتون

اون طوری که در کتاب خوندم، ظاهرا فقط در صورتی که با save مقادیر Attribute ها رو massive مقدار دهی کنیم

در برابر sql injection داده ها فیلتر میشن

به همین خاطر من از save به صورت زیر استفاده کردم

[/font][/rtl]


if (isset($_POST[$UserProfile]))

	{

	$user->u_prof->attributes= $_POST[$UserProfile];

	$user->u_prof->save(true,array('note'));

	}



[font="Tahoma"][rtl][b]

چون فقط قرار بود فیلد note مقدارش ذخیره بشه، من آرگومان های save رو طبق رفرنس به شکل بالا قرار دادم

اما هر طوری که تست کردم، دستورات بالا به جای note همه فیلدهای لود شده رو ذخیره می کنه

در حالی که طبق رفرنس yii الان باید فقط مقدار note ذخیره بشه!

[/b]

[/font][/rtl]

[font="Tahoma"][rtl]

(1)

همونطور که گفتم شخصاً در پروژه های مختلف هر دو رو استفاده کردم. فکر میکنم اگر تاریخ همیشه شمسی باشه کار با timestamp ساده تر باشه. اما اگر مطمئن هستید تاریخ میلادیه که خب همون نوع date میتونید بذارید که دیگه هم نخواد بعد از خوندن فیلد، اون رو از تابع خاصی عبور بدید. من خودم گرایشم به سمت timestamp هست ولی اگر این یک روش قطعی بود هیچوقت mysql تایپ date رو درست نمیکرد، پس حتماً یه مزایایی برای خودش داره. نهایتاً انتخابش با خودتونه و البته تحقیق رو فراموش نکن. سعی کن ببینی در پروژه های بزرگ و برنامه نویسای بزرگ از چه روشهایی استفاده کردند بعد بیا به منم بگو! ;)

(4)

من هم شنیدم AC کارایی رو پایین میاره ولی شاید برای سایتهای بسیار بزرگ باشه، من که خودم سادگی کارشو ترجیح میدم به معایبش. ضمن اینکه نباید ویژگی Lazy loading رو هم که به سرعت کمک میکنه رو فراموش کرد.

حالا یه چیز هم بگم که اگر نمیدونستی، بیشتر ته دلتو خالی کنم :D هر وقت برای اولین مرتبه یک مدل AC رو میسازی، برای اینکه ستون ها و ساختار جدول رو بفهمه، بلافاصله دو تا کوئری خوشگل میگیره اینطوری:

[/rtl]




SHOW COLUMNS FROM `user`

SHOW CREATE TABLE `user`



[rtl]

البته بعداً اگر بازهم از اون مدل بسازی، دیگه این کدها رو تکرار نمیکنه.

درمورد QB و نحوه جایگزین کردنش با AC خیلی دنبال چیز پیچیده ای نباشید، درست میگید که از مدل های AC استفاده نمیشه و شاید یک مقدار روش کار متفاوت باشه، من وقتی به منطقم رجوع میکنم میبینم که در QB خودمون کوئری رو میسازیم پس اسم تیبل و فیلدها رو همون موقع وارد میکنیم و میمونه مقادیرشون، که اون هم مستقیم از ‎$_GET خونده میشن و در پارامترهای کوئری قرار میگیرند. میمونه بحث Validate کردن که اون رو هم میشه از مدل های CFormModel کمک گرفت، یعنی اینکه مقادیر رو از ‎$_GET ریخت توی یه مدل CFormModel بعد validate کرد و نهایتاً مقادیر همون Model رو در درست کردن کوئری در روش QB مورد استفاده قرار داد.

من خودم با QB زیاد کار نکردم ولی فکر نمیکنم چیزی بیشتر از این باشه، با این حل خودتون هم یه تحقیق کنید.

http://www.yiiframew…e.query-builder

(2)

حق با شما بود کد من دو کوئری اجرا میکنه، حال اونکه با updateByPk میشه با یک کوئری هم همونکارو انجام داد. این میتونه صحیح تر باشه:

[/rtl]




User::model()->updateByPk(1, array('email'=>$_POST['User']['email']));



[rtl]

اما درمورد مسئله ای که شما مطرح کرده بودید، از دو حالت خارج نیست، یا مدل User رو قبلاً برای اهداف دیگه لود کردید که خب object اون وجود داره و از ریلیشن اون برای آپدیت note میتونید استفاده کنید. بدین صورت:

[/rtl]




$user->u_prof->note = $_POST['UserProfile']['note'];

$user->u_prof->update();



[rtl]

و یا اینکه هنوز object user ایجاد نشده پس نیازی هم بهش نداریم و چون note مربوط به جدول مستقل UserProfile هست، میتونید مستقیماً note رو توی جدولش بنویسیم. اینطوری:

[/rtl]




UserProfile::model()->updateByPk(Yii::app()->user->id, array('note'=>$_POST['UserProfile']['note']));



[rtl]

در هر دو حالت هم تنها یک کوئری اجرا میشه.

ممنون.

[/font]

[font="Tahoma"][/rtl][/font]

[rtl][font="Tahoma"]مثکه بازم وقتی در حال پاسخ نوشتن بودم، پستت رو ویرایش کردی. درمورد آخر والا کدت به نظر درست میاد. فقط اون ‎$UserProfile علامت دلار اولش درسته؟!

[/font][/rtl]

[font="Tahoma"][rtl]

سلام مجدد و تشکر از شما دوست خوبم برای راهنمایی و حسن نیت تون.

آخر شب که اومدم دیدم هنوز کسی جواب نداده، پست رو ادیت کردم که هم کمی کوتاه تر بشه و هم مشکل save رو قرار بدم

اما از پاسخ کامل شما خیلی ممنونم.

علامت دلار موقع نوشتن در اینجا اشتباها تایپ شده. در کد اصلی رو چک کردم، اونجا به این شکل نیست.

اما واقعا این کدی که من با save اون بالا نوشتم، به جای این که فقط فیلد note رو ذخیره کنه، میاد و همه فیلدهای لود شده رو ذخیره می کنه!!!

حالا اگه امکان تست رو داشتید خودتون می تونید آزمایش کنید.

در مورد مثال های شما من یاد مطلبی افتادم.

در رفرنس ها گفته شده که برای جلوگیری از SQL Injection باید از جانگهدارها استفاده کنیم

یعنی اول بگیم مثلا note= :note و بعد در جای دیگری بگیم

[/rtl]:note= "my note reveived from from"[rtl]

من در مثال اولم پیرامون مشکل update این روند رو انجام دادم که می تونید ببینید.

در مثال های خوب شما، این آیتم رو نمی بینم!

کد من به این شکله که جدول های user و userProfile رو لود می کنیم تا در صفحه اول کنترل پنل کاربر مشخصاتش رو نشون بدیم. در همون صفحه یک فورم با تنها یک کادر متنی برای submit کردن سریع note گذاشتم.

مثل facebook که در همون صفحه نمایش فیدهای کاربران در تایم لاین، اون بالا یک کادر متنی به اسم post user status گذاشته که کاربر خیلی سریع همون جا status ارسال کنه.

برای اینکه بعد از ذخیره کردن note کاربر ما ناچار نشیم یکبار دیگه به همون صفحه redirect کنیم

من برنامه رو این طور نوشتم:

نمایش کنترل پنل کاربر

1- مدل های کاربر و پروفایل رو لود کن

2- اگر کاربر در فرم موجود در صفحه کنترل پنل، note رو submit کرده، مقدار note رو در رکورد لود شده و همچنین در جدول بانک اطلاعاتی به روز کن

3- صفحه کنترل پنل رو نمایش بده

[/rtl]




	/**

	 * Shows the Control panel of User

	 */

	public function actionIndex()

	{

		$user=$this->loadUser(Yii::app()->user->id);

		if (empty($user->u_prof))

			throw new CHttpException(403,'The user has not created profile yet.');

		

		// Save UserProfile->note value from forms

		if (isset($_POST['UserProfile'])) { // save $user->u_prof->note

			$user->u_prof->attributes= $_POST['UserProfile'];

			$user->u_prof->save(true,array('note'));

			}

			

		$this->render('index',array(

			'user'=>$user,

		));

	}


Comment: $user->u_prof->save(array('note')); and $user->u_prof->save('note');

get the same result and saved all the fields in DB! (instade of save only "note" field)



[rtl]

در مورد ایده استفاده از CFormModel فکر کنم جالب باشه. باید سر فرصت این رو آزمایش کنم

توضیح شما مفید بود.

اون دو تا کوئری خوشگل رو در totorial های لاری اولمن خونده بودم و یادمه ایشون هم گله کرده بودن

تو zend framework ما یک کلاس به نام جدول تعریف می کنیم که شامل مشخصات فیلدهای جدوله و دیگه نیازی به اون دو کوئری نیست. نمی دونم چرا تو Yii این کار رو نکردن

اما زمان

من بررسی کردم دیدم در کدهای اغلب کلاس های نوشته شده برای تبدیل تاریخ میلادی به شمسی، اول تاریخ رو به فورمات یونیکس تبدیل می کنند و بعد مثلا میرن سراغ محاسبه معال شمسی اون تاریخ

از طرفی اگه ما بخوایم اختلاف دو زمان رو محاسبه کنیم باز هم ناچاریم اون ها رو به شکل یونیکس داشته باشیم

پس با این که الان در بانک اطلاعاتی من تمام تاریخ ها به صورت فیلدهای date یا datetime هستند

اما با توضیح فوق فکر می کنم بهتره در اولین فرصت همه فیلدهای زمان رو به Integer تبدیل کنم و تاریخ رو با فورمات یونیکس (همون تایع time()) در جدول های بانک اطلاعاتی ذخیره کنم.

البته اگه شما هم موافق هستید :)

[/rtl][/font]

[right][font="Tahoma"][rtl]

فقط به عنوان یک نکته بگم که در اکثر پروژه ها استفاده از timestamp یا همون intکافیه و حتی توی خیلی از محاسبات مربوط به تاریخ کار آدم رو راحتتر میکنه[/font]

[font="Tahoma"]اما با این حال توی بعضی پروژه های خاص که نیاز به دخیره کردن و نمایش تاریخهای خیلی قدیمی دارن (مثلا قرن 5 میلادی یا شمسی یا هر چیز دیگه ای) استفاده از unix timestamp مشکل ساز خواهد شد چون فقط بعد از سال 1970 میلادی رو ساپورت میکنه اما چون datetime به صورت رشته در DB ذخیره میشه این محدودیت رو نداره ( البته به شرط اینکه سمت php هم برای نمایش این تاریخهای قدیمی از توابع مناسب استفاده کنید)

موفق باشید

[/font][/rtl]

[rtl]

[font=“Tahoma”]اگر علاقه و وقت کافی برای این تغییرات دارید کار منطقی ایه ;)[/font]

[/rtl]

[/right]

[font="Tahoma"][rtl]

وقتی مباحث زیادی رو همزمان مطرح میفرمائید لطفاً شماره گذاری کنید تا نیاز به نقل قول نباشه.

(1)

درمورد ذخیره کردن فقط فیلد note:

من قبلش تست کرده بودم، روش کار به نظر درست میاد. ممکن است در جای دیگری کد مشکل داره که باید کد کاملتری بگذارید.

(2)

درمورد روش مقدار دهی با استفاده از note=:note

این روش برای زمانیه که از condition استفاده میکنیم و شرط رو به صورت یک string وارد میکنیم که غالباً بعد از آرگومان condition همیشه یک آرگومان params برای پارامترهای اون میاد. (که شما استفاده کردید) اما زمانی که مقادیر به صورت array و زوج کلید=>مقدار، انتساب داده میشوند؛ عملیات اسکیپ یا سایر لحاظ های امنیتی به طور توکار توسط فریم ورک انجام میشود. (به همین خاطر من استفاده نکردم)

(البته این بر اساس تجربه شخصی بود و منبعی برای این مطلب ندارم که امیدوارم اشتباه نکرده باشم. لطفاً اساتید تائید یا رد کنند)

(3)

درمورد کدی که قرار دادی، لازمه یک نکته رو بگم.

این syntax صحیح استفاده از متد save است:

[/rtl]




public boolean save(boolean $runValidation=true, array $attributes=NULL)



[rtl]

توجه کنید که شما میتونید پارامتر اول رو مقدار بدید و پارامتر دوم از مقدار پیشفرضش استفاده بشه ولی نمیتونید مستقیم مقدار دوم رو مقدار دهی کنید و همیشه مجبورید پارامتر اول متد رو هم مقدار بدید.

با این توضیج به کدهاتون در commentیی که گذاشتید دقت کنید، شما دارید پارامتر اول رو با یک رشته یا array که همیشه true است مقدار میدید! یعنی اینکه کلیه دستورات زیر یک کار یکسان انجام میدن:

[/rtl]




$user->u_prof->save(array('daily_msg'));

$user->u_prof->save('daily_msg');

$user->u_prof->save(true);

$user->u_prof->save();



[rtl]

یعنی هر چهار دستور، قائدتاً باید کلیه فیلدها رو ذخیره کنند.

اما درمورد این دستور قضیه فرق میکنه و [/font][font="Tahoma"][font="Tahoma"]قائدتاً [/font]باید تنها فیلد daily_msg ذخیره بشه:

[/rtl]




$user->u_prof->save(true,array('daily_msg'));



[rtl]

اگر غیر از اینه، که با منابعی که در اختیار گذاشتید من نمیتونم بگم مشکل از کجاست!

(4)

درمورد کوئری های اضافه:

و جالب اینجاست در بالای Model های ActiveRecord که توسط GII تولید میشن، اسم فیلدها رو به صورت توضیحات درج میکنه! در حالی که میشه اون ها رو به صورت منطقی در کد قرار داد که قابل انتساب باشند و نیازی نباشه هر بار برای خوندن ساختار تیبل کوئری بگیره.

(5)

درمورد نوع ذخیره کردن date در دیتابیس هم من نظری ندارم :D

ممنون

[/rtl]

[/font]

[font="Tahoma"][rtl]

سلام دوست خوبم

ممنون از توضیحات خوب و مفید شما

مشکل ذخیره شدن همه فیلدها هنوز هم هست

من کد دیگری ندارم که بگذارم.

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

اما اگر شما یا دوستان دیگر کسی حوصله کنه و کد زیر رو نگاه کنه، ممنون میشم

کد زیر همون کد بالا هست. منتها روش من در ازمایش ذخیره سازی فیلدها رو نشون میده

[/rtl]




	/**

	 * Shows the Control panel of User

	 */

	public function actionIndex()

	{

		$user=$this->loadUser(Yii::app()->user->id);

		if (empty($user->u_prof))

			throw new CHttpException(403,'The user has not created profile yet.');

		

		// Save UserProfile->note value from forms

		if (isset($_POST['UserProfile'])) { // save $user->u_prof->note

			$user->u_prof->attributes= $_POST['UserProfile'];

			

			$user->u_prof->first_name='new name';


			$user->u_prof->save(true,array('note'));

			}

			

		$this->render('index',array(

			'user'=>$user,

		));

	}



[rtl]

فرم ما فقط یک فیلد note داره با یک دکمه post جهت submit کردن فرم

اگه کد بالا درست باشه باید فقط مقدار note ذخیره بشه اما با کمال تعجب میبینیم که مقدار فیلد first_name هم با عبارت جدید new name ذخیره شده!!!

[/font][/rtl]

[rtl][font="Tahoma"]یکبار به همین روش سعی کن یک فیلد از مدل User رو سیو کنی، یعنی کاری به ریلیشنش نداشته باش.

ببین چطوری میشه

[/font][/rtl]

[font="Tahoma"][rtl]

وقتی با مدل User کار می کنم این مشکل وجود نداره. الان چک هم کردم و فقط همان فیلد مورد نظرم را ذخیره کرد.

اما چرا با رابطه که میام کار کنم، دچار مشکل میشه و جواب نمیده؟!

[/rtl][/font]

[font="Tahoma"][rtl]

با سلام به همه دوستان عزیز و بخصوص دوست خوبمون Nabi که در این تاپیک وقت زیادی رو صرف کردند.

برای حفظ بار آموزشی این موضوع برای سایر کاربران مبتدی نتیجه کار من به شرح زیر شد:

تمام ترکیبات دیگه مثل

[/rtl]




$user->u_prof->update(array('note'));


Or


$user->u_prof->saveAttributes(array('note'));



[rtl]

رو من چک کردم.

دستورات بالا اگرچه باید تنها یک فید و آن هم فیلد note رو به روز کنند. اما عملا

تمام فیلدهای u_prof رو به روز می کنند. علت رو نمی دونم!

اما عملا باید در این مواقع به جای لود کردن یکجای دو مدل که با هم رابطه دارند، آن دو مدل رو جداگانه لود کنیم

تا این قبیل کارها هم بی دردسر انجام بشه. به این صورت:

[/rtl]




u_prof->update(array('note'));


Or


u_prof->saveAttributes(array('note'));



[rtl]

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

یعنی با QB جدول های مورد نظرم رو بخونم و آرایه حاوی مقادیر فیلدها رو برای view ارسال کنم.

[b][color="#ff0000"]به روز رسانی: (برای دوستانی که بعدا این بخش رو میبینند)

این نتیجه گیری صحیح نیست و فیلد داخل ریلیشن به طور کاملا صحیح به روز میشه. لطفا پست های ادامه رو ببینید.[/color][/b]

[/font][/rtl]

[font="Tahoma"][rtl]

سلام،

[/rtl]

[rtl]

خواهش میکنم.

[/rtl]

[rtl]

راستش من خودم کنجکاو شدم و یه پروژه کوچیک تعریف کردم و به درستی یک فیلد ریلیشن رو مقدار دهی کردم.

کد رو نگاه کن و با کد خودت مقایسه کن.

مطمئن باش یجای برنامت داری اشتباه میکنی.

اگر کد بیشتری بزاری شاید بهتر بتونم کمکت کنم.

[/rtl]

MySQL:




CREATE TABLE IF NOT EXISTS `profile` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `fname` varchar(45) DEFAULT NULL,

  `lname` varchar(45) DEFAULT NULL,

  `note` text,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;


INSERT INTO `profile` (`id`, `fname`, `lname`, `note`) VALUES

(1, 'a', 'b', 'c');


CREATE TABLE IF NOT EXISTS `user` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `username` varchar(45) NOT NULL,

  `password` varchar(45) NOT NULL,

  PRIMARY KEY (`id`),

  KEY `fk_user_profile_idx` (`id`)

) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;


INSERT INTO `user` (`id`, `username`, `password`) VALUES

(1, 'ali', '123');



User Model:




	public function relations()

	{

		return array(

			'profile' => array(self::BELONGS_TO, 'Profile', 'id'),

		);

	}



Profile Model:




	public function relations()

	{

		return array(

			'user' => array(self::HAS_ONE, 'User', 'id'),

		);

	}



Action:




	function actionSave() {

		$model = User::model()->findByPk(1);

		$model->profile->fname = 'hasan';

		$model->profile->lname = 'hasanpor';

		$model->profile->note = 'salam';

		if ($model->profile->validate()) {

			$model->profile->save(true, array('note'));

			echo 'Saved.';

		} else {

			var_dump($model->profile->errors);

		}

	}



[rtl]

در نهایت پیشنهاد نمیکنم از saveAttributes استفاده کنی، چون لزومی نداره و ممکنه برات دردسر ایجاد کنه. اینجا گفته:

[/rtl]

http://www.yiiframew…tributes-detail

Saves a selected list of attributes. Unlike save, this method only saves the specified attributes of an existing row dataset and does NOT call either beforeSave or afterSave. Also note that this method does neither attribute filtering nor validation. So do not use this method with untrusted data (such as user posted data).

[rtl]

ممنون

[/rtl]

[/font]

[rtl]

[font="Tahoma"]سلام به شما دوست خوب و با مسئولیتم. بله، کاملا حق با شماست!

اتفاقا خودم هم الان متوجه شدم و زودی اومدم خبر بدم که دیدم شما زودتر از من تست کردید و زحمت افتادید.

در واقع فیلد ما فقط داخل view تغییر می کرد و نه در داخل بانک اطلاعاتی.

البته من مقادیر داخل جدول رو با phpMyAdmin چک می کردم و هنوز نمی دونم چرا متوجه این آیتم نشدم که فیلدها در داخل جدول تغییر نمی کنند یا اینکه چه چیزی باعث این تصور اشتباه شد. شاید خستگی.

خلاصه چون پروژه رو باید تا هفته دیگه تموم کنم و هنوز یک عالمه کار مونده، وقتی برای تبدیل کوئری ها از AR به QB نداشتم و همین باعث بررسی بیشتر شد.

کد من رو که چند پست بالاتر قرار دادم، مجددا این زیر می گذارم. ببینید:

[/font][/rtl]




     /**

      * Shows the Control panel of User

      */

     public function actionIndex()

     {

         $user=$this->loadUser(Yii::app()->user->id);

         if (empty($user->u_prof))

             throw new CHttpException(403,'The user has not created profile yet.');

         

        // Save UserProfile->note value from forms

         if (isset($_POST['UserProfile'])) { // save $user->u_prof->note

             $user->u_prof->attributes= $_POST['UserProfile'];

             

            $user->u_prof->first_name='new name';   // CHANGES THE first_name JUST IN LOADED MODEL


            $user->u_prof->save(true,array('note'));

             }

             

        $this->render('index',array(

             'user'=>$user,

         ));    // SHOWS PAGE WITH CHANGED first_name. BUT first_name IS NOT CHANGED IN DB!

     }

 

[rtl]

[font="Tahoma"]در کد بالا اول [font="Arial"][/rtl]


$user->u_prof->first_name='new name'

[rtl]

[/font][/font][font="Tahoma"]اجرا میشه

و بعد همون مدل که البته فیلد first_name اون نه در بانک اطلاعاتی، بلکه فقط در مدلی که لود کردیم، تغیر کرده! به view ارسال میشه

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

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

ممنون :)

[/font]

[/rtl]

[rtl][font="Tahoma"]خواهش میکنم دوست من

و خوشحالم که مشکلت حل شد

ولی دیگه داشتم شاخ در میاوردم :D

از یی لذت ببر!

[/font][/rtl]