indatus/trucker

A simple active resource implementation written in PHP to consume any REST API

v1.0.2 2014-07-31 15:16 UTC

This package is not auto-updated.

Last update: 2024-11-04 07:13:27 UTC


README

Latest Stable Version Total Downloads Build Status Coverage Status Dependency Status

Trucker is a PHP package for mapping remote API resources (usually RESTful) as models in an ActiveResource style. The benefit is easier use of remote APIs in a fast and clean programming interface.

<?php

class Product extends Trucker\Resource\Model {} //create a class to use

$p = new Product(['name' => 'My Test Product']);
$success = $p->save(); //create a new entity

$found = Product::find(1); //find an existing entity

$found->name = 'New Product Name';
$success = $found->save(); //update an entity

$success = $found->destroy(); //destroy an entity

$results = Product::all(); //find a collection

This project is looking for new maintainers. Please open an issue if interested.

README Contents

Installation

Requirements

  • Any flavour of PHP 5.4+ should do

Install With Composer

You can install the library via Composer by adding the following line to the require block of your composer.json file:

"indatus/trucker": "dev-master"

For Laravel 5 support, see the laravel-5 branch

Next run composer install, now you need to publish the config files.

Trucker's config files are where you'd define constant things about the API your interacting with, like the end-point, what drivers you want to use etc.

Configure in Laravel

Trucker works well with the Laravel framework. If your using Trucker within Laravel, you just need to run the following command to publish the Trucker config files to the app/config/packages/indatus/trucker folder.

php artisan config:publish indatus/trucker

The final step is to add the service provider. Open app/config/app.php, and add a new item to the providers array.

'Trucker\TruckerServiceProvider'

Now you should be ready to go.

Configure outside Laravel

If your using Trucker outside Laravel you just need to create the .trucker folder in your project root and copy the package's config files there. Here's the *nix command for that.

