I'm using CakePHP 3.6
I have two models Users
and WalletTransactions
.
WalletTransactions
is associated with Users
with user_id
and have a column price
.
I am using following code to show the list of users
UsersController.php
public function index()
{
$users = $this->Users->find();
$this->set(compact('users'));
}
users/index.ctp
<?php foreach($users as $user): ?>
<?= $user->name ?>
<?php endforeach; ?>
Now, I want to show the sum of price
from WalletTransactions
inside the list of users in the template.
For that, I have written a function to get the sum of price
in WalletTransactionsTable.php
public function walletBalance($user_id)
{
$total_balance = 0;
$walletTransactions = $this->find()
->where([
'user_id' => $user_id
]);
foreach ($walletTransactions as $transaction) {
$total_balance += $transaction->price;
}
return $total_balance;
}
and set a property function in User.php
entity class
protected function _balance()
{
$user_id = $this->_properties['id'];
$WalletTransactions = TableRegistry::get('WalletTransactions');
$transaction = $WalletTransactions->walletBalance($user_id);
return $transaction;
}
in the template in the users
loop when using
<?= $user->balance ?>
it prints nothing.
How can I show values from other models inside a template?
Accessors must start with _get
, ie _getBalance
. However, ideally entities should be stupid data containers, making them issue queries isn't the best idea, not to mention that it's rather inefficient to issue a query everytime a property is being accessed.
I'd suggest to use for example a custom finder. Also there's no need to retrieve all transactions and calculate on PHP level, this can be easily done on SQL level instead:
// UsersTable
public function findWithWalletBalance(\Cake\ORM\Query $query, array $options)
{
return $query
->leftJoinWith($this->WalletTransactions->getName())
->select([
'balance' => $query->func()->sum($this->WalletTransactions->aliasField('price'))
])
->group(array_map([$this, 'aliasField'], (array)$this->getPrimaryKey()))
->enableAutoFields(true);
}
// UsersController
public function index()
{
$users = $this->Users->find('withWalletBalance');
$this->set(compact('users'));
}
See also