Reputation: 138
CakePHP Version: 4.0.1
Introduction
This problem follows on from another problem I had here where a not ideal solution was to redirect back to itself. Unfortunately the controller I was testing didn't have any associated columns so this new problem was not identified.
I referenced this in the cookbook.
Hopefully the below code will allow the problem to be reproduced.
Contacts Table
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('contacts');
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Accounts', [
'foreignKey' => 'account_id'
]);
}
// Custom Finder
public function findSuperuserAllContacts(Query $query, array $options): object
{
$query
->where(['Contacts.status' => $options['status']])
->andWhere([
'Users.client_id' => $options['client_id'],
'Users.status' => 1
]);
return $query;
}
Contacts Controller
public $paginate = [
'sortWhitelist' => [
'Contacts.first_name',
'Contacts.last_name',
'Accounts.account_name',
'Users.first_name',
'Users.last_name',
'Contacts.primary_tel',
'Contacts.mobile',
'Contacts.email'
]
];
public function index() {
$query = (object) $this->Contacts->find('superuserAllContacts', [
'contain' => ['Users', 'Accounts'],
'status' => 1,
'client_id' => 1001
]);
$page = '';
$sort = 'Accounts.account_name';
$direction = 'asc';
$config = $this->paginate = [
'page' => $page,
'sort' => $sort,
'direction' => $direction,
'limit' => 10
];
$contacts = $this->Paginator->paginate($query, $config);
$this->set(compact('contacts'));
}
What Happens
The page displays a type error in the framework.
C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\View\Helper\PaginatorHelper.php
strtolower() expects parameter 1 to be a string, bool given
public function sortDir(?string $model = null, array $options = []): string
{
$dir = null;
if (empty($options)) {
$options = $this->params($model);
}
if (isset($options['direction'])) {
debug($options['direction']); // THIS IS FALSE NOT asc or desc?
$dir = strtolower($options['direction']);
}
if ($dir === 'desc') {
return 'desc';
}
return 'asc';
}
Stacktrace from error.log
2020-06-01 10:33:20 Error: [TypeError] strtolower() expects parameter 1 to be string, bool given in C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\View\Helper\PaginatorHelper.php on line 264
Stack Trace:
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\View\Helper\PaginatorHelper.php:264
- C:\xampp\htdocs\crm\templates\Contacts\index.php:5
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\View\View.php:1164
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\View\View.php:1125
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\View\View.php:750
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Controller\Controller.php:691
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Controller\Controller.php:533
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Controller\ControllerFactory.php:79
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\BaseApplication.php:229
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:77
- C:\xampp\htdocs\crm\vendor\cakephp\authentication\src\Middleware\AuthenticationMiddleware.php:122
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:73
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\I18n\Middleware\LocaleSelectorMiddleware.php:70
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:73
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:77
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Middleware\CsrfProtectionMiddleware.php:132
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:73
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:58
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Routing\Middleware\RoutingMiddleware.php:162
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:73
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Routing\Middleware\AssetMiddleware.php:68
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:73
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Error\Middleware\ErrorHandlerMiddleware.php:118
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:73
- C:\xampp\htdocs\crm\vendor\cakephp\debug_kit\src\Middleware\DebugKitMiddleware.php:60
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:73
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Runner.php:58
- C:\xampp\htdocs\crm\vendor\cakephp\cakephp\src\Http\Server.php:90
- C:\xampp\htdocs\crm\webroot\index.php:40
Request URL: /contacts
Referer URL: https://localhost/crm/welcome
Question
Why is a type error displayed instead of loading the index template with the sort on the account_name?
Thanks Z.
EDIT
I've just tried a fresh install with
composer self-update && composer create-project --prefer-dist cakephp/app:4.* crm
and baked users, contacts and accounts.
The new version is 4.0.8 and I added the code I have above in the new project but unfortunatley got exactly the same type error.
If the sort is on the same table, ie: Contacts.last_name the last name has the sort on it but if I change it to the associated table Accounts.account_name the type error is displayed.
Upvotes: 0
Views: 720
Reputation: 138
The sort field whitelist must be passed in the config when using the paginator directly.
$config = $this->paginate = [
'sortWhitelist' => [
'Contacts.first_name',
'Contacts.last_name',
'Accounts.account_name',
'Users.first_name',
'Users.last_name',
'Contacts.primary_tel',
'Contacts.mobile',
'Contacts.email'
],
'page' => $page,
'sort' => $sort,
'direction' => $direction,
'limit' => 10
];
$contacts = $this->Paginator->paginate($query, $config);
$this->set(compact('contacts'));
The sort is now displayed on the account_name.
Upvotes: 1