Get part of url from Laravel named route - laravel

Is there a possibility to get the part of url, that is defined in route?
For example with this route:
Route::get('/editor/{id}', 'EditorController#editor')->name('editorNew');
after using mentioned functionality, let's say route_link(); i would like to get:
$route_link = route_link('editorNew', array('id' => 1));
//$route_link containts "/editor/1"
I tried to use route(), but i got http://localhost/app/public/editor-new/1 instead of /editor-new/1 and that's not what i wanted.
For clarity need this functionality to generate links depending on machine, that the app is fired on (integration with Shopify).

You can use route method to get the relative path by passing false in the third parameter as:
route('editorNew', [1], false); // returns '/editor-new/1'

You could use the following:
$route_link = route('editorNew', [1]);
1 is the first value that will be on the route, at this moment {id}.
If you want to use the paramater (id) in your method, it will be the following:
public function editor($id) {
//your code
}
And in the view you could use:
Route::input('id');
Hope this works!

Related

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.

Get last part of current URL in Laravel 5 using Blade

How to get the last part of the current URL without the / sign, dynamically?
For example:
In www.news.com/foo/bar get bar.
In www.news.com/foo/bar/fun get fun.
Where to put the function or how to implement this in the current view?
Of course there is always the Laravel way:
request()->segment(count(request()->segments()))
You can use Laravel's helper function last. Like so:
last(request()->segments())
This is how I did it:
{{ collect(request()->segments())->last() }}
Use basename() along with Request::path().
basename(request()->path())
You should be able to call that from anywhere in your code since request() is a global helper function in Laravel and basename() is a standard PHP function which is also available globally.
The Route object is the source of the information you want. There are a few ways that you can get the information and most of them involve passing something to your view. I strongly suggest not doing the work within the blade as this is what controller actions are for.
Passing a value to the blade
The easiest way is to make the last part of the route a parameter and pass that value to the view.
// app/Http/routes.php
Route::get('/test/{uri_tail}', function ($uri_tail) {
return view('example')->with('uri_tail', $uri_tail);
});
// resources/views/example.blade.php
The last part of the route URI is <b>{{ $uri_tail }}</b>.
Avoiding route parameters requires a little more work.
// app/Http/routes.php
Route::get('/test/uri-tail', function (Illuminate\Http\Request $request) {
$route = $request->route();
$uri_path = $route->getPath();
$uri_parts = explode('/', $uri_path);
$uri_tail = end($uri_parts);
return view('example2')->with('uri_tail', $uri_tail);
});
// resources/views/example2.blade.php
The last part of the route URI is <b>{{ $uri_tail }}</b>.
Doing it all in the blade using the request helper.
// app/Http/routes.php
Route::get('/test/uri-tail', function () {
return view('example3');
});
// resources/views/example3.blade.php
The last part of the route URI is <b>{{ array_slice(explode('/', request()->route()->getPath()), -1, 1) }}</b>.
Try request()->segment($number) it should give you a segment of the URL.
In your example, it should probably be request()->segment(2) or request()->segment(3) based on the number of segments the URL has.
YourControllor:
use Illuminate\Support\Facades\URL;
file.blade.php:
echo basename(URL::current());
It was useful for me:
request()->path()
from www.test.site/news
get -> news
I just had the same question. In the meantime Laravel 8. I have summarised all the possibilities I know.
You can test it in your web route:
http(s)://127.0.0.1:8000/bar/foo || baz
http(s)://127.0.0.1:8000/bar/bar1/foo || baz
Route::get('/foo/{lastPart}', function(\Illuminate\Http\Request $request, $lastPart) {
dd(
[
'q' => request()->segment(count(request()->segments())),
'b' => collect(request()->segments())->last(),
'c' => basename(request()->path()),
'd' => substr( strrchr(request()->path(), '/'), 1),
'e' => $lastPart,
]
)->where('lastPart', 'foo,baz'); // the condition is only to limit
I prefer the variant e).
As #Qevo had already written in his answer. You simply make the last part part of the request. To narrow it down you can put the WHERE condition at the route.
Try with:
{{ array_pop(explode('/',$_SERVER['REQUEST_URI'])) }}
It should work well.

Laravel routing & filters

I want to build fancy url in my site with these url patterns:
http://domain.com/specialization/eye
http://domain.com/clinic-dr-house
http://domain.com/faq
The first url has a simple route pattern:
Route::get('/specialization/{slug}', 'FrontController#specialization');
The second and the third url refers to two different controller actions:
SiteController#clinic
SiteController#page
I try with this filter:
Route::filter('/{slug}',function()
{
if(Clinic::where('slug',$slug)->count() == 1)
Route::get('/{slug}','FrontController#clinic');
if(Page::where('slug',$slug)->count() == 1)
Route::get('/{slug}','FrontController#page');
});
And I have an Exception... there is a less painful method?
To declare a filter you should use a filter a static name, for example:
Route::filter('filtername',function()
{
// ...
});
Then you may use this filter in your routes like this way:
Route::get('/specialization/{slug}', array('before' => 'filtername', 'uses' => 'FrontController#specialization'));
So, whenever you use http://domain.com/specialization/eye the filter attached to this route will be executed before the route is dispatched. Read more on documentation.
Update: For second and third routes you may check the route parameter in thew filter and do different things depending on the parameter. Also, you may use one method for both urls, technically both urls are identical to one route so use one route and depending on the param, do different things, for example you have following urls:
http://domain.com/clinic-dr-house
http://domain.com/faq
Use a single route for both url, for example, use:
Route::get('/{param}', 'FrontController#common');
Create common method in your FrontController like this:
public function common($param)
{
// Check the param, if param is clinic-dr-house
// the do something or do something else for faq
// or you may use redirect as well
}

Laravel how to route old urls

I am using Laravel 4.
I have an old url that needs to be routable. It doesn't really matter what it's purpose is but it exists within the paypal systems and will be called regularly but cannot be changed (which is ridiculous I know).
I realise that this isn't the format url's are supposed to take in Laravel, but this is the url that will be called and I need to find a way to route it:
http://domain.com/forum/index.php?app=subscriptions&r_f_g=xxx-paypal
(xxx will be different on every request)
I can't figure out how to route this with laravel, i'd like to route it to the method PaypalController#ipbIpn so i've tried something like this:
Route::post('forum/index.php?app=subscriptions&r_f_g={id}-paypal', 'PaypalController#ipbIpn');
But this doesn't work, infact I can't even get this to work:
Route::post('forum/index.php', 'PaypalController#ipbIpn');
But this will:
Route::post('forum/index', 'PaypalController#ipbIpn');
So the question is how can I route the url, as it is at the top of this question, using Laravel?
For completeness I should say that this will always be a post not a get, but that shouldn't really make any difference to the solution.
Use this:
Route::post('forum/{file}', 'PaypalController#ipbIpn');
And then in the controller, use
public function forum($file) {
$request = Route::getRequest();
$q = (array) $request->query; // GET
$parameters = array();
foreach($q as $key => $pararr) {
$parameters = array_merge($parameters, $pararr);
}
}
You can then access the get parameters via e.g.
echo $parameters['app'];
you can use route redirection to mask and ending .php route ex:
Route::get('forum/index', ['uses'=> 'PaypalController#ipbIpn']);
Route::redirect('forum/index.php', 'forum/index');

How to Remove/Register Suffix on Laravel Route?

EDIT: See below for my current problem. The top portion is a previous issue that I've solved but is somewhat related
I need to modify the input values passed to my controller before it actually gets there. I am building a web app that I want to be able to support multiple request input types (JSON and XML initially). I want to be able to catch the input BEFORE it goes to my restful controller, and modify it into an appropriate StdClass object.
I can't, for the life of me, figure out how to intercept and modify that input. Help?
For example, I'd like to be able to have filters like this:
Route::filter('json', function()
{
//modify input here into common PHP object format
});
Route::filter('xml', function()
{
//modify input here into common PHP object format
});
Route::filter('other', function()
{
//modify input here into common PHP object format
});
Route::when('*.json', 'json'); //Any route with '.json' appended uses json filter
Route::when('*.xml', 'xml'); //Any route with '.json' appended uses json filter
Route::when('*.other', 'other'); //Any route with '.json' appended uses json filter
Right now I'm simply doing a Input::isJson() check in my controller function, followed by the code below - note that this is a bit of a simplification of my code.
$data = Input::all();
$objs = array();
foreach($data as $key => $content)
{
$objs[$key] = json_decode($content);
}
EDIT: I've actually solved this, but have another issue now. Here's how I solved it:
Route::filter('json', function()
{
$new_input = array();
if (Input::isJson())
{
foreach(Input::all() as $key => $content)
{
//Do any input modification needed here
//Save it in $new_input
}
Input::replace($new_input);
}
else
{
return "Input provided was not JSON";
}
});
Route::when('*.json', 'json'); //Any route with '.json' appended uses json filter
The issue I have now is this: The path that the Router attempts to go to after the filter, contains .json from the input URI. The only option I've seen for solving this is to replace Input::replace($new_input) with
$new_path = str_replace('.json', '', Request::path());
Redirect::to($new_path)->withInput($new_input);
This however leads to 2 issues. Firstly I can't get it to redirect with a POST request - it's always a GET request. Second, the data being passed in is being flashed to the session - I'd rather have it available via the Input class as it would be with Input::replace().
Any suggestions on how to solve this?
I managed to solve the second issue as well - but it involved a lot of extra work and poking around... I'm not sure if it's the best solution, but it allows for suffixing routes similar to how you would prefix them.
Here's the github commit for how I solved it:
https://github.com/pcockwell/AuToDo/commit/dd269e756156f1e316825f4da3bfdd6930bd2e85
In particular, you should be looking at:
app/config/app.php
app/lib/autodo/src/Autodo/Routing/RouteCompiler.php
app/lib/autodo/src/Autodo/Routing/Router.php
app/lib/autodo/src/Autodo/Routing/RoutingServiceProvider.php
app/routes.php
composer.json
After making these modifications, I needed to run composer dumpautoload and php artisan optimize. The rest of those files are just validation for my data models and the result of running those 2 commands.
I didn't split the commit up because I'd been working on it for several hours and just wanted it in.
I'm going to hopefully look to extend the suffix tool to allow an array of suffixes so that any match will proceed. For example,
Route::group(array('suffix' => array('.json', '.xml', 'some_other_url_suffix')), function()
{
// Controller for base API function.
Route::controller('api', 'ApiController');
});
And this would ideally accept any call matching
{base_url}/api/{method}{/{v1?}/{v2?}/{v3?}/{v4?}/{v5?}?}{suffix}`
Where:
base_url is the domain base url
method is a function defined in ApiController
{/{v1?}/{v2?}/{v3?}/{v4?}/{v5?}?} is a series of up to 5 optional variables as are added when registering a controller with Route::controller()
suffix is one of the values in the suffix array passed to Route::group()
This example in particular should accept all of the following (assuming localhost is the base url, and the methods available are getMethod1($str1 = null, $str2 = null) and postMethod2()):
GET request to localhost/api/method1.json
GET request to localhost/api/method1.xml
GET request to localhost/api/method1some_other_url_suffix
POST request to localhost/api/method2.json
POST request to localhost/api/method2.xml
POST request to localhost/api/method2some_other_url_suffix
GET request to localhost/api/method1/hello/world.json
GET request to localhost/api/method1/hello/world.xml
GET request to localhost/api/method1/hello/worldsome_other_url_suffix
The last three requests would pass $str1 = 'hello' and $str2 = 'world' to getMethod1 as parameters.
EDIT: The changes to allow multiple suffixes was fairly easy. Commit located below (please make sure you get BOTH commit changes to get this working):
https://github.com/pcockwell/AuToDo/commit/864187981a436b60868aa420f7d212aaff1d3dfe
Eventually, I'm also hoping to submit this to the laravel/framework project.

Resources