Is it unconventional and therefore ill-advised to use the match() method to determine which controller method to use under 1 uniformed named route? I have this code:
Route::match(['get', 'post'], '/add/lecture/{course}', [
'as' => 'addLecture',
'uses' => Request::isMethod('post') ? 'Main#addLecture':'Main#showAddLecture'
]);
Which works as expected. But I just want to know if this is a feasible solution, or if I should stop being lazy and create two separate routes (I am not using Route::resource() for a particular reason, so please don't advise me to use that for basic CRUD). I don't mean for this question to be subjective, I presume there is an objective reason as to why this isn't employed very often?
It looks like hack. It's not readable and can stop working after random minor Laravel update. In my opinion it's better to create two explicit routes.
Related
I'm curious about your thoughts.
Let us say I have these two methods:
Route::get('/shoppingcart', 'CartController#index')
->name('cart');
Route::post('/shoppingcart', 'CartController#store')
->name('cart.store');
I just wanted to write:
Route::apiResource('shoppingcart', 'CartController');
Would you say it is bad because other routes are registered as well? (Show, Destroy, Update)
You can use Partial Resources to only include certain crud operations.
Route::resource('shoppingcart', 'CartController')->only([
'index', 'store'
]);
I have 3 domains which, on my local server, take the format:
mydomainfirst.local
mydomainsecond.local
mydomainthird.local
In my routes.php file, I have the following:
Route::group(array('domain' => '{domain}.{suffix}'), function() {
Route::get('/', 'Primary#initialize');
});
The idea is to take the $domain variable in my controller and extract the first/second/third part from it, which works fine. However, now my site is online, this routing file no longer works and throws a Http-not-found exception. After a while, I have figured that the problem is that the domains have now taken the format mydomainfirst.co.uk. Because there are now 2 parts to the domain suffix, it seems I need to do this:
Route::group(array('domain' => '{domain}.{a}.{b}'), function() {
Route::get('/', 'Primary#initialize');
});
To get it to work. Which is stupid. How can I tell it to just accept any suffix? Is there an 'anything' wildcard I can use?
I have tried a few things like this answer but it doesn't work with route groups.
EDIT: It seems the Enhanced Router package would at least enable me to add a where clause to the route group, but does it solve the problem of how to set a wildcard that will match an indeterminate number of segments? I need something like:
{domain}.{anything}
That will match both:
mydomainfirst.local AND mydomainfirst.co.uk
?
Ok let me first say that the code of this package actually looks good and should work. Even if you can't get it running by installing you could take the files and use the code with your own service provider etc.
But there's also a kind of quick and dirty solution. (Actually the package does it pretty similar, but it looks a lot nicer ;))
First, here's how you can do it for one route:
Route::group(array('domain' => '{domain}.{tld}'), function(){
Route::get('/', 'Primary#initialize')->where('tld', '.*');
});
So the where condition for the route group actually gets set on the individual route.
Of course you don't want to do this for every route inside that group so you can use a simple foreach loop:
Route::group(array('domain' => '{domain}.{tld}'), function($group){
Route::get('/', 'Primary#initialize');
foreach($group->getRoutes() as $route){
$route->where('tld', '.*');
}
});
Note: The loop needs to come after all routes. Otherwise they won't registered and therefore not returned with getRoutes()
I want to do some pre and post processing of requests like handling authentication, loading contextual data, performance timings and things like that. Coming from Django there's a concept of MIDDLEWARE_CLASSES that lets me handle the request in various stages: https://docs.djangoproject.com/en/dev/topics/http/middleware/
Currently it seems like each Controller has to do the same setup and load, in the constructor which isn't ideal because if the constructor fails, the class doesn't get initialized which has subtle but important consequences. I want to move this global handling to a global place.
Any suggestions?
There is not.
This might be helpful.
Codeigniter forum
You need to use hooks for this, Edit your application/config/hooks.php
$hook['post_controller_constructor'][] = array(
'class' => 'Autologin',
'function' => 'cookie_check',
'filename' => 'autologin.php',
'filepath' => 'hooks'
);
I recently stumbled upon this question so even tho it has been 6 years since this question was asked, I am answering in case it helps anybody else like me.
I have found CodeIgniters has "filters" which can be used for that same purpose:
http://codeigniter.com/user_guide/incoming/filters.html?highlight=filters
Actually there is not middleware routing structure in any codeigniter framework until now. But some guys has written a bunch of code to implement that.
I have found it usable for some purposes
i need to ask solution of my problem
usually people make url path like mylaravelsite/products/{id}
ex. mylaravelsite/products/1
i'm build a website but i need to create url path like mylaravelsite/products/{title}
example:
mylaravelsite/products/name-of-product
after doing The Alpha solution and thats works :)
You can do it. It doesn't matter if you want to use a parameter as slug/string instead of an id/numeric. Just declare the route the same way you would have declared for a numeric id parameter. For example, you may declare a route like this:
Route::get(
'/products/{title}',
array('uses' => 'ProductController#show', 'as' => 'product.show')
);
Then, the URL for this route could be http://yourdomain.com/products/name-of-product.
The reason people use an id because, most often people use an auto-incremented numeric id a primary key in their database and it's a good idea to use something like that which would be unique. You just make sure that your products are unique as well and insert them as slug in your database using:
$product->title = Str::slug(Input::get('product_title'));
Also, you may use a where condition in your route to make sure that the product name supplied to the route is an string using something like this:
Route::get(
'/products/{title}',
array('uses' => 'ProductController#show', 'as' => 'product.show')
)->where('title', '[A-Za-z-]+');
This is a macro I've used for same reason (From Slug to Title):
Str::macro('toTitle', function($str){
return ucwords(str_replace('-', ' ', $str));
});
You may use a normal helper function as well and maybe you may use preg_replace if needed.
I'm using Basset 4 to manage assets.
In the config file i'm declaring a collection 'admin'
return array(
'collections' => array(
'admin' => function($collection)
{
$collection->directory('assets/js', function($collection)
{
$collection->add('vendor/jquery-1.9.1.min.js');
});
},
),
...
)
later in a view, I would like to add an extra file in admin collection.
I've try the following code, but it doesn't work:
Basset::collection('admin', function($collection)
{
$collection->add('function.js');
});
Is there a way to add file into a collection from a view or from a controller?
Thank you
Basset isn't really designed to work like that. You should be defining all your assets within that initial call, even though the ability to add assets throughout the execution of an application is possible, it's not recommended.
When building a collection assets that are added for a particular route won't be available to the builder since Artisan doesn't fire any routes, etc.
Adjusting a collection in numerous places can often lead to confusion further down the line.
I know this isn't ideal as you're probably looking at implementing page specific JavaScript, correct? I've thought about it but can't really think of a clean solution (suggestions?), although I've heard of people assigning a unique ID to the body or perhaps some classes that their JavaScript can then attach themselves to.
It's not brilliant but that's the best I can give you at the moment.