2

I have this tables:

customers[id, name, surname, phone, text, balance, created]

service_types[id, title, price, length, is_subscription, created]

customer_service_types[id, customer_id, service_type_id, price, created]

When I add a new customerServiceType for a customer I want to update the balance of the customer accordingly using the given price value of the customerServiceType.

So here is what I have tried:

CustomerServiceTypes/add.ctp:

<fieldset>
        <legend><?= __('Add Customer Service Type') ?></legend>
        <?php
            echo $this->Form->control('customer_id', ['options' => $customers]);
            echo $this->Form->control('service_type_id', ['options' => $serviceTypes]);
            echo $this->Form->control('price');
        ?>
    </fieldset>
    <?= $this->Form->button(__('Submit')) ?>
    <?= $this->Form->end() ?>

Model/Entity/CustomerServiceType.php:

class CustomerServiceType extends Entity
{
//On create a new CustomerServiceType then update the selected customer's balance
    public function addCustomerServiceType($data = array()){
        $this->create;
        $this->save($data);

        //update customer balance
        $customer = $this->Customers->get($data['customerid']);

        $this->Customer->updateAll(
            array('Customer.balance' => 'Customer.balance + ' . $data['price']),
            array('Customer.id' => $data['customerid'])
        );

        return true;
    }
}

So in CustomerServiceTypesController.php I changed the add() like this:

public function add($customerid = null)
    {
        $customerServiceType = $this->CustomerServiceTypes->newEntity();
        if ($this->request->is('post')) {
            $customerServiceType = $this->CustomerServiceTypes->patchEntity($customerServiceType, $this->request->getData());
            if ($this->CustomerServiceType->addCustomerServiceType($this->request->data)) {
                $this->Flash->success(__('The customer service type has been saved.'));

                return $this->redirect(['action' => 'index']);
            }
            $this->Flash->error(__('The customer service type could not be saved. Please, try again.'));
        }
        $customers = $this->CustomerServiceTypes->Customers->find('list', ['limit' => 200]);
        $serviceTypes = $this->CustomerServiceTypes->ServiceTypes->find('list', ['limit' => 200]);
        $this->set(compact('customerServiceType', 'customers', 'serviceTypes'));
    }

But I get this error:

Call to a member function addCustomerServiceType() on boolean

And this notice:

Undefined property: CustomerServiceTypesController::$CustomerServiceType

Community
  • 1
  • 1
netdev
  • 496
  • 1
  • 5
  • 22
  • The first error is most likely caused because you are attempting to call a table that has not yet been loaded into the controller via `$this->loadModel()` and the notice is due to the fact that you cannot call entities like `$this->CustomerServiceType`, you would instead call `$customerServiceType->addCustomerServiceType()`. However as Mary has pointed out, there are much better approaches to this problem. – Derek Fulginiti Oct 06 '18 at 00:12

1 Answers1

1

Since you want something to happen after saving data, I think you are better off using the Model.afterSave event: https://book.cakephp.org/3.0/en/orm/table-objects.html#aftersave

In your Controller

$this->CustomerServiceTypes->save($customerServiceType)

In your Table Object CustomerServiceTypesTable.php

namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\Event\Event;
use Cake\ORM\TableRegistry;
use ArrayObject;
use Cake\Datasource\EntityInterface;

class CustomerServiceTypesTable extends Table
{
    public function afterSave(Event $event, EntityInterface $entity, ArrayObject $options)
    {
        // only execute if the entity is new
        // if you want this to happen on edits too, remove this clause

        if ($entity->isNew()) {
            // get instance of the Customers table
            $customers = TableRegistry::getTableLocator()->get('Customers');

            $customer = $customers->get($entity->customerid);
            // do more stuff here
        }
    }
}
Marijan
  • 1,825
  • 1
  • 13
  • 18
  • Argument 2 passed to App\Model\Table\CustomerServiceTypesTable::beforeMarshal() must be an instance of App\Model\Table\EntityInterface, instance of ArrayObject given, called in C:\xampp\htdocs\bodytec_new_dev\vendor\cakephp\cakephp\src\Event\EventManager.php on line 353 – netdev Oct 05 '18 at 14:01
  • Sorry, my fault – should be `afterSave` instead of `beforeMarshal`. Updated the answer. – Marijan Oct 05 '18 at 14:04
  • hmmm now I receive this error: Argument 2 passed to App\Model\Table\CustomerServiceTypesTable::afterSave() must be an instance of App\Model\Table\EntityInterface, instance of App\Model\Entity\CustomerServiceType given, called in C:\xampp\htdocs\bodytec_new_dev\vendor\cakephp\cakephp\src\Event\EventManager.php on line 353 – netdev Oct 08 '18 at 06:34
  • I ended up doing all the update action in the `add` function, but I would like to see your example working – netdev Oct 08 '18 at 08:19
  • Please add the classes that the `afterSave` function receives instances from by adding `use ArrayObject;` and `use Cake\Datasource\EntityInterface;` to your table object. – Marijan Oct 08 '18 at 10:41