0

In blade I have a list of books. I want to choose a specific book to show its information. And to do so I want to send with href the id of the book to my controller passing through route.

For example i have

 <div class="body text-center">
 <a href="{{HERE!}}"><h6><b>{{($book->getName())}}</b></h6></a>
 </div> 

In href I want to add $bookId = $book->id and the route name so I can call the route with the specific name which calls a method in a controller which can use the variable $bookId

 Route::get('/infromation','Books\BookController@index')->name('info');
InFo55
  • 13
  • 8
  • I'm not sure to get what you want. You don't want to change the URL but you want to add the ID. (Perhaps a POST request?). Does the route should return the `index` as well? – Clément Baconnier Jan 12 '20 at 15:00
  • url: /books -> where all books are shown I select one of the books and I want the shown url to become: /{book-name}/info or just /info and also i want to send the selected book's id to the controller Bookcontroller. – InFo55 Jan 12 '20 at 15:12
  • If you want the book name in the URL is recommended you to have a [slug](https://github.com/spatie/laravel-sluggable) Is that acceptable for you? – Clément Baconnier Jan 12 '20 at 15:14
  • I don't know. I will take a look – InFo55 Jan 12 '20 at 15:15
  • Also, I don't recommend URL like `/info` without using `id` or `slug` because, in my opinion, it provide a bad user experience when trying to access the resource. – Clément Baconnier Jan 12 '20 at 15:16

2 Answers2

0

You can try like this

    <form action="/BookName/information/<?php echo $book->id; ?>" method="post">
      <div class="body text-center">
       <input type="hidden" name="book_id" value="{{ $book->id }}">
       <a href="/information/<?php echo $book->id; ?>">
          <button type="submit" name="book_information" class="btn btn-primary"> 
            <h6>
              <b>{{($book->getName())}}</b> 
            </h6>
         </button>
     </div>

   </form> 

    // make route like this
    Route::post('/BookName/information/{id}','Books\BookController@index');

    // Access the that id in controller
    public function index(Request $request)
    {
        echo $request->book_id;
    }
Hitesh Kumar
  • 383
  • 2
  • 6
  • Okay but I don't want to show the id on the url is it possible to send the id and keeping the url '/information' or sending the id and changing the url to '/bookName/information'? – InFo55 Jan 12 '20 at 15:01
  • I update my answer as per what you say, so please check – Hitesh Kumar Jan 12 '20 at 15:23
0

Here's two propositions:

  • The first one is to use spatie/laravel-sluggable to have the book name in the URL
  • The second one is to access the book without changing the URL with a POST request

Using spatie/laravel-sluggable

The slug will be generated automatically from name when the book is created.

your-migration.php

 Schema::create('books', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('slug')->unique()->index();
    $table->string('name');
    // ...
    $table->timestamps();
});

web.php

// Change the URIs as you want. `{book}` is mandatory to retrieve the book though.
Route::get('/books','Books\BookController@index')->name('book.index');
Route::get('/books/{book}','Books\BookController@show')->name('book.show');

Book.php

use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;

class Book extends Model
{
    use HasSlug;

    protected $guarded = [];

    public function getSlugOptions()
    {
        // Adapt with what you want
        return SlugOptions::create()
            ->generateSlugsFrom('name')
            ->saveSlugsTo('slug')
            ->doNotGenerateSlugsOnUpdate();
    }

    public function getRouteKeyName()
    {
        return 'slug';
    }

}

BookController.php

class BookController extends Controller
{
    public function index()
    {
        return view('book.index');
    }

    public function show(Book $book)
    {
        // $book is retrieving using Model Binding: https://laravel.com/docs/5.8/routing#route-model-binding 
        return view('book.show', compact('book'));
    }
}

index.blade.php

<div class="body text-center">
    <a href="{{ route('book.show', $book) }}">
        <h6><b>{{ $book->getName() }}</b></h6>
    </a>
</div> 

Using POST request (URI does not change) and without SLUG

I wouldn't recommend using this for the user experience.

  • The user cannot bookmark the book or share the link with someone else
  • When refreshing the page, it will prompt to the user if he want to re-submit the form request

web.php

Route::get('/books','Books\BookController@index')->name('book.index');
Route::post('/books','Books\BookController@show')->name('book.show');

BookController.php

class BookController extends Controller
{
    public function index()
    {
        return view('book.index');
    }

    public function show()
    {
        $book = Book::findOrFail(request('book_id'));
        return view('book.show', compact('book'));
    }
}

index.blade.php

<div class="body text-center">
    <form action="{{ route('book.show') }}" method="POST">
        @csrf
        <input type="hidden" value="{{ $book->id }}" name="book_id">
        <h6>
            <button type="submit"> 
                <b>{{ $book->getName() }}</b>
            </button>
        </h6>
    </form>
</div> 

You can remove the default button style to make it looks like a link https://stackoverflow.com/a/45890842/8068675

Clément Baconnier
  • 5,718
  • 5
  • 29
  • 55