Passing a param as a query string or part of url? - laravel

Should you pass a param to a GET request as part of the URL or as a query string, for example?
Route::get('/image/{id}', 'ImageController#get');
Should we do:
/image/10
/image?id=10

The question of which approach should you do is one I won't answer, as that's entirely up to you to determine which method you'd want to do.
With your current Route, only one of the supplied URLs would hit the get() method in your ImageController.
/image/10 matches your Route, and would be used as:
public function get($id){
dd($id); // 10
}
/image?id=10 doesn't match your URL, and would be a 404 due to a missing parameter. The route would need to be modified to:
Route::get('/image', 'ImageController#get');
And your Controller method would need to be:
public function get(Request $request){
$id = $request->input('id');
dd($id); // 10
}
There's pros and cons to each approach, Query String params are good for multiple required and/or option parameters, while URL params are better suited to single required/optional. Multiple optional URL params is not something that is supported, so keep that in mind.

Related

Laravel: Multiple Route to Same Controller

May I know how can I make just a single route so I don't have to repeat it? Thanks in advance.
Route::get('/url', 'CtcFormController#index' )->name('CtcForm.ch');
Route::post('/url/submit', 'CtcFormController#submit')->name('CtcForm.submit');
Route::view('/url/submitted', 'form.submit')->name('CtcForm.submit');
Route::get('/url2','CtcFormController#store')->name('CtcForm.eng');
Route::post('/url2/submit', 'CtcFormController#submit')->name('CtcForm.submit');
Route::view('/url2/submitted', 'form.submit')->name('CtcForm.submit');
As per your given example, you want to handle the variable part of the route which is /url/ and /url12/. Yes! you can handle there both different route using a single route in ways:
Use route variable to handle dynamic url values i.e. url, url2,url3...url12 and so on.
Route::get('/{url}', 'CtcFormController#index' )->name('CtcForm.ch');
Route::post('/{url}/submit', 'CtcFormController#submit')->name('CtcForm.submit');
Route::view('/{url}/submitted', 'form.submit')->name('CtcForm.submit');
Now in your controller methods handing above routes receive extra parameter $url like:
In controller CtcFormController.php class:
public function index(Request $request, string $url) {
//$url will gives you value from which url request is submitted i.e. url or url12
//method logic goes here ...
}
Similarly, method handling /{url}/submit route will be like:
public function submit(Request $request, string $url) {
//method logic goes here ...
}
Let me know if you have any further query regarding this or you face any issue while implementing it.

Checking what action would be called by a given url string

In Laravel (5.6) I want to see what route would be called by a given url string. Say the url was "report/sales" I would like to check what function from what controller would be called, eg could be "ReportController#salesreport". It's sort of the opposite of the action() function but I can't find anything like it.
Would be wonderful if anyone has a solution.
Laravel doesn't provide a direct means of checking for a Route matching a URI, likely because it performs multiple assertions for host, method, etc. during matching. Almost all matching uses a Request object for comparison.
The quickest way to use existing functionality is to manually create a Request object with the details you wish to match against (HTTP method, URI, etc.). Once you've done that, you can grab the Router and look:
$request = \Illuminate\Http\Request::create('/report/sales');
$routes = Route::getRoutes(); // Or, you can get the Router directly, through app(), etc.
try {
$route = $routes->match($request);
$action = $route->getActionName();
} catch (\Symfony\Component\HttpKernel\Exception\NotFoundHttpException $e) {
// No matching route was found.
} catch (\Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
// The URI matches a route for a different HTTP method
}
You could retrive the Router instance through the Container and retrive all routes, then filter the retrived routes to match only the ones that has url attribute equal to the given url string. Finally, pluck the matching controller action for each route.
$routes = app('router')->getRoutes()->getRoutes();
$target = 'report/sales';
$actions = collect($routes)->filter(function($route) use ($target) {
return $route->uri == $target;
})->pluck('action.controller');
dd($actions);
If you only need to get one route only (eg: no routes with the same URL but different verbs), just replace filter with first to stop at the first matching occurence. As a result you will no longer need pluck, as you will be given a Route instance, not a collection:
$routes = app('router')->getRoutes()->getRoutes();
$target = 'report/sales';
$action = collect($routes)->first(function($route) use ($target) {
return $route->uri == $target;
})->action['controller'];
dd($action);

