This model provides an eloquent-like base class that can be used to build custom models for remote APIs.
Install using composer:
$ composer require gruz/remote-model
To implement a custom API request method in the model, simple extend the Gruz\RemoteModel\Model
class and use that extended model in the app models.
Example
<?php
namespace App;
use APIClient;
use Gruz\RemoteModel\Model;
class BaseModel extends Model
{
/**
* Make request through API.
*
* @return mixed
*/
protected function request($endpoint = null, $method, $params)
{
$endpoint = $endpoint ? $endpoint : $this->endpoint;
$results = APIClient::$method($endpoint, $params);
return $results ? $this->newInstance($results) : null;
}
}
$client = new Client();
$client->{ENDPOINT}()->{METHOD}();
ENDPOINT
The "snake case", plural name of the model class will be used as the endpoint name unless another name is explicitly specified. Using protected $endpoint = 'users';
at the top of the model, this is similar to the $table
variable in Laravel models.
METHOD This is the action to take on the endpoint. It can be anything that the wrapper class provides.
<?php
namespace PackageName\Api;
use PackageName\Api\Exception\BadMethodCallException;
use PackageName\Api\Exception\InvalidArgumentException;
class Client
{
/**
* The HTTP client instance used to communicate with API.
*
* @var HttpClient
*/
private $httpClient;
/**
* Instantiate a new client.
*/
public function __construct()
{
$this->httpClient = new HttpClient;
}
/**
* @param string $name
*
* @throws InvalidArgumentException
*
* @return ApiInterface
*/
public function api($name)
{
switch ($name)
{
case 'users':
$api = new Endpoints\Users($this);
break;
case 'reviews':
$api = new Endpoints\Reviews($this);
break;
default:
throw new InvalidArgumentException(sprintf('Undefined api instance called: "%s"', $name));
}
return $api;
}
/**
* @param string $name
*
* @throws InvalidArgumentException
*
* @return ApiInterface
*/
public function __call($name, $args)
{
try {
return $this->api($name);
}
catch (InvalidArgumentException $e) {
throw new BadMethodCallException(sprintf('Undefined method called: "%s"', $name));
}
}
}
This is just to give an example.
<?php
namespace PackageName\Api\Endpoints;
use PackageName\Api\Client;
class Users
{
/**
* The client.
*
* @var \PackageName\Api\Client
*/
protected $client;
/**
* @param \PackageName\Api\Client $client
*/
public function __construct(Client $client)
{
$this->client = $client;
}
/**
* Register a user.
*
* @param array $params
*
* @return array
*/
public function add(array $params)
{
return $this->client->post('users', $params);
}
/*
* Update user data
*
* @param array $params
*
* @return object
*/
public function update(array $params)
{
return $this->client->patch('users/self', $params);
}
/**
* Get extended information about a user by its id.
*
* @param string $user_id
*
* @return array
*/
public function find($user_id)
{
return $this->client->get('users/'.rawurlencode($user_id));
}
}
An API client must be set before any data can be retrieved . To set the client use the static Model::setClient
method.
Below is an example of the service provider way of setting the client.
<?php
namespace App\Providers;
use Gruz\RemoteModel\Model;
use PackageName\API\Client;
use Illuminate\Support\ServiceProvider;
class ApiServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application events.
*
* @return void
*/
public function boot()
{
Model::setClient($this->app['apiclient']);
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->singleton('apiclient', function () {
return new Client(); // API Client
});
}
/**
* Get the services provided by the provider.
*
* @return string[]
*/
public function provides()
{
return [
'apiclient'
];
}
}
<?php
namespace App;
use DateTime;
use Gruz\RemoteModel\Model as BaseModel;
class User extends BaseModel
{
protected $hidden = [
'password'
];
protected $casts = [
'age' => 'integer'
];
public function save()
{
return API::post('/items', $this->attributes);
}
public function setBirthdayAttribute($value)
{
$this->attributes['birthday'] = strtotime($value);
}
public function getBirthdayAttribute($value)
{
return new DateTime("@$value");
}
public function getAgeAttribute($value)
{
return $this->birthday->diff(new DateTime('now'))->y;
}
}
Using model
$item = new User([
'name' => 'john'
]);
$item->password = 'bar';
echo $item; // {"name":"john"}