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.
Related
I have following table structure store category
When I wiil start to create my form, I have add first dropdown for lvl 1 category by default, now i want to another dropdown for sub-category which based on category, then I want 3rd lvl sub-category which are based on 2nd lvl selected sub-cateogry list.
I have only store 4 levels, Any Idea about how can build this structure on Symfony2.3?
Any Possibility to make above functionality manage in symfony2.3 or need to change in SQL table structure?
If you're using an entity to access your table, this extensions seems to be made for what you're trying to achieve:
https://github.com/Yavin/symfony-form-tree
You might have to modify your table structure slightly, though.
If you're sure you'll never have more than 4 levels, you could have 4 nested foreach cycles and produce an array similar to:
$categories = array("Electronics" =>
array("Television" =>
array("LED" =>
array(7 => "X SERIES",
8 => "TRILUMINOS")
)
)
);
and then pass it into your form like so:
$form = $this->createFormBuilder()
->add('category', 'choice', array(
'choices'=> $choices
))
I would solve it like this:
don't save redundant data or optimize, so remove 'level' and let's solve it for any depth. Limitations are often more complicated and bad code than solving the whole problem. If you don't want more levels, than just check the level when inserting a child, but when designing the model/entity layer, think about 0,1,n relations.
save the parent id as nullable integer foreign key, so a root category is defined by having parent id NULL and a leaf is defined by not being parent to any other category. This 1:n relation means parent id is the owning side, and a pseudo field 'children' (ArrayCollection) is the reversed side, that's doctrine.
The idea:
The form and request data is just the 'current category'. There is only one path from the current selected category to its root, so we don't need more data.
The validation of the form is simply a check: if category is a leaf, than the form is valid.
The model-view transformer takes a category and transforms it into its children. NULL at first is transformed into the root categories (something like CategoryRepository::findRoots()), and any valid category is transformed into its children (e.g. Category::getChildren()). You have to declare your transformer as a service since it depends on the database.
So use 'entity' as form type so we don't need to write our own view transformation. The entity form type is actually a choice form type and takes an array of items, but is now taking a single category and showing its children.
And please don't use any validation logic in the controller. An action like http://symfony.com/doc/current/book/forms.html#handling-form-submissions works for you. Let the isValid method invoke your validators via a constraint like #Leaf in your data object (like this example: http://symfony.com/doc/current/book/forms.html#embedding-a-single-object).
And don't forget
to hide items with status = 0
remember maybe there is a parent with all children having status = 0, so check that there are no children with status != 0 and not just if it's empty
There are so many exception when dealing with forms. I really recommend to write tests (but also for other parts ;) )!
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 the following relation scheme:
1 portfolio -> Many Users in each Portfolio -> Each User owns many Products
Entities: Portfolio, User, Products
What I would like to display is in one page:
1. The name of the portfolio
2. The title of a user
3. CGridView of all products owned by that user
It seems, if CGridView were not being used, you would populate your model appropriately and then use a foreach loop to loop through each user relation and then loop through the products related to that user. And create a render_partial view for the products and for the user.
However, I am at a complete loss as how to accomplish this with CGridView.
Any advice is much, much appreciated!
You want to render the User's Products in a CGridView?
To render data with a CGridView you need to pass in a CDataProvider to populate the view. So the question is: how do you make a CDataProvider for the HAS_MANY relation?
Surprisingly, the CActiveDataProvider does not support relations in this way. What you need to do get the relation and pass that data into a CArrayDataProvider. Assuming the $user->productsrelation,you can do it like this:
$dataProvider = new CArrayDataProvider($user->products, array());
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
'id', // your columns here
),
));
It's not ideal, but it works. Credit goes here for this specific technique: http://learnyii.blogspot.com/2010/12/yii-how-to-display-related-hasmany-grid.html
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.
I have two models in cakePHP, one is Parts and the other is Orders.
Parts is a simple model with an id column plusaction multiple fields such as customer, part number, description etc. Each part has its own unique id.
Orders is another simple model with a field called *part_id* which represents an id from the Parts model.
In an action, in the Orders controller I wll need to pull all the orders for that particualr view, find information about that order from the Parts database and put it together in an array ready to be passed to the view.
For example that tables might look like:
ORDERS
Part_id id
2 5
1 7
PARTS
customer partnumber description id
Google XHA-V1 widget_1 1
Yahoo YVS-XN widget_5 2
Since I will have 50-100 orders in any one view, I need an efficient way to reference each order's *part_id* in the Parts database and combine this into one array. Its the searching of the Parts database multiple times that I'm unsure how to achieve effectively.
Note: I guess the solution could be cake or pure PHP.
If you have correctly defined the relation in your Order Model, you should be able to retreive all the corresponding Parts
$this->Orders->find('all');
cakephp will do it in two queries:
- a SELECT for all the Orders
- a SELECT for all the Products where product.id in ( list_of_Orders_ids )
and then it will contruct an array in a proper format
If you need an special query, you could also "manually" set the joins for the query, but you'll need to set the recursive to -1:
$this->Orders->find('all',array('recursive'=>-1,
'fields'=>array('Order.*','Part.*'),
'joins'=>array(array('table' => 'parts',
'alias' => 'Part',
'type' => 'INNER', //or left
'conditions' => array('Part.id = Order.part_id')))))
Good Luck!
You can get an array of (all) Orders using the $this->Order->find('all', array('recursive' => 2)); in your controller. Each order also contains the related Parts information.
Imo customer information should be part of the Order, not of Part. Also you might want Orders to consist of multiple Parts.