Laravel Eloquent many to many relationship with translation - laravel

I have a problem with a many to many relationship and the translations of the terms.
I have 4 tables:
products
- id, price, whatever
products_lang
- id, product_id, lang, product_name
accessori
- id, active
accessori_lang
- id, accessori_id, lang, accessori_name
I'm trying to assign accessories to products with an intermediate table named:
accessori_products
this is the model for Product:
class Product extends Model {
protected $table = 'products';
public function productsLang () {
return $this->hasMany('App\ProductLng', 'products_id')->where('lang','=',App::getLocale());
}
public function productsLangAll() {
return $this->hasMany('App\ProductLng', 'products_id');
}
public function accessori() {
return $this->belongsToMany('App\Accessori', 'accessori_products');
}
}
this is the model for productLng:
class ProductLng extends Model {
protected $table = 'products_lng';
public function products() {
return $this->belongsTo('App\Product', 'products_id', 'id');
}
}
Then I have the model for Accessori:
class Accessori extends Model {
protected $table = 'accessori';
public function accessoriLang() {
return $this->hasMany('App\AccessoriLng')->where('lang','=',App::getLocale());
}
public function accessoriLangAll() {
return $this->hasMany('App\AccessoriLng');
}
public function accessoriProducts() {
return $this->belongsToMany('App\Products', 'accessori_products', 'accessori_id', 'products_id');
}
}
And the model for AccessoriLng:
class accessoriLng extends Model {
protected $table = 'accessori_lng';
public function accessori() {
return $this->belongsTo('App\Accessori', 'accessori_id', 'id');
}
}
the last model is for the relationship between the two tables above:
class ProductAccessori extends Model {
protected $table = 'accessori_products';
public function accessoriProducts() {
return $this->belongsTo('App\Product', 'accessori_id', 'products_id');
}
}
I'm trying to get the accessories of each product and to get also the translation but I'm having a lot of problem with this.
It's my first time with a many to many relation with translations too.
Can anyone put me on the right direction?

controller
$products = Product::has('accessori')->with([
'productsLang ',
'accessori' => function ($accessori){
$accessori->with([
'accessoriLang'
]);
}
])->get();
return $products;
you'll get products with accessori that has accessoriLang.

Related

Blank object in Eloquent belongsTo()

I'm trying to display which one attribute (code) of Item. ServiceItem has Item as a foreign key. But I can't get the Item at all.
This one gives a blank object in blade template:
#foreach ($service->serviceItems as $serviceItem )
{{ json_encode($serviceItem->item()) }}
#endforeach
Here's my model declaration:
//ServiceItem model
class ServiceItem extends Model
{
use HasFactory;
public $fillable = ['service_id', 'item_id', 'values'];
public function service()
{
return $this->belongsTo(Service::class, 'foreign_key');
}
// this doesn't work
public function item()
{
return $this->belongsTo(Item::class, 'foreign_key');
}
}
// Service model
class Service extends Model
{
use HasFactory;
public $fillable = ['user_id', 'site_id', 'title', 'status', 'remarks', 'report', 'date'];
public function user()
{
return $this->belongsTo('\App\Models\User');
}
public function site()
{
return $this->belongsTo('\App\Models\Site');
}
public function serviceItems() {
return $this->hasMany('\App\Models\ServiceItem');
}
}
This is my controller:
public function index()
{
$services = Service::latest()->paginate(5);
return view('services.index', compact('services'))
->with('i', (request()->input('page', 1) - 1) * 5);
}
Please help me to display the code attribute in Item from Service!!! Thanks a lot!
I suppose you read the Laravel doc of model relationship definition. They referenced to put foreign key as the second parameter, not the foreign_key as word but your actual foreign key that reference the parent table. you have to change the model code.
class ServiceItem extends Model
{
use HasFactory;
public $fillable = ['service_id', 'item_id', 'values'];
public function service()
{
return $this->belongsTo(Service::class, 'service_id');
}
public function item()
{
return $this->belongsTo(Item::class, 'item_id');
}
}
and then $serviceItem->item should work as expected.

Laravel eloquent is very slow when joining two models

There is a model Invoice which equals to a purchase basket and model InvoiceItem which stores items inside a specific invoice. The model invoice has status field, if its value is 2999 and someone has verified it, it is successful. I need to get invoice items which are sold. Here is codes:
class Invoice extends Model
{
protected $fillable = [];
protected $table = 'payment_invoices';
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function scopeSuccessful($query)
{
return $query->where('status', 2999)->where('verified_at', '<>', null);
}
}
and
class InvoiceItem extends Model
{
protected $fillable = [];
protected $table = 'payment_invoice_items';
public function invoice()
{
return $this->belongsTo(Invoice::class, 'invoice_id');
}
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function vendor()
{
return $this->belongsTo(Vendor::class, 'vendor_id');
}
public function scopeNotDeleted($query)
{
return $query->where('deleted_at', null);
}
public function scopeSold($query)
{
return $query->notDeleted()->whereHas('invoice', function ($q) {
$q->successful();
});
}
}
The following statement
InvoiceItem::sold()->take(10)->get()
returns 10 sold items but it is very slow. it takes about 4 seconds to retrieve the information while the query
select *
from laravel.payment_invoice_items pii
join laravel.payment_invoices pi
on pi.id = pii.invoice_id
and pii.deleted_at isnull
and pi.status=2999
and pi.verified_at notnull
limit 10
takes about 800 milliseconds. Eloquent is very inefficient. Is there any solution to use the eloquent and get the same efficiency here?

