passing value from Yii CController class to CForm (Form Builder) config array - yii

I'm new to Yii, and I'm trying to do my initial project the "right" way. I've created a CFormModel class that needs three fields to query for some data, a CForm config to construct the form, and a CController to tie it together (all given below).
The data request needs an account, and this can come from a couple of different places. I think retrieving it should be in the controller. However, I don't know how to get it into the form's hidden "account" field from the controller, so that it makes it to the arguments assigned to the CFormModel after submission. More generally, I know how to pass from CController to view script, but not to CForm. Is the registry (Yii::app()->params[]) my best bet?
I suppose I can just leave it out of the form (and required fields) and wait to populate it in the submit action (actionSummaries). Does that break the intention of CForm? Is there a best practice? Even taking this solution, can someone address the first issue, in case it comes up again?
Any other, gentle critique is welcome.
models/SummariesForm.php
class SummariesForm extends CFormModel
{
public $account;
public $userToken;
public $year;
public function rules () {...}
public function fetchSummary () {...}
static public function getYearOptions () {...}
}
views/account/select.php
<?php
$this->pageTitle=Yii::app()->name;
?>
<div class="form">
<?php echo $form->render(); ?>
</div>
controllers/AccountController.php
class AccountController extends CController
{
public $layout = 'extranet';
public function actionSelect ()
{
$model = new SummariesForm();
// retrieve account
require_once 'AccountCookie.php';
/*
*
* Here, I insert the account directly into the
* model used to build the form, but $model isn't
* available to selectForm.php. So, it doesn't
* become part of the form, and this $model doesn't
* persist to actionSummaries().
*
*/
$model->account = AccountCookie::decrypt();
if ($model->account === false) {
throw new Exception('Unable to retrieve account.');
}
$form = new CForm('application.views.account.selectForm', $model);
$this->render('select', array(
'form' => $form,
'account' => $model->account,
));
}
public function actionSummaries ()
{
$model = new SummariesForm();
if (isset($_POST['SummariesForm'])) {
$model->attributes = $_POST['SummariesForm'];
/*
*
* Should I just omit "account" from the form altogether
* and fetch it here? Does that break the "model"?
*
*/
if ($model->validate() === true) {
try {
$summaries = $model->fetchSummary();
} catch (Exception $e) {
...
CApplication::end();
}
if (count($summaries) === 0) {
$this->render('nodata');
CApplication::end();
}
$this->render('summaries', array('model' => $model, 'summaries' => $summaries));
} else {
throw new Exception('Invalid year.');
}
}
}
}
views/account/selectForm.php
<?php
return array(
'title' => 'Select year',
'action' => Yii::app()->createUrl('Account/Summaries'),
'method' => 'post',
'elements' => array(
'account' => array(
'type' => 'hidden',
'value' => $account,
),
'userToken' => array(
'type' => 'hidden',
'value' => /* get token */,
),
'year' => array(
'type' => 'dropdownlist',
'items' => SummariesForm::getYearOptions(),
),
),
'buttons' => array(
'view' => array(
'type' => 'submit',
'label' => 'View summaries',
),
),
);

The answer is NO to do what you asked. You can see $form variable which acted almost like array when it was passed from controller to view. The solution is you add more property $account into selectForm model and treat it like other elements. I don't think leaving the new field outside the form will be properly way if you want to submit its value also.
Edited:

Related

How to get values from my object model and display my banner on header in Prestashop

I developed a custom multi-banner module to display on the header of my prestashop page. When i save my changes on form i would like to display it on header.
My module form:
My table to see all banner inserted:
I tried to use smarty and orm to retrieve all information but i don't know how to display on my header.
Any issues? I hope i can understand my trobles :)
Thanks
Here's the code of some of my files:
//in main file:
public function hookDisplayHeaderBanner($params) {
$banner = Banner::getBannerToDisplay();
// If there is a banner to display
if ($banner) {
$this->context->smarty->assign([
'banner' => $banner
]);
return $this->display(__FILE__, 'views/templates/hook/display-custom-banner.tpl');
}
// Nothing to display
return false;
}
//In classes/Banner.php
class Banner extends ObjectModel
{
public $id;
public $color;
public $background_color;
public $content;
public static $definition = [
'table' => 'custom_banner',
'primary' => 'id_custom_banner',
'multilang' => false,
'fields' => [
'color' => [
'type' => self::TYPE_STRING,
],
'background_color' => [
'type' => self::TYPE_STRING,
],
'content' => [
'type' => self::TYPE_STRING
]
]
];
/*
*
* Return the banner to display
*
* Here we put the logic to select the right banner
*/
public static function getBannerToDisplay()
{
$sql = 'SELECT *
FROM `' . _DB_PREFIX_ . self::$definition['table'] . '`
WHERE active = 1';
return Db::getInstance()->getRow($sql);
}
}
//In display-custom-banner.tpl
<div id="banner" style="background-color:{$banner.background_color}!important;">
<p style="color:{$banner.color}!important;">
{$banner.content}
</p>
</div>
Using:
return Db::getInstance()->getRow($sql);
only retrieve the first row of the result, if you would like to return more than one banner you would like to use Db::getInstance()->executeS($sql); to get all results.
Also check your DB table structure and a var_dump() of the involved variables, this would help understanding if there are more issues.

