SQL query similar to the concept of set (complement or except) - laravel

I need your help. I just want to display the name of all users (from table users) whose are not in table documents but in today's date
I've tried but I failed
Here is my code
public function activeUser(){
$documents = DB::table('users')
->leftJoin('documents', 'users.id', '=', 'documents.user_id')
->select('users.fname','users.mname','users.sname','documents.created_at')
->where('documents.user_id',null)
->where('documents.created_at',null)
->get();
return view('activity.activity')->with('documents', $documents);
}
I don't know to add current date in the where clause.
The above code gave me the all users who are note in table documents but if user exist in documents once will always considered as is in that documents table.

You can use "whereBetween" (https://laravel.com/docs/6.x/queries#where-clauses).
public function activeUser(){
$yesterday = Carbon::yesterday();
$today = Carbon::today();
$documents = DB::table('users')
->leftJoin('documents', 'users.id', '=', 'documents.user_id')
->select('users.fname','users.mname','users.sname','documents.created_at')
->where('documents.user_id',null)
->whereBetween('documents.created_at', [$yesterday, $today])
->get();
return view('activity.activity')->with('documents', $documents);
}
Remember, you can also use "whereNotInBetween" if that better matches your business logic case.

Related

use of orWhere() in Eloquent

I have a eloquent query that I am running twice, but feel can be run once.
I'd want to return the values of the first where statement if exists otherwise check the second where statement which is the default in the query.
This is what I am currently doing:
$details = Telco::select('telcos.id AS telco_id', 'telcos.name AS telco_name')
->leftJoin('telco_prefixs', 'telco_prefixs.telco_id', '=', 'telcos.id')
->where('telco_prefixs.prefix', '=', $phone_number) // check if ndc exists
->first();
if ($details){
return $details;
}
return Telco::select('telcos.id AS telco_id', 'telcos.name AS telco_name')
->leftJoin('telco_prefixs', 'telco_prefixs.telco_id', '=', 'telcos.id')
->where('telcos.name', '=', 'Default') //default channel
->first();
I have a feeling this can be combined to something like below:
However, this fails as keeps executing the OrWhere clause.
Telco::select('telcos.id AS telco_id', 'telcos.name AS telco_name')
->leftJoin('telco_prefixs', 'telco_prefixs.telco_id', '=', 'telcos.id')
->where('telco_prefixs.prefix', '=', $phone_number) // if ndc exists
->Orwhere('telcos.name', '=', 'Default') //default channel
->first();
Someone help. Thanks
Try to add your where and or where condition as below.
Telco::select('telcos.id AS telco_id', 'telcos.name AS telco_name')
->leftJoin('telco_prefixs', 'telco_prefixs.telco_id', '=', 'telcos.id')
->where(function ($query) use($phone_number) {
$query->where('telco_prefixs.prefix', '=', $phone_number);
$query->Orwhere('telcos.name', '=', 'Default');
})->first();
I you want to use just eloquent a possible solution would be to have something like:
I suppose you have model called Telco and another one calle TelcoPrefix.
//Telco.php
//first we create a has many relationship with your telco_prefixs table.
public function telcoPrefixs(){
return $this->hasMany(TelcoPrefix::class);
}
Once you have that relationship you can use something similar to this code:
Telco::whereHas('telcoPrefixs',function($query, $phone_number){
return $query->where('prefix,'=',$phone_number);
})->select('id','name')->first();
This will compare the relationship and if it exists or has it will return your first record in one query.
Hope it helps at least to give a guide of what you can do.

Join Laravel tables

I have got three tables Kudos, Kudoscategories, and specialpost. I need to get the data from those tables and check the post id using a where condition.
I have attached the database table screenshot here
I already tried this, but it's not getting any result.
$results = DB::table('kudos')
->select('kudos.description','kudoscategory.catname','kudoscategory.image','kudos.spid')
->join('kudoscategory', 'kudoscategory.id', '=', 'kudos.categoryid')
->where('kudos.spid', '=', $post_id)
->first();
return $results;
What I need to do is get the results using below where condition newsfeed_special_posts.main_post_id = kudos.spid
You must add another join with newsfeed_special_posts.
The query will be like,
$results = DB::table('kudos')
->select('kudos.description','kudoscategory.catname','kudoscategory.image','kudos.spid')
->join('kudoscategory', 'kudoscategory.id', '=', 'kudos.categoryid')
->join('newsfeed_special_posts', 'newsfeed_special_posts.main_post_id', '=', 'kudos.spid')
->where('kudos.spid', '=', $post_id)
->first();
return $results;
Though this is not a good practice for laravel. using laravel eloquent relationships will be more efficient for these results.
https://laravel.com/docs/5.8/eloquent-relationships
you can still do it this way. still efficient to avoid sql injection since you are getting all the record from the 3 tables. seeing your table above, its not properly normalised. anywaye try this.
$results = DB::table('kudos')
->leftjoin('kudoscategory', 'kudoscategory.id', '=', 'kudos.categoryid')
->leftjoin('newsfeed_special_posts', 'newsfeed_special_posts.id', '=', 'kudos.spid')
->where('kudos.spid', '=', $post_id)
->first();
return $results;
you can try this code
at first, create model Kudos,KudosCategory,NewsfeedSpecialPosts
Kudos Model
public function kudoscategory_dta()
{
return $this->belongsTo('App\Model\KudosCategory','categoryid');
}
public function newsfeed_special_posts_dta()
{
return $this->belongsTo('App\Model\NewsfeedSpecialPosts','spid','main_post_id ');
}
controller
Kudos::with('kudoscategory_dta','newsfeed_special_posts_dta')->first();

search in eloquent return query variable

Here is my problem. Please help
I have these two tables Course and Students. Students take courses. Now I want to get a specific course as shown then see in student table if this course is taken by the student.
Course table:
id
name
description
Student table:
user_id
course_id
semester
address
phone
What I tried:
$course = Course::where('name', '=', $data["id"]);
$enroll= Students::where('course_id', '=', $course["id"]);
$enroll= Students::where('course_id', '=', $course->id);
$$result=$course->toArray();
$enroll= Students::where('course_id', '=', $course["id"]);
I need to search the variable where the return value of eloquent query is stored.
For a specific user and a specific course you can get the collection of records from student table with the following query:
$courceId = 1;
$userId = 1;
$enrolled = Students::where('course_id', $courseId)
->where('user_id', $userId)
->count() > 0;
$enrolled will have true or false value
You can use eloquent relationship to obtain this in a much better way. However you can do this like the following assume your course name is $course_name:
$course = Course::where('name', '=', $course_name)->first();
if($course!=null){
$enroll= Students::where('course_id', '=', $course->id)->get();
}
and then you can check if it has data or not like
if($enroll!=[]){
echo 'this course has been taken by some student';
}
Here some student are the $enroll student.

Foreach loop not going through correctly

I have a form to mark employees' attendance that HR fill in which is looped over every current employee. I need it to show the current values where attendance is marked in the database, otherwise it should be blank.
In my controller I query the existing results:
$results = Attendance::where('Sdate', '=', date("Y-m-d", strtotime($TheDate))) ->get();
Then loop through them to get the employee details:
foreach($results as $result)
{
$contractors = DB::table('contractors') ->where('contractors.AreaPosition', '=', $department) ->where('PRN', '!=', $result->PRN) ->get(); $employees = DB::table('current_employees') ->where('current_employees.AreaPosition', '=', $department) ->where('PRN', '!=', $result->PRN) ->get(); $showEmployees = array_merge($contractors, $employees);
}
This should exclude all employees who have a record saved in attendance for that date, however it doesn't seem to be looping correctly. It will exclude some results, but not all. If I return the results variable I get the correct list of records so I know that part is working correctly.
What I'm looking to achieve in my view is something like:
#foreach($attendance as $results)
Show form where there's an existing record for this date and department
#endforeach
#foreach($employees as $employee)
Show form for all employees in this department (but should exclude results where there is a record in attendance)
#endforeach
The problem with your code is you are saving the result in a variable and not in an array.
Your solution would be to store the data in an array
foreach($results as $result)
{
$contractors[] = DB::table('contractors') ->where('contractors.AreaPosition', '=', $department) ->where('PRN', '!=', $result->PRN) ->get(); $employees = DB::table('current_employees') ->where('current_employees.AreaPosition', '=', $department) ->where('PRN', '!=', $result->PRN) ->get(); $showEmployees = array_merge($contractors, $employees);
}
Try printing contractors array and see what happens.I hope this works
This was answered for me on Laracasts.
What I needed to do was create a list of the variable to check against (employee number)
$PRNs = Attendance::where('Sdate', '=', date("Y-m-d", strtotime($TheDate)))->lists('PRN');
And then use Laravel's whereNotIn, checking against the list.
$contractors = DB::table('contractors')
->where('contractors.AreaPosition', '=', $department)
->whereNotIn('PRN', $PRNs)
->get();

Laravel eloquent and relationship

I have a code:
$response = $this->posts
->where('author_id', '=', 1)
->with(array('postComments' => function($query) {
$query->where('comment_type', '=', 1);
}))
->orderBy('created_at', 'DESC')
->limit($itemno)
->get();
And when I logged this query with:
$queries = \DB::getQueryLog();
$last_query = end($queries);
\Log::info($last_query);
In log file I see follow:
"select * from `post_comments` where `post_comments`.`post_id` in (?, ?, ?, ?) and `comment_type` <> ?"
Why is the question mark for comment_type in the query?
Update #1:
I replaced current code with following and I get what I want. But I'm not sure it is OK. Maybe exists many better, nicer solution.
$response = $this->posts
->where('author_id', '=', 1)
->join('post_comments', 'post_comments.post_id', '=', 'posts.id')
->where('comment_type', '=', 1)
->orderBy('created_at', 'DESC')
->limit($itemno)
->get();
Behind the scene the PDO is being used and it's the way that PDO does as a prepared query, for example check this:
$title = 'Laravel%';
$author = 'John%';
$sql = "SELECT * FROM books WHERE title like ? AND author like ? ";
$q = $conn->prepare($sql);
$q->execute(array($title,$author));
In the run time during the execution of the query by execute() the ? marks will be replaced with value passed execute(array(...)). Laravel/Eloquent uses PDO and it's normal behavior in PDO (PHP Data Objects). There is another way that used in PDO, which is named parameter/placeholder like :totle is used instead of ?. Read more about it in the given link, it's another topic. Also check this answer.
Update: On the run time the ? marks will be replaced with value you supplied, so ? will be replaced with 1. Also this query is the relational query, the second part after the first query has done loading the ids from the posts table. To see all the query logs, try this instead:
$queries = \DB::getQueryLog();
dd($queries);
You may check the last two queries to debug the queries for the following call:
$response = $this->posts
->where('author_id', '=', 1)
->with(array('postComments' => function($query) {
$query->where('comment_type', '=', 1);
}))
->orderBy('created_at', 'DESC')
->limit($itemno)
->get();
Update after clarification:
You may use something like this if you have setup relation in your Posts model:
// $this->posts->with(...) is similar to Posts::with(...)
// if you are calling it directly without repository class
$this->posts->with(array('comments' =. function($q) {
$q->where('comment_type', 1);
}))
->orderBy('created_at', 'DESC')->limit($itemno)->get();
To make it working you need to declare the relationship in your Posts (Try to use singular name Post if possible) model:
public function comments()
{
return $this->hasmany('Comment');
}
Your Comment model should be like this:
class Comment extends Eloquent {
protected $table = 'post_comments';
}

Resources