Laravel Routes Wildcard - php

I'm new to Laravel and wondering if anyone can assist with wildcards in routes.php file
This is what I currently have
Route::post('/post/method1','postController#method1');
Route::post('/post/method2','postController#method2');
Route::post('/post/method3','postController#method3');
This is what I'm trying to achieve.
Route::post('/post/{variable}','postController#{variable}');
Help greatly appreciated

Create a method in the controller to route the request based on the parameter value:
public function route(string $path){
// define the allowed methods
$allowedMethods = ['someMethodName', 'anotherMethodName'];
// check if the path name is a method and is allowed
if(in_array($path, $allowedMethods, true) && method_exists($this, $path)){
// call method
return $this->{$path}();
}
// handle error
}
Then just use the controller like you would do normally:
Route::post('/post/{variable}','postController#route');

Related

Use optional parameter in route

I want to use same route in 2 scenarios,
use route without passing parameter
use route with parameter
So, is it possible & how to do it?
You can optional parameters like this
Route::get('my-method/{param?}', function ($param= null) {
// your code here
});
In Web Php
Route::get('find-services/{service_name?}', 'commonController#find_services')->name('find-services');
and handle the parameters in commonController.php
public function find_services($service_name = null) {// Do something here}
Or Simple use the get method and check parameter in Controller
public function find_services() {
$input = Request::all();
if (isset($input['service_name']) AND ! empty($_GET['service_name'])) {
// Code
}
}
I hope this one helps and For More Information Here => https://laravel.com/docs/7.x/routing#parameters-optional-parameters

Laravel function with optional parameter

In my web file, I have a route that accepts a $id as a value to be passed to a function within my PagesController. However, I want the function to still execute and show the intended form even when the $id is not passed to the function.
web.php file
Route::get('/request/{id}', 'PagesController#makeRequest');
PagesController.php file
public function makeRequest($id)
{
if(!empty($id)){
$target = Partner::find($id);
}
return view('pages.makeRequest')->with('target', $target);
}
makeRequest.blade.php
<input type="text" class="form-control" value="{{$target->inst_name}}" required disabled>
I want the page to display details from the database with the $id when provided or have empty spaces when the $id isn't provided.
As the Laravel Documentation states: Use Optional Parameters like this:
Route::get('/request/{id?}', 'PagesController#makeRequest'); //Optional parameter
Controller
public function makeRequest($id = null)
{
if(!empty($id)){
$target = User::find($id);
return view('pages.makeRequest')->with('target', $target);
} else {
return view('pageslist'); ///set default list..
}
}
This is the way I did it:
Route::get('index', 'SeasonController#index');
// controller
public function index(Request $request )
{
$id= $request->query('id');
}
The way you call it:
localhost/api/index?id=7
All your solutions were helpful. The main thing was that when I called just the view without passing $target to the view, the page displayed an error. So this is what I did.
Route::get('/request/{id?}', 'PagesController#makeRequest');
Then in the controller,
public function makeRequest(Request $request, $id=null)
{
if ($id != null) {
$target = Partner::find($id);
return view('pages.makeRequest')->with('target', $target);
}
return view('pages.makeNullRequest');
}
If you didn't understand what happened, I created a new view which had this instead of what I had posted in the question.
<input type="text" class="form-control" value="" required readonly>
Sorry I didn't update you guys in time. I think Jignesh Joisar came closest to helping me solve this issue. really appreciate all you guys. You're just awesome
You can use optional parameter :
Route::get('/request/{id?}', 'PagesController#makeRequest');
Now, as the parameter is optional, while defining the controller function you need to assign its default value to null in argument declaration.
<?php
public function makeRequest($id = null)
{
if($id){
$target = Partner::findOrFail($id);
return view('pages.makeRequest')->with(compact('target'));
}
// Return different view when id is not present
// Maybe all targets if you want
$targets = Partner::select('column1', 'column2')->get();
return view('pages.all')->with('targets');
}
I am using findOrFail instead of find. Its Laravel's very handy function which automatically throws a ModelNotFound exception and for frontend user throws a simple 404 page.
So if anyone is accessing www.url.com/request/2, its a valid id then it will show a valid page with data. If the accessed url is www.url.com/request/blahblah then it will throw 404. It avoids efforts of handling this manually.
For optional parameter pass id with ? in route and give $id = null in your function's parameter like this:
Route::get('/request/{id?}', 'PagesController#makeRequest'); //Optional parameter
makeRequest($id = null) {
// Code here...
...
}
in your routes file (web.php , as mentioned in your question)
Route::get('/request/{id?}', 'PagesController#makeRequest');
and in your controller PagesController.php
public function makeRequest($id = null)
{
}
To read more about this, just read https://laravel.com/docs/5.7/routing#parameters-optional-parameters
For me the answer was in the order that I listed the Routes in the routes file.
The routes file will call the first one that matches the pattern.
Route::get('/ohmy/{id?}', 'OhMyController#show');
Route::get('/ohmy/all', 'OhMyController#all'); //never gets called
Instead, put optional parameters at end of list:
Route::get('/ohmy/all', 'OhMyController#all');
Route::get('/ohmy/{id?}', 'OhMyController#show');
the answer has been said. just a side note: optional parameters won't work if you are using resource routes.
for example:
Route::resource('items',itemController::class)->except([
'create',
]);
Route::get('/items/create/{category_id?}',function($category_id = 'abc'){
dd($category_id);
});
if i go to " items/create/1 ", the result will be "1".
if i go to " items/create ", it will return 404. ( but we expect it to say "abc".)
this happens because other routes that start with "items" are expected to be generated from "resource" functionality.
so if you use resource routes, you should consider that.

Redirect if route does'n exist

I have a question : so for examples I have an app in symfony3 which have the following routes : /admin/login,admin/news,admin/gallery, but the route /admin/authentification doesn't exist. So the idea is if the route doesn't exist I want to redirect the user to homepage /. Can you help me please ? Thanks in advance and sorry for my english
I'm not confident this is the best solution, but you can use a UrlMatcher to check that the URL you're passing correlates to an available route:
/**
* #Route("/debug")
*/
public function DebugAction(){
$router = $this->get('router');
//Get all the routes that exist.
$routes = $router->getRouteCollection();
$context = $router->getContext();
$urlMatcher = new UrlMatcher($routes, $context);
$url = '/admin/login';
try{
//UrlMatcher::match() will throw a ResourceNotFoundException if the route
//doesn't exist.
$urlMatcher->match($url);
return $this->redirect($url);
} catch (\Symfony\Component\Routing\Exception\ResourceNotFoundException $e){
return $this->redirect('/');
}
}
I'm not particularly keen on this solution because it relies on catching an exception, rather than checking a boolean value to determine if the route exists.
You can check if the rout exist.
function routeExists($name)
{
// I assume that you have a link to the container in your twig extension class
$router = $this->container->get('router');
return (null === $router->getRouteCollection()->get($name)) ? false : true;
}
And depending on result, do the redirect to the rout, or to the default webpage, or whatever you need.

Laravel: Parse arbitrary URL to its corresponding Controller/Route?

Given I have an arbitrary URL mapped (amongst many others) like this
...
Route::get('/foobar/{parameter}', 'MyFoobarController#index');
...
How can I "reverse parse/resolve" the URL (like http://localhost/foobar/foo) into this configured controller (MyFoobarController) again? Please note: I am not talking about the current Request but a general approach to parse any URL that is mapped in Laravel to its corresponding Controller and Action (anywhere in the code independent of the current request). Thanks!
Update: It should also correctly match Routes, that have parameters in them.
You can compare the URL path, to the paths added to the router. So let's take your example:
Route::get('/foobar', 'MyFoobarController#index');
You can use the Route facade to get a list of all registered routes:
// This is your URL as a string
$url = 'http://localhost/foobar';
// Extract the path from that URL
$path = trim(parse_url($url, PHP_URL_PATH), '/');
// Iterate over the routes until you find a match
foreach (Route::getRoutes() as $route) {
if ($route->getPath() == $path) {
// Access the action with $route->getAction()
break;
}
}
The getAction method will return an array containing the relevant information about the action mapped for that route. You can check out the Illuminate\Routing\Route API for more info on what methods are available for you to use once you have matched a route.
private function getMatchRoutes($request)
{
$referer = $request->header('Referer');
$refererPath = parse_url($referer,PHP_URL_PATH);
$routes = Route::getRoutes()->getRoutes();
$matchedRoute = null;
foreach ($routes as $route) {
$route->compiled = (new RouteCompiler($route))->compile();
if (is_null($route->getCompiled())) continue;
if (preg_match($route->getCompiled()->getRegex(), rawurldecode($refererPath))) {
$matchedRoute = $route;
}
}
if (is_null($matchedRoute)) return $matchedRoute;
return explode('#',$matchedRoute->getActionName())[0];
}
the codes above i wrote is to get controller/action from request referer ,you can replace it by a valid url, try it , may be helpful ~~~

Laravel - using controllers instead of routes for actions

I've literally downloaded Laravel today and like the looks of things but i'm struggeling on 2 things.
1) I like the controllers' actions method of analysing urls instead of using routes, it seems to keep everything together more cleanly, but lets say I want to go to
/account/account-year/
how can I write an action function for this? i.e.
function action_account-year()...
is obviously not valid syntax.
2) If i had
function action_account_year( $year, $month ) { ...
and visited
/account/account_year/
An error would be displayed about missing arguments, how do you go about making this user friendly/load diff page/display an error??
You would have to manually route the hyphenated version, e.g.
Route::get('account/account-year', 'account#account_year');
Regarding the parameters, it depends on how you are routing. You must accept the parameters in the route. If you are using full controller routing (e.g. Route::controller('account')) then the method will be passed parameters automatically.
If you are manually routing, you have to capture the params,
Route::get('account/account-year/(:num)/(:num)', 'account#account_year');
So visiting /account/account-year/1/2 would do ->account_year(1, 2)
Hope this helps.
You can think of the following possibility as well
class AccountController extends BaseController {
public function getIndex()
{
//
}
public function getAccountYear()
{
//
}
}
Now simply define a RESTful controller in your routes file in the following manner
Route::controller('account', 'AccountController');
Visiting 'account/account-year' will automatically route to the action getAccountYear
I thought I'd add this as an answer in case anyone else is looking for it:
1)
public function action_account_year($name = false, $place = false ) {
if( ... ) {
return View::make('page.error' );
}
}
2)
not a solid solutions yet:
laravel/routing/controller.php, method "response"
public function response($method, $parameters = array())
{
// The developer may mark the controller as being "RESTful" which
// indicates that the controller actions are prefixed with the
// HTTP verb they respond to rather than the word "action".
$method = preg_replace( "#\-+#", "_", $method );
if ($this->restful)
{
$action = strtolower(Request::method()).'_'.$method;
}
else
{
$action = "action_{$method}";
}
$response = call_user_func_array(array($this, $action), $parameters);
// If the controller has specified a layout view the response
// returned by the controller method will be bound to that
// view and the layout will be considered the response.
if (is_null($response) and ! is_null($this->layout))
{
$response = $this->layout;
}
return $response;
}

Categories