I have a query
$p = $this->Products
->findById($id)
->select(['name'])
->contain(['Categories.Sizes' => function($q) {
return $q->select(['id', 'name']);
}
]);
which is only returning product's name and not the Size of the product's category. But if the remove the select function which accepts the field names then it delivers also the Sizes
Is there any solution for that?
According to the CakePHP 3 book, in the area "Selecting Rows From A Table", you can specify which fields you want returned by including them in a select array:
$query = $articles
->find()
->select(['id', 'name']) // <-- Notice this line
->where(['id !=' => 1])
->order(['created' => 'DESC']);
So for yours, you're limiting the fields that are returned because you're specifying that you only want the 'name' field.
Related
I have a many to many relation between sizes and toppings and and have a thrird table which contains extra fields the table is named toppings_sizes
Now I want to select only one field from toppings_sizes, at the moment I have a query which delivers all available field in all 3 tables.
$rs = $this->Toppings
->find()
->contain(['Sizes'])
->where(['category_id' => $categoryId]);
debug( json_encode($rs, JSON_PRETTY_PRINT));
I this can I need only 2 fields Sizes.name and ToppingsSizes.price
One way is by adding ->select to specify fields:
$rs = $this->Toppings
->find()
->select(['Sizes.name', 'ToppingsSizes.price'])
->contain(['Sizes'])
->where(['category_id' => $categoryId]);
$rs = $this->Toppings
->find()
->contain([
'Sizes' => function ($q) {
return $q
->select(['name']);
},
'ToppingsSizes' => function ($q) {
return $q
->select(['price']);
}
]);
->where(['category_id' => $categoryId]);
By Using this code you can get desired fields from table.
You need to pass Relationship model names into contain() method array which model entity you need in result data.
$rs = $this->Toppings
->find()
->select(['Sizes.name', 'ToppingsSizes.price'])
->contain(['Sizes','ToppingsSizes'])
->where(['Toppings.category_id' => $categoryId]);
I have a query which looks like
$entity = $this->Products
->findById($id)
->contain( [ 'Categories',
'Categories.Sizes',
'ProductsPrices.Sizes' => function($q) {
return $q->select('Sizes.name');
}
])->first();
In this case a Product belongTo a Category and in turn Category hasMany Sizes Similerly Producthas many prices depending on it's size.
For example if a Product is available in 4 different sizes, then it will have 4 prices in the ProductsPrices table.
The query is returning the desired results, but problem is it is returning all the fields from each row. For example from Categories table i only need it's name. And from Categories.Sizes only id and name
Can I limit it to only fields which I need. I tried with ->select at different levels but not working. For example 'ProductsPrices.Sizes' I see only the Sizes query not the ProductsPrices one
Read more:
http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html
$entity = $this->Products
->findById($id)
->contain( [
'Categories' => function($q){
return $q->select(['name'])
->contain([
'Sizes' => function($q) {
return $q->select(['id','name']);
}
]);
},
// -------------
])->first();
I am converting some finds from cakephp2 to cakephp3.
I need to search on a first name and surname on a tutors table that are stored on different columns. According to the docs I needed to have a LEFT join bewtween the tables. I have used an or condition with 2 fields but it works like and 'and' condition if both parameters have a value.
My issue is
q1) I cant get the data with just the first name only , and the surname is null.
q2) I need to pass both first name and surname to get just those data with that name.
Not sure how to do this in cakephp3.
eg $a5='fred'; //just want all first names like fred
$a6=null; //sometimes this will be filled
$a3='2015-05-30';
$a4='2016-06-01';
$query3 = $this->Lessons->find()
->contain(['Tutors'])
->select(['lessons.id','lessons.lesson_date','tutors.id','tutors.first_name','tutors.last_name' ])
->where(['Lessons.lesson_date >' => $a3,'Lessons.lesson_date <' => $a4,
'OR' => [['tutors.first_name like' => '%'.$a5.'%'], ['tutors.last_name like' => '%'.$a6.'%']],
]);
foreach ( $query3 as $row) {
debug($row->toArray());
}
I didnt understand the docs on this point.
http://book.cakephp.org/3.0/en/orm/query-builder.html#advanced-conditions
UPDATE- tried this and this also just gives all the data with either 'at' or 'to' but it should be any names with both 'at' and 'to' in them.
$query3 = $this->Lessons->find()
->contain(['Tutors','Subjects', 'TutoringTypes','Terms','Students'])
->select(['lessons.id','lessons.lesson_date','tutors.id','tutors.first_name','tutors.last_name',
'subjects.id','subjects.name','terms.id','terms.title'])
->where(['Lessons.lesson_date >' => $a3,'Lessons.lesson_date <' => $a4])
->orWhere(function ($exp) {
return $exp->and_([
'tutors.first_name like' => '%an%',
'tutors.last_name like' => '%to%',
]);
});
Pay attention to the generated SQL. You either see it in DebugKit or debug it by calling $query->sql(). You're building a wrong query:
You generate OR ((... AND ...)) because you're using an and_. You probably want ... OR ....
->orWhere(function ($exp) {
return $exp->and_([
'tutors.first_name like' => '%an%',
'tutors.last_name like' => '%to%',
]);
});
You probably want OR. But passing the array directly to orWhere() would work as well.
Looking to limit the returned fields of a WP Query to help with speeding up the response from the server and reducing the amount of data retrieved. For the query I'm using, it only needs up to 3 fields of data, the rest is brought in through ACF get_field_object in the loop. Other functions I'm using such as get_posts or get_terms have field options but are limited to a small number of things, such as 'slug' only or 'id => slug'.
I'm used to developing in CakePHP, which has the option to specify each and every field to return, but the project calls for wordpress for other functionality and so I'm quite limited.
TL;DR need to speed up getting posts from Wordpress
I used fields parameter in the query and run get posts on this query.
For example: In my case, I just needed to get the Post ids for multiple categories, so I created a query like this:
$the_query = new WP_Query( array(
'ignore_sticky_posts' => 1,
'posts_per_page' => -1,
'cat' => '2,6,7' ,
'fields' => 'ids',
'post_type' => 'post',
'post_status' => 'publish',
)
);
Run the get_posts on this query:
$posts = $the_query->get_posts();
$posts will get only the IDs of particular categories posts.
Or it can also be done with the standard and popular way and i.e., by running the loop of have_posts:
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
$post_id_array[] = get_the_ID();
}
}
These are the two ways to help with speeding up the response from the server and reducing the amount of data retrieved
WP_Query will return objects...so it's pretty fast. However, if you really want to limit what's returned, you can do so with the Return Fields Parameter of WP_Query.
I don't know how much it will help but below is how I'm getting a flattened array from a CPT. It's not the fastest but it could be worse. I'm using ACF to get a Custom Field but you could just get back the slug or you could get back multiple fields instead:
// Query Jobs Args
$query_args = array(
'post_type' => 'job',
'posts_per_page' => -1,
'fields' => 'ids'
);
// Get Jobs Query
$query = new WP_Query($query_args);
// Loop Persistent Vars
$job_ids = array();
// Loop Over Jobs
foreach($query->posts as $post_id) {
$job_ids[] = get_field('job_id', $post_id);
}
// Do stuff with flattened array of job ids
This is what I've done to limit the fields from WP_Query, especially, when I want to json_encode them. The $return variable contains my array of posts with only the fields listed in the $fields array.
$query = new WP_Query( array( 'post_type' => 'my_custom_type' ) );
$return = array();
$fields = array('post_title', 'ID'); //list of fields I want in $return
$posts = $query->get_posts();
foreach($posts as $post) {
$newPost = array();
foreach($fields as $field) {
$newPost[$field] = $post->$field;
}
$return[] = $newPost;
}
Interestingly enough, you can do this with the WP Rest API using the _fields parameter
https://yoursite.com/wp-json/wp/v2/posts?_fields=author,id,excerpt,title,link
More info on the API here: https://developer.wordpress.org/rest-api/
i have a little problem with cakephp
i have DB
measurers => id, title, color...
usages => id, measurer_id, value...
and i want to do something like
$this->paginate = [
'contain' => [
'MeasurerTypes',
'Usages' => function($q) {
return $q->find('latest');
}
],
'finder' => ['my' => $this->user['id']]
];
$this->set('title',__('My measurers'));
$this->set('measurers', $this->paginate($this->Measurers));
$this->set('_serialize', ['measurers']);
this is only example code, is there to find only one latest variable and no all list for that?
Check this:
http://book.cakephp.org/2.0/en/models/additional-methods-and-properties.html#model-getinsertid
Example:
$lastItem = $this->YOURMODEL->getInsertID();
Edit:
In CakePHP 3
http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html
$result = $articles->find('all')->all();
// Get the first and/or last result.
$row = $result->first();
$row = $result->last();