تالار گفتمان nCIS.ir

نسخه‌ی کامل: چیدن فیلد ها بر اساس سناریو در فرم
شما در حال مشاهده نسخه آرشیو هستید. برای مشاهده نسخه کامل کلیک کنید.

a1552f

سلام من یک مدل دارم با چندین سناریو میخوای توی ویو جستجو و ویو افزودن فیلد ها رو نصبت به اون ظرفی که دارم ، مثلا (col-xs-8 یا col-xs-12) 
مثلا وقطی ظرف کلی col-8 هست فیلد ها با col-xs-4 قرار بگیرند و وقتی 12 هست با 3

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

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

a1552f

به عنوان مثال من 10 تا سناریو دارم . ابتدا اومدم یک ولیدیشن به اسم FormValidation ساختم که از کلاس 

namespace commoncomponentsvalidator;

use yiivalidatorsvalidator;

class FormValidator extends Validator
{

}

کارش این هست که هر attribute بهش پاس بدم ولید میشه ! و اومدم توی مدلم به اسم فایل دوتا متد نوشتم 
class File extends yiidbActiveRecord
{

.
.
.

public function myAttributes()
{
$scenario = $this->getScenario();
$scenarios = $this->myScenarios();
if(!isset($scenarios[$scenario])){
return [];
}
$attributes = $scenarios[$scenario];
foreach ($attributes as $attribute) {
if($attribute[0] === '!') { 
$attributes[$i] = substr($attribute, 1);
}
}

return $attributes
}


public function myScenarios()
{
$scenarios = [];
foreach($this->getValidators() as $validator){
if($validator instanceof FormValidator){
foreach($validator->on as $name) {
foreach($validator->attributes as $attribute) {
$scenarios[$name][$attribute] = true;
}
}
}

}

foreach ($scenarios as $scenario => $attributes){
if(!empty($attributes)){
$scenarios[$scenario] = array_keys($attributes);
}
}

return $scenarios;

}

}
داخل ویو میام توی بدنه فرم کلاسی رو که برای چیدن فرم نوشتم فراخونی میکنم و متغییرهای form و model رو بهش پاس میدم .

کد ویو : 
<?php

use yiibootstrapActiveForm;
use yiibootstrapHtml;


?>

<div class="row">
<?php 

$form = ActiveForm::begin();
$dynamicForm = new commonwidgetsDynamicForm($form, $model)
?>
<div class="col-xs-12">
<?= Html::submitButton('search', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div> 

حالا به نظرتون توی این کلاس DynamicForm بیام و بر اساس هر سناریو یک ویو بسازم یا اینکه بیام و فیلد ها رو به صورت داینامیک نشون بدم ، برای نمایش داینامیک امکان داره توی هر سناریو یک فیلد به صورت تکی یا دو چند فیلد کنار هم دیگه قرار بگیرن که با input-group-addon بوت استراپ از هم جدا میشن ولی به صورت inline  کنار هم هستن .

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

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

امیدوارم تونسته باشم منظورمو برسونم
اون ولیدیتورتون چرا اینطوریه؟ خوب چرا از safe استفاده نمیکنید؟ بنظر من برای هر سناریو یه ویوی جداگانه بسازین، خوانایی و قابلیت پشتیبانی برنامه شما بهبود پیدا میکنه.
یه روش سوم هم وجود داره: بیاین مدلهای مختلف بسازین برای سناریوهای مختلف (که به دیتابیس وصل نیستن) و ولیدیتورها رو اونجا برای هرکدوم جداگانه تعریف کنید. بعد از اینکه مدل ولیدیت شد، اتریبیوتها رو به مدل اصلی پاس بدین و ذخیره کنید (بدون ولیدیشن مجدد توی مدل اکتیورکورد). مثال:
$model = new RegisterModel();
if($model->load(Yii::$app->post()) && $model->validate()) { // validation is done here
    $user = new Users;
    $user->attributes = $model->attributes;
    $user->save(false); // save without double validation
}