How to combine these multiple queries in laravel eloquent - laravel

I have the following query, where the final result I want is the $rate
// get latest effective date
$effectiveDate = CpfEffectiveDate::where('effective_from', '<=', $currentDate)
->orderBy("effective_from", 'DESC')
->first();
// get scheme related to the effective date and citizenship type
$scheme = CpfScheme::where("cpf_citizenship_id", $request->cpf_citizenship_id)
->where('cpf_effective_date_id', $effectiveDate->id)
->first();
// get rate based on scheme and other data
$rate = CpfRate::where("cpf_scheme_id", $scheme->id)
->where("minimum_wage", '<', ceil($totalWage)) // query does not accept floats. should be acceptable as wage tiers should be integers
->where("minimum_age", '<', $request->employee_age)
->orderBy('minimum_wage', 'DESC')
->orderBy('minimum_age', 'DESC')
->first();
How can I combine all 3 queries into a single one?
First I get the correct effective date from the first table, after which I use it to find the correct scheme (together with a citizenship_id) which I use to find the correct rate.
Here are the following models:
CpfRate
class CpfRate extends Model
{
protected $table = "cpf_rates";
protected $primaryKey = "id";
protected $hidden = ["created_at", "updated_at"];
public function scheme()
{
return $this->belongsTo(CpfScheme::class, "cpf_scheme_id");
}
protected $fillable = [
"minimum_age",
"minimum_wage",
"employer_percentage",
"employee_percentage",
"employee_offset_amount", // used for special cases, such as -500 for percentage = 0.15 * (TW - 500)
"ordinary_wage_cap", // ordinary wage cap
];
}
CpfScheme
class CpfScheme extends Model
{
protected $table = "cpf_schemes";
protected $primaryKey = "id";
protected $hidden = ["created_at", "updated_at"];
public function citizenship()
{
return $this->belongsTo(CpfCitizenship::class, "cpf_citizenship_id");
}
public function effectiveDate()
{
return $this->belongsTo(CpfEffectiveDate::class, "cpf_effective_date_id");
}
}
CpfEffectiveDate
class CpfEffectiveDate extends Model
{
protected $table = "cpf_effective_dates";
protected $primaryKey = "id";
protected $hidden = ["created_at", "updated_at"];
// mutated to dates
protected $dates = ['effective_from'];
public function schemes() {
return $this->hasMany(CpfScheme::class, "cpf_effective_date_id");
}
}
CpfCitizenship
class CpfCitizenship extends Model
{
protected $table = "cpf_citizenships";
protected $primaryKey = "id";
protected $hidden = ["created_at", "updated_at"];
// fields
protected $fillable = ['description'];
public function schemes() {
return $this->hasMany(CpfScheme::class, "cpf_citizenship_id");
}
}

$rate = CpfRate::select('cpf_rates.*')
->where('cpf_scheme_id', '=', function ($query) use ($request) {
$query->select('id')
->from('cpf_schemes')
->where("cpf_citizenship_id", $request->cpf_citizenship_id)
->where('cpf_effective_date_id', '=', function($query, $currentDate) {
$query->select('id')
->from('cpf_effective_dates')
->where('effective_from', '<=', $currentDate)
->orderBy("effective_from", 'DESC')
->limit(1);
})
->first();
})
->where("minimum_wage", '<', ceil($totalWage)) // query does not accept floats. should be acceptable as wage tiers should be integers
->where("minimum_age", '<', $request->employee_age)
->orderBy('minimum_wage', 'DESC')
->orderBy('minimum_age', 'DESC')
->first();
I did not tested but what only here can be problem is $currentdate, so if it is problem just use Carbon class to get current date directly in query.

Related

find() and delete() not working in laravel 9

