Laravel - Conditional Route Name mapping / dynamic routes - php

I thought to write static routes like contact, imprint or "About Us" in the web.php as a one-liner. I saw this at Laravel Daily.
web.php
Route::get('/{page}', App\Http\Controllers\StaticPageController::class)
->name('page')
->where('page', 'about-us|imprint|contact');
It's nice but I'm getting problems with my navbar.
My Blade navbar has a dynamic part. The current menu item is highlighted. Very simple.
nav.blade.php
<x-nav-link :href="route('about-us')" :active="request()->routeIs('about-us')">
{{ __('About us') }}
</x-nav-link>
With the new one-liner, I then get the following error message:
Symfony\Component\Routing\Exception\RouteNotFoundException.
Route [about-us] not defined. (View: /project01/resources/views/includes/nav.blade.php)
Which is logical, because I no longer have the about-us route.
Actually, the route should be given a corresponding array mapping. But I don't know how. How can I solve the problem?
The solution for this problem will be:
<x-nav-link :href="route('page', ['page' => 'about-us'])" :active="request()->routeIs('about-us')">
{{ __('About us') }}
</x-nav-link>
Special Thanks for all good answears!

You have two options.
1- Change the routeIs() to is() and use the path, not the route name
<x-nav-link :href="route('page', ['page' => 'about-us'])" :active="request()->is('about-us/*')">
{{ __('About us') }}
</x-nav-link>
2- Switch back to 3 routes instead of the one liner. There is no gain in using the one liner. It is slower and harder to read (maintain)

You have assigned a name page to a given route with the required parameter named page. So, you must use the following code:
route('page', ['page' => 'about-us']);
https://laravel.com/docs/6.x/routing#named-routes

I think there is a misunderstanding.'about-us|imprint|contact' is the parameter restrictions.'page' is the route name.So this should work;
<x-nav-link :href="route('page','about-us')" :active="Request::url() == route('page','about-us')">
{{ __('About us') }}
</x-nav-link>

Related

Hypertext to route not working

Hi I have a hyperlink from a page:
<h3>hitest</h3>
the route:
Route::get('hitest', function(){ return 'hitest message';});
There is an error:
No query results for model [App\User2].
hyper link is from a page with this url
/userpage/1
the 1 is a model object.
Shouldn't the hyperlink route to /hitest ?
Please see my other post: Strange behavior with routing and hypertext.
I'm new at web development. Is there configurations for routing? The app is hosted (not local).
As bytesarelife already mentioned, you can use the url()-function, like so:
{{ url('your/url/') }}
A better way in terms of maintainability would be to give your routes names, so you would not have to replace every url in every template once you want to change it. You can do so, by adding the name in your routes:
Route::get('hitest', function(){ return 'hitest message';})->name('getHittest');
And then you can use the route function in your view:
{{ route('getHittest') }}

Laravel 5.1 - Pass parameter to Breadcrumbs

