Show second & third model level - laravel

I kow this is known subject discussed but I'm not getting the issue solved.
This is my current app model design:
Institution is the parent model of the app, which has many branches
Branch model has a polymorphic relationship with Building model (child enttity)
Classroom model belongs to Building model (1 Building, M Classroom)
I have a show.blade.php view where I list a Branch and I have 2 tabs for Buildings & Classrooms.
I can show each building for that branch but when I can' get to show all the classrooms in that branch (the relatioship is branch->building->classroom)
I have to solve this with a custom query in controller and then pass the result to the view or there is another approach?
Im trying to show classrooms from each institution ... but classrooms are related to builings.
$a=App\Institution::find(1); //OK
$a->branches; //OK
$a->buildings; //OK
$a->buildings->classrooms //Exception with message 'Property [classrooms] does not exist on this collection instance.
Regards
Institution Model
public function branches()
{
return $this->hasMany(Branch::class);
}
public function buildings()
{
return $this->morphMany('App\Building', 'buildingable');
}
Branch Model
public function institution()
{
return $this->belongsTo(Institution::class);
}
public function buildings()
{
return $this->morphMany('App\Building', 'buildingable');
}
Building Model
public function buildingable()
{
return $this->morphTo();
}
public function classrooms()
{
return $this->hasMany(Classroom::class);
}
Classroom Model
public function building()
{
return $this->belongsTo(Building::class);
}
TABLE STRUCTURES
public function up()
{
Schema::create('institutions', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('inst_name', 30);
$table->string('inst_id_type', 10);
$table->string('inst_id_number', 10);
$table->string('inst_country', 15);
$table->string('inst_type', 15);
});
public function up()
{
Schema::create('branches', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('branch_name', 30);
$table->string('branch_id_type', 10);
$table->string('branch_id_number', 10);
$table->string('branch_country', 15);
$table->string('branch_type', 15);
$table->integer('institution_id');
});
}
public function up()
{
Schema::create('buildings', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('building_name', 30);
$table->integer('buildingable_id');
$table->string('buildingable_type');
});
}
public function up()
{
Schema::create('classrooms', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('classroom_name', 20);
$table->integer('building_id');
$table->integer('employee_id');
});
}

$a->buildings->classrooms is the problem. $a->buildings is a collection, not an eloquent model. To get the classrooms of each building, you could use a foreach loop or the each() function on the connection.
foreach example:
foreach($a->buildings as $building) {
$classrooms = $building->classrooms;
// Do stuff here...
}
each() example:
$a->buildings->each(function ($building) {
$classrooms = $building->classrooms;
// Do stuff here...
}

Related

Laravel: cannot insert into many to many relationship

i hope you're having a good day.
so i have this ManyToMany relationship where a user can apply to multiple jobs, and a job can have multiple applicants (users).
here is the table schema
Schema::create('applicant_job', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('job_id');
$table->unsignedBigInteger('applicant_id');
$table->unique(['job_id', 'applicant_id']);
$table->foreign('job_id')
->references('id')
->on('jobs')
->onDelete('cascade');
$table->foreign('applicant_id')
->references('id')
->on('default_users')
->onDelete('cascade');
});
and here is the model code.
DefaultUser.php
class DefaultUser extends Model
{
public function user()
{
return $this->morphOne(User::class, 'userable');
}
public function applications()
{
return $this->belongsToMany(Job::class, 'applicant_job', 'job_id', 'applicant_id');
}
}
and Job.php
class Job extends Model
{
public function owner()
{
return $this->belongsTo(BusinessUser::class, 'business_user_id');
}
public function applicants()
{
return $this->belongsToMany(DefaultUser::class, 'applicant_job', 'applicant_id', 'job_id');
}
}
everything seems ok and find, however when i try to save ( a user applying to a job), i get the following error
i'm doing so inside ApplyToJobController.php
class ApplyToJobController extends Controller
{
public function store(Job $job, Request $request) {
$default_user = auth()->user()->userable;
$job->applicants()->attach($default_user->id);
return redirect("/en");
}
}
and, Thank you very much for your answers.
EDIT
i have changed the column names to this
Schema::create('applicant_job', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('job_id');
$table->unsignedBigInteger('default_user_id');
$table->unique(['job_id', 'default_user_id']);
$table->foreign('job_id')
->references('id')
->on('jobs')
->onDelete('cascade');
$table->foreign('default_user_id')
->references('id')
->on('default_users')
->onDelete('cascade');
});
it made it work, im curios any idea why?
Try to switch the order of the foreign keys in the applicants relation declared in the Job model like the example below :
public function applicants()
{
return $this->belongsToMany(DefaultUser::class, 'applicant_job', 'job_id', 'applicant_id');
}