find()
This is correct:
$user = Users::where('userid', '=', $id)->get();
return redirect('/register/view');
This is Incorrect:
$user = Users::find($id);
return redirect('/register/view');
delete()
This is Correct:
$user = Users::where('userid', '=', $id)->get();
if(!is_null($user))
{
Users::where('userid', '=', $id)->delete();
}
return redirect('/register/view');
This is Incorrect:
$user = Users::where('userid', '=', $id)->get();
if(!is_null($user))
{
$user->delete();
}
return redirect('/register/view');
Users Modedl:
class Users extends Model
{
use HasFactory;
protected $table = 'users';
protected $primarykey = 'userid';
}
Both codes are correct but not in my case. i don't know why. can anyone tell me what is wrong.
If you're looking for a single record by id (or userid in your case), don't use ->get():
$user = User::where('userid', $id)->first();
// OR
$user = User::find($id);
When deleting, also don't use ->get(). is_null on the result of ->get() will always be false, since ->get() returns a Collection, which isn't null.
$user = User::where('userid', $id)->delete();
// OR
$user = User::findOrFail($id)->delete();
Note: Your Model should be User, and the property to set the primary key in the Database is primaryKey, not primarykey:
class User extends Model {
use HasFactory;
protected $table = 'users';
protected $primaryKey = 'userid';
}
You're misunderstanding and misusing Laravel a lot here. ->get() should never be used for a single record, model names are singular, casing matters, etc etc.

Recursive relationship and nested eager loading with constraints

