activeresource The RESTful equivalent to ActiveRecord

ActiveResource for Yii ¶

  1. Requirements
  2. NOTES
  3. Changes
  4. Version 0.7 (01-16-2012):

This extension could be considered as the "RESTful" equivalent to Yii's CActiveRecord class. While CActiveRecord is using a database to store and manipulate data ActiveResource is using a REST service.

This concept allows you to use Yii's ActiveRecord goodness (like validation, easy formular inputs via ActiveForms etc.) with webservices that expose their resources via REST (e.g.: your own RESTful API)

Requirements ¶

Basic tests done with Yii 1.1.8 but should work for lower versions too

PHP 5.3 recommended

INSTALL: ¶

  1. Get the extension at ActiveResource on Github
  2. Add the extension to Yii by placing it in your application's extension folder (for example '/protected/extensions')
  3. Edit your applications main.php config file and add 'application.extensions.EActiveResource.*' to your import definitions
  4. Add the configuration for your resources to the main config
'activeresource'=>array(
    'class'=>'EActiveResourceConnection',
    'site'=>'http://api.aRESTservice.com',
    'contentType'=>'application/json',
    'acceptType'=>'application/json',
    'queryCacheId'=>'SomeCacheComponent'
)
  1. Now create a class extending EActiveResource like this (don't forget the model() method!):
class Person extends EActiveResource
     {
     /* The id that uniquely identifies a person. This attribute is not defined
      * as a property      
      * because we don't want to send it back to the service like a name, surname or    
      * gender etc.
      */
     public $id;

     public static function model($className=__CLASS__)
     {
         return parent::model($className);
     }
     
     /* Define the resource property of this class */
     public function rest()
     {
         return CMap::mergeArray(
	     parent::rest(),
	     array(
		'resource'=>'people',
             )
	);
     }

     /* Let's define some properties and their datatypes*/
     public function properties()
     {
         return array(
             'name'=>array('type'=>'string'),
             'surname'=>array('type'=>'string'),
             'gender'=>array('type'=>'string'),
             'age'=>array('type'=>'integer'),
             'married'=>array('type'=>'boolean'),
             'salary'=>array('type'=>'double'),
         );
     }

     /* Define rules as usual */
     public function rules()
     {
         return array(
             array('name,surname,gender,age,married,salary','safe'),
             array('age','numerical','integerOnly'=>true),
             array('married','boolean'),
             array('salary','numerical')
         );
     }

     /* Add some custom labels for forms etc. */
     public function attributeLabels()
     {
         return array(
             'name'=>'First name',
             'surname'=>'Last name',
             'salary'=>'Your monthly salary',
         );
     }
 }

Usage: ¶

/* GET to http://api.example.com/person/1 and populates a single Person model*/
    $person=Person::model()->findById(1);

    /* GET to http://api.example.com/person and populating Person models */
    $persons=Person::model()->findAll();

    /* create a resource*/
    $person=new Person;
    $person->name='A name';
    $person->age=21;
    $person->save(); POST request. Returns false if the model doesn't validate

    /* Updating a resource (sending a PUT request)
    $person=Person::model()->findById(1);
    $person->name='Another name';
    $person->save(); //PUT request. Returns false if the model doesn't validate

    //or short version
    Person::model()->updateById(1,array('name'=>'Another name'));

    /* DELETE a resource */
    $person=Person::model()->findById(1);
    $person->destroy(); //DELETE to http://api.example.com/person/1

    //or short version
    Person::model()->deleteById(1);

    //setting attributes
    $person->attributes=$_POST['Person'];
    if($person->save())
        echo 'yipiie'; //model validated and was saved/updated

Additional information ¶

  1. ActiveResource wiki
  2. Forum-thread

NOTES ¶

  1. This is an early release and not perfect. Don't be mad if it is still buggy. Please report bugs at Github instead or drop me a line on Haensel at Twitter. Help would be much appreciated (a "fake" REST API allowing tests would be nice)

Changes ¶

Version 0.7 (01-16-2012): ¶

1. Separation of connection information and resource information: ¶

The EActiveResourceConnection component now only holds information that is used by all resources using it as a connection like site,auth,ssl,contentType,acceptType. Resource specific information has to be defined in the rest() method of each resource.

'activeresource'=>array(
            	'class'=>'EActiveResourceConnection',
        		'site'=>'http://api.aRESTservice.com',
        		'contentType'=>'application/json',
            	'acceptType'=>'application/json',
            	'auth'=>array(
            	'type'=>'basic', //or digest
            		'username'=>'#####',
            		'password'=>'#####'
            	)
       		)),
       		'queryCacheId'=>'SomeCacheComponent')
       		
       		///in the resource itself
       		public function rest()
    		{
		 		return CMap::mergeArray(
		 			parent::rest(),
		 			array(
		 				'resource'=>'people',
		 			)
		 		);
     		}

By default all resources use the "activeresource" component. If you want to use more than one service you'll have to define additional components and override the connectionName() method. Here's an example:

'mySecondService'=>array(
            	'class'=>'EActiveResourceConnection',
        		'site'=>'http://api.aRESTservice.com',
        		'contentType'=>'application/json',
            	'acceptType'=>'application/json',
            	'auth'=>array(
            	'type'=>'basic', //or digest
            		'username'=>'#####',
            		'password'=>'#####'
            	)
       		)),
       		'queryCacheId'=>'SomeCacheComponent')
       		
       		///in the resource itself
       		public function connectionName()
    		{
		 		return 'mySecondService';
     		}
2. Separation between queries and data manipulating requests ¶

In previous versions one could cache PUT, DELETE, POST requests which could lead to strange behaviors. By default, caching is only used by the finder methods

3. BeforeFind events ¶

All finder methods now fire a beforeFind event before they are executed.

4. Content type and accept type changed according to the convention ¶

The Connection properties contenttype and accepttype are now called contentType and acceptType according to the known Yii naming convention.

5. Allow or deny null values when sending requests ¶

If you don't want to send null values/empty strings you can now define 'allowNullValues'=>false in your connection component configuration. This way all empty strings and null values won't be sent.

24 0
37 followers
250 downloads
Yii Version: 1.1
License: BSD-2-Clause
Category: Web Service
Tags: rest
Developed by: Haensel Haensel
Created on: Jul 6, 2011
Last updated: 13 years ago

Related Extensions