Calling a Function in Model A from Controller A


#1

Good day.

I am new to CakePHP. I am using 3.2.6. Kindly explain with sample code how I can call a function in the Model from the Controller for the Model or direct me to a tutorial that will teach this.

Thanks.


#2

AnyTable.php

function myFunction() {
}

in AnyController.php
(since we are talking same table “Any” here) you can just

$this->any->myFunction();

If you are in any other controller, you need to load the proper model before:

AnyOtherController.php

$anyTable = $this->loadModel(‘Any’);
$anyTable->myFunction();


#3

find below functions in model

<?php namespace App\Model\Table; use App\Model\Entity\Payment; use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; use Cake\ORM\TableRegistry; /** * Payments Model * * @property \Cake\ORM\Association\BelongsTo $Members * @property \Cake\ORM\Association\BelongsTo $PaymentTypes */ class PaymentsTable extends Table { /** * Initialize method * * @param array $config The configuration for the Table. * @return void */ public function initialize(array $config) { parent::initialize($config); $this->table('payments'); $this->displayField('id'); $this->primaryKey('id'); $this->belongsTo('Members', [ 'foreignKey' => 'member_id', 'joinType' => 'INNER' ]); $this->belongsTo('PaymentTypes', [ 'foreignKey' => 'payment_type_id', 'joinType' => 'INNER' ]); } /** * Default validation rules. * * @param \Cake\Validation\Validator $validator Validator instance. * @return \Cake\Validation\Validator */ public function validationDefault(Validator $validator) { $validator ->integer('id') ->allowEmpty('id', 'create'); $validator ->allowEmpty('amount'); return $validator; } /** * Returns a rules checker object that will be used for validating * application integrity. * * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. * @return \Cake\ORM\RulesChecker */ public function buildRules(RulesChecker $rules) { $rules->add($rules->existsIn(['member_id'], 'Members')); $rules->add($rules->existsIn(['payment_type_id'], 'PaymentTypes')); return $rules; } public function findTotalPaid(Query $query) { $payments=TableRegistry::get('Payments'); $query = $payments->find() ->select(['member_id','amount_paid' => $query->func()->sum('amount')]) ->where(function ($q) { $q->notIn('amount', ['SICK','New','Excuse']) ->isNotNull('amount');}) ->group(['member_id']); //->execute(); return $query; } /*select m.id,sum(CAST(p.amount AS UNSIGNED)) as amount_paid from payments p join members m on p.member_id=m.id where p.amount not in ('SICK','New','Excuse') and p.amount is not null and p.member_id=16 group by m.id;*/ public function findTotalOwed(Query $query) { $payments=TableRegistry::get('Payments'); $query = $payments->find() ->contain(['PaymentTypes','Members']) ->select(['member_id','amount_due' => $query->func()->sum('PaymentTypes.amount_due')]) ->where(function ($q) { $q->isNull('Payments.amount');}) ->group(['member_id']); //->execute(); return $query; } /*select m.id,sum( t.amount_due) as amount_due from payments p join payment_types t on t.id=p.payment_type_id join members m on m.id=p.member_id where p.amount is null group by m.id;*/ } //The commented sql is what I will like to achieve. find below the controller action calling it <?php namespace App\Controller; use App\Controller\AppController; /** * Payments Controller * * @property \App\Model\Table\PaymentsTable $Payments */ class PaymentsController extends AppController { /** * Index method * * @return \Cake\Network\Response|null */ public function index() { $this->paginate = [ 'contain' => ['Members', 'PaymentTypes'] ]; $userId=$this->Auth->user('id'); $role=$this->Auth->user('role'); $branchId=$this->Auth->user('branch_id'); if ($role==='member') { $payments =$this->paginate = [ 'contain' => ['Members', 'PaymentTypes'], 'conditions' => [ 'Members.user_id' => $userId ] ]; } else if ($role==='branch_admin') { $payments =$this->paginate= [ 'contain' => ['Members', 'PaymentTypes'], 'conditions'=> [ 'Members.branch_id'=>$branchId ], ]; } else { $payments = $this->paginate($this->Payments); } //$role=$this->Auth->user('role'); //$this->set('role',$role); //$this->set(compact('members')); //$this->set('_serialize', ['members']); $amounts=$this->Payments->find('TotalPaid'); $amounts_owed=$this->Payments->find('TotalOwed'); //$this->set(compact('payments')); $this->set('payments', $this->paginate($this->Payments)); $this->set('_serialize', ['payments']); $this->set('amounts', $this->paginate($amounts)); $this->set('_serialize', ['amounts']); $this->set('amounts_owed', $this->paginate($amounts_owed)); $this->set('_serialize', ['amounts_owed']); } find below the view displaying

<?= __('Paid Summary') ?>

<?php foreach ($amounts as $amount): ?> <?php endforeach; ?>
<?= $this->Paginator->sort('Member Name') ?> <?= $this->Paginator->sort('Amount Paid') ?>
<?= $amount->has('member') ? $this->Html->link($amount->member->surname.', '.$amount->member->first_name.' '.$amount->member->middle_name, ['controller' => 'Members', 'action' => 'view', $amount->member->id]) : '' ?> <?= h($amount->amount_paid) ?>

<?= __('Owed Summary') ?>

<?php foreach ($amounts_owed as $owed): ?> <?php endforeach; ?>
<?= $this->Paginator->sort('Member Name') ?> <?= $this->Paginator->sort('Amount Owed') ?>
<?= $owed->has('member') ? $this->Html->link($owed->member->surname.', '.$owed->member->first_name.' '.$owed->member->middle_name, ['controller' => 'Members', 'action' => 'view', $owed->member->id]) : '' ?> <?= h($owed->amount_due) ?>

<?= __('Payment Details') ?>

<?php foreach ($payments as $payment): ?> <?php endforeach; ?>
<?= $this->Paginator->sort('Name') ?> <?= $this->Paginator->sort('amount') ?> <?= $this->Paginator->sort('payment_type') ?> <?= __('Actions') ?>
<?= $payment->has('member') ? $this->Html->link($payment->member->surname.', '.$payment->member->first_name.' '.$payment->member->middle_name, ['controller' => 'Members', 'action' => 'view', $payment->member->id]) : '' ?> <?= ($payment->amount) ? h($payment->amount): 'Payment due' ?> <?= $payment->has('payment_type') ? $this->Html->link($payment->payment_type->type_name, ['controller' => 'PaymentTypes', 'action' => 'view', $payment->payment_type->id]) : '' ?> <?= $this->Html->link(__('View'), ['action' => 'view', $payment->id]) ?> <?= $this->Html->link(__('Edit'), ['action' => 'edit', $payment->id]) ?> <?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $payment->id], ['confirm' => __('Are you sure you want to delete # {0}?', $payment->id)]) ?>
    <?= $this->Paginator->prev('< ' . __('previous')) ?> <?= $this->Paginator->numbers() ?> <?= $this->Paginator->next(__('next') . ' >') ?>