I'm tryng to create nested eager loading with a where constraint on a recursive relationship
Models and query simulation:
Model Hierarchy
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Hierarchy extends Model
{
protected $table = 'hierarchy';
protected $primaryKey = 'id_hierarchy';
protected $fillable = [
'name',
'parent_id'
];
/**
* #return HasMany
*
* This method implement recursive relationship
*/
public function children()
{
return $this->hasMany(Hierarchy::class, 'parent_id')->with('children');
}
/**
* #return HasMany
*/
public function grandchildren()
{
return $this->hasMany(Grandchild::class, 'id_hierarchy');
}
}
Model Grandchild
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Grandchild extends Model
{
protected $table = 'grandchildren';
protected $primaryKey = 'id';
protected $fillable = [
'id_hierarchy',
'id_something'
'name'
];
/**
* #return BelongsTo
*/
public function hierarchy()
{
return $this->belongsTo(Hierarchy::class, 'id_hierarchy');
}
}
The following query does not return the grandchildren as it was supposed to;
public function read($id)
{
$data = Hierarchy::query()
->whereNull('parent_id')
->with(['children.grandchildren' => function ($query) use($id) {
$query->where('id_something', $id);
}])
->get();
}
The problem is in the constrain, because with the following query it returns the grandchildrren (although not filtered because it doesn't have the where condition)
$data = Hierarchy::query()
->whereNull('parent_id')
->with(['children.grandchildren'])
->get();
Thanks in advance for suggestions to resolve this issue.
Edited:
As the code is a simulation of the real case, I added 'id_something' to be clearer what is involved.
'id_something' is related to another model that is not represented here
Assuming that HomeCity is one of the related models for GrandChild and the relationship is defined as
//GrandChild.php
public function home_city()
{
return $this->hasMany(HomeCity::class);
}
Then the query to return GrandChild records who live in HomeCity (id_something is a column on home_city table) identified by $id may written as:
public function read($id)
{
$data = Hierarchy::query()
->whereNull('parent_id')
->with(['children' => function ($query) use($id) {
$query->with(['grandchildren' => function($query) use($id) {
$query->whereHas('home_city', fn($query) => $query->where('id_something', $id);
}]);
}])
->get();
}

How can I use parent relation attribute in sub query in laravel eloquent

$order_detail = Order::where([['user_id', $user->id], ['updated_at', '>', $updated_at]])
->with([
'currency' => function ($query) {
$query->select('currency_code', 'currency_symbol', 'ex_rate_with_base');
},
'orderList' => function ($query) {
$query->select('id', 'order_id', 'product_code', 'qty',
DB::raw('(unit_price*orders.ex_rate_with_base) as unit_price_new'), 'status');
},
])->get();
Please help,
How can I use the attribute ex_rate_with_base from order table in sub query.
I do not want to use DB query. Please solve it with eloquent.
I would have done it like this 👇
Database Structure:
ModelCurrency.php
class ModelCurrency extends Model
{
public $timestamps = true;
protected $table = 'currency';
protected $guarded = [];
}
ModelOrderList.php
class ModelOrderList extends Model{
public $timestamps = true;
protected $table = 'order_list';
protected $guarded = [];
}
ModelOrderDetail.php
class ModelOrderDetail extends Model{
public $timestamps = true;
protected $table = 'order_detail';
protected $guarded = [];
public function scopeOfUser($query, $user_id){
return $query->where('user_id', $user_id);
}
public function scopeUpdatedAfter($query, $updated_at){
return $query->where('updated_at', '>', $updated_at);
}
public function currency(){
return $this->hasOne(ModelCurrency::class, 'id', 'currency_id');
}
public function order_lists(){
return $this->hasMany(ModelOrderList::class, 'order_id', 'id');
}
}
Function in controller:
//imports
use App\ModelOrderDetail;
use Illuminate\Support\Carbon;
public function prices() {
$user_id = 1;
$updated_at = Carbon::yesterday();
$data = ModelOrderDetail::with('currency', 'order_lists')->ofUser($user_id)->updatedAfter($updated_at)->get();
foreach ($data as $d){
$base_rate = $d->currency->base_rate;
foreach($d->order_lists as $o) $o->new_unit_price = $base_rate * $o->unit_price;
}
return response()->json($data);
};
Edit - Output : https://pastebin.com/i53PytSk

Need to take a sample of all positions where user_id is not equal to ours

Have 3 tables
users
posts
post_user (id, post_id, user_id)
class Post extends Eloquent {
protected $table = 'posts';
public $timestamps = true;
public function users()
{
return $this->belongsToMany('User');
}
}
class Users extends Eloquent {
protected $table = 'users';
protected $hidden = array('password', 'remember_token');
public function posts()
{
return $this->belongsToMany('Post');
}
}
Controller
public function application()
{
$posts = Post::find(1);
$user = DB::table('post_user')->where('user_id', '=', $this->id)->lists('user_id');
$posts = Post::whereNotIn('id', $user)->get();
return View::make('applications')->with(array('posts' => $posts));
}
What am I doing wrong? If possible with an explanation
You probably want to do lists('post_id').
However there is a much nicer way with whereDoesntHave:
$userId = $this->id;
$posts = Post::whereDoesntHave('users', function($q) use ($userId){
$q->where('user_id', $userId);
})->get();
Assuming that $this->id contains your user id, try this:
$posts = Post::whereHas('users', function($q) {
$q->whereNotIn( 'id', [$this->id])
})->get();
Method whereHas() selects posts belonging users, which have met a condition within the Closure. And this condition - method whereNotIn() - check if user id is different form $this->id.

How to use Eager Loading and Join in Eloquent at a same time in laravel 4

Models
class WPModel extends Eloquent
{
protected $table = 'work_processes';
protected $guarded = array('id');
protected $softDelete = true;
// declaring one-to-many relationship
public function relatedWPAQs()
{
return $this->hasMany('WPAQModel', 'wp_id');
}
public function relatedUsers()
{
return $this->belongsTo('UserModel', 'wp_owner_id');
}
}
class UserModel extends Eloquent
{
protected $table = 'users';
protected $softDelete = true;
public function relatedWPs()
{
return $this->hasMany('WPModel', 'wp_owner_id');
}
}
class WPAQModel extends Eloquent
{
protected $table = 'wp_audit_questions';
protected $fillable = array('wp_id', 'wp_audit_question');
// declaring one-to-many relationship - the inverse way
public function relatedWP()
{
return $this->belongsTo('WPModel', 'wp_id');
}
public function scopeWpParent($query, $id)
{
return $query->where('wp_id', '=' ,$id);
}
}
Controller
class WPAQController extends BaseController
{
public function showWPAQ($wpid)
{
$workprocess = WPModel::where('id', $wpid)
->join('users', 'users.id', '=', 'work_processes.wp_owner_id')
->select('users.user_name', 'work_processes.*')
->with(array(
'relatedWPAQs' => function($query) use ($wpid)
{
$query->where('wp_id', '=',$wpid);
}
))
->get();
return View::make('wpaqshow')->with(compact('workprocess'));
}
}
when I run this code, I get following error
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in
where clause is ambiguous (SQL: select users.user_name,
work_processes.* from work_processes inner join users on
users.id = work_processes.wp_owner_id where
work_processes.deleted_at is null and id = ?) (Bindings: array (
0 => '1', ))
Try the following:
$workprocess = WPModel::where('work_processes.id', $wpid)
->join('users', 'users.id', '=', 'work_processes.wp_owner_id')
->select('users.user_name', 'work_processes.*')
->with(array(
'relatedWPAQs' => function($query) use ($wpid)
{
$query->where('wp_id', '=',$wpid);
}
))
->get();
You have joined few tables. Now laravel has many Ids. You have to tell Laravel which id in where clause Laravel should use..
WPModel::where('id', $wpid)

Resources