We are moving our forum in GitHub Discussions. For questions about Phalcon v3/v4 you can visit here and for Phalcon v5 here.

Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

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.6k

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: http://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.