0
votes

Comment transmettre une demande personnalisée à Api Resource

J'ai une classe de requête personnalisée:

class SomeResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            ...
        ];
    }
}

et recours API:

class ApiRequest extends FormRequest
{
    ...
    public function locale()
    {
        $lang = $this->header('Accept-Language');
        return $lang ? $lang : 'uz';
    }
}

mais je ne peux pas utiliser la méthode locale() d'ApiRequest dans SomeResource. Parce que toArray() n'accepte que \Illuminate\Http\Request .

Y a-t-il une idée que je passe ma classe là-dedans? Ou une meilleure solution de votre part.


2 commentaires

Comment passez-vous la demande via la ressource API? Mettez à jour votre réponse avec ce code.


Je l'utilise dans un contrôleur: return new SomeResource (User :: find (2)), laravel le récupère automatiquement.


3 Réponses :


0
votes

Les ressources API doivent recevoir des instances de modèle et non des requêtes elles- mêmes. Ceci est un exemple:

ApiRequest.php

MyCoolController extends Controller {

    public function myFunction(ApiRequest $request)
    {
        $lang = $request->header('Accept-Language') ?? 'uz';
        \App::setLocale($lang); // <--

        $model = MyModel::find($request->get('id'));

        return new SomeResource($model);
    }
}

MyCoolController.php

ApiRequest extends Request {

    public function authorize() { /** your logic */ }

    public function rules() { /** your logic */ }

}


4 commentaires

Je ne voulais pas récupérer l'en-tête de la requête à chaque fois dans mon contrôleur, je voulais donc le généraliser d'une manière ou d'une autre


Vous pourriez mettre cette logique dans un middleware, ce n'était qu'un exemple. Mon point est que vous ne devriez pas utiliser de requêtes dans vos ressources API. Gardez à l'esprit que cette classe sera appliquée pour chaque instance de modèle (au cas où vous SomeResource::collection($models); dans une collection d'objets en utilisant l'option statique: SomeResource::collection($models); ) donc ne serait pas très efficace à mon avis.


voir ma solution ci-dessous


@SomeDev voir mon commentaire ci-dessus: v. Encore une fois, ce n'est qu'une suggestion, gardez cela à l'esprit.



0
votes

J'ai créé une classe Resource de base, que toutes mes autres classes de ressources l'étendent avec ma méthode personnalisée:

class SomeResource extends BaseResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        $lang = $this->locale($request);

        return [
            'id' => $this->id,
            'hash' => $this->hash,
            'name'  => $this->translation('name', $this->locale($request)),
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

et je l'utilise en classe enfant:

class BaseResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return parent::toArray($request);
    }

    protected function locale($request)
    {
        $lang = $request->header('Accept-Language');
        return $lang ? $lang : 'uz';
    }
}


0 commentaires

1
votes

L'instance de demande liée dans le conteneur est injectée dans la classe de ressources JSON lorsque la réponse est créée.

Une méthode pour obtenir ce que vous voulez serait de créer votre demande personnalisée qui étend la classe de demande standard, puis de la lier dans le conteneur en tant qu'instance de demande à utiliser pour le reste de la demande. Cela pourrait être fait dans un middleware affecté spécifiquement au groupe API ou simplement dans des contrôleurs spécifiques.

Cela sera ensuite injecté dans la méthode toArray() dans votre classe de ressources JSON lorsque la réponse est toArray() et vos méthodes personnalisées seront disponibles pour utilisation.

Classe de demande personnalisée

class SomeResource extends JsonResource
{
    public function toArray($request)
    {
        // $request is now instanceof ApiRequest

        return [
            'id' => $this->id,
            'locale' => $request->locale()
        ];
    }
}

Intergiciel API

class ApiMiddleware
{
    ...
    public function handle($request, $next)
    {
        $request = app()->instance('request', ApiRequest::createFrom($request));
        
        return $next($request);
    }
}

Ressource JSON

class ApiRequest extends Request
{
    ...
    public function locale()
    {
        $lang = $this->header('Accept-Language');
        return $lang ? $lang : 'uz';
    }
}


0 commentaires