Can't Retrieve One to Many Relationship Data In Laravel - laravel

I have a bit strange of problem about retrieving one to many relationship data in Laravel.
Model
// JobTypes model
public function jobs()
{
// one type of job has many jobs
return $this->hasMany('App\Jobs', 'id'); // id refer to jobs.id
}
// Jobs model
public function job_types()
{
// one job only belongs to one type of job
return $this->belongsTo('App\jobTypes');
}
Pivot table
Schema::create('jobs_job_types', function (Blueprint $table) {
$table->increments('id');
$table->integer('jobs_id')->unsigned()->nullable();
$table->integer('job_types_id')->unsigned()->nullable();
$table->timestamps();
$table->foreign('jobs_id')->references('id')->on('jobs');
$table->foreign('job_types_id')->references('id')->on('job_types');
});
Controller
$data = \App\JobTypes::paginate($items);
return view('jobs.index', compact('data'))->with(array('showData' => $showData, 'count' => $count))->withItems($items);
View
#foreach($data as $jobType)
<td>
#foreach($jobType->jobs as $category)
{{ $category->name }}
#endforeach
</td>
#endforeach
Am I missing something?

You don't need a pivot table for a one-to-many relationship in Laravel. The child relationship (the "many" side) can simply store the id of the parent model it belongs to.
(See also my comment above about following general Laravel naming conventions.)
Models:
// JobType.php
class JobType extends Model
{
public function jobs()
{
return $this->hasMany('App\Job');
}
}
// Job.php
class Job extends Model
{
public function job_type()
{
return $this->belongsTo('App\JobType');
}
}
Migrations:
// create_job_types_table.php
Schema::create('job_types', function (Blueprint $table) {
$table->increments('id');
...
});
// create_jobs_table.php
Schema::create('jobs', function (Blueprint $table) {
$table->increments('id');
$table->integer('job_type_id')->unsigned()->index();
...
$table->foreign('job_type_id')->references('id')->on('job_types');
});

try like this:
// JobTypes model
public function jobs()
{
// one type of job has many jobs
return $this->hasMany(\App\Job_Type::class, 'job_id');
}
// Jobs model
public function job_types()
{
// one job only belongs to one type of job
return $this->belongsTo('App\jobTypes','job_type_id','id');
}

Related

Summary table for the model

There is a model ObjectType and a model GuestOptions
I want to create a pivot table, I do this
public function up()
{
Schema::create('object_type_options', function (Blueprint $table) {
$table->unsignedBigInteger('object_type_id');
$table->unsignedBigInteger('guest_option_id');
$table->foreign('object_type_id')->references('id')->on('object_types')->onDelete('cascade');
$table->foreign('guest_option_id')->references('id')->on('guest_options')->onDelete('cascade');
$table->primary(['object_type_id','guest_option_id']);
});
}
In the model I define the relation ObjectType , but there is no result
public function options()
{
return $this->belongsToMany(GuestOptions::class,'object_type_options');
}
What am I doing wrong?
Can give two basic and quick solutions.
public function options()
{
return $this->belongsToMany(GuestOptions::class,'object_type_options','object_type_id','guest_option_id');
}
you can also use the relation more clearly like below. but need to change some attributes in the database.
public function options()
{
return $this->belongsToMany(GuestOptions::class);
}
And Table need to change
public function up()
{
//table name changed
Schema::create('guest_options_object_type', function (Blueprint $table) {
$table->unsignedBigInteger('object_type_id');//actual table name
$table->unsignedBigInteger('guest_options_id'); //actual table name
$table->foreign('object_type_id')->references('id')->on('object_types')->onDelete('cascade');
$table->foreign('guest_options_id')->references('id')->on('guest_options')->onDelete('cascade');
$table->primary(['object_type_id','guest_option_id']);
});
}

Can't create one to many relationship on same model

I want to create sponsors users on my website. I use the same model as relationship.
User.php (model):
public function sponsor(): HasMany
{
return $this->hasMany(self::class, 'sponsored_id', 'sponsor_id');
}
public function sponsored(): BelongsTo
{
return $this->BelongsTo(self::class, 'sponsor_id', 'sponsored_id');
}
Sponsor rows :
Schema::table('users', function (Blueprint $table) {
$table->foreignId('sponsor_id')->nullable();
$table->foreignId('sponsored_id')->nullable();
});
My UserSeeder:
$sponsor = User::factory()->create(['name' => 'sponsor']);
$sponsor->sponsor()->save(
User::factory()->make()
);
As per your comment you are trying to retrieve one record from sponser so it should be
$sponsor->sponsor()->first()

Laravel Models and displaying them on view together