I use davejamesmiller Breadcrumbs package. I am wondering how to pass a parameter to a breadcrumb, something like an id.
In the docs (here) it says that is possible, but can't find the way to do it.
My goal es to do a breadcrumb like this: Dashboard \ User \ New Model. Where New Model its a form to add model data with some relationship with the user. Without the user_id param the link for User won't work.
Any idea?
You can pass global variable
\View::share ( 'variable2', $variable2 );
if render breadcrumbs in layout
or You need render breadcrumbs in `user.new_model.blade
#section('content')
{!! Breadcrumbs::render('page', $page) !!}
#stop`
my way
Create template
breadcrumbs.blade.php
with content
#if(!empty($breadcrumbs))
<ol class="breadcrumb">
<li>{!! link_to_route('main', 'Home') !!}</li>
#foreach($breadcrumbs as $bread)
#if(isset($bread['url']))
<li>{!! link_to($bread['url'], $bread['name']) !!}</li>
#else
<li>{!! $bread['name'] !!}</li>
#endif
#endforeach
</ol>
#endif
and connect it to layout
#include('breadcrumbs')
and in your action pass array of links
\View::share('breadcrumbs', [
['url' => route('collection.show', ['id'=>$data->collection, 'url'=>$data->collection]), 'name' => $data->collection->name],
['name' => $data->article]
]);
There is another way. As general, in each view just calling Breadcrumbs::render() should create the hierarchy of the breadcrumbs links depending on the routes defined in routes/breadcrumbs.php.
There are two essential points that you have keep in mind to go further with this solution:
The callback function that found in breadcrumbs.php routs definition is the place from which you should pass your parameters.
Giving correct name to your web route from routes/web.php which will be used later in routes/breadcrumbs.php
Checkout the following code snippets that demonstrates the above two points:
//Point1: routes/breadcrumbs.php
Breadcrumbs::register('job.edit', function($breadcrumbs, $job, $title)
{
$breadcrumbs->parent('job','job');
$breadcrumbs->push($title, route('job.edit', $job));
});
Breadcrumbs::register('job.edit.install', function($breadcrumbs, $job, $title)
{
$breadcrumbs->parent('job.edit',$job, $title);
$breadcrumbs->push('Job Install Equipments', route('job.edit.install','job'));
});
In the above code we passed $job and $title through the callback function.
//Point2 routes/web.php
Route::get('/job/edit/{job}', 'JobController#edit')->name('job.edit');
Route::get('/job/install-equipments/{job}', 'JobController#installEquipments')->name('job.edit.install');
We give a name to the route through the name method , Laravel 5.4, which allow us to define the routes correctly in Point1.
The last step, is what you have do in the view file. Here I will show you the last one regarding /job/install-equipments which should be rendered in the breadcrumb as the last element and its parent is job/edit with parameter job which handles the primary key id
//install.equipments.blade.php
#extends('layouts.main')
#section('content')
{!! Breadcrumbs::render('job.edit.install',$job->id, __('Edit').': '.$job->title) !!}
The above will render a breacrumbs look like:
Home / Job / Edit: title of
job / Job Install Equipment
The required parameters that handles breadcrumbs render are supplied un the above render method i.e through $job->id and __('Edit').': '.$job->title) , the last just adjusting the text and it could be done inside the callback function of breadcrumbs routes.

Custom method instead of resource for Laravel routes

Using 4.2 and trying to add a custom method to my controller.
My routes are:
Route::get('ticket/close_ticket/{id}', 'TicketController#close_ticket');
Route::resource('ticket', 'TicketController');
Everything CRUD wise works as it should, but at the bottom of my TicketController I have this basic function:
public function close_ticket($id) {
return "saved - closed";
}
When I am showing a link to route on my page:
{{ link_to_route('ticket/close_ticket/'.$ticket->id, 'Mark As Closed', array($ticket->id), array('class' => 'btn btn-success')) }}
I constantly get a route not defined error, but it surely is defined...?
Any ideas where this is going wrong?
link_to_route expects a route name, not a url. This is why you are getting 'route not defined' errors, because you have not defined a route with the name you supplied to link_to_route. If you give your route a name, you can use link_to_route.
Given the following route definition, the name of the route is now 'close_ticket':
Route::get('ticket/close_ticket/{id}', array('as' => 'close_ticket', 'uses' => 'TicketController#close_ticket'));
The value for the 'as' key is the route name. This is the value to use in link_to_route:
{{ link_to_route('close_ticket', 'Mark As Closed', array($ticket->id), array('class' => 'btn btn-success')) }}
The laravel helper method link_to_route generates an HTML link. Which mean when clicked, the user will be performing a GET request.
In your routes file, you are defining this as a POST route.
Route::post(...)
Also, take a look at the docs for link_to_route here:
http://laravel.com/docs/4.2/helpers
You'll see that the first argument should be just the route name, without the ID appended.

