Restler

API Framework without learning curve

ANDY TRUONG

Twitter: thehongtt

Email: andy at GO1.com.au

Start coding

composer.json

{
    "require": {
        "luracast/restler": "~3.0.0"
    }
}

public/index.php

Front controller

<?php

require_once __DIR__ . '/../vendor/autoload.php';
(new MySoftware\Application())->handle();

src/*.php

Application

<?php

namespace MySoftware {
    class Application extends \Luracast\Restler\Restler {
        public function __construct() {
            $this->addAPIClass('MySoftware\Hello');
            $this->setSupportedFormats('JsonFormat', 'XmlFormat');
        }
    }
    
    class Hello { // HEY: our controller has no dependency
        /**
         * @url GET /{name}/{age}
         * @param string $name
         * @return string
         */
        public function sayHello($name = 'PHP', $age = 19) {
            return ["name" => $name, "age" => $age];
        }
    }
}

Versioning

Provide new logic

<?php

namespace MySoftware\v1 {
  class Hello {
    /**
     * @url GET /{name}/{age}
     * @param string $name
     * @return string
     */
    public function sayHello($name = 'PHP', $age = 19) {
      return ["name" => $name, "age" => $age];
    }
  }
}

namespace MySoftware\v2 {
  class Hello {
    /**
     * @url GET /{name}/{age}
     * @param string $name
     * @return string
     */
    public function sayHello($name, $age) {
      return ['status' => 'OK', 'output' => "Hello {$name} {$age}!"];
    }
  }
}

Config Application

<?php

namespace MySoftware;

class Application extends \Luracast\Restler\Restler {
    public function __construct() {
        $this->setSupportedFormats('JsonFormat', 'XmlFormat');

        // Support multiple versions
        Luracast\Restler\Defaults::$apiVendor = "MySoftware";
        Defaults::$useUrlBasedVersioning = true;
        Luracast\Restler\Defaults::$useVendorMIMEVersioning = true;

        $this->addAPIClass('MySoftware\Hello');
        $this->setAPIVersion(2);
    }
}

Detect version

using URL

GET /v1/hello/PHP/19 <---- \MySoftware\v1\Hello::sayHello
GET /hello/PHP/19    <---- \MySoftware\v2\Hello::sayHello
GET /v2/hello/PHP/19 <---- \MySoftware\v2\Hello::sayHello

Detect version

using Vendor mime

# Use version 1
curl example.com/hello/PHP/19 \
    -H 'Accept: application/MySoftware-v1+json'



# Use version 2
curl example.com/hello/PHP/19 \
    -H 'Accept: application/MySoftware-v2+json'

Authentication

Provide a handler

<?php

namespace MySoftware {
  use Luracast\Restler\iAuthenticate\iAuthenticate;

  class Authentication implements iAuthenticate
  {
    const KEY = 'hello-restler';

    public function __getWWWAuthenticateString() {
      return 'Query name="api_key"';
    }

    public function __isAllowed() {
      return !empty($_GET['api_key']) && self::KEY === $_GET['api_key'];
    }
  }
}

Update App

<?php

namespace MySoftware;

class Application extends \Luracast\Restler\Restler {
  public function __construct() {
    \Luracast\Restler\Defaults::$apiVendor = "MySoftware";
    \Luracast\Restler\Defaults::$useUrlBasedVersioning = true;
    \Luracast\Restler\Defaults::$useVendorMIMEVersioning = true;

    $this->addAPIClass('MySoftware\Hello');
    $this->setAPIVersion(2);

    // Add auth handler
    $this->addAuthenticationClass('MySoftware\Authentication');
  }
}

Protect a resource

<?php

namespace MySoftware\v2 {
  class Hello {
    /**
     * @url GET /{name}/{age}
     * @param string $name
     * @return string
     */
    protected function sayHello($name, $age) {
      return ['status' => 'OK', 'output' => "Hello {$name} {$age}!"];
    }

    /**
     * @access protected
     * @url GET /time
     */
    public function useAnnotation() {
      return ['status' => 'OK', 'time' => time()];
    }
  }
}

Documentation

Update App

<?php

namespace MySoftware {
  class Application extends \Luracast\Restler\Restler {
    public function __construct() {
        $this->addAuthenticationClass('MySoftware\Authentication');
        $this->setAPIVersion(2);
    
        \Luracast\Restler\Defaults::$apiVendor = "MySoftware";
        \Luracast\Restler\Defaults::$useUrlBasedVersioning = true;
        \Luracast\Restler\Defaults::$useVendorMIMEVersioning = true;
    
        $this->addAPIClass('Resources'); // <--- add Resources
        $this->addAPIClass('MySoftware\Hello');
    }
  }
}

Build Swagger UI

follow Restler-API-Explorer

ln -s \
    ../vendor/luracast/restler/public/examples/_008_documentation/explorer 
    public/api

or just

go to…

here.me/api/index.html

Ideas?

Restler

By Andy Truong

Restler

  • 4,226