New Yii REST Tutorial

Thanks for the great tutorial. My REST client for Firefox is returning the data from the database, but I need to initialize my data before I load app.js.

<script type=‘text/javascript’ src=’<?php echo Yii::app()->request->baseUrl; ?>/scripts/js/jquery-1.7.1.min.js’><script>

<script type=‘text/javascript’ src=’<?php echo Yii::app()->request->baseUrl; ?>/scripts/js/underscore-min.js’></script>

<script type=‘text/javascript’ src=’<?php echo Yii::app()->request->baseUrl; ?>/scripts/js/backbone-min.js’></script>

<script>

var trucks = < I need to get the JSON string from ApiController via api/trucks >

</script>

<script type=‘text/javascript’ src=’<?php echo Yii::app()->request->baseUrl; ?>/scripts/js/app.js’></script>

Any help is appreciated.

Sorry for responding to my own post, this works, but is there a better way?

<script>

var trucks = [];

$.ajax({

url: &quot;/index.php/api/trucks&quot;,


dataType: &quot;json&quot;,


method: &quot;GET&quot;,


async: false,


success: function(response){


	trucks = response;


}


});

</script>

<script type=‘text/javascript’ src=’<?php echo Yii::app()->request->baseUrl; ?>/scripts/js/app.js’></script>

How to authentication

I use RESTClient addon Firefox but I dont know how to set header of it.

I try Content-Type: application/json and body HTTP_X_ASCCPE_PASSWORD=emo&HTTP_X_ASCCPE_USERNAME =aaaaaaaaaaaa

But it not return true

In RESTClient, use the ‘headers’ functionality:

  • menu ‘Headers’

  • ‘Custom Header’

  • ‘Name’ : X_ASCCPE_PASSWORD

  • ‘Value’ : emo

And the same with USERNAME.

HTH,

JM.

What is the body you get back?

The user emo:emo exists in you User table?

You could put some traces in code (Yii::trace()) and activate logging (see http://www.yiiframew.../topics.logging)

JM.

The user comes from a table in the database. Until you setup this, try following: in the function _checkAuth() (in the protected/controllers/ApiController.php file), that should look like this:




private function _checkAuth() 

{ 

	// Check if we have the USERNAME and PASSWORD HTTP headers set? 

	if(!(isset($_SERVER['HTTP_X_'.self::APPLICATION_ID.'_USERNAME']) and isset($_SERVER['HTTP_X_'.self::APPLICATION_ID.'_PASSWORD']))) { 

		// Error: Unauthorized 

		$this->_sendResponse(401); 

	} 

	$username = $_SERVER['HTTP_X_'.self::APPLICATION_ID.'_USERNAME']; 

	$password = $_SERVER['HTTP_X_'.self::APPLICATION_ID.'_PASSWORD']; 

	// Find the user 

	$user=User::model()->find('LOWER(username)=?',array(strtolower($username))); 

	if($user===null) { 

		// Error: Unauthorized 

		$this->_sendResponse(401, 'Error: User Name is invalid'); 

	} else if(!$user->validatePassword($password)) { 

		// Error: Unauthorized 

		$this->_sendResponse(401, 'Error: User Password is invalid'); 

	} 

} // }}}  




insert following line before the ‘// Find the user’ line:




if ($username === "emo" && $password === "emo") return;



JM.

Glad it works!

Sure, if you already have created some kind of user table, tweak the code so as to use your data:

Remove the line I told you to insert (was for test), and adapt the line




$user=User::model()->find('LOWER(username)=?',array(strtolower($username)));



to match your model.

Then modify the password validation (currently ‘else if(!$user->validatePassword($password))’) to whatever you need.

As an example (yours will probably differ), here is how I modified it (I’m using the Users extension):




        	$identity = new UserIdentity($username, $password);

        	$identity->authenticate();

        	if ($identity->errorCode === UserIdentity::ERROR_NONE) {

                	Yii::app()->user->login($identity, 0);

        	} else {

            	$this->_sendResponse(401, 'Invalid credentials');

        	}




Hi all,

I just followed this tutorial. It’s now working on my personal laptop(localhost) but when I try to upload it to the server (godaddy.com) I just doesn’t work. I get an error that says ‘no input file specified’. 404 Not Found. If i remove the urlFormat It just work perfectly, I means the controller and ActiveRecords ). Doesn’t anyone knows why this it?

Thanks a lot.

j

THANKS!, I’m just starting on Yii and i was wondering how to implement a REST service on it. Thanks a lot man!

Also it will be helpfull if you describe how to do in such case

have 2 URL

site.ru/user/create(for HTML)

and site.ru/user/create.json(for JSON)

