I have the following path inside my / Scope:
$routes->connect('/api/:controller/:action', ['prefix'=>'api'], ['routeClass' => 'DashedRoute']);
And on my src/Controller/UsersController.php i have api_index()
But when i go to the url api/Users/index it says Controller not found, because is asking me to add another UsersController inside a subfolder named Api on Controller folder.
Untill Cakephp 2.x using this behavior worked fine for me, how can i achieve the same behavior on CakePHP 3.x like it was on Cakephp 2.x ?
Thank you very much !
From cakephp book
Prefix Routing
static Cake\Routing\Router::prefix($name, $callback)
Many applications require an administration section where privileged users can make changes. This is often done through a special URL such as /admin/users/edit/5. In CakePHP, prefix routing can be enabled by using the prefix scope method:
use Cake\Routing\Route\DashedRoute;
Router::prefix('admin', function (RouteBuilder $routes) {
// All routes here will be prefixed with `/admin`
// And have the prefix => admin route element added.
$routes->fallbacks(DashedRoute::class);
})
;
Prefixes are mapped to sub-namespaces in your application’s Controller namespace. By having prefixes as separate controllers you can create smaller and simpler controllers. Behavior that is common to the prefixed and non-prefixed controllers can be encapsulated using inheritance, Components, or traits. Using our users example, accessing the URL /admin/users/edit/5 would call the edit() method of our src/Controller/Admin/UsersController.php passing 5 as the first parameter. The view file used would be src/Template/Admin/Users/edit.ctp
You can map the URL /admin to your index() action of pages controller using following route:
Router::prefix('admin', function (RouteBuilder $routes) {
// Because you are in the admin scope,
// you do not need to include the /admin prefix
// or the admin route element.
$routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
});
https://book.cakephp.org/3/en/development/routing.html#prefix-routing
Related
I'm working with Laravel 4.2. I have an app that's routing to the wrong view, although the URL is correct. On a button click, it's supposed to route to users.create (UsersController#create), but is instead routing to UsersController#show. The resolved URL is correct, though, and the DOM element has the correct URL listed. Can anyone help me out?
Here is my Routes file:
// Home page
Route::get('/', 'BaseController#index');
// Define User model to pass through routes
Route::model('user', 'User');
// Create custom route for editing a user
Route::get('users/edit/{user}',
array('as' => 'users.edit', 'uses' => 'UsersController#edit'));
// Create custom route for showing a user
Route::get('users/{user}',
['as' => 'users.show', 'uses' => 'UsersController#show']);
// Remaining routes
Route::resource('users', 'UsersController',
array('except' => array('edit', 'show')));
Here is my UsersController with the two functions in question:
class UsersController extends \BaseController {
protected $user;
public function create()
{
return View::make('users/create');
}
public function show($user)
{
return View::make('users/show', ['user' => $user]);
}}
And here are the relevant results from php artisan routes:
GET:HEAD users/{user} users.show UsersController#show
GET:HEAD users/create users.create UsersController#create
Thanks for your help!
Edit:
The answer to the problem was to simply re-order the routes so that the resource is defined first. I was aware that Laravel grabs the first route that matches a URI, but I still don't understand why a route that isn't passed a user object would select a route defined as users/{user}. Furthermore, I was accessing the route via link_to_route(), that is to say, by name. Why would Laravel pick a different route from the one I explicitly named?
I suppose these questions are beyond the scope of the initial question, but I would greatly appreciate further explanation from someone. Problem solved!
The first thing that jumps out at me is there is no route for "create". There is the "restful" controller, but maybe you want to just try putting the route in. I'm slightly uncomfortable using restful routes when serving html. In the project i'm working on i've been trying to preserve those for data/json transmission, in order to support outside api action.
I think your routes setup recognizes create as {user} in user/{user}, thus redirect to user/show/create as your "custom route for showing a user" setup.
You may have to avoid getting string variable right after users/ route.
I basically have to implement API commands for an external app using their URI pattern. I want to implement all the methods in a Controller so I added the following in routes.php:
Route::controller('/ch', 'CHController');
I have to implement GET /ch/api_function/param1/param2. The issue is the external API's URI uses the '_' syntax for their action and laravel can't route it correctly to the right function.
The Laravel documentation for controllers here http://laravel.com/docs/controllers#resource-controllers suggests
If your controller action contains multiple words, you may access the action using "dash" syntax in the URI. For example, the following controller action on our UserController would respond to the users/admin-profile URI:
public function getAdminProfile() {}
Just define the routes manually in your routes file
Route::group(['prefix' => 'ch'], function()
{
Route::post('/api_function/{param1}/{param2}', ['uses' => 'CHController#function1']);
Route::post('/another_function/{param1}', ['uses' => 'CHController#function2']);
}
I would like to create an administrator interface for my Laravel project, which is completely separated from the user side.
For example, in Yii framework I can make a module and this will ensure full separation from the user side. Inside a module I can use separate folder structure etc.
This is really a broad question and one answer can't cover everything about best practice for admin controllers or back end management but there are some basic concepts for building an Admin Panel:
// Keep all of your admin routes inside something like this
Route::group(array('prefix'=> 'admin', 'before' => 'auth.admin'), function() {
// Show Dashboard (url: http://yoursite.com/admin)
Route::get('/', array('uses' => 'Admin\\DashBoardController#index', 'as' => 'admin.home'));
// Resource Controller for user management, nested so it needs to be relative
Route::resource('users', 'Admin\\UserController');
});
// Other routes (Non-Admin)
Route::get('login', array('uses' => 'AuthController#showLogin' 'as' => 'login'));
By using a prefix you may separate all admin routes whose url will be prefixed with admin so, if you have a users controller for user management in back end then it's url will be prefixed with admin, i.e. site.com/admin/users. Also using a before filter you may add an authentication for all admin controllers in one place, that means, to access all of your admin controllers user must be logged in and the filter could be something like this:
Route::filter('auth.admin', function($route, $request, $args){
// Check if the user is logged in, if not redirect to login url
if (Auth::guest()) return Redirect::guest('login');
// Check user type admin/general etc
if (Auth::user()->type != 'admin') return Redirect::to('/'); // home
});
For, CRUD (Create, Read, Update, Delete) use a resourceful controller, for example, the UserController in an example of resourceful route declaration.
Use repository classes (Repository Pattern) for decoupling of dependencies, read this article.
Always use a named route, i.e. array('as' => 'routename', 'uses' => 'SomeController#method'), this is an example of naming a route. Named routes are easy to refer, i.e. return Redirect::route('admin.home') will redirect to site.com/admin because we have used admin.home in as to assign the name for that route.
Keep admin controllers in a separate folder and use a namespace for example, Admin\\DashBoardController#index controller should be in app/controllers/admin and your DashBoardController controller should look like this:
<?php namespace Admin;
class DashBoardController extends \BaseController {
public function index()
{
//...
}
}
There are more but it's enough to start with, read articles online and must read the documentation.
If you are familiar with composer you can import in packages (aka modules)
There is a widely available module with multi level interface already called Sentry 2.0:
https://github.com/cartalyst/sentry
You could also make your own if needed if the one I propose is too complex.
There is even a "laravel-ready" version of sentry.
I use the same directory structure that you would like to use on most (if not all) my Laravel projects. Basically, I keep admin views and admin controllers separate from the front-end ones.
Examples:
Controllers:
app/controllers/admin/Admin*Name*Controller.php
app/controllers/site/*Name*Controller.php
Views:
app/views/admin/some_folder/index.blade.php
app/views/site/some_folder/index.blade.php
I would also suggest that you install this laravel project https://github.com/andrewelkins/Laravel-4-Bootstrap-Starter-Site which will give a very good starting on how to organise things in your laravel project. It also has the same folder structure you would like to use.
Good luck.
I have this blog resource which has the usual CRUD methods.(index, create, store, show, edit, update, destroy).
I have the following route in my routes.php:
Route::resource('blog', 'PostsController');
but I want to restrict all but index and show.
so I have
Route::get('blog', 'PostsController#index');
Route::group(array('before' => 'auth'), function()
{
Route::resource('blog', 'PostsController');
});
which is fine for index but I don't know how to route the show method ? Or is there another way? Instead of routing the resource should I route every URI individually and put the ones I want restricted in my restricted access route?
Cheers
Laravel has a feature that lets you specify filters in the controllers' __construct method using $this->beforeFilter. This function takes a second argument that lets your provide exceptions (or enable the filter only for certain methods). Try using your original routes file and set up your controller like this:
class PostsController extends BaseController {
function __construct() {
// ...
$this->beforeFilter('auth', array('except' => array('index', 'show')));
// ...
}
// ...
See Controller Filters in the Laravel documentation. It's not entirely well-documented, but you can also start a deeper journey into the guts of Laravel from here.
In Laravel 5 you use middleware function instead like this:
$this->middleware('auth', array('except' => array('index', 'show')));
I have built admin of my cakephp site using prefix 'webadmin'. Now I need to change this to something like 'aRRT6nnf'.
I changed the admin prefix in core.php, routes.php and even changes the filenames in views folder but this gives the following error:
Error: The requested address '/aRRT6nnf' was not found on this server.
I made following changes to accomplish this:
//core.php
Configure::write('Routing.prefixes', array('aRRT6nnf'));
//routes.php
Router::connect('/aRRT6nnf', array('controller' => 'dashboard', 'action' => 'index', 'prefix'=>'aRRT6nnf', 'aRRT6nnf'=>true));
Any help would be appreciated.
Have you changed the prefixes on your controller methods
When using admin routing in Cake 1.3 your controller actions need to be prefixed with the route they pertain to for example take route admin your Dashboard controller should be something like this
class DashboardController extends AppController
{
public admin_index() {
}
So in your specific case you would need to change them to
public aRRT6nnf_index() {
}