FrozenNode / Laravel-Administrator

An administrative interface package for Laravel
http://administrator.frozennode.com/
MIT License
1.94k stars 501 forks source link

If using Zizaco Entrust and having "permissions" as column in Role model config, you need a custom Accessor/Mutator #266

Closed Gadoma closed 11 years ago

Gadoma commented 11 years ago

Just a quick note for those using Zizaco Entrust for Role/Permission management (updated)

The Role model extends the EntrustRole class. The password attribute is fetched using a custom getter (json decoder) and writter with a custom setter (json encoder). Because while trying to get permissions you'd suppose a string (as it is a string or text field) you will get an array of strings - as a result of json_decode.

Initially, when I put "permissions" attribute as a column in Role administrator model config , while trying to view a list of Roles in Administrator I got an error

[2013-07-25 19:50:32] log.ERROR: exception 'ErrorException' with message 
'Array to string conversion' in ... vendor/frozennode/administrator/src/Frozennode/ 
Administrator/DataTable/Columns/Column.php:242 

Creating a custom Accessor/Mutator (a getter/setter) in the Role model and using it as a custom field solves the problem, as Administrator can properly render the item list and column content - the (formated_)permissions attribute is fed properly as String not as Array (because of Entrust).

public function getFormatedPermissionsAttribute()
{
    return implode(",",$this->getAttribute('permissions'));

}

public function setFormatedPermissionsAttribute($p)
{
    $this->setPermissionsAttribute(explode(",",$p));
}

See post below for a full example solution including Role model and Role model config.

Regards, Gadoma

janhartigan commented 11 years ago

Thanks for posting this! As I've said before, one of my favorite things about Administrator is that it sits on top of Eloquent, and as such you have access to an enormous amount of features from that alone.

Gadoma commented 11 years ago

I crosschecked it with Entrust's Role's model source in

entrust / src / Zizaco / Entrust / EntrustRole.php

/**
* Before save should serialize permissions to save
* as text into the database
*
* @param array $value
*/
public function setPermissionsAttribute($value)
{
    $this->attributes['permissions'] = json_encode($value);
}

    

/**
* When loading the object it should un-serialize permissions to be
 * usable again
 *
 * @param string $value
 * permissoins json
 */
public function getPermissionsAttribute($value)
{
    return (array)json_decode($value);
}

So I guess the proper fix should include the modified Setter as well, please correct me if Im missing something here? ;)

public function getFormatedPermissionsAttribute()
{
$p = $this->getAttribute('permissions');
return is_array($p) ? implode('|',$p) : $p; 
} 

public function setFormatedPermissionsAttribute($p)
{
$p = (strpos($p,"|")!==false) ? explode("|",$p) : array($p);

$this->attributes['pemission'] = $p;

} 
janhartigan commented 11 years ago

I've never used Entrust...you are now the authoritative source on combining Administrator with Entrust :)

Though it looks like you misspelled "formatted" ;)

Gadoma commented 11 years ago

OK I did some tests and here's the final fix :ok_hand:

example Role model config (uses translations as field titles):

return array(
    'title' => trans('administrator.role._admin.title'), 
    'model' => 'Role', 
    'single' => trans('administrator.role._admin.single'), 
    'form_width' => 500, 
    'sort' => '', 
    'columns' => array( 
    'id' => array( 
        'title' => trans('administrator.role.id') , 
    ), 
    'name' => array( 
        'title' => trans('administrator._global.name') , 
    ), 
    'formated_permissions' => array( 
        'title' => trans('administrator._global.permissions') , 
    ), 
    'created_at' => array( 
        'title' => trans('administrator._global.created_at') , 
        'editable' => 0, 
    ), 
), 
'filters' => array( 
    'id' => array( 
        'title' => trans('administrator.role.id') , 
        'type' => 'key', 
    ), 
    'name' => array( 
        'title' => trans('administrator._global.name') , 
        'type' => 'text', 
        'limit' => '128', 
    ), 
    'permissions' => array( 
        'title' => trans('administrator._global.permissions') , 
        'type' => 'text', 
        'limit' => '128', 
    ), 
    'created_at' => array( 
        'title' => trans('administrator._global.created_at') , 
        'type' => 'date', 
        'editable' => 0, 
    ), 
), 
'edit_fields' => array( 
    'id' => array( 
        'title' => trans('administrator.role.id') , 
        'type' => 'key', 
    ), 
    'name' => array( 
        'title' => trans('administrator._global.name') , 
        'type' => 'text', 
        'limit' => '128', 
    ), 
    'permissions' => array( 
        'title' => trans('administrator._global.permissions') , 
        'type' => 'text', 
        'limit' => '512', 
    ), 
), 
); 

example Role model class:

 use Zizaco\Entrust\EntrustRole;
class Role extends EntrustRole
{

public static $rules = array();
public $timestamps = true;

...
...
...

public function getFormatedPermissionsAttribute()
{
    return implode(",",$this->getAttribute('permissions'));

}

public function setFormatedPermissionsAttribute($p)
{
    $this->setPermissionsAttribute(explode(",",$p));
}

}

EDIT: I also updated the initial post to include full info and solution.

liucf commented 10 years ago

@Gadoma i am working on Zizaco Entrust, and after I install this Laravel-Administrator, i want integrate them correctly. i want in admin edit I edit a user, i can edit it's role in the same page, how can i do that? also i want when I edit a role, i can edit this role's permission in the same page. how can i do that?

please let me know.

thanks