Issue while trying to search using whereBetween in Laravel Eloquent - laravel

I have 2 database tables in MySQL below.
Table - 1
CREATE TABLE `tblaccount` (
`account_id` mediumint(8) UNSIGNED NOT NULL,
`account_number` varchar(100)
)
ALTER TABLE `tblaccount`
ADD PRIMARY KEY (`account_id`);
Table - 2
CREATE TABLE `tblcollectoractions` (
`collector_action_id` mediumint(8) UNSIGNED NOT NULL,
`account_id` mediumint(8) UNSIGNED DEFAULT NULL,
`pay_date` date DEFAULT NULL
);
ALTER TABLE `tblcollectoractions`
ADD PRIMARY KEY (`collector_action_id`),
ADD KEY `tblcollectoractions_account_id_foreign` (`account_id`);
I have a query below. It joins records in both tables on the basis of account_id. It also filters those accounts in tblcollectoractions table where pay_date lies between start and end date.
Here is my Laravel Eloquent Query. AccountModel is related to tblaccount and ActionModel is related to tblcollectoractions.
$query = (new AccountModel())->newQuery();
$data->whereIn("account_id", function($query) use($inputs) {
$query->select('account_id')->from(with(new ActionModel)->getTable())
->whereBetween('pay_date', [$inputs["from_pay_date"], $inputs["to_pay_date"]]);
});
But, this shows me all the records from table tblcollectoractions. I meant, it does not filter on the basis of start and end date.
Am I missing anything?

This is the most Eloquent way to do this, checking if the $inputs variable is set
$data = AccountModel::query()
->with([
'actions' => function($query) use ($inputs) {
if ($inputs['from_pay_date']) {
$query->whereBetween('pay_date', [
$inputs['from_pay_date'],
$inputs['to_pay_date']
]);
}
}
])
->has('actions')
->get();
the models should look something like this:
AccountModel.php
class AccountModel extends Model
{
protected $guarded = ['id'];
public function actions()
{
return $this->hasMany(ActionModel::class, 'account_id', 'account_id');
}
}

Related

How to delete record with composite primary keys using Eloquent?