<?= $this->Paginator->counter() ?>

find below error message

Warning (4096): Argument 1 passed to Cake\Database\Expression\QueryExpression::_addConditions() must be of the type array, null given, called in C:\xampp\htdocs\umuakolomvillage\vendor\cakephp\cakephp\src\Database\Expression\QueryExpression.php on line 137 and defined [CORE\src\Database\Expression\QueryExpression.php, line 604]
Warning (2): Invalid argument supplied for foreach() [CORE\src\Database\Expression\QueryExpression.php, line 610]
Warning (4096): Argument 1 passed to Cake\Database\Expression\QueryExpression::_addConditions() must be of the type array, null given, called in C:\xampp\htdocs\umuakolomvillage\vendor\cakephp\cakephp\src\Database\Expression\QueryExpression.php on line 137 and defined [CORE\src\Database\Expression\QueryExpression.php, line 604]
Warning (2): Invalid argument supplied for foreach() [CORE\src\Database\Expression\QueryExpression.php, line 610]

I hope someone can direct me now.


#4

see view again. It did not come out right.

<?= __('Paid Summary') ?>

<?php foreach ($amounts as $amount): ?> <?php endforeach; ?>
<?= $this->Paginator->sort('Member Name') ?> <?= $this->Paginator->sort('Amount Paid') ?>
<?= $amount->has('member') ? $this->Html->link($amount->member->surname.', '.$amount->member->first_name.' '.$amount->member->middle_name, ['controller' => 'Members', 'action' => 'view', $amount->member->id]) : '' ?> <?= h($amount->amount_paid) ?>

