Laravel library to convert your models into API responses.

Overview

Laravel Scene

Laravel library to convert your models into API responses.

Why a transformation library?

By default you can use the default implementation which converts your models to json based on toArray(). This approach starts to get messy once you start having different responses for your models for different endpoints (Eg: based on user permissions, endpoint types, etc).

This library also allows you to seperate your object transformation logic from your Models. Your models do not need to concern themselves with how they get represented over the wire at different endpoints. The same way you can use the transformers to transform objects or arrays. They don't have to be eloquent models.

Note: Laravel API Resource is a great start if you're using >= 5.5. In that case you should carefully evaluate your needs and how your complexity will grow before choosing this.

Installation

Install using composer.

composer require azaan/laravel-scene

Usage

Create a transformer class to transform your model. You can use the same transform method to transform an array/collection of objects or a single object.

Example.

class PersonTransformer extends SceneTransformer {
    
    /**
     * Eloquent relations to preload
     *
     * Note: It will only get preloaded if it already isnt.
     */
    protected function getPreloadRelations()
    {
        return [
            // preload nested relations of posts defined in PostTransformer
            'posts'   => SceneTransformer::PRELOAD_RELATED,
            
            // load addresses if $this->showMin is truthy
            'address' => $this->showMin,
            
            // preload createdBy relation
            'createdBy',
        ];
    }

    /**
     * Structure transformations.
     *
     * @return array structure
     */
    protected function getStructure()
    {
        return [
            'id',
            'name',
            'email',
            'fullname',
            'actions',
            'address' => [
                'name',
                'street',
            ],
            'status' => new ArrayMapTransform([
                'active'        => 'Active',
                'blocked'       => 'Blocked',
                'temp-disabled' => 'Temporarily Disabled',
            ]),
            'posts' => PostTransformer::createMinTransformer(),
            
            // return the field 'joined_date' as 'date',
            'date' => 'joined_date',
            
            'created_at' => new DateFormatTransform('Y-m-d'),
        ];
    }
    
    /**
     * Structure to use when returning multiple objects
     *
     * @return array structure
     */
    protected function getMinStructure()
    {
        return [
            'id',
            'name',
            'email',
            
            // add extra key only when some condition meets
            'extra' => $this->when($this->someCondition, 'extra'),
        ];
    }

    protected function getFullname(Person $person)
    {
        return $person->first_name . ' ' . $person->last_name;
    }
    
    protected function getActions(Person $person)
    {
        // call service methods to figure out what actions the user can perform
        
        return ['can_edit', 'can_update'];
    }
}

Now in your controller method.

    public function all()
    {
        $people = $this->personService->getAllPeople();

        $transformer = PersonTransformer::createMinTransformer();
        return SceneResponse::respond($people, $transformer);
    }
    
    public function show($id)
    {
        $person = $this->personService->getPersonByIdOrFail($id);
        
        $transformer = new PersonTransformer();
        return SceneResponse::respond($person, $transformer);
    }

You can use the SceneRespond::respond method with either a collection of data or a single object. The transformer will handle it appropriately. It can also handle a LengthAwarePaginator.

In this example it is assumed your model (Person) has the attributes id, name, email and created_at. For the field fullname the method getFullname is used to resolve the value.

Keys are resolved using the following steps:

  1. If a getter method exists in the transformer it is called
  2. Check if the key exists on the object
  3. Check if a getter method for the key exists on the object
  4. Returns null

Nesting Transformers

You can nest transformers within another transformer. For example if you had a Company model with a relation called owner which resolves to a Person object your Company transformer can look like this.

class CompanyTransformer extends SceneTransformer {
    /**
     * Structure transformations.
     *
     * @return array structure
     */
    protected function getStructure()
    {
        return [
            'id',
            'name',
            'owner' => new PersonTransformer()
        ];
    }
}

This way your transform logic for every model is compartmentalised and can easily be reused.

Hooks

Several hook methods are defined which you can override to get desired behaviour.

Injecting from Laravel Container

If you need to inject classes from the laravel container you can override the method inject. All parameters of the inject method will be resolved from the Laravel Container.

Minimum Structure

When you're responding with a collection of objects (Eg: for a listing) you might want to respond with different fields. You can use this by overriding the method getMinStructure(). In this case when you're instantiating the transformer in the controller use the method ::createMinTransformer()

Preload Eloquent relations

When responding with a collection of eloquent objects and accessing relations which haven't been loaded it will lead to the N+1 query problem. You can override the method getPreloadRelations and return an array of relations to be preloaded by the transformer. The transformer will take care of only loading the relations which haven't been loaded and will load them whenever appropriate. You can also use dot notation to preload nested relations. (Eg: person.address)

Pre process

Override the methods preProcessSingle and preProcessCollection to run any pre process logic before the transformer starts transforming the objects.

Null State

Override the method getNullState to return the default state if the object is null. Default implementation returns null

Ordering

Usually it is better to do your ordering before passing into the transformer. However in cases where you require to order by a field which is only present after the transformation you can override getOrderBy to provide ordering. You should return the field name as a string to order by. If you require direction return an array. (Eg: ['field_name', 'DESC'])

Post process hook.

To do any changes after all transformations you can override the method transformObject. The transformed output array will be passed in as the first argument and original object as the second.

Licence

MIT

