im trying to make a searchfield that returns records that are equal to the search result. I have 2 models, Brands and Cars. My relationship is that a brand(Opel, Suzuki etc.) has many cars and a car belongs to a brand.
Brand Model
class Brand extends Model
{
protected $fillable = [
'brandname'
];
public function cars(){
return $this->hasMany(Car::class);
}
}
Cars Model
class Car extends Model
{
public function brand(){
return $this->belongsTo(Brand::class);
}
protected $fillable = [
'user_id', 'brand_id', 'year', 'licensplate'
];
}
I have a page that shows all the cars with some information.
Find Cars form
This is de code of the page:
<div class="col-sm-8 blog-main">
<h1>Alle auto's</h1><hr>
<form method="POST" action="/allcars">
{{csrf_field()}}
<div class="form-group">
<input type="text" name="searchfield" placeholder="Merk">
<button type="submit">Zoek</button>
</div>
</form>
#foreach($brands as $brand)
#foreach($brand->cars as $car)
<div class="form-group">
<h5>
{{$brand->brandname}}
</h5>
Kenteken: {{$car->licensplate}}<br>
Bouwjaar: {{$car->year}}<br>
</div>
#endforeach
#endforeach
</div>
This is my route file:
Routes
Route::post('/allcars', 'CarController#show');
Finally my controller file:
CarController.php
public function show(){
$input = request('searchfield');
if(empty($input))
{
return back();
}
else if(is_numeric($input))
{
// Search on year
$brands = Brand::with('cars')->whereHas('cars', function($q)
{
$input = request('searchfield');
$q->where('year', $input);
})->get();
return view('content.cars.index', compact('brands'));
}
else
{
// Search on brandname
$brands = Brand::with('cars')->get()->where('brandname', $input);
return view('content.cars.index', compact('brands'));
}
}
The else if statement is working perfectly. When an integer (year) is being filled in it uses the year search and when a string is filled in it uses the brand search.
However, the brand search is working perfectly. If I search on 'Opel', i get all the cars with some information that are from the brand Opel. But when I search on 1990, I get a brand that has a car with the year 1990, and then i get the other cars from that brand as well.
Example:
If I search for 1990, I get 3 cars: Opel(1990), Opel(2000) and Opel(1882).
An other example:
I search on 2000, I get 5 cars: Opel(2000), Opel(1990), Opel(1882), BMW(2000), BMW(1721).
I think I am doing something wrong in my code, please correct me.
These are my migrations btw:
Car Migration
Schema::create('cars', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedInteger('brand_id');
$table->foreign('brand_id')->references('id')->on('brands')->onDelete('cascade');
$table->string('year');
$table->string('licensplate');
$table->timestamps();
});
Brand Migration
Schema::create('brands', function (Blueprint $table) {
$table->increments('id');
$table->string('brandname');
$table->timestamps();
});
Try changing the else if part to this:
else if(is_numeric($input))
{
// Search on year
$brands = Brand::with(['cars' => function ($q) use ($input) {
$q->where('year',$input);
}])->get();
return view('content.cars.index', compact('brands'));
}
Related
I have 1 relation
Order(id, user_id, total_price)
OrderDetail(order_id, product_id, num_of_product)
Product(id, title, num_of_existed, price)
Ask: How to get order across template:
order:[
id: 1,
user_id:1,
total_price:1.1,
order_detail:[
id:1,
order_id:1,
book_id:1,
num_of_product:10
product:[
id:1,
title: 'abc',
num_of_existed: 100,
price: 0.1
]
]
]
Create relationship in your Order model as ,
public function order_details()
{
return $this->hasOne('App\OrderDetail','order_id','id');
}
In your Orderdetail model,
public function product_details()
{
return $this->belongsTo('App\Product','id','product_id'); // first foreign key then local key
}
In your controller
$orders = Order::all();
return view('view_name',compact('orders'));
In the view
#foreach ($orders as $order)
#if ($order->order_details)
{{$order->order_details->num_of_product}}
#if($order->order_details->product_details)
{{$order->order_details->product_details->title}}
{{$order->order_details->product_details->num_of_existed}}
{{$order->order_details->product_details->price}}
#endif
#endif
#endforeach
you can do it via laravel eloquent relationship, to define relationship you will have 3 models like Order, OrderDetail,Product related to corresponding tables.
On your order model:
public function OrderDetail()
{
return $this->hasOne('App\OrderDetail','order_id');
}
On your OrderDetail model:
public function Order()
{
return $this->belongsTo('App\Order','order_id');
}
public function Product()
{
return $this->belongsTo('App\Product','product_id');
}
Then on your controller
public function foo(){
$orders=Order::all(); //remember to use 'App\Order'
return view('filename',compact('orders'));
}
Now on your blade, you will find all related table data just by chaining orders
#foreach ($orders as $order)
#if ($order->OrderDetail)
#if($order->OrderDetail->Product)
{{$order->OrderDetail->Product->title}}
#endif
#endif
#endforeach
for more see documentation
In a Laravel 5 app, I have 5 tables - users, books, authors, followers and activity_feeds.
Users can follow authors and a book can have several authors.
When a book is made, an activity_feeds entry is made that references the book_id.
I need to build an eloquent query to get a collection of activity_feeds for each users, to iterate over in their home page activity feed.
My Book model includes
public function authors()
{
return $this->belongsToMany('App\Author')->withTimestamps();
}
The activity_stream table looks like this (with example data)
id (1)
user_id (3)
type (New Book)
book_id (18)
created_at etc
and my User controller includes
public function feedItems()
{
return $this->hasMany('App\ActivityFeed');
}
public function userFollowings()
{
return $this->belongsToMany('App\User', 'followers', 'follower_id', 'subject_id')->withTimestamps();
}
public function authorFollowings()
{
return $this->belongsToMany('App\Author', 'followers', 'follower_id', 'author_id')->withTimestamps();
}
My current query (which isn't working), contained in the User model is
public function getactivityFeedsAttribute()
{
$userFollowings = $this->userFollowings()->pluck('subject_id')->toArray();
$authorFollowings = $this->authorFollowings()->pluck('author_id')->toArray();
$userFeeds = ActivityFeed::whereIn('user_id', $userFollowings)
->orwhereIn('book_id', function($query){
$query->select('id')
->from(with(new Book)->getTable())
->whereHas->authors()
->whereIn('id', $authorFollowings);
})
->get();
return $userFeeds;
}
$userFollowings and $authorFollowings are working fine.
I'm not sure I'm using the correct syntax for data[book_id] to pluck the book id from the activity_feeds row, and I'm really not sure if I can nest a table look up or use $query like this.
It also seems VERY complicated. Am I might be missing something much more straight forward?
In the blade I am calling like this
#forelse ($user->activityFeeds as $activityFeed)
<div class="row">
<div class="col-2">
{{ $activityFeed->user->firstname }}
</div>
<div class="col-2">
{{ $activityFeed->type }}
</div>
</div>
<hr>
#empty
No activity yet
#endforelse
Which works if I just query 'ActivityFeed::whereIn('user_id', $userFollowings)'
I'll rewrite the query in an answer because comments aren't very legible.
public function getactivityFeedsAttribute()
{
$userFollowings = $this->userFollowings()->pluck('subject_id')->toArray();
$authorFollowings = $this->authorFollowings()->pluck('author_id')->toArray();
$books = Book::whereHas('authors', function ($query) use ($authorFollowings) {
// Have to be explicit about which id we're talking about
// or else it's gonna throw an error because it's ambiguous
$query->whereIn('authors.id', $authorFollowings);
})->pluck('id')->toArray();
$userFeeds = ActivityFeed::whereIn('user_id', $userFollowings)
->orwhereIn('book_id', $books)
->get();
return $userFeeds;
}
I recently asked a question about defining many to many relationships (using belongsToMany) and it was a huge help. So now in my models I have:
Users model
public function subjects()
{
return $this->belongsToMany('App\Subject', 'users_subjects', 'user_id', 'subjects_id');
}
Subjects model
public function users()
{
return $this->belongsToMany('App\User', 'users_subjects', 'subject_id', 'user_id');
}
This way I establish a relationship between users and subjects via the users_subjects table. My next step was to create a controller, SubjectsController, which ended up looking like this:
class SubjectsController extends Controller
{
// returns the view where subjects will be displayed
public function index()
{
return view('profiles.professor.prof_didactic_subjects');
}
// get users with subjects
public function getSubjects()
{
$subjects = User::with('subjects')->get();
}
// get a single user with a subject
public function getSubject($id)
{
$materia = User::where('id', '=', $id)->with('subjects')->first();
}
}
I'm not very sure about the code in the controller though.
The final step is where it gets tricky for me, even after reading the docs: I want to pass each result to the view, so I can have multiple tiles, each populated with data from subjects the user is associated with:
#foreach ($subjects as $subject)
<div class="tile is-parent">
<article class="tile is-child box">
<p class="title">{{ $subject['name'] }}</p>
<div class="content">
<p>{{ $subject['description'] }}</p>
</div>
</article>
</div>
#endforeach
I tried many different route configurations, but kept getting either the undefined variable error or trying to access non-object error.
What's the proper course of action here? I feel I'm missing something very basic. Thanks in advance for any help.
The answer
The solution provided below by #Sohel0415 worked perfectly. My index() method on the controller now looks like this:
public function index()
{
// temporary value while I figure out how to get the id of the current user
$user_id = 6;
$subjects = Subject::whereHas('users', function($q) use ($user_id){
$q->where('user_id', $user_id);
})->get();
return view('profiles.professor.prof_didactic_subjects')->with('subjects', $subjects);
}
My route looks like this:
Route::get('/professor', 'SubjectsController#index');
I was pretty lost, so this absolutely saved me, thanks again :)
You need to pass $subjects to your view. You can use compact() method for that like -
public function index()
{
$subjects = Subject::with('users')->get();
return view('profiles.professor.prof_didactic_subjects', compact('subjects'));
}
Or using with() method like -
public function index()
{
$subjects = Subject::with('users')->get();
return view('profiles.professor.prof_didactic_subjects')->with('subjects', $subjects);
}
If you want to get Subject for a particular user_id, use whereHas() -
$subjects = Subject::whereHas('users', function($q) use ($user_id){
$q->where('user_id', $user_id);
})->get();
I have 3 models in my app Users, Sales and Plans, when I render sales for each customer (due to storing) I only get id's for other users and models related to that sale (like account manager, owner, plan), now I'm trying to use those ID's inside blade to get names or other rows based on ID and model. Here is the show function:
public function show($id) {
$user = User::find($id);
$sales = Sale::where('customer_id', '=', $id)->get();
return view('profiles.customer', ['user' => $user, 'sales' => $sales]);
}
And in blade I get all those sales like:
#foreach ($sales as $sale)
<li>
<i class="fa fa-home bg-blue"></i>
<div class="timeline-item">
<span class="time"><i class="fa fa-clock-o"></i> {{$sale->created_at->format('g:ia, M jS Y')}}</span>
<h3 class="timeline-header">{{$user->name}} became a customer</h3>
<div class="timeline-body">
<p>Date: {{$sale->sold_date}}</p>
<p>Price: {{$sale->sale_price}}</p>
</div>
</div>
</li>
#endforeach
So inside each record I have like "account_manager_id", "agent_id", "owner_id", "plan_id".
Currently I have this solved by adding public static function (this is for users, have same function for Plan model as well) in Sale model class:
public static function getUser($id) {
return User::where('id', $id)->first();
}
And I'm using it like this in Blade:
Account manager: {{$sale->getUser($sale->account_mgr_id)->name}}
Is this the safest and best way to do it? Or there is something I'm overlooking here?
You need to add relationships in your Sales Model.
class Sales extends Eloquent {
.....
.....
public function accountManager() {
return $this->hasMany('App\User', 'account_manager_id');
}
public function agents() {
return $this->hasMany('App\User', 'agent_id');
}
public function owner() {
return $this->hasOne('App\User', 'owner_id');
}
}
Now $sales->agents will give you a user with agent_id as id in User table.
Update your hasOne, hasMany relationships as your need. Laravel Documentation.
From your blade template, your access your AccountManager as
#foreach($sales->accountManager as $manager)
Name: {{ $manager->name}}
#endforeach
I think you could use Eloquent relationships. Taking your example, you should define relationship in your User model:
<?php
class User extends Eloquent {
public function sales() {
return $this->hasMany(Sale::class, 'customer_id');
}
}
Then, whenever you need to get sales of that user (entries, that relate via customer_id column), just simply do
<?php
$user = User::find($id);
$sales = $user->sales;
This is very fun when when you have to print out list of users that have sales, for example
<?php
public function showUsersWithSales() {
$users = User::with('sales')->get();
return view('users-with-sales', compact('users'));
}
users-with-sales.blade.php example:
#foreach ($users as $user)
User: {{ $user->name }}<br>
Sales:<br>
#foreach ($user->sales as $sale)
{{ $sale->amount }} {{ $sale->currency }} # {{ $sale->created_at }}<br>
#endforeach
<hr>
#endforeach
It would print all users with their sale amount and currency, followed by date when it was created.
This sample takes into account, that your User model has name attribute and your Sale model has amount, currency, created_at and customer_id fields in your database.
To reverse the action, say you have a sale and want to know who made it, just simply define a relationship!
<?php
class Sale extends Eloquent {
public function customer() {
return $this->belongsTo(User::class, 'customer_id');
}
}
Hope that helps!
Eloquent Relationship is your friend, https://laravel.com/docs/5.2/eloquent-relationships and you can solve your problem easily.
Suggestion is to remove all those function access and control from view and put it somewhere else. This will be good habit for you so you can avoid the infamous fat view.
I am trying to do a simple group by 'alpha' in my loop for a glossary page but not sure how to achieve this. My data is
alpha glossary_title
A Apple B Banana A Another Apple!
GlossaryController.php
public function index() {
$glossary = Glossary::groupBy('alpha')->orderBy('glossary_title', 'asc')->get();
return View::make('glossary')->with('glossary', $glossary);
}
migration
Schema::create('glossary', function(Blueprint $table)
{
// columns
$table->increments('id');
$table->string('glossary_title');
$table->text('glossary_desc')->nullable();
$table->char('alpha', 1);
$table->timestamps();
});
glossary.blade.php
#foreach($glossary as $glossary)
<li>{{ $glossary->glossary_title}} <br /> {{ $glossary->glossary_desc}}</li>
#endforeach
This will return a new collection groupped by $glossary->alpha:
$glossary = Glossary::orderBy('glossary_title', 'asc')->get();
$glossary = $glossary->groupBy('alpha');
// same as this:
$glossary = $glossary->groupBy(function ($entry) {
return $entry->alpha;
});
You will need 2 loops in your view then, first for groups, second for entries in each group.