In my CJuiAutoComplete, I currently have the code below.
$this->widget('zii.widgets.jui.CJuiAutoComplete', array(
'name'=>'ABCForm[postcode]',
'id'=>'ABCForm_postcode',
..........
));
Is there a way to get the model name so I don't have to hard code it in my jquery?
In case I change the name in the future, I don't have to go though all my JS code to change the name and id.
I think you should use CHtml::activeId and CHtml::activeName as it fits Yii much better. So your code would look like:
$this->widget('zii.widgets.jui.CJuiAutoComplete', [
'name'=>CHtml::activeName($model, 'postcode'),
'id'=>CHtml::activeId($model, 'postcode'),
//..........
]);
EDIT: I have never used CJuiAutoComplete before but wouldn't it make more sense to use its model and attribute widget parameters (http://www.yiiframework.com/doc/api/1.1/CJuiInputWidget#model-detail):
$this->widget('zii.widgets.jui.CJuiAutoComplete', [
'model'=>$model,
'attribute'=>'postcode',
//..........
]);
If you have passed a model using the variable $model to your view, you can try:
get_class($model)
Related
I made a custom field in prestashop.
I would like to know if there is some way to make this field only required on the frontend and not for administrators.
this is my code in Customer class
array('type' => self::TYPE_STRING, 'required' => true, 'size' => 64),
Thanks in advance
Can't think of a quick way to make this possible exactly as you want it, so here are two suggestions:
1 - Remove the 'required' => true from the definition and create some kind of custom validation like if (Tools::getValue('type ') == "") { return false; } in an override of the front office AuthController (Warning: code is completely untested and should definitely be improved, also according to your particular PS version).
2 - Use frontend validation by giving the frontend form field the required attribute (you should do this even if oyu use 1)
How to pass $id to search scenario? Maybe in model look like this, so I can call like in controller like:
$model = new job('search',$id);
I think that you are trying to do a search. Search is one thing, a "scenario" is something else.
Scenarios are used in validation rules in order to be able to validate the same model in multiple ways depending from where you're inserting/adding OR searching data.
There's also a scenario called 'search' that is used by the model's search() method, but I tell you why:
There are a couple of ways to search for something in your database using Yii, I will mention two:
1) By using ClassName::model()->findCommandHere
And there are a couple of them:
ClassName::model()->findByPk($id);
ClassName::model()->findAll("id=$id");
ClassName::model()->findByAttributes(array('id'=>$id));
And so on, more here: http://www.yiiframework.com/doc/guide/1.1/en/database.ar#reading-record
2) By using the model's search() method
This way of finding data is mostly used for easily creating search pages and in combination with data grids.
If you generate CRUD code with the GII code generation tool it will generate all the parts for you, but I will explain each part how it works.
This code is from the blog demo found in Yii files:
In controller it defines a $model using Post class and 'search' as scenario.
$model=new Post('search');
if(isset($_GET['Post'])) // <- checks if there are search params in the URL
$model->attributes=$_GET['Post']; // <- assigns all search params masively to the model (later you'll see why)
$this->render('admin',array(
'model'=>$model,
));
The 'search' scenario here tells Yii what validation rules to use when assigning search parameters directly from $_GET (URL).
You can see that the params are assigned massively to reduce code written but $model->attributes=$_GET['Post'] it is the same as doing:
$model->title=$_GET['Post']['title'];
$model->status=$_GET['Post']['status'];
In the Post model you can find the validation rules for the search scenario. Tells Yii that it is safe to assign title and status fields in order to later use them in the search.
public function rules()
{
return array(
// ... //
array('title, status', 'safe', 'on'=>'search'),
);
}
Then also in the Post model you can see the search() method that will actually be used to get the data:
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('title',$this->title,true);
$criteria->compare('status',$this->status);
return new CActiveDataProvider('Post', array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'status, update_time DESC',
),
));
}
The search method creates a "criteria" and applies the desired way of filtering using the values you have previously assigned to this model. See the $this->title it comes from the $model->attributes=$_GET['Post'] you used in the controller.
The criteria can be used directly on the model, such as Post::model()->findAll($criteria), but in this case the search() method uses something different, a "data provider".
The data provider is a good thing because it provides you a lot of tools in one place, it returns you the data, but also the pagination, and the sorting, so you don't have to manually define more code for that purposes (CPagination, CSort).
Finally, in the view admin.php in this case it will display the results using a grid view:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array(
'name'=>'title',
'type'=>'raw',
'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'
),
array(
'name'=>'status',
'value'=>'Lookup::item("PostStatus",$data->status)',
'filter'=>Lookup::items('PostStatus'),
),
),
));
Now you can see that in the configuration of the grid it passes $model->search() method as the dataProvider that the grid should use.
Now the grid can access the rest of the dataProvider elements such as sort, pagination and display them on the page.
If you did not want to use the CGridView because it's a very basic table and you want to create your own html markup, you can also retrieve the dataProvider and its components one by one and place them in your HTML code and display data as you want:
$dataProvider=$model->search(); // get the dataprovider from search method
$models=$dataProvider->getData(); // actually get the data (rows) and assign them to a $models variable that you can put in a foreach loop
// show pagination somewhere
$this->widget('CLinkPager', array(
'pages' => $dataProvider->pagination,
));
// create sort links
echo $dataProvider->sort->link('title', 'Title');
So I hope it solves some of your doubts on how to use Yii for displaying/searching data.
I suggest you read the official manual: http://www.yiiframework.com/doc/guide/1.1/en/index
I also suggest to look at the API and so search there all the Yii components to see what methods and params they have: http://www.yiiframework.com/doc/api/
Also exploring the framework codebase manually is quite a good way to learn. If you don't know how CActiveDataProvider works, then find the CActiveDataProvider class file in the code and you'll see all the methods and properties that it uses, so do this for everything you don't understand how it works.
Also for beginners I recommend using a good IDE that auto-completes code and allows you to Ctrl+Click a class name and it will locate the original file where it was defined. I use NetBeans for PHP and after creating a project I add Yii framework files to the project's include paths that way NetBeans knows how to find the framework files for auto-complete and for ctrl+click.
Yes you can define scenario with parameter but that is included within the class constructor of the model
$model = new Job('search'); // creating a model with scenario search
If you wish to include more parameters, then you need to use createComponent -remember, all is a component
$model = Yii::createComponent(array('class'=>'Job','scenario'=>'search'));
I think this will simply do the job without needing any scenario
$model = new job;
$model->search($id);
But If I have failed to understand your problem then you can also try this
$model = new job('search');
$model->search($id);
Think of scenarios as a special variable that you can use in the model.
$userModel = new User("register");
$userModel->setId = 10;
which is the same
$userModel = new User();
$userModel->scenario = 10
$userModel->setId = 10;
And in your model
class Manufacturer extends CActiveRecord
{
// :
if ($this->scenario == 'register') ...
// :
}
I have a model InboxMessageHelper with relations like
'message', 'sender' and 'receiver' and I am using the following criteria to query data:
$model = new CActiveDataProvider('IndividualMessageHelper', array(
'criteria'=>array(
'condition'=>'receiver_id = '.Yii::app()->user->id,
'order'=>'message.created_at DESC',
'with'=>array('message', 'sender', 'receiver'),
'together'=>true,
),
));
I want to get all data (i.e. including the relations data) inside the controller and form a JSON, but the problem is that i cannot access related fields data. I can see that the data is available when I use
CVarDumper::dump()
when I try to encode $model->data then only data from current table gets encoded. How should I go about it?
I don't think CActiveDataProvider can be used in this way. You need to be working with the model. So you'll need something like this in your controller.
$models = IndividualMessageHelper::model()->findAll('receiver_id = '.Yii::app()->user->id);
foreach($models as $model){
$json[] = $model->getAttributes; //This won't get any model properties you've declared
yourself, only database columns
}
//Now get the related records and add them to the array.
array_push($json, $model->getRelated('message')->getAttributes());
array_push($json, $model->getRelated('sender')->getAttributes());
array_push($json, $model->getRelated('receiver')->getAttributes());
echo json_encode($json);
I'm using giix to extend model (and crud) behavior. In this I would like to handle columns of type timestamp (that already exist in my model) specifically, rather like autoincrement fields are handled. (Ignored and not shown, that is.) However, there is no property $column->isTimestamp. I would like to add this somewhere, but I'm rather at loss what the best place for this would be. Do I put it in giix somewhere, or do I have to extend the column-baseclass?
Edit: I want to ignore them from every view, for every table. Since this is a lot of work, and it's something I always want, I'd like to automate it. Adapting the generators seems to make most sense, but I'm not sure what the best way to do it would be.
Here is the process:
Extend your database schema, if you are on MySQL it is CMysqlSchema.
Extend CMysqlColumnSchema and add a "isTimestamp" attribute.
In your CMysqlSchema sub-class extend createColumn and test for a timestamp, you'll see that Yii makes simple string comparisons here to set it's own flags. Set "isTimestamp" in your CMysqlColumnSchema here.
Tell Yii to use your schema driver like this in your components section in the config:
'db' => array(
'connectionString' => 'mysql:host=localhost;dbname=database',
'username' => '',
'password' => '',
'driverMap' => array('mysql' => 'CustomMysqlSchema'),
),
You will need to query the column schema, I've not used giix but find where it is generating the views, it should be looping through either the model attributes or the underlying table schema.
If it is looping through the schema:
//you can also ask Yii for the table schema with Yii::app()->db->schema->getTable[$tableName];
if ('timestamp' === $tableSchema->columns[$columnName]->dbType)
continue; //skip this loop iteration
If it loops over the attributes:
$dbType = Yii::app()->db->schema->getTable[$model->tableName]->columns[$modelAttribute]->dbType;
if ('timestamp' === $dbType)
continue; //skip this loop iteration
I used Yii's Gii's CRUD generator for a model that has a relation defined with another model, expecting that it would create some sort of dropdown or other way to select an instance of the related entity, but rather it just showed a regular textbox.
Is this the normal behavior of Gii or did I do something wrong?
This are the models and their relations:
Model Event: relation 'Venue' => array( self::BELONGS_TO, 'Venue', 'venue' )
Model Venue: relation 'Events' => array( self::HAS_MANY, 'Event', 'venue' )
I was expecting the Event CRUD to show some way of picking an instance of Venues.
That is just normal behaviour for Gii, when generating forms(for both CRUD and only forms), it makes all input fields textfields. So the default gii CRUD and form generator doesn't take relations into account while generating code.
We have to manually make changes to the view file, namely _form.php for the model in question, for you that is Event.
So for your requirement, you can make the following changes to that file :
/* As you have 'venue' field as the foreign key in the Event model */
<div class="row">
<?php echo $form->labelEx($model, 'venue'); ?>
<?php echo $form->dropDownList($model,'venue', CHtml::listData(Venue::model()->findAll(),
'id', //this is the attribute name(of Venue model- could be the id of the venue) for list option values
'name' // this is the attribute name(of Venue model- could be the name of the venue) for list option texts
)
); ?>
<?php echo $form->error($model,'venue'); ?>
</div>
To make further changes/customizations read more about CActiveForm.
Hope this helps.
Use Giix it works perfactly for what you are looking for.. no manual modifications required.