You might also like...
This PHP library will help you to work with your Pinterest account without using any API account credentials.
This PHP library will help you to work with your Pinterest account without using any API account credentials.

Pinterest Bot for PHP A PHP library to help you work with your Pinterest account without API credentials. The Pinterest API is painful: receiving an a

The 1Password Connect PHP SDK provides your PHP applications access to the 1Password Connect API hosted on your infrastructure and leverage the power of 1Password Secrets Automation

1Password Connect PHP SDK The 1Password Connect PHP SDK provides your PHP applications access to the 1Password Connect API hosted on your infrastructu

Laravel api tool kit is a set of tools that will help you to build a fast and well-organized API using laravel best practices.
Laravel api tool kit is a set of tools that will help you to build a fast and well-organized API using laravel best practices.

Laravel API tool kit and best API practices Laravel api tool kit is a set of tools that will help you to build a fast and well-organized API using lar

A simple way of authenticating your RESTful APIs with API keys using Laravel

ApiGuard This package is no longer maintained This package is no longer maintained as Laravel already has a similar feature built-in since Laravel 5.8

📒📚Generate beautiful interactive documentation and Open-API 3.0 spec file from your existing Laravel app.
The efficient and elegant JSON:API 1.1 server library for PHP

Woohoo Labs. Yin Woohoo Labs. Yin is a PHP framework which helps you to build beautifully crafted JSON:APIs. Table of Contents Introduction Features W

The efficient and elegant, PSR-7 compliant JSON:API 1.1 client library for PHP

Woohoo Labs. Yang Woohoo Labs. Yang is a PHP framework which helps you to communicate with JSON:API servers more easily. Table of Contents Introductio

A PHP library for the CoinMarketCap API designed to be easy to use.

Help wanted: I don't have enough time to keep updating this library, if you can, don't be shy. Pull requests are welcome. PHP CoinMarketCap API This p

PHP library for Qvapay API integration.

Php library for Qvapay API This PHP library facilitates the integration of the Qvapay API. Sign up on QvaPay Create your account to process payments t

Comments
  • Added additional check on method_exists() supporting php8.0

    Added additional check on method_exists() supporting php8.0

    Method method_exists('ObjectOrClassName', 'methodName) earlier not used to throw an error if we pass anything to first param instead of Object or Class name as string. In PHP8.0 function throws an TypeError exception.

    Here is the test evaluating same on major PHP version https://3v4l.org/pRbos

    opened by vrajroham 0
Releases(v2.0.1)
Owner
Ahmed Azaan
Ahmed Azaan
Raidbots API wrapper which incorporates existing reports and static data into your project.

Raidbots API Raidbots API wrapper which incorporates existing reports and static data into your project. Usage use Logiek\Raidbots\Client; $client =

Logiek 2 Dec 23, 2021
Jane is a set of libraries to generate Models & API Clients based on JsonSchema / OpenAPI specs

Jane is a set of libraries to generate Models & API Clients based on JsonSchema / OpenAPI specs Documentation Documentation is available at http://jan

Jane 438 Dec 18, 2022
Airbrake.io & Errbit integration for Symfony 3/4/5. This bundle plugs the Airbrake API client into Symfony project

AmiAirbrakeBundle Airbrake.io & Errbit integration for Symfony 3/4/5. This bundle plugs the Airbrake API client into Symfony project. Prerequisites Th

Anton Minin 8 May 6, 2022
Simple and effective multi-format Web API Server to host your PHP API as Pragmatic REST and / or RESTful API

Luracast Restler ![Gitter](https://badges.gitter.im/Join Chat.svg) Version 3.0 Release Candidate 5 Restler is a simple and effective multi-format Web

Luracast 1.4k Dec 14, 2022
Easily integrate custom-made NPS (Net Promoter Score) into your application

Laravel NPS Easily integrate custom-made NPS (Net Promoter Score) to your application. Installation You can install the package via composer: composer

H-FARM Innovation 48 Oct 27, 2022
Provides tools for building modules that integrate Nosto into your e-commerce platform

php-sdk Provides tools for building modules that integrate Nosto into your e-commerce platform. Requirements The Nosto PHP SDK requires at least PHP v

Nosto 5 Dec 21, 2021
🍞🧑‍🍳 An on-the-fly GraphQL Schema generator from Eloquent models for Laravel.

An on-the-fly GraphQL Schema generator from Eloquent models for Laravel. Installation Quickstart Model schemas Installation This package requires PHP

Scrn 100 Oct 16, 2022
微信支付 API v3 的 PHP Library,同时也支持 API v2

微信支付 WeChatPay OpenAPI SDK [A]Sync Chainable WeChatPay v2&v3's OpenAPI SDK for PHP 概览 微信支付 APIv2&APIv3 的Guzzle HttpClient封装组合, APIv2已内置请求数据签名及XML转换器,应

null 275 Jan 5, 2023
Provides a Middleware to integration Tideways into Symfony Messenger Processing

Tideways Middleware for Symfony Messenger This package is currently under development and might be moved into the Tideways PHP Extension or stay indep

Tideways 6 Jul 5, 2022
Http-kernel - The HttpKernel component provides a structured process for converting a Request into a Response.

HttpKernel Component The HttpKernel component provides a structured process for converting a Request into a Response by making use of the EventDispatc

Symfony 7.8k Jan 9, 2023