3

I have a controller App/Controllers/Api/Orders.php

<?php

namespace App\Controllers\Api;

use CodeIgniter\RESTful\ResourceController;

class Orders extends ResourceController
{
    protected $modelName = 'App\Models\Order';
    protected $format    = 'json';

    public function getIndex()
    {
        return $this->respond($this->model->findAll());
    }

    public function delete($id = null)
    {
        return $this->respond(['test' => 123]);
    }
}

When I'm trying to access /api/orders/ with GET request it works fine (so auto routing is working).

But when I'm trying to send a DELETE request: /api/orders/15 I get error 404. What am I doing wrong? The main source of confusion for me is that Codeigniter 4 RESTful documentation seems to talk about manual routes or legacy auto routing but not the improved version where you need to specify methodFunction (like getIndex).

Running php spark routes gives me the following:

+--------------+------------------+------+---------------------------------------+----------------+---------------+
| Method       | Route            | Name | Handler                               | Before Filters | After Filters |
+--------------+------------------+------+---------------------------------------+----------------+---------------+
| GET(auto)    | api/orders       |      | \App\Controllers\Api\Orders::getIndex |                | toolbar       |
| DELETE(auto) | api/orders/[/..] |      | \App\Controllers\Api\Orders::delete   | <unknown>      | <unknown>     |

CodeIgniter version: 4.3.1

app/Config/Routes.php

$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Auth');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
$routes->get('/', 'Home::index');

app/Config/Filters.php

public array $globals = [
    'before' => [
        // 'honeypot',
        // 'csrf',
        // 'invalidchars',
    ],
    'after' => [
        'toolbar',
        // 'honeypot',
        // 'secureheaders',
    ],
];
user64675
  • 482
  • 7
  • 25

1 Answers1

1

Solution:

Beyond prefixing the Controller method with an HTTP verb i.e delete, you need to provide a 'Controller method name' as the suffix. I.e: httpVerbMethodName.

Instead of: ❌

public function delete($id = null)
{
   // ...
}

Use this: ✅

public function deleteOrder($id = null)
{
   // ...
}

Route endpoint:

DELETE: http://localhost:4599/api/orders/order/15

| DELETE(auto) | api/orders/order[/..] |      | \App\Controllers\Api\Orders::deleteOrder |                | toolbar  


Reference:

URI Segments

The segments in the URL, in following with the Model-View-Controller approach, usually represent:

example.com/class/method/ID
  1. The first segment represents the controller class that should be invoked.

  2. The second segment represents the class method that should be called.

  3. The third, and any additional segments, represent the ID and any variables that will be passed to the controller.

Consider this URI:

example.com/index.php/helloworld/hello/1

In the above example, when you send a HTTP request with GET method, Auto Routing would attempt to find a controller named App\Controllers\Helloworld and executes getHello() method with passing '1' as the first argument.

Note

A controller method that will be executed by Auto Routing (Improved) needs HTTP verb (get, post, put, etc.) prefix like getIndex(), postCreate().

See Auto Routing in Controllers for more info.

steven7mwesigwa
  • 5,701
  • 3
  • 20
  • 34
  • 1
    Ok but the RESTful CodeIgniter page lists common (good) practice with RESTful routes like this: `$routes->delete('photos/(:segment)', 'Photos::delete/$1');`. I guess this just means that auto routing doesn't work here – user64675 Jan 21 '23 at 14:16
  • 1
    @user64675 Correct! In that case, you **can't** use auto-routing. Disable Auto-routing by changing `public bool $autoRoutesImproved = false;` in `app/Config/Feature.php` and `$routes->setAutoRoute(false);` in `app/Config/Routes.php`. Then, [manually define routes](https://codeigniter4.github.io/userguide/incoming/routing.html#examples) in `app/Config/Routes.php`. I.e: `$routes->delete('api/orders/(:num)', 'Api\Orders::delete/$1');` – steven7mwesigwa Jan 21 '23 at 18:59
  • 1
    @user64675 Your HTTP request would then be something similar to; `DELETE: http://localhost:4599/api/orders/15` – steven7mwesigwa Jan 21 '23 at 19:02