I'm trying to delete a record with two primary keys, using Eloquent - Laravel.
This is my model
class Like extends Model
{
//protected $primaryKey = ['crdid', 'usrid'];
public $timestamps = false;
use HasFactory;
}
Controller
try{
$dellike = Like::where('crdid', '=', $like->crdid, 'and')
->where('usrid', '=', $like->usrid)->first();
$dellike->delete();
}
catch(Exception $e){
return $e->getMessage();
}
Table definition
Schema::create('likes', function (Blueprint $table) {
$table->biginteger('crdid');
$table->biginteger('usrid');
$keys = array('crdid', 'usrid');
$table->primary($keys);
});
However, it gives me the below error;
Column not found: 1054 Unknown column 'id' in 'where clause' (SQL: delete from `likes` where `id` is null)
I believe the 'id' is the default primary key used by Eloquent, but I'm not using it.
How should I define that, I'm not using the default primary key? or what is the correct way to delete the record with composite primary keys? Any help would be highly appreciated.
As Laravel Eloquent Docs says:
Eloquent requires each model to have at least one uniquely identifying "ID" that can serve as its primary key. "Composite" primary keys are not supported by Eloquent models. However, you are free to add additional multi-column, unique indexes to your database tables in addition to the table's uniquely identifying primary key.
So you can't use some methods of eloquent.
But seeing your code, looks like you are trying to create a model for a relationship pivot table (many to many between user and crd (what is crd?! no reason to abreviatte here.)
Try defining a many to many relationship on your user and crd model.
Also laravel naming convention for key columns is: model_name_id for a model named ModelName
But, just to delete, you can skip the first in your query:
Like::where('crdid', '=', $like->crdid, 'and')
->where('usrid', '=', $like->usrid)->delete();
This happens because when you delete a model (your attempt) laravel uses the primary key field (defaults to id) as where condition. But manually querying, you are defining the where clauses of the delete.
Just create additionnal column named id in the table as unique with auto-increment option. Eloquent will use it to delete each row with delete function.
Example with Laravel 5.5 :
$logement = Logement::findOrFail($id);
$commodites = Commodites_logement::all()->where('logement_id','=',$logement->id);
foreach ($commodites as $commodite) {
$commodite->delete();
}

Laravel - for some reason, max breaks my query

I have this piece of code:
$query = Student::whereHas('statusuri', function($q) use ($status) {
$q->latest('status_student.id')->take(1)
->where('status_id', $status)
->whereNotNull('status_id');
});
and it works fine, but I don't necessarily get the desired result.
I tried changing the first line to max (so I don't filter all my records then do a limit 1), I just get the highest ID from the beginning - like this:
$query = Student::whereHas('statusuri', function($q) use ($status) {
$q->max('status_student.id')
->where('status_id', $status)
->whereNotNull('status_id');
});
but then my query breaks.
For some reason, I get this:
Unknown column 'students.id' in 'where clause' (SQL: select max(`status_student`.`id`) as aggregate from `statusuri` inner join `status_student` on `statusuri`.`id` = `status_student`.`status_id` where `students`.`id` = `status_student`.`student_id`)
Why does my query break after I do this change?
Thanks.
Tables:
students
id bigint(20)
//other non-related data
statusuri
id bigint(20)
nume VARCHAR(255)
status_student
id int(11)
student_id int(10)
status_id int(10)
stare_stagiu_id int(11)
created_at timestamp
updated_at timestamp
statusuri() from Student
public function statusuri()
{
return $this->belongsToMany(Status::class, 'status_student')
->withPivot('id', 'data_inceput', 'data_sfarsit', 'document', 'status_id', 'stare_stagiu_id')
->withTimestamps();
}
Status and StatusStudent classes
class StatusStudent extends Model
{
protected $table = 'status_student';
protected $fillable = ['id', 'student_id', 'status_id', 'stare_stagiu_id'];
}
class Status extends Model
{
protected $table = 'statusuri';
public $fillable = ['nume'];
}
Your relations are messed up. The query is trying to use a column from the student table, but the student table is not available in said query as it is not joined. See this fiddle to see what goes wrong in the SQL.
http://sqlfiddle.com/#!9/52c96fa/6
In the end, I'd do it like this if I understood you correctly:
In StatusStudent.php (Model):
public function student() {
return $this->hasOne(Student::class, 'id', 'student_id');
}
In Controller:
public function stackoverflowtest() {
//Set teststatus
$status = 1;
//Get the latest status of all users - and if that status is correct, retrieve into array
$latest = DB::select( DB::raw("SELECT max(id) as id, student_id FROM status_student group by student_id"));
$array = [];
foreach ($latest as $l) {
$status_id = StatusStudent::whereId($l->id)->whereStatusId($status)->first();
if ($status_id) {
array_push($array, $status_id);
}
}
//$array now holds all the StatusStudent, simply user ->student to get the student related to said status, example below
if($array) {
dd($array[0]->student);
return $array;
} else {
return 'No match';
}
}
First, we get all latest records for each user IF the status is correct. Then, we simply get the Student from the status_student table via the relation.

Laravel paginate with only first result

i'm kinda new to Laravel so I hope the question is clear enough.
I have a table with Users and another table with Tasks.
In my User model I have the following :
public function tasks() {
return $this->hasMany('App\User' , 'id');
}
I can do the following to retrieve a single user from the DB
$users = \App\User::find(1)->tasks()->paginate();
but i get
{"current_page":1,"data":[{"id":1,"name":"Ed","email":"mail#weqweqeq.com","email_verified_at":null,"created_at":null,"updated_at":null,"tasks":[{"id":1,"name":"Ed","email":"mail#weqweqeq.com","email_verified_at":null,"created_at":null,"updated_at":null}]},{"id":2,"name":"Alyse","email":"mail#rxygewe.com","email_verified_at":null,"created_at":null,"updated_at":null,"tasks":[]}],"first_page_url":"http:\/\/127.0.0.1:8000?page=1","from":1,"last_page":1,"last_page_url":"http:\/\/127.0.0.1:8000?page=1","next_page_url":null,"path":"http:\/\/127.0.0.1:8000","per_page":15,"prev_page_url":null,"to":2,"total":2}
I've also tried :
$users = \App\User::with(['tasks' => function($q) {
$q->first();
}])->paginate();
but the tasks property is empty
My question is how I can get all the users but only with first task and paginate to work?
Tasks table
1 id(Primary) bigint(20) UNSIGNED No None AUTO_INCREMENT
2 created_at timestamp Yes NULL
3 updated_at timestamp Yes NULL
4 task_name varchar(255) utf8mb4_unicode_ci No None
5 user_id(Index) bigint(20) UNSIGNED No None
Your model relationship is defined incorrectly. You have associated a User with many Users.
https://laravel.com/docs/master/eloquent-relationships#one-to-many
public function tasks() {
// a User ($this) has many Tasks
return $this->hasMany('App\Task');
}
Also, be careful when using ->first() as the order is not guaranteed unless specified.
$users = \App\User::with(['tasks' => function($q) {
// get the most recently created task
$q->latest()->first();
}])->paginate();
for another example
$getData = $User::where('code_transaction',$code)->first();
$pag = $getData->paginate(10);

Laravel eloquent table joined to itself, how to get 1 array with all values

I am using a table employee that is joined to itself for the manager.
Employee
id
name
manager_id (FK to Employee)
I am using the following model for Employee:
public function my_employees()
{
return $this->hasMany('App\Employee', 'manager_id');
}
public function my_manager()
{
return $this->belongsTo('App\Employee', 'manager_id');
It is working fine because I can use the my_employees function on an employee and it will get me all the records linked to this employee.
Now I would like to get a table with all the employees where the column manager_id is replaced by manager_name. How can I achieve this with Eloquent?
Not using Eloquent, I do:
$employee = DB::table('employee')
->select('employee.id', 'employee.name', 'employee.manager_id','manager.name AS manager_name')
->join('employee AS manager', 'employee.manager_id','=','manager.id');
This gets me of course what I want but I would like to understand how to do it with Eloquent only.
Thanks.
Exactly the same way.
$employees = Employee::select('employee.id', 'employee.name', 'employee.manager_id', 'manager.name AS manager_name')
->join('employee AS manager', 'employee.manager_id', '=', 'manager.id')
->get();
You could also do this shown below. But then you need to access the manager name from the relationship object.
$employees = Employee::with('my_manager')->get();
foreach($employees as $employee) {
echo $employee->my_manager->name;
}
Edit
You can add any constraint to the eager loaded relationship.
$employees = Employee::with(['my_manager' => function($query) {
$query->select('manager_id', 'name');
}])->get();

How to select field in another table join by eager loading in Laravel

I got category_to_news and news_main table
category_to_news
news_id int
name varchar
title timestamp
news_main
id int
title varchar
image varchar
created_at timestamp
how to return by news_main's field and category_news's field ? I've tried this method and it's not work
$posts = Categorytonews::with(array(
'Newsmain' => function($query)
{
$query->orderBy('id', 'DESC')->select(array('title', 'id', 'created_at', 'image'));
}
))
->get( );
You need join for this because with() runs another query, so ordering there won't do the job:
$posts = Categorytonews::with('Newsmain') // get all fields from Newsmain
->join('news_main', 'category_to_news.news_id', '=', 'news_main.id') // join for ordering
->orderBy('news_main.id','desc') // order by joined field
->get('category_to_news.*'); // select only main table, you don't need joined fields
// on Categorytonews model - they will be loaded by with()
$posts = Categorytonews::with(array('Newsmain' => function($query)
{
$query->select(array('title', 'id', 'created_at', 'image'))->orderBy('id', 'DESC');
}))->get();

Resources