Dependent Entities

I’m new to CakePHP 3, though I used CakePHP 2 some years ago.

I have a table called users. A user has one bank account.

When a user is added, I need the bank account to be added (no extra information needed from what is in the add user form already), and also a transaction.

Should I do this all in the controller? Or is there some way of linking these together? I’m not sure if it’s possible to do that in the afterSave event of users.

Here’s my controller code right now for the add action. Let me know if there’s a better way of doing this. This isn’t yet showing the transaction, just the bank account.

public function add()
{
    $user = $this->Users->newEntity();
    if ($this->request->is('post')) {
        $user = $this->Users->patchEntity($user, $this->request->data);
        if ($this->Users->save($user)) {
            $bankAccounts = TableRegistry::get('BankAccounts');
            $bankAccount = $bankAccounts->newEntity();
            $bankAccount->add(1000.00);
            $bankAccount->user = $user;
            $bankAccounts->save($bankAccount);
            $this->Flash->success(__('The user has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('The user could not be saved. Please, try again.'));
        }
    }
    $this->set(compact('user'));
    $this->set('_serialize', ['user']);
}

I think it would be better to put the bank-adding-functionality inside the BankAccountsTable, so that you can just call it inside of the user save for example like this:

$this->Users->BankAccounts->addAccount( $user->id, '1000.00');

And in the BankAccountsTable add something like:

public function addAccount ($user_id, $amount)
{
    $account = $this->newEntity(['user_id' => $user_id, 'balance' => $amount]);

    return $this->save($account);
}

I simply wrote what would make sense to me, so this may not be exactly what you need, but in general it’s wise to add this kind of functionality inside the model in this way.

Naturally, you could also instead add a createUserAccount method in the UsersTable which does both things at once, but it’s usually better to have some degree of seperation to be more flexible.

2 Likes

Thanks for your reply. This makes sense. But where do I put this line?

$this->Users->BankAccounts->addAccount( $user->id, '1000.00');

You said in user save. Do you mean overriding the save method in the user table class? Or do you just mean in the controller as I had it?

after user save(), you need save user first to get $user->id

if ($this->Users->save($user)) {
$this->Users->BankAccounts->addAccount( $user->id, ‘1000.00’);
}

solution2: let cake care about associations IDs, use save associated data http://book.cakephp.org/3.0/en/orm/saving-data.html#saving-with-associations

$user = $this->Users->newEntity($data, [‘associated’ => [‘BankAccounts’]]);

2 Likes

Yes, what Diego said is exactly right, I think that answers your question :smiley: