Can't select specific relationship columns with eloquent's with method - php

I want to improve the resolution times of my backend axios calls and so I'm trying to use with method special syntax for selecting specific columns, but for some reason category field is returning null.
In my method:
$venues = Venue::select(['id','name','lat','lng'])->with('category:id,title')->take(10)->get();
My venue relationship:
public function category()
{
return $this->belongsTo('App\Models\VenueCategory', 'venuecategory_id');
}
and VenueCategory
public function venue()
{
return $this->belongsTo('App\Models\Venue', 'venue_id');
}
The resulting venue payload is like this (notice category is null)
Object { id: 1, name: "El Pimpi", lat: "36.7219260", lng: "-4.8594939", category: null}
Venue migration:
Schema::create('venues', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('venuecategory_id')->index();
$table->foreign('venuecategory_id')->references('id')->on('venuecategories')->onDelete('cascade')->onUpdate('cascade');
$table->unsignedInteger('user_id')->index()->nullable();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->string('name');
$table->string('description');
$table->string('image')->nullable();
$table->string('address')->nullable();
$table->text('openingTimes')->nullable();
$table->decimal('lng', 10, 7);
$table->decimal('lat', 10, 7);
$table->boolean('isConfirmed')->default(0);
$table->boolean('isHot')->default(0);
$table->boolean('isVisible')->default(0);
$table->boolean('isFeatured')->default(0);
$table->timestamp('lastScrapeForContacts')->nullable();
$table->timestamps();
});
VenueReview migration:
Schema::create('venuereviews', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('venue_id')->index();
$table->foreign('venue_id')->references('id')->on('venues')->onDelete('cascade')->onUpdate('cascade');
$table->unsignedInteger('user_id')->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->integer('rating');
$table->text('body')->nullable();
$table->boolean('isVisible')->default(0);
$table->boolean('isFeatured')->default(0);
$table->boolean('isConfirmed')->default(0);
$table->timestamps();
});

When you specify columns in a Laravel query and need to get a relationship, you also need to get the column that the relationship uses, or else it won't have the data to make the relationship. The child models are queried after the original model is retrieved. Add the column, and it will work:
$venues = Venue::select(['id','name','lat','lng','venuecategory_id'])->with('category:id,title')->take(10)->get();

Related

how to display the number of products in that category? in laravel using Eloquent ORM

How can I display the number of products in a category using Eloquent ORM?
Categories table
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('categoryName');
$table->text('categoryDescription')->nullable();
$table->integer('parentId')->nullable();
$table->string('categorySlug')->unique();
$table->text('categoryImage');
$table->tinyInteger('status');
$table->timestamps();
});
Products table
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('productName');
$table->text('productDescription')->nullable();
$table->integer('categoryId');
$table->integer('manufacture')->nullable();
$table->text('productTags')->nullable();
$table->text('productSlug');
$table->float('regularPrice');
$table->tinyInteger('status');
$table->timestamps();
});
I want, for example:
Fruits & Vegetables (5)
Fresh Fruits (2)
Breakfast (3)
Once you have the products relationship in your Category model:
public function products()
{
return $this->hasMany(\App\Models\Product::class, 'categoryId');
}
You can then do something like:
$categories = \App\Models\Category::query()->withCount('products')->get();
// each $category in your collection will have a products_count attribute
foreach($categories as $category){
dump($category->id.' has '.$category->products_count.' products!');
}
This will not be recursive. If you need recursion, you'll have to so some researches since it is way more complex to implement without performance issues.

Laravel: Paginate query which is ordered by a hasOne-relationship

I have a Customer model which has many Contacts. I want to create a view / list of contacts which paginated and ordered by the latest Contact.
Customer.php
public function contacts()
{
return $this->hasMany(Contact::class);
}
public function latestContact()
{
return $this->hasOne(Contact::class)->latestOfMany()->withDefault();
}
In the view, I want to show the customers like this:
#foreach ($customers as $customer)
<x-table.row wire:key="row-{{ $customer->id }}">
<x-table.cell>
{{ $customer->last_name }}, {{ $customer->first_name }}
</x-table.cell>
<x-table.cell>
{{ $customer->latestContact->contacted_at }}
</x-table.cell>
</x-table.row>
#endforeach
Table Structure
Schema::create('customers', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id');
$table->string('first_name');
$table->string('last_name');
});
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id');
$table->foreignId('customer_id');
$table->string('type');
$table->string('body');
$table->timestamp('contacted_at');
});
I am struggling to get the correct query for this. Here's my last try which gives me the following error:
Illuminate\Database\QueryException
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'latestContact.contacted_at' in 'order clause'...
return view('livewire.dashboard', [
'customers' => Customer::with('customers.*', 'latestContact.contacted_at')
->join('contacts', 'contacts.customer_id', '=', 'customers.id')
->orderBy('latestContact.contacted_at')
->paginate(25)
]);
Appreciate your support!
I think you should rewrite your query like this
Customer::with(['contacts', 'latestContact'])
->orderBy('latestContact.contacted_at')
->paginate(25)
Updated Answer
$customers= Customer::with(['contacts', 'latestContact'=>function($query){
return $query->orderBy('contacted_at','DESC');
}])->paginate(25);
In Customer model you need to modify relation like below
public function latestContact()
{
return $this->hasOne(Contact::class)->withDefault();
}
latestOfMany Indicate that the relation is the latest single result of a larger one-to-many relationship.
latestOfMany($column = 'id', $relation = null)

How to use hasOne relationship correctly?