Empty array trying to get all the review of product with the product id in the review table

I'm trying to get the review of a product by the product Id in the review table but i do get an empty array or nothing
this are my code.
public function index(Product $product)
{
return $product->reviews;
}
public function product()
{
return $this->belongsTo('App\Model\Product');
}
public function reviews(){
return $this->hasMany(Review::class);
}
migration code
ReviewController
public function up()
{
Schema::create('reviews', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('customer');
$table->integer('star');
$table->text('review');
$table->unsignedBigInteger('product_id')->index();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->timestamps();
});
}
Try this way
$product->with('reviews');

Fetching Relationship Model Data

I have the Below Table Structure
Users table
id- integer
name-string
Casefiles table
id- integer
user_id- foreign_key
name-string
Followups table
id- integer
date- date
casefile_id-foreign_key
I'm using the below Relationship between this models
User.php
public function casefiles()
{
if ($this->hasRole(['sales_executive'])) {
return Casefile::where('user_id', $this->id);
}
}
Casefile.php
public function user()
{
return $this->belongsTo('App\User');
}
public function followups()
{
return $this->hasMany('App\FollowUp');
}
Followup.php
public function casefile()
{
return $this->belongsTo('App\Casefile');
}
I want to fetch Users followups directly. How can i achive this ?
you need to use hasManyThrough() in your User.php you can add this,
public function followUps()
{
return $this->hasManyThrough('App\FollowUp','App\Casefile');
}
then you can normally call the followups using User::with('followUps')->find(1)->followUps
I have noticed that you are checking role in your relationship $this->hasRole(['sales_executive'] this may occur error as you are not if the statement is false. I think you take another approached and handle that as well. for more information on hasManyThrough prefer this link
This should be the case for a HasManyThrough Relationship.
In your case it should be
// Followups migration
Schema::create('followups', function (Blueprint $table) {
$table->bigIncrements('id');
$table->date('date');
$table->unsignedBigInteger('casefile_id')->nullable();
$table->timestamps();
$table->foreign('casefile_id')
->references('id')
->on('casefiles');
});
// Casefile migration
Schema::create('casefiles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->unsignedBigInteger('user_id')->nullable();
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users');
});
// User.php
public function followups() {
return $this->hasManyThrough(FollowUp::class, Casefile::class);
}
// YourController.php
$user = User::all()->first();
dd($user->followups);

accessing nested relationship in laravel 5

