Laravel eloquent relations not working completely - laravel

I've a payment gateway, I want to access the product items after returning, so I created several tables Payments, Orders, OrderItems and configured the relationships between them.
Each Payment is for one Order and each Order contains several OrderItem and each OrderItem contains one product. Now I want to access each Product through an object of the Payment Model, which returns the following error.
Illuminate\Database\QueryException SQLSTATE[42S22]: Column not found:
1054 Unknown column 'orders.order_item_id' in 'field list' (SQL:
select products.*, orders.order_item_id as laravel_through_key
from products inner join orders on orders.id =
products.order_id where orders.order_item_id = 68 limit 1)
$product_order_item = $payment->order->order_items->map(function ($order_item) {
dd($order_item->product);
});
Payment Model:
protected $table = "payments";
protected $guarded = [];
public function order() {
return $this->belongsTo(Order::class);
}
Order Model:
protected $table = "orders";
protected $guarded = [];
public function payment() {
return $this->hasOne(Payment::class);
}
public function order_items() {
return $this->hasMany(OrderItem::class);
}
OrderItem Model:
protected $table = "order_items";
protected $guarded = [];
public function order() {
return $this->belongsTo(Order::class);
}
public function product() {
return $this->hasOneThrough(Product::class, Order::class);
}
Product Model:
protected $table = "products";
protected $guarded = [];
public function order_items() {
return $this->belongsToMany(OrderItem::class);
}
That is migrations:
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE');
$table->unsignedInteger('amount');
$table->unsignedInteger('res_code');
$table->enum('status', ['paid', 'unpaid']);
$table->timestamps();
});
=====================================================
Schema::create('order_items', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('order_id');
$table->foreign('order_id')->references('id')->on('orders')->onDelete('CASCADE');
$table->unsignedBigInteger('product_id');
$table->foreign('product_id')->references('id')->on('products')->onDelete('CASCADE');
$table->unsignedInteger('price');
$table->timestamps();
});
===========================================================
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('order_id');
$table->foreign('order_id')->references('id')->on('orders')->onDelete('CASCADE');
$table->enum('status', ['paid', 'unpaid']);
$table->unsignedInteger('ref_id');
$table->unsignedInteger('res_id');
$table->enum('gateway', ['idpay', 'zarinpal']);
$table->timestamps();
});
what is the problem?
Thanks in advance...

You should use belongsTo for the product relationship of OrderItem Model
OrderItem Model:
public function product() {
return $this->belongsTo(Product::class);
}
https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-inverse
And hasMany for the order_items relationship of Product Model
Product Model:
public function order_items() {
return $this->hasMany(OrderItem::class);
}
https://laravel.com/docs/8.x/eloquent-relationships#one-to-many

Related

laravel 8 update child table data from parent table

I'm working on a Laravel 8 project.
I have a payments table, it's the migration:
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->enum('gateway',['idpay','zarinpal']);
$table->unsignedInteger('res_id')->nullable();
$table->char('ref_code',128)->nullable();
$table->enum('status',['paid','unpaid']);
$table->unsignedBigInteger('order_id');
$table->foreign('order_id')->references('id')->on('orders')->onDelete('cascade');
$table->timestamps();
});
as you can see this table has a foreign key that references on orders table, and it is orders migration:
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('amount');
$table->char('ref_code',128)->nullable();
$table->enum('status',['unpaid','paid',]);
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
I created a one to one relationship in Order model:
class Order extends Model
{
use HasFactory;
protected $guarded = [];
public function payment()
{
return $this->hasOne(Payment::class);
}
}
The problem is that when I want to use order() method on Payment class it does not work.
for example:
Payment::find(10)->order()->update(['status' =>'paid']);
I get this error:
BadMethodCallException Call to undefined method
App\Models\Payment::order()
UPDATE:
Here is Payment model:
class Payment extends Model
{
use HasFactory;
protected $guarded = [];
}
Thank you for helping me.
You should use like this a method in the payment model.
public function order()
{
return $this->belongsTo(Order::class);
}
Because you still don't have any relationship in the payment model to order.
You can check here for detailed information.
https://laravel.com/docs/8.x/eloquent-relationships#one-to-one-defining-the-inverse-of-the-relationship
You have to describe the order relation ship in the Payment model
class Payment extends Model
{
use HasFactory;
protected $guarded = [];
public function order()
{
return $this->belongsTo(Order::class);
}
}
and after that you can access the payment's order like this:
Payment::find(10)->order->update(['status' =>'paid']);

Laravel eloquent with categories

