I'm trying to figure out how to get all the posts for a category using Laravel Eloquent 5.3.
I have three tables..
**Posts**
id | title | text
**Term_relationships**
term_id | post_id
**Terms**
id | name
Eloquent Models
class Term extends Model
{
public function posts()
{
return $this->belongsToMany('App\Post', 'term_relationship');
}
}
class Post extends Model
{
public function terms()
{
return $this->belongsToMany('App\Term', 'term_relationship');
}
}
class Term_relationship extends Model
{
}
I've tried with for example
Term::where('name', $category)->posts->get();
Easy,
if you want Posts with Terms do this
$data = App\Post::with('terms')->get();
in your view :
#foreach($data as $post) // will loop over posts and show title
<div>{{$post->title }} </div>
#foreach($post->terms as $term)
<div> {{ $term->title }} </div> // will loop and echo all terms for current post
#endforeach
#endforeach
if you want Terms with posts do this
$data = App\Term::with('posts')->where('name', $category)->get();
in your view
#foreach($data as $term) // will loop over terms and show title
<div>{{$term->title }} </div>
#foreach($term->posts as $post)
<div> {{ $post->title }} </div> // will loop and show all posts in each term
#endforeach
#endforeach
i think the seconds way suits your needs better since int he first example u will need to use wherehas and a closure
Related
I wrote a relation belongsToMany between products and photos and now I want to show products in the home page. I did it like so:
#foreach ($latestProducts as $product)
<img src="{{$product->photos()->path}}">
#endforeach
homeController:
public function index()
{
$latestProducts = Product::orderBy('created_at' , 'desc')->limit(10)->get();
return view('front.layouts.index' , compact('latestProducts'));
}
photo model:
public function products() {
return $this->belongsToMany(Product::class);
}
product model:
public function photos() {
return $this->belongsToMany(Photo::class);
}
I got Undefined property: Illuminate\Database\Eloquent\Relations\BelongsToMany::$path .And when I write {{$product->photos[0]->path}} , the error changes to "Undefined array key 0. Also when I write {{$product->photos->path}} ,I get an error as "Property [path] does not exist on this collection instance."
I believe you got a photo attribute/field in the Photo model. Because photos is a collection of photos, you might want to write:
#foreach ($latestProducts as $product)
#foreach ($product->photos as $photo)
<img src="{{$photo->path}}">
#endforeach
#endforeach
And only the first photo:
#foreach ($latestProducts as $product)
<img src="{{$product->photos->first()->path}}">
#endforeach
// Or to be safe
#foreach ($latestProducts as $product)
<img src="{{optional($product->photos->first())->path}}">
#endforeach
// Or this in php 8
#foreach ($latestProducts as $product)
<img src="{{$product->photos->first()?->path}}">
#endforeach
You have to use
{{ $product->photos->path }}
cause when you deal with relations in blade you deal with it as a property of class of the father class unlike when you deal with it in eloquent ORM you can use photos()
Basically the error is saying that there is no property photos in the $products. Assuming that the table name is correct and the foreign keys too
you can just do:
public function index()
{
$latestProducts = Product::with('photos')->orderBy('created_at' , 'desc')->limit(10)->get();
return view('front.layouts.index' , compact('latestProducts'));
}
And in blade file try to remove the (), because it will load the relationship.
#foreach ($latestProducts->photos as $product)
<img src="{{$product->path}}">
#endforeach
I am displaying a list on my blade view which contains data from the display table: name, school and IP.
The school is saved as a school id in this table.
The Schools table contains the list of ids and related schools.
I want to use the school names from the schools table and display them on my blade view.
I can get this data separately.
This gets all the data from the display table
$records = DB::table('display')->paginate(10);
This gets all the school name from the schools table.
$schools = DB::table('schools')
->join('display', 'schools.id', '=', 'display.school')
->select('schools.name')
->get();
To display the data from the display table I'm using a foreach loop.
#foreach ($records as $record)
{{ $record->name }}
{{ $record->school }}
{{ $record->ip }}
#endforeach
I don't know how to insert the school name into the space where currently $record->school appears. $record->school displays the school ID, but I want to display the school name which is saved in the school table.
Display model
public function school()
{
return $this->belongsTo('App\School');
}
School model
public function display()
{
return $this->hasMany('App\Display');
}
If you have models and Eloquent relations, you can simply use it:
Controller
$records = Display::with('school')->paginate(10);
Blade view
#foreach ($records as $record)
{{ $record->name }}
{{ $record->school->name }} <!-- school name via relation -->
{{ $record->ip }}
#endforeach
Display Model
class Display extends Model
{
public function school()
{
return $this->hasOne('App\School');
}
}
You really should be using Eloquent as it makes life so much easier. However, using DB, you need code similar to below, where you are joining schools as a relationship to display.
$records = DB::table('display')
->join('schools', 'schools.id', '=', 'display.school')
->paginate(10);
#foreach ($records as $record)
{{ $record->name }}
{{ $record->schools->name }}
{{ $record->ip }}
#endforeach
Goods Model
class goods extends Model
{
protected $table = "goods";
public function sales(){
return $this->belongsToMany('App\sales', 'sales_details', 'goods', 'sales');
}
}
Sales Model
class sales extends Model
{
protected $table = "sales";
public function goods(){
return $this->belongsToMany('App\goods','sales_details','sales','goods');
}
}
i also make this model but i don't know if i ever need it or not
class salesDetail extends Model
{
protected $table = "sales_details";
}
my controller
public function test()
{
$goods = goods::all();
return view('test',compact('goods'));
}
my test.blade.php
#foreach($goods as $data)
<li><strong>{{ $data->name }}</strong> - {{ $data->company->kind }} {{ $data->company->name }}</li>
<p>{{ $goods->sales }}</p>
#endforeach
i connect goods table with sales table with many to many without following laravel naming.
This is my table contents
goods
-id
-name
sales
-id
-date
sales_details
-goods
-sales
-qty
-price
and i couldn't make it work. i just wanted to show the result like this
sales -id
sales - date
goods - name
sales_details - qty
sales_details - price
this should be the result
In your #foreach loop you're trying to access sales on the collection of goods rather than the instance in the loop. Also, because the sales() relationship is a belongsToMany (many-to-many) you're going to get a collection and not a single instance so you're going to need to loop through them as well e.g.
#foreach($goods as $data)
<li>
<strong>{{ $data->name }}</strong> - {{ $data->company->kind }} {{ $data->company->name }}
#foreach($data->sales as $sale)
<p>{{ $sale->date }} - {{ $sale->pivot->qty }}</p>
#endforeach
</li>
#endforeach
To access data from your pivot table you will first need to tell Laravel to include that information in the relationship:
public function sales()
{
return $this->belongsToMany('App\sales', 'sales_details', 'goods', 'sales')
->withPivot('qty', 'price');
}
You should also add the withPivot method to the good() relationship in the sales class as well.
Then you'll be able access the information from the pivot property. This is happening in the example above with {{ $sale->pivot->qty }}.
Many to many docs (scroll down to Retrieving Intermediate Table Columns )
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 have two model which is RoomCategory and Room. and i want to paginate all rooms related by each roomcategory by a foreach loop, here's my MVC.
Model
class RoomCategory extends \Eloquent {
public function Room(){
return $this->hasMany('Room','category_id','id','RoomCategory');
}
}
class Room extends \Eloquent {
public function RoomCategory(){
return $this->belongsTo('RoomCategory','id','category_id','Room');
}
}
Controller
public function index()
{
$room_category = RoomCategory::get()
->with('Room')->paginate(1);
return View::make('pages.roomlist', compact('room_category'));
}
View
#foreach($room_category as $category)
{{$category->name}}
#foreach($category->room as $rooms)
{{$rooms->name}}
{{$category->room->links()}}
#endforeach
#endforeach
and i got this error
Call to undefined method Illuminate\Database\Eloquent\Collection::with()
can someone help me how to paginate those rooms under a foreach loop of the roomcategories. thanks
To achieve what you want you have to fetch all room categories, loop through them and then loop through the each room category rooms.
This is example code:
public function index()
{
$room_category = RoomCategory::with('Room')->paginate(1);
return View::make('pages.roomlist', compact('room_category'));
}
Your view:
#foreach($room_category as $category)
{{$category->name}}
#foreach($category->Room as $rooms)
{{$rooms->name}}
#endforeach
#endforeach
You don't need get() method if you are using paginate. Replace this
$room_category = RoomCategory::get()
->with('Room')->paginate(1);
with this
$room_category = RoomCategory::with('Room')->paginate(1);
EDIT
It would be good if you don't use pagination links for room in your index page, just paginate your roomcategory.
$room_category = RoomCategory::with([
'Room' => function($query) {
$query->latest()->limit(5);
}
])->paginate(3);
On your index view paginate the categories and make a link to each category page and paginate your room their
index.blade.php
#foreach($room_category as $room_cat)
#foreach($room_cat->Room as $room)
<div class="room-section"></div>
#endforeach
View more of this category
#endforeach
{{ $room_category->links() }}
Your Controller
public function showCategory($id)
{
$room_category = RoomCategory::with([
'Room' => function($query) {
$query->latest()->paginate(8);
}
])->find($id);
return View::make('category.show', compact('$room_category'));
}
and category/show.blade.php you can paginate room
#foreach($room_category->Room as $room)
<div class="room-section"></div>
#endforeach
{{ $room_category->Room()->links() }}