prestashop - Display status of order in AdminStats

I want the status order to display at AdminStats. I created the file override/controllers/admin/AdminStatsController.php:
<?php // Check order status in Stats Dashboard BO class AdminStatsController extends AdminStatsControllerCore {
public function __construct() {
parent::__construct();
$this->fields_list['order_statuses'] = array('title' => $this->l('Order Status');
}
}
But when I go to AdminStats, a blank page shows up (see image below).
Any suggestions?
EDIT: this is not the solution in respect to the question asked.
I'd to do the exact same thing. I did it something like this, but it was AdminOrdersController but it's pretty much the same. Here it is,
// override/controllers/admin/AdminStatsController.php
<?php
public function __construct() {
parent::__construct();
$this->fields_list = array_merge($this->fields_list, [
'order_statuses' => [
'title' => $this->l('Order Status'),
'align' => 'text-center',
'callback' => 'orderStatusFunction', // yes, a callback to get a piece of UI back, a button maybe
'orderby' => false, // or true, anything you'd like
'search' => false,
'remove_onclick' => true,
]
]);
}
}
Now the callback
<?php
public function orderStatusFunction($row_number, $row_data) // row_data like date, order, customer, etc
{
/* do stuff with data and assign to your template */
$view = _PS_MODULE_DIR_ . 'path/to/view/file/view.tpl';
$html = $this->context->smarty->createTemplate($view, $this->context->smarty)->fetch();
return $html;
}
Let me know if you've any confusion, or if it didn't work out.

Filters in CGridView not filtering

Can You check why filtering is not working in CGridView? When i type for exaple 'Adam' in filter field, nothing happens. I can't find my mistake, everything looks ok but not working. I helped with that article: Yii: CGridView Filter examples
CONTROLLER
<?php
class UzytkownikController extends CController
{
public function actionIndex()
{
$Dane = new Uzytkownik('search');
$Dane -> unsetAttributes(); // clear any default values
if(isset($_GET['Uzytkownik']))
{
$Dane->attributes=$_GET['Uzytkownik'];
}
$this -> render ('index', array(
'Dane' => $Dane,
));
}
}
?>
MODEL
<?php
class Uzytkownik extends CActiveRecord
{
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function search()
{
$criteria = new CDbCriteria;
$criteria -> compare('imie', $this -> imie, true);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
)
);
}
}
?>
WIEV
<?php
$this -> widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $Dane -> search(),
'filter' => $Dane,
'columns' => array(
array(
'name' => 'imie',
'type'=>'raw',
),
array(
'name' => 'nazwisko',
'type'=>'raw',
'filter' => false,
),
array(
'name' => 'data',
'filter' => false,
),
),
)
);
?>
For future reference:
In order to make sure the $model->attributes "saves" the attributes the model needed the following addition:
public function rules() {
return array(
array('imie', 'safe', 'on'=>'search')
);
}
And $_GET should have been used instead of $_POST Because the CGridView widget uses GET when posting to the server:
class UzytkownikController extends CController
{
public function actionIndex()
{
$Dane = new Uzytkownik('search');
$Dane -> unsetAttributes(); // clear any default values
if(isset($_GET['Uzytkownik']))
{
$Dane->attributes=$_GET['Uzytkownik'];
}
$this -> render ('index', array(
'Dane' => $Dane,
));
}
}

How to use Yii trait in controller

