Yii1.1 实现简单restful 框架

学习了下php的rest服务,将总结记录如下。采用Yii1.1版本,Yii2已经专门有restful专题(ps:暂时没有学习)


1.先用Yii创建项目

2.创建数据库(rest)和表(rest_user)及对应模型(user)[脚手架创建]

CREATE TABLE `rest_user` (
  `id` int AUTO_INCREMENT COMMENT '用户账号',
  `name` char(32) NOT NULL COMMENT '用户姓名',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


INSERT INTO `rest_user` VALUES 
('1','考勤'),
('2','hu'),
('3','wang'),
('4','fan'),
('5','yuan');


3.在protected/config/main.php中配置路由

'urlManager'=>array(
		    'urlFormat'=>'path',
		    'showScriptName'=>false,//为优化URL去掉index.php入口文件名字准备
		    'rules'=>array(
		        'user//'=>'user/view',
		        'users/'=>'users/index',
		        // REST patterns
		        array('api/list', 'pattern'=>'api/', 'verb'=>'GET'),
		        array('api/view', 'pattern'=>'api//', 'verb'=>'GET'),
		        array('api/update', 'pattern'=>'api//', 'verb'=>'PUT'),
		        array('api/delete', 'pattern'=>'api//', 'verb'=>'DELETE'),
		        array('api/create', 'pattern'=>'api/', 'verb'=>'POST'),
		        // Other controllers
		        '/'=>'/',
		    ),
		),

4.建立相关控制器处理rest请求(ApiController.php)

_checkAuth();
        switch($_GET['model'])
        {
            case 'users': // {{{ 
                $models = User::model()->findAll();
                break; // }}} 
            default: // {{{ 
                $this->_sendResponse(501, sprintf('Error: Mode list is not implemented for model %s',$_GET['model']) );
                exit; // }}} 
        }
        if(is_null($models)) {
            $this->_sendResponse(200, sprintf('No items where found for model %s', $_GET['model']) );
        } else {
            $rows = array();
            foreach($models as $model)
                $rows[] = $model->attributes;

            $this->_sendResponse(200, CJSON::encode($rows));
        }
    } // }}} 
    // {{{ actionView
    /* Shows a single item
     * 
     * @access public
     * @return void
     */
    public function actionView()
    {
        //$this->_checkAuth();
        // Check if id was submitted via GET
        if(!isset($_GET['id']))
            $this->_sendResponse(500, 'Error: Parameter id is missing' );
        var_dump($_GET['id']);
        var_dump($_GET['model']);
        switch($_GET['model'])
        {
            // Find respective model    
            case 'users': // {{{ 
                $model = User::model()->findByPk($_GET['id']);
                break; // }}} 
            default: // {{{ 
                $this->_sendResponse(501, sprintf('Mode view is not implemented for model %s',$_GET['model']) );
                exit; // }}} 
        }
        if(is_null($model)) {
            $this->_sendResponse(404, 'No Item found with id '.$_GET['id']);
        } else {
            $this->_sendResponse(200, $this->_getObjectEncoded($_GET['model'], $model->attributes));
        }
    } // }}} 
    // {{{ actionCreate
    /**
     * Creates a new item
     * 
     * @access public
     * @return void
     */
    public function actionCreate()
    {
        //$this->_checkAuth();

        switch($_GET['model'])
        {
            // Get an instance of the respective model
            case 'users': // {{{ 
                $model = new User;                    
                break; // }}} 
            default: // {{{ 
                $this->_sendResponse(501, sprintf('Mode create is not implemented for model %s',$_GET['model']) );
                exit; // }}} 
        }
        // Try to assign POST values to attributes
        foreach($_POST as $var=>$value) {
            // Does the model have this attribute?
            if($model->hasAttribute($var)) {
                $model->$var = $value;
            } else {
                // No, raise an error
                $this->_sendResponse(500, sprintf('Parameter %s is not allowed for model %s', $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 = "

Error

"; $msg .= sprintf("Couldn't create model %s", $_GET['model']); $msg .= "
    "; foreach($model->errors as $attribute=>$attr_errors) { $msg .= "
  • Attribute: $attribute
  • "; $msg .= "
      "; foreach($attr_errors as $attr_error) { $msg .= "
    • $attr_error
    • "; } $msg .= "
    "; } $msg .= "
"; $this->_sendResponse(500, $msg ); } var_dump($_REQUEST); } // }}} // {{{ actionUpdate /** * Update a single iten * * @access public * @return void */ public function actionUpdate() { // $this->_checkAuth(); // Get PUT parameters parse_str(file_get_contents('php://input'), $put_vars); switch($_GET['model']) { // Find respective model case 'users': // {{{ $model = User::model()->findByPk($_GET['id']); break; // }}} default: // {{{ $this->_sendResponse(501, sprintf('Error: Mode update is not implemented for model %s',$_GET['model']) ); exit; // }}} } if(is_null($model)) $this->_sendResponse(400, sprintf("Error: Didn't find any model %s with ID %s.",$_GET['model'], $_GET['id']) ); // Try to assign PUT parameters to attributes foreach($put_vars as $var=>$value) { // Does model have this attribute? if($model->hasAttribute($var)) { $model->$var = $value; } else { // No, raise error $this->_sendResponse(500, sprintf('Parameter %s is not allowed for model %s', $var, $_GET['model']) ); } } // Try to save the model if($model->save()) { $this->_sendResponse(200, sprintf('The model %s with id %s has been updated.', $_GET['model'], $_GET['id']) ); } else { $msg = "

Error

"; $msg .= sprintf("Couldn't update model %s", $_GET['model']); $msg .= "
    "; foreach($model->errors as $attribute=>$attr_errors) { $msg .= "
  • Attribute: $attribute
  • "; $msg .= "
      "; foreach($attr_errors as $attr_error) { $msg .= "
    • $attr_error
    • "; } $msg .= "
    "; } $msg .= "
"; $this->_sendResponse(500, $msg ); } } // }}} // {{{ actionDelete /** * Deletes a single item * * @access public * @return void */ public function actionDelete() { // $this->_checkAuth(); switch($_GET['model']) { // Load the respective model case 'users': // {{{ $model = User::model()->findByPk($_GET['id']); break; // }}} default: // {{{ $this->_sendResponse(501, sprintf('Error: Mode delete is not implemented for model %s',$_GET['model']) ); exit; // }}} } // Was a model found? if(is_null($model)) { // No, raise an error $this->_sendResponse(400, sprintf("Error: Didn't find any model %s with ID %s.",$_GET['model'], $_GET['id']) ); } // Delete the model $num = $model->delete(); if($num>0) $this->_sendResponse(200, sprintf("Model %s with ID %s has been deleted.",$_GET['model'], $_GET['id']) ); else $this->_sendResponse(500, sprintf("Error: Couldn't delete model %s with ID %s.",$_GET['model'], $_GET['id']) ); } // }}} // }}} End Actions // {{{ Other Methods // {{{ _sendResponse /** * Sends the API response * * @param int $status * @param string $body * @param string $content_type * @access private * @return void */ private function _sendResponse($status = 200, $body = '', $content_type = 'text/html') { $status_header = 'HTTP/1.1 ' . $status . ' ' . $this->_getStatusCodeMessage($status); // set the status header($status_header); // set 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 templatized in a real-world solution $body = ' ' . $status . ' ' . $this->_getStatusCodeMessage($status) . '

' . $this->_getStatusCodeMessage($status) . '

' . $message . '


' . $signature . '
'; echo $body; exit; } } // }}} // {{{ _getStatusCodeMessage /** * Gets the message for a status code * * @param mixed $status * @access private * @return string */ 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( 100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => '(Unused)', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported' ); return (isset($codes[$status])) ? $codes[$status] : ''; } // }}} // {{{ _checkAuth /** * Checks if a request is authorized * * @access private * @return void */ 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'); } } // }}} // {{{ _getObjectEncoded /** * Returns the json or xml encoded array * * @param mixed $model * @param mixed $array Data to be encoded * @access private * @return void */ private function _getObjectEncoded($model, $array) { if(isset($_GET['format'])) $this->format = $_GET['format']; if($this->format=='json') { return CJSON::encode($array); } elseif($this->format=='xml') { $result = ''; $result .= "\n<$model>\n"; foreach($array as $key=>$value) $result .= " <$key>".utf8_encode($value)."\n"; $result .= ''; return $result; } else { return; } } // }}} // }}} End Other Methods } /* vim:set ai sw=4 sts=4 et fdm=marker fdc=4: */ ?>

到此即生成简单的rest框架

下面的get请求id的效果




你可能感兴趣的:(Yii)