Laravel Eloquent select data from one Model by checking another Model values - laravel

I want to select all the Offers with the condition that it is not completed (data not exist on OffersProof OR offers proof status = 0 with multiple where conditions in OffersProof)
List offers that do not have the proof. If proof exists then check the status of it. if that is 0 then show it in the list.
Offers Model
class Offers extends Model
{
protected $table = 'offers';
protected $fillable = [ "name","desc"];
protected $hidden = [];
}
Offers Proof Model
class OffersProof extends Model
{
protected $table = 'offers_proof';
protected $fillable = [ "offer", "user","pub","time","status" ];
protected $hidden = [];
}
Here is the query that I have tried. There are issues in the selection. Not sure this one works as perfect or needs to implement this using relation.
$user = "test";
$pub = "demo";
$offers = Offers::leftJoin('offers_proof', function($leftJoin)use($user,$pub)
{
$leftJoin->on('offers_proof.offer', '=', 'offers.id');
$leftJoin->where('offers_proof.user', '=', $user);
$leftJoin->where('offers_proof.pub', '=', $pub);
$leftJoin->where('offers_proof.status', '!=', 0);
})->where($conditions)->get();
This code returns all the offers. I want to filter the offers that have no proof on the OffersProof table.
Is there any better way to take the data with good performance query and how can I select the offers as per the above requirement.

If I understand you correctly, you want to select offers that are not complete OR offers proof status = 0. I think this code should work.
$user = "test";
$pub = "demo";
$offers = Offers::leftJoin('offers_proof', 'offer', 'offers.id')
->select(*)
->where('offers_proof.user', $user)
->where('offers_proof.pub', $pub)
->where('offers_proof.status', 0)
->where($conditions)
->get();

I have missed the DB::Raw part and one condition to check whether left join data exists.
$user = "test";
$pub = "demo";
$offers = Offers::leftJoin('offers_proof', function($leftJoin)use($user,$pub)
{
$leftJoin->on('offers_proof.offer', '=', 'offers.id');
$leftJoin->where('offers_proof.user', '=', DB::raw("'$user'"));
$leftJoin->where('offers_proof.pub', '=', DB::raw("'$pub'"));
$leftJoin->where('offers_proof.status', '!=', DB::raw("0"));
})->where('offers_proof.user', '=', NULL)->where($conditions)->get();

Related

eloquent with() in multiple where() clouse

I am trying to filter results of relationship table.
public function read_projects_by_coords(Request $request)
{
$from_lat = $request->get("from_lat");
$to_lat = $request->get('to_lat');
$from_lng = $request->get('from_lng');
$to_lng = $request->get('to_lng');
$projects = Project::with(["details" => function($query) use ($from_lat, $from_lng, $to_lat, $to_lng){
return $query->where("details.lat", ">", $from_lat)
->where("details.lat", "<", $to_lat)
->where("details.lng", ">", $from_lng)
->where("details.lng", "<", $to_lng);
}])->get();
return response()->json($projects);
}
But when I run the above details(child) coming with a empty/null result and parent/Project table not filtered. I returns all...
For example $projects = Project::with(["details"])->get(); this is works without a problem. But when I try to filter Project Model with the where inside the with() I can't get the detail object records, and parent is not filtered.
to anyone who wants to see the models parent and child
class Project extends Model
{
protected $table = "projects";
protected $guarded = [];
protected $with = ["details"];
public function details(){
return $this->hasOne("App\Models\Detail");
}
}
class Detail extends Model
{
protected $table = "details";
protected $guarded = [];
public function project(){
return $this->belongsTo("App\Models\Project");
}
}
What am I am missing?
To filter the Project table to only select the ones with some Details matching your parameters, you need to use whereHas. You need to keep your with clause too in order to have the details property correctly populated.
I would use a callback to not repeat the same conditions
$callback = function($query) use ($from_lat, $from_lng, $to_lat, $to_lng) {
$query->where("lat", ">", $from_lat)
->where("lat", "<", $to_lat)
->where("lng", ">", $from_lng)
->where("lng", "<", $to_lng);
}
$projects = Project::with(['details' => $callback])
->whereHas('details', $callback)
->get();
return response()->json($projects);

The equivalence of the AND statement in a ON statement (JOIN) in EloquentORM

Take a look at the query below:
SELECT v*, s.*
FROM videos v
INNER JOIN subtitles s ON (s.subtitle_id = v.video_id AND s.language = 'en')
WHERE v.video_id = 1000
I want to find the equivalent data retrieval action for a Laravel / Eloquent ORM environment.
So, my options are:
using the DB facade
using the query builder
defining the relationship in the Video model
Let's say I wish to use the latter (if possible).
namespace App\Models\v1;
use App\Models\v1\Subtitles;
use Illuminate\Database\Eloquent\Model;
class Video extends Model
{
protected $table = 'videos';
public function subtitle()
{
return $this->hasOne(Subtitles::class, 'subtitle_id', 'video_id'); // How can I define the AND s.language = 'en' ?
}
}
The problem here is that I don't know how to define the AND s.language = 'en' in EloquentORM.
Any help is appreciated.
You can add a where clause to the relationship:
public function subtitle()
{
return $this->hasOne(Subtitles::class, 'subtitle_id', 'video_id')->whereLanguage('en');
}
Retrieving the model:
Provided you changed your primaryKey property on the video model:
protected $primaryKey = 'video_id';
Docs
You can do the following:
$video = Video::findOrFail(1000);
$subtitle = $video->subtitle;
You can define the relationship and then use whereHas
public function subtitle()
{
return $this->hasOne(Subtitles::class, 'subtitle_id', 'video_id');
}
And then filter it like this
$video = Video::where('video_id', 1000)->whereHas('subtitle', function($query){
$query->where('language', 'en');
})->first();
For details check the doc
If you just want to use join then you can use it like this
$lang = 'en';
$video = Video::where('video_id', 1000)
->join('subtitles', function ($join) use ($lang){
$join->on(function ($query) use ($lang) {
$query->on('subtitles.subtitle_id', '=', 'videos.video_id');
$query->on('subtitles.language', '=', DB::raw($lang));
});
})->first();
Check laravel join

