Let say I have my user controller and there are action_index(), action_login(), action_logout() action_profile($userid) methods in it. I want to make a routing that
www.mysite.com/user/xxxx
checks the xxxx part of the url and if it is not one of (login,logout,index) it calls action_profile(xxxx) method.
Now I am doing it like this:
my routing routs all www.mysite.com/user/xxxx type of requests to action_index and it checks whether xxxx is a method name or not. If it is not a method name it calls action_profile(xxxx)
However, I think it is possible in a better way. How can I do it better?
Hmm I'm not sure if I understand what you're asking. Routes in laravel are on a first match basis.
So you could just add the following to your routes.php:
Route::get('user/(:num)', 'user#profile');
Route::controller('user');
The first line is for routing user/xxx to action_profile() in user controller where xxx is any numerical value. While the second will maps any other URI (user/***/***) to corresponding user controller's methods. That means it automatically maps user/login to action_login(), user/register to action_register() and so on.
I would recommend you avoid using Route::controller() in this instance. While it can be fine to use in some cases, for what you're after it would be better to map to the routes.
You could do it like so.
Route::get('user', 'user#index');
Route::get('user/(:num)', 'user#profile');
Route::get('user/(:any)', 'user#(:1)');
Or you could be a little stricter with your last route.
Route::get('user/(login|logout)', 'user#(:1)');
My reasoning for recommending you avoid Route::controller() is that it does create duplicates to some content. For example, yoursite.com/user will by duplicated on yoursite.com/user/index. This can be bad for search engine optimization.
Mapping to your actions gives you that extra flexibility and control.
Related
After some playing around and research it seems that Route::when() and Route::filter() are deprecated in Laravel 5+. I need to be able to route all URIs that begin with members to the same controller. For example:
Route::get('members/home', 'MembersController');
Route::get('members/view/all', 'MembersController');
Route::get('members/any/possible/route', 'MembersController');
I will not know all the possible routes that begin with members, as they will be stored in my database. Is there a wildcard equivalent to what Laravel 4.2 had that I can use in 5.4?
The idea is to have any routes that begin with certain prefixes to go to its specified controller, then the controller will compare the entire URI string and retrieve the page that has the matching slug in the db.
You can do this using a route parameter that allows any value. E.g. (.*). You'll then need to handle all of the requests from a single controller action.
Route::get('members/{action}', 'MemberController#all')->where('action', '(.*)');
To take this further, if you don't know that your requests will all be GET requests, you could use the :any method type.
Route::any('members/{action}', 'MemberController#all')->where('action', '(.*));
Route::get('/members/{section}', 'MembersController#index' )
->where(['section' => '.*']);
Or better yet you can use a group route. It's faster and optimizes your app.
Route::prefix('members')->group(function () {
Route::get('{section}', 'MembersController#index' )
->where(['section' => '.*']);
});
I'm trying to set up a routing prefix in cakephp 3 so any URLs starting with /json/ get the prefix key set and I can change the layout accordingly in the app controller. Other than that, they should use the usual controller and action. I have added the following to routes.php
$routes->prefix('json', function($routes) {
$routes->connect(
'/:controller/:action/*',
[],
['routeClass' => 'InflectedRoute']
);
});
I want to direct all requests with json as first url segment to controller specified in second url segment. e.g. /json/users/add_account_type/ goes to users controller. However when accessing this URL I get the message:
Error: Create the class UsersController below in file:
src/Controller/Json/UsersController.php
whereas I want it to be using
src/Controller/UsersController.php
I think this should be possible but I can't quite see what I'm doing wrong when consulting the book. Have partly based my code on: CakePHP3.x controller name in url when using prefix routing
Thanks a lot in advance
That's simply how prefix routing now works in 3.x, as explained in the docs, prefixes are being mapped to subnamespaces, and thus to separate controllers in subfolders.
http://book.cakephp.org/3.0/en/development/routing.html#prefix-routing
If you'd wanted to change that behavior (I don't really see why), one way would be to implement a custom ControllerFactory dispatcher filter.
http://book.cakephp.org/3.0/en/development/dispatch-filters.html
On a side note, the RequestHandler component supports layout/template switching out of the box, so maybe you should give that a try.
http://book.cakephp.org/3.0/en/controllers/components/request-handling.html
http://book.cakephp.org/3.0/en/views/json-and-xml-views.html
Prefix routing is a way of namespacing parts of your routes to a dedicated controller. It seem that what you want is a scope and not a prefix, for what you describe:
Router::scope('/json', function($routes) {
$routes->fallbacks('InfledtedRoute')
});
As I am new to the laravel 4 after spending some few months in Codeigniter, I went through the lots of tutorials about laravel and one thing I want to be clear is what is the actual difference between Routes and Controller in laravel, because we can create and generate view in both controller and routes too. Will anyone explain me in brief when to use routes and Controller in laravel? Because in other Framework we need routes to specify some particular URL's within the apps and Controller were used to do some real tasks but in laravel I didnt get the main concept of Routes except the routing mechanism?
In Laravel, you can totally skip controllers and do the task of performing business logic and generating the view in the routes.
E.g I have a link b2.com/getUsers so in routes.php I can write:
Route::get('/getUsers',function()
{
$users=User::all(); //select * from users
return View::make('allUsers')->with('users',$users);
}
So, here to serve the request b2.com/getUsers, we didn't use controller at all and you can very well do this for handling all requests in your application, both get and post.
But then, if your application is large and have 500+ url's with complex business logic then imagine putting everything in one routes.php. It will totally make it criminally messy and whole purpose of architecture will be defeated. Hence what we usually do is, reserve routes.php for routing only and write all business logic (along with generation of views inside controllers)
So the same example can be solved as:
To handle link: b2.com/getUsers, in routes.php
Route::get('/getUsers', array('before' => 'auth', 'uses' => 'MyController#getUsers'));
MyController has the method getUsers defined like this:
public function getUsers()
{
$users=User::all(); //select * from users
return View::make('allUsers')->with('users',$users);
}
I usually create a controller for related activities e.g for login/signup/logout. I create AuthController and all the links related to those activities are routed to AuthController through routes.php.
The fact that you can get views or do a lot of things in Routes::any() is against MVC and separation of logic.
In Route::get("admin", function(){}), you indeed have a fast access to your route callback, which otherwise in a standard fashion must just be bound to controller. But Laravel allows you to do your job there in a closure (function(){}), instead of binding it to a controller. Anyway, it lets you, but you'd better avoid it. In Route::get() you only should go with your 'routing' and nothing more.
There is no reason for you to use callbacks in Route unless for testing or some trivial requests. So, better to avoid this:
Route::get("admin", function(){
return View::make("admin_index");
});
And rather go with this:
Route::controller("admin", "AdminController");
And in your AdminController.php :
// I mean create a file named AdminController.php in controllers directory under app.
class AdminController extends Controller
{
function getIndex()
{
return View::make("admin_index");
}
}
Read more about Route::controller and restful controllers.
Some Notes:
Having the ability to add closures in your Routes allows you to make
complex decisions on Routes and have a powerful routing system.
These callbacks let you add conditions to your route.
Having Controller separated from you Routes makes you application
more extensible, less confusing and makes other coders more
comfortable in future.
It allows you to focus better on your problem and finding solution,
this physical separation is very important. Having View::make()
inside your Route stirs all problems into each other and makes up a
confusion for the coder.
Let's see what we have in both cases:
In CodeIgniter, a route is just pointing your request to a specific method of your controller:
$route['blog/joe'] = "blogs/users/34";
Here when you visit application.com/blog/joe, you will invoke the controller BlogsController, call the method users() and pass 34 as the first parameter. Nothing else. As they put it, a route in CI is just a one-to-one relationship between a URL string and its corresponding controller class/method.
Now, in Laravel, you have a lot of possibilities:
You can directly return a simple response
You can return a view
You can point the request to a specific controller and a method
You can write some logic in a closure and then decide what you want to do
You can add some additional functionality to them, like attaching filters, checking parameters upon a regex, give them separate names, etc., but this is the main functionality.
What's the reason for being able to do so much stuff? It gives you the power to use them in any way you need. Examples:
Need a small website, rendering static HTML? Use them like this:
Route::get('/', function()
{
return View::make('greeting');
});
Need a bigger application using the traditional MVC pattern? Use like this:
Route::get('user/{id}', 'UserController#showProfile');
Need a RESTful approach? No problem. This will generate routes for all the CRUD methods:
Route::resource('photo', 'PhotoController');
Need something quick and dirty to handle a specific Ajax request? Keep it simple:
Route::post('foo/bar', function()
{
return 'Hello World';
});
TL;DR: For very simple things without or with very little logic, use them instead of controllers. Otherwise, always stick to the MVC principles and route to your controllers, so that they're the ones who do the actual work.
I'm just new to Laravel but I immediately fell in love with it. As a not so super experienced php developer I do find the official documentation, although very expansive, somewhat complicated to use and find everything I need.
My question is about the Routing component. As the documentation states you can assign a route to a controller with the Route::controller method. So if I want a Blog controller for all /blog/ routes I assign it like this:
Route::controller('blog', 'BlogController');
So then if I'd like to acces all my blog posts I acces the the getIndex method by www.foo.com/blog or www.foo.com/blog/index
But let's say I'd like to be able to display categories via a getCategory method. My url would look like www.foo.com/blog/category and if, for example, I want to get the news category from the DB by slug, I'd like to use: www.foo.com/blog/category/news as the URI.
My question now is, how do I pass the slug to the url and access it in the getCategory method? Do I need specify it via Route::get('blog/category/{slug}', 'BlogController#getCategory') or is there a way to use Route::controller('blog', 'BlogController') and to send and acces parameters from the URL in the getCategory method?
I already tried to find it via google and in the official documentation, but I couldn't find a crystal clear answer to this problem...
You can simply add parameters to your getCategory method:
public function getCategory($category) {
die($category);
}
If you initialize it to null in the parameter list, it becomes optional. Alternatively, you can always pull parameters from the Input object but they would need to be passed in querystring format:
$category = Input::get('category');
With that said, I'd caution against using the Controller route. It's handy and mimics traditional MVC frameworks, but I believe it's planned to be deprecated -- and honestly, you miss out on some pretty flexible features.
using Route::controller('blog', 'BlogController'); allows you to define a single route to handle every action in a controller using REST naming conventions.then you have to add methods to your controller, prefixed with the HTTP verb they respond to. That means if you have a method called getIndex() it will be executed when there is a GET request to the url "yoursite.com/blog".
To handle POST requests to the same url add a method prefixed with post(ex: postComment()) and so on for other http verbs PUT, PATCH and DELETE.
I think you want something more customized, so you can use a resource controller:
Route::resource('blog', 'BlogController');
This will generate some RESTful routes around the blog resource, run php artisan routes in your project folder to see the generated routes, it should be something like this:
Verb Path Action Route Name
GET /blog index blog.index
GET /blog/create create blog.create
POST /blog store blog.store
GET /blog/{blog} show blog.show
GET /blog/{blog}/edit edit blog.edit
PUT/PATCH /blog/{blog} update blog.update
DELETE /blog/{blog} destroy blog.destroy
in the action column are the functions that you should have in the controller.
If you want to define more routes you can simply do it with Route::get or Route::post in the routes.php file
I hope this will make it more clear for you, enjoy routing with Laravel!!!
How can I rewrite the following codeigniter url
localhost/test_project/pages/show_page/11
to
localhost/test_project/pages/11
and is it possible to further reduce like:
localhost/test_project/11
Thanks.
You should edit this file: application/config/routes.php.
Let's assume you have a pages controller and a show_page method with receives an id as a parameter (just as you said).
your URL is like localhost/test_project/pages/show_page/11
I assume that the parameter is always a number, so using wildcards as described here you can add the following to your routes.php file:
$route['pages/(:num)'] = "pages/show_page/$1";
So your URLs will be like localhost/test_project/pages/3. This is like saying if anyone tried to visit localhost/test_project/pages/3, he/she actually means localhost/test_project/pages/show_page/3.
For urls like localhost/test_project/3 you can add this:
$route['(:num)'] = "pages/show_page/$1";
You've a few options. These are in descending order of priority.
First there is routes.php, which is the generally preferred way of handling things (information already provided, but here it is again).
You can also add a _resolve method to a controller (which means that CI needs to get to your controller to begin with), and
finally you can override the CI_Router library, the class which actually returns the route to go to.
Seriously, don't override CI_Router unless you know what you're doing.