mkdir .trucker && cp vendor/indatus/trucker/src/config/* .trucker/

Configuration Options

Trucker comes with its own configuration file where you can specify options that are constant to your configuration.

Auth (auth.php)

Supported Option Details:

Error Handler (error_handler.php)

Supported Option Details:

Query Condition (query_condition.php)

When making a request for a collection you may specify conditions similar to a SQL WHERE clause. These will be sent along with your request as an array parameter which contains a grouping of key / values that define the set of conditions.

Supported Option Details:

The resulting GET parameters may look something like:

search[0][property]=someProperty
search[0][operator]=<
search[0][value]=1234
search[1][property]=anotherProperty
search[1][operator]=LIKE
search[1][value]=someString
logical_operator=AND

Request (request.php)

Supported Option Details:

Resource (resource.php)

Response (response.php)

Wildcards may be used to match what an http code starts with (e.g - 20*).

Supported Option Details:

Result Order (result_order.php)

Supported Option Details:

Transporter (transporter.php)

Creating an entity

Now you can create an entity object for a noun in your API (this is the minimum code you'll need to get started):

<?php
class Product extends Trucker\Resource\Model
{

}

Trucker uses convention over configuration, so it will infer what the URI should be based on your class name. In the example of 'Product' the URI will be assumed to be /products.

Working with your entity

Now that you have Trucker object you can use it with CRUD operations as you may expect you would with an ORM.

Fetching Records

Trucker splits fetching records over your API into 2 categories. Getting an instance and getting a collection.

Fetch an Instance

If you have an entity where you know the value of it's identity_property you can fetch it with the find() method.

$p = Product::find(1);

Optional 2nd arg: find() takes a second parameter as well that allows you to pass in an arbitrary associative array that you want to be converted into query string arguments that get sent with the request.

Optional 3rd arg: find() takes a third parameter as well that allows you to pass in an object of the class your finding on with properties that have been set at runtime. The find() function will use this object for interperting the URL if given, other wise it will call new static; on the class find() is called on.

Fetch a Collection

When you want to fetch a collection of records you can use the all() function.

$results = Product::all();

The all() function takes arguments that allow you to specify conditions on the results that you'll get back. How the request will be made to the API depends on collection_query_condition_driver and collection_result_order_driver you are using.

Fetch a collection using query conditions and result ordering
$conditions = ConditionFactory::build();
$conditions->addCondition('name', '=', 'Roomba 650');
$conditions->addCondition('vendor', '=', 'Irobot');
$conditions->addCondition('price', '>=', 10000);
$conditions->setLogicalOperator($conditions->getLogicalOperatorAnd());

$order = ResultOrderFactory::build();
$order->setOrderByField('name');
$order->setOrderDirection($order->getOrderDirectionDescending());

$results = Product::all($conditions, $order);

Note: You may also provide a third array parameter to the all() function containing an associative array of values to include in the request as querystring parameters.

Create, Update & Destroy Operations

Create

$attributes = ['name' => 'XYZ Headphones', 'vendor' => 'Acme', 'price' => '10000'];

//pass attributes to the constructor
$p = new Product($attributes);

//or use the fill() method
$p = new Product;
$p->fill($attributes);

//get the attributes back if you want to see them
print_r($p->attributes());
// => ['name' => 'XYZ Headphones', 'vendor' => 'Acme', 'price' => '10000']

//maybe you want to see a particular property
echo $p->name; // => XYZ Headphones

//or modify a property
$p->name = "ABC Headphones";

//save the object over the API.  The save() method will create or update 
//the object as necessary.  It returns true or false based on success.
$success = $p->save(); 

if ($success) {

  //the identity property is set back on the object after it is created
  echo "Saved product '{$p->name}' with ID: ". $p->getId();

} else {

  //maybe you want to print out the errors if there were some
  echo "Errors: ". implode(", ", $p->errors());
  // => ['Category is required', 'Cost must be greater than 0']
}

Update

Update works quite similar to the create functionality, from the code perspective it is nearly identicial.

$p = Product::find(1);
$p->name = "My Product";

if ($p->save()) {
   echo "Updated!";
} else {
   echo "Error: ". implode(", ", $p->errors());
}

Destroy

The destroy function requires an existing instance, and returns a boolen based on the success of the request.

$p = Product::find(1);

if ($p->destroy()){
  echo "Deleted product: {$p->name}";
} else {
  echo "Error deleting product: {$p->name}";
  echo "Errors: ". implode(", ", $p->errors());
}

Customizing Entities

Trucker uses sensible defaults for its default configuration, but allows you to customize it via the config settings. Additionally you can override the config settings for an individual class by overriding properties on the concrete implementation; by setting values at runtime on the class or in the config.

Setting concrete class properties.

The following fields can be set on a class implementation to override interpreted values, default values or just to define the class functionality.

Example:

<?php
class Product extends Trucker\Resource\Model
{
  protected $uri = "/small_electronic_products";
  protected $guarded = "price,sale_price";
  protected $fileFields = "picture";
}

Setting runtime properties

There may be situations where you can't set a property in the concrete class implementation because it's value is variable and changes at runtime. For this situation you could set the property before it is used in a request.

Example:

<?php
$vendor_id = 9876;
$p = new Product;
$p->nestedUnder = "Vendor:{$vendor_id}";
$found = Product::find(1, [], $p);
//will hit /vendors/9876/products/1

Setting config values at runtime

There may be times where you need to change values that are set in your Trucker config files at runtime before a request is made that uses those values. You can use Trucker's config manager for this.

Note: If your using Trucker in Laravel you'll want to alias the Trucker config manager Config to something different like TruckerConfig so it doesn't conflict with Laravel's own Config class.

Example:

<?php
use Trucker\Facades\Config as TruckerConfig;

TruckerConfig::set('auth.basic.username', $someUsername);
TruckerConfig::set('auth.basic.password', $somePassword);
$found = Product::find(1);