Revision #12 has been created by Maurizio Domba Cerin on Apr 16, 2011, 7:18:34 AM with the memo:
formated code indent
[...]
In order to parse these URL's, set up the URL manager in _config/main.php_ like this:
```php
...
'urlManager'=>array(
'urlFormat'=>'path',
'rules'=>array(
'post/<id:\d+>/<title:.*?>'=>'post/view',
'posts/<tag:.*?>'=>'post/index',
// REST patterns
array('api/list', 'pattern'=>'api/<model:\w+>', 'verb'=>'GET'),
array('api/view', 'pattern'=>'api/<model:\w+>/<id:\d+>', 'verb'=>'GET'),
array('api/update', 'pattern'=>'api/<model:\w+>/<id:\d+>', 'verb'=>'PUT'),
// Update
array('api/delete', 'pattern'=>'api/<model:\w+>/<id:\d+>', 'verb'=>'DELETE'),
array('api/create', 'pattern'=>'api/<model:\w+>', 'verb'=>'POST'),
// Create
// Other controllers
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
),
),
),
),
...
```[...]
```php
class
class ApiController extends Controller
{
// Members[...]
return array();
}
// Actions
public function actionList()
{
}
public function actionView()
{
}
public function actionCreate()
{
}
public function actionUpdate()
{
}
public function actionDelete()
{
}[...]
```php
public function actionList()
{
{
// Get the respective model instance
switch($_GET['model'])
{
{
case 'posts':
$models = Post::model()->findAll();
break;
default:
// Model not implemented error
$this->_sendResponse(501, sprintf(
'Error: Mode <b>list</b> is not implemented for model <b>%s</b>',
$_GET['model']) );
exit;
}
// Did we get some results?
if(is_null($models)) {
// No
$this->_sendResponse(200,
sprintf('No items where found for model <b>%s</b>', $_GET['model']) );
} else {
// Prepare response
$rows = array();
foreach($models as $model)
$rows[] = $model->attributes;
// Send the response
$this->_sendResponse(200, CJSON::encode($rows));
}
} // }}} }
}
```[...]
```php
public function actionView()
{
// Check if id was submitted via GET
if(!isset($_GET['id']))
$this->_sendResponse(500, 'Error: Parameter <b>id</b> is missing' );
switch($_GET['model'])
{
// Find respective model
case 'posts':
$model = Post::model()->findByPk($_GET['id']);
break;
default:
$this->_sendResponse(501, sprintf(
'Mode <b>view</b> is not implemented for model <b>%s</b>',
$_GET['model']) );
exit;
// }}}
}
// Did we find the requested model?
If not, raise an error
if(is_null($model))
{
// No, raise an error
$this->_sendResponse(404, 'No Item found with id '.$_GET['id']);
} else {
else
$this->_sendResponse(200, CJSON::encode($_GET['model']));
}
} // }}} }
```[...]
```php
public function actionCreate()
{
{
switch($_GET['model'])
{
{
// Get an instance of the respective model
case 'posts':
$model = new Post;
break;
default:
$this->_sendResponse(501,
sprintf('Mode <b>create</b> is not implemented for model <b>%s</b>',
$_GET['model']) );
exit;
}
}
// Try to assign POST values to attributes
foreach($_POST as $var=>$value) {
// Does the model have this attribute?
If not raise an error
if($model->hasAttribute($var))
{
$model->$var = $value;
} else
{
// No, raise an error
$this->_sendResponse(500,
sprintf('Parameter <b>%s</b> is not allowed for model <b>%s</b>', $var,
$_GET['model']) );
}
}
}
// Try to save the model
if($model->save())
{
// Saving was OK
$this->_sendResponse(200,
$this->_getObjectEncoded($_GET['model'], $model->attributes) );
} else {
// Errors occurred
$msg = "<h1>Error</h1>";
$msg .= sprintf("Couldn't create model <b>%s</b>", $_GET['model']);
$msg .= "<ul>";
foreach($model->errors as $attribute=>$attr_errors) {
$msg .= "<li>Attribute: $attribute</li>";
$msg .= "<ul>";
foreach($attr_errors as $attr_error)
{
$msg .= "<li>$attr_error</li>";
}
$msg .= "</ul>";
}
$msg .= "</ul>";
$this->_sendResponse(500, $msg );
}
} // }}}
}
```[...]
```php
public function actionUpdate()
{
{
// Parse the PUT parameters
parse_str(file_get_contents('php://input'), $put_vars);
switch($_GET['model'])
{
{
// Find respective model
case 'posts':
$model = Post::model()->findByPk($_GET['id']);
break;
default:
$this->_sendResponse(501,
sprintf(
'Error: Mode <b>update</b> is not implemented for model <b>%s</b>',
$_GET['model']) );
exit;
}
// Did we find the requested model?
If not, raise an error
if(is_null($model))
{
// No, raise an error
$this->_sendResponse(400,
sprintf("Error: Didn't find any model <b>%s</b> with ID <b>%s</b>.",
$_GET['model'], $_GET['id']) );
}
// Try to assign PUT parameters to attributes
foreach($put_vars as $var=>$value) {
// Does model have this attribute?
If not, raise an error
if($model->hasAttribute($var))
{
$model->$var = $value;
} else {
// No, raise error
$this->_sendResponse(500,
sprintf('Parameter <b>%s</b> is not allowed for model <b>%s</b>',
$var, $_GET['model']) );
}
}
}
// Try to save the model
if($model->save())
{
$this->_sendResponse(200,
sprintf('The model <b>%s</b> with id <b>%s</b> has been updated.',
$_GET['model'], $_GET['id']) );
} else {
else
// prepare the error $msg
// see actionCreate
// ...
$this->_sendResponse(500, $msg );
}
}
```[...]
```php
public function actionDelete()
{
{
switch($_GET['model'])
{
// Load the respective model
case 'posts':
$model = Post::model()->findByPk($_GET['id']);
break;
default:
$this->_sendResponse(501,
sprintf('Error: Mode <b>delete</b> is not implemented for model <b>%s</b>',
$_GET['model']) );
exit;
}
// Was a model found?
if(is_null($model)) {
// No, raise an error
If not, raise an error
if(is_null($model))
$this->_sendResponse(400,
sprintf("Error: Didn't find any model <b>%s</b> with ID <b>%s</b>.",
$_GET['model'], $_GET['id']) );
}
// Delete the model
$num = $model->delete();
if($num>0)
$this->_sendResponse(200,
sprintf("Model <b>%s</b> with ID <b>%s</b> has been deleted.",
$_GET['model'], $_GET['id']) );
else
$this->_sendResponse(500,
sprintf("Error: Couldn't delete model <b>%s</b> with ID <b>%s</b>.",
$_GET['model'], $_GET['id']) );
}
```[...]
```php
private function _sendResponse($status = 200, $body = '', $content_type = 'text/html')
{
{
// set the status
$status_header = 'HTTP/1.1 ' . $status . ' ' . $this->_getStatusCodeMessage($status);
// set the status
header($status_header);
//
setand the content type
header('Content-type: ' . $content_type);
// pages with body are easy
if($body != '')
{
{
// send the body
echo $body;
exit;
}
// we need to create the body if none is passed
else
{
// create some body messages
$message = '';
// this is purely optional, but makes the pages a little nicer to read
// for your users. Since you won't likely send a lot of different status codes,
// this also shouldn't be too ponderous to maintain
switch($status)
{
{
case 401:
$message = 'You must be authorized to view this page.';
break;
case 404:
$message = 'The requested URL ' . $_SERVER['REQUEST_URI'] . ' was not found.';
break;
case 500:
$message = 'The server encountered an error processing your request.';
break;
case 501:
$message = 'The requested method is not implemented.';
break;
}
// servers don't always have a signature turned on
// (this is an apache directive "ServerSignature On")
$signature = ($_SERVER['SERVER_SIGNATURE'] == '') ? $_SERVER['SERVER_SOFTWARE'] . ' Server at ' . $_SERVER['SERVER_NAME'] . ' Port ' . $_SERVER['SERVER_PORT'] : $_SERVER['SERVER_SIGNATURE'];
// this should be templated in a real-world solution
$body = '
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>' . $status . ' ' . $this->_getStatusCodeMessage($status) . '</title>
</head>
<body>
</head>
<body>
<h1>' . $this->_getStatusCodeMessage($status) . '</h1>
<p>' . $message . '</p>
<hr />
<address>' . $signature . '</address>
</body>
<hr />
<address>' . $signature . '</address>
</body>
</html>';
echo $body;
exit;
}
} // }}} }
```[...]
```php
private function _getStatusCodeMessage($status)
{
{
// these could be stored in a .ini file and loaded
// via parse_ini_file()... however, this will suffice
// for an example
$codes = Array(
200 => 'OK',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
500 => 'Internal Server Error',
501 => 'Not Implemented',
);
return (isset($codes[$status])) ? $codes[$status] : '';
} // }}}
}
```[...]
```php
private function _checkAuth()
{
// Check if we have the USERNAME and PASSWORD HTTP headers set?
if(!(isset($_SERVER['HTTP_X_USERNAME']) and isset($_SERVER['HTTP_X_PASSWORD']))) {
// Error: Unauthorized
$this->_sendResponse(401);
}
$username = $_SERVER['HTTP_X_USERNAME'];
$password = $_SERVER['HTTP_X_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');
}
} // }}} }
}
```
Also, in all REST methods where an authentication is required, we need to put[...]