How to use hasOne relationship correctly? - php

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

Related

make relation for value from array laravel

I have a table for data:
Schema::create('general', function (Blueprint $table) {
$table->id();
$table->string('key')->unique();
$table->longText('value')->nullable();
$table->timestamps();
});
When adding data, I get the following records in the database:
id: 2
key: country
value: ["Italy","Germany"]
Countries are now added to me through tags, like this:
$form->tags('value', __('Value'))->help('Use key `<b>Enter</b>` to add a new value')
->separators([';']);
The model has a function that receives and shares all values ​​with the key country:
public static function getCountries()
{
$country= self::where('key', 'country')->first();
return explode(',', $country['value']);
}
And then on the blade.php page I display these countries:
#foreach(App\Models\General::getCountries() as $country)
<span>{{ $country }}</span>
#endforeach
The task is to attach a picture with a flag to each country.
I create a new model with migration to add a picture:
Schema::create('general_flags', function (Blueprint $table) {
$table->id();
$table->string('flag_image', 128);
$table->timestamps();
});
My controllers are all done correctly and pictures are added and saved.
The main question is how do I create a relation of each value from the array with the desired flag, any ideas how to do this?
The problem is that I can’t change adding countries, so I have to work with what I have.
You can make new col in general_flags named country_code then when save countries_array in general save it as associative array ['country_code' => 'country name'].
Or save image as associative array ['country_code' => 'Image'].
But, In my opinion you should make table for countries and every country has a flag.

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)

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.

selecting data with laravel eloquent relationship

I trying to understand laravel eloquent relationship so i created two tables. structure of tables defined in laravel migration is
for mostpopular table
Schema::create('mostpopulars',function(Blueprint $table){
$table->increments('id');
$table->integer('song_id')->unsigned();
$table->index('song_id');
$table->foreign('song_id')->references('id')->on('song_details')->delete('cascade');
});
for song_detail table
Schema::create('song_details', function (Blueprint $table) {
$table->increments('id');
$table->string('song_title');
$table->string('song_name');
$table->string('song_album');
$table->string('song_singer');
$table->string('song_musicby');
$table->string('song_location');
$table->string('song_album_image');
$table->string('song_language');
$table->string('song_lyrics',3000);
$table->timestamps();
});
then in Mostpopular model defined function for relating two table
public function song_detail()
{
return $this->hasOne('App\Song_detail','id');
}
and in controller index function i want to do something like this
$songs = Song_detail::select()->latest()->get();
$malayalamSongs = Mostpopular::select('song_id')->groupBy('song_id')->havingRaw('COUNT(*) > 2')->get();
$mp = $malayalamSongs;
dd($mp->song_detail);
but getting error
Undefined property: Illuminate\Database\Eloquent\Collection::$Song_detail
please help me to find the error and what i am trying to do is get the details of songs from song_details table where song_id occurred more than two times song_id is in mostpopular tables.
the eloquent get() will return an array, you cannot call relation method on the array.
you can use first() to replace the get() or
change
$mp = $malayalamSongs;
dd($mp->song_detail);
to
$mp = $malayalamSongs;
foreach($mp as $v)
{
dd($v->song_detail);
}

Categories