This forum has moved to a new location and is in read-only mode. Please visit talk.octobercms.com to access the new location.

JimRed
JimRed

Hello Guys,

Could you please help me how can I extend a model of an existing plugin?
I've add a new (subgroup) field to groups controller of shahiemseymor's roles plugin but I would like to extend its UserGroup model as well.

So I tried to put this code into my Plugin.php file:

    UserGroup::extend(function($model) 
    {
        $model->hasOne['subgroup'] = ['Company\Project\Models\Group'];
    });    

My Group model has the the following scheme:

    Schema::create('company_project_groups', function($table)
    {
        $table->engine = 'InnoDB';
        $table->increments('id');
        $table->integer('user_group_id');
        $table->string('subgroup');
        $table->timestamps();
    });

...and as I see shahiemseymor's UserGroup model has the following scheme:

   Schema::create('shahiemseymor_roles', function($table)
    {
        $table->increments('id')->unsigned();
        $table->string('name')->unique();
        $table->timestamps();
    });

So as I mentioned I've already put subgroup field into groups controller of the roles plugin but when I save the form it does not create record in my database table...

I've already tried to define foreign keys and local keys, table names and everything else I just found in the documentation but it still doesn't work.

I don't know what could be wrong. Please help me!

Thank you!

ps.: sorry for my poor english... :/

a2thek26
a2thek26

Have you tried adding the belongsTo() relationship in your model?

JimRed
JimRed