but only one controller should be (he will render HTML or JSON

Does anyone here tried this REST extension – https://github.com/weavora/wrest ?

I found the syntax very neat. Like you, i want to develop a RESTful app with YII.

Any feedback on this extension is really appreciated.

Thanks.

Help me please

I tried to do follow this

But it return

Status Code: 401 Unauthorized


Connection: Keep-Alive


Content-Length: 795


Content-Type: text/html


Date: Mon, 03 Dec 2012 11:27:53 GMT


Keep-Alive: timeout=5, max=100


Server: Apache/2.4.2 (Win32) OpenSSL/1.0.1c PHP/5.4.4


X-Powered-By: PHP/5.4.4

When I didn’t use $this->_checkAuth();

It’s work. I don’t know how can I fix it.

I’ve never used web service before, it’s first time for me.

Thank a lot.

Hi

I’m using RESTClient Firefox Add-ons

I’ve set Custom Header.

Name: HTTP_X_ASCCPE_USERNAME

Password: demo

and again another custom header with:

Name: HTTP_X_ASCCPE_PASSWORD

Password: demo

I’m sure that a user with username=demo and password=demo is exist in Database, but I’ve got this error:







    Status Code: 401 Unauthorized

    Connection: Keep-Alive

    Content-Length: 762

    Content-Type: text/html

    Date: Sat, 16 Mar 2013 07:34:04 GMT

    Keep-Alive: timeout=5, max=100

    Server: Apache/2.4.2 (Win64) PHP/5.4.3

    X-Powered-By: PHP/5.4.3






What should I do?

Thanks a lot

Hi,

check this : http://stackoverflow.com/questions/10453918/how-to-set-header-for-restful-api-authentication-using-restclient-addon-firefox/10478442#10478442 (or this : http://www.yiiframework.com/forum/index.php/topic/18412-new-yii-rest-tutorial/page__st__20__p__151819#entry151819)

HTH,

JM.

This is great, just what i’ve been looking for!

Again… Thank you so much for this tutorial!

Thanks for the tutorial. nice job thanks :)

Hi all, i’m getting this error. pls help me

The table "{{user}}" for active record class "User" cannot be found in the database.

    After i removed braces, now it showing like this......


   


The table &quot;user&quot; for active record class &quot;User&quot; cannot be found in the database.

Just wanted to add some tips on using exceptions that I’ve found very helpful while developing a REST API for internal use. The primary use case for interacting with the API is through Ajax requests - sending a POST or GET request and returning JSON - and I wanted a streamlined approach to handling and routing errors.

(Note: I get a lot of ideas from the folks at APIgee.)

These exception tips are also useful outside the API context as well for controlling application flow.

Custom CHttpException Base Class

I created a custom HttpException subclass that contains methods specifying the type of information I want available when presenting errors to developers or users, namely:

  • $message: The message for end users

  • $developer: the message for developers (more technical)

  • $statusCode: the relevant Http status code

  • $statusText: the relevant Http status text, e.g. "Forbidden" for 403

  • $infoUrl: a URL the developer can visit for more info about the error

  • $code: the internal classification code for the error

My most common use case for interacting with the API is through AJAX, in which case I usually specify done() and fail() handlers. This info usually contains all I need to easily relay specific information back to both end users and developers.

Common Sub-Classes

  • Http400Exception - For input/parameter errors

  • Http401Exception - for authentication errors

  • Http403Exception - for not-permitted errors

  • Http404Exception - when a specified resource is not found but the request is otherwise valid

  • Http500Exception - for unspecified internal errors

These provider shorthand access to the most common error types and enable me to subclass them for further customization (see below).

Model-Specific Exceptions

  • ValidationException - for when a model fails to validate (extends Http400Exception)

  • SaveException - for when an otherwise valid model fails to save to the database or execute a desired action (extends Http500Exception)

These special exceptions take a CModel instance in their constructor that references the model related to the error, allowing me to use the exception to determine what errors occurred, if any.

Example API Action

With these exceptions, my API Actions end up initializing a model, asking it to do things, and throwing exceptions whenever un-recoverable errors occur. It makes for little reduced visibility at first, but I like that 1) it’s clear once you dive in; 2) it’s easy to debug; and 3) it keeps all but presentation and routing logic out of the controller.

And after much trial and error, I find this easier and more maintainable than using exceptions in Models. I prefer having the controller ask the model to do stuff, see if it worked (true/false), handle that response, and then relay messages to the user (e.g. by asking the model for the errors that occurred).




public function actionUpdate($id, $suppress_status_code=false) {

	try {

		$model = MyModel::findByPk($id);

		if ($model===null)

			throw new Http404Exception("Model #{$id} was not found in the database");

		elseif (!authManager()->checkAccess('MyModel.update', user()->id, array('modelId' =>$id)))

			throw new Http403Exception("You are not authorized to update Model #{$id}");

		elseif (!isset($_POST['MyModel']))

			throw new Http400Exception("Your request could not be completed because we could not tell what attributes you wanted to update", 'Specify Model attributes using the $_POST["Model"]');

		else {

			$model->setAttributes($_POST['MyModel']);


			if (!$model->validate())

				throw new ValidationException($model);

			elseif (!$model->save(false))

				throw new SaveException($model);

			else {

				header("HTTP/1.0 200 OK");

				header('Content-type: text/json');

				echo CJSON::encode(array(

					"statusCode" =>200,

					"statusText" =>"OK",

					"message"    =>"Model #{$id} was successfully updated!",

					"developer"  =>null,

					"infoUrl"    =>null,

				));

				Yii::app()->end();

			}

		}

	} catch (HttpException $e) {

		$statusHeader = $suppress_status_code

			? "HTTP/1.0 200 OK"

			: "HTTP/1.0 {$e->statusCode} {$e->getStatusText()}";

		header($statusHeader);

		header('Content-type: text/json');

		echo $e->getJsonMessage();

		Yii::app()->end();

	}

}



i do it and in firefox extension all is good but in yii no :( my call is:


$.ajax({

                url: 'url',

                type:'post',

                contentType: 'application/x-www-form-urlencoded',

                data: $("#product").val()               

                });

            }

what is wrong? $_POST result empty but POST variable of firebug is correctly filled

:( tnx at all