Laravel eloquent multiple levels of relations

Alright so I am basically trying to retrieve all animal_registry codes based on a user ID.
Idea is that
1 user has many jobs.
Jobs are consisted of many "Jobs data".
Jobs data has many "Animal registry" entries.
These are my relations
Image relations link (click)
And these are my relations in Laravel
class User
{
public function jobs()
{
return $this->hasMany('App\Models\RegistryJobs', 'employee', 'id');
}
}
class RegistryJobs extends Model
{
protected $table = "registry_jobs";
protected function jobsData()
{
$this->hasManyThrough('App\Models\AnimalRegistry', 'App\Models\RegistryJobsData', 'id', 'animal_registry_id');
}
}
class RegistryJobsData extends Model
{
protected $table = "registry_jobs_data";
public function jobs()
{
$this->belongsTo('App\Models\RegistryJobs', 'id', 'registry_jobs_id');
}
public function animals()
{
$this->hasMany('App\AnimalRegistry', 'id', 'animal_registry_id');
}
}
class AnimalRegistry extends Model
{
protected $table = "animal_registry";
}
And now I am trying to query it from a controller in a way
$data = User::whereHas('jobs', function ($query) {
$query->where('id', 1);
})->get();
But I am unable to access the properties from the animal_registry.
Can you try like this :
public function animals(){
return $this->hasManyThrough('App\Registry_Jobs_data','App\Registry_Jobs', 'employee',
'registry_jobs_id', 'id' ,'id')->join('//Do the joining')->select();
}
Check the hasManyThrough i am not sure..

How to get data from table related through pivot table?

I have 4 tables: countries, activities, country_activities and packages.
countries and activities are related through pivot table country_activity, and packages is related to country_activity.
Now, How do I eager load all packages related to each activity in a country?
class Country extends Model
{
public function activities() {
return $this->belongsToMany('App\Models\Activity','country_activities')->using('App\Models\CountryActivity')->as('country_activities');
}
}
class Activity extends Model
{
public function countries() {
return $this->belongsToMany('App\Models\Country','country_activities')->using('App\Models\CountryActivity')->as('country_activities');
}
}
class Package extends Model
{
public function country_activities() {
return $this->belongsToMany('App\Models\CountryActivity');
}
}
class CountryActivity extends Pivot
{
protected $table = 'country_activities';
public function packages() {
return $this->hasMany('App\Models\Package');
}
}
So, this worked for me.
class Country extends Model
{
public function activities() {
return $this->belongsToMany('App\Models\Activity','country_activities')->using('App\Models\CountryActivity')->withPivot(['id'])->as('country_activities');
}
Now, In my controller, I do this
$country = Country::with(['activities'=> function($q) {$q->where('name','Trekking');}])->where('name','Nepal')->first(['id','name']);
$country->activities->map(function ($i){
$i->country_activities->load('packages');
return $i;
});
I did something similar in a project i worked on. I'm not sure it will work but it's worth the shot:
$country = Country::find(1);
$country->activities = $contry->activities()->get()->each(function ($i, $k){
$i->packages = $i->pivot->packages;
//$i->makeHidden('pivot'); -> This is useful if you want to hide the pivot table
});
var_dump($country);

Laravel Eloquent hasMany and BelongsToMany not returning using with

I am trying to do a single query to get back an order and the card to charge, but getting an error.
Card model:
class Card extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function user()
{
return $this->belongsTo('User');
}
public function orders()
{
return $this->hasMany('Order');
}
}
Order model:
class Order extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function user()
{
return $this->belongsTo('User');
}
public function card()
{
return $this->hasOne('Card');
}
public function address()
{
return $this->belongsTo('Address');
}
public function orderItems()
{
return $this->hasMany('OrderItem');
}
}
What I am trying to get back:
$order = Order::with('card')->find($id);
This obviously doesn't work and I have tried several combos. I think the issue is with my models/relationships.
Any idea how I can get back the order with the card/token details?
DB info: Each order can have only one card_id and each card can be in many orders. There is no order_id in the card.
Orders table basically:
id | card_id
Cards table:
id | token
Trying to get the token col to return with the Order.
In your Order model, you need to change this:
public function card()
{
return $this->hasOne('Card');
}
to this:
public function card()
{
return $this->belongsTo('Card');
}
The reason is that you are defining the inverse of the hasMany relationship. With the belongsTo relationship, Eloquent will look for a card_id column on the orders table.

Resources