من قصد دارم یه فرم بسازم با فیلد هایی از اکتیو رکورد های یک جدول (a)(نتیجه کوئری) که بعد از اعتبارسنجی در جدول دیگر(b) هر فیلد فرم بعنوان یک اکتیو رکورد ذخیره بشه . آیا چنین چیزی با توجه به متفاوت بودن نوع فیلد های فرم (textfiels , dropdownlist , ...)و همچنین بحث اعتبار سنجی امکان پذیر هست. چگونه؟ راه حل بهنری پیشنهاد می کنید؟؟
[
attachment=39]
لطفاً عکس ضمیمه خودتون رو اینجا ضمیمه کنید. عکسهای ضمیمه انجمنهای دیگه اینجا بارگذاری نمیشن.
ضمناً اکتیورکورد معادل یک رکورد هست نه یک فیلد.
از توجهتون سپاسگزارم
درست میفرمایید ولی من اینجا قصد دارم به تعداد رکورد های جدول a فیلد در فرم بسازم و سپس مقادیر وارد شده توسط کاربر رو در جدول b ذخیره کنم.
معماری ما به این
لینک شبیهه
مشکل اینه که همه فیلد ها از یک نوع نیستند یه خصوصیت رو با textfield میگیریم . یکی دیگه رو با dropdownlist و ...
آیا راه حل بهتری وجود داره؟؟
خوب شما باید یک جایی نوع رو تعریف کنید بالأخره. یا توی جدول خصوصیات یا فایل یا هر جای دیگه ولی در کل برای ساخت فیلد توی فرم به تعداد رکوردهای یک جدول، میتونید از این ایده استفاده کنید:
<?php $count = B::model()->count(); ?>
<?php for($i = 0; $i < $count; $i++) : ?>
<?php echo $form->textField($model, values[]); ?>
<?php endfor; ?>
درصورتی که خصوصیات کالاهاتون با هم فرق میکنه، یک فیلد کلی برای خصوصیاتش بگذارین و همه رو بصورت Serialize شده داخل همون بگذارین یا اینکه یک جدول واسطه برای ارتباط جداول A و B بگذارین با این ساختار:
و از این طریق، یک ارتباط n به n بین جداول A و B برقرار کنید و به ازای تمام مقادیری که کاربر توی فرم انتخاب میکنه، یک شئ از مدل این جدول وسطی درست کنید و id کالا رو که از جدول A خوندین توی a_id و id خصوصیات رو که از جدول B میاد، توی فیلد b_id و درنهایت مقدار خصوصیت رو در فیلد value ذخیره کنید.
متشکرم وای مشکل این کد اینه که تمام فیلد ها رو از نوع textfield میسازه.در صورتی که ما بطور مثال به dropdownlist هم نیاز داریم.
حالا فرض کنیم که ستونی برای نوع ( textfield و dropdownlist و ..)هم در جدول a در نظر گرفتیم ولی باز dropdownlist به آپشن های دیگه ای مثل منبع نیاز داره که در این حلقه امکان گنجاندنش نیست.
با توجه به معماری گفته شده در
لینک پاسخ قبل آیا راه دیگه ای برای چنین پیاده سازی وجود داره؟؟
والا من راه دیگه ای به ذهنم نمیرسه ولی میتونید فرضاً اسم مدل و شرط موردنظر رو هم داخل جدول B ذخیره کنید. مثلاً این فیلدها رو داشته باشین:
کد:
id
attribute
type
model
where
حالا فرض کنید این مقادیر توی جدول ذخیره شده:
id attribute type model where
----------------------------------------------------------------------------
1 name textField NULL NULL
2 country_id dropDownList Countries confirmed=1
3 username textField NULL NULL
4 password passwordField NULL NULL
حالا با این کد میتونید المنتهای فرمتون رو بسازین:
<?php foreach(B::model()->findAll() as $b) : ?>
<?php if(!$b->model) : ?>
<?php echo $form->{$b->type}($model, $b->attribute); ?>
<?php else: ?>
<?php echo $form->{$b->type}($model, CHtml::listData({$b->model}::model()->findAll($b->where), 'id', 'name')); ?>
<?php endif; ?>
<?php endforeach; ?>
سعی کردم سناریوی کلی رو بهتون بگم. دیگه بیشتر از این رو باید با توجه به نیازتون، خودتون روی کدها کار کنید.
یعنی فرم بصورت استاتیک و بدون مدل طراحی بشه؟؟ و برای ساخت از درون کنترلر هربار یه مدل ایجاد بشه و ذخیره بشه؟؟
البته کدی که من گذاشتم مدل داره ولی میتونید بدون مدل هم فرم بسازین. کافیه مستقیماً از CHtml استفاده کنید.
چون توی فرم میبایست از radiobutton هم استفاده میکردم . تصمیم گرفتم فرم رو با chtml بسازم ولی مشکل اینه وقتی فرم رو ارسال میکنم توی actionCreate و جهت تست توی print_r قرار میدم فقط فیلد های تعریف شده در مدل دریافت شدن. و خبری از داده های المنت هایی که اضافه کردیم نیست. و اینکه به این ترتیب validation رو هم نمیشه انجام داد
class DynamicFormModel extends CFormModel {
private $_dynamicData=array();
private $_dynamicFields = array(
'firstname' => 1,
'lastname' => 1
);
public function rules() {
return array(
array('firstname, lastname', 'safe')
);
}
public function attributeNames() {
return array_merge(
parent::attributeNames(),
array_keys($this->_dynamicFields)
);
}
/**
* Returns the value for a dynamic attribute, if not, falls back to parent
* method
*
* @param type $name
* @return type
*/
public function __get($name) {
if (!empty($this->_dynamicFields[$name])) {
if (!empty($this->_dynamicData[$name])) {
return $this->_dynamicData[$name];
} else {
return null;
}
} else {
return parent::__get($name);
}
}
/**
* Overrides the setter to store dynamic data.
*
* @param type $name
* @param type $val
*/
public function __set($name, $val) {
if (!empty($this->_dynamicFields[$name])) {
$this->_dynamicData[$name] = $val;
} else {
parent::__set($name, $value);
}
}
}
نظر شما در رابطه با این قطعه کد چیه؟ مشخصه که override کرده ولی روش استفادش به چه شکله؟
اینم توضیحات نویسنده:
1. Add a private array called "dynamicValues" for storing data for dynamic properties.
2. Add a "dynamicAttributeNames" property for storing the names of dynamic attributes.
3. Override the "__set" and "__get" magic methods to see if the property being set is dynamic and store/retrieve it from the right data structure.
برای دریافت سایر داده ها، لازم نیست که حتماً توی دیتابیس باشن. دستی توی کلاس مدلتون فیلد public اضافه کنید و براشون توی rules ولیدیشن رول بنویسید. البته اگه تغییراتتون زیاده، توصیه میکنم از CFormModel استفاده کنید.