I'm trying to create a simple REST server using CI 4 based on this article. this is my code:
app/Controllers/Barang.php
<?php
namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\API\ResponseTrait;
use App\Models\Model_Barang;
class Barang extends ResourceController
{
use ResponseTrait;
// get multiple data
public function index()
{
$apiModel = new Model_Barang();
$data = $apiModel->orderBy('id', 'ASC')->findAll();
return $this->respond($data);
}
// get single data
public function getBarang($id = null)
{
$apiModel = new Model_Barang();
$data = $apiModel->where('id', $id)->first();
if($data){
return $this->respond($data);
}else{
return $this->failNotFound('Barang tidak ditemukan.');
}
}
// the other functions for create, update, delete
}
app/Models/Model_Barang.php
<?php
namespace App\Models;
use CodeIgniter\Model;
class Model_Barang extends Model
{
protected $table = 'barang';
protected $primaryKey = 'id';
protected $allowedFields = [
'nama',
'harga',
'jumlah',
'kode_supplier'
];
}
when I test it using Postman with method GET on this URL http://localhost:8080/barang/
it works fine (it shows all the data in the barang
table), but when I use http://localhost:8080/barang/1
it suddenly returns an error saying
{
"status": 501,
"error": 501,
"messages": {
"error": "\"show\" action not implemented."
}
}
I know that according to the code, I should use http://localhost:8080/barang/getBarang/1
instead, and when I tried using getBarang/
it DID work.. but isn't that not RESTful? also, the article said that I can use the url without getBarang/
to get a specific data.. am I doing something wrong? or is this just a CI4's cons?
$routes->resource('barang');
The above line of code in app/Config/Routes.php
is equivalent to:
// Equivalent to the following auto-generated routes:
$routes->get('barang/new', 'Barang::new');
$routes->post('barang', 'Barang::create');
$routes->get('barang', 'Barang::index');
$routes->get('barang/(:segment)', 'Barang::show/$1');
$routes->get('barang/(:segment)/edit', 'Barang::edit/$1');
$routes->put('barang/(:segment)', 'Barang::update/$1');
$routes->patch('barang/(:segment)', 'Barang::update/$1');
$routes->delete('barang/(:segment)', 'Barang::delete/$1');
Calling http://localhost:8080/barang/1
in postman corresponds to this route match:
$routes->get('barang/(:segment)', 'Barang::show/$1');
'Barang::show/$1'
means that CodeIgniter is going to try to call the show(...)
method in the Barang
controller passing (:segment)
which in your case is 1
as the first method argument.
Since your controller is missing the show(...)
method, CodeIgniter complains about it with an error below:
{
"status": 501,
"error": 501,
"messages": {
"error": "\"show\" action not implemented."
}
}
To resolve this, you have 2 options/solutions. Whichever solution fits your needs, you will be able to get a single data set in postman by using GET http://localhost:8080/barang/1
Simply rename the controller method:
App\Controllers\Barang.php
Instead of:
// ...
public function getBarang($id = null) ❌
// ...
Use this:
// ...
public function show($id = null) ✅
// ...
If for some reason you wish to maintain the method name getBarang(...)
to act as the equivalent of the expected method show(...)
, inform the $routes->resource(...);
not to auto-create the show(...)
method route definition and later manually define it on your own. I.e:
app/Config/Routes.php
Instead of:
// ...
$routes->resource('barang'); ❌
// ...
Use this:
// ...
$routes->resource('barang', ['except' => 'show']); ✅
$routes->get('barang/(:segment)', 'Barang::getBarang/$1');
// ...