Self join in Laravel - laravel

I am trying to build a self join in Laravel. I wish to compare 2 columns in the same table.
When I write this in my controller:
$char_name_obj = User::find($user->id)->characters()->where('lord_id', '=', 'id')->get();
lord_id is one column, id is the other column in the same table named characters. This returns nothing. I am sure I need to do a self join to be able to achieve this.
Character model:
class Character extends Eloquent {
protected $table = 'characters';
protected $fillable = array('lord_id','char_name', 'char_dynasty', 'picture');
public function user()
{
return $this->belongsTo('User');
}
public function Titles()
{
return $this->hasMany('Title');
}
public function LordCharID()
{
return $this->has_one('Character');
}
}
I don't know how to use the last function LordCharID().

has_one is the Laravel 3 function; so if you're using Laravel 4, you need to use hasOne
You can use whereRaw to compare columns:
User::find($user->id)->characters()->whereRaw('lord_id = id')->get();

Related

How to sort parent data based on child column detial in laravel 5.4?

I have 3 way relationship firstl i have get code like this in a controller
Trial::with('subjects')->where('source_id', $sourceId)->get()->toArray()
Now I want to sort subject.reactions on desc order of subject.reactions.accounts.nb_followers column. I tried to use orderby on relationship but it does not work because it sorting account indsted on reactions. I want to sort reaction based on value of "nb_followes" column present inside account table.
Trail Model
class Trial extends Model
{
use HasFactory;
public $table = 'trials';
public function subjects()
{
return $this->hasMany(Subject::class, 'trial_id')->with(['reactions', 'news'])->withCount('reactions');
}
}
Subject Model
class Subject extends Model
{
use HasFactory;
public $table = 'subjects';
public function reactions()
{
return $this->hasMany(Reaction::class, 'subject_id', 'id')->with(['accounts' => function ($q) {$q->orderBy('nb_followers', 'DESC');}])->where('twitter_error', 0)->where('active', 1)->orderby('key_reaction', 'DESC');
}
public function news()
{
return $this->hasone(News::class, 'id', 'news_item_id');
}
Reaction Model
class Reaction extends Model
{
use HasFactory;
public $table = 'reactions';
public function accounts()
{
return $this->belongsTo(Account::class, 'account_id', 'id')->where('name', '!=', '');
}
Thank you in Advance.
I want to sort reactions based on account table's column yes i cant use simple eloquent query because it will not create a structure that i want so that's why i created these relationships.
first you need to loop over trails using map method
second you need to use transform method to transform your subject in
sorted manner
as show in Subject model you need sort reaction by key_reaction
feild
$trails = ViewTrial::with('subjects')->where('source_id', $sourceId)->get();
$trails->map(function($trails){
return $trails->subjects = $trails->subjects->transform(function (&$subject) {
return [
"column" => $subject->column,
"reactions" => $subject->reactions->sortByDesc(function ($reactions) {
return $reactions['accounts']['nb_followers'];
})->sortByDesc('key_reaction')->values()->all()
]
})->values();
});
return $trails->toArray();

How do i delete all rows based on a single column in one to many relationship in laravel eloquent?

When deleting a particular movie , i want to delete all showtime related to it. I have 3 tables related to this query.
Showtime (which has m-m relation with times table (pivot table showtime_time)
Times
Movies
What i tried is:
MovieController:
public function destroy($id)
{
$movie = Movie::findOrFail($id);
if (ShowTime::where('movie_id', '=', $id)->exists()) {
$showtimes = ShowTime::whereIn('movie_id', '=', $id)->get();
foreach ($showtimes as $showtime) {
$showtime->times()->detach();
$showtime->delete();
$movie->delete();
}
return back();
} else {
$movie->delete();
}
return redirect()->route('movies.index');
}
Which gave me this error.
Argument 1 passed to
Illuminate\Database\Query\Builder::cleanBindings() must be of the type
array, string given, called in
C:\Users\lenovo\cinetime_nepal_backend\vendor\laravel\framework\src\Illuminate\Database\Query\Builder.php
on line 907
Model class
<?php
namespace Modules\Movie\Entities;
use Illuminate\Database\Eloquent\Model;
class Movie extends Model
{
protected $guarded = ['id']; //fillable
protected $hidden = ['created_at', 'updated_at'];
public function showTimes()
{
return $this->hasMany(ShowTime::class, 'movie_id');
}
}
This is how i am deleting showtime in showtimecontroller
ShowtimeController
public function destroy($id)
{
$showtime = ShowTime::findOrFail($id);
$showtime->times()->detach();
$showtime->delete();
return back();
}
I am new to laravel, i searched and tried many codes answered in this site but could not help myself.
Help Please
If you're using MySQL you can add 'ON DELETE CASCADE' to your foreign key. This will automatically delete any records that reference the parent when the parent is deleted. just put it to your showtime migration
$table->foreign('movie_id')->references('id')->on('movies')->onDelete('cascade');
Or, if you don't want that approach, then you can overwrite your delete method in your movie model. Put this code in your movie model.
public function delete() {
$this->showTimes()->times()->delete();
$this->showTimes()->delete();
parent::delete();
}
Then in your controller you just delete your movie and it's all fine.
public function destroy($id)
{
$movie = Movie::findOrFail($id);
$movie->delete();
return redirect()->route('movies.index');
}

How to use where clause on multiple nested eager loading in Laravel 5.8.2

I have four tables that are having relationships form the first to the last where
users is a parent to village on applicant_id , Village to Cell on village_id , Cell to Sector on cell_id
and my eloquent query is as follows and it works perfectly without a where clause, when where clause is added I get an error:
Column not found: 1054 Unknown column 'applicant_id' in 'where clause'
// joins users , village ,cell and sector
$uvcsector = SectorApproval::with('Cell.Village.UserApplicant')
->where('applicant_id', 10)
-> get();
Models :
class Users extends Model
{
protected $table ="users";
public function VillageApplicant(){
return $this->hasMany(VillageApproval::class);
}
}
class VillageApproval extends Model
{
protected $table ="villageapplication";
// OnetoOne relationship inverse
public function UserApplicant()
{
return $this->belongsTo(Users::class, 'applicant_id');
}
// One Village application can be sent in one cell (OnetoOne)
public function Cell(){
return $this->hasOne(CellApproval::class);
}
}
class CellApproval extends Model
{
protected $table ="cellapplication";
// OnetoOne relationship inverse
public function Village()
{
return $this->belongsTo(VillageApproval::class, 'village_id');
}
// One Cell application can be sent in one sector (OnetoOne)
public function Sector(){
return $this->hasOne(SectorApproval::class);
}
}
class SectorApproval extends Model
{
protected $table ="sectorapplication";
// OnetoOne relationship inverse
public function Cell()
{
return $this->belongsTo(CellApproval::class, 'cell_id');
}
}
Use whereHas to search in the related tables.
$uvcsector = SectorApproval::with('Cell.Village.UserApplicant')
->whereHas('Cell.Village.UserApplicant', function($query) use ($id){
$query->where('applicant_id', $id);
})
-> get();
->where('village.application_id', 10)

Laravel 5.3 belongsToMany return null, pivot data

I have a next models:
class Product extends Model{
protected $table = 'products';
public function payments()
{
return $this->belongsToMany('App\Payment', 'payment_product', 'product_id', 'payment_id')
}
}
class Payment extends Model{
protected $table = 'payments';
public function products(){
return $this->belongsToMany('App\Product');
}
}
Pivot table: payment_product(id, product_id, payment_id)
Eloquent
public function details($id){
$product = Product::with('payments')->find($id);
dd($product->payments); // return null
return view('products.details', ['product' => $product]);
}
I need to bring in a foreach, but $product->payments is null. Why is that ?
All the tables are not empty.
UPD
Sub query $this->belongsToMany('App\Payment', 'payment_product', 'product_id', 'payment_id');
Results:
try:
public function payments()
{
return $this->belongsToMany('App\Payment', 'payment_product', 'payment_id', 'product_id')
}
I think you have your FK in the wrong order.
In fact, I don't think you need to specify anything more than:
public function payments()
{
return $this->belongsToMany('App\Payment')
}
Looks like you are joining two tables based on unrelated fields.
When you do
return $this->belongsToMany('App\Payment', 'payment_product', 'product_id', 'payment_id')
your table products gets inner joined with payment_product on
products.product_id = payment_product.payment_id.
But I think these two columns are not the related keys. Instead, in your payment_product, join with the product_id in this table with products.product_id.
That might work.
Rename payments to payments_method:
public function payments_method(){
return $this->belongsToMany('App\Payment'); //or ('App\Payment', 'payment_product', 'payment_id', 'product_id')
}
$product = Product::find($id);
$product->payments_method; //this is work
This is magic:)

Laravel 4 - How to use where conditions for relation's column

This is what I want, I have two tables. one is 'Restaurants' and other is 'Facilities'.
The tables are simple.. and One-To-One relations. like there is a restaurant table with id, name, slug, etc and another table called facilities with id, restaurant_id, wifi, parking, etc
Here are my models:
class Restaurant extends Eloquent {
protected $table = 'restaurants';
public function facilities() {
return $this->hasOne('Facilities');
}
}
class Facilities extends Eloquent {
protected $table = 'facilities';
public function restaurant() {
return $this->belongsTo('Restaurant');
}
}
I want do like this Select * from restaurants r left join facilities rf on r.id=rf.restaurant_id where r.name = 'bbq' and rf.wifi != '1'.
How to use Eloquent to do that?
ps. sorry for modify from https://stackoverflow.com/questions/14621943/laravel-how-to-use-where-conditions-for-relations-column#= , but I have the similar problem.
You can use where and other sql-based methods on the relationship objects.
That means you can either create a custom method in your model:
class Restaurant extends Eloquent {
protected $table = 'restaurants';
public function facilities($wifi) {
return $this->belongsTo('Facility')->where('wifi', '=', $wifi);
}
}
Or you can try to use query scopes:
class Restaurant extends Eloquent {
protected $table = 'restaurants';
public function facility() {
return $this->belongsTo('Restaurant');
}
public function scopeFiltered($query, $wifi)
{
return $query->where('wifi', '>', 100);
}
}
Then:
$wifi = 1;
$restaurants = Restaurant::facilities()->filtered($wifi)->get();
This isn't exactly what you need likely, but query scopes is likely what you want to use to get what you're attempting.
THe key point is to know that relationship classes can be used like query builders - for example:
$this->belongsTo('Facility')->where('wifi', '=', $wifi)->orderBy('whatever', 'asc')->get();
There are some ways to filter both, this is using QueryBuilder:
Restaurant::join('facilities','facilities.restaurant_id','=','restaurants.id')
->where('name','bbq')
->where('facilities.wifi','!=', 1)
->get();

Resources