apt get life

Life around technology

  • Technology
    • Guides
    • Linux
    • Development
      • Laravel
    • Misc
    • Raspberry Pi
  • Writing
  • Crafts
    • Crochet
    • Model Making
    • Painting
  • Privacy Policy
You are here: Home / Technology / Development / Laravel / Getting started with Laravel 5 & Dingo API: 4. Transformers

Getting started with Laravel 5 & Dingo API: 4. Transformers

2016/04/01 by sudo

Okay, so the last few lessons have got us up to the point where we’re able to send and receive data to the API, but there are some problems that need to be thought about:

  1. We’re exposing our database architecture – people can see orders have fields “order_ref”, “recipient_id”, etc.
  2. Our index functions are using “all()”, so they get all results from the database.
  3. We’re not validating our data before adding it to the database.
  4. We’re not authenticating users.

Lets star addressing these.

Transformers

Transformers are often used in APIs to obscure and abstract the database later from the responses provided to users. What this means is we “transform” what our database record field names are, and turn them into something else. Say in our database we were storing a field “recipient_name”. Instead of the API returning this to the user on a get request, we could use a transformer to return a different field name “name” for example. This obscures our database architecture so we’re not giving away our field names. Additionally, the abstraction here means that if we change our database architecture we’re not relying on API users to change their tools or utilities as well. We can change the database field names without worrying about what users are doing.

Variants Transformer

Once again, I’m going to start with the Variants as this is the smallest part of the API. All we do here is get variants, we don’t allow them to be added, updated or deleted. I’m going to start by looking at my project structure. At the moment we should have Http/Controllers/api and all of the controllers should be within this. It doesn’t really make sense to put transformers here, as they’re not controllers. Instead, I think we should make a new folder in the app directory, and lets version it too, incase different versions of the API use different transformers

mkdir app/Transformers
mkdir app/Transformers/V1

Now lets make a new VariantsTransformer.php file in that directory:

touch app/Transformers/V1/VariantsTransformer.php

Open that file in Atom and lets make our transformer

<?php

namespace App\Transformers\V1;

// We need to reference the Variants Model
use App\Variants;

// Dingo includes Fractal to help with transformations
use League\Fractal\TransformerAbstract;

class VariantsTransformer extends TransformerAbstract
{
    public function transform(Variants $variant)
    {
            // Specify what elements are going to be visible to the API
            return [
        'id' => (int) $variant->id,
                'size' => $variant->size,
                'brand' => $variant->brand,
                'type' => $variant->type,
                'color' => $variant->colour,
                'design' => $variant->design,
        ];
    }
}

All we’re doing here is transforming our Database collection into an array and returning it. The left hand side of the array define the keys that will be used for the JSON response. The right hand side gets the variant fields from the database. What this empowers you to do is hide database fields – like created at – so there’s no risk they’ll be visible to the API. Only items in this array will be returned in API requests. The next key advantage is that the variant database field name doesn’t have to match the API field name. This means that if there’s a major database update that needs to take place, you can update the transformer and not have to ask customers to re-map everything in their APIs.

In the VariantsController, we need to change our functions to adopt the new transformer

use App\Transformers\V1\VariantsTransformer;
public function index()
{
    // Return variants via the Variants Transformer.
    return $this->collection(Variants::all(), new VariantsTransformer);
}
public function show($id)
{
    return $this->item(Variants::find($id), new VariantsTransformer);
}

I’ve added the show function here to return an individual variant instead of a collection. You’ll also need to add the route for it to work:

$api->get('/variants/{id}', 'App\Http\Controllers\api\VariantsController@show');

Now when you call the variants controller in postman, you should see array values coming through as keys in JSON, not database field names.

Following this theme we need to update the Items controller, as well as creating an ItemsTransformer, and the orders controller along with an OrdersTransformer.

ItemsTransformer:

<?php

namespace App\Transformers\V1;