Why is passing of second variable on href much flexible in Laravel?

I am using Laravel Framework 4.1.30.
My Original Problem was...
I got a working route that when I type "localhost/user/alvin" it works but when I click a drop-down bar, it does not work.
drop-down bar from template was: (li tag removed)
{{ Auth::user()->username }}
route is:
Route::get('/user/{username}', array(
'as' => 'profile-user',
'uses' => 'ProfileController#user'));
View of URL when I click the dropdown bar is:
"localhost/user/%7Busername%7D"
I got 3 working answers for this from other communities.
First was a simple:
{{ Auth::user()->username }}
Second was:
{{ Auth::user()->username }}
Last was:
<a href="{{ URL::route('profile-user',['username'=>Auth::user()->username]) }}">
{{ Auth::user()->username}}</a>
Originally I thought the simplest (First Solution) form would be the wisest choice but as per most developer they choose the Third answer because it allows some flexibility to some extent.
I want to implement a good Quality Assured code as much as possible.
My question... Why would the 3rd solution be much more flexible compared to a much simpler code?
You can even use a more flexible, shorter modification of the third one:
<a href="{{ route('profile-user', Auth::user()->username) }}">
When you are using named routes, you do not put actual URLs, nor controller method names into your Views. You only provide a route name to your Views, and all other things are defined in your routes, and can be changed, if needed, without making breaking anything else. It would be a waste not to use this feature.
It is also more flexible, by not specifying the parameter name, so it can be changed in the routes too, without breaking the Views. This way they will be just taken in the order they were inputted. They are also read by a controller method in the order, i.e. public function index($parameter1, $parameter2) not by an associative array.
The route() is an alias to URL::route().

Laravel 4 - Multiple forms on same page?

I'm having some strange behavior with my forms in Laravel 4. I have a "settings" page with two forms, each (are supposed to) POST to a controller method, update the database and return back to the settings page. However, there seems to be an issue, either with the way my forms are working or my routes.
Here's how it is, simplified:
Settings page: (site.com/settings)
<div id="form-one" class="form-area">
{{ Form::open(array('action' => 'SettingController#editOption')) }}
{{ Form::text('optionvalue', 'Default')) }}
{{ Form::submit('Save Changes') }}
{{ Form::close() }}
</div>
<div id="form-two" class="form-area">
{{ Form::open(array('action' => 'SettingController#editPage')) }}
{{ Form::text('pagevalue', 'Default')) }}
{{ Form::submit('Save Changes') }}
{{ Form::close() }}
</div>
So basically, two seperate forms on the same page that post to two seperate methods in the same Controller - when the method is successful, it redirects them back to "settings". I won't post the methods, since tested them and they work, I believe the problem is in the routes file:
routes.php
// Checks if a session is active
Route::group(array('before' => 'require_login'), function()
{
Route::group(array('prefix' => 'settings'), function()
{
Route::get('/', 'SettingController#index');
Route::post('/', 'SettingController#editOption');
Route::post('/', 'SettingController#editPage');
});
});
Now I'm pretty sure it doesn't like the two POST routes being like that, however I cannot think of another way to do it, since the forms are on the same page. I get the error:
Unknown action [SettingController#editOption].
Since the option form comes first I guess. If I take the open form blade code out (for both), it loads the page - but obviously the form doesn't do anything.
Any help would be nice! Thanks in advance.
You can't add two same routes for different actions, because of they will be passed to first matched route and in your case to SettingController#editOption. Change your routes to :
Route::post('/option', 'SettingController#editOption');
Route::post('/page', 'SettingController#editPage');
Than in both actions you can redirect to '/': return Redirect::back(), and if error was occured:
if ($validation->fails())
{
return Redirect::to('/settings')->with_errors($validation);
}
My alternative solution for this is to create an hidden html input in each form and make the controller identify what for is submitted based in this field. So, yu can use just one route for both.

Categories