I'm trying to compare two date columns from different tables.
Here's my model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ExitAccessionGood extends Model
{
protected $fillable = ['exit_accession_id', 'norm_id', 'quantity'];
public function entry_goods()
{
return $this->hasMany('App\EntryAccessionGood', 'norm_id', 'norm_id');
}
public function packagings()
{
return $this->hasMany('App\PackagingItem', 'norm_id', 'norm_id');
}
}
The entry_goods() function gather all "norms" from the entry_accession_goods table that have the same norm_id as in the exit_accession_goods table.
public function entry_goods()
{
return $this->hasMany('App\EntryAccessionGood', 'norm_id', 'norm_id');
}
But it gathers all of them, however I only need the get the ones with the date less or equal to the model's table.
So for example, if there are norm ids 1 and 2 added in the exit_accession_goods table (yesterday), and the same ids (1 and 2) added today in the entry_accession_goods table (today), the function entry_goods() should NOT get the data from the entry_accession_goods table.
This is what I tried:
public function entry_goods()
{
return $this->hasMany('App\EntryAccessionGood', 'norm_id', 'norm_id')
->whereRaw('entry_accession_goods.created_at <= exit_accession_goods.created_at');
}
I'm unable to access the exit_accession_goods.created_at which is the problem, anyone know the solution? Thank you.
You can put it as an eloquent query...
$date = 2020/01/01'
$var = ExitAccessionGood::whereHas('entry_good', function ($query) use ($date) {
$query->where('created_at', '<', $date);
})->get();
That should do what you want, assuming I understood the question
This Correct Relation
public function entry_goods(){
return $this->hasMany('App\EntryAccessionGood', 'norm_id', 'norm_id')
->where(created_at <= $this->attributes['created_at']);
}
Related
I could not find this in the laravel docs on aggregate relationships
I was able to do something like this
private function refreshUsers()
{
$this->users = User::withSum(['taskTimeSessions'=> function ($query) {
$query->whereMonth('created_at',$this->month)
->where('is_reconciled',1);
}],'session_duration_in_seconds')
->get();
}
But now I am trying to query what is the total time a Sprint has or at the very least what the individual tasks inside a sprint have so that I can just sum the total of those somehow.
Sprint has many SprintTasks (pivot table)
SprintTask belongs to one Task
Task has many TaskTimeSessions
So I am trying to go find the total time of the TaskTimeSessions
Sprint::with([
'sprintTasks.task'=> function ($query) {
$query->withSum('taskTimeSessions','session_duration_in_seconds');
}])
->get();
I am not getting any errors, but not finding the result anywhere when dd
I thought i would get lucky and have something like this work
->withSum('sprintTasks.task.taskTimeSessions', 'session_duration_in_seconds')
But I am getting this error
Call to undefined method App\Models\Sprint::sprintTasks.task()
If anyone can help me out with some guidance on how to go about this, even if it doesn't include withSum it would be much appreciated.
As requested, these are the models.
// Sprint
public function sprintTasks()
{
return $this->hasMany(SprintTask::class, 'sprint_id');
}
// SprintTask
protected $fillable = [
'sprint_id',
'task_id',
'is_completed'
];
public function task()
{
return $this->belongsTo(Task::class,'task_id');
}
public function sprint()
{
return $this->belongsTo(Task::class,'sprint_id');
}
// Task
public function taskTimeSessions()
{
return $this->hasMany(TaskTimeSession::class, 'task_id');
}
// TaskTimeSessions
protected $fillable = [
'task_id',
'session_duration_in_seconds'
];
public function task()
{
return $this->belongsTo(Task::class,'task_id');
}
Is it possible to abstract this into the model as like
public function totalTaskTime() {
// using the relationship stuff to figure out the math and return it?
}
Looking for any advice on what the best approach is to do this.
Right now I am literally doing this in the blade and seems very bad
#php
$timeTracked = 0;
foreach ($sprint->sprintTasks as $sprintTask) {
$timeTracked += $sprintTask->task->time_tracked_in_seconds;
}
#endphp
You have a many to many relation between sprint and task
For that you can setup a direct relation belongsToMany with sprint_tasks as the pivot table
// Sprint
public function sprintTasks()
{
return $this->hasMany(SprintTask::class, 'sprint_id');
}
public function tasks()
{
return $this->belongsToMany(Task::class, 'sprint_tasks', 'sprint_id', 'task_id')->withPivot('is_completed');
}
Now you can use that relation to query your needs
Sprint::with(['tasks'=> function ($query) {
$query->withSum('taskTimeSessions','session_duration_in_seconds');
}])
->get();
There is a good package for Laravel for complex relationships - eloquent-has-many-deep. You can use it to build relationships through an unlimited number of tables.
composer require staudenmeir/eloquent-has-many-deep:"^1.7"
Sprint.php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Staudenmeir\EloquentHasManyDeep\HasManyDeep;
use Staudenmeir\EloquentHasManyDeep\HasRelationships;
class Sprint extends Model
{
use HasRelationships;
public function tasks(): BelongsToMany
{
return $this->belongsToMany(Task::class, 'sprint_tasks');
}
public function taskTimeSessions(): HasManyDeep
{
return $this->hasManyDeepFromRelations($this->tasks(), (new Task())->taskTimeSessions());
}
}
Task.php
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Task extends Model
{
use HasFactory;
public function taskTimeSessions(): HasMany
{
return $this->hasMany(TaskTimeSession::class);
}
}
Result:
$sprints = Sprint::withSum('taskTimeSessions', 'session_duration_in_seconds')->get();
I have a registration table where the situation is that I have a table for months and a table for years. The relationship between months and registration is one-to-many and same is the case with years and registration like below:
//Here is the registration migration
public function up()
{
Schema::create('registrations', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('father_name');
$table->string('contact1');
$table->string('contact2')->nullable();
$table->string('address')->nullable();
$table->integer('amount');
$table->integer('day');
$table->unsignedInteger('month_id');
$table->unsignedBigInteger('year_id');
$table->timestamps();
});
}
Below is the Registration model:
class Registration extends Model
{
protected $fillable =
['name', 'father_name', 'contact1', 'contact2', 'address', 'amount',
'day', 'month_id', 'year_id'
];
public function month()
{
return $this->belongsTo(Month::class);
}
public function year()
{
return $this->belongsTo(Year::class);
}
}
This is Month model:
class Month extends Model
{
public function registration()
{
return $this->hasMany(Registration::class);
}
}
This is Year model:
class Year extends Model
{
public function registration()
{
return $this->hasMany(Registration::class);
}
}
Now, when I want to show one registration record with its relationships like below, I get all the registration records instead of one.
public function show(Registration $reg)
{
$registration = $reg::with('month', 'year')->get();
return ['registration' => $registration];
}
When I used with function with modal name then I get all records correctly but when I use it even with the single instance of the modal, I still get all the related records which I don't want. I want to select the Month and Year related to the single instance of the registration.
Any help is appreciated in advance.
This is due to ->get();
in $reg you have one instance but then you do but then you make a new request with ->get(); and get displays all records
Do it like this
public function show($regId)
{
$registration = Registration::with('month', 'year')->findOrFail($regId);
return ['registration' => $registration];
}
You can do it like this:
public function show(Registration $reg)
{
$reg->load(['month', 'year']);
return ['registration' => $reg];
}
You can also remove model binding and use with() for eager loading.
public function show($id)
{
$registration = Registration::with(['year', 'month'])
->firstWhere('id', $id);
return ['registration' => $registration];
}
It think you don't have specified the foreign_key in relation.
Or you have to define the
foreign_key by
class Registration extends Model
{
protected $fillable = [
'name', 'father_name', 'contact1', 'contact2', 'address',
'amount','day', 'month_id', 'year_id'
];
public function month()
{
return $this->belongsTo(Month::class,'month_id');
}
public function year()
{
return $this->belongsTo(Year::class,'year_id');
}
}
May be it will solve your problem.
Actually the get() method will return an array of records that you can loop over and that's why you get them all. Have you tried using the first() method that will return exactly one record.
$registration = $reg::with('month', 'year')->first();
I'm trying to fetch the created_at attribute in the model so I can put it in my relationship.
E.g. rows in exit_accession_goods created today should look at rows in entry_accession_goods that were made today or before it.
Here's what I've tried:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ExitAccessionGood extends Model
{
protected $fillable = ['exit_accession_id', 'norm_id', 'quantity'];
public function entry_goods()
{
return $this->hasMany('App\EntryAccessionGood', 'norm_id', 'norm_id')
->whereDate('created_at', '<=', $this->created);
}
public function packagings()
{
return $this->hasMany('App\PackagingItem', 'norm_id', 'norm_id');
}
public function getCreatedAttribute()
{
return "{$this->created_at}";
}
}
The $this->created returns an empty string.
Try this
public function getCreatedAttribute(){
return $this->attributes['created_at'];
}
I have 2 tables (students, tests) and a pivot table (student_test).
From a specific student, I want to get all rows from the tests including the related columns from student_test. If there are no test results the values of the columns of student_test are NULL.
I have tried to do it like this:
public function all_tests()
{
$collection = new Collection();
foreach (Tests::all() as $test) {
if (($model = $this->tests->find($test->id)) === null) {
$model = $test;
}
$collection->push($model);
}
return $collection;
}
I have the following models.
app/Http/Models/Student.php:
class Student extends Model
{
protected $table = 'students';
// Attributes: id, first_name, last_name
public function tests()
{
return $this->belongsToMany(Test::class);
}
}
app/Http/Models/Test.php:
class Student extends Model
{
protected $table = 'tests';
// Attributes: id, name
public function students()
{
return $this->belongsToMany(Student::class);
}
}
I want to return a collection of Test models with the extra column (test_result) from student_test table.
Laravel is only using the table student_test to get the model either from tests table or students table its not taking any extra columns into account.
I think you need an extra model called Result that has a many to one relation with a test and a one to many relation with a student
Add the model with the result columns
Add this to the Student model
public function results()
{
return $this->hasMany(Result::class);
}
Add this to the Test model
public function results()
{
return $this->hasMany(Result::class);
}
Add this to the Result model
public function test()
{
return $this->belongsTo(Test::class);
}
public function student()
{
return $this->belongsTo(Student::class);
}
And add the correct columns.
This way you can do:
$student->results->whereHas('test', function ($query) use ($test) {
$query->where('id', '=', $test->id);
})->get();
Or:
$test->results->whereHas('student', function ($query) use ($student) {
$query->where('id', '=', $student->id);
})->get();
i think this code can be help you.
you must use 'with' by relation model
$collection = new Collection();
foreach (Tests::all()->with('tests') as $test) {
if (($model = $this->tests->find($test->id)) === null) {
$model = $test;
}
$collection->push($model);
}
return $collection;
Inspired by Mike's solution, I came up with the following:
$student_id = 1;
$test_results = Test::crossJoin('students')
->leftJoin('results', [
['students.id', '=', 'results.student_id'],
['test.id', '=', 'results.test_id'],
])
->where('students.id', $student_id)
->get();
My Model looks like this
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class appraisaltask extends Model
{
//
protected $table = 'empappraisaltask';
/*
* An invoice can has many payments
*
*/
public function ratings(){
return $this->hasMany('App\appraisalrating','empappraisaltask_id')->select(array('comment', 'rating'));
}
}
and I am doing a query in my function like this
public function getUserbasictask(){
$taskwithcomments = appraisaltask::select(array('id','taskname','description','status'))->with( array('ratings' => function($query)
{
// the condition that will be apply on the with relation
$query->where('emp_id','=',Auth::user()->empid);
}))->where('type','=','basic')->get();
return json_encode($taskwithcomments);
}
But I am getting Empty Rating object . ANy suggestion how to do that
If I remove the select() from the rating function in the model I get all the details
Any help would be appreciated
i got your issue,update your ratings function in appraisaltask model
public function ratings()
{
return $this->hasMany('App\appraisalrating','empappraisaltask_id')->select(array('emp_id','comment', 'rating'));
}
and also update query
public function getUserbasictask(){
$taskwithcomments = appraisaltask::select(array('id','taskname','description','status'))
->with(['ratings' => function($query)
{
// the condition that will be apply on the with relation
$query->where('emp_id','=',Auth::user()->empid);
}])->where('type','=','basic')->get();
return json_encode($taskwithcomments);
}
hope it will work.