Self Join in Laravel 5.2 - php

I have the following Ticket Table
if(!Schema::hasTable('tblticket')) {
Schema::create('tblticket', function (Blueprint $table) {
$table->increments('TicketID');
$table->string('Subject', 50);
$table->integer('ParentTicketID')->nullable()->unsigned();
$table->timestamps();
$table->foreign('ParentTicketID')->references('TicketID')->on('tblticket');
});
}
Primary Key is TicketID and There is another column called ParentTicketID, which is related to TicketID.
Below is Ticket Model
class TicketModel extends Model
{
public $table = 'tblticket';
public $primaryKey = 'TicketID';
public $timestamps = true;
public function TicketReplies() {
return $this->belongsTo('\App\Models\TicketModel', 'TicketID');
}
}
Below is my Query
$Ticket = \App\Models\TicketModel
::with('TicketReplies')
->where('ParentTicketID', '=', $TicketID)
->first();
I am trying to get all child tickets of a Ticket. but I am getting null.
Can you please guide if I am missing something.

this is my sample code, you can try this, I hope that will help you
/*---------------------------------------------------------
* Relationship with same table, means recursive key
* --------------------------------------------------------
*/
//this will get the childern against parent.
public function doseage_childs(){
return $this->hasMany('App\Models\DoseageForm', 'parent_id', 'id');
}
//this will get the parent against childern
public function doseage_parent(){
return $this->belongsTo('App\Models\DoseageForm', 'parent_id', 'id');
}
Edited
update your this method
public function TicketReplies() {
return $this->belongsTo('\App\Models\TicketModel', 'TicketID');
}
like this
public function TicketReplies() {
return $this->hasMany('\App\Models\TicketModel','ParentTicketID' ,'TicketID');
}
and update your query model like this, because you already getting TicketReplies relationships.
$Ticket = \App\Models\TicketModel
::with('TicketReplies')
->where('TicketID', '=', $TicketID)
->first();
You relationship will works then

Related

Relationship queries in a three-way PivotTable

I had the task of working with a three-sided summary table, but I can not get all the properties and their values for a particular product.
I have three models Product, Property and PropertyValue.
Model Product:
public function properties() :BelongsToMany
{
return $this->belongsToMany(Property::class,'product_property', 'product_id', 'property_id')
->with('values')
->withPivot('property_value_id')
->orderBy('order');
}
public function values() :BelongsToMany
{
return $this->belongsToMany(PropertyValue::class,'product_property', 'product_id', 'property_value_id');
}
Model Property:
public function products() :BelongsToMany
{
return $this
->belongsToMany(Product::class, 'product_property', 'property_id', 'product_id');
}
public function values() :BelongsToMany
{
return $this->belongsToMany(PropertyValue::class, 'product_property','property_id','property_value_id')->withPivot('product_id');
}
Model PropertyValue:
public function properties() :BelongsToMany
{
return $this
->belongsToMany(Property::class, 'product_property','property_id','property_value_id');
}
public function products() :BelongsToMany
{
return $this
->belongsToMany(Product::class, 'product_property','property_value_id','product_id');
}
Pivot table migration product_property:
public function up()
{
Schema::create('product_property', function (Blueprint $table) {
$table->bigIncrements('id');
$table->foreignId('product_id')->constrained()->onDelete('cascade');
$table->foreignId('property_id')->constrained()->onDelete('cascade');
$table->foreignId('property_value_id')->constrained()->onDelete('cascade');
});
}
I can get Product and then get either its properties Property
$product->properties
or only the values of its PropertyValue properties
$product->values
However, I can't get the chain:
Product->This property->The values of these properties for the selected product.
If I do something like
$product->properties()->first()->values
then I get all the PropertyValue selected Property in the pivot table, not for the specifically selected Product.
My task is complicated by the fact that I cannot make any changes to the database.
Please tell me how to get a chain without changing the pivot table
Product->This property->The values of these properties for the selected product.
Try something like this :
$property = $product->properties()->first();
$values = $property->values()->where('product_id', $product->id)->get();
Or like this :
$property = $product->properties()->first();
$values = $property->values()
->join('product_property', 'product_property.property_value_id', '=', 'property_values.id')
->where('product_id', $product->id)
->get();

How to get related records for a single record in Laravel 5.8?

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();

Laravel through model relationships

