How to give string in the url in RESTful api in Cakephp?

泪湿孤枕 提交于 2019-12-10 18:05:18

问题


As per the this Cakephp CookBook the simple setup for RESTful api :

HTTP Method     URL.method  Controller action invoked
GET     /recipes*.method*   RecipesController::index()
GET     /recipes/123.method     RecipesController::view(123)
POST    /recipes*.method*   RecipesController::add()
PUT     /recipes/123*.method*   RecipesController::edit(123)
DELETE  /recipes/123.method     RecipesController::delete(123)
POST    /recipes/123*.method*   RecipesController::edit(123)

here all the URL parameters are numeric i.e 123. When I tried with the string i.e

GET     /recipes/test.json  RecipesController::view(123)

this gives me an error :

{
   code: "404"
   url: "/myproject/recipes/test.json"
   name: "Action RecipesController::test() could not be found."
}

here the URL

     "/myproject/recipes/test.json" // doesn't work

but 
      "/myproject/recipes/123.json" // works 

I used the default Router::mapResources('recipes')

Thanks in advance!


回答1:


Well, reading the API for that piece of code, the value passed before the dot is matched automatically to an id or UUID. Right in that API there's the params definitions

'id' - The regular expression fragment to use when matching IDs. By default, matches integer values and UUIDs.

What mapResources does is simply add a lot of Router::connect with some pre-established options (that basically has the form of :controller/:action/:id).

So, if the rule is to match ids (that cake considers to be ints) to a regular expression, clearly your string isn't passing that validation. So the Router skips that connect rule and goes to the other, until one matches. And the one that matches is in the form of :controller/:action.extension (probably). That's why you're getting that error, test is clearly not intended to be an action.

Luckily, one of that options that mapResourcesgives for customizing is the rule to match the $id.

To add the option of strings as "ids" (since that's the only variable the REST actions are going to receive if you add the connection routes with mapResources), change the regex that validates that rule like this

Router::mapResources('recipes', array('id'=>'[0-9A-Za-z]'));

or whatever rule you want to make (I'm bad with regex, so try to adjust it to what you need).

Take a look at the docs of the API to see what other options you can add.

Keep in mind that mapResources is there to make your life easier, so if you need more complicated routes with more params or something extra, consider forgetting about mapResources and constructing the routes yourself (like it says in the bottom of the page of the link you provided).




回答2:


Define in your routes below code :

// used for the rest API 
$routes->extensions(['json','xml']); // type of format you want to get response
$routes->resources('Api');

Then create a controller for the API like below inside controller folder

<?php
namespace App\Controller;
use Cake\I18n\Time;
use Cake\Database\Type; 
Type::build('date')->setLocaleFormat('yyyy-MM-dd'); // customize date format

// src/Controller/RecipesController.php
class ApiController extends AppController
{

    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('RequestHandler');
        // load Model 
        $this->loadModel('Sales'); // load model to fetch data from database
        $this->Auth->allow();      // allow URL to public in case of Auth check 
    }

    public function beforeFilter(\Cake\Event\Event $event)
    {
        parent::beforeFilter($event);
        $this->loadComponent('RequestHandler');     
        $this->loadComponent('Flash');

    }

    public function index($fromdate = null, $todate = null)
    {
        //set date range to fetch the sales in particular date 
        if(!empty($_GET['fromdate_utc']) && !empty($_GET['todate_utc'])){
            // if from amd to date are same add +1 day in to date to get result 
            $to_date = date('Y-m-d', strtotime($_GET['todate_utc'] . ' +1 day'));
            $dateRage = array('Sales.SalesDate >= ' => $_GET['fromdate_utc'], 'Sales.SalesDate <=' => $to_date);
        }else{
            $dateRage = array();                    
        }

        $conditions = array(
            'and' => array($dateRage),
        );

        //$this->Auth->allow();
        $sales= $this->Sales->find('all', array(
                        'conditions' => $conditions
                    ))
                    ->select(['SalesNo', 'SalesDate', 'TotalValue', 'TotalDiscount', 'NetTotal', 'PaymentMode', 'Status'])
                    ->where(['StoreId' => '1']);
       // set data for view or response of API
        $this->set([
            'sales' => $sales,
            '_serialize' => ['sales']
        ]);
    }

}

?>

How to pass parameters in API URL for XML format check below :-

https://example.com/api/index.xml?fromdate_utc=2016-10-03&todate_utc=2016-10-03

How to pass parameters in API URL for JSON format check below :-

https://example.com/api/index.json?fromdate_utc=2016-10-03&todate_utc=2016-10-03


来源:https://stackoverflow.com/questions/17108069/how-to-give-string-in-the-url-in-restful-api-in-cakephp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!