phplaravelrelationshipdtolaravel-permission

Permissions relation loaded but not returned with DTO [ Laravel/Spatie-permissions/Spatie-data ]


I've started laravel two months ago and I work to project.

I have problem that I don't understand. All my others DTO works but not them have relation with Spatie permissions. My problems are that I have undefined PermissionsData's collection after to be passed to RoleData.

Here my DTO :

<?php

namespace App\Data;

use Spatie\LaravelData\Data;
use Spatie\LaravelData\DataCollection;
use Spatie\LaravelData\Lazy;
use Spatie\LaravelData\Optional;
use Spatie\Permission\Models\Role;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript]
class RoleData extends Data
{
    public function __construct(
      public int $id,
      public string $name,
      /** @var DataCollection<PermissionData> */
      public Lazy|DataCollection|Optional $permissions,
      public string $created_at,
      public string $updated_at,
    ) {
    }

    public static function fromModel(Role $role): self
    {
        return new self(
            id: $role->id,
            name: $role->name,
            permissions: Lazy::create(fn () => PermissionData::collection($role->permissions)),
            created_at: $role->created_at->toDateTimeString(),
            updated_at: $role->updated_at->toDateTimeString(),
        );
    }
}

It is used inside my controller and rendered to inertia.

I share you all place where it used.

Here inside my controller:

public function show(Role $role): InertiaResponse
    {
        $role->load('permissions');

        return Inertia::render('Roles/Show', new RolesShowViewModel(
            role: RoleData::from($role),
        ));
    }

Here inside my view model ( used like super DTO ):

<?php

namespace App\ViewModels\Roles;

use App\Data\RoleData;
use Spatie\LaravelData\Data;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript]
class RolesShowViewModel extends Data
{
    public function __construct(
        public RoleData $role
    ) {
    }
}

And here my Show.tsx page:

import { RolesShowViewModel } from "@/types/generated";

export default function Show({ role }: RolesShowViewModel): JSX.Element {
    console.log(role.permissions);

    return (
        <div>
            <h1>Role {role.name}</h1>
            <h2>Permissions</h2>
            <ul>
                {role?.permissions?.map(permission => (
                    <li key={permission.id}>{permission.name}</li>
                ))}
            </ul>
        </div>
    );
}

When I dd inside my formModel function, permissions are correctly loaded but after when I console.log to my page, it return undefined.

Thank you in advanced for help

I have log all moments where I had permissions loaded to $role.

I had inspected my other DTO.

Review documentation to Spatie permissions.

Open discussion to spatie permissions github.

Ask community laracast.

Ask senior Laravel dev.


Solution

  • Evening,

    It's resolved.

    Just need to use :

    Lazy::whenLoaded('permissions', $role, fn () => PermissionData::collection($role->permissions))
    

    Instead of Lazy::create

    Spatie laravel-data