Eloquent is setting a value to null

i'm having an error with Eloquent (and Many to Many relationship).
This is my code:
$user = new Users;
$rs = $user
->company()
->where('company_role.users_id', $request->session()->get('usrid'))
->where('code', $request->company)
->first();
The query that Eloquent perform is this one:
select `companies`.*, `company_role`.`users_id` as `pivot_users_id`, `company_role`.`companies_id` as `pivot_companies_id`, `company_role`.`role_name` as `pivot_role_name` from `companies` inner join `company_role` on `companies`.`id` = `company_role`.`companies_id` where `company_role`.`users_id` is null and `company_role`.`users_id` = 1 and `code` = 12345678901 limit 1)"
How is this possible? Do you guys have any idea?
This is my Users model:
class Users extends Model
{
//table associated with model
protected $table = 'users';
protected $primaryKey = 'id';
public function company(){
return $this->belongsToMany('App\Companies','company_role')->withPivot('role_name');
}
}
It was a rookie error
i just changed this:
$rs = $user->company()->where('company_role.users_id',$request->session()->get('usrid'))->where('code',$request->company)->first();
into this:
$rs = $user->find($request->session()->get('usrid'))->company()->where('piva',$request->company)->first();
and everything works as expected.
Thanks to everyone!
First, define the variables
$user_id = $request->session()->get('usrid');
$user = User::find($user_id);
Then, you need to find the user and the companies they are attached, and an individual company with the search params
$companies = $user->company()->get();
$company = $user->company()->where('code', $request->company)->first();

Laravel eloquent whereIn with one query

In laravel, I can use many where rules as an array a run one query to the database using laravel eloquent where method to get needed result.
Code:
$where = [];
$where[] = ['user_id', '!=', null];
$where[] = ['updated_at', '>=', date('Y-m-d H:i:s')];
if($request->searchTerm) {
$where[] = ['title', 'like', '%' . $request->searchTerm . '%'];
}
Model::where($where)->get();
Question part:
Now I need to use Laravel Eloquent method whereIn with array params to get needed result with one query.
I tried by looping method but with many queries to the database.
Code:
$model = new Model;
$whereIn = [];
$whereIn[] = ['date', '>=', Carbon::now()->subDays(10)];
$whereIn[] = ['user_role', 'candidate'];
if (!empty($scope) && is_array($scope)) {
$whereIn[] = ['user_id', $scope];
}
if(is_array($employment) && !empty($employment)) {
$whereIn[] = ['employment', $employment];
}
if(is_array($experience) && !empty($experience)) {
$whereIn[] = ['experience', $experience];
}
foreach ($whereIn as $v) {
$model = $model->whereIn($v[0], $v[1]);
}
dump($model->get());
First I tired $model->whereIn($whereIn)->get() but it's return error. It's possible get results with one query using whereIn without looping?
Note: My $whereIn array will be dynamic array!
whereIn is a query builder function so you can't use it on the model directly. Instead you should create a query builder instance. I also suggest you use when instead of the if statements:
$models = Model::when(!empty($scope) && is_array($scope), function ($query) use ($scope) {
$query->whereIn('user_id', $scope);
})->when(!empty($employment) && is_array($employment), function ($query) use ($employment) {
$query->whereIn('employment', $employment);
})->when(!empty($experience) && is_array($experience), function ($query) use ($experience) {
$query->whereIn('experience', $experience);
})->get();
dump($models);
when essentially runs the function when the first parameter is true. There's more detail in the documentation under conditional clauses.
Since your $whereIn variable is an array of arrays it will work like :
$model->whereIn($whereIn[0][0], $whereIn[0][1])->get();
If it just a simple array then you can use :
$model->whereIn($whereIn[0], $whereIn[1])->get();
Do in Eloquent
$model = Model::whereIn('id', array(1, 2, 3))->get();
Or using Query builder then :
$model = DB::table('table')->whereIn('id', array(1, 2, 3))->get();

Add custom column to identify table during query

How can I add a custom column in an Eloquent select query in order to identify the table?
For example, I have the current query:
$posts = Post::where('user_id', getUserID())
->get();
I'd like to add a column is_post with value 1 (for true) during the query.
The Post class:
<?php
class Post extends Eloquent {
protected $table = 'posts';
}
How can I do this?
You could do it for example this way:
$posts = Post::where('user_id', getUserID())->selectRaw('*, 1 AS `is_post`')->get();
but depending on your needs, you can also use the piece of code you showed:
$posts = Post::where('user_id', getUserID())->get();
and add accessor in Post model this way:
public function getIsPostAttribute($value) {
return 1;
}
In both cases you should be able to display is_post value for example this way:
foreach ($posts as $post) {
echo $post->is_post;
}

Resources