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">
<h6><b>{{($book->getName())}}</b></h6>
</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');
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
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;
}
Related
This is error Call to a member function comments() on null, in model give a relation still show this error
Article model
function user() {
return $this->belongsTo(User::class, 'id');
}
public function comments()
{
return $this->hasMany(Comment::class, 'id');
}
Comment Model
public function user()
{
return $this->belongsTo(User::class);
}
public function article()
{
return $this->belongsTo('App\Article');
}
This is contoller
public function store(Request $request)
{
//dd($request->all());
Auth::user();
$comment = new Comment;
$comment -> user_id=Auth::user()->id;
$comment-> comment = $request->get('comment');
$article = Article::find($request->article_id);
$article->comments()->save($comment);
return redirect()->back()->with('success', 'your comment,successfully save');
}
This is blade file
<form method="post" action="{{ route('comment.store') }}">
#csrf
<div class="form-group">
<textarea class="form-control" name="comment"></textarea>
<input type="hidden" name="article_id"/>
</div>
<div class="form-group">
<input type="submit" class="btn btn-success" value="Add Comment" />
</div>
</form>
You need to set a value for the hidden field.
<input type="hidden" name="article_id" value="{{ $article->id }}"/>
Secondly for easier debugging these errors, using findOrFail() will ensure your app blows up, with a proper error message. Instead of just returning null.
$article = Article::findOrFail($request->article_id);
EDIT
You are also mixing two saving approaches together, either you associate the article to the comment or create a new comment. This is the approach i like to use.
$comment = new Comment;
$comment->user_id = Auth::user()->id;
$comment->comment = $request->get('comment');
$article = Article::find($request->article_id);
$comment->article()->associate($article);
$comment->save();
I have a little one with my school app. I want to display all the faculties of a school. Indeed in my DB a school can have one or more faculties and a faculty can belong to one or more schools.
Model School:
public function filieres ()
{
return $this->belongsToMany('App\Models\Filiere','etablissement_filieres','id_etablissements','id_filieres');
}
public function etablissement_filieres(){
return $this->hasMany('App\Models\Etablissement_filiere');
}
protected $fillable = [
'nom', 'image', 'ville', 'adresse', 'contact_1', 'contact_2',
'email', 'logo', 'presentation', 'brochure', 'localisation',
];
Model table pivot Etablissement_filiere:
public function filiere(){
return $this->belongsTo('App\Models\Filiere');
}
protected $fillable = [
'id', 'id_etablissements', 'id_filieres', 'prise_en_charge', 'prix',
];
Model Filiere:
public function etablissements ()
{
return $this->belongsToMany(Etablissement::class,'etablissement_filiere');
}
protected $fillable = [
'nom', 'diplome_requis', 'diplome_obtenu', 'prix', 'duree', 'type',
];
Controller:
public function show($id)
{
$faculty = Etablissement_filiere::where('id_etablissements','=','$id')->get();
return view('etablissements/edhec/touteslesfilieresedhec', compact('faculty','etablissements'));
}
Blade view:
#foreach($faculty->filieres as $filiere)
<div class="container bg-fil py-4 my-5">
<div class="row pl-5">
<div class="col-md-9">
<h6 class="font-weight-bold">{{ $filiere ->nom}} <br>
<span class="text-primary"> {{ $filiere ->diplome_obtenu}}</span></h6>
</div>
<div class="col-md-3 pt-n5">
<img src="{{asset($etablissement->image)}}" alt="">
</div>
</div>
<div class="row pl-5 mt-md-n5">
<div class="col-md-6">
<h6> <strong> Diplôme réquis</strong>: {{ $filiere ->diplome_requis}} <br>
<strong>Durée</strong>: {{ $filiere ->duree}} <br>
<strong>Montant de la formation</strong>: {{ $etablissement_filieres ->prix}}</h6>
</div>
<div class="col-md-6">
<h6> <strong> Mode d'etude</strong>: {{ $filiere ->type}} <br>
<strong>Prise en charge</strong>: {{ $etablissement_filieres ->prise_en_charge}}</h6>
</div>
</div>
<div class="row pl-5 mt-4">
<div class="col-md-6">
INSCRIVEZ VOUS MAINTENANT
</div>
</div>
</div>
#endforeach
I am trying to display all the faculties in the school but I have this error:
Property [filieres] does not exist on this collection instance.
Can you tell me where the error is preventing?
Your immediate view error is when it tries to evaluate $faculty->filieres.
Calls to something like Model::where()->get() return a Collection instance (which is like an iterable group) of Models, not a single Model. Even if that collection only contains one model, it's still a group and not the model itself.
So, $faculty = Etablissement_filiere::where('id_etablissements','=','$id')->get(); returns a Collection, not a single model. A single model may have a filieres property, but the Collection instance (which itself is a class in Laravel) does not. So, if what you want is the first result only, and not a collection, end that line with ->first() instead of ->get().
However even if you fix that, you also have a second problem. You're getting an instance of the pivot model Etablissement_filiere, and then trying to access the filieres property on it (which it doesn't have). Instead, you should be getting an instance of the School model. If you've defined your relations correctly, Laravel will take care of finding the pivot for you, so you normally wouldn't access a pivot model directly unless you had a particular reason to. So, instead try this in your controller:
public function show($id)
{
$establissement = Etablissement::find($id);
$faculty = $establissement->filieres;
return view('etablissements/edhec/touteslesfilieresedhec', compact('faculty','etablissement'));
}
and then in your view:
#foreach($faculty as $filiere)
There are cleaner ways to do this (e.g. look into some tutorials on route-model binding), but that should at least solve the error for your current code.
Change your code to
public function show($id)
{
$faculty = Etablissement_filiere::where('id_etablissements','=',$id)->first();
return view('etablissements/edhec/touteslesfilieresedhec', compact('faculty','etablissements'));
}
been trying to create a laravel form with several fields that the user can enter text/number into a field and it takes the field with data and performs a database query. Now the form works with just one field but when i add more fields it only returns data for the final query, not for the other two.
perfumes controller
class perfumescontroller extends Controller
{
public function index()
{
$pstoreNum = request('pstoreNum');
$result = perfumes::where('StoreNumber','=',$pstoreNum)
->get();
return view('perfumes',compact('result'));
}
public function perfWeekSearch()
{
$weekNum = request('perfWeekNum');
$result = perfumes::where('WeekNumber','=',$weekNum)
->get();
return view('perfumes',compact('result'));
}
}
Route::get('/perfumes', 'perfumescontroller#index');
Route::get('/perfumes', 'perfumescontroller#perfWeekSearch');
Blade:
<form action="perfumes" method="get">
{{ csrf_field() }}
<div class="input-group">
<input type="text" class="form-control" name="perfWeekNum" placeholder="Type in Store Number">
<span class="input-group-btn">
<button type="submit" class="btn btn-default">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</form>
Do i need to use some sort of check if not null method? or is there an easier way??
Thanks
I think this would be work below is your perfumes controller
class perfumescontroller extends Controller
{
public function index()
{
$data = $request->all();
if(!empty($data['pstoreNum'])){
$pstoreNum = $data['pstoreNum'];
$result = DB::table('perfumes')->where('StoreNumber','=',$pstoreNum)
->get();
return view('perfumes',compact('result'));
} else if(!empty($data['perfWeekNum'])){
$weekNum = $data['perfWeekNum'];
$result = DB::table('perfumes')->where('WeekNumber','=',$weekNum)
->get();
return view('perfumes',compact('result'));
}
}
}
and you use any with route like below:
Route::any('/perfumes', 'perfumescontroller#index');
i defined a route as
Route::get('roundtables/{name}/tags/store',['as'=>'tags.store','uses'=>'TagController#store','middleware'=>['owner','auth']]);
In my view, i have a form in this url
http://localhost:8000/roundtables/1/tags
<div class="col-md-3">
<div class="well">
{!! Form::open(['route'=>'tags.store','method'=>'GET']) !!}
<h2>New Tags</h2>
{{ Form::label('name','Name') }}
{{ Form::text('name',null,['class'=>'form-control']) }}
{{Form::submit('Create New Tag',['class'=>'btn btn-primary btn-block btn-h1-spacing'])}}
</div>
</div>
My problem is, how to get the id from url which is id '1' and passing into the form when user clicked submit.
My controller
public function store(Request $request,$name)
{
$this->validate($request,array('name'=>'required|max:255'));
$tag=new Tag;
$tag->name=$request->name;
$tag->roundtable_id=$name;
$tag->save();
Session::flash('success','New Tag was successfully added');
return redirect()->route('tags.index');
}
When you're using custom routes for CRUD, avoid using standard RESTful method and route names. Before building the form, you need to pass this variable to the view:
public function createTag($name)
{
....
return view('form', compact('name'));
}
Define your route as:
Route::get('roundtables/{name}/tags/storeTag',['as'=>'tags.storeTag','uses'=>'TagController#storeTag','middleware'=>['owner','auth']]);
Then pass variable to from the form:
{!! Form::open(['route' => ['tags.storeTag', $name], 'method'=>'GET']) !!}
And get it in the controller:
public function storeTag(Request $request, $name)
{
echo $name;
You get the wildcard value by using request() helper method easily.
{{request()->route('name')}}
In your TagController
public function index($name)
{
$tags= Tag::where($name)->first();
// add name parameter to return
return view('tags.index')->withTags($tags)->withName($name);
}
And in your view
<div class="col-md-3">
<div class="well">
//edit this form tag
{!! Form::open(['route'=>['tags.store',$name],'method'=>'GET']) !!}
<h2>New Tags</h2>
{{ Form::label('name','Name') }}
{{ Form::text('name',null,['class'=>'form-control']) }}
{{Form::submit('Create New Tag',['class'=>'btn btn-primary btn-block btn-h1-spacing'])}}
</div>
</div>
And in your TagController#store
public function store(Request $request,$name){
echo $name;
}
This should work.
Request::segment(2)
Or pass it from controller:
public function index($name)
{
$tags= Tag::where($name)->first();
return view('tags.index')->withTags($tags)->with('name', $name);
}
Then just pass it into the form:
{!! Form::open(['route'=>['tags.store', $name],'method'=>'GET']) !!}
I have a list containing article posts from all categories. I want to display the category tag in each post on the list and I tried this :
<article class="post bg z-depth-1">
<?php foreach ($article_list as $article): ?>
<div class="post-img">
<a href="post.html">
<img class="retina" src="{{ asset('image/' . $article->image) }}" width="820" height="500" alt="Post Image">
</a>
</div>
<div class="post-content">
<div class="post-header center-align">
<div class="tags">
{{ $article->category->title }}</div>
<h2 class="post-title">{{ $article->title }}</h2>
<div class="date">Posted on {{ Carbon\Carbon::parse($article->created_at)->format('F j, Y') }}</div>
</div>
<div class="post-entry">
<p>sss</p>
</div>
<div class="post-footer">
<div class="post-footer-item">
<span class="text">Read More</span> <i class="fa fa-arrow-circle-right"></i>
</div>
</div>
</div><!-- .post-content -->
<?php endforeach ?>
</article><!-- .post -->
and it gave me error Undefined property: stdClass::$category and I don't know why, I already define the relationship in each model Article and Category. Thanks for the help!
In Article model :
public function category()
{
return $this->belongsTo('App\Category', 'category_id');
}
In Category model :
public function article() {
return $this->hasMany('App\Article', 'category_id');
}
Controller :
public function index() {
$article_list = Article::all();
return view('article/index', compact('article_list', $article_list));
}
What you need to do is eager load those relationships in your controller.
When you pull the records do it like this:
$article_list = Article::with('category')->get();
https://laravel.com/docs/5.3/eloquent-relationships#eager-loading
Change this: $article->category->title
To this: $article->category()->title
When you define the relationship in your model you are also creating a function not a property called category.
public function category()
{
return $this->belongsTo('App\Category');
}
In Category model :
public function article() {
return $this->hasMany('App\Article');
}
Controller :
public function index() {
$article_list = Article::all();
return view('article/index', compact('article_list'));
}
This should work for you now like this.