I have a question about eloquent in laravel.
DB tables
categories: id root_id name
products id name etc..
product_categories id product_id category_id
So it might be CategoryA which has a child CategoryB and CategoryB by itself has a child CategoryC.
When I click in CategoryA I want to find all products that are part of CategoryA, CategoryB, CategoryC
Category Model
public function cats()
{
return $this->hasMany(Category::class);
}
public function childrenCategories()
{
return $this->hasMany(Category::class)->with('cats');
}
Product Model
public function categories()
{
return $this->belongsToMany(Category::class);
}
Controller
//firsty I get all id of all categories, subcategories of all levels.
$categories = Category::where('category_id',$category_id)->with('childrenCategories')->get();
$all_cat_array=array();$all_prod=array();
foreach ($categories as $category)
{
foreach ($category->childrenCategories as $childCategory) {
array_push($all_cat_array, $childCategory->id);
}
array_push($all_cat_array,$category->id);
}
//then i get all id of products
foreach ($all_cat_array as $cat)
{
if(CategoryProduct::where('category_id',$cat)->exists()) {
$prod=CategoryProduct::where('category_id',$cat)->pluck('product_id');
array_push($all_prod,$prod );
}
}
But I don't want to use of all these foreach, since I want to optimise the code.
What can I do to make it simplier ???
For more information please read Laravel Docs
DATABASE
Category A database
Schema::create('category_as', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('product_id');
...
$table->timestamps();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
});
Category B database
Schema::create('category_bs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('category_a_id');
...
$table->timestamps();
$table->foreign('category_a_id')->references('id')->on('category_as')->onDelete('cascade');
});
MODEL
Products model
public function categories_a() {
return $this->hasmany(Category_a::class);
}
Category A model
public function categories_b() {
return $this->hasmany(Category_b::class);
}
public function product() {
return $this->belongsTo(Product::class);
}
Category B model
public function category_a() {
return $this->belongsTo(Category_a::class);
}
public function clients() {
return $this->hasManyThrough(Client::class, Code::class);
}
CONTROLLER
public function index() {
$products = Product::all();
$query = $products->categories_a->categories_b;
dd($query);
}
EDITED
DATABASE
Category A database
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('product_id');
...
$table->timestamps();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
});
MODEL
Products model
public function categories() {
return $this->hasmany(Category::class);
}
Category model
public function product() {
return $this->belongsTo(Product::class);
}
CONTROLLER
public function index() {
$products = Product::all();
$query = $products->categories;
dd($query);
}
I recommend you to use nested set structure in Category model.
It is well implemented in this package https://github.com/lazychaser/laravel-nestedset.
You could get products of category and all it's descendants (with unlimited nesting) with 2 queries.
If Category belongsToMany Product:
$categoryIds = Category::descendantsAndSelf($categoryId)->pluck('id');
$products = Product::whereHas('categories', function ($query) use ($categoryIds) {
$query->whereIn('categories.id', $categoryIds);
});
If Category hasMany Product
$categoryIds = Category::descendantsAndSelf($categoryId)->pluck('id');
$products = Product::whereIn('category_id', $categoryIds);

How to access the values of a foreign key of another table using laravel

I created a custom pivot model which is SectionSubject that have an id, section_id and subject_id. I want now to access the other values related to the section_id. Here is my Sectionsubject model and section_subject table:
SectionSubject.php
class SectionSubject extends Model
{
protected $table = 'section_subject';
public function students()
{
return $this->belongsToMany(Student::class, 'section_subject_student','section_subject_id'
)->withTimestamps();
}
public function assignStudents(Student $student)
{
return $this->students()->save($student);
}
}
create_section_subject.php
Schema::create('section_subject', function (Blueprint $table) {
$table->increments('id');
$table->integer('section_id')->unsigned();
$table->integer('subject_id')->unsigned();
$table->string('schedule')->unique();
$table->string('room_no');
$table->foreign('section_id')
->references('id')
->on('sections')
->onDelete('cascade');
$table->foreign('subject_id')
->references('id')
->on('subjects')
->onDelete('cascade');
});
Now I want to fetch those values and place it on my ReservationController. I tried to use one to many relationship but it seems not working.
class ReservationController extends Controller
{
public function index()
{
$sectionSubject = SectionSubject::find(1);
//code here
return view('reservation.form', compact('sectionSubject');
}
}
you can fetch relationship by doing this
$sectionSubject = SectionSubject::with('students')->find(1);
//print your variable
echo "<pre>";
print_r($sectionSubject->toArray());
echo "</pre>";
you will find the related table data

Laravel BelongsToMany Error - Base table or view not found

I hope this thread find everyone healthy.
What is wrong with the following code? I am getting an error on my many to many relationship. For the past 4 hours i am stuck with this problem. I would be very thankful if you find the bug or source of problem.
Here is my code and tables:
Schema::create('products', function(Blueprint $table)
{
$table->increments('id');
$table->integer('category');
$table->string('thumbnail');
$table->string('images');
$table->string('logo');
$table->string('main_photo');
$table->timestamps();
});
//categories table
Schema::create('product_categories', function(Blueprint $table)
{
$table->increments('id');
$table->string('category');
});
//relationship table
Schema::create('product_productcategory', function(Blueprint $table)
{
$table->increments('id');
$table->integer('product_id'); // the id of the bear
$table->integer('productcategories_id'); // the id of the picnic that this bear is at
});
products model:
class Product extends Model
{
protected $table = 'products';
public function product_category() {
return $this->belongsToMany('App\product_category', 'App\product_productcategory', 'product_id', 'productcategories_id');
}
}
And pivot model
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
return $this->belongsToMany('App\Product', 'App\product_productcategory', 'productcategories_id', 'product_id');
}
}
Thanks in advance!
Updates: The problem is solved thanks to #mimo.
But now i want to translate the categories in different languages so i created a table like this:
Schema::create('category_translations', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('product_categories')->onDelete('cascade');
$table->integer('locale_id')->unsigned();
$table->foreign('locale_id')->references('id')->on('locales')->onDelete('cascade');
$table->unique(['category_id', 'locale_id']);
});
And my product categories with new relationship to the translations
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
//return $this->belongsToMany('App\Product', 'App\product_productcategory', 'productcategories_id', 'product_id');
return $this->belongsToMany('App\Product', 'product_productcategory');
}
public function translation($lang) {
return $this->hasMany('App\Category_Translation')->where('locale_id', '=', $lang);
}
}
And in category translation:
class Category_Translation extends Model
{
protected $table = 'category_translations';
public function product_category() {
return $this->belongsTo('App\product_category');
}
}
And finally my Product:
class Product extends Model
{
protected $table = 'products';
public function translation($lang) {
return $this->hasMany('App\Product_Translation')->where('locale_id', '=', $lang);
}
public function product_category() {
//return $this->belongsToMany('App\product_category', 'App\product_productcategory', 'product_id', 'productcategories_id');
//return $this->belongsToMany('App\product_category', 'product_productcategory');
return $this->belongsToMany('App\product_category', 'product_productcategory')->translation(1);
}
}
Now when i run:
$product = App\Product::find(1)->first();
echo $product->product_category;
I get error:
Call to undefined method Illuminate\Database\Query\Builder::translation()
Your migration file is wrong:
//relationship table
Schema::create('product_productcategory', function(Blueprint $table)
{
$table->integer('product_id')->unsigned()->index(); // the id of the bear
$table->foreign('product_id')->references('id')->on('products');
$table->integer('productcategories_id')->unsigned()->index(); // the id of the picnic that this bear is at
$table->foreign('productcategories_id')->references('id')->on('product_categories');
});
This code will made the relationship on the database level.
When you have 12 min free time you can check out this tutorial about many to many relationships in laravel:
https://laracasts.com/series/laravel-5-fundamentals/episodes/21
Update:
you need to update your relationships too:
class Product extends Model
{
protected $table = 'products';
public function product_category() {
return $this->belongsToMany('App\product_category', 'product_productcategory');
}
}
and:
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
return $this->belongsToMany('App\Product', 'product_productcategory');
}
}

