Simple Restful Implementation for Yii

    Introduction

    I decided on copper to write the google chrome extension for the project of the company in which I work. The extension and the project itself is dedicated to auto topics. In the process of writing, the server side annoyed me, which gave the extension ready-made data layout and styles, but I wanted json. An article about restful caught my eye and decided to write the server side on restful architecture.
    Our project is implemented on native php without using any frameworks. I wrote a simple class that implements the necessary fennies, but could not stop there, since I am a fan of yii decided to implement this for him as well. I looked at third-party developments, but I wanted my own, moreover, the class I wrote normally coped with the tasks assigned to it. My adapted class for yii was shown to colleagues, saying yes and how they liked it. But then I suffered, I wanted it even easier.

    so

    In yii there is such a wonderful opportunity “ Binding action parameters ” as the manual says - you can set named parameters that will automatically get the corresponding value from $ _GET.

    class UpdateAction extends CAction
    {
        public function run($id)
        {
            // $id будет заполнен значением из $_GET['id']
        }
    } 


    Here the idea visited the opportunity not only to receive from GET but also POST, PUT, DELETE according to restful. As a result, I had to redefine the CController class with its runAction method and add the missing one.
    GetActionParams is responsible for getting the GET; it is simple to the ugliness.
    /**
    * Returns the request parameters that will be used for action parameter binding.
    * By default, this method will return $_GET. You may override this method if you
    * want to use other request parameters (e.g. $_GET+$_POST).
    * @return array the request parameters to be used for action parameter binding
    * @since 1.1.7
    */
    public function getActionParams()
    {
    	return $_GET;
    }
    

    By adding your methods to the overridden class ORestController.
    (I used the latest version 1.1.9 and get the data from $ _POST I didn’t succeed as I didn’t try, I had to take everything from the stream)
    //возвращает POST данные
     public function getActionParamsPOST()
        {
           //Получаем данные
           $fh = fopen("php://input", 'r');
           $post_string=stream_get_contents($fh);
           $post_param = explode("&", $post_string);
           $array_put=array();
           foreach($post_param as $post_val)
           {
           $param = explode("=", $post_val);
           $array_post[$param[0]]=urldecode($param[1]);
           }
           return $array_post;
        }
    //возвращает DELETE данные
        public function getActionParamsDELETE()
        {
            //получаем данные
           $fh = fopen("php://input", 'r');
           $delete_string=stream_get_contents($fh);
           $delete_param = explode("&", $delete_string);
           $array_delete=array();
           foreach($delete_param as $delete_val)
           {
              $param = explode("=", $delete_val);
              $array_delete[$param[0]]=urldecode($param[1]);
           }
           if($_GET)
               $_delete=$_GET;
           else
               $_delete=$array_delete;
           return $_delete;
        }
    //возвращает PUT данные
        public function getActionParamsPUT()
        {
            //Получаем данные из PUT
            $fh = fopen("php://input", 'r');
            $put_string=stream_get_contents($fh);
            $put_param = explode("&", $put_string);
            $array_put=array();
            foreach($put_param as $put_val)
            {
            $param = explode("=", $put_val);
            $array_put[$param[0]]=urldecode($param[1]);
            }
            return $array_put;
        }


    And slightly changing the original method
    /**
         * Runs the action after passing through all filters.
         * This method is invoked by {@link runActionWithFilters} after all possible filters have been executed
         * and the action starts to run.
         * @param CAction $action action to run
         *
         * Переопределяем runAction для получения PUT,DELETE,POST
         */
        public function runAction($action)
        {
            $priorAction=$this->_action;
            $this->_action=$action;
            $params=false;
            if($this->beforeAction($action))
            {
                switch ($_SERVER['REQUEST_METHOD'])
                {
                    case "POST":
                        $params= $this->getActionParamsPOST();
                    break;
                    case "PUT":
                        $params= $this->getActionParamsPUT();
                    break;
                    case "DELETE":
                        $params= $this->getActionParamsDELETE();
                    break;
                    default:
                       $params= $this->getActionParams();
                }
                if($action->runWithParams($params)===false)
                    $this->invalidActionParams($action);
                else
                    $this->afterAction($action);
            }
            $this->_action=$priorAction;
        }
    


    Well, that's all in principle, we inherit our new controller and work.
    Example:
    
    class ApiController extends  ORestController
    {
        public function actions()
        {
    	return array
    	(
    		'test' => 'application.controllers.actionsApi.actionTest',
    	);
        }
    }


    class actionTest extends CAction 
    {
     public function run($params='')
     {
         switch ($_SERVER['REQUEST_METHOD'])
         {
             case "POST":
                 echo "POST ".$params;
             break;
             case "PUT":
                 echo "PUT ".$params;
             break;
             case "DELETE":
                 echo "DELETE ".$params;
             break;
             default:
                 echo "GET ".$params;
         }
      }
    }
    

    It remains to implement the necessary functionality for each action, each action works with a separate entity as described in restful. No need to set the URL rules therefore does not affect the performance of the application.
    PS: The methods getActionParamsPOST, getActionParamsPUT, getActionParamsDELETE can be reduced to one method, thereby reducing another code.

    Also popular now: