I'm building a RESTful API System with CakePHP 3.1.13 ( i can't use 3.2.x because the Server PHP Version is 5.5.x ).
My controller name is CmsCouplesController.php and the url :
http://localhost/~emanuele/works/grai/html/api/v1/cms-couples.json
works correctly.
BUT the other call ( http://localhost/~emanuele/works/grai/html/api/v1/cms-couples/1.json ) return :
Action CmsCouplesController::1() could not be found, or is not accessible.
If i create a controller CouplesController.php all works fine.
So why?!
UPDATE : routes configuration
Router::scope('/', function ($routes) {
$routes->prefix('v1',function($routes) {
$routes->extensions(['json','xml']);
$routes->resources('Couples');
$routes->fallbacks('DashedRoute');
});
Resource routes require separate inflection configuration
You are missing the proper inflection configuration for your resource routes. By default resource routes are using underscore inflection, ie currently your resource routes will match cms_couples.
Note that you can easily check which/how routes are connected by using the routes shell
bin/cake routes
It will show you something like
| v1:cmscouples:index | /v1/cms_couples | {"controller":"CmsCouples","action":"index","_method":"GET","prefix":"v1","plugin":null} |
| v1:cmscouples:add | /v1/cms_couples | {"controller":"CmsCouples","action":"add","_method":"POST","prefix":"v1","plugin":null} |
| v1:cmscouples:view | /v1/cms_couples/:id | {"controller":"CmsCouples","action":"view","_method":"GET","prefix":"v1","plugin":null} |
| v1:cmscouples:edit | /v1/cms_couples/:id | {"controller":"CmsCouples","action":"edit","_method":["PUT","PATCH"],"prefix":"v1","plugin":null} |
| v1:cmscouples:delete | /v1/cms_couples/:id | {"controller":"CmsCouples","action":"delete","_method":"DELETE","prefix":"v1","plugin":null} |
Long story short, use dasherize inflection and you should be good.
$routes->resources('CmsCouples', [
'inflect' => 'dasherize'
]);
See also
Cookbook > Shells, Tasks & Console Tools > Routes Shell
Cookbook > Routing > URL Inflection for Resource Routes
API > \Cake\Routing\RouteBuilder::resources()
from my understanding...
http://localhost/~emanuele/works/grai/html/api/v1/cms-couples.json
must be pointing to index function of CmsCouplesController.php controller
then for what reason you want this kind of url
http://localhost/~emanuele/works/grai/html/api/v1/cms-couples/1.json
you can give url like
http://localhost/~emanuele/works/grai/html/api/v1/cms-couples/json-request
then you can put your code in jsonReuest function of the CmsCouplesController.php controller ...
If this does not help then explain your question with answer of my question of why you want URl like 1.json
Related
I have a standard resource controller registered like this:
Route::resource('/movies', \App\Http\Controllers\MovieController::class );
I checked php artisan route:list and I have the get 'movies' route.
But in blade template
Movies
does not work anymore.
And only
Movies
works.
Before that when I had:
Route::get('/movies', function () {
return view('movies');
})->name('movies');
The route method worked.
So url() method works everywhere and route() only in specific cases.
Could anyone tell me what is the main difference between those two methods?
which one should be used when?
And the main question - is it OK that the route() method does not work with resource controller, or is it something wrong with my code?
And since url() works everywhere should I just forget about route() method as unreliable?
If you look at the result of php artisan route:list you will see several routes e.g.
| | POST | movies | movies.store | App\Http\Controllers\MovieController#store | web |
| | GET|HEAD | movies | movies.index | App\Http\Controllers\MovieController#index | web |
| | DELETE | movies/{movie} | movies.destroy | App\Http\Controllers\MovieController#destroy | web |
| | PUT|PATCH | movies/{movie} | movies.update | App\Http\Controllers\MovieController#update |
route() and url() accept different values.
route() will accept route names e.g. movies.index, movies.destroy, movies.update and
url() will accept movies, movies/23.
route() will select the right methods (GET, POST, PATCH, DELETE) for you but
url() will only provide the path.
I am using Laravel 5.6 and I'm getting HTTP404 responses on existing routes in routes/api.php which I define as follows:
Route::middleware('auth:api')->post('/account/plan', 'Account\BillingController#updatePlan');
Route::middleware('auth:api')->put('/account/plan', 'Account\BillingController#unsubscribe');
Route::middleware('auth:api')->patch('/account/plan', 'Account\BillingController#resubscribe');
When I use axios.post() on these routes and include the _method parameter I get a 404 response on the PUT and PATCH routes. I have also tested axios.put()/axios.patch() in place of using post() with and without the inclsion of the _method parameter. I have also confirmed these are being correctly represented by artisan route:list:
| | POST | api/account/plan | | App\Http\Controllers\Account\BillingController#updatePlan | api,auth:api |
| | PUT | api/account/plan | | App\Http\Controllers\Account\BillingController#unsubscribe | api,auth:api |
| | PATCH | api/account/plan | | App\Http\Controllers\Account\BillingController#resubscribe | api,auth:api |
Example of the Axios Call:
axios.post(url,{_method:"PUT",confirm:"unsubscribe"})
.then(response => callback(response.data))
.catch(error => console.log(error))
When I define these same routes as follows they all work as intended:
Route::middleware('auth:api')->post('/account/plan', 'Account\BillingController#updatePlan');
Route::middleware('auth:api')->post('/account/unsubscribe', 'Account\BillingController#unsubscribe');
Route::middleware('auth:api')->post('/account/resubscribe', 'Account\BillingController#resubscribe');
I am able to separate endpoints by the request method on other routes I am unsure why these are creating a problem. Can someone explain why I get the 404 responses and how I can avoid them?
Since it seems you are doing evrything fine maybe by following laravel more strict conventions on defining routes you won't encounter the problem? Try like this:
Route::middleware(['auth:api'])->group(function () {
Route::post('/account/plan', 'Account\BillingController#updatePlan');
Route::put('/account/plan', 'Account\BillingController#unsubscribe');
Route::patch('/account/plan', 'Account\BillingController#resubscribe');
});
I have opened a project that I downloaded in IntelliJIDEA IDE. The project structure is as follows. I am trying to run the userAuthenticationController.php controller's index() method to view the login page.
According to this project's config.php File, the base_url is provided as follows.
config.php
$config['base_url'] = 'http://localhost:9080/Internship-Management/Sourcecode/Codeigniter/';
I tried running this address in Chrome but am getting the following error.
userAuthenticationController.php
// Show login page
public function index() {
$this->load->view('login/loginView');
}
routes.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/*
| -------------------------------------------------------------------------
| URI ROUTING
| -------------------------------------------------------------------------
| This file lets you re-map URI requests to specific controller functions.
|
| Typically there is a one-to-one relationship between a URL string
| and its corresponding controller class/method. The segments in a
| URL normally follow this pattern:
|
| example.com/class/method/id/
|
| In some instances, however, you may want to remap this relationship
| so that a different class/function is called than the one
| corresponding to the URL.
|
| Please see the user guide for complete details:
|
| https://codeigniter.com/user_guide/general/routing.html
|
| -------------------------------------------------------------------------
| RESERVED ROUTES
| -------------------------------------------------------------------------
|
| There are three reserved routes:
|
| $route['default_controller'] = 'welcome';
|
| This route indicates which controller class should be loaded if the
| URI contains no data. In the above example, the "welcome" class
| would be loaded.
|
| $route['404_override'] = 'errors/page_missing';
|
| This route will tell the Router which controller/method to use if those
| provided in the URL cannot be matched to a valid route.
|
| $route['translate_uri_dashes'] = FALSE;
|
| This is not exactly a route, but allows you to automatically route
| controller and method names that contain dashes. '-' isn't a valid
| class or method name character, so it requires translation.
| When you set this option to TRUE, it will replace ALL dashes in the
| controller and method URI segments.
|
| Examples: my-controller/index -> my_controller/index
| my-controller/my-method -> my_controller/my_method
*/
$route['default_controller'] = 'welcome';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
Do I need to change the path that I am using to load the controller in my browser?
Any suggestions in this regard will be highly appreciated.
Unfortunately, opening a project in IDEA/PhpStorm is not enough.
You still need to:
Install Apache (I think using XAMPP would be the best shot for you)
Configure it to run on port 9080 (according to the config file you posted)
Deploy the project to the Apache web root (manually, or by using a PhpStorm/IDEA deployment configuration)
The Laravel application I am working on has two resources.
The routes for the second resource are given below:
$ php artisan route:list | grep -i activity
POST | admin/procedure/{id}/activity | admin.procedure.{id}.activity.store | (...)\ProcedureActivityController#store
GET|HEAD | admin/procedure/{id}/activity | admin.procedure.{id}.activity.index | (...)\ProcedureActivityController#index
GET|HEAD | admin/procedure/{id}/activity/create | admin.procedure.{id}.activity.create | (...)\ProcedureActivityController#create
GET|HEAD | admin/procedure/{id}/activity/{activity} | admin.procedure.{id}.activity.show | (...)\ProcedureActivityController#show
PUT|PATCH | admin/procedure/{id}/activity/{activity} | admin.procedure.{id}.activity.update | (...)\ProcedureActivityController#update
DELETE | admin/procedure/{id}/activity/{activity} | admin.procedure.{id}.activity.destroy | (...)\ProcedureActivityController#destroy
GET|HEAD | admin/procedure/{id}/activity/{activity}/edit | admin.procedure.{id}.activity.edit | (...)\ProcedureActivityController#edit
I call this setup a nested resource because activities are defined under a procedure. The definition or the routes looks like this:
Route::resource('procedure', 'ProcedureController');
Route::resource('procedure/{id}/activity', 'Admin\ProcedureActivityController');
I would like to generate a link to the POST action for a new activity that belongs to procedure 3 as I would with the list-all-procedures route;
$ php artisan tinker
>>> route('admin.procedure.index')
=> "http://localhost/admin/procedure"
>>> route('admin.procedure.{id}.activity')
InvalidArgumentException with message
'Route [admin.procedure.{id}.activity] not defined.'
Is there a way to generate a link to a nested resource using the standard helpers and facades?
Your route definition for the nested resource is not quite right.
Route::resource('procedure/{id}/activity', 'Admin\ProcedureActivityController');
Should be:
Route::resource('procedure.activity', 'Admin\ProcedureActivityController');
Also I am not sure how you are getting {id} in the URI as the ResourceRegistrar will create parameters based on the resource name. Based on the definition that should be {procedure} for your first resource definition.
You should end up with a route name like admin.procedure.activity.index for the index route.
route('admin.procedure.activity.index', ['procedure' => $id]);
Laravel 5.1 - Controllers - Restful - Nested Resources
Route::resource('photos.comments', 'PhotoCommentController');
This route will register a "nested" resource that may be accessed with URLs like the following: photos/{photos}/comments/{comments}.
You should use route() with a parameter to make it work:
route('admin.procedure.{id}.activity.index', $id);
I'm creating my custom modules for my projects to be able to add some features to a project or another depending of the requeriments.
My issue is with the routes, I load the routes in a ModuleServiceProvider loaded in app.php:
include __DIR__.'/../../modules/canae/Http/routes.php';
I checked that this works with an echo inside that file. The routes.php file contains the following code:
Route::group(['prefix' => 'admin', 'middleware' => 'auth'], function() {
Route::controller('dogs', 'Canae\Http\Controllers\Admin\DogController');
});
I also checked that Laravel can find the Controller, the problem is that it's unable to execute the code inside it.
Here's the code I have inside DogController:
<?php namespace Canae\Http\Controllers\Admin;
class DogController extends \Origin\Http\Controllers\Controller {
public function getIndex() {
echo "Hello!";die();
}
}
And the error is Controller method not found.
If I modify the extends below to Origin\Http\Controllers\Controller (removing the first \) I get the following error: Class 'Canae\Http\Controllers\Admin\Origin\Http\Controllers\Controller' not found so my conclusion is that the code inside this controller is executing, at least reading from Laravel.
Also I'm trying to achieve the Index function with this route http://localhost/canae/public/admin/dogs/index.
This is the tail result of executing php artisan route:list:
| | GET|HEAD | admin/dogs/index/{one?}/{two?}/{three?}/{four?}/{five?} | | Canae\Http\Controllers\Admin\DogController#getIndex | auth |
| | GET|HEAD | admin/dogs | | Canae\Http\Controllers\Admin\DogController#getIndex | auth |
| | GET|HEAD|POST|PUT|PATCH|DELETE | admin/dogs/{_missing} | | Canae\Http\Controllers\Admin\DogController#missingMethod | auth |
+--------+--------------------------------+-------------------------------------------------------------------------------+--------+--------------------------------------------------------------------+------------+
Tell me if you need more information. And thanks for your time.
I solved it moving the line inside providers that loads this routes to the first item of the providers array, even before the application ones. Don't know why, but now it's working.
In light of the docs at: http://laravel.com/docs/master/controllers
Have you tried using the "use" statement? Your code would then look like:
<?php
namespace Canae\Http\Controllers\Admin;
use Canae\Http\Controllers\Controller;
class DogController extends Controller {
public function getIndex() {
echo "Hello!";die();
}
}
I'm also not sure why your namespace is "Canae\Http\Controllers\Admin" as the example shows "App\Http\Controllers" only. I'm not familiar with the specific structure of your project, but removing the "\Admin" might also help.