Relationship data to view - Laravel 5.2 - laravel

Having a Problem to output a relationship data to view.
Error message is: "Trying to get property of non-object View".
For explanation all Task depend to a job.
So Task belongsTo Job and Job hasMany tasks.
I have all Relationships in my Models and test it in Tinker everything works.
In my view I Output every Task name and the job name
#foreach ($tasks as $task)
<div class="list-item">
<span class="item-name">{{ $task->job->name }}
<span class="item-name">{{ $task->name}} </span>
</div>
#endforeach
The index function of my TaskController:
public function index(Request $request)
{
$label = Label::all();
$user = User::all();
$task = Task::orderBy('duedate')->get();
$team = Team::all();
$customer = Customer::all();
$status = Status::all();
$job = Job::all();
return view('tasks.index')->with([
'tasks' => $task,
'teams' => $team,
'customers' => $customer,
'labels' => $label,
'users' => $user,
'jobs' => $job,
'statuses' => $status,
]);
}
Table schema / output from tinker
id: 1,
assigned_user_id: 1,
team_id: 4,
name: "Label many to many ",
duration: 2,
created_at: "2016-06-16 14:50:57",
updated_at: "2016-07-05 09:10:34",
job_id: 1,
duedate: "0000-00-00 00:00:00",
status_id: 3,
job: App\Job {#702
id: 1,
name: "quia",
jobnumber: "8076",
customer_id: 2,
status_id: 0,
created_at: null,
updated_at: null,
},
user: null,
Relationships
**Job Model **
class Job extends Model
{
protected $fillable = ['name', 'jobnumber', 'customer_id', 'status_id'];
/**
* Get all Task for Job
*/
public function task()
{
return $this->hasMany(Task::class);
}
Task model
public function job()
{
return $this->belongsTo(Job::class);
}
Hope you can help me, thanks!

With reference to your answer:
In the DB some Task entries had an job_id to an none exisiting Job
You can use has method to limit your results based on the existence of a relationship. see doc for querying relationship absence
$task=Task::orderBy('duedate')->has('job')->get();

This kind o f error occurs when you are trying to print a model value that doesn't exists. Try to print using {{isset($task->job->name)?$task->job->name:'Task without Job'}} and check what it outputs.

You don't load the "job" relationship on $task before trying to access it's values :
public function index(Request $request)
{
$label = Label::all();
$user = User::all();
$task = Task::with('job')->orderBy('duedate')->get(); // loading the relationship
$team = Team::all();
$customer = Customer::all();
$status = Status::all();
$job = Job::all();
return view('tasks.index')->with([
'tasks' => $task,
'teams' => $team,
'customers' => $customer,
'labels' => $label,
'users' => $user,
'jobs' => $job,
'statuses' => $status,
]);
}

Found the solution.
In the DB some Task entries had an job_id to an none exisiting Job, thats it.

Related

laravel-medailibrary getFirstMediaUrl("images") not work for joined tables

I have a problem getting media from a joined table in laravel-medailibrary, I used getFirstMediaUrl("images") to get photos from one table and it works, but if I join two or three tables it not work, how can I solve it?
I want to get photos from those posts that shared by a user.
this post table:
this is share_tb table:
this is users table:
this is the media table:
I find my answer after trying some ways:
public function getPosts(Request $request)
{
$result = [];
$postID = DB::table("share_tb")->where("user_id", Auth::user()->id)->get();
foreach ($postID as $id) {
if (count(Post::where("id", $id->related_id)->get()) > 0) {
$posts = Post::where("id", $id->related_id)->get();
foreach ($posts as $post) {
// $result = $post->getMedia('images');
array_push($result, [
"comment_count" => getTotalComment($post->id),
"course_id" => $post->course_id,
"id" => $post->id,
'post_image' => count($post->getMedia('images')) > 0 ? $post->getMedia('images')[0]->getFullUrl('big') : "",
'logo'=>GetCourseLogo::collection(Course::where('course_id',$post->course_id)->get()),
"post_author" => $post->post_author,
"post_date" => $post->post_date,
"post_excerpt" => $post->post_excerpt,
"post_modified" => $post->post_modified,
"post_parent" => $post->post_parent,
"post_title" => $post->post_title,
"post_type" => $post->post_type,
]);
}
}
}
return Response()->json($result);
}
and by this resource collection, I get the logo:
class GetCourseLogo extends JsonResource
{
public function toArray($request)
{
return $this->getFirstMediaUrl('logo');
}
}

Call to a member function pro_events() on null

Hello I'm trying to fix this issue where the error
Call to a member function pro_events() on null
would not happen all the time. I'm not sure what's causing this.
Any idea how to prevent this error in case it would appear again? We just saw this error in the log but can't duplicate the issue. Thanks!
Organizer.php model
class Organiser extends MyBaseModel
{
protected $rules = [
'org_name' => ['required', 'unique:organisers,name'],
'email' => ['required', 'email', 'unique:organisers'],
'organiser_logo' => ['mimes:jpeg,jpg,png', 'max:10000'],
'terms_agreed' => ['required'],
'org_tags' => ['required'],
];
protected $messages = [
'org_name.required' => 'You must at least give a name for the event organiser.',
'org_name.unique' => 'Your desired organisation name is already taken.',
'organiser_logo.max' => 'Please upload an image smaller than 10Mb',
'organiser_logo.size' => 'Please upload an image smaller than 10Mb',
'organiser_logo.mimes' => 'Please select a valid image type (jpeg, jpg, png)',
];
public function pro_events() {
return $this->hasMany(\App\Models\ProEvent::class)->orderBy('event_date', 'asc');
}
SomeController.php
public function showPackageHome($organiser_id, $event_dummy = null, $event_id = null, $the_country = null, $package_type_id = null, $package_category_id = null)
{
date_default_timezone_set('Europe/London');
$now = Carbon::now();
$cacheKey = md5(vsprintf('%s.%s', [
$organiser_id,
'organiser_cache'
]));
$organiser = Cache::remember($cacheKey, 10, function() use ($organiser_id) {
return Organiser::find($organiser_id);
});
$cacheKey = md5(vsprintf('%s', [
'event_list_cache'
]));
$events = Cache::remember($cacheKey, 1, function() use ($organiser, $now) {
return $organiser->pro_events()
->where("event_status", "live")
->whereDate('event_date', '>=', $now->format("Y-m-d"))
->orderBy('event_date', 'asc')
->get();
});
ProEvent.php model
class ProEvent extends MyBaseModel
{
use SoftDeletes;
protected $table = 'pro_events';
You must go up in the call stack to find where the organizer_id comes from. A possible reason would be that the admin/loggedIn person may change the route manually and try to load an organizer that doesn't exist.
If you have a route like /organizer/{organizer_id}, then you must make sure that the provided ID actually exists in db. One way to do it would be to use findOrFail instead of find and to catch the thrown exception in case the organizer doesn't exist.
public function showPackageHome($organiser_id, $event_dummy = null, $event_id = null, $the_country = null, $package_type_id = null, $package_category_id = null)
{
date_default_timezone_set('Europe/London');
$now = Carbon::now();
$cacheKey = md5(vsprintf('%s.%s', [
$organiser_id,
'organiser_cache'
]));
$organiser = Cache::remember($cacheKey, 10, function() use ($organiser_id) {
return Organiser::findOrFail($organiser_id);
});
$cacheKey = md5(vsprintf('%s', [
'event_list_cache'
]));
$events = Cache::remember($cacheKey, 1, function() use ($organiser, $now) {
return $organiser->pro_events()
->where("event_status", "live")
->whereDate('event_date', '>=', $now->format("Y-m-d"))
->orderBy('event_date', 'asc')
->get();
});
}
In your controller method you can actually catch the exception and display something to the user:
public function yourControllerMethod(Illuminate\Http\Request $request)
{
// something more here
try {
$events = $this->showPackageHome($request->get('organizer_id'), /* the other parameters */);
return $this->view(..., ['events' => $events]);
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $ex) {
// The organizer couldn't be found
return redirect()->back()->withErrors(['organizer-not-found' => 'The organizer could not be found'])
}
}
i think it's because the instance of Organizer where you called pro_events() function was null.

How model relationships works with blades?

I have a model 'applicants' and it has a 'belongsTo' relationship with 'BloodGroup' model.
Here is the index function from ApplicantController:
public function index()
{
$user = Auth::user();
// $user = User::find(1);
$applicants = $user->applicants->where('visible', 1);
foreach ($applicants as $applicant) {
$applicant->bloodGroup;
$applicant->fiqa;
$applicant->gender;
}
// return response()->json($applicants);
return view('applicants.index', ['applicants' => $applicants]);
}
Here is the response that I get from the API:
{
"1": {
"id": 4,
"blood_group_id": 1,
"created_at": "2019-04-22 13:24:16",
"updated_at": "2019-04-26 10:21:41",
"blood_group": {
"id": 1,
"name": "A+",
"visible": 1,
"created_at": "2019-04-22 08:21:19",
"updated_at": "2019-04-22 08:21:19"
}
}
}
But when I pass data to the view. It generates an error in the following lines:
<div class="row mx-4">
<div class="col-06 pr-3">
<p class="h5">Name:</p>
</div>
<div class="col-06">
<p><?php echo e($applicant->blood_group->name); ?></p>
</div>
</div>
BloodGroup Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class BloodGroup extends Model
{
public function applicants()
{
return $this->hasMany('App\Applicant');
}
}
BloodGroup relationship in Applicants table:
public function bloodGroup()
{
return $this->belongsTo('App\BloodGroup');
}
Can you please point out what I'm doing wrong and how this should be done.
As your relationship suggests
public function bloodGroup()
{
return $this->belongsTo('App\BloodGroup');
}
for a particular applicant, $applicant = Applicant::find(1);, you will be able to get bloodGroup like $applicant->bloodGroup, now you should be able to get the name with $applicant->bloodGroup->name.
Your code should be
public function index()
{
$user = Auth::user();
$applicants = $user->applicants()->where('visible', 1)->get();
return view('applicants.index', ['applicants' => $applicants]);
}
In your view
#foreach ( $applicants as $applicant )
{{ $applicant->bloodGroup->name }}
#endforeach
#swonder's concern
>>> App\User::find(1)->roles->where('role_id', '<', 1)
=> Illuminate\Database\Eloquent\Collection {#3178
all: [
App\models\Role {#3166
id: 1,
name: "super-admin",
display_name: "Super Admin",
description: "This will be one permission, that can not be assigned or
modified.",
created_at: "2019-01-11 19:06:23",
updated_at: "2019-01-11 19:06:23",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#3141
user_id: 1,
role_id: 1,
},
},
],
}
yes #swonder is correct, you should use
$user->applicants()->where('visible', 1)->get();
and not $user->applicants->where('visible', 1) instead you may try collection where with all() or get(), but you may not prefer that after looking into below observation
>>> App\User::find(1)->roles->where('role_id', '=', 1)
=> Illuminate\Database\Eloquent\Collection {#3160
all: [],
}
>>> App\User::find(1)->roles->whereStrict('role_id', '=', 1)
=> Illuminate\Database\Eloquent\Collection {#3163
all: [],
}
>>> App\User::find(1)->roles->whereStrict('role_id', '<', 1)
=> Illuminate\Database\Eloquent\Collection {#3169
all: [],
}
>>> App\User::find(1)->roles->whereStrict('role_id', '>', 1)->all()
=> []
>>> App\User::find(1)->roles->whereStrict('role_id', '>', 1)->all()
>>> App\User::find(1)->roles->whereStrict('role_id', '=', 1)->all()
=> []
>>> App\User::find(1)->roles->whereStrict('role_id', '>', 1)->all()
=> []
What is the error that it says?
return view('applicants.index', ['applicants' => $applicants]);
You are passing applicants to the view but you use $applicant in it. Are you looping over $applicants? If no that's the error.
I'm finding issue with your code, since you're running a query but not actually asking anything out of it here:
$applicants = $user->applicants()->where('visible', 1);
This will need to be come:
$applicants = $user->applicants()->where('visible', 1)->get();
Since you're calling them anyway, perhaps try eager loading the relationships with:
$applicants = $user->applicants()->with('blood_group')->where('visible', 1)->get();
Resulting in your index method to look like this:
public function index()
{
$user = Auth::user();
$applicants = $user->applicants()->with('blood_group')->where('visible', 1)->get();
return view('applicants.index', ['applicants' => $applicants]);
}
Then you can access $applicants in your blade file like so:
#foreach($applicants as $applicant)
<div class="row mx-4">
<div class="col-06 pr-3">
<p class="h5">Name:</p>
</div>
<div class="col-06">
<p>{{$applicant->blood_group->name}}</p>
</div>
</div>
#endforeach
Hope this helps.

Is there any efficient method on how to get id of object to my create method

I am creating a web module, and want to get ID of table licensing level two parse into my create method. Hence each ID of level will have a task and the ID need to be stored within my licensing table as a foreign key which reflects ID in Level Two table. How could I solve this, anyone can give me a good suggestion or way on doing this
public function add_show($id)
{
$level = PreLicensingLevelTwo::where('id', $id)->first();
$level->prelicensingtask = PreLicensingTask::where('pre_licensing_level_two_id', $level->id)->with('staff', 'statusdesc', 'prelicensingtaskstaff')->get();
return view('staff.regulatory.statutory.approval.display',compact('level'));
}
public function create()
{
$staff = Staff::pluck('staff_name');
$status = PreLicensingStatus::pluck('status_description', 'id');
return view('staff.regulatory.statutory.approval.create', compact('staff','status'));
}
public function show($id)
{
$one = PreLicensingLevelOne::where('pre_licensing_main_id', $id)->get();
foreach ($one as $key => $license)
{
$license->two = PreLicensingLevelTwo::where('pre_licensing_level_one_id', $license->id)->get();
}
$rendered = view('staff.regulatory.statutory.approval.show')->with('one', $one)->render();
return response()->json(array('status' => 1, 'tableData' => $rendered));
}
With help from my working collegue this is how i able to solve the question i asked
public function store(Request $request)
{
$this->validate($request, [
'task_title' => 'required',
'task_description' => 'required',
'task_due_date' => 'required',
]);
$leveltwo = PreLicensingLevelTwo::find($request->input('pre_licensing_level_two_id'));
$prelicensingtask = new PreLicensingTask;
$prelicensingtask->task_title =$request->input('task_title');
$prelicensingtask->task_description =$request->input('task_description');
$prelicensingtask->task_due_date =$request->input('task_due_date');
$prelicensingtask->created_by_staff_id = Auth::user()->ref_user->staff_id;
$prelicensingtask->status = $request->input('status');
$prelicensingtask->pre_licensing_level_two_id = $leveltwo->id;
$prelicensingtask->pre_licensing_level_one_id = $leveltwo->pre_licensing_level_one_id;
$prelicensingtask->pre_licensing_main_id = $leveltwo->pre_licensing_main_id;
$prelicensingtask->centre_id = Auth::user()->ref_user->centre_id;
$prelicensingtask->save();
return redirect()->back();
}

Validate single rows only when they are present Laravel

So i have a model named Customer.
The db the Customer looks like this:
id, name, lastName, personal, address, zip, location, phones, emails updated_at, created_at
Emails and Phones is special rows because they are store as an json object example
['john#doe.com', 'some#othermail.com', 'more#mails.com']
I use the Customer Model to store the validation rules and custom messages like this
<?php
class Customer extends BaseModel
{
public function validationRules()
{
return array(
'name' => 'required|max:255',
'lastName' =>'max:255',
'personal'=> 'integer',
'location' => 'max:255',
'address' => 'max:255',
'zip' => 'required|integer',
'phones' => 'betweenOrArray:8,10|required_without:emails',
'emails' => 'emailOrArray'
);
}
public function validationMessages()
{
// returns Validation Messages (its too much to write down)
}
}
The OrArray Rule is found here https://stackoverflow.com/a/18163546/1430587
I call them through my controller like this
public function store()
{
$customer = new Customer;
$messages = $customer->validationMessages();
$rules = $customer->validationRules();
$input['name'] = Input::get('name');
$input['lastName'] = Input::get('lastName');
$input['personal'] = preg_replace("/[^0-9]/", "", Input::get('personal'));
$input['location'] = Input::get('location');
$input['address'] = Input::get('address');
$input['zip'] = Input::get('zip');
$input['emails'] = Input::get('emails');
$input['phones'] = Input::get('phones');
foreach($input['phones'] as $i => $value)
{
$input['phones'][$i] = preg_replace("/[^0-9]/", "", $value);
}
$validator = Validator::make($input, $rules, $messages);
}
This all works just fine, but I want to be able to PUT/PATCH request to update a single row.
But the validationRules has Required on certain fields so when its not present i cant update that single row. Without getting an error that the other fields (witch I'm not posting) is required.
How would I best approach this ?
You should get that instance of the model that represent the row you want to edit, that's why the resource controller's update method has a parameter that is the resource you want to edit.
public function update($resourceId) {
$customer = Customer::where('id', '=', $resourceId);
}
Now this customer has all the attributes you set before, so you can access them like:
$customer->name;
$customer->lastName;
So when you valide the values you can use the existing values in your validator where the input is empty:
$input['name'] = (Input::get('name')) ? (Input::get('name')) : $customer->name;
Or a prettier solution with the elvis operator:
$input['name'] = (Input::get('name')) ?: $customer->name;
I came up with another solution to this problem that works very well and its much cleaner.
$customer = Customer::find($id);
$input = Input::except('_method', '_token');
$customer->fill($input);

Resources