Routes with multiple parameters not working properly in Laravel 4? - php

I am trying to make my urls seo friendly. I want my urls to be like http://www.example.com/products/asus-zenfone-4-5649. I am using the following code. But it is not working properly.
In my routes.php,
Route::get('/products/{name}-{id}', 'ProductController#showProduct');
And in my controller,
public function showProduct($name, $id)
{
echo $name;
echo $id;
}
If the url is like http://www.example.com/products/motoe-5649, it displays
$name = motoe
$id = 5649 ---> Working fine
If the url is like http://www.example.com/products/asus-zenfone-4-5649, it displays
$name = asus
$id = zenfone-4-5649 ---> Not working properly
Note: Do not want to use like.
Route::get('/products/{name}/{id}', 'ProductController#showProduct');
How can I solve the same?

This Route::get('/products/{name}-{id}', 'ProductController#showProduct'); expects exactly two parameters. One named name after the /products/ and before - and one named id right after the -. So whatever exists after - is considered to be the id parameter no matter how many - it contains.
If you want to use more parameters then add them to your route and controller's method declaration. If you have optional parameters use the question mark next to them to make them optional in your route and assign default value to null in your method.
Route:
Route::get('products/{name}-{id}-{parameter1?}-{parameter2?}, ['as' => 'products', 'uses' => 'ProductController#showProduct']);
Controller's method:
public function showProduct($name, $id, $parameter1 = null, $parameter2 = null)
{
return $name.$id.$parameter1.$parameter2;
}
call route:
{{route('products', ['aName', 'anId'])}}
or
{{route('products', ['anotherName', 'anotherId', 'aParameter1', 'aParameter2'])}}
shall both work. Of course each will give a different url.

Related

Laravel 9 pass variable from route to controller

My problem:
I am currently trying to refactor some of my controllers. Doing so I found these two routes:
Route::get('/events', [EventsController::class, 'eventsList'])->name('event-list');
Route::get('/courses', [EventsController::class, 'allCoursesList'])->name('all-events');
they show different filter options in the frontend.
What I want to do:
Example Code:
Route::get('/courses', [
'all' => 1,
EventsController::class, 'courseList'
])->name('all-events');
so having the ability to pass a variable, in this case all to my controller. EventsController So I can check with if in my controller and handle these routes differently with only one function instead of two.
With the current solutions on StackOverflow, users are using:
'uses'=>'myController#index'
now if I try it like this:
Route::get('/courses', [
'all' => 1,
'uses' => 'EventsController#CourseList'
])->name('all-events');
I get the following error:
Target class [EventsController] does not exist.
Question:
What is the current, correct way, to pass a variable to a controller, from a route. In Laravel 9 and 10.
You can pass arbitrary data to the route as a parameter using the defaults method of Route:
Route::get('courses', [EventsController::class, 'list'])
->name('all-events')
->defaults('all', 1);
Route::get('events', [EventsController::class, 'list'])
->name('event-list');
public function list(Request $request, $all = 0)
{
...
}
There are also other ways of using the Route to pass data.
Laravel versions 8 and above do not automatically apply namespace prefixes. This means that when passing the class name as a string, you need to use the fully qualified class name (FQCN).
For example:
Route::get('/courses', [
'all' => 1,
'uses' => '\App\Http\Controllers\EventsController#CourseList'
])->name('all-events');
If it makes sense for your use case, you could also use URL parameters. For example, if your Course models belong to a Category model, you might do something like this:
Route::get('/courses/{category}', [EventsController::class, 'allCourseList');
Then in your countroller, you define the allCoursesList function like so:
public function allCoursesList(Category $category)
{
// ... do something with $category which is an instance of the Category model.
}
You can use Route Parameters to pass variable from route to controller.
// web.php
Route::get('/events/{all}', [EventsController::class, 'eventsList'])->name('event-list');
then in your controller you can access the variables
public function eventsList(Request $request,$all){
if($all==1){
//your logic for handling the condition when $all =1
}
// the remaining condition
}
if you have multiple parameters you can pass them like so, you can use ? for optional parameter.
// web.php
Route::get('/courses/{param_one}/{param_two?}', [EventsController::class, 'allCoursesList'])->name('all-events');
then in your controller you can access the variables
public function allCoursesList(Request $request,$paramOne,$paramTwo){
return $paramOne.' '.$paramTwo;
}
to access the query parameter
// web.php
Route::get('/evets', [EventsController::class, 'allCoursesList'])->name('all-events');
if the route were /events?timeframe=0&category=1 you can access the query parameter like so
public function allCoursesList(Request $request,$paramOne,$paramTwo){
$timeframe= $request->query('timeframe');
// do this for all the query parameters
}

I'm having trouble creating some basic filtering using Laravel

My index page displays all images from my images table with the newest submissions on top. I'm trying to add some basic filtering so I can grasp the concept but I'm doing something wrong. My idea is:
Add 2 <a> elements with URLs to www.domain.com and www.domain.com/ascending. If the user goes to www.domain.com, the images will be displayed in descending order and if he goes to www.domain.com/ascending they will be displayed in ascending order.
Then I make my home route Route::get('/', 'PagesController#index')->name('home'); have an optional parameter like Route::get('/{filter?}', 'PagesController#index')->name('home');
Based on the optional parameter, I'll send different $images variable to the view:
public function index($filter){
switch($filter) {
case 'ascending' : $images = Image::orderBy('created_at', 'asc')->get();break;
default : $images = Image::orderBy('created_at', 'desc')->get();
}
return view('home', ['images' => $images]);
}
As soon as I did this, I got 2 problems so far:
Firstly, when I go to www.domain.com, I get "Type error: Too few arguments to function App\Http\Controllers\PagesController::index(), 0 passed and exactly 1 expected"
Secondly, after adding the optional parameter to the route Route::get('/{filter?}', 'PagesController#index')->name('home'); I get send to my index page even when I'm going to URLs like http://example.com/admin or http://example.com/albums.
I believe this happens because my code assumes that /admin and /albums are the optional parameter in my http://example.com url and not a separate url like it should be.
Route::get('/{filter?}', 'PagesController#index')->name('home');
Route::get('/image/{id}', 'PagesController#specificImage')->name('specificImage');
Route::get('/tags', 'PagesController#tags')->name('tags');
So even if I go to the tags route, the index view will be displayed instead of the tags view.
you can do this
www.domain.com?orderby=asc
Route::get('/', 'PagesController#index')->name('home');
public function index(Request $request){
$images = array();
$images = Image::orderBy('created_at', $request->get('orderBy') ?? 'desc')->get();
return view('home', ['images' => $images]);
}
I suggest you use get params in this case to avoid conflicting urls. So that request to /
should now be
/?order=asc or /?order=desc
and rather switch the get param order to know whether to show the page in descending or ascending order.
First and foremost, using query parameter looks best for filtering in this situation instead of having two (or more) url endpoints.
However, if you want to stick with your implementation there are few things to do:
Declare your routes without leading slash, e.g:
Route::get('{filter?}', 'PagesController#index')->name('home')
Not so sure this does make any difference though, but something I personally watchout for (slashes everywhere)
Use optional path variable with restricted values, by using where() after the route declaration:
Route::get('{filter?}', 'PagesController#index')->name('home')->where('filter', 'ascending|');
It accepts ascending or nothing.
Pass a default parameter to your controller method:
public function index($filter = null)
{
.....
}
Just in case nothing was passed. This is one of the important points to note with optional path variables.
Finally, you can avoid if statement totally, by using a Ternary operator before making the query:
public function index($filter = null){
$order = $filter === 'ascending' ? 'asc' : 'desc';
$images = Image::orderBy('created_at', $order)->get();
return view('home', ['images' => $images]);
}

laravel controller function parameters

I'm trying to call a function inside one of my controller from the action() helper function. I need to pass a paramter to my function.
Here is the funciton I'm trying to call :
public function my_function($clef = 'title')
{
$songs = Song::orderBy($clef)->get();
return View::make('my_view', compact('songs'));
}
Here is the way I call it :
Author
The function is always running with the default value, even if I put anything else in my call. From what I can see in my address bar, the paramter seems to be sent along with the call :
http://www.example.com/my_view?clef=author
From the little I know, it seems correct to me, but since it doesn't work, I must come to the evidence that it isn't. What would be the cleanest way to call my function with the right parameter?
The reason why it's not working is because query strings aren't passed as arguments to your controller method. Instead, you need to grab them from the request like this:
public function my_function(Request $request)
{
$songs = Song::orderBy($request->query('clef'))->get();
return View::make('my_view', compact('songs'));
}
Extra tidbit: Because Laravel uses magic methods, you can actually grab the query parameter by just doing $request->clef.
Laravel URL Parameters
I think assigning parameters need not be in key value pair. I got it to work without names.
If your route is like /post/{param} you can pass parameter as shown below. Your URL will replace as /post/100
URL::action('PostsController#show', ['100'])
For multiple parameters say /post/{param1}/attachment/{param2} parameter can be passed as shown below. Similarly your url will be replaced as /post/100/attachment/10
URL::action('PostsController#show', ['100', '10'])
Here show is a method in PostsController
In PostsController
public function show($param1 = false, $param2 = false)
{
$returnData = Post::where(['column1' => $param1, 'column2' => $param2 ])->get();
return View::make('posts.show', compact('returnData'));
}
In View
Read More
In Routes
Route::get('/post/{param1}/attachment/{param2}', [ 'as' => 'show', 'uses' => 'PostsController#show' ] );
URL Should be: http://www.example.com/post/100/attachment/10
Hope this is helpful.

laravel route with parameter not coming from url

I have multiple routes that look like this:
Route::get('pending-submit', 'CasesController#cases');
Route::get('submited', 'CasesController#cases');
Route::get('closed', 'CasesController#cases');
I have been looking around even in the router API documentation and I can't find a solution for my requirement other than creating multiple methods within the controller. The method does the exact same query except for adding a where clause to identify the different status between each case, what I was trying to do is have a method like this
public function cases($whereStatus = 0){
return Cases::where('status', $whereStatus)->get();
}
Instead of doing this:
public function pendingCases(){
return Cases::where('status', 0)->get();
}
public function submitedCases(){
return Cases::where('status', 1)->get();
}
public function closedCases(){
return Cases::where('status', 2)->get();
}
But I can figure a way to pass that parameter to the method from the route so I now have to create a method for each route which does not seem necessary to me. I understand I could just generate urls with the get parameter in it but I wanted to make that cleaner, is there a way for me to add that parameter without having it in the url?
By the way, I also tried something like this which did not wok:
Route::get(
'pending-submit',
array(
'uses' => 'CasesController#cases',
'params' => array(
'filter' => 0
)
)
);
EDIT:
I understand I can make URLs like https://someurl.com/cases?status=0 and can also have URLs like https://someurl.com/cases which require a different method per route however what I want is have URLs like https://someurl.com/cases and have a single method where the parameter is passed by the router instead of me getting it from the request so I can do it like this:
public function myMethod($param){
/*
* Here I access the $param without calling Request::input('someparam');
* or without Request::path() where then I have to check what path is it
*/
echo $param; /* this should already have the param from the route */
}
EDIT:
#AndyNoelker what I have is 3 different values either 0, 1 or 2
I want to have something like this
Route::get(
'cases',
array(
'uses' => 'CasesController#cases',
'status' => 0 /* this is what I need */
)
);
If not possible from the routes.php it is fine, I just want to know, all other methods you are giving me is not what I want or asking for since I already know how to do those.
You are going to have to pass the desired status in through the URL - otherwise the route will have no way of knowing which status you desire. You can either do it through URL query parameters or as a fully-fledged route parameter. I would personally suggest using a query parameter in this case, but I'll show you both.
Using Query parameters
URL
example.com/cases?status=1
Routes
Route::get('cases', CasesController#cases);
CasesController
public method cases(Request $request)
{
$input = $request->all();
$status = $input['status'];
return Cases::where('status',$status)->get();
}
Using Route parameters
URL
example.com/cases/1
Routes
Route::get('cases/{id}', CasesController#cases);
CasesController
public method cases($id)
{
return Cases::where('status',$id)->get();
}
Of course if you'd prefer that they use a slug or something other than a unique id in the route, then you'd have to adjust for that in your query, but this should give you the right idea.
I think you're looking for route parameters:
Route::get("/cases/{case}", "CasesController#cases");
This will match any of the following:
some_url/cases/pending-submit
some_url/cases/submited
some_url/cases/closed
...
Then, your function public function cases in CasesController would look like this:
public function cases($case){
if($case == "pending-submit"){
// Do Something
} else if($case == "submited") {
// Do Something Else
}
// OR
return Cases::where('status', $case)->get();
}
Etc etc. Look more into url parameters here: Documentation
Route::get('pending-submit', array('status' => 0, 'uses' => function(){
$CasesController = $app->make('CasesController');
return $CasesController->callAction('cases', $parameters = array());
}));
If I am understanding your question correctly, this should work.
Web Route
Route::get('pending-submit', [
'as' => 'pending',
'uses' => 'CasesController#cases',
'status-id' => '0'
]);
And, you can access the parameter passed with the route like below,
In Controller
$request->route()->getActions('status-id')
In View
{{ request()->route()->getAction('status-id') }}
Tested and perfectly works in L5.6

Some mandatory parameters are missing ("url_tag") to generate a URL for route "customUrl". Laravel 4

I am trying to break out a resource ("fans") into separate routes so I can have custom urls for the individual resource pages, as opposed to using just $id.
So instead of this:
Route::resource('fans', 'FansController');
I have broken it into this:
Route::get('fans/{url_tag}', array('as' => 'customUrl', function($url_tag)
{
$fan = Fan::where('url_tag','=',$url_tag);
return View::make('fans.show', compact('fan'));
}))
->where('url_tag', '[A-Za-z]+');
Route::get('fans/{id}', function($id)
{
// do something with $id or
return Redirect::route('customUrl');
})
->where('id', '[0-9]+');
In the fans controller, I have this:
public function show($id)
{
$fan = Fan::find($id);
return View::make('fans.show', compact('fan'))
->with('fans', Fan::all())
->with('latest_fan_likes', Fanartist::latest_profile_fan_likes($id));
}
Basically I would like the page /fans/$id to appear as /fans/$url_tag (where url_tag is another column in the db, that is unique). But I would like it to have all of the properties of the resource, so I can call $fan->column directly.
When I run this, I get the error:
Some mandatory parameters are missing ("url_tag") to generate a URL for route "customUrl".
Any idea what is going on or what is wrong? I am using Laravel 4. Thank you.
You probably are trying to generate an URL, somewhere else in your code, in a controller or even a view, something like (may not be exactly that!):
URL::route('customUrl');
or
route('customUrl');
But you need to provider the url_tag:
URL::route('customUrl', array('url_tag' => 'something');
For you could be something like:
URL::route('customUrl', array('url_tag' => $fan->url_tag);

Categories