So i have relationship declared on the parents Model as
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Parents extends Model
{
protected $fillable = [
'firstName',
'middleName',
'lastName',
'phoneNumber',
'gender',
];
public function students(){
return $this->belongsToMany('App\Student','parent_student','parentId','studentId');
}
}
with the anchor table parent_student and a students table with the column classId. here is the students model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
//
protected $fillable = [
'firstName',
'middleName',
'lastName',
'regNo',
'gender',
'dob',
'classId',
];
public function parents(){
return $this->belongsToMany('App\Parents','parent_student','studentId','parentId');
}
public function classes()
{
return $this->belongsTo('App\Classes','classId');
}
}
what i am tring to achieve is to get the email addresses for parents with students in one class eg class 1, which i pass the classId from a dropdown select in a form on the view to the controller.
Here is my controller.
public function submitEmail(Request $request)
{
$validatedData = $request->validate([
'class' => 'required|integer',
'message' => 'string|max:255',
'subject' => 'string|max:255',
]);
$class = $request->input('class');
$message = $request->input('message');
$subject = $request->input('subject');
$parents = Parents::all();
$parents = Parents::where($parents->students->classId,"=",$class)->get();
die($parents);
}
I am fairly new to laravel and this is the far i have gone so far.Any suggestions would be much appreciated.(I am using laravel 5.6)
This line
$parents->students
is where your problem is. $parents is a Collection (array) of Parents models, not a single Parents1 model. To get a single classId, you need to use a Loop:
foreach($parents AS $parent){
... // Should be able to access $parent->students without issue;
}
Next, you're trying to access ->classId of $parent->students, which is the same issue. $parent->students is a Collection, and not a single Student2 model. You'd need another loop to get the classId:
foreach($parents AS $parent){
foreach($parent->students AS $student){
... // Should be able to access `$student->classId` without issue
}
}
But, this still doesn't solve your core issue. It's important to know when you're accessing a Collection vs a single Model, so keep that in mind.
All of that aside, it sounds like you're trying to get all the Parents of Students in Class of $class (passed from your <form>). To accomplish this, you can use ->whereHas(), as below:
$parents = Parents::whereHas("students", function($query) use($class){
$query->where("classId", "=", $class);
})->with(["students" => function($query) use($class){
$query->where("classId", "=", $class);
}])->get();
What this does, is queries the parents table for any student records that have a class with an id of $class.
Note that whereHas and with contains the same subquery to constrain and eager-load each Parents collection of Students to what's required.
Sidenote: Your classes() relationship on Student has an issue. Since it's a belongsTo() method, it should be class() (singular), as $student->classes would only return a single Class model.
1 Pay attention to naming conventions. Parents should be Parent; Model names are singular.
2 You named the Student Model right, so be consistent.
Try this query:
$parents = Parents::with(['students' => function($query) use ($class){
$query->where('classId',$class);
}])->get();
Instead of:
$parents = Parents::where($parents->students->classId,"=",$class)->get();
Then instead of die($parents) use dd($parents)
Related
I have three models with some methods like
1.Employee Model
class Employee extends Model
{
protected $fillable = [
'employee_no','card_no','inactivedate', 'activedate', 'status',
];
public function office(){
return $this->hasOne(EmployeeOffice::class);
}
public function section(){
return $this->belongsTo('App\Hrm\Section');
}
}
2.EmployeeOffice Model
class EmployeeOffice extends Model
{
$fillable = ['employee_id','section_id','line_id','join_date','gross','confirm_date'];
public function employee(){
return $this->belongsTo(Employee::class);
}
public function section(){
return $this->belongsTo('App\Hrm\Section');
}
}
3.Section model....
class Section extends Model
{
protected $fillable = ['name','description','status'];
//
}
i need all inactive employee information according to the employee inactive date(from employee model) as well as their all office information from EmployeeOffice model and must be groupBy according to section_id which is (section_id as foreign key) available in EmployeeOffice model.
For that i have to go with some condition like ..
Employee::where('inactivedate','like','%'.$date.'%');
*And need all data from office and employee table
*need section name and grouped by as section name from section model
***please suggest me how can i solve this problem ***
Try this:
$data = Section::with(
array(
'employeeOffice' => function(
$query->with(
'employees' => function(
$query->where('employees.inactivatedate', 'like', '%'.$date.'%'
)
)
)
)
)
->get();
This should give you an array to every section_id. In this array are the employeeOffices (1:n-Relationship). The second query with with will fetch for each employeeOffice the employee who sits in it.
But if you defined the relationships right, this should do the trick to:
Section::with('EmployeeOffice.Employee')->get();
Nested Eager Loading
I have solved my problem by this...
if(Input::has('start') && Input::has('end')){
$start = Carbon::parse(Input::get('start'))->startOfDay();
$end = Carbon::parse(Input::get('end'))->endOfDay();
$start = $start->format('Y-m-d');
$end = $end->format('Y-m-d');
EmployeeOffice::query()->whereHas('employee',function ($query) use ($start,$end){
$query->whereBetween('inactivedate',[$start, $end])->where('status',0);
})->paginate()->groupBy('section_id');
}
Here is the current code I have for the model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Courses extends Model
{
protected $table = 'courses';
foreach ($courses as $course) {
echo $course->course;
}
}
Is this coded correctly? The data is being fetched from the 'courses' table and 'courses' is the name of the column.
I am adding a new feature to my search directory. The profiles contain variables from the database so there is a lot of data being fetched from the same database table. There is one data, however, that is being put into a separate table because it can't fit in the same table as the other data. So I have to figure out a way to fetch that data from the other database table and put it into the profile code.
Here is the controller for the profile page (the snippet that controls the view):
//view school
public function viewschool ($url){
$url ='schools/' . $url;
if (count(School::where('url', '=', $url)->first()) <> 1 ) {
return redirect()->back();
}
$sch = School::where('url', '=', $url)->first();
$articles = posts::where('post_type','article')->where('school',$sch->name)->take(3)->get();
$news = posts::where('post_type','news')->where('school',$sch->name)->take(3)->get();
$others = posts::where('post_type','news')->take(3)->get();
return view('school-info')
->with(array('sch' => $sch,'school_articles' => $articles,'school_news' => $news,'others' => $others));
}
The new data are the school courses. the database table for courses contain columns for school ID (basically the courses are matched up to the ID of the school name they belong to in the schools table) as well as other data such as duration of course and tuition.
Am wondering how do I create the controller code for the school courses?
So first improve your understanding of the Model in Laravel. You just define the properties for your classes there. The foreach is totally out of place there.
An example Model should look like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Course extends Model
{
protected $table = 'courses';
protected $fillable = ['properties'];
}
So you would've start with a "fresh" and ready to use Model. Every Action with your Model you do inside your Controller. But DB Queries you do inside a Repository.
And now regarding your Question:
You can define relationships within Models via e.g.
protected $searchable =
[
'relations' => [
'schools' => [
'foreignKey' => 'school_id',
'foreignField' => 'courses'
]
]
]
Edit: forgot the method inside the model :D
public function schools(): BelongsTo
{
return $this->belongsTo(Schools::class);
}
I am trying to find an easier approach to this simple function I have. Basically what I am doing is dynamically loaded a form that's based on an Eloquent model. I do not want to include certain columns in the model like id's and the created_at and update_at columns. I am able to accomplish this with the following piece of code:
get Controller:
$cms_information = collect(CmsUserInformation::where('users_id', Auth::user()->id)->first()->toArray());
$cms_information->forget('id');
$cms_information->forget('users_id');
$cms_information->forget('created_at');
$cms_information->forget('updated_at');
$cms_information->all();
return view('cms::admin.profile', ['user' => Auth::user(), 'cms_information' => $cms_information]);
Then, I will loop through the fields in a form and post them like so:
Post Controller:
$profile = CmsUserInformation::where('users_id', Auth::user()->id)->first();
$cms_user_information = Input::except('_token', 'email', 'password');
foreach($cms_user_information as $field => $info ) {
$profile->$field = $info;
}
$profile->save();
My Eloquent table:
id
user_id
first_name
last_name
email
created_at
updated_at
This works exactly how I want but I feel like it's a quick and dirty way around using the Eloquent object to accomplish this. Does anyone have a way to accomplish this same thing but only use Eloquent object rather than converting to an array and using the collect() function?
You can use the $hidden property on your Eloquent model:
class CmsUserInformation extends Model
{
protected $hidden = [
'id',
'users_id',
'created_at',
'updated_at',
];
}
This will automatically exclude the given attributes when the models are ultimately serialized.
If you only want to hide it in a specific instance, use the setHidden method:
$info = CmsUserInformation::where('users_id', Auth::id())->first();
$info->setHidden([
'id',
'users_id',
'created_at',
'updated_at',
]);
Use hidden property in the model you are using like this:
class User extends Model{
protected $hidden=[
'id',
'created_at',
'updated_at'
];
...
}
I have three models all related by one-to-many. Category, Subcategory and Style. I have relationships working both ways - though I seem to have a problem accessing related attributes.
After my queries have ran, I'm left with this an instance of Style where 'relations' is an instance of Subcategory, and 'relations' in Subcategory is an instance of Category. Which is all correct.
The problem is that I now seem to not be able to access the related model instances. For example, if I call:
$style->subcategory->name;
I get 'Trying to get property of non-object'. So I tried calling just $style->subcategory and the result is '1'.
Why doesn't $style->subcategory return the instance of the subcategory model? Am I missing something or is my understanding incorrect?
--EDIT--
Models
Category
<?php
namespace Paragon\Products;
use Illuminate\Database\Eloquent\Model as Eloquent;
class Category extends Eloquent {
protected $table = 'product_categories';
protected $fillable = [
'name',
'slug',
'image'
];
public function subcategories() {
return $this->hasMany('Paragon\Products\Subcategory', 'category');
}
}
Subcategory
<?php
namespace Paragon\Products;
use Illuminate\Database\Eloquent\Model as Eloquent;
class Subcategory extends Eloquent {
protected $table = 'product_subcategories';
protected $fillable = [
'category',
'name',
'slug',
'image'
];
public function styles() {
return $this->hasMany('Paragon\Products\Style', 'subcategory');
}
public function category() {
return $this->belongsTo('Paragon\Products\Category', 'category');
}
}
Style
<?php
namespace Paragon\Products;
use Illuminate\Database\Eloquent\Model as Eloquent;
class Style extends Eloquent {
protected $table = 'product_styles';
protected $fillable = [
'subcategory',
'name',
'slug',
'image'
];
public function subcategory() {
return $this->belongsTo('Paragon\Products\Subcategory', 'subcategory');
}
}
Query
$style->where($id, $item)->with('subcategory.category')->first();
Tables
Paragon\Products\Category
ID ...
1
2
Paragon\Products\Subcategory
ID Category ...
1 2
2 2
Paragon\Products\Style
ID Subcategory ...
1 1
2 1
Since the subcategory method in the Style model should refer to a single instance of Subcategory and not a Collection of them, shouldn't I be able to just call attributes the way I am (or am trying to)?
Ok I think I see now what is going on. Your Eloquent model is called subcategory, but so is the foreign key. So when you call
$style->subcategory
That is returning the foreign key instead of the model. To fix this, I'd recommend changing the name of the foreign key id to subcategory_id. If you can't change the database, you could force it to use the model by chaining the method with something like this
$style->subcategory()->first()->name
Edit:
Another idea, you could change the name of the relationship to something like
public function subcategory_item()
{
return $this->belongsTo('Paragon\Products\Subcategory', 'subcategory');
}
Then you ought to be able to properly reference it with
$style->subcategory_item->name
I am taking a shot in the dark here. But I will try and explain how to work with collection and difference between first and get.
$users= $user-> with('images') -> first(); <-- this is first row in the table users, each user has many images.
$users-> username; //works;
$users-> images-> image_name; // wont work , model has many ,
you get error <-- Trying to get property of non-object.
// access the proprety image and loop through the collection of objects.
$images = $user-> images; //
foreach ($images as $image){
echo $image- >image_name;
}
on the other hand if the image did belong to one user and the user has one image. You can access image_name like this
$user -> image(() -> image_name;
in your case
$style -> subcategory() -> name;
to get a style by id with subcategoty
$style -> with('subcategry') -> where('id', $styleId) -> first();
this is my campus model
i have stripped the models for readability
and of course there is join table named as campus_user with id, campus_id, user_id
users can subscribe to campuses
now i want 2 things
1. Get all the users subscribed to a specific campus
2. Check to see if a specific user ( say with id = 1 ) is subscribed to a specific campus ( say with id = 2 )
class Campus extends \Eloquent{
protected $table = "campuses";
public function users(){
return $this->belongsToMany("User");
}
}
// this is my user model
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $table = 'users';
protected $hidden = array('password', 'remember_token');
public function campuses(){
return $this->belongsToMany('\Models\Campus');
}
}
Well the most "Eloquent like" way would be using relationship querying:
http://laravel.com/docs/4.2/eloquent#querying-relations
A simple example would be returning users with any campuses.
// Get users with any campus relationship.
$users = User::has('campuses')->get();
However you need something more powerful.
For 'users' in a specific 'campus'.
// Get 'users' in a 'campus' where the 'name' column equals 'foo'.
$campus = 'foo';
$users = User::whereHas('campuses', function($query) use ($campus) {
$query->where('name', $campus);
})->get();
For a specific 'user' in a specific 'campus' the code would almost be the same.
// Find the 'user' with a primary key of '1' in the 'campus' where
// the 'name' column equals 'foo'.
$primaryKey = 1;
$campus = 'foo';
$users = User::whereHas('campuses', function($query) use ($campus) {
$query->where('name', $campus);
})->find($primaryKey);
As you can see the last example replaced the get() method from the previous example.
You can do the same with the callback in the whereHas() method when you want to query using the primary key. This would result in the following.
...
$query->find($campus);
...
All the methods described above can be found in the Illuminate\Database\Eloquent\Builder class.
I would recommend taking a look at some of the source files to get a better understanding how request are handled.