Laravel 5 Nested Relationships - php

I have the following table I can't use Order hasMany Product b/c Product don't have a foreign order_id. I want to access everything through Invoice, is that possible?
I try to use Has Many Through but that is a A->B->C Relationship, I think want I setup need A->B<-C Relationship.
users table
| id |
invoice table
| id | user_id |
order table
| id | invoice_id | product_id |
product table
| id |
I wish to access all data through invoice table
INVOICE MODEL
class invoice extends Model {
public function user() {
return $this->belongsTo('App\User');
}
public function order() {
return $this->belongsTo('App\Order');
}
}
ORDER MODEL
class Order extends Model
{
public function invoice()
{
return $this->belongsTo('App\Invoice');
}
}
PRODUCT MODEL
class product extends Model
{
protected $table = 'products';
public function order()
{
return $this->belongsTo('App\Order');
}
}

This is how your models should look like according to the schema.
INVOICE MODEL
class invoice extends Model {
public function user() {
return $this->belongsTo('App\User');
}
public function order() {
return $this->hasMany('App\Order');
}
public function products() {
return $this->belongsToMany('App\Product', 'order', 'invoice_id', 'product_id');
}
}
ORDER MODEL
class Order extends Model
{
public function invoice()
{
return $this->belongsTo('App\Invoice');
}
public function product()
{
return $this->belongsTo('App\Product');
}
}
PRODUCT MODEL
class product extends Model
{
protected $table = 'products';
public function orders()
{
public function products() {
return $this->belongsToMany('App\Invoice', 'order', 'product_id', 'invoice_id');
}
}
If this is not what you want, you will probably need to change the schema.

Related

What if you make Model for pivot table in Many To Many relationship

I have made a separate Model and defined the required relationships between all my Many To Many Models:
class AttributeProduct extends Model
{
use HasFactory;
protected $table = 'attribute_product';
protected $guarded = [];
public function attribute()
{
return $this->belongsTo(Attribute::class, 'attribute_id', 'id');
}
public function product()
{
return $this->belongsTo(Product::class, 'product_id', 'id');
}
public function value()
{
return $this->belongsTo(Value::class, 'value_id', 'id');
}
}
For example, this Model is connected to attribute_products table.
And then I added this method to Product model:
public function attributeproducts()
{
return $this->hasMany(AttributeProduct::class, 'product_id', 'id');
}
So I wonder if it is good to make a separate model and add my own methods to it or I should use Laravel pre-defined way?

Php Laravel get relation inside relation

I have a problem, I am trying to retrieve orders with products from my database. The idea is that you have an order with products in it and a product can have options with different options. For example a big mac menu has different options, such as size with three different options. This is what I have now:
OrderModel:
class Order extends Model
{
use HasFactory;
protected $table = 'orders';
public function user()
{
return $this->belongsTo(User::class);
}
public function table()
{
return $this->belongsTo(Table::class);
}
public function branch()
{
return $this->belongsTo(Branch::class);
}
public function products()
{
return $this->belongsToMany(Product::class)->withPivot('quantity');
}
}
OrderProduct:
class OrderProduct extends Pivot
{
use HasFactory;
public $incrementing = true;
protected $table = 'order_product';
public function options()
{
return $this->hasMany(OrderProductOptions::class);
}
public function products()
{
return $this->hasMany(Product::class);
}
}
OrderProductOptions:
class OrderProductOptions extends Model
{
use HasFactory;
public $incrementing = true;
protected $table = 'order_product_options';
public function options()
{
return $this->belongsTo(OrderProductsOptionsOptions::class);
}
}
OrderProductsOptionsOptions:
class OrderProductsOptionsOptions extends Model
{
use HasFactory;
protected $table = 'order_products_options_options';
public function Option()
{
return $this->belongsTo(OrderProductOptions::class);
}
}
When I want to pick up an order with products and selected options like this:
$newOrder = Order::with('products.options')->findOrFail($order->id);
I get all the options that the product has, how do I get only the selected ones that belong to the order?
see laravel document , you must define foringPivotKey and relatedPivot key like this:
return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id');

Laravel 5 Three-way One-to-Many Eloquent Relationship

I have database like this
opportunities
Id
contact_id
contacts
Id
User_id
users
id
User model :
class User extends Authenticatable
{
public function Contact()
{
return $this->hasMany('Customer\model\Contact');
}
}
Contact model:
class Contact extends Model
{
public function Opportunity()
{
return $this->hasMany('Sale\Model\Opportunity');
}
public function User()
{
return $this->belongsTo('App\User');
}
}
Opportunity model
class Opportunity extends Model
{
public function Contact()
{
return $this->belongsTo('Customer\Model\Contact');
}
public function User()
{
return $this->hasManyThrough('App\User','Customer\Model\Contact','user_id','id');
}
}
When on controller
$Opportunity = Opportunity::with('User')->paginate(10);
print_r($Opportunity->User);
Show me wrong data.

Wrong table when updating "Belongs To" relationships in Laravel

Here I'm trying to save article's category with given id which exists in categories table,I have set the relationships but when trying to save, Laravel tries to insert new row in articles table not in the pivot table .
Here is the error:
*Unknown column 'category_id' in 'field list' (SQL: update `articles` set `category_id` = 1, `updated_at` = 2015-11-16 13:15:32 where `id` = 53)*
And these are relations and pivot table
class Article extends Model implements SluggableInterface
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
class Category extends Model implements SluggableInterface
{
public function articles()
{
return $this->hasMany('App\Article','article_category');
}
}
//pivot table
Schema::create('article_category',function(Blueprint $table){
$table->integer('article_id')->unsigned()->index();
$table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
And here is my save function
public function store(ArticleRequest $request)
{
$article=Auth::user()->articles()->create($request ->all());
$category =Category::find($request ->input('category'));
$article->category()->associate($category)->save();
}
Your relationship type is many to many relotionship, not one to many.
Your models should be like this:
class Article extends Model implements SluggableInterface
{
public function categories()
{
return $this->belongsToMany('App\Category', 'article_category');
}
}
class Category extends Model implements SluggableInterface
{
public function articles()
{
return $this->belongsToMany('App\Article', 'article_category');
}
}
If you want one to many relationship not need 'article_category' table your migrations should like this:
Schema::create('articles',function(Blueprint $table){
$table->integer('id')->increments();
$table->string('title');
$table->text('content');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
and models:
class Article extends Model implements SluggableInterface
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
class Category extends Model implements SluggableInterface
{
public function articles()
{
return $this->hasMany('App\Article');
}
}
Not sure but it looks to me that the relations should be:
articlass Article extends Model implements SluggableInterface
{
public function category()
{
return $this->belongsTo('App\ArticleCategory', 'category_id');
}
}
and
class Category extends Model implements SluggableInterface
{
public function articles()
{
return $this->hasMany('App\ArticleCategory','article_id');
}
}
so it references to the pivot table

Laravel 5 hasManyThrough

I have 3 tables: company <-> users <-> invoice.
A company hasMany users.
A user belongsTo a company and, and a user hasMany invoices.
An invoice belongsTo a user.
Now I have an invoice with information about user (customer), and I want to get the user its information about the company so I made an:
An invoice hasManyThrough users, company (so gets the company through user)
Now it doesn't work as it is needed.
Models:
class Company extends Eloquent {
protected $table = 'companies';
public function users()
{
return $this->hasMany('App\User', 'id');
}
public function invoices()
{
return $this->hasManyThrough('App\Company', 'App\User');
}
}
class User extends Model {
protected $table = 'users';
public function usertype()
{
return $this->belongsTo('App\UserType','usertype_id','id');
}
public function company()
{
return $this->belongsTo('App\Company','company_id','id');
}
public function invoice()
{
return $this->hasMany('App\Invoice');
}
}
class Invoice extends Model {
protected $table = 'invoices';
public function users() {
return $this->belongsTo('App\User', 'id');
}
}
Invoice Controller:
class InvoiceController extends Controller {
private $invoice;
public function __construct(Invoice $invoice)
{
$this->invoice = $invoice;
}
public function index(Invoice $invoice)
{
$invoices = $invoice->with('users', 'company')->get();
dd($invoices);
return view('invoice.index', compact('invoices'));
}
public function create()
{
//
}
public function store()
{
}
public function show($id)
{
$invoice = Invoice::with('users')->find($id);
return view('invoice.show', compact('invoice'));
}
public function edit($id)
{
//
}
public function update($id)
{
//
}
public function destroy($id)
{
//
}
}
The dd($invoices) will give a BadMethodCallException
Call to undefined method Illuminate\Database\Query\Builder::company()
Any further needed information can be provided!
Let's say we have table A and B and C
where table A has many of B (OneToMany) and B has many of C (OneToMany)
inorder to access the table C from table A you can use the Laravel shortcut (HasManyThrough) on the Table A and the problem is solved
BUT If you have table A and B and C
where table A has many of B (OneToMany) and B has many of C (ManyToMany)
you cannot use the laravel's (HasManyThrough) shortcut to access the table C from table A, {because of the pivot table in the middle between B and C} what you can do in this case is very simple:
In this example table A will be [courses], table B will be [chapters], and table C will be [videos]
where every course has may chapters, while a chapter can belong to only one course. in the other hand every chapter has many videos while a video can belong to many chapters.
<?php namespace Moubarmij\Models;
use Eloquent;
class Video extends Eloquent{
protected $table = 'videos';
/*************************************************************
* Query Scopes
**************************************************************/
public function scopePublished($query)
{
return $query->where('published', '=', '1');
}
public function scopeOrdered($query)
{
return $query->orderBy('order_number', 'ASC');
}
/*************************************************************
* Relations
**************************************************************/
public function chapters()
{
return $this->belongsToMany('Moubarmij\Models\Chapter', 'chapters_videos');
}
}
<?php namespace Moubarmij\Models;
use Eloquent;
class Chapter extends Eloquent{
protected $table = 'chapters';
/*************************************************************
* Query Scopes
**************************************************************/
public function scopePublished($query)
{
return $query->where('published', '=', '1');
}
public function scopeOrdered($query)
{
return $query->orderBy('order_number', 'ASC');
}
public function scopeWithVideos($query)
{
return $query->with(['videos' => function($q)
{
$q->ordered();
}]);
}
/*************************************************************
* Relations
**************************************************************/
public function course()
{
return $this->belongsTo('Course');
}
public function videos()
{
return $this->belongsToMany('Moubarmij\Models\Video', 'chapters_videos');
}
}
<?php namespace Moubarmij\Models;
use Eloquent;
class Course extends Eloquent{
protected $table = 'courses';
/*************************************************************
* Query Scopes
**************************************************************/
public function scopeVisible($query)
{
return $query->where('visible', '=', '1');
}
public function scopeOrdered($query)
{
return $query->orderBy('order_number', 'ASC');
}
public function scopeWithChapters($query)
{
return $query->with(['chapters' => function($q)
{
$q->ordered();
}]);
}
public function scopeWithChaptersAndVideos($query)
{
return $query->with(['chapters' => function($q)
{
$q->ordered()->withVideos();
}]);
}
/*************************************************************
* Relations
**************************************************************/
public function chapters()
{
return $this->hasMany('Moubarmij\Models\Chapter');
}
}
You can also do this in the Course class, so when you use ->with('chapters'), it automatically loads the videos too:
public function chapters()
{
return $this->hasMany('Moubarmij\Models\Chapter')->with('videos');
}

Categories