echo $form->input(
'country_id',
array(
'type' => 'select',
'label' => __('Country *', true),
'empty' => 'Select' ,
'order' => array('countries.name ASC')
)
);
Country list are not showing up in Ascending Order. Please anybody help me to find out an error or good way to show country list in ascending order.
You need to add order to your find query:
$countries = $this->Country->find('list', array(
'fields' => array('Country.id', 'Country.name'),
'order' => array('Country.name' => 'ASC')
))
For cakephp 3.* you can use this code;
$countries = $this->Country
->find('list',
[
'keyField' => 'Country.id',
'valueField' => 'Country.name',
'order' => array('Country.name' => 'ASC')
])
->toArray();
Related
I don't know if I'm explaining this correctly, but I have a loop that's pulling all products assigned to a specific category (in this case, Current Season - this is for a performing arts organisation).
But each product is actually assigned to multiple categories for various reasons, and in this case I want all products assigned to 'current-season', but NOT also assigned to the category 'series'.
I've tried the following, but it has done nothing to change my query display.
It's still showing everything assigned to 'current-season'.
$args_right = array(
'post_type' => 'product',
'posts_per_page' => 999,
//'product_cat' => 'current-season',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'series',
'operator' => 'NOT IN'
),
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'current-season',
'operator' => 'IN'
)
),
'meta_key' => 'date',
'orderby' => 'meta_value_num',
'order' => 'ASC'
);
I'm sure I'm just missing something very obvious. I bang my head against the wall, and then wind up going "D'UH"!!
Thanks in advance!
i beleive your problem with the 'meta_key' => 'date' if you want to order the posts by date you can use the following query.
$args_right = array(
'post_type' => 'product',
'posts_per_page' => 12,
'orderby' => 'date',
'order' => 'ASC',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'terms' => array('current-season'),
'field' => 'slug',
'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'.
), array(
'taxonomy' => 'product_cat',
'terms' => array('series'),
'field' => 'slug',
'operator' => 'NOT IN' // Possible values are 'IN', 'NOT IN', 'AND'.
)
),
);
$loop = new WP_Query($args_right);
if ($loop->have_posts()) {
while ($loop->have_posts()) :
$loop->the_post();
wc_get_template_part('content', 'product');
endwhile;
} else {
echo __('No products found');
}
wp_reset_postdata();
Reference
I tested this query locally and it's displaying all product with current-season category and if one product in this category assigned to another category or sub-category series it's excluded
In a WP_Query, i need some arrays to be dynamic, when a checkbox-group is checked.
The code so far is:
$args = array(
'post_type' => 'hold',
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'hold_serie',
'value' => 'serie3',
'compare' => 'LIKE'
),
array(
'relation' => 'OR',
'options' => array()
),
),
);
$days = array('man', 'tir', 'ons');
foreach ($days as $value_day) {
$args['meta_query']['options'] = array(
'key' => 'hold_day',
'value' => $value_day,
'compare' => 'LIKE'
);
}
I have a checkbox group, which will make the same array as the $days-array().
What I'm hoping to achieve is, that the array with 'key' => 'hold_day' will be repeated three times, and the WP_Query will look at all the posts, that have either "man", "tir" OR "ons".
At this point, the WP_query only takes the post, with the last value in the array, in this case "ons".
If I delete "ons", so the array only have "man" and "tir", it only finds the posts, where "hold_day" = "tir".
What am I doing wrong?
You dose not need to use second part of the code.
You can use an array as the value of meta key, but in that case you need to use "IN" in compare field.
Your code should be
$args = array(
'post_type' => 'hold',
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'hold_serie',
'value' => 'serie3',
'compare' => 'LIKE'
),
array(
'relation' => 'OR',
'key' => 'hold_day',
'value' => array('man', 'tir', 'ons'),
'compare' => 'IN'
),
),
);
Try the above code and let me know the result.
Thanks
How can I group by fields and Order by DESC in cakephp?
$this->set('messages', $this->Message->find('all',array('conditions' => array('Message.receiver_id'=>$this->Session->read('Auth.User.id')),'group' => array('Message.user_id'),'order' => array('max(Message.created) ASC'))));
Records are fetched in cakePhp depend on a model is
$records = $this->Model->find('all', array(
'conditions' => array(conditons),
'fields' => array(fieldlist),
'group' => array('Model.column'),
'order' => array('Model.column', 'Model.column2 DESC')
));
From your code, you can write as
$data = $this->Message->find('all', array(
'conditions' => array( 'Message.receiver_id'=>$this->Session->read('Auth.User.id')),
'group' => array('Message.user_id'),
'order' => array('max(Message.created) ASC')
));
$this->set('messages', $data);
$records = $this->Model->find('all', array(
'conditions' => array(conditons),
'recursive' => -1,
'fields' => array(fieldlist),
'group' => array('Model.column'),
'order' => array('Model.column', 'Model.column2 DESC')
));
If you want to order by latest Message inserted then instead of sort by created use sort by id like this Model.id DESC'
I want to convert following mysql statement into cakephp query syntax.Please help me. Here is my query.SELECT * FROM post WHERE (user_id == $id OR awarded_to = $id ) AND id = $id
Here is my cakephp query. is it wrong.
$this->Post->find('all',
array('conditions' => array('OR' =>
array('Post.user_id' => $id),
array('Post.awarded_to' => $id)
),
'AND' =>
array('Post.id' => $id)
))
This one's on the house, but next time read the docs.
$this->Post->find('all', array(
'conditions' => array(
'OR' => array(
array('Post.user_id' => $id),
array('Post.awarded_to' => $id)
),
'Post.id' => $id
)
));
The 2 OR arrays need to be inside an array themself, and there's no need for AND.
Just add Post.id = $id below the OR condition without you give "and" it's automatic read as and condition...
$this->Post->find('all', array(
'conditions' => array(
'OR' => array('Post.user_id' => $id),
array('Post.awarded_to' => $id)
),
'Post.id' => $id
));
You are very close with your query, just you need little modification like to remove 'AND' in conditions array after 'OR' as:
$this->Post->find('all', array(
'conditions' => array(
'OR' => array(
array('Post.user_id' => $id),
array('Post.awarded_to' => $id)
),
'Post.id' => $id
)
));
Or
$this->Post->find('all', array(
'conditions' => array(
'Post.id' => $id
)
));
The second option will be the best for you if you are passing tables primary key 'id' in AND conditions.
I have the following tables: binders, docs, users, docs_users. Doc belongsTo Binder, Doc hasAndBelongsToMany User.
I want to get binders and their associated docs for the user that is currently logged in (the associated user_id in the docs_users table).
I have tried Containable and find('all') with joins, conditions, etc. but I can't figure out how to remove the Docs that are from Users who are not associated in the docs_users table.
This code does NOT work:
$binders = $this->Binder->find(
'all',
array(
'joins' => array(
array(
'table' => 'binders_users',
'alias' => 'BindersUser',
'type' => 'inner',
'foreignKey' => false,
'conditions'=> array(
'BindersUser.binder_id = Binder.id',
'BindersUser.user_id = ' . $this->Auth->user('id')
)
),
array(
'table' => 'docs',
'alias' => 'Doc',
'type' => 'left',
'foreignKey' => false,
'conditions'=> array(
'Doc.binder_id = Binder.id',
)
),
array(
'table' => 'docs_users',
'alias' => 'DocsUser',
'type' => 'left',
'foreignKey' => false,
'conditions'=> array(
'DocsUser.doc_id = Doc.id',
'DocsUser.user_id = ' . $this->Auth->user('id')
)
)
),
'recursive'=>0
)
);
$this->set('binders', $binders);
And neither does this:
$this->Binder->recursive = 2;
$this->Binder->Behaviors->attach('Containable');
$this->Binder->contain(array(
'Branch',
'Doc' => array(
'User' => array(
'DocsUser' => array(
'conditions' => array('id = "17"')
)
)
)
));
$binders = $this->Binder->find('all');
Any help from you seasoned pros would be great! Thanks!
Alternative/Simplified Solutions?
This works if I just want to get binders to which users have permissions. Short and sweet. However, it will still send ALL associated docs through, which is NOT the behavior I want. It needs to only pass on the docs to which the user has permissions (as described previously).
$binders = $this->Binder->find(
'all',
array(
'joins' => array(
array(
'table' => 'binders_users',
'alias' => 'BindersUser',
'type' => 'inner',
'foreignKey' => false,
'conditions'=> array(
'BindersUser.binder_id = Binder.id',
'BindersUser.user_id = ' . $this->Auth->user('id')
)
)
)
)
);
These are a few of the options available for doing deep finds on data in CakePHP:
https://github.com/Terr/linkable/wiki
http://mark-story.com/posts/view/using-bindmodel-to-get-to-deep-relations
http://bakery.cakephp.org/articles/view/quick-tip-doing-ad-hoc-joins-in-model-find
Here's the final solution I came up with based on all of the great feedback I got. I think this is an elegant solution that can be reused in any scenario where deep associations are required.
In the binder_controller I unbound the Doc model, and bound it back using the finderQuery to select only the Docs that a user has permission to see. Then in joined the binders_users table selecting only the binders that users have permissions to.
Thank you everyone for all your help!
$this->Binder->unbindModel(array('hasMany' => array('Doc')));
$this->Binder->bindModel(
array('hasMany' => array(
'Doc' => array(
'className' => 'Doc',
'foreignKey' => 'binder_id',
'dependent' => false,
'finderQuery' => 'SELECT Doc.* FROM docs AS Doc INNER JOIN docs_users AS DocsUser ON DocsUser.doc_id = Doc.id AND DocsUser.user_id = ' . $this->Auth->user('id')
)
)
)
);
$binders = $this->Binder->find(
'all',
array(
'joins' => array(
array(
'table' => 'binders_users',
'alias' => 'BindersUser',
'type' => 'inner',
'foreignKey' => false,
'conditions'=> array(
'BindersUser.binder_id = Binder.id',
'BindersUser.user_id = ' . $this->Auth->user('id')
)
)
)
)
);
More on binding/unbinding models
On this line, you need to tell Cake which Model's id you are talking about:
'conditions' => array('id = "17"')
e.g. DocsUser.id
...and you don't use recursive with containable. Get rid of it.
Have you tried coming in from a user perspective?
$this->Binder->Doc->User->Behaviors->attach('Containable');
$this->Binder->Doc->User->contain(array('Doc'=>'Binder'));
$user = $this->Binder->Doc->User->find('all',array('conditions'=>'User.id'=>$user_id));
The 'DocsUser' association should be detected anyway.
From a Binders perspective maybe
In your Binders MODEL add ( please check table, key and model names in case I made a typo )
function getBindersByUserSql($user_id)
{
$dbo = $this->getDataSource();
$subQuery = $dbo->buildStatement(
array(
'fields' => array('DISTINCT(Doc.binder_id)'),
'table' => "docs_users",
'joins' => array(
array('table' => 'users',
'alias' => 'User',
'type' => 'INNER',
'conditions' => array('DocsUser.user_id = User.id')
),
array('table' => 'docs',
'alias' => 'Doc',
'type' => 'INNER',
'conditions' => array('Doc.id = DocsUser.doc_id')
)
),
'alias'=>"DocsUser",
'conditions' => array("User.id"=>$user_id),
'order' => null,
'group' => "Doc.binder_id"
),
$this
);
return $dbo->expression($subQuery);
}
Then in your binders CONTROLLER try
$this->Binder->Behaviors->attach('Containable');
$this->Binder->contain(array('Doc'));
$conditions = array();
$conditions = $this->Binder->getBindersByUserSql($this->Auth->user('id'));
$binders = $this->Binder->find('all',array('conditions'=>$conditions)));
Any good?