Welcome Guest, Not a member yet? Register   Sign In
How-To: Add custom user fields in Codeigniter 4 and Shield
#1
Information 

Responded to a Stack question so I thought I would post here as well for continuity. If you have a better way, please share Smile

There are many conversation on this topic and several ways you can implement this. Some have expanded the users table, some the auth_identities table. I chose to create a seperate user_details table. Either method is fine and purely based on your development style and application needs.

Here is my table, it has a lot more than this, but you get the idea:

I set a Key to the auth_identities  table in case the user is removed.
PHP Code:
    CREATE TABLE `user_details` (
    `idINT(11UNSIGNED NOT NULL AUTO_INCREMENT,
    `user_idINT(11UNSIGNED NOT NULL,
    `firstnameVARCHAR(255NOT NULL COLLATE 'utf8_general_ci',
    `middlenameVARCHAR(50NULL DEFAULT NULL COLLATE 'utf8_general_ci',
    `lastnameVARCHAR(255NOT NULL COLLATE 'utf8_general_ci',
    `phoneVARCHAR(255NOT NULL COLLATE 'utf8_general_ci',
    `address1VARCHAR(255NOT NULL COLLATE 'utf8_general_ci',
    `address2VARCHAR(255NULL DEFAULT NULL COLLATE 'utf8_general_ci',
    `cityVARCHAR(255NOT NULL COLLATE 'utf8_general_ci',
    `stateVARCHAR(255NOT NULL COLLATE 'utf8_general_ci',
    `zipINT(11NULL DEFAULT '0',
    `updated_atTIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`) USING BTREE,
    INDEX `user_id` (`user_id`) USING BTREE,
    CONSTRAINT `auth_identities_user_id_fk2FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE
    
)
    COLLATE='utf8_general_ci'
    ENGINE=InnoDB
    AUTO_INCREMENT
=1

https://codeigniter4.github.io/shield/qu...ing-a-user

The below taken from the documentation above, Make sure you are using the right Model before your class name:
PHP Code:
    use CodeIgniter\Shield\Models\UserModel;

    protected $usersModel;

    public function __construct() {
        $this->usersModel          = new UserModel();
    

In my Controller, I have the following as a view for the user, (I use an Ajax Modal Window):
PHP Code:
    public function view() {
        checkAjax();
        if (!$this->user->hasPermission('users.read')) {
            $response['success']       false;
            $response['messages']      lang("App.invalid_permission");
            return $this->response->setJSON($response);
        }
        $id                    $this->request->getPost('id');
        $user                  $this->usersModel->findById($id);
        $permission            $user->getPermissions();
        $identity              $user->getEmailIdentity();

        $data = [
            'title'            => 'View Users',
            'user'             => $user,
            'details'          => $this->detailsModel->where('user_id'$id)->first(),
            'group'            => (!empty($user->groups) ? $user->groups[0] : 'Unassigned'),,
            'pTable'           => buildPermissionsTable($permission),
            'identity'         => $identity->secret
        
];

        return view('users/view'$data);
    

The "buildPermissionsTable" is in a array_helper file as I only give one role to the users where Shield allows multiple. I assign each user permissions based on Controller.Method IE: users.create or users.update or users.delete. This helps me to prevent group overlap or creating several different groups when I only need to assign a specific level of access.

Updating the user is the same as above, sort the data from the posted user form in the controller and insert into the appropriate table. You can find more on that using the link above:

You put everything in the users and auth_identities tables first, then the rest in the user_details table, basic example below:

Example to modify the data in users and auth_identities tables slightly modified from the above documentation link (obviously the method below is not complete):
PHP Code:
    public function edit() {
        checkAjax();
        if (!$this->user->hasPermission('users.update')) {
            $response['success']       false;
            $response['messages']      lang("App.invalid_permission");
            return $this->response->setJSON($response);
        }
        
        $id                            
$this->request->getPost('id');
        $originalDate                  Time::now('America/Chicago''en_US');
        $newDateString                 $originalDate->format('Y-m-d H:i:s');
        
        
// Add all of your post value here... 
        // $authFields are for Shield
        // $detailFields are for user_details table
        $authFields['username']           $this->request->getPost('username');
        $authFields['email']              $this->request->getPost('email');
        $authFields['updated_at']         $newDateString;
        // Snip... 

        $detailFields['firstname']        $this->request->getPost('firstname');
        $detailFields['lastname']         $this->request->getPost('lastname');
        $detailFields['phone']            $this->request->getPost('phone');
        // Snip... You get the idea from here...
        
        $this
->validation->setRules([
            'username'             => ['label' => 'Username''rules'              => 'required|max_length[20]|min_length[6]|alpha_dash|is_unique[users.username,id,'.$id.']'],
            'email'                => ['label' => 'Email Address''rules'         => 'required|valid_email|is_unique[auth_identities.secret,user_id,'.$id.']'],
            'password'             => ['label' => 'Password''rules'              => 'permit_empty|min_length[8]'],
            'confirm_password'     => ['label' => 'Confirm Password''rules'      => 'permit_empty|min_length[8]|matches[password]'],
            'group'                => ['label' => 'User Group''rules'            => 'required'],
        ]);

        $response = array();

        if ($this->validation->run($fields) == FALSE) {
            $response['success']           false;
            $response['messages']          $this->validation->getErrors(); //Show Error in Input Form
        } else {
            $users             $this->_usersModel;
            $user              $users->findById($id);
            $user->fill($fields);
            
            
if ($users->save($user)) {
                $user->syncGroups($fields['group']);

                // reset rules to check user details data
                $this->validation->reset();

                // Validation for Rules are in UserDetailsModel
                if ($this->detailsModel->save($detailFields)  == TRUE) {
                    $response['success']    true;
                    $response['messages']   lang("App.update-success");
                } else {
                    $response['success']    false;
                    $response['messages']   $this->_detailsModel->errors();
                }
            } else {
                $response['success']        false;
                $response['messages']       lang("App.update-error");
            }
        }
        return $this->response->setJSON($response);
    
Hope this helps!
If you see a mistake or if your way is better, post it below!

- Dean
Reply




Theme © iAndrew 2016 - Forum software by © MyBB