Question

I am having problems setting up an RESTful API with Kohana 3.3. I have added the following module (branch 3.3/release/v2.0), https://github.com/michal-m/kohana-modules-restful, to my bootstrap.

Kohana::modules(array(
    'restful' => MODPATH.'restful'
));

I've created a new controller, Controller_Api which extends RESTful_Controller and has get, update, create, delete actions. In my routes file I have:

Route::set('api', '(<controller>(/<action>(/<id>)))')
    ->defaults(array(
        'controller' => 'api',
        'action'     => 'index'
));

But the problem I'm having is when I go to: http://example.com/api/user/1

I get the following error which indicates my route is wrong but I can't work it out:

Kohana_HTTP_Exception [ 404 ]: Unable to find a route to match the URI: api/user/1

Was it helpful?

Solution

Firstly, get the latest 3.3/release/2.0 version. It's not final yet, but I've just pushed 2 important hotfixes.

Secondly, you have to add a route filter to translate request method (GET, POST, etc.) to appropriate actions. You can use one supplied with the module, like this:

Route::set('api', '(<controller>(/<action>(/<id>)))')
    ->filter('RESTful::route_filter')
    ->defaults(array(
        'controller' => 'api',
        'action'     => 'index'
));

Or create a simple one yourself, e.g.:

Route::set('api', '(<controller>(/<action>(/<id>)))')
    ->filter(function($route, $params, $request){
        $params['action'] = strtolower($request->method());
        return $params;
    })
    ->defaults(array(
        'controller' => 'api',
        'action'     => 'index'
));

OTHER TIPS

  1. Was restful module added successfully? You can try, for example, Kohana::autoload('RESTful_Controller') (returns boolean).
  2. Checkout your route list. Common mistake is to add your custom route after default catch-all route. Call Route::all() and you will see all routes in order they were added.
  3. Your route looks correct, but you can test it:
      $route = Route::get('api');
      $request = Request::factory('api/user/1');
      // since 3.3 Route::matches requires Request object
      $params = $route->matches($request);

$params should contain Request param names (controller, action etc). If your route is incorrect, $params is FALSE.

I'm use route filter. Route filters added in 3.3 version. Example:

bootstrap.php

Route::set('users', '(<controller>(/<id>))')
->filter(function ($route, $params, $request) {
    $params['action'] = strtolower($request->method()) . '_' . $params['action'];
    return $params;
})
->defaults(array('controller' => 'Users', 'action' => 'user'));

bootstrap.php (If need check authentication)

Route::set('users', '(<controller>(/<id>))')
->filter(function ($route, $params, $request) {
    if (Auth::instance()->logged_in())
    {
        $params['action'] = strtolower($request->method()) . '_' . $params['action'];
    }
    else
    {
        $params['action'] = 'noauth';
    }

    return $params;
})
->defaults(array('controller' => 'Users', 'action' => 'user'));

And code cuts from my controller.

<?php defined('SYSPATH') or die('No direct script access.');

class Controller_Users extends Controller {

    public function action_get_user ()
    {
       // GET method
    }

    public function action_post_user ()
    {
       // POST method
    }

    public function action_put_user ()
    {
       // PUT method
    }

    public function action_delete_user ()
    {
       // DELETE method
    }

    public function action_noauth ()
    {
       // No authentication response
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top