I am learning Laravel and I'm trying to create simple online store.
I created tables Items and Amounts. Now I want to display all Items with their amount in stock but for some reason unknown to me, amount of item is not fetched into items.
These are my schemas for tables:
Items:
Schema::create('items', function (Blueprint $table) {
$table->increments('id');
$table->integer('category_id')->unsigned();
$table->string('name', 120)->nullable(false);
$table->float('price',8,2)->unsigned()->nullable(false);
$table->longText('short_specification');
$table->longText('specification');
$table->longText('description');
$table->string('photo', 100);
$table->engine = 'InnoDB';
$table->foreign('category_id')->references('id')->on('categories');
});
Amounts:
Schema::create('amounts', function (Blueprint $table) {
$table->integer('item_id')->unsigned();
$table->integer('amount')->unsigned()->nullable(false);
$table->engine = 'InnoDB';
});
Schema::table('amounts',function($table){
$table->foreign('item_id')->references('id')->on('items');
$table->primary('item_id');
});
These are my models:
Item:
class Item extends Model
{
public $timestamps = false;
function amount()
{
return $this->hasOne('App\Amount','item_id','id');
}
}
Amount:
class Amount extends Model
{
function item()
{
//$this->belongsTo('App\Item');
return $this->belongsTo('App\Item','item_id','id');
}
}
When I do:
$items = DB::table('items')->get();
dd($items);
return view('home')->with('items',$items);
Items are displayed correctly, but amount of item isn't there.
When I do:
#foreach($items as $item)
{{ $item->id }}
{{ $item->amount }}
#endforeach
I get:
Undefined property: stdClass::$amount (View: D:\2.
PROGRAMY\xampp\htdocs\silicon_store\resources\views\home.blade.php)
error.
From what I've seen on the web (I've been trying to fix this for over 3 hours now so I must be doing something totally wrong) it should work properly but it isn't.
With $items = DB::table('items')->get();, you're using the query builder. It won't have the value of the relationship unless you join the amounts table in the query.
$items = DB::table('items')
->leftJoin('amounts', 'items.id', '=', 'amounts.item_id')
->get();
I think you could also use an Eloquent query. In that case each $item would be an instance of the Item model rather than a StdClass object.
$items = App\Item::with('amount')->get();
or you can use kind of this query
$items = App\Item::whereHas('amount')->get()
Here link to understanding whereHas

Join using associatif table

I set up a relationship between the following three tables : Card, Event and Presence (associatif table). Presence my associatif table, which contains id_card and id_event. I tried to create a fuction that return $count (number of event foreach member).
But my problem is $count return if the number of all event or zero and the result have been 1
My controller :
$count = DB::table('presences')
->join('cards','cards.id','presences.id_card')
->join('events','events.id','presences.id_event')
->where('presences.date','like','%event.dateEvent%')
->where('presences.qrcode','like','%cards.qrcode_membre%')
->get()
->count();
Model Card :
public function event()
{
return $this->belongsToMany('App\Event');
}
Migration :
$table->bigIncrements('id');
$table->string('nom');
$table->string('prenom');
$table->string('cin');
$table->date('dateNaissance');
$table->date('dateAffection');
$table->string('qrcode_membre')
Model Event :
public function card()
{
return $this->belongsToMany('App\Card');
}
Migration :
$table->bigIncrements('id');
$table->string('libelle');
$table->string('description');
$table->date('dateEvent');
Model Presence :
$table->bigIncrements('id');
$table->date('heureEntree');
$table->date('heureSortir');
$table->date('date');
$table->string('qrcode');
$table->unsignedInteger('id_card');
$table->foreign('id_card')->references('id')->on('cards');
$table->unsignedInteger('id_event');
$table->foreign('id_event')->references('id')->on('events');

Column not found: 1054 Unknown column 'id' in 'where clause' - Laravel

There has been lot of issues on this but i am following the exact procedure to solve this issue as described in the other related S.O questions yet i get the same error.
Shop
public function products()
{
return $this->hasMany('App\Product');
//->withTimestamps();
}
Product
public function shop()
{
return $this->belongsTo('App\Shop');
//->withTimestamps();
}
This is how my schema looks like
Schema::create('products', function (Blueprint $table) {
$table->increments('product_id');
$table->integer('shop_id')->unsigned()->nullable();
$table->foreign('shop_id')->references('id')->on('shops');
$table->timestamps();
);
Controller
$products = new Product(array(
'name' => $request->('name');
));
$shop->products()->save($products);
After submitting my form data into the products table, i get an error Column not found: 1054 Unknown column 'id' in 'where clause'. Laravel by default seems to take id by default as my primary key but then it is product_id.
In my model, i have specified protected $primaryKey = 'product_id' and it wouldn't solve my problem. What am i doing differently ?
In the relationships you have to specify the name of the primary key when it is not called id, try to change the model like this:
SHOP
public function products()
{
return $this->hasMany('App\Product', 'product_id');
//->withTimestamps();
}
PRODUCT
public function shop()
{
return $this->belongsTo('App\Shop', 'product_id');
//->withTimestamps();
}
In the documentation explains how it works:
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many
If you are using resoure routes, then you need to specify the route key name as well:
public function getRouteKeyName()
{
return 'product_id';
}
I had tried with my local with following:
Schema:
Schema::create('shops', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('products', function (Blueprint $table) {
$table->increments('product_id');
$table->string('name');
$table->integer('shop_id')->unsigned()->nullable();
$table->foreign('shop_id')->references('id')->on('shops');
$table->timestamps();
});
Model relationship exactly same as your post.
Controller code:
$shop = new Shop;
$shop->name = 'test';
$shop->save();
$products = new Product;
$products->name = 'test';
$shop->products()->save($products);
And final result? It is saved into products table without error.
I am using Laravel 5.4 at my local.
When it stated Unknown column 'id' in 'where clause' but does it stated is products table? Can you show the full Sql error log?
I suspect it might be other relationship caused the error.

Categories