hey guys i have a confusing question
I have 3 tables
basket_lists (carts)
basket_items (carts_item)
products
with this migrate
'basket_lists':
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->boolean('active');
$table->timestamps();
basket_items:
$table->bigIncrements('id');
$table->unsignedBigInteger('product_Id');
$table->unsignedBigInteger('basket_list_id');
$table->timestamps();
products:
$table->bigIncrements('id');
$table->string('title');
$table->text('description');
$table->bigInteger('amount');
$table->timestamps();
I have some products in my table , when i search (query) {
BasketList::where('active', '=', 1)->with('basketItems.products')->get();
it only gives me the first basketlist products (where id = 1)
if i insert new basketlist and set the first basketlist to (active = 0) and second one to (active = 1) it will not show any products.
Here is my model classes :
class BasketList extends Model
{
public function basketItems()
{
return $this->hasMany(BasketItem::class ,'basket_list_id' );
}
}
class BasketItem extends Model
{
public function products()
{
return $this->hasMany(Product::class,'id' );
}
public function basketList()
{
return $this->belongsTo(BasketList::class);
}
}
public function basketItem()
{
return $this->belongsTo(BasketItem::class ,'product_id');
}
You must change your relationship to belongsTo()
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class BasketItem extends Model
{
//
protected $table = 'basket_items';
public function product()
{
return $this->belongsTo(Product::class, 'product_id','id' ); // Watch out for the case sensitive. how did you wright product_id in your migration. (product_id or product_Id)
}
You break Laravel default naming conventions for foreign keys 'product_Id'
It must be 'product_id'
Eloquent determines the foreign key of the relationship based on the
model name. In this case, the BasketItem model is automatically
assumed to have a 'product_id' foreign key. If you wish to override this
convention, you may pass a second argument to the hasMany method:
Fix
App\BasketItem.php
public function product()
{
return $this->belongsTo(Product::class, 'product_Id','id' );
}
Check Documentation
Usage
BasketList::where('active', '=', 1)->with('basketItems', 'basketItems.product')->get();
Related
i am trying to retrieve questions based on the category witch they belong with this function inside my questions controller:
public function getByCategoryName($categoryName) {
$category = Category::where('name', $categoryName)->first();
return response($category->questions);
}
the problem is that, even if $category its being correctly set, $questions is null and the browsers returns an empty response to my request
the tables are created like this:
Questions table:
Schema::create('questions', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('title')->nullable(false);
$table->string('content')->nullable(false);
$table->integer('points')->default(0);
$table->foreignId('user_id')
->constrained('users')
->onDelete('cascade');
$table->string('category_name');
$table->foreign('category_name')
->references('name')->on('categories')
->onDelete('cascade')
->onUpdate(null);
});
categorie table:
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('name')->nullable(false);
$table->unique('name');
});
I have the relatives relationship functions HasMany and BelongsTo seated inside the the models.
Question model:
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
Category model:
public function question() : HasMany {
return $this->hasMany(Question::class);
}
What am I doing wrong?
As others have pointed out. It's better to use the primary ID key for efficient mapping. However, for education purposes it is possible and I will explain. Eloquent determines the foreign key name by examining the name of the relationship method and suffixing the method name with _id.
So, in this case, Eloquent assumes that the Question model has a category_id column.
However, since the foreign key on the Question model is not category_id, we must pass a custom key name as the second argument to the belongsTo method:
public function category()
{
return $this->belongsTo(Category::class, 'foreign_key'); // If we do not pass this eloquent thinks the foreign key is 'category_id'
}
// We need to pass our custom foreign key
public function category()
{
return $this->belongsTo(Category::class, 'category_name');
}
Eloquent assumes the parent model Category will be associated using its primary id. Since this is not our case we need to associate the parent model key to the 'name' column.
So we need to pass a third argument to the belongsTo method specifying the parent tables custom key:
public function category()
{
return $this->belongsTo(Category::class, 'category_name', 'name');
}
Your complete solution should look something like this.
// Question model
public function category()
{
return $this->belongsTo(Category::class, 'category_name', 'name');
}
// Category model
public function questions()
{
return $this->hasMany(Question::class, 'category_name', 'name');
}
Change this :
public function question() : HasMany {
return $this->hasMany(Question::class);
}
To this :
public function questions() : HasMany {
return $this->hasMany(Question::class, 'category_name');
}
I have a model named Point having the following fields:
name
description
lat
lng
The fields "name" and "description" can be in several languages, so I created two tables for points and their details.
Schema::create('points', function (Blueprint $table) {
$table->id();
$table->float('lat');
$table->float('lng');
$table->timestamps();
Schema::create('point_details', function (Blueprint $table) {
$table->id();
$table->integer('point_id');
$table->string('name');
$table->string('description');
$table->string('lang');
There is an index unique on point_id/language.
In the model files I have One To Many relationships
class Point extends Model
{
public function details()
{
return $this->hasMany(PointDetail::class);
}
}
class PointDetail extends Model
{
public function point()
{
return $this->belongsTo(Point::class);
}
}
Now I want to get the Point with details based on User language. I do so in the PointController:
class PointController extends Controller
{
public function show($id)
{
$point = Point::with(['details' => function($query) {
$query->where(
'lang', Auth::user()->lang ?
Auth::user()->lang :
'it');
}])->find($id);
return view('points.show',compact(['point']));
}
}
Can I avoid the "with" clause in the Controller? Maybe making the right query in the Point model file. I'm looking for a way to return the point with one detail associated with it, based on language of the Auth::user().
Thanks for any suggestion.
you can add query to relationship method in point class to details method
like that :
class Point extends Model
{
public function details()
{
return $this->hasMany(PointDetail::class)->where('lang', Auth::user()->lang);
}
}
All polymorh examples I found are one to many if I get it correct. (Tag to Post / Video e.g)
In my Case the parent class is multiple and the child class also. Therefore i set up the pivot table
Tables
Person
id
Venture
id
Capital
id
Estate
id
PIVOT TABLE
Revenues
emitter_id //ID of the revenue emitting class (Venture, Capital, Estate)
emitter_type // Class of the Emitter (App\Models\Venture App\Models\Estate)
receiver_id // Id of Receiver (Venture or Person)
receiver_type // type of Receiver (App\Models\Venture or App\Models\Person)
revenue
In the Estate Model i try this
public function revenuePersons()
{
// searched type, own type/id ,tabel own ID to search id
return $this->morphToMany(Person::class, 'emitter' ,'revenues' ,'emitter_id','receiver_id')
->withPivot('revenue');
}
One the Person Model
public function estaterevenues(){
// searched type, own type/id ,tabel own ID to search id
return $this->morphToMany(Estate::class, 'receiver' ,'revenues' ,'receiver_id','emitter_id')
->withPivot('revenue');
}
The Code works but in some cases i get additional relations back. So it seams the searched _type is not correctly considered.
So i started to implement a own database query function that gives me the Revenue Entry back. It works correctly.
Revenue Model
public function getRevenue($ownside, $emitter_id = Null, $emitter_type,$receiver_id=Null, $receiver_type ){
$revenue = DB::table('revenues')
->where('emitter_id', $emitter_id)
.....()->get()}
But I am not able to do something like
$persons->getRevenues
because a Relationship is expected as return value
So if anyone has an idea how to do that correctly I would be very happy. Or some other best practices for this many to many approach.
The second Question is how to get all revenue receiver at once.
Instead of
$estate->revenuepersons
$estate->revenueventures
Have something like
$estate->revenues //that list both, Ventures and Persons
And here a Class Diagram
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* Get all of the tags for the post.
*/
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
namespace App;
use Illuminate\Database\Eloquent\Model;
class Video extends Model
{
/**
* Get all of the tags for the post.
*/
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tag extends Model
{
/**
* Get all of the posts that are assigned this tag.
*/
public function posts()
{
return $this->morphedByMany(Post::class, 'taggable');
}
/**
* Get all of the videos that are assigned this tag.
*/
public function videos()
{
return $this->morphedByMany(Video::class, 'taggable');
}
}
$post = Post::find(1);
dd($post->tags);
$video = Video::find(1);
dd($video->tags);
$tag = Tag::find(1);
dd($tag->posts);
$tag = Tag::find(1);
dd($tag->videos);
posts table migration:
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string("name");
$table->timestamps();
});
videos table migration:
Schema::create('videos', function (Blueprint $table) {
$table->increments('id');
$table->string("name");
$table->timestamps();
});
tags table migration:
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string("name");
$table->timestamps();
});
taggables table migration:
Schema::create('taggables', function (Blueprint $table) {
$table->integer("tag_id");
$table->integer("taggable_id");
$table->string("taggable_type");
});
Below are all of the models, migrations and controller.
Donation Model
class Donation extends Model
{
protected $guarded =[];
public function users(){
return $this->hasMany(User::class);
}
public function items(){
return $this->belongsTo(DonationItems::class);
}
}
Donation Items Model:
class DonationItems extends Model
{
protected $guarded=[];
public function donation(){
return $this->hasMany(Donaition::class);
}
}
Donation Items Migration:
public function up()
{
Schema::create('donation_items', function (Blueprint $table) {
$table->id();
$table->string('category');
$table->timestamps();
});
}
Donation Migration:
public function up()
{
Schema::create('donations', function (Blueprint $table) {
$table->id();
$table->string('item');
$table->unsignedInteger('user_id');
$table->unsignedInteger('donation_item_id');
$table->timestamps();
});
}
In my controller I want to access the items as follows:
$don = Donation::all();
$don->items;
But I'm unable to achieve this.
Its not working because laravel follows one rule for relationships:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
So you can try by supplying local and foreign id
So it would look something like this
Donation Model
class Donation extends Model
{
protected $guarded =[];
public function users(){
return $this->hasMany(User::class);
}
public function items(){
return $this->belongsTo(DonationItems::class, 'donation_item_id', 'id');
}
}
Donation Items Model:
class DonationItems extends Model
{
protected $guarded=[];
public function donation(){
return $this->hasMany(DonationItems::class, 'id', 'donation_item_id');
}
}
I am writing from my head you might need to swap local and foreign ID's
I have a table which is named cars with 2 fields id, matriculation.
Then, I have another table which is named series with 2 fields id, name.
I have created my fk_serie on my table cars.
public function up()
{
Schema::create('cars', function (Blueprint $table) {
$table->increments('id');
$table->string('matriculation', 25);
$table->integer('fk_serie')->unsigned();
$table->foreign('fk_serie')->references('id_serie')->on('serie');
$table->timestamps();
});
}
Here is my information about the table series.
public function up()
{
Schema::create('series', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 30);
$table->timestamps();
});
}
In my model, I only have a function on the model Car.
public function serie(){
return $this->belongsTo('App\Serie', 'fk_serie');
}
I don't have nothing in my model Serie
class Serie extends Model
{
//
}
Is it normal that the model Serie is empty?
Because, my join works.
What do you think ?
Is there an error?
As Dparoli mentioned in comments if you don't need the below query then your above structure of relationship is normal
Serie::with('cars')->find($id)
But if you want to setup relationship in Serie Model you can do something like below:
class Serie extends Model
{
public function cars() {
return $this->hasMany('App\Car', 'fk_serie'); // your relationship
}
}
And after that you can do:
$series = Serie::with('cars')->find($id); //eager loading cars
$cars = $series->first()->cars;