phplaravellaravel-blademodel-bindinglaravel-routing

Issues with Laravel 5's Route::bind()


I'm having a little problem trying out Laravel 5.

I followed the whole tutorial in laracasts and tried to do everything the same exact way they do it there, only I changed the name of the model, table and controller.

At some point something with Route::bind() stopped working and because of that, now when I try to access a route with a Wild Card, the view will come up, but without the data.

This is my routes.php

Route::bind('singers', function($slug, $route){
return App\Singer::whereSlug($slug)->first();
});

Route::resource('singers', 'SingerController', [
                                            'names' => [
                                                    'index' => 'singers_index',
                                                    'show' => 'singers_show',
                                                    'edit' => 'singers_edit',
                                                    'update' => 'singers_update',
                                                    'create' => 'singers_create',
                                                    'store' => 'singers_store',
                                                    'destroy' => 'singers_destroy',
                                                        ],
                                                ]);

These are some snippets of my SingerController

namespace App\Http\Controllers;

use Illuminate\Routing\Controller;
use Illuminate\Http\Request;
use App\Http\Requests\CreateSingerRequest;
use App\Singer;

class SingerController extends Controller {

    public $restful = true;

    public function __construct(Singer $singer){
        $this->singer = $singer;
    }

    public function index()
    {
        $singers = $this->singer->orderBy('id', 'DESC')->get();
        return view('singers.list',compact('singers'));
    }

    public function show(Singer $singer){
        return view('singers.show', compact('singer'));
    }

    public function edit(Singer $singer){
        return view('singers.edit', compact('singer'));
    }

    public function update(Singer $singer, Request $request){
        $singer->fill($request->input());
        $singer->save();
        return view('singers.show', compact('singer'));
    }

    public function create(){
        return view('singers.new');
    }

    public function store(Singer $singer, CreateSingerRequest $request){
        $singer->create($request->all());
        return redirect()->route('singers_index');
    }

    public function destroy(Singer $singer){
        $singer->delete();
        return redirect()->route('singers_index');
    }
}

Now. The reason I try to bind the variable 'singers' in routes.php, is because they do it in the videos, and that way, the code in the Controller is shorter. And it WAS actually working. And then I just added the destroy function and it all stopped working. As I said, I can see the views, the tags, and any other text in them, but not the data that I pass, except for the index function, since I actually do the Eloquent search in the function itself.

Now here's a snippet of my show.blade.php

<b>Full Name: </b> {{ $singer->name.' '.$singer->lastname }}
<br>
<b>Age: </b> {{ $singer->age }}
<br>
<b>Country: </b> {{ $singer->country }}
<br>
<br>
<p>
    <b>Bio: </b> {!! nl2br($singer->bio) !!}
</p>

{!! HTML::linkRoute('singers_edit', 'Update', [$singer->slug], ['class' => 'btn btn-primary']) !!}

{!! Form::open(['method'=>'DELETE', 'route'=>['singers_destroy', $singer->slug]]) !!}
    <div class="form-group">
        {!! Form::submit('Delete', ['class'=>'btn btn-danger']) !!}
    </div>
{!! Form::close() !!}

My index view works fine, and the other views are just forms, but any view that I'm passing variables to isn't working, whether I pass it by doing this:

return view('singers.show',compact('singer'));

or this:

return view('singers.show')->with('singer',$singer);

So to recap:

Edit

Paths

Keep in mind that the {singers} wildcard is actually $singer->slug in each case, but the Route::bind() function doesn't allow me to call it whatever I want. And of course before the first slash comes myserver/myproject/public


Solution

  • I've just tested it.

    Singer model:

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Singer extends Model {
    
    }
    

    SingerController - exact code you provided (this file was placed of course in app\Http\Controllers path.

    In routes.php :

    Route::bind('singers', function($slug, $route){
       return App\Singer::whereSlug($slug)->first();
    });
    
    Route::resource('singers', 'App\Http\Controllers\SingerController', [
        'names' => [
            'index' => 'singers_index',
            'show' => 'singers_show',
            'edit' => 'singers_edit',
            'update' => 'singers_update',
            'create' => 'singers_create',
            'store' => 'singers_store',
            'destroy' => 'singers_destroy',
        ],
    ]);
    

    As you see I've added here full namespace path: 'App\Http\Controllers\SingerController' and not only SingerController.

    I'ce created simple Singer table, with fields just id and slug - just for test (so I have only those 2 columns) and added 2 records:

    id slug
    1  abc
    2  def
    

    Views I've created:

    list.blade.php:

    @foreach ($singers as $s)
    {{ $s->slug }}<br />
    @endforeach
    

    edit.blade.php and show.blade.php (exact same code):

    {{ $singer->slug }}
    {{ $singer->id }}
    

    Now when I run:

    http://testpro/singers I get result:

    def
    abc
    

    as expected.

    When I run:

    http://testpro/singers/abc/edit

    I get:

    abc 1
    

    as expected.

    And when I run:

    http://testpro/singers/def

    I get:

    def 2
    

    as expected.

    Everything seems to work fine here. Make sure you are using it the way I showed and it should work without any problem