We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Confused with defining relationships between more 'complicated' models (ie User -> UserRole -> Role)

I am having some issues with defining relationships between models and having them save correctly. I can't get anything more complicated than a ...->HasOne(...) relationship to work.

Consider this for example:

A user is logged in and wants to create a new role. We give the role a title and hit 'submit'. Upon submittion, I need to inser this new role into the data base and automatically add the current user to the role.

I am not sure what relationships I need to define in my models (User/UserRole/Role) and how I would go about actually inserting items into the data base etc.

I tried to define a many to many relationship from the User to UserRole to Role, something like this:

//user

$this->hasManyToMany( "Id", "UserRole", "UserID", "RoleID", "Role", "Id" );

I did the opposite in Role model

//Role

$this->hasManyToMany( "Id", "UserRole", "RoleID", "UserID", "User", "Id" );

And finally, in the UserRole model, I created 2 'belongs to' relationships like so:

//UserRole

$this->belongsTo("UserID", "User", "Id");

$this->belongsTo("RoleID", "Role", "Id");

But thats all just starting to get confusing and I am not sure what I am doing wrong or right. For example, I tried the following to create a new role and add the active user to it immediately:

$newRole = new Role();

$newRole->name = "Test Role";

$newRole->UserRole = array();

$newRole->UserRole[0] = new UserRole();

$newRole->UserRole[0]->RoleID = $newRole->Id;

$newRole->UserRole[0]->UserID = $activeUserID;

$newRole->create();

And that just isn't working. I am just a little lost and was wondering if someone can point me in the right direction!



33.8k

I think you don't need the UserRole->belongsTo functions from what I've read, only in User and Role (I didn't give a try yet).



2.6k
edited Sep '14

Tried it but that doesn't work. When I 'create()' the role, the UserRole object isn't inserted into the table, even though I pushed it into the Role's UserRole array. Also, the documentation has a lot of auto-magic stuff on foreign keys that I just can't seem to get working. I mean sure, it is easy for me the manually insert a UserRole object every time I want to add a user to a role, but it would be so much better if I could just retreive that user from the database, add a UserRole to their UserRole array and then 'save()' that user and have the changes apply to the database.

edit:

Even better, it would be awesome if I could eventually do something like $role->Users and have the framework automatically return me an array of users by checking the UserRole table to see which users are a part of the role. I don't know if Phalcon has that sort of functionality 'built in' to its database/module classes, but I think that it would because it would be pretty pointless to define all these relationships otherwise.



6.9k
Accepted
answer

First,

All the documentation for this is at: https://docs.phalcon.io/en/latest/reference/models.html#defining-relationships

Second,

I believe that your UsersRoles table needs a PK. At least that is how I have seen all the documentation on it.

Third,

I always define an alias on the relationship to make it easier to use:

Users.php

        $this->hasManyToMany(
            "id",
            "Namespace\Models\UsersRoles",
            "user_id",
            "role_id",
            "Namespace\Models\Roles",
            "id",
            array('alias' => 'roles')
        );

UsersRoles.php

        $this->belongsTo('role_id', 'Namespace\Models\Roles', 'id',
            array('alias' => 'role')
        );
        $this->belongsTo('user_id', 'Namespace\Models\Users', 'id',
            array('alias' => 'user')
        );

Then, you should be able to use a magic getter on your alias as you requested:


    $roles = $user->getRoles();

Or you should be able to assign roles to a user:

    $role = \Namespace\Models\Roles::findFirst("name = 'Admin'"),
    $user->roles = [
        $role
    ];
    $user->update();

Finally,

Defining tables and column names with capitals is a quick recipe for diaster. I highly reccomend not doing this.



2.6k

Thanks so much for this! That image was the first example I could find online, my tables and column names do not contain capitals! :) I didn't end up needing a PK for the 'UserRoles' table.