How to add associated data while adding User simultaneously CakePHP 3.x?

632 Views Asked by At

I would like to be able to add a membership record at the same time I add a user. I can't seem to get it to work. I want to be able to select the membership level and have that data get sent to the controller where I can add the data, unless there is a way to just select the membership level and it will automatically create a membership record for the user that gets added.

The membership level contains the information for that level of membership and the membership record contains some information from the membership level and is associated to a user.

The add form I believe is where the problem lies, but just in case here are the important snippets of code. I tried to keep it as simple as possible.

Users Table Initialize Function:

public function initialize(array $config)
{
    parent::initialize($config);

    $this->table('users');
    $this->displayField('id');
    $this->primaryKey('id');
    $this->addBehavior('Timestamp');

    $this->hasOne('Memberships', [
        'foreignKey' => 'user_id',
        'joinType' => 'INNER'
    ]);
}

Memberships Table Initialize Function:

public function initialize(array $config)
{
    $this->table('memberships');
    $this->displayField('id');
    $this->primaryKey('id');
    $this->addBehavior('Timestamp');
    $this->belongsTo('Users', [
        'foreignKey' => 'user_id',
        'joinType' => 'INNER'
    ]);
    $this->hasOne('MembershipLevels', [
        'foreignKey' => 'membership_level_id',
        'joinType' => 'INNER'
    ]);
}

Users Controller Add Method:

public function add()
{
    $user = $this->Users->newEntity($this->request->data(), [
        'associated' => [
            'Memberships' => ['associated' => ['MembershipLevels']]
        ]
    ]);

    if ($this->request->is('post')) {
        $user = $this->Users->patchEntity($user, $this->request->data(), [
            'associated' => [
                'Memberships' => ['associated' => ['MembershipLevels']]
            ]
        ]);
        if ($$this->Users->save($user)) {
            $this->Flash->success(__('You have been added.'));
        } else {
            $this->Flash->error(__('You could not be added. Please, try again.'));
        }
    }

    $membershipLevels = $this->Users->Memberships->MembershipLevels->find('list', ['limit' => 200]);
    $this->set(compact('user', 'membershipLevels'));
    $this->set('_serialize', ['user', 'membershipLevels']);
}

Add Users Form:

<div class="form">
    <h1>Join Now</h1>
    <?= $this->Form->create($user); ?>
    <fieldset>
        <legend><?= __('User Info') ?></legend>
        <?= $this->Form->input('full_name', ['required' => false]); ?>
        <?= $this->Form->input('username', ['required' => false]); ?>
        <?= $this->Form->input('email', ['required' => false]); ?>
        <?= $this->Form->input('password', ['required' => false]); ?>
        <?= $this->Form->input('password_confirmation', ['type' => 'password', 'required' => false]); ?>
        <?php
            if ($current_user['role'] === 1 && isset($logged_in)) {
                echo $this->Form->input('role', ['type' => 'select', 'options' => ['1' => 'Admin', '2' => 'Editor', '3' => 'Author', '4' => 'Reader'], 'default' => '4']);
            }
        ?>
    </fieldset>

    <fieldset>
        <legend><?= __('Membership Info') ?></legend>
        <?= $this->Form->label('Membership Level'); ?>
        <?= $this->Form->input('memberships.membership_levels._id', ['options' => $membershipLevels, 'required' => false]); ?>
    </fieldset>

    <?= $this->Form->button(__('Sign Up'));?>
    <?= $this->Form->end();?>
</div>

I changed the code a bit thanks to the comments and answers. The membership levels now show up in the form and I pick a membership level when saving the user, but the membership doesn't get saved as well, just the user. Any further suggestions?

2

There are 2 best solutions below

0
On

How about start reading the migration guide, or doing the blog tutorial for CakePHP3? Your trial and error approach is time consuming and frustrating. I can't recommend this enough: Always read documentation before shooting in the darkness. There has a lot changed in CakePHP3. This includes the way the dot notation is used. Reading saving associations might help as well.

You don't use any longer the model prefix on the first level.

Model.field 

is now just

field

For nested associations it's now

associated_data.field
associated_data.second_level_data.field

Notice that this is inflected and singular or plural depending on the kind of association.

0
On

I have updated my code to get the closest I can to getting all the automagic to work.

Key points: 1.) In controller I got the membership levels variable to pass to the view by adding this line. (notice the calling of the users table then memberships and then membershiplevels).

$membershipLevels = $this->Users->Memberships->MembershipLevels->find('list', ['limit' => 200]);

2.) In the view I added:

<?= $this->Form->input('memberships.membership_levels._id', ['options' => $membershipLevels, 'required' => false]); ?>

This is not a complete answer however because I still have to grab the membership level in the controller with a query and then manually save the data from that level to the memberships table.

I can at least populate the membership level input in the form dynamically and submit it.

I had looked over the bookmarker tutorial that I had previously done since it uses associations, but with that tutorial they are able to add the bookmarks_tags record automatically when you add a bookmark and I am not sure if it is due to the functions in the table files or not.