No data was collected in my relation array in Laravel Eloquent method - php

I used eloquent method in my controller to collect data from my database, but something weird happened. If i use this code below,
$female_old_visitors = Treatment::with('diseases', 'patient', 'insurance', 'referer')
->leftJoin('patients', 'treatments.patient_id', 'patients.id')
->where('treatments.visit_status', 'old')
->where('patients.gender', 'female')
->whereBetween('treatments.date', $date_range)
->get();
i can get all the data that i want include diseases and referer
Collection {#3053 ▼
#items: array:25 [▼
0 => Treatment {#2799 ▼
...
#relations: array:4 [▼
"diseases" => Collection {#3346 ▼
#dates: array:1 [▶]
#cascadeDeletes: array:1 [▶]
#guarded: []
#connection: "mysql"
#table: "diseases"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:32 [▶]
#original: array:32 [▶]
#changes: []
#casts: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#forceDeleting: false
}
"patient" => Patient {#3328 ▶}
"insurance" => Insurance {#3346 ▶}
"referer" => TreatmentReferer {#3138 ▶}
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#forceDeleting: false
}
but when i use other code like this
$common_insurance_old_visitors = Treatment::with('diseases', 'patient', 'insurance', 'referer')
->leftJoin('insurances', 'treatments.insurance_id', 'insurances.id')
->where('treatments.visit_status', 'old')
->where('insurances.id', 1)
->whereBetween('treatments.date', $date_range)
->get();
all the data has been selected or collected except disease and referer
Collection {#3053 ▼
#items: array:25 [▼
0 => Treatment {#2799 ▼
...
#relations: array:4 [▼
"diseases" => Collection {#3246 ▼
#items: []
}
"patient" => Patient {#3328 ▶}
"insurance" => Insurance {#3346 ▶}
"referer" => null
]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#forceDeleting: false
}
i have been checking in my database, that the data is still there and the column is not empty, it should be collected just like the code i use first. Is it because i use left join uncorrectly? i am still new for laravel, thanks for anyone who giving me a solution for this problem
this is my model for Treatment
<?php
namespace App;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Iatstuti\Database\Support\CascadeSoftDeletes;
class Treatment extends Model
{
use SoftDeletes, CascadeSoftDeletes;
protected $dates = ['deleted_at'];
protected $cascadeDeletes = ['medicines', 'actions', 'referer', 'diseases', 'queues'];
protected $guarded = [];
public function queues(){
return $this->hasMany(TreatmentQueue::class);
}
public function treatmentType(){
return $this->belongsTo(TreatmentType::class);
}
public function medicines(){
return $this->hasMany(TreatmentMedicine::class)->with('medicine', 'recu');
}
public function actions(){
return $this->hasMany(TreatmentAction::class)->with('action', 'doctor', 'nurse', 'recu', 'teeth', 'therapy', 'treatmentDisease');
}
public function insurance(){
return $this->belongsTo(Insurance::class);
}
public function referer(){
return $this->hasOne(TreatmentReferer::class)->with('puskesmas', 'disease');
}
public function diseases(){
return $this->hasMany(TreatmentDisease::class)->with('disease', 'doctor', 'teeth');
}
public function patient(){
return $this->belongsTo(Patient::class);
}
}

with() is for eager loading. That basically means, along the main model, Laravel will preload the relationship(s) you specify. This is especially helpful if you have a collection of models and you want to load a relation for all of them. Because with eager loading you run only one additional DB query instead of one for every model in the collection.
In your example.
you're using left join why? it already contain in with() you use with('patient') it means you join treatments to left join with patient
$female_old_visitors = Treatment::with('diseases', 'insurance', 'referer')
->with(['patient' => function ($q) {
$q->where('gender', 'female');
}])
->where('visit_status', 'old')
->whereBetween('treatments.date', $date_range)
->get();
eager-loads

Related

Laravel ManyToMany withPivot Trying to get property 'started_at' of non-object

I have a simeple ManyToMany relation between 2 models when I try to access a field in my pivot table I get this error:
Trying to get property 'started_at' of non-object
I have followed the instructions on the laravel documentation correctly.
My Models:
Instance:
public function steps(): BelongsToMany
{
return $this->belongsToMany(Step::class)
->using(InstanceStep::class)
->withTimestamps();
}
Step:
public function instances(): BelongsToMany
{
return $this->belongsToMany(Instance::class)
->using(InstanceStep::class)
->withPivot([
'started_at',
'finished_at',
'failed_at',
'output',
])
->withTimestamps();
}
How I try to access 'started_at' of a step:
dd($step->pivot->started_at);
EDIT
private function finishStep(Step $step)
{
dd($step->pivot->started_at);
}
/** #var Step $step */
foreach ($this->workflow->steps as $step) {
StepJob::dispatch($step, $instance);
}
dd($step)
Step {#420 ▼
#table: "workflow_steps"
#fillable: array:6 [▶]
#casts: array:3 [▶]
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:10 [▼
"id" => "ca646f59-b215-41b0-afe6-ea9e6174f4f5"
"workflow_id" => "d786bd13-4111-4199-94d6-c52fef33b78b"
"category" => "transport"
"properties" => "props"
"entity_type" => "App\TransportWorkflowStep"
"entity_id" => "4d32e11c-6453-4f48-9419-7c5cbd647128"
"order" => 1
"created_at" => "2019-07-04 11:19:41"
"updated_at" => "2019-07-04 11:41:16"
"deleted_at" => null
]
#original: array:10 [▶]
#changes: []
#dates: array:1 [▶]
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
#forceDeleting: false
}
Attach step to instance
// set started_at
$workflowInstance->workflowsteps()->attach(
$step,
[
'started_at' => Carbon::now(),
]
);
// do something
// set finished_at when done
dd($step->pivot->started_at);
I did the dd($step->pivot->started_at); to see if i am working with the correct pivot row
You've not specified the relationship you're after, you may access the intermediate table using the pivot attribute on the models:
Try the following code:
private function finishStep(Step $step)
{
foreach ($step->instances as $instance) {
var_dump($instance->pivot->started_at);
}
die();
}
It depends on how declare $step, it gets collection and you have to insert it in foreach loop.
private function finishStep(Step $step)
{
dd($step->pivot->started_at);
}
this doesn't declare $step, you have to declare it first like
$step=Step::where(...)->get();
and then you can dd($step);
in short - object doesn't exist yet

How to transfer one-to-many data from a database to a template in Laravel?

There are many tables. One characterizes the sliders, the other contains information inside these sliders. My task is to transfer all values from tables into one template. That is, when choosing the desired slider from the possible, we were given relevant information.
What has been done:
Tables were connected by a one-to-many method.
Main model
class AdminSlider extends Model
{
public function aboutUs()
{
return $this->hasMany('App\AboutUs');
}
public function mainSlider()
{
return $this->hasMany('App\MainSlider');
}
}
Dependent models looks like
class MainSlider extends Model
{
public function adminSlider()
{
return $this->belongsTo('App\AdminSlider', 'slider_id', 'id');
}
}
2. Was created the variable which is working with template in controller
public function index()
{
$adminSlidersItems = $this->getSliderInfo();
$sliderInfo = view('admin.adminEditText')->with('sliderInfo',$adminSlidersItems)->render();
$this->vars = array_add($this->vars, 'sliderInfo', $sliderInfo);
return $this->renderOutput();
}
public function getSliderInfo() {
$sliderInfoItems = $this->as_rep->get();
return $sliderInfoItems;
}
When I looked into variable admin in controller I saw Collection
{#230 ▼
#items: array:6 [▼
0 => AdminSlider {#231 ▼
#connection: "mysql"
#table: "admin_sliders"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:7 [▼
"id" => 1
"title" => "Main Slider"
"path" => "http://jinol/admin/sliders/mainslider"
"img" => "mainslider.jpg"
"alias" => "mainslider"
"created_at" => null
"updated_at" => null
]
#original: array:7 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [▶]
}
1 => AdminSlider {#232 ▶}
2 => AdminSlider {#233 ▶}
3 => AdminSlider {#234 ▶}
4 => AdminSlider {#235 ▶}
5 => AdminSlider {#236 ▶}
]
}
template.layout
#extends('admin.site')
#section('admin.adminNavigation')
{!! $adminNavigation !!}
#endsection
#section('admin.adminEditText')
{!! $sliderInfo !!}
#endsection
Define our variables in template.
#if(count ($sliderInfo) > 0) <br>
<div id="content-page" class="content group"><br>
#foreach($sliderInfo as $info)<br>
<tr><br>
<td class="align-left">{{$info->adminSlider->id}}</td><br>
</tr><br>
#endforeach<br>
</div><br>
#endif
In the end of this I have got an error.
Trying to get property 'id' of non-object (View:
W:\domains\jinol\resources\views\admin\adminEditText.blade.php).
How can I find my mistake?
try
$info->adminSlider['id']
insted of
$info->adminSlider->id
i think it will be solve your problem
In your controller change:
public function index()
{
$adminSlidersItems = $this->getSliderInfo();
$sliderInfo = view('admin.adminEditText')->with('sliderInfo',$adminSlidersItems)->render();
$this->vars = array_add($this->vars, 'sliderInfo', $sliderInfo);
return $this->renderOutput();
}
To:
public function index()
{
$adminSlidersItems = $this->getSliderInfo();
return view('admin.adminEditText', ['sliderInfo' => $adminSlidersItems]);
}
In your view change
<td class="align-left">{{$info->adminSlider->id}}</td><br>
To
<td class="align-left">{{optional($info->adminSlider)->id}}</td><br>
Apparently, not all of your $sliderInfo's have a ->adminSlider defined and you get an error when trying to access id on it when it's set to null. The optional helper will only try to access the id when ->adminSlider is not null.

Laravel 5 returns JSON instead of object on belongsTo() relationship

I have installed Laravel framework v5.3.2 and dimsav/aravel-translatable package v6.0.1. I'm having problem with getting data from belongsTo() relationship (parent) on same model.
Category.php model
class Category extends Eloquent
{
public $translatedAttributes = [
'name', 'slug', 'description'
];
public function category()
{
return $this->belongsTo('App\Model\Category', 'category_id', 'id');
}
public function categories()
{
return $this->hasMany('App\Model\Category', 'category_id', 'id');
}
}
Method for getting list of all categories:
$categoryModel = new Category;
$categories = $categoryModel->with('category.translations')->get();
When I print name attribute in view, Laravel throws exception: "Trying to get property of non-object".
<?php foreach ($categories as $category): ?>
Name: <?php echo $category->category->name; ?>
<?php endforeach; ?>
But when I try to get value as array it works:
<?php foreach ($categories as $category): ?>
Name: <?php echo $category->category['name']; ?>
<?php endforeach; ?>
One more thing, when i try to var_dump($category->category) inside foreach I get this:
object(App\Model\Category)[221]...
Results of dd($category) in view inside foreach:
Category {#231 ▼
#table: "category"
+translatedAttributes: array:4 [▶]
+timestamps: false
#connection: null
#primaryKey: "id"
#keyType: "int"
#perPage: 15
+incrementing: true
#attributes: array:3 [▶]
#original: array:3 [▶]
#relations: array:2 [▼
"category" => Category {#220 ▶}
"translations" => Collection {#228 ▶}
]
#hidden: []
#visible: []
#appends: []
#fillable: []
#guarded: array:1 [▶]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
+exists: true
+wasRecentlyCreated: false
}
So the object exists but Laravel does not show it properly when i try accessing the attribute directly. Anyone knows where the problem is? Is it in Laravel or maybe in laravel-translatable package?
This code returns collection of objects:
$categoryModel->with('category')->get();
But you're trying to use it as object and that's why you're getting the error.
You need to iterate over collection to use objects in it, so try something like this:
#foreach ($categories as $category)
{{ $category->category->name }}
#endforeach

Laravel count amount where the value of a key is true in multidemensional array

I have an array that looks like this when dd'd out :)
array:2 [▼
0 => Comment {#253 ▼
#guarded: []
#table: "comments"
+timestamps: false
#connection: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
#attributes: array:7 [▶]
#original: array:7 [▼
"id" => "1"
"on_projects" => "2"
"from_user" => "19"
"body" => "hi"
"unread" => "1"
"created_at" => "2016-06-13 23:54:39"
"updated_at" => "0000-00-00 00:00:00"
]
#relations: []
#hidden: []
#visible: []
#appends: []
#fillable: []
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
}
1 => Comment {#269 ▶}
]
Now my goal is to count the amount of where the unread key is true.
This is what I've tried but doesn't seem to be working.
$unreads = $comments->where('unread', 1);
dd(count($unreads));
I get this error:
Call to a member function where() on array
Anyone can help me out here?
Many thanks in advance!
EDIT
$uid = Auth::user()->id;
$projects = User::find($uid)->projects;
//comments
if (!empty($projects)) {
foreach ($projects as $project) {
$comments_collection[] = $project->comments;
}
}
if (!empty($comments_collection)) {
$comments = array_collapse($comments_collection);
$unreads = collect($comments)->where('unread', 1)->count();
dd($unreads);
}
This gives me 0 it should give me 2 since I have 2 comments with unread 1
After you've retrieved the data you can collect, filter and count using Illuminate\Collection.
collect($comments)->where('unread', 1)->count();
That said, if your goal is to simply count the data and do nothing else with it, you could achieve this using Eloquent as presumably you've already used a similar query to get the data in the first place.
Comments::where('unread', 1)->count();
Amends based on OP edit.
$projects = Project::with(['comments'])
->where('user_id', Auth::id())
->get();
$count = $projects->sum(function ($project) {
return $project->comments->where('unread', 1)->count();
});
dd($count);
Having thought a bit more about it, as you just want a count (it seems), you can add a relation and an accessor to your Project model.
public function commentsCountUnread() {
return $this->hasOne(Comment::class)
->selectRaw('project_id, count(*) as aggregate')
->where('unread', 1)
->groupBy('project_id');
}
public function getCommentsCountUnreadAttribute()
{
if (! $this->relationLoaded('commentsCountUnread')) {
$this->load('commentsCountUnread');
}
$related = $this->getRelation('commentsCountUnread');
return ($related) ? (int) $related->aggregate : 0;
}
Then you could do something like
$posts = Project::with('commentsCountUnread')->get();
$count = $projects->sum(function($project) {
return $project->commentsCountUnread;
});
dd($count);

Laravel 5 - Undefined property when using relationships

I started with a basic query which returned project data from a table:
$project = Project::find($id);
return view('project.show')->with('project', $project);
And then on my page I dd()'d the $project->id and it worked.
I also now have a table called user.
A project belongs to a user, so I have a relationship set up in my model:
public function user()
{
return $this->belongsTo('App\User');
}
And I then do:
$project = Project::with('user')->where('id', $id)->get();
But I get the error:
Undefined property: Illuminate\Database\Eloquent\Collection::$id
If I just dd() the $project:
Collection {#200 ▼
#items: array:1 [▼
0 => Project {#196 ▼
#fillable: array:1 [▶]
#dates: array:2 [▶]
#connection: null
#table: null
#primaryKey: "id"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:5 [▶]
#original: array:5 [▶]
#relations: array:1 [▶]
#hidden: []
#visible: []
#appends: []
#guarded: array:1 [▶]
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
}
]
}
What am I doing wrong?
To clarify, I want to be able to do:
$project->id
$project->user->name
The get() method will always return an Illuminate\Database\Eloquent\Collection object. This means that your $project variable is a Collection, so when you try $project->id, you're trying to access the id attribute on the Collection, which doesn't exist. This is why you get the error.
There are a couple of different ways to get at what you're trying to do. They are shown in code below. They are all pretty much equivalent.
// This is your code, just added the call to first() on the Collection
// to get the first item in the Collection
$project = Project::with('user')->where('id', $id)->get()->first();
// This is a little more efficient. It is calling first() on the QueryBuilder.
// This will directly return the desired object, without having to create
// an intermediate Collection.
$project = Project::with('user')->where('id', $id)->first();
// This is equivalent to the previous statement, just a little cleaner.
// find() is just a shortcut for where('id', $id)->first().
$project = Project::with('user')->find($id);
All three of the above statements will get you the Project object, which you can then use as you'd like:
$project = Project::with('user')->find($id);
// print the id
echo $project->id.PHP_EOL;
// if the user exists, print the name
if ($project->user) {
echo $project->user->name.PHP_EOL;
}
I would do it like this:
Controller:
Project::where('id', $id)->get();
Model
public function user(){
return $this->belongsTo(User::class);
}
View
#foreach($project as $i)
{{ $i->user->user_id }}
Try something like
$project = Project::with('user')->find($id);

Categories