Laravel Routes and 'Class#Method' notation - how to pass parameters in URL to method

I am new to Laravel so am uncertain of the notation. The Laravel documentation shows you can pass a parameter this way:
Route::get('user/{id}', function ($id) {
return 'User '.$id;
});
Which is very intuitive. Here is some existing coding in a project I'm undertaking, found in routes.php:
Route::get('geolocate', 'Api\CountriesController#geolocate');
# which of course will call geolocate() in that class
And here is the code I want to pass a variable to:
Route::get('feed/{identifier}', 'Api\FeedController#feed');
The question being, how do I pass $identifier to the class as:
feed($identifier)
Thanks!
Also one further sequitir question from this, how would I notate {identifier} so that it is optional, i.e. simply /feed/ would match this route?
You should first create a link which looks like:
/feed/123
Then, in your controller the method would look like this:
feed($identifier)
{
// Do something with $identifier
}
Laravel is smart enough to map router parameters to controller method arguments, which is nice!
Alternatively, you could use the Request object to return the identifier value like this:
feed()
{
Request::get('identifier');
}
Both methods have their merits, I'd personally use the first example for grabbing one or two router parameters and the second example for when I need to do more complicated things.

Yii's CController::forward() can specify parameters to pass to the action?

I want to use CController::forward() instead of redirect or instantiating the controller and directly calling the action, because this way Yii::app()->controller->action->id correctly shows the action that ultimately ran.
Although I don't see in the documentation how to specify parameters to pass to the forwarded action, because the $route parameter is a string, not an array.
public function actionIndex() {
$this->forward('/otherCtrl/view'); // how to pass a parameter here?
otherController.php:
public function actionView( $id ) {
//get the id here
Parameters injected into action method comes from $_GET. So if you need to pass $id into forwarded action, you need to set value in $_GET array:
$_GET['id'] = 'some id';
But using forward() is basically always a sign of bad design of application - I suggest to extract shared logic into separate method/component, and avoid using forward() or calling controller actions directly.
You can try:
$this->forward('/otherCtrl/view/id/'.$id);
Query string depends on your URL settings.

Call an index controller with parameter

So basically, I have a setup of restful controller in my route. Now my problem is how can I call the Index page if there is a parameter.. it gives me an error of Controller not found
Im trying to call it like this www.domain.com/sign-up/asdasdasd
Route::controller('sign-up','UserRegisterController');
then in my Controller
class UserRegisterController extends \BaseController {
protected $layout = 'layouts.unregistered';
public function getIndex( $unique_code = null )
{
$title = 'Register';
$this->layout->content = View::make( 'pages.unregistred.sign-up', compact('title', 'affiliate_ash'));
}
By registering:
Route::controller('sign-up','UserRegisterController');
You're telling the routes that every time the url starts with /sign-up/ it should look for corresponding action in UserRegisterController in verbAction convention.
Suppose you have:
http://domain.com/sign-up/social-signup
Logically it'll be mapped to UserRegister#getSocialSignup (GET verb because it is a GET request). And if there is nothing after /sign-up/ it'll look for getIndex() by default.
Now, consider your example:
http://domain.com/sign-up/asdasdasd
By the same logic, it'll try looking for UserRegister#getAsdasdasd which most likely you don't have. The problem here is there is no way of telling Route that asdasdasd is actually a parameter. At least, not with a single Route definition.
You'll have to define another route, perhaps after your Route::controller
Route::controller('sign-up','UserRegisterController');
// If above fail to find correct controller method, check the next line.
Route::get('sign-up/{param}', 'UserRegisterController#getIndex');
You need to define the parameter in the route Route::controller('sign-up/{unique_code?}','UserRegisterController');. The question mark makes it optional.
Full documentation here: http://laravel.com/docs/routing#route-parameters

Resources