XF 2.0 Proper Way to Save/Update User Entity in AdminCP

BoostN

Well-known member
I've added a new field to the xf_user table. I've extended the following class:
XF\Admin\Controller\User
to BoostN\AppName\XF\Admin\Controller\User

PHP:
<?php

namespace BoostN\AppName\XF\Admin\Controller;

class User extends XFCP_User
{
    protected function userSaveProcess(\XF\Entity\User $user)
    {
        parent::userSaveProcess($user);

        $form = $this->formAction();

        $input = $this->filter([
            'user' => [
                'my_column' => 'str'
            ]
        ]);
     
        //return $form->basicEntitySave($user, $input['user']); //This worked at first, but only this field would save.
     
        return $form->setupEntityInput($user, $input['user']);
    }
}

My Listener:

PHP:
<?php

namespace BoostN\AppName;

use XF\Mvc\Entity\Entity;

class Listener
{
    public static function userEntityStructure(\XF\Mvc\Entity\Manager $em, \XF\Mvc\Entity\Structure &$structure)
    {
        $structure->columns['my_column'] = ['type' => Entity::STR, 'default' => null];
    }
}

Code Event Listener:
Listen to Event: entity_structure
Callback: BoostN\AppName\Listener Method: userEntityStructure

I'm wanting to do this for the AdminCP View only. If I populate the column in the DB with text, it shows up fine, I'm just unable to save the modified values via the form.

When saving:
Code:
XF\Db\Exception: MySQL statement prepare error [1054]: Unknown column 'my_column' in 'field list' src\XF\Db\AbstractStatement.php:183

I found this post by Mike, and tried that but no luck either. And perhaps I just didn't understand..
 
Last edited:
You're throwing away the return value from the parent version of the userSaveProcess method. You need the FormAction it returns. You need to add your changes on top of it (and then you return the modified object).

In terms of the last error, it sounds like you haven't added the column to the DB.
 
Thanks Mike.

The column exists, because I'm getting data when I load the form:
1503498707803.webp

My class is now this, but it still tells me the same error message as my last post:

Code:
XF\Db\Exception: MySQL statement prepare error [1054]: Unknown column 'my_column' in 'field list' in src\XF\Db\AbstractStatement.php at line 183

PHP:
<?php

namespace BoostN\AppName\XF\Admin\Controller;

class User extends XFCP_User
{
    protected function userSaveProcess(\XF\Entity\User $user)
    {
        $form = parent::userSaveProcess($user);

        $input = $this->filter([
            'user' => [
                'my_column' => 'str',
            ],
        ]);

        return $form->setupEntityInput($user, $input['user']);
    }
}
 
I added XF\Entity\User to the Event Hint in my code event listener. Seems to be working now? :unsure:
 
Another question regarding saving the user.

Any helpful ideas on the logic for creating a user via the AdminCP? I currently have no issues updating the fields when editing an existing user. But when I try to create the user via the AdminCP I have the following error:

Code:
XF\Db\Exception: MySQL statement prepare error [1054]: Unknown column 'my_column' in 'field list' in src\XF\Db\AbstractStatement.php at line 183

My current process of saving a user is extending the "userSaveProcess".
 
Last edited:
PHP:
<?php

namespace BoostN\AppName\XF\Admin\Controller;

class User extends XFCP_User
{
    protected function userSaveProcess(\XF\Entity\User $user)
    {
        $form = parent::userSaveProcess($user);

        $input = $this->filter([
                'my_column' => 'str',
        ]);

        $form->setup(function () use ($user, $input)
        {
            $user->bulkSet($input);
        });

        return $form;
    }
}
Check it like this
 
PHP:
<?php

namespace BoostN\AppName\XF\Admin\Controller;

class User extends XFCP_User
{
    protected function userSaveProcess(\XF\Entity\User $user)
    {
        $form = parent::userSaveProcess($user);

        $input = $this->filter([
                'my_column' => 'str',
        ]);

        $form->setup(function () use ($user, $input)
        {
            $user->bulkSet($input);
        });

        return $form;
    }
}
Check it like this

What if I'm saving into the xf_user_option table instead?
PHP:
<?php

namespace BoostN\Test\XF\Admin\Controller;

class User extends XFCP_User
{
    protected function userSaveProcess(\XF\Entity\User $user)
    {
        $form = parent::userSaveProcess($user);

        $input = $this->filter([
            'option' => [
                'my_column' => 'bool'
            ]]);

        $userOptions = $user->getRelationOrDefault('Option');
        $form->setupEntityInput($userOptions, $input['option']);
        return $form;
    }
}
 
Exactly that ^

But didn't you add the my_column column to your User entity structure? You'd need to add it to the UserOption entity structure instead.

The error you posted yesterday suggests you're attempting to save to a column that doesn't exist in the database.

It might be worth providing an up to date account of what you're trying to do, which events/classes you're extending, which columns and tables are involved and what current errors you're hitting etc. as it's not totally clear at this stage.
 
Sorry for the delay.

My Class:
PHP:
<?php

namespace BoostN\Test\XF\Admin\Controller;

class User extends XFCP_User
{
    protected function userSaveProcess(\XF\Entity\User $user)
    {
        $form = parent::userSaveProcess($user);

        $input = $this->filter([
            'option' => [
                'my_column' => 'bool'
        ]]);

        $userOptions = $user->getRelationOrDefault('Option');
        $form->setupEntityInput($userOptions, $input['option']);
        return $form;
    }
}

Event Listeners:

Code Event: Entity Structure
Hint: XF\Entity\UserOption
Callback: BoostN\Test\Listener :: userEntityStructure

Listener:

PHP:
<?php

namespace BoostN\Test;

use XF\Mvc\Entity\Entity;
use XF\Mvc\Entity\Structure;

class Listener
{
    public static function userEntityStructure(\XF\Mvc\Entity\Manager $em, \XF\Mvc\Entity\Structure &$structure)
    {
        $structure->columns['my_column'] = ['type' => Entity::BOOL, 'default' => 0];
    }
}
 
I had two code event listeners setup.

Code Event: Entity Structure
Hint: XF\Entity\UserOption
Callback: BoostN\Test\Listener :: userEntityStructure

and

Code Event: Entity Structure
Hint: XF\Entity\User
Callback: BoostN\Test\Listener :: userEntityStructure

I also had another new column on the xf_user table. Once I removed that and this 2nd code event listener it all works.
 
Top Bottom