User Profile

Sanctum middleware

To make sure you can get your profile just right, you should add the auth:sanctum middleware to the restify middleware config:

// config/restify.php

'middleware' => [
    'api',
    'auth:sanctum',
    \Binaryk\LaravelRestify\Http\Middleware\DispatchRestifyStartingEvent::class,
    \Binaryk\LaravelRestify\Http\Middleware\AuthorizeRestify::class,
]

Get profile

When retrieving the user's profile, it is serialized by using the UserRepository.

GET: /api/restify/profile

This is what we have for a basic profile:

{
    "id": "7",
    "type": "users",
    "attributes": {
        "name": "Eduard",
        "email": "interstelar@me.com"
    },
    "meta": {
        "authorizedToShow": true,
        "authorizedToStore": true,
        "authorizedToUpdate": true,
        "authorizedToDelete": true
    }
}

You can add more fields in your UserRepository if you want to display them.

public function fields(RestifyRequest $request): array
{
    return [
        field('name')->rules('required'),

        field('email')->rules('required')->storingRules('unique:users'),

        field('age')
    ];
}

Since the profile is nicely set on by using the UserRepository, you can now benefit from the power of the related entities. For example, if you want to return user roles:

//UserRepository

public static array $related = [
    'roles',
];

Also, make sure that the User model has this method that returns a relationship from another table. You can do that or you can simply return an array:

//User.php

public function roles(): array
{
    // In a real project, here you will get this information from the database.
    return [
        'owner',
        'admin'
    ];
}

Now, let's get the profile by using the roles relationship:

GET: /api/restify/profile?include=roles

The result will look like this:

{
    "id": "7",
    "type": "users",
    "attributes": {
        "name": "Eduard",
        "email": "interstelar@me.com"
    },
    "relationships": {
        "roles": [
            "owner",
            "admin"
        ]
    },
    "meta": {
        "authorizedToShow": true,
        "authorizedToStore": true,
        "authorizedToUpdate": true,
        "authorizedToDelete": true
    }
}

Without repository

In some cases, you might choose not to use the repository for the profile serialization. Afterwards, you should add the trait Binaryk\LaravelRestify\Repositories\UserProfile into your UserRepository:

// UserProfile

use Binaryk\LaravelRestify\Repositories\UserProfile;

class UserRepository extends Repository
{
    use UserProfile;

    public static $model = 'App\\Models\\User';
    
    //...
}

The profile will return the model directly:

Relations

Note that when you're not using the repository, the ?include will not work anymore.

/api/restify/profile

You will get:

{
    "data": {
        "id": 7,
        "name": "Eduard",
        "email": "interstelar@me.com",
        "email_verified_at": null,
        "created_at": "2020-12-24T08:49:30.000000Z",
        "updated_at": "2020-12-24T08:52:37.000000Z"
    }
}

Conditionally use repository

In rare cases you may want to utilize the repository only for non admin users. Make sure to serialize specific fields for the users:

use Binaryk\LaravelRestify\Fields\Field;
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
use Binaryk\LaravelRestify\Repositories\UserProfile;
use Illuminate\Http\Request;

class UserRepository extends Repository
{
    use UserProfile;

    public static $model = 'App\\Models\\User';

    public static function canUseForProfile(Request $request)
    {
        return $request->user()->isAdmin();
    }
    
    public function fields(RestifyRequest $request)
    {
        return [
            field('name')->rules('required'),

            field('email')->rules('required')
                ->storingRules('unique:users')->messages([
                    'required' => 'This field is required.',
                ]),
        ];
    }
}

Thus, you instruct Restify to only use the repository for users who are admins of your application.

Update Profile using repository

By default, Restify will validate and fill only the fields presented in your UserRepository for updating the user's profile. Let's get as an example the following repository fields:

// UserRepository

public function fields(RestifyRequest $request)
{
    return [
        field('name')->rules('required'),

        field('email')->storingRules('required', 'unique:users')->messages([
                'required' => 'This field is required.',
            ]),
    ];
}

If we will try to call the PUT method to update the profile without data:

{}

We will get back a 4xx validation:

Accept header if you test it via Postman (or other HTTP client) and make sure you always pass the Accept header application/json. This will instruct Laravel to return you back the json formatted data:

{
    "message": "The given data was invalid.",
    "errors": {
        "name": [
            "The name field is required."
        ]
    }
}

Let's say we have to populate the user name in the payload:

{
    "name": "Eduard Lupacescu"
}

Since the payload is valid now, Restify will update the user's profile (a name, in our case):

{
    "id": "7",
    "type": "users",
    "attributes": {
        "name": "Eduard Lupacescu",
        "email": "interstelar@me.com"
    },
    "meta": {
        "authorizedToShow": true,
        "authorizedToStore": true,
        "authorizedToUpdate": true,
        "authorizedToDelete": true
    }
}

Update without repository

If you don't use the repository for the user's profile, Restify will only update the fillable user attributes that are present in the request payload: $request->only($user->getFillable()).

PUT: /api/restify/profile

Payload:

{
    "name": "Eduard Lupacescu"
}

The response will be the updated user:

{
    "data": {
        "id": 7,
        "name": "Eduard",
        "email": "interstelar@me.com",
        "email_verified_at": null,
        "created_at": "2020-12-24T08:49:30.000000Z",
        "updated_at": "2020-12-24T09:34:48.000000Z"
    }
}

User avatar

To prepare your users for avatars, you can add the avatar column in your users' table:

// Migration
public function up()
{
    Schema::table('users', function( Blueprint $t) {
        $t->string('avatar')->nullable();
    });
}

Now, you should specify in the user repository that the user has an avatar file:

use Binaryk\LaravelRestify\Fields\Image;

public function fields(RestifyRequest $request)
{
    return [
        field('name')->rules('required'),

        field('avatar')->image()->storeAs('avatar.jpg')
    ];
}

You can use the Restify's profile update and give the avatar as an image.

Post request

You cannot upload a file by using PUT or PATCH verbs, so we should use a POST request instead.

POST: /api/restify/profile

The payload should be a form-data, with an image under the avatar key:

{
    "avatar": "binary image in form data request"
}

If you have to customize the path or disk of the storage file, check the image field

Edit this page on GitHub Updated at Tue, Jul 26, 2022