For a school assignment we have two tables and models players and countries
I know its either my models or my controller (I've had this problem before but in another assignment their was only one country so i just looped through a country variable and used arrays instead but this wont work for multiple countries)
When I try to display in the view i get "Trying to get property of non-object 'name' on the {{$player->country->name}} and this is the way the teacher has explicitly said we are to display it.
Currently before anything else id like to display all my players and their country names
Models
class Country extends Model
{
//
protected $table = 'countries';
protected $fillable=['name','flag'];
public function player(){
return $this->hasMany(Player::class);
}
}
class Player extends Model
{
//
protected $fillable =['name','age','role','batting','bowling','image','odiRuns','countries_id'];
public function country()
{
return $this->belongsTo(Country::class);
}
}
Tables
public function up()
{
Schema::create('countries', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('flag');
$table->timestamps();
});
}
public function up()
{
Schema::create('players', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('age');
$table->string('role');
$table->string('batting');
$table->string('bowling');
$table->string('image');
$table->string('odiRuns');
$table->integer('countries_id')->unsigned();
$table->foreign('countries_id')->references('id')->on('countries');
$table->timestamps();
});
}
Controller
use App\Player;
use App\Country;
use Illuminate\Http\Request;
class PlayerController extends Controller
{
public function index()
{
//
$players=Player::all();
return view('index',compact('players'));
}
View
#extends('layout')
#section('content')
#foreach ($players as $player )
{{$player->name}}
{{$player->age}}
{{$player->role}}
{{$player->batting}}
{{$player->bowling}}
{{$player->odiRuns}}
{{$player->country->name}}
#endforeach
#endsection
Edit
players all have country id's relating to the countries table
Tables
players table
countries table
The problem is your missing foreign key in relation. When you are defining a relationship, if you explicitly don't tell which foreign key to use for the relationship, Laravel looks for a foreign key like relationname_primarykeyoftheparenttable. In your case its country_id but in your players table the column name is countries_id. So relationship is not building and you are getting error. Change the column name or tell the relationship which foreign key to use to build the relationship.
class Player extends Model
{
protected $fillable =['name','age','role','batting','bowling','image','odiRuns','countries_id'];
public function country()
{
return $this->belongsTo(Country::class,'countries_id');
}
}
Laravel Doc

Eloquent - How to match data between tables of a single ID

Having multiple tables with data that relates to each other, i'm trying to display that data in a view using Laravel.
I must be confused with how Laravel runs its queries and I need help to sort how to do, what in PHP&SQL would be a left join.
My Asset Model:
public function category(){
return $this->hasOne(Category::class);
}
My Category Model:
public function asset()
{
return $this->belongsTo(Asset::class);
}
My Country Model:
public function country()
{
return $this->belongsTo(Asset::class);
}
And my AssetsController:
public function asset($id)
{
$asset = Asset::find($id);
return view('admin.assets.asset')->with('assets', $asset);
}
And the Router:
Route::get('/admin/assets/asset/{id}', [
'uses' => 'AssetsController#asset',
'as' => 'assets.asset'
//Show the Asset
]);
And the View:
<p><strong>Price:</strong>{{$assets->price}} €</p>
<p><strong>Description:</strong>{{$assets->description}}</p>
<p><strong>Country:</strong>{{$assets->country}}</p>
<p><strong>Category:</strong>{{$assets->name}}</p>
So in the 'asset.blade.php' I get the id from a previous index.blade.php that has a list of all the assets. I want to get via the ID, an asset page that displays the category name and the country name, instead of the ID that belongs to the Asset table.
So it should echo something like $assets->country->country_name and $assets->category->name
dd($asset);
EDIT: Additional information about migrations
categories_table migration
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('url');
$table->timestamps();
});
}
assets_table migration:
public function up()
{
Schema::create('assets', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->double('price',15,2);
$table->mediumText('description');
$table->integer('country');
$table->integer('category');
$table->integer('subcategory');
$table->integer('subsubcategory');
$table->integer('broker');
$table->string('featured');
$table->string('slug');
$table->timestamps();
});
}
Got it working.
class Category
{
public function asset()
{
return $this->hasMany(Asset::class);
}
}
class Asset
{
public function category()
{
return $this->belongsTo(Category::class);
}
}
use App\Asset;
use App\Category;
use App\Country;
use App\Subcategory;
use Illuminate\Http\Request;
class AssetController extends Controller
{
public function asset($id)
{
$asset = Asset::find($id);
return view('admin.assets.asset')
->with('asset', $asset)
->with('category', Category::all())
->with('subcategory', Subcategory::all())
->with('country', Country::all());
}
}
The other models have the same relationship towards the Asset model and vice-versa.
The View:
<p><strong>Category:</strong>{{$asset->category->name}}</p>
<p><strong>Sub-Category:</strong>{{$asset->subcategory->name}}</p>
It now shows the name matching the id of the corresponding tables.

Get all categories of post in Laravel

I create a table post__post_category_relations to save categories of post.
Schema::create('post__post_category_relations', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('post_id')->unsinged();
$table->integer('category_id')->unsinged();
$table->timestamps();
});
At blade template edit post, I want show list categories of post.
In Post model I wrote:
public function categories(){
return $this->belongsTo(PostCategoryRelations::class,'id','post_id','category_id');
}
But it only return one category. Can you show me how to show all categories? Thank so much!
This looks similar to Many To Many approach between posts and categories. And a junction table which connects post and category table should have post_id, category_id and other columns are not required like id , timestamps() i guess you won't be using them in your application.
Migration would minimize to
Schema::create('post__post_category_relations', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->integer('post_id')->unsinged();
$table->integer('category_id')->unsinged();
});
For many to many you can add definitions in your models like
class Post extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class, 'post__post_category_relations', 'post_id');
}
}
class Category extends Model
{
public function posts()
{
return $this->belongsToMany(Post::class, 'post__post_category_relations', 'category_id');
}
}
If you still want to keep other columns from junction table post__post_category_relations you can access them by defining as pivot attributes in your model like
class Post extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class, 'post__post_category_relations', 'post_id')
->withPivot('id','cols')
->as('post__post_category_relation_cols');
}
}

Resources