Skip to content
Advertisement

Laravel doubles the route when navigating between navbar links

I have a problem with laravel routes. I have a navbar with the urls /products and /employee. I manage to switch between perfectly perfectly without giving error. However, when I access the link /products/new and from there I try to go back to /products or go to /employees through the navbar, the link is /products/products or /employee/employee. How do I not replicate the links?

Routes

Route::get('/', function () {
    return view('index');
});

Route::get('/products', 'ControllerProduct@index');
Route::get('/products/new', 'ControllerProduct@create');    
Route::post('/products', 'ControllerProduct@store');    
Route::get('/products/show/{id}', 'ControllerProduct@show');    
Route::get('/products/delete/{id}', 'ControllerProduct@destroy');
Route::get('/products/edit/{id}', 'ControllerProduct@edit');
Route::post('/products/{id}', 'ControllerProduct@update');

app.blade

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="{{asset('css/app.css')}}">
        <meta name="csrf-token" content="{{csrf_token()}}">
        <style>
            body {
                padding: 20px;
            }
            .card {
                padding: 20px;
            }
            h1, h2, h3, h4, h5 {
                margin: 20px 0 20px 0;
            }
        </style>
    </head>
    <title>Products</title>
    <body>
        <div class="container"> 
            @component('componente_navbar', ["current"=>$current])
            @endcomponent
            <main role="main">
                @hasSection('body')
                    @yield('body')
                @endif
            </main>           
        </div>

        <script src="{{asset('js/app.js')}}" type="text/javascript"></script>
    </body>
</html>

index.blade

@extends('layout.app', ["current"=>"home"])

@section('body')
@endsection

producs.blade

@extends('layout.app', ["current"=>"products"])

@section('body')
<h5 class="card-title">Product Registration</h5>
<div class="card border">
    <div class="card-body">        
        @if(count($products)>0)
            <table class="table table-ordered table-hover">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Título</th>
                        <th>Ações</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach($products $pro)
                        <tr>
                            <td>{{$pro->id}}</td>
                            <td>{{$pro->titulo}}</td>
                            <td>
                                <a href="/products/show/{{$pro->id}}" class="btn btn-sm btn-success">Show</a>
                                <a href="/products/edit/{{$pro->id}}" class="btn btn-sm btn-primary">Edit</a>
                                <a href="/products/delete/{{$pro->id}}" class="btn btn-sm btn-danger">Delete</a>
                            </td>
                        </tr>
                    @endforeach
                </tbody>
            </table>
        @endif
    </div>
    <div class="card-footer">
        <a href="/products/new" class="btn btn-sm btn-primary" role="button">New Products</a>
    </div>    
</div>
@if (session('status'))
    <br>
    <div class="alert alert-danger">
        {{ session('status') }}
    </div>
@endif
@endsection

new_products.blade

@extends('layout.app', ["current"=>"products"])

@section('body')
<h4>Products Registration</h4>
<div class="card border">
    <form action="/products" method="POST">
        @csrf
        <div class="form-group">
            <label for="title_product">Titulo:</label>
            <input type="text" class="form-control" name="title_product" required>
            <br>
            <label for="cod_product">Código:</label>
            <input type="text" class="form-control" name="cod_product" pattern="d{3}-d{3}-d{1}"  placeholder="Ex.: 000-000-0" required>
            <br>
            <label for="date_product">Data:</label>
            <input type="text" class="form-control" name="date_product" pattern="d{2}/d{/}/d{4}"  placeholder="Ex.: dd/mm/aaa" required>
            <br>
            <label for="value_product">Valor:</label>
            <input type="number" class="form-control" name="value_product" step="0.01" required>
            <br>            
        </div>
        <button type="submit" class="btn btn-primary btn-sm">Ok</button>
        <button type="submit" class="btn btn-danger btn-sm">Cancel</button>
    </form>
</div>
@endsection

componente_navbar.blade

<nav class="navbar navbar-expand-lg navbar-dark bg-dark rounded">
    <div class="container-fluid">
      <div class="collapse navbar-collapse" id="navbarNav">
        <ul class="navbar-nav">
          <li class="nav-item">
            <a @if($current=="home") class="nav-link active" @else class="nav-link" @endif aria-current="page" href="/">Home</a>
          </li>
          <li class="nav-item">
            <a @if($current=="projects") class="nav-link active" @else class="nav-link" @endif href="projects">Projects</a>
          </li>
          <li class="nav-item">
            <a @if($current=="employees") class="nav-link active" @else class="nav-link" @endif href="employees">Employees</a>
          </li>          
        </ul>
      </div>
    </div>
</nav>

Advertisement

Answer

The problem is with how you have specified your href values on your a links, they are all defined as relative to the current path:

<a ... href="employees" />

What the above says is; from where I am currently, take me to the employees page. If you’re at the root (/) of your application then the path is /employees. However, if you are anywhere else, the path is /you-are-here/employees.

What you really want to do is use one of the Laravel URL helpers such as url() or route().

I personally favour the route helper as it uses the name you have defined for a route meaning if the path for a given route changes, you only need to change it in your web.php file and don’t have to go searching your code base for instances of /some/path/used/everywhere/.

You define a name for your route on the route definition in your web.php file, so for example:

Route::get('/products', 'ControllerProduct@index')->name('products.index');

With a name defined (they must be unique by the way), you can use the name in conjunction with the route() helper:

<a ... href="{{ route('products.index') }}">Projects</a>

Now it doesn’t matter how deep you are in your site structure, your link will always take you to /products.

On a side note, seeing as you appearing to be doing CRUDDY operations, you might want to consider using the resource method available on Route. This defines all your common routes and their names for you.

Route::resource('/products', 'ProductController');
Route::resource('/employees', 'EmployeeController');

Note that these assume you’re following naming conventions. So rather than /products/new it’s /products/create and your controllers as named {Something}Controller. Follow framework conventions where possible, it will save you and other headaches down the line.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement