Extending User Profiles

Assuming you will be utilizing the standard users package powered by Armor, you may wish to expand it for your application. With its extensible design, it's rather easy to extend the user profiles to store and retrieve any additional information you desire, trigger additional functions during typical CRUD operations, and more.

Learning by example, this guide will go through the process of allowing additional chef profile information to be stored with each user, including number of michelin stars, their restaurant name, signature dish, speciality, and date they became a chef. Let's jump right into it.

Create Package, Database, and Model

First, create a new chefs package with the terminal command:

./apex package create chefs

Open the file at ~/etc/Chefs/install.sql and enter the below contents:

CREATE TABLE chefs_profiles (
    uuid VARCHAR(30) NOT NULL PRIMARY KEY, 
    michelin_stars INT NOT NULL DEFAULT 0, 
    restaurant_name VARCHAR(100) NOT NULL, 
    signature_dish VARCHAR(100) NOT NULL, 
    speciality VARCHAR(100) NOT NULL, 
    started_at DATE NOT NULL, 
    FOREIGN KEY (uuid) REFERENCES armor_users (uuid) ON DELETE CASCADE
);

Either connect to your SQL database and copy and paste that above code, or run it via migrations with the terminal command:

./apex migration install chefs

Last, create the model with the command:

./apex opus model src/Chefs/ChefProfile.php --dbtable chefs_profile

A new file will now be located at ~/src/Chefs/ChefsProfile.php that is a model with all proper get / set methods, which you may modify as desired.

Create Listener -- Load User

Create a listener with the terminal command:

./apex create listener chefs load_user --routing-key users.profile.load --target-package chefs

Open the new file at ~/src/Chefs/Listeners/LoadUser.php, and replace with the following contents:

<?php
declare(strict_types = 1);

namespace App\Chefs\Listeners;

use Apex\Svc\Db;
use Apex\Cluster\Interfaces\{MessageRequestInterface, FeHandlerInterface};

/**
 * Load user listener
 */
class LoadUser
{

    /**
     * Load user
     */
    public function load(MessageRequestInterface $msg, FeHandlerInterface $handler):?ChefsProfile
    {

        // Get uuid being loaded
        $uuid = $msg->getParams();

        // Load the model
        if (!$chef = $this->db->getIdObject(ChefsProfile::class, 'chefs_profile', $uuid)) { 
            return null;
        }

        // Return
        return $chef;
    }
}

Retrieving Chef Profiles

You can now retrieve the chef profile of any user by calling the getExtended() method on any user object:

[data-line=42]
$chef = $user->getExtended('chefs');

// $chef is now either null, or an instance of the CefsProfile model.

For example, you may wish to create an HTTP controller and view to display chef profiles on the public site. Run the terminal commands:

./apex create http-controller chefs --route "/chef/:username"
./apex create view public/chefs chefs

Open the new ~/src/HttpControllers/Cefs.php file, and enter the following contents:

Extending CRUD Functionality

You may also easily have additional PHP code executed when users are created, deleted and updated. Simply create a listener with the routing key users.profiles with the terminal command:

./apex create listener chefs users --routing-key users.profiles

Within the new class available at ~/src/Chefs/Listeners/Users.php you may add any of the following methods:

  • preCreate()
  • postCreate()
  • preDelete()
  • postDelete()
  • activated()
  • deactivated()
  • approved() - Only applicable if new users are initially marked as pending. This method is executed upon administrator approval of pending user.
  • usernameUpdated()
  • emailUpdated()
  • phoneUpdated()
  • passwordUpdated()
  • groupUpdated()
  • login
  • logout