I have 3 tables with this order:
School it has -> id
SchoolSemester it has -> school_id
SemesterClass it has -> semester_id
Now I am trying to make relation between School and SemesterClass in order to get list of classes of each school as well as name of schools in each class.
based on documentation i have this relationships:
school model
class School extends Model
{
public function semesters() {
return $this->hasMany(SchoolSemester::class);
}
public function classes() {
return $this->hasManyThrough(SemesterClass::class, SchoolSemester::class);
}
}
SchoolSemester model
class SchoolSemester extends Model
{
public function school() {
return $this->belongsTo(School::class);
}
public function classes() {
return $this->hasMany(SemesterClass::class, 'semester_id', 'id');
}
}
SemesterClass model
class SemesterClass extends Model
{
public function school() {
return $this->hasOneThrough(School::class, SchoolSemester::class, 'school_id', 'id');
}
public function semester() {
return $this->belongsTo(SchoolSemester::class, 'semester_id', 'id');
}
}
Controller
public function show($id)
{
$class = SemesterClass::with(['school', 'teacher', 'teacher.user', 'students'])->findOrFail($id);
dd($class);
//return view('admin.Classes.show', compact('class'));
}
Results
Any idea?
Your intermediate table is school_semester, laravel will find the foreign_key school_semester_id by default, however, your foreign_key is semester_id, so you need to specify the foreign_key in hasManyThrough:
public function classes() {
return $this->hasManyThrough(
SemesterClass::class,
SchoolSemester::class
'school_id', // Foreign key on school_semesters table...
'semester_id', // Foreign key on classes table...
'id', // Local key on schools table...
'id' // Local key on school_semesters table...
);
}
And change your hasOneThrough code like this:
public function school() {
return $this->hasOneThrough(
School::class,
SchoolSemester::class,
'id',
'id',
'semester_id',
'school_id' );
}
Another Solution:
Because the reverse is just the concatenation of two BelongsTo relationships, so you can just put the belongsTo in SchoolSemester and School Model.
And get the relationship like this:
SemesterClass::with(['semester.school'])
Or you can define a mutator in SemesterClass Model:
protected $appends = ['school'];
public function getSchoolAttribute() {
return $this->semester->school;
}

How to get all rows from related table including columns from pivot table?

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();

Laravel Defining Relationships

I have one table named Content which is a master table like
Content : id content_name created_at updated_at
and another table Course like
Course table have many content_id
Course : id content_id course_name created_at updated_at
I have created relation like this.
Content Model
class Content extends Eloquent {
protected $table = 'contents';
protected $guarded = array('id');
public function course()
{
return $this->belongsTo('Course');
}
}
Course Model
class Course extends Eloquent {
protected $table = 'courses';
protected $guarded = array('id');
public function content()
{
return $this->hasMany('Content');
}
}
When i am fething the data like this
$courses=Course::find(1)->content;
It throws error like
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'contents.course_id' in 'where clause' (SQL: select * from contents where contents.course_id = 1)
I am unable to rectify the problem in relations as I am new to laravel.
Close, but you have your relationships backwards. The table that has the foreign key is the one that belongsTo the other one. In this case, your course table has the foreign key content_id, therefore Course belongs to Content, and Content has one or many Courses.
class Content extends Eloquent {
public function course() {
return $this->hasMany('Course');
}
}
class Course extends Eloquent {
public function content() {
return $this->belongsTo('Content');
}
}
in your migrations(create_courses_table) , make sure to set the foreign key like that ,
$table->integer('content_id)->unsigned()->index();
$table->foreign('content_id')
->references('id')
->on('contents')
->onDelete('cascade');
I don't really understand your table design, maybe it should be something like this.
Taking your statement: "Course table have many content_id". I perceive that you are saying that 1 course can have multiple content, is that right? If yes, you might want to change your table design to something like below
Course
======
id
course_name
created_at
updated_at
Content
=======
id
course_id (set this as FK)
content_name
created_at
updated_at
migration code for content
public function up()
{
Schema::create('content', function(Blueprint $table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('course_id')->unsigned();
$table->string('content_name');
});
Schema::table('content',function($table)
{
$table->foreign('course_id')->references('id')->on('course')->onDelete('cascade');
});
}
Then in your model
class Course extends Eloquent
{
protected $table = 'course';
public function content()
{
return $this->hasMany('content', 'course_id', 'id');
}
}
class Content extends Eloquent
{
protected $table = 'content';
public function course()
{
return $this->belongsTo('course', 'course_id', 'id');
}
}
Then to access your data via eager loading
$course = Course::with('content')->get();
OR
$content = Content::with('course')->get();
This is about determining associations. Your associations should be:
Content
Content has many courses
class Content extends Eloquent {
protected $table = 'contents';
protected $guarded = array('id');
public function courses()
{
return $this->hasMany('Course');
}
}
Course
The course belongs to content.
class Course extends Eloquent {
protected $table = 'courses';
protected $guarded = array('id');
public function content()
{
return $this->belongsTo('Content');
}
}
So you can do query association.
For finding content -> courses:
$courses = Content::find(1)->courses;
For finding course -> content:
$content = Course::find(1)->content;

Categories