In my controllers a lot of code, about 1000 lines
Advise how you can make more convenient, for example to make a piece of code in trait
components/ProductTrait.php
trait ProductTrait{
protected function getProductProvider(Product $model){
$dataProductProvider = new CActiveDataProvider('Product', array(
'criteria' => array(
'limit' => $pageLimit,
'condition' => 't.creatorId = :creatorId AND t.categoryId =:categoryId',
'order' => 't.created DESC',
'params' => array(
':creatorId' => $model->creatorId,
':categoryId' => $model->categoryId,
),
),
'pagination' => false,
'sort' => false,
));
return $dataProductProvider;
}
}
Controller
class DealerController extends Controller{
use ProductTrait;
public function actionView($id){
$model = $this->loadModel($id);
if ($model === null) {
throw new CHttpException(404, 'The requested page does not exist.');
}
$renderParams['productProvider'] = $this->getProductProvider($model);
}
}
You can use Trait, but you can also use behaviors.
First you declare your behavior
class ProductBehavior extends CBehavior
{
protected function getProductProvider(Product $model){
$dataProductProvider = new CActiveDataProvider('Product', array(
'criteria' => array(
'limit' => $pageLimit,
'condition' => 't.creatorId = :creatorId AND t.categoryId =:categoryId',
'order' => 't.created DESC',
'params' => array(
':creatorId' => $model->creatorId,
':categoryId' => $model->categoryId,
),
),
'pagination' => false,
'sort' => false,
));
return $dataProductProvider;
}
}
Then you use it in your controller (don't forget to attach it, I've done it in the init method)
class DealerController extends Controller{
public function init() {
//Attach the behavior to the controller
$this->attachBehavior("productprovider",new ProductBehavior);
}
public function actionView($id){
$model = $this->loadModel($id);
if ($model === null) {
throw new CHttpException(404, 'The requested page does not exist.');
}
//We use the behavior methods as if it is one of the controller methods
$renderParams['productProvider'] = $this->getProductProvider($model);
}
}
The main point of behaviors is it's working in php 5.3 whereas trait are not.
Now here's some difference between traits and behaviors:
A first difference with behaviors is that traits can not be parameterized.
In your controller you could declare the behaviors this way:
public function behaviors(){
return array(
'ProductBehavior ' => array(
'class' => 'components.behaviors.ProductBehavior',
'firstAttribute' => 'value',
'secondAttribute' => 'value',
)
);
}
Your ProductBehavior class would have 2 public attributes: firstAttribute and secondAttribute.
One thing traits lack when compared to behaviors is runtime attachement. If you want to extend a given (let's say 3rdParty) class with some special functionality, behaviors give you a chance to attach them to the class (or more specifically to instances of the class). Using traits, you had to to modify the source of the class.
A Wiki about behaviors
The Yii Guide
The CBehavior doc

Yii: Multimodelform Extension - How to create more than 1 member

I'm using Multimodelform extension to create multiple model in a single form.
This extension is working great but unfortunately i would like more than 1 member instead.
I have tried it without success at all.
My problem is I could not make more than 1 member by this extension.
Here's my code :
From Controller
public function actionCreate()
{
Yii::import('ext.multimodelform.MultiModelForm');
$model=new Endheader;
$member = new Enddetail;
$member2 = new Enddetailnq; <-- i just ant to this new member.
$validatedMembers = array();
//$validatedMembers2 = array();
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if(isset($_POST['Endheader']))
{
$model->attributes=$_POST['Endheader'];
if(isset($_POST['sav'])){
if((MultiModelForm::validate($member, $validatedMembers, $deleteItems) && MultiModelForm::validate($member2, $validatedMembers, $deleteItems)) && $model->save())
{
$masterValues = array('HEH_ID'=>$model->HEH_ID);
if(MultiModelForm::save($member,$validatedMembers,$deleteItems,$masterValues) && MultiModelForm::save($member2,$validatedMembers,$deleteItems,$masterValues))
$msg2 = CHtml::link('View Details',array('view','id'=>$model->HEH_ID));
// $this->redirect(array('view','id'=>$model->HCO_ID));
Yii::app()->user->setFlash('success','You data have been saved successfully. '.$msg2);
$this->redirect(array('update','id'=>$model->HEH_ID));
}
}
}
$this->render('create',array(
'model'=>$model,'transport'=>$transport,
'member2'=>$member2,
'member'=>$member,
// 'validatedMembers2' => $validatedMembers2,
'validatedMembers' => $validatedMembers,
));
}
From View
$memberFormConfig = array(
'elements'=>array(
'HED_RPASS'=>array(
'type'=>'text',
'maxlength'=>11,
),
'HED_PCS'=>array(
'type'=>'text',
'maxlength'=>5,
),
));
$this->widget('ext.multimodelform.MultiModelForm',array(
'id' => 'id_member', //the unique widget id
'formConfig' => $memberFormConfig, //the form configuration array
'model' => $member, //instance of the form model
'tableView' => true,
//if submitted not empty from the controller,
//the form will be rendered with validation errors
'validatedItems' => $validatedMembers,
//'sortAttribute' => 'position',
//array of member instances loaded from db
'data' => $member->findAll('HEH_ID=:HEH_ID', array(':HEH_ID'=>$model->HEH_ID)),
));
$memberFormConfig2 = array(
'elements'=>array(
'HED_ARV_PCS'=>array(
'type'=>'text',
'maxlength'=>5,
),
'HED_ARV_VOL'=>array(
'type'=>'text',
'maxlength'=>10,
),
));
$this->widget('ext.multimodelform.MultiModelForm',array(
'id' => 'id_member2', //the unique widget id
'formConfig' => $memberFormConfig2, //the form configuration array
'model' => $member2, //instance of the form model
'tableView' => true,
//if submitted not empty from the controller,
//the form will be rendered with validation errors
'validatedItems' => $validatedMembers,
//'sortAttribute' => 'position',
//array of member instances loaded from db
'data' => $member->findAll('HEH_ID=:HEH_ID', array(':HEH_ID'=>$model->HEH_ID)),
));