Yes, I tried but nothing happened... :(

a2thek26
a2thek26

Maybe post a little more code from your plugin and your model to see a little more.

JimRed
JimRed

Okay. Here is my pages:

Plugin.php

<?php namespace Codebugs\Ldap;

use System\Classes\PluginBase;
use Event;
use ShahiemSeymor\Roles\Models\UserGroup;

/**
 * Ldap Plugin Information File
 */
class Plugin extends PluginBase
{

    /**
     * Returns information about this plugin.
     *
     * @return array
     */
    public function pluginDetails()
    {
        return [
            'name'        => 'Ldap',
            'description' => 'No description provided yet...',
            'author'      => 'Codebugs',
            'icon'        => 'icon-leaf'
        ];
    }

    public function boot()
    {

        UserGroup::extend(function($model) 
        {
            $model->hasOne['subgroup_name'] = ['Codebugs\Ldap\Models\Subgroup'];
        });

        Event::listen('backend.form.extendFields', function($widget){

            //Extend groups controller
            if (!$widget->getController() instanceof \ShahiemSeymor\Roles\Controllers\Groups) return;
            if (!$widget->model instanceof \ShahiemSeymor\Roles\Models\UserGroup) return;

            $widget->addFields([
                'subgroup_name' => [
                    'label' => 'Sub-group name',
                    'comment' => 'Select the sub-group name',
                    'type' => 'text',
                    'span' => 'auto'      
                    ]
                ]);
        });
    }

}

Subgroup model (Subgroup.php)

<?php namespace Codebugs\Ldap\Models;

use Model;

/**
 * Subgroup Model
 */
class Subgroup extends Model
{

    /**
     * @var string The database table used by the model.
     */
    public $table = 'codebugs_ldap_subgroups';

    /**
     * @var array Guarded fields
     */
    protected $guarded = ['*'];

    /**
     * @var array Fillable fields
     */
    protected $fillable = [];

    /**
     * @var array Relations
     */
    public $hasOne = [];
    public $hasMany = [];
    public $belongsTo = [
        'group' => ['UserGroup', 'foreignKey' => 'user_group_id']
    ];
    public $belongsToMany = [];
    public $morphTo = [];
    public $morphOne = [];
    public $morphMany = [];
    public $attachOne = [];
    public $attachMany = [];

}

Subgroup table scheme

<?php namespace Codebugs\Ldap\Updates;

use Schema;
use October\Rain\Database\Updates\Migration;

class CreateSubgroupsTable extends Migration
{

    public function up()
    {
        Schema::create('codebugs_ldap_subgroups', function($table)
        {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->integer('user_group_id');
            $table->string('subgroup_name');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('codebugs_ldap_subgroups');
    }

}

Thank you for your help!

Last updated

a2thek26
a2thek26

I think in your model belongsTo() need to be the fully qualified namespace of UserGroup.

So try:

public $belongsTo = [
    'group' => ['\ShahiemSeymor\Roles\Models\UserGroup', 'foreignKey' => 'user_group_id']
];
JimRed
JimRed

I tried in this way but it still does not work... :(
Do you have other idea what could be the problem?

Thank you!

Last updated

a2thek26
a2thek26

Well I think you'll probably still need to keep that in your model. One other idea is taken from the way they do it with the forum plugin with extending the fields. So you've named your field subgroup_name and your relationship is named group. You may want to just change the field name to name in the db and extend the fields buy using the array syntax.

$widget->addFields([
    'group[name]' => [
        'label' => 'Sub-group name',
        'comment' => 'Select the sub-group name',
        'type' => 'text',
        'span' => 'auto'      
    ]
]);
JimRed
JimRed

It says the following error:
Unexpected type of array, should attribute "group" be jsonable?

What could be wrong?

a2thek26
a2thek26

Post your code. But it sounds like you made the key an actual array instead of an array-like string.

This $group['name'] is not the same as this 'group[name]'

JimRed
JimRed

Unfortunately it still not ok... :( Here are my pages now, after the changes...

Plugin.php

<?php namespace Codebugs\Ldap;

use System\Classes\PluginBase;
use Event;
use ShahiemSeymor\Roles\Models\UserGroup;

/**
 * Ldap Plugin Information File
 */
class Plugin extends PluginBase
{

    /**
     * Returns information about this plugin.
     *
     * @return array
     */
    public function pluginDetails()
    {
        return [
            'name'        => 'Ldap',
            'description' => 'No description provided yet...',
            'author'      => 'Codebugs',
            'icon'        => 'icon-leaf'
        ];
    }

    public function boot()
    {

        UserGroup::extend(function($model) 
        {
            $model->hasOne['subgroup_name'] = ['Codebugs\Ldap\Models\Subgroup'];
        });

        Event::listen('backend.form.extendFields', function($widget){

            //Extend groups controller
            if (!$widget->getController() instanceof \ShahiemSeymor\Roles\Controllers\Groups) return;
            if (!$widget->model instanceof \ShahiemSeymor\Roles\Models\UserGroup) return;

            $widget->addFields([
                '$group[name]' => [
                    'label' => 'Sub-group name',
                    'comment' => 'Select the sub-group name',
                    'type' => 'text',
                    'span' => 'auto'      
                    ]
                ]);
        });
    }

}

Subgroup model (Subgroup.php)

<?php namespace Codebugs\Ldap\Models;

use Model;

/**
 * Subgroup Model
 */
class Subgroup extends Model
{

    /**
     * @var string The database table used by the model.
     */
    public $table = 'codebugs_ldap_subgroups';

    /**
     * @var array Guarded fields
     */
    protected $guarded = ['*'];

    /**
     * @var array Fillable fields
     */
    protected $fillable = [];

    /**
     * @var array Relations
     */
    public $hasOne = [];
    public $hasMany = [];
    public $belongsTo = [
        'group' => ['\ShahiemSeymor\Roles\Models\UserGroup', 'foreignKey' => 'user_group_id']
    ];
    public $belongsToMany = [];
    public $morphTo = [];
    public $morphOne = [];
    public $morphMany = [];
    public $attachOne = [];
    public $attachMany = [];

}

Subgroup table scheme

<?php namespace Codebugs\Ldap\Updates;

use Schema;
use October\Rain\Database\Updates\Migration;

class CreateSubgroupsTable extends Migration
{

    public function up()
    {
        Schema::create('codebugs_ldap_subgroups', function($table)
        {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->integer('user_group_id');
            $table->string('name');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('codebugs_ldap_subgroups');
    }

}

ShahiemSeymor's UserGroup table scheme

       Schema::create('shahiemseymor_roles', function($table)
        {
            $table->increments('id')->unsigned();
            $table->string('name')->unique();
            $table->timestamps();
        });

What am I doing wrong?
Thank you for your help!

JimRed
JimRed

I tried to change by the Forum plugin and my Plugin.php looks like this now:

Plugin.php

<?php namespace Codebugs\Ldap;

use System\Classes\PluginBase;
use Event;
use ShahiemSeymor\Roles\Models\UserGroup;

/**
 * Ldap Plugin Information File
 */
class Plugin extends PluginBase
{

    /**
     * Returns information about this plugin.
     *
     * @return array
     */
    public function pluginDetails()
    {
        return [
            'name'        => 'Ldap',
            'description' => 'No description provided yet...',
            'author'      => 'Codebugs',
            'icon'        => 'icon-leaf'
        ];
    }

    public function boot()
    {

        UserGroup::extend(function($model) 
        {
            $model->hasOne['group'] = ['Codebugs\Ldap\Models\Subgroup'];
        });

        Event::listen('backend.form.extendFields', function($widget){

            //Extend groups controller
            if (!$widget->getController() instanceof \ShahiemSeymor\Roles\Controllers\Groups) return;
            if (!$widget->model instanceof \ShahiemSeymor\Roles\Models\UserGroup) return;

            $widget->addFields([
                'group[name]' => [
                    'label' => 'Sub-group name',
                    'comment' => 'Select the sub-group name',
                    'type' => 'text',
                    'span' => 'auto'      
                    ]
                ]);
        });
    }

}

But when I try to save the form on backend I receive the following error message:
"Creating default object from empty value"

Can you help me what could be the problem now?
Thank you!

a2thek26
a2thek26

I would really just keep using the forum as an example. Specifically, the way the forum_user interacts with the Member and User model. You'll need to populate the data from the base UserGroup and make sure it is stored on your group model relationship.

JimRed
JimRed

Thank you a2thek26. Just a last question: Are my relationship settings are ok in the Plugin.php and in my Subgroup model?

I ask it because ShahiemSeymor does not use user_group_id field in the shahiemseymor_roles table so the link reference would be the following:
subgroupmodel.user_group_id = usergroupmodel.id (but the usergroup model uses the table shahiemseymor_roles)

So did I set the relationships fine?

Thank you for your help!

a2thek26
a2thek26

One thing to remember is that whatever you set the relationship alias to, is how you will end up referencing the relationship when using the model. So if UserGroup is the model you are extending by adding a Subgroup, it is referenced by the alias. You are extending the UserGroup with the alias group (which is your subgroup). Because you've aliased Subgroup as group and you want the name field. (you may want to changed the alias to subgroup just so it is clear)

$userGroup = UserGroup::find(1);
$subGroupName = $userGroup->subgroup->name;

The reverse is the same for referencing the UserGroup from the Subgroup:

$subGroup = Subgroup::find(8);
$userGroupName = $subGroup->group->name;

Hope that makes sense.

JimRed
JimRed

But how October knows what columns should match if these names are differs? I mean the UserGroup model uses the shahiemseymor_roles table and there is only an id and a name field in it. My Subgroup model uses table codebugs_ldap_subgroups and it also has an id but I would like if the usergroup.id would be linked to subgroups.user_group_id. (usergroup.id = subgroup.user_group_id) and every UserGroup has one subgroup
How should I set the relationships?

Sorry, my english is poor but I hope you understand what I would like to say...

a2thek26
a2thek26

In your Subgroup Model you should have this:

public $belongsTo = [
        'group' => ['\ShahiemSeymor\Roles\Models\UserGroup', 'foreignKey' => 'user_group_id']
    ];

In your plugin you should have this:

public function boot()
    {

        UserGroup::extend(function($model) 
        {
            $model->hasOne['subgroup'] = ['Codebugs\Ldap\Models\Subgroup'];
        });

        Event::listen('backend.form.extendFields', function($widget){

            //Extend groups controller
            if (!$widget->getController() instanceof \ShahiemSeymor\Roles\Controllers\Groups) return;
            if (!$widget->model instanceof \ShahiemSeymor\Roles\Models\UserGroup) return;

            $widget->addFields([
                'subgroup[name]' => [
                    'label' => 'Sub-group name',
                    'comment' => 'Select the sub-group name',
                    'type' => 'text',
                    'span' => 'auto'      
                    ]
                ]);
        });
    }

Last updated

JimRed
JimRed

I just noticed some interesting thing...
I've added a new record manualy to my subgroup table and when I checked in the backend form the value appeared in the subgroup field and I was able to change that, so I was able to update the existing record... BUT when I tried to create a new record via backend (so not manually in the database table) I received the error message that "Creating default object from empty value"

Should I make some pre-check if the form uses update or create method?
Or what should I do to make it work when I create brand new record?

Here is my Plugin.php file now:

<?php namespace Codebugs\Ldap;

use Event;
use Backend;
use ShahiemSeymor\Roles\Models\UserGroup;
use Codebugs\Ldap\Models\Subgroup;
use System\Classes\PluginBase;

/**
 * Forum Plugin Information File
 */
class Plugin extends PluginBase
{

    public $require = ['ShahiemSeymor.Roles'];

    /**
     * Returns information about this plugin.
     *
     * @return array
     */
    public function pluginDetails()
    {
        return [
            'name'        => 'Ldap',
            'description' => 'A simple embeddable forum',
            'author'      => 'Alexey Bobkov, Samuel Georges',
            'icon'        => 'icon-comments'
        ];
    }

    public function boot()
    {
        UserGroup::extend(function($model) {
            $model->hasOne['forume'] = ['Codebugs\Ldap\Models\Subgroup'];
        });

        Event::listen('backend.form.extendFields', function($widget) {
            if (!$widget->getController() instanceof \ShahiemSeymor\Roles\Controllers\Groups) return;
            if (!$widget->model instanceof \ShahiemSeymor\Roles\Models\UserGroup) return;
            //if ($widget->getContext() != 'update') return;
            //if (!Member::getFromUser($widget->model)) return;

            $widget->addFields([
                'forume[name]' => [
                    'label'   => 'Username',
                    'tab'     => 'Forum',
                    'comment' => 'The display to represent this user on the forum.',
                ],
            ], 'primary');
        });

        Event::listen('backend.list.extendColumns', function($widget) {
            if (!$widget->getController() instanceof \ShahiemSeymor\Roles\Controllers\Groups) return;
            if (!$widget->model instanceof \ShahiemSeymor\Roles\Models\UserGroup) return;

            $widget->addColumns([
                'subgroup_name' => [
                    'label'      => 'Forum Username',
                    'relation'   => 'forume',
                    'select'     => 'name',
                    'searchable' => true,
                ]
            ]);
        });

    }

}

Thank you for your help!

Last updated

a2thek26
a2thek26

This line if ($widget->getContext() != 'update') return; will extend the form if it isn't creating the record. So on update, it will extend the form. Which means it will update properly. So that is the pre-check you are speaking of.

JimRed
JimRed

But if I put this line into my code and the page is not the update page but the create page than the subgroup field don't appear on the page...

1-20 of 27

You cannot edit posts or make replies: the forum has moved to talk.octobercms.com.