Search code examples
phplaraveleloquentlaravel-4

Write to hasMany relationship with Eloquent ORM/Laravel


Question about Laravel's Eloquent ORM. I've had a look on SO already, apologies if I've missed a similar question.

I have a User model, and I'm trying to write an array of Permissions back to the UserPermissions model, via the relationship in the User model.

I've setup the hasMany link already, and can retrieve the correct data from the User object ($user->roles), but can't work out how to write back if it is at all possible.

This is my basic user model:

class User extends Eloquent {

    protected $table = 'users';

    public $timestamps = false;

    protected function roles() {

        return $this->hasMany('UserPermission');

    }

}

and the UserPermission model:

class UserPermission extends Eloquent {

    protected $table = 'users_permissions';

    public $timestamps = false;

    protected $fillable = ['role_id', 'user_id'];

}

At this stage, I've reverted to saving the User, and then running UserPermission::insert(), which allows an array to be passed, but I'd prefer to do it in one step if possible.

Anyone know if this is possible?

Thanks!


UPDATE:

Table structure is below for your perusal:

users table

+------------------+------------------+------+-----+---------+----------------+
| Field            | Type             | Null | Key | Default | Extra          |
+------------------+------------------+------+-----+---------+----------------+
| id               | int(10) unsigned | NO   | PRI | 0       | auto_increment |
| username         | varchar(255)     | NO   |     |         |                |
+------------------+------------------+------+-----+---------+----------------+

users_roles table

+------------------+------------------+------+-----+---------+----------------+
| Field            | Type             | Null | Key | Default | Extra          |
+------------------+------------------+------+-----+---------+----------------+
| id               | int(10) unsigned | NO   | PRI | 0       | auto_increment |
| name             | varchar(255)     | NO   |     |         |                |
| description      | varchar(255)     | YES  |     | NULL    |                |
| url_access       | varchar(255)     | NO   |     |         |                |
+------------------+------------------+------+-----+---------+----------------+

users_permissions table

+------------------+------------------+------+-----+---------+----------------+
| Field            | Type             | Null | Key | Default | Extra          |
+------------------+------------------+------+-----+---------+----------------+
| id               | int(10) unsigned | NO   | PRI | 0       | auto_increment |
| role_id          | int(10) unsigned | NO   |     |         |                |
| user_id          | int(10) unsigned | NO   |     |         |                |
+------------------+------------------+------+-----+---------+----------------+

role_id relates to users_roles.id and user_id relates to users.id

As background logic, the users_roles table has a url_access column which contains a url. If the user is assigned to that role, they have access to the subpages from that url.


Solution

  • I do not really see why you are using hasMany relationship instead of belongsToMany. Actually it seems that your database structure is already such that is utilized by the belongsToMany relationship in Laravel.

    My solution:

    User.php

    <?php
    
    class User extends Eloquent {  
    
      public function roles() {
        return $this->belongsToMany('Role');
      }
    
      protected $table = 'users';
      protected $guarded = array('id', 'password');
    }
    

    Role.php

    <?php
    
    class Role extends Eloquent {
    
    public function users()
      {
      return $this->belongsToMany('User');
      }
    
    protected $table = 'roles';
    protected $guarded = array('id');
    

    }

    The corresponding database tables should be: users, roles and role_user. These are according to Laravel's naming conventions in order to keelp things simple.

    Now you may call the sync method and pass an array to it:

    $user->roles()->sync(array(1, 2, 3));
    

    The sync method is briefly described in the Eloquent ORM documentation.