Laravel: Eloquent Relationship error

I have a many to many relationship between products and a product_categories tables. Now I want to create a translation table for categories.
But how do I relate them in eloquent? i am learning database relationships so forgive my ignorance.
Here is my tables:
//languages
Schema::create('locales', function(Blueprint $table)
{
$table->increments('id');
$table->string('code', 2);
$table->string('name');
});
//products
Schema::create('products', function(Blueprint $table)
{
$table->increments('id');
$table->string('thumbnail');
$table->timestamps();
});
//categories
Schema::create('product_categories', function(Blueprint $table)
{
$table->increments('id');
$table->string('category');
});
//relationship table
Schema::create('product_productcategory', function(Blueprint $table)
{
$table->integer('product_id')->unsigned()->index(); // the id of the bear
$table->foreign('product_id')->references('id')->on('products');
$table->integer('product_category_id')->unsigned()->index(); // the id of the picnic that this bear is at
$table->foreign('product_category_id')->references('id')->on('product_categories');
});
//category translations
Schema::create('category_translations', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('product_categories')->onDelete('cascade');
$table->integer('locale_id')->unsigned();
$table->foreign('locale_id')->references('id')->on('locales')->onDelete('cascade');
$table->unique(['category_id', 'locale_id']);
});
Product Model:
class Product extends Model
{
protected $table = 'products';
public function product_category() {
return $this->belongsToMany('App\product_category', 'product_productcategory')->translation(1);
}
}
Product categories:
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
return $this->belongsToMany('App\Product', 'product_productcategory');
}
}
Category Translations
class Category_Translation extends Model
{
protected $table = 'category_translations';
public function product_category() {
return $this->belongsTo('App\product_category');
}
}
But when i run:
$product = App\Product::find(1)->first();
echo $product->product_category;
I get error:
Call to undefined method Illuminate\Database\Query\Builder::translation()
You should not call translation in the Product model category relation (because you still interacting with the query builder), instead you should access the translation as a property on the category object:
echo $product->product_category->first()->getTranslatedIn(1)->name;
So you could refactor your code like this:
Product Model:
class Product extends Model
{
protected $table = 'products';
public function product_category() {
return $this->belongsToMany('App\product_category', 'product_productcategory');
}
}
Product categories:
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
return $this->belongsToMany('App\Product', 'product_productcategory');
}
public function translations() {
return $this->hasMany('App\Category_Translation', 'category_translations');
}
// relation filtered by language (cannot be accessed as a property unless you define the parameter as optional)
public function translatedIn($language) {
return $this->hasOne('App\Category_Translation', 'category_id')->where('locale_id', $language);
}
// access translated object
public function getTranslatedIn($language) {
return $this->translatedIn($language)->getResults();
}
}

Resources