// We need to reference the Items Model
use App\Items;

// Dingo includes Fractal to help with transformations
use League\Fractal\TransformerAbstract;

class ItemsTransformer extends TransformerAbstract
{
    public function transform(Items $item)
    {
        // specify what elements are going to be visible to the API
        return [
            'id' => (int) $item->id,
            'item_ref' => $item->item_ref,
            'quantity' => (int) $item->quantity,
            'variant_id' => (int) $item->variant_id,
        ];
    }

    public function deform(Items $item)
    {
        // specify what elements are going to be visible to the API
        return [
            'id' => (int) $item->id,
            'item_ref' => $item->item_ref,
            'quantity' => (int) $item->quantity,
            'variant_id' => (int) $item->variant_id,
        ];
    }
}

ItemsController:

// At the top of the file, include the items tranformer
use App\Transformers\V1\ItemsTransformer;


// Update the index function to use the ItemsTransformer
public function index()
    {
        return $this->collection(Items::all(), new ItemsTransformer);
    }  

// Update the show function to use the items transformer
public function show($id)
    {
        return $this->item(Items::find($id), new ItemsTransformer);
    }

OrdersTransformer:

<?php

namespace App\Transformers\V1;

// We need to reference the Orders Model
use App\Orders;

// Dingo includes Fractal to help with transformations
use League\Fractal\TransformerAbstract;

class OrdersTransformer extends TransformerAbstract
{
    public function transform(Orders $order)
    {
        // specify what elements are going to be visible to the API
        return [
            'id' => (int) $order->id,
            'order_ref' => $order->order_ref,
            'recipient_id' => $order->recipient_id,
            'shipping_method' => $order->shipping_method,
        ];
    }

    public function deform(Orders $order)
    {
        // specify what elements are going to be visible to the API
        return [
            'id' => (int) $order->id,
            'order_ref' => $order->order_ref,
            'recipient_id' => $order->recipient_id,
            'shipping_method' => $order->shipping_method,
        ];
    }
}

OrdersController:

// Include the orders transformer
use App\Transformers\V1\OrdersTransformer;


// change the index function to use the transformer
public function index()
    {
        return $this->collection(Orders::all(), new OrdersTransformer);
    }

// Change the show function to use the transformer
public function show($id)
    {
        return $this->item(Orders::find($id), new OrdersTransformer);
    }

 

Save all of your work, git commit it if you’re being safe (I won’t show you how to do that now, you know how by now!) and run php artisan serve in order to start the local webserver. Use Postman to send requests to see if your updates are working.

 

One thing to note is that this only transforms the output of our database. Your incoming requests are not handled via the transformer. This is due to the design of fractal, and there is a discussion about it here if you’re interested. Instead of “transforming” input in this way, it’s suggested that models and validation are used instead. Next time we’ll look at running some validation on the input we’re sending to create new orders and order items, as well as working out how to apply the API architecture to the models.

 

Related

Filed Under: Development, Laravel, Technology Tagged With: API, Dingo API, Getting started with Laravel 5 & Dingo API, Laravel, larvel 5, Transformers

Recent Posts

  • System Hang on Ubuntu 24.04 “e1000_print_hw_hang”
  • Disable iLO on HP Microserver Gen8
  • Ubuntu Desktop 24.04 Change Wallpaper Settings
  • Customising Ubuntu Desktop 24.04
  • Remove domains from Let’s Encrypt using Certbot

Tags

API auditing crochet data recovery debian debudding development Dingo API docker email Getting started with Laravel 5 & Dingo API hard drive health HP Microserver KVM Laravel larvel 5 lenovo Linux Minion mint netgear nas networking network shares php PHP development Postfix raspberry pi review samba security SMART smartctl smartmontools smb testing traefik ubuntu ubuntu 18.04 ubuntu 20.04 ubuntu 22.04 ubuntu server vagrant Virtual machines xdebug xubuntu

© Copyright 2015 apt get life