i have 3 models like below :
Date
Property
PropertyDetail
and here is my migration for tables i write in order
Date :
public function up()
{
Schema::create('dates', function (Blueprint $table) {
$table->bigIncrements('id');
$table->dateTime('date');
$table->timestamps();
});
}
Property :
public function up()
{
Schema::create('properties', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('type');
$table->text('title');
$table->integer('base_capacity');
$table->timestamps();
});
and PropertyDetail :
public function up()
{
Schema::create('property_details', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('property_id');
$table->string('state');
$table->string('city');
$table->timestamps();
});
}
i tried to remove unnecessarily fields from migration so to keep it clean so here is my 2 relations bettwen date and proeprties
Datemodel :
public function properties() {
return $this->belongsToMany(Property::class);
}
and propery model :
public function dates(){
return $this->belongsToMany(Date::class);
}
public function features(){
return $this->hasMany(Feature::class);
}
ok now finally in my controller i want to do this :
$search = Date::with('properties')
->where('date',$someday)->get()
->and some how here i want to select the city from the property detail table
;
so here is my problem , now i can easily access properties and show thier name but from this relation how can i access features relation and select the city from there should i use joins or some thing there i hope i was clear enough that what i want to do
You can do this:
Property model:
public function details(){
return $this->belongsToMany(Details::class,'property_details','id','property_id');
}
and in Date model:
public function properties() {
return $this->belongsToMany(Property::class);
}
public function propertiesDetails() {
return $this->properties()->with('details');
}
and in your controller you can get detail of properties by use:
$search = Date::with('propertiesDetails')
->where('date',$someday)->get();
now you can access to details of properties.
Hope it helps.

how to get data of other table in laravel 5.2

I am new to Laravel and i am working on the project where i want to retrieve the full details of address table including city name, state name and country name.
In routes following is the code.
$addresses = App\Address::with('countries', 'states','cities')->get();
return $addresses;
when i am running the code i get an error
BadMethodCallException in Builder.php line 2161:
Call to undefined method Illuminate\Database\Query\Builder::countries()
Please help me.
cities table
Schema::create('cities', function (Blueprint $table) {
$table->increments('id');
$table->integer('state_id')->unsigned();
$table->foreign('state_id')->references('id')->on('states');
$table->string('cityName', 50);
$table->timestamps();
});
states Table
Schema::create('states', function (Blueprint $table) {
$table->increments('id');
$table->integer('country_id')->unsigned();
$table->foreign('country_id')->references('id')->on('countries');
$table->string('stateName', 50);
$table->timestamps();
});
countries Table
Schema::create('countries', function (Blueprint $table) {
$table->increments('id');
$table->string('countryName', 50);
$table->timestamps();
});
addresses Table
Schema::create('addresses', function (Blueprint $table) {
$table->increments('id');
$table->integer('country_id')->unsigned();
$table->foreign('country_id')->references('id')->on('countries');
$table->integer('state_id')->unsigned();
$table->foreign('state_id')->references('id')->on('states');
$table->integer('city_id')->unsigned();
$table->foreign('city_id')->references('id')->on('cities');
$table->string('firstLine', 50);
$table->string('secondLine', 50);
$table->string('thirdLine', 50);
$table->string('zipCode', 50);
$table->timestamps();
});
and in models
City
class City extends Model
{
// City belongs to a State
public function city(){
return $this->hasOne('App\State');
}
public function address(){
return $this->belongsTo('Address');
}
}
State
class State extends Model
{
// State has many Cities
public function cities(){
return $this->hasMany('App\City');
}
// State belongs to a Country
public function country(){
return $this->hasOne('App\Country');
}
public function address(){
return $this->belongsTo('Address');
}
}
Country
class Country extends Model
{
// Country has many States
public function states(){
return $this->hasMany('App\State');
}
public function address(){
return $this->belongsTo('Address');
}
}
Address
class Address extends Model
{
// Address has one City
public function cities(){
return $this->hasOne('App\City','city_id');
}
// Address has one State
public function states(){
return $this->hasOne('App\State','state_id');
}
// Address has one Country
public function countries(){
return $this->hasOne('App\Country','country_id');
}
}
Now that we can access all of a post's comments, let's define a
relationship to allow a comment to access its parent post. To define
the inverse of a hasMany relationship, define a relationship function
on the child model which calls the belongsTo method:
Look One To Many
You have one Country has many states and inverse relation is the state has one country.
So you should in model State change method country() like this
public function country(){
return $this->belongsTo('App\Country');
}
and use State::with('country')
P.S.
And check the other models.

Resources