How to paginate related articles in cakephp 4 [duplicate] - cakephp

Products belongsToMany Categories and Categories hasMany Products, inside my Product view I'm showing a list of all it's categories but I want to paginate or limit these results.
My current code on ProductsController is:
$product = $this->Products
->findBySlug($slug_prod)
->contain(['Metas', 'Attachments', 'Categories'])
->first();
$this->set(compact('product'));
I know I need to set $this->paginate() to paginate something but I can't get it working to paginate the categories inside the product. I hope you guys can understand me.
UPDATE: Currently I have this going on:
$product = $this->Products->findBySlug($slug_prod)->contain([
'Metas',
'Attachments',
'Categories' => [
'sort' => ['Categories.title' => 'ASC'],
'queryBuilder' => function ($q) {
return $q->order(['Categories.title' => 'ASC'])->limit(6);
}
]
])->first();
The limit works but I don't know how to paginate yet

The paginator doesn't support paginating associations, you'll have to read the associated records manually in a separate query, and paginate that one, something along the lines of this:
$product = $this->Products
->findBySlug($slug_prod)
->contain(['Metas', 'Attachments'])
->first();
$categoriesQuery = $this->Products->Categories
->find()
->innerJoinWith('Products', function (\Cake\ORM\Query $query) use ($product) {
return $query->where([
'Products.id' => $product->id,
]);
})
->group('Categories.id');
$paginationOptions = [
'limit' => 6,
'order' => [
'Categories.title' => 'ASC'
]
];
$categories = $this->paginate($categoriesQuery, $paginationOptions);
$this->set(compact('product', 'categories'));
Then in your view template you can display your $product and separately paginate $categories as usual.
See also
Cookbook > Controllers > Components > Pagination
Cookbook > Views > Helper> Paginator
Cookbook > Database Access & ORM > Query Builder > Filtering by Associated Data

Related

Retrieve data from associated database in cakephp

I have an Entries table with users_id as a foreign key to the Users table.
I have set the belongsTo association in the EntriesTable like so:
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
After that I wrote this in the EntriesController:
$entries = TableRegistry::get('Entries');
$query = $entries->findByTitle($title)
->contain(['Users']);
$entry = $query->first();
$this->set('entry', $entry);
In the VIEW template of the Entries I have to show the username field of the user that wrote the Entry.
I am aware that in previous versions of CakePHP 1, I could just write $entry['User']['username'] to retrieve the username of the User who wrote the Entry. Now that I am using CakePHP 3.6, it doesn't seem to work. How do I perform the same task in CakePHP 3?
You can write like below
In controller
public function view($title)
{
$entry = $this->Entries->findByTitle($title)->contain(['Users']);
$entry = $entry->first();
$this->set('entry', $entry);
}
OR
public function view($title)
{
$query = $this->Entries->find('all', [
'where' => ['Entries.title' => $title],
'contain' => ['Users']
]);
$entry = $query->first();
$this->set('entry', $entry);
}
In view
<?= $entry->user->username ?>
So in cakephp you were loading Model of its controller, which is done as default,you can directly create an find() method in same controller,if you want to find from other table/ model you can do is-
a. $this->Entries->otherTableName()->find()->all();
b. $tableName= $this->loadModel('tableName');
$tableName->find();

cakephp 3 paginator doesn't work with a specific query [duplicate]

Products belongsToMany Categories and Categories hasMany Products, inside my Product view I'm showing a list of all it's categories but I want to paginate or limit these results.
My current code on ProductsController is:
$product = $this->Products
->findBySlug($slug_prod)
->contain(['Metas', 'Attachments', 'Categories'])
->first();
$this->set(compact('product'));
I know I need to set $this->paginate() to paginate something but I can't get it working to paginate the categories inside the product. I hope you guys can understand me.
UPDATE: Currently I have this going on:
$product = $this->Products->findBySlug($slug_prod)->contain([
'Metas',
'Attachments',
'Categories' => [
'sort' => ['Categories.title' => 'ASC'],
'queryBuilder' => function ($q) {
return $q->order(['Categories.title' => 'ASC'])->limit(6);
}
]
])->first();
The limit works but I don't know how to paginate yet
The paginator doesn't support paginating associations, you'll have to read the associated records manually in a separate query, and paginate that one, something along the lines of this:
$product = $this->Products
->findBySlug($slug_prod)
->contain(['Metas', 'Attachments'])
->first();
$categoriesQuery = $this->Products->Categories
->find()
->innerJoinWith('Products', function (\Cake\ORM\Query $query) use ($product) {
return $query->where([
'Products.id' => $product->id,
]);
})
->group('Categories.id');
$paginationOptions = [
'limit' => 6,
'order' => [
'Categories.title' => 'ASC'
]
];
$categories = $this->paginate($categoriesQuery, $paginationOptions);
$this->set(compact('product', 'categories'));
Then in your view template you can display your $product and separately paginate $categories as usual.
See also
Cookbook > Controllers > Components > Pagination
Cookbook > Views > Helper> Paginator
Cookbook > Database Access & ORM > Query Builder > Filtering by Associated Data

CakePHP 3 Pagination

I am trying to make a pagination for my threads.
The code works, but I want to limit the posts per page.
How can I achieve this?
And how to draw the pagination to my threads view?
My code:
$this->paginate = [
'contain' => 'posts'
];
$query = $this->Threads->find('all')->where(['id' => $id]);
$this->set('test', $this->paginate($query));
Thanks.
Have you tried passing a limit option to $this->paginate?
$this->paginate = [
'contain' => ['Posts'],
'limit' => 10 // limits the rows per page
];
https://book.cakephp.org/3.0/en/controllers/components/pagination.html

CakePHP 3 Sort by associated model with HasOne relationship

Order HasOne Suborder
Suborder BelongsTo Order
I need to sort Orders by a field in Suborders, but sorting by virtual fields appears to have been removed in Cake 3.x
In OrdersTable.php, I have
$this->hasOne('Suborder', [
'className' => 'Suborders',
'foreignKey' => 'order_id',
'strategy' => 'select',
'conditions' => function ($exp, $query) {
return $exp->add(['Suborder.id' => $query
->connection()
->newQuery()
->select(['SSO.id'])
->from(['SSO' => 'suborders'])
->where([
'Suborder.order_id = SSO.order_id',
'SSO.suborder_type_id in' => [1, 2, 3]
])
->order(['SSO.id' => 'DESC'])
->limit(1)]);
}
]);
In OrdersController.php, I have
$this->paginate = [
'limit' => 20,
'order' => ['id' => 'desc'],
'sortWhitelist' => [
'id',
'title',
'client_order',
'substatus',
'Workflows.order_status_id',
'Clients.name',
'ProductTypes.type',
'Suborder.due_date',
'Suborder.created',
],
];
$orders = $this->paginate($collection);
In index.ctp, I have
$this->Paginator->sort('Suborder.created', 'Order Placed'),
$this->Paginator->sort('Suborder.due_date'),
and the error I'm getting is Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Suborder.created' in 'order clause'. How do I get Cake to include the Suborder in the initial query for sorting and pagination?
Edit:
$collection = $this->Orders->find()
->contain([
'Clients',
'CurrentAssignment.Users',
'Workflows.OrderStatuses.Category',
'Workflows.OrderStatuses.Departments' => function ($q) use ($uID) {
return $this->Departments->find()->matching('Users', function ($q) use ($uID) {
return $q->where(['Users.id' => $uID]);
});
},
'ClientProducts.ProductTypes',
'Reviews' => function ($q) {
return $q->where(['review_type_id is not' => 6]);
},
'Reviews.ReviewTypes',
'PublicNotes',
'ActiveReview',
'Suborder',
'Suborder.SuborderTypes',
'Suborders.SuborderTypes',
]);
and $collection is modified with 150 lines of wheres, orWheres, and joins based on a number of conditions.
You have configured the assocaition to use the select strategy, which will use a separate query to retrieve the data (currently wrongly documented), hence you cannot reference it in the main query used for pagination.
So you have to use the default join strategy instead if you want to sort on it.
See also
Cookbook > Database Access & ORM > Associations - Linking Tables Together > HasOne Associations

cakephp 3 show latest value with contain

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();

Resources