i am using cakephp 1.3 to generate a form i am creating a select list using hasOne and belongsTo relation
my models: image, category
category hasMany image
image belongsTo Category
category table has two columns id and category_name
i am doing
$this->set('categories',
$this->Image->Category->find(
'list',
array( 'order' => 'category_name ASC' )
)
); //to generate the select list
so far so good, there is only one problem left, the select list generated shows the id of the category instead of the category_name as the option text, i know this is not cakePHP's fault but i need to know the solution
any help please.
P.S if i am unclear about the question please let me know
You need to define the displayField property in your category model, so that CakePHP can properly determine which field to display as a label. This code in your category model will fix it for you:
var $displayField = 'category_name';
Alternatively, rename the category_name field to 'name' or 'title' (I would do this, it's obvious that a 'name' field in a category table is going to be the name of the category).
When in doubt, read the manual:
3.7.3.1.4 find('list')
When calling find('list') the fields passed are used to determine what should be used as the array key, value and optionally what to group the results by. By default the primary key for the model is used for the key, and the display field (which can be configured using the model attribute displayField) is used for the value.
Related
i have a db structure like this:
Addresses
id primary key auto_increment
name
surname
email
categories
id primary key auto_increment
name
address_category
id primary key auto_increment
addr_id
cate_id
on the gridview, into categories filter column i have inserted a select2 extension with multiple set to true and on the addressesSearch model i have added this code:
->andFilterWhere(['address_category.cate_id'=> $category]
it function but not like i want, yii make a IN query like cate_id IN (4,5,6) instead i need a query that find the address that are tagged with all the categories selected.
i hope to have explained well my problem
thanks
select2 multiple returns comma separated values. split it first, maybe check for integer values
->andFilterWhere(['IN', 'address_category.cate_id', array_map('intval', explode(',', $category))]);
i have find a solution, i don't know if is the best way but works.
$query->select(['addresses.*, (select count(*) as categories from address_category where cate_id IN ('.implode(",",$category).') and addr_id=addresses.id) as categories']);
$query->having(['categories' => count($category)]);
I believe the OP's working solution may use a calculated field in the query, and that possibly ties-in with a solution that eventually worked for me, so this might just be an alternative approach. Note: I tried everything to parse/manipulate the attribute, but nothing worked.
So create a field in your model using a (getter), that simply replicates the attribute, so in a model which has a getter for a Country name in a country table with country_id as the attribute, something like:
public function getCountrylink()
{
return $this->country_id;
}
This (countryLink) is then used as the attribute in the view/index and as a simple replacement in the modelSearch filter:
$query->andFilterWhere(['country_id' => $this->countryLink]);
N.B. You'll also need to add the calc field as a public variable and include as a safe entry in the rules in the modelSearch, as per standard instructions for establishing a calculated field (search for "Filter & Sort by calculated/related fields in GridView Yii 2.0").
Some difficulties with "condition"
I have a table Tags with fields : id, name, count
I have table PagesTags with fields : id, page_id and tag_id
I have table Pages with several fields : id, name, shownmenu, onilne.
In my TagsController, I have a simple code to extract and display the Tags
function tagsList(){
//$this->loadModel('PageTag');
return $this->Tag->find('all',
array('order'=>'name ASC','conditions'=>array('Tag.count >= 0')));
}
The problem is, I do not want to display the tags associated to a page which is Offline.
Then in my aboce I should use somethink like $this->loadModel('PageTag'); to get the Id of the associated page and a second $this->loadModel('Page');
to get the page status 'online' (true/false)
Can we do it at once?
How can I do it simply?
How can I look in two table at one?
You need to use model relationships to link your models together. Read the manual about it or see my answer on this topic here:
CakePHP 1.3 - Unknown column in where clause
In your case, PagesTags hasOne Page and hasMany Tags. You will write these relationships into the model. Also you will write into Tags model that it hasOne PagesTags, which will in turn retrieve the associated Page.
After you have done all of that, you don't need to call loadModel, you just query Tag and it will implicitly join the associated PagesTags and Page records, so you can just put this into your conditions:
'Page.status !=' => 'Offline'
I think the relation of the table is HABTM so you have to look this component for searching http://bakery.cakephp.org/articles/Kumazatheef/2008/10/22/habtm-searching
I have managed to join 2 of my tables clients and risk_codes to each other where clients.risk_code_id is a foreign key for risk_codes.id.
In my edit view for Clients I ouput a form using the HTML Helper. E.g. to add an input to edit clients.name I would use echo $this->Form->input('name');
Given that risk_codes is a separate table/model how would I output a select dropdown with the options being risk_codes.name and the values being risk_codes.id?
The tables are linked like so:
Client belongsTo RiskCode
RiskCode hasMany Client
In your RiskCode model make sure that displayField is either set to null or name (the latter is one of the defaults):
public $displayField = 'name'; // or null;
In the controller set a list of risk codes for the view:
$this->set('riskCodes', $this->Client->RiskCode->find('list'));
And in the view simply reference the appropriate foreign key field name:
echo $this->Form->input('risk_code_id');
CakePHP will automatically create an appropriate select list, using the models id and displayField field values from the list set as riskCodes.
ps. Many questions like this are answered in the Cookbook, and can also be figured out by using CakePHP to bake the controllers and views.
I have 3 DB tables tbl_categories, tbl_items, tbl_items_categories like this:
tbl_categories fields: id (category id - primary key), name (category's name)
tbl_items fields: id (item id - primary key), name (item name)
tbl_items_categories fields: id (primary key), item_id (id field value from tbl_items), category_id (id field value from tbl_category)
Please note that one item can be in multiple categories (tbl_items_categories is being used for this purpose)
I have created 3 models (in YII) - categories, items, itemMultiCategories for these tables.
Can anyone please let me know how to create relations in YII for following purpose:
If I have an item id, I should be able to get all its category names (good to have category ids)
If I have category id, I should get all item names in that category (good to have item ids as well)
Thanks in advance.
You are not creating relations in Yii, you are doing it in the database.
Take a look at this answer.
After you created the relations, go into the gii (http://yourhost.com/?r=gii), and create all the models again. Don't forget to check the checkbox for relation creation.
What you have here is a many to many relationship bridged by an associative table (tbl_items_categories). This should be easily handled by Yii's many to many relational active record.
http://www.yiiframework.com/doc/guide/1.1/en/database.arr
For instance, to have a relationship in your items model that gets you all categories, you could do something like this:
public function relations()
{
return array(
'categories' => array(self::MANY_MANY, 'categories','tbl_items_categories(item_id, category_id)'),
);
}
The foreign key, tbl_items_categories(item_id, category_id), is just the name of your associative table with the table fields that will match your linked tables, in parentheses. Your fields should be listed in order, such that the field that will link to the primary key of the current model is listed first. My understanding is if you want to get items by category, the foreign key in the relationship in your category model will look like this: tbl_items_categories(category_id, item_id).
A note on your associative table:
You might consider removing the "id" field, since the combination of item_id and category_id is probably unique. Also, because the table only needs to be referenced in these relationship declarations, you probably don't need to set up a separate model for it.
This is may be a stupid question, but I am kind of new in yii, and had problem with this simple view..
I have a data like this:
task_type
id name
1 agenda
2 task
3 notes
agenda:
id user due_at created_at task_type_id description
And I would like to display them separately, as agenda and tasks, and notes in different html views like these:
tasks
due_at description
agenda
due_at created_at description
notes
description
I don't want any fancy user filtering as these tables only shows one week max on front page, for current week, and there will be separate page dedicated for this sort of tasks. This is only at front page as quick tasks. I have been trying on CGridView but can't filter it without letting html filter to show up. I need to filter at due_at, and ranged due_at for agenda, and then by user.
Can someone help me to create this?
Thank you in advance
There are a few things that you need to take care of, if you want to use a CGridView for this, and they are the following:
Use a DataProvider : CGridView requires a data provider as its input. A data provider is:
Data providers are components that can feed data for widgets such as data grid, data list. Besides providing data, they also support pagination and sorting.
For your current requirement you can use a CActiveDataProvider. So your gridview code needs this:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
));
Pass this data provider from the controller action to the view.
Use criteria: You can pass all those conditions in the criteria property of CActiveDataProvider. This criteria is an object of CDbCriteria. So your $dataProvider can be something like:
$dataProvider=new CActiveDataProvider('Agenda',array(
'criteria'=>array(
'condition'=>'task_type_id=1 AND due_at BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 1 WEEK)',
'select'=>'due_at, description' // columns you want to select
)
));
The condition property is the:
query condition. This refers to the WHERE clause in an SQL statement. For example, age>31 AND team=1.
The select property is:
the columns being selected. This refers to the SELECT clause in an SQL statement. The property can be either a string (column names separated by commas) or an array of column names. Defaults to '*', meaning all columns.
Don't specify the filter: To not show a filter, just don't pass any filter property value to the grid:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
//'filter'=>$model // don't pass any filter
));
Use columns: Use the columns property of CGridView to show only the specific columns you want to show:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'agenda-grid',
'dataProvider'=>$dataProvider,
'columns'=>array(
'due_at',
'description'
)
));
Also pass an id which will become the id of this grid's div, incase you don't want the auto-generated id.
That's it, you should get what you want by following the above steps.