<?= __('Owed Summary') ?>

<?php foreach ($amounts_owed as $owed): ?> <?php endforeach; ?>
<?= $this->Paginator->sort('Member Name') ?> <?= $this->Paginator->sort('Amount Owed') ?>
<?= $owed->has('member') ? $this->Html->link($owed->member->surname.', '.$owed->member->first_name.' '.$owed->member->middle_name, ['controller' => 'Members', 'action' => 'view', $owed->member->id]) : '' ?> <?= h($owed->amount_due) ?>

<?= __('Payment Details') ?>

<?php foreach ($payments as $payment): ?> <?php endforeach; ?>
<?= $this->Paginator->sort('Name') ?> <?= $this->Paginator->sort('amount') ?> <?= $this->Paginator->sort('payment_type') ?> <?= __('Actions') ?>
<?= $payment->has('member') ? $this->Html->link($payment->member->surname.', '.$payment->member->first_name.' '.$payment->member->middle_name, ['controller' => 'Members', 'action' => 'view', $payment->member->id]) : '' ?> <?= ($payment->amount) ? h($payment->amount): 'Payment due' ?> <?= $payment->has('payment_type') ? $this->Html->link($payment->payment_type->type_name, ['controller' => 'PaymentTypes', 'action' => 'view', $payment->payment_type->id]) : '' ?> <?= $this->Html->link(__('View'), ['action' => 'view', $payment->id]) ?> <?= $this->Html->link(__('Edit'), ['action' => 'edit', $payment->id]) ?> <?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $payment->id], ['confirm' => __('Are you sure you want to delete # {0}?', $payment->id)]) ?>
    <?= $this->Paginator->prev('< ' . __('previous')) ?> <?= $this->Paginator->numbers() ?> <?= $this->Paginator->next(__('next') . ' >') ?>

<?= $this->Paginator->counter() ?>


#5

Thanks. I just pasted some more info. I will be glad if you can assist.


#6

Man, your problems are completely out of the subject you propose. Even your first question (which I believe I could help) has no link at all with the problem you are showing now!

Put is simple, I thought I was able to help, but I’m not.

Just be give you some alternative:

The errors seems look like http://qaoverflow.com/question/cakephp-3-x-hasmany-through-association-find/

And the query, you can always use

$conn = ConnectionManager::get(‘default’);
$query = “select fields from table where…”;
$results = $conn->execute($query)->fetchAll(‘assoc’);


#7

Thanks for responding.

The issue is with the calls below

$amounts=$this->Payments->find(‘TotalPaid’);
$amounts_owed=$this->Payments->find(‘TotalOwed’);

I don’t know how to call the function findTotalPaid(Query $query) and findTotalOwed(Query $query). I don’t know how to pass the Query $query to the function or get ride of it completely.

I will appreciate if you can help.


#8

I believe you had already solved your problem, I’m rigth? Sorry, I stay out of forum for too long.

$amounts=$this->Payments->find(‘TotalPaid’);
$amounts_owed=$this->Payments->find(‘TotalOwed’);

Should be

$amounts = $this->Payments->TotalPaid()
$amounts_owed = $this->Payments->TotalOwed()

Assuming this->Payments is your Payment model. If not, my first answer aplies:

$Payments = $this->loadModel(‘Payments’);
$amounts = $Payments->TotalPaid();
$amounts_owed = $Payments->TotalOwed()