Laravel Eloquent Relationship Many-to-one is not working - laravel

[Laravel 5.7] I have a relationship between two entities (User, Voices) as Many-to-One relationship and it is not working in my project.
Users migration:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('n_name');
$table->string('n_photo');
$table->string('n_gender');
});
Voices migration:
Schema::create('voices', function (Blueprint $table) {
$table->increments('id');
$table->string('voice');
$table->integer('n_id')->unsigned();
$table->foreign('n_id')->references('id')
->on('users')->onDelete('cascade');
});
Users Model:
class User extends Model
{
public function voices(){
return $this->hasMany(Voice::class);
}
}
Voices Model:
class Voice extends Model
{
public function user(){
return $this->belongsTo(User::class, 'n_id');
}
}
And the function "index" in my controller as below:
public function index()
{
$user= User::all();
$voices = $user->voices()::get(); -- error <described below>
return view('index', compact('user', 'voices'));
}
when I want to get the voices for each user it gives me an error says:
"Method Illuminate\Database\Eloquent\Collection::voices does not exist."
My view looks like this:
#if($n->voices)
#foreach($n->voices as $voice)
<audio controls src="voices/{{$voice->voice}}"></audio><br/>
#endforeach
#endif
I hope that I explained the issue very well and Ia waiting for a solution.

Sorry for my previous message, I've just got the issue you had.
You can't fetch relationship on a COLLECTION of entities.
Your controller should look like so:
public function index()
{
$user= User::with('voices')->get();
return view('index', compact('user'));
}
And your blade should look like:
#foreach($users as $user)
#foreach($user->voices as $voice)
<audio controls src="voices/{{$voice->voice}}"></audio><br/>
#endforeach
#endif
Does it work for you?

Try in your controller:
$users = User::with('voices')->get();
I use it that way and it works properly for me.

Related

Can't Retrieve One to Many Relationship Data In 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');
}

Retriving All Polymorphic Relations in Laravel

I've created polymorphic relations in my project. when i want to retrieve them like below
return view('category.index')->with('categories', Category::all()) ;
It returns the relations when i dd() them. However when I want to access the relation in view
when i call it in view it gives me the following result
{"id":1,"image":"abc\/abc.jpg","imageable_id":6,"imageable_type":"App\\Category","created_at":"2020-07-24T13:37:29.000000Z","updated_at":"2020-07-24T13:37:29.000000Z"}
but when i want to access the id or image index it says
Trying to get property 'id' of non-object (View:
D:\WaheedSindhani\Projects\Menu\menu_proj\resources\
views\category\index.blade.php)
i am not picking it up what is happening here
#if(isset($categories))
#foreach($categories as $category)
<tr>
<th scope="row">{{$loop->index+1}}</th>
<td>{{$category->name}}</td>
<td>{{$category->images->image}}</td>
</tr>
#endforeach
#endif
It says no attribute named image found.
Migration are as below
Images Table
public function up()
{
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->string('image');
$table->unsignedInteger('imageable_id');
$table->string('imageable_type');
$table->timestamps();
});
}
Menus Table
public function up()
{
Schema::create('menus', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('visible');
$table->integer('priority');
$table->timestamps();
});
}
Categories Table
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('visibility');
$table->integer('priority');
$table->timestamps();
});
}
Models are as follow
class Menu extends Model
{
public function images()
{
return $this->morphMany( 'App\Image', 'imageable');
}
}
class Image extends Model
{
protected $guarded = [];
public function imageable(){
return $this->morphTo();
}
}
class Category extends Model
{
protected $guarded = [];
public function images()
{
return $this->morphMany(Image::class, 'imageable');
}
}
your problem occurs because the category->images is a Collection of images, not a single image. Because your relation is one to many, not one to one relationship so the soultion would be to loop over the images using a each loop and then do your work there.
that is why you are getting the error that you are trying to access a prop on a non-object.
#if(isset($categories))
#foreach($categories as $category)
<tr>
<th scope="row">{{$loop->index+1}}</th>
<td>{{$category->name}}</td>
#foreach($category->images as $image)
<td>{$image->name}</td>
#endforeach
</tr>
#endforeach
#endif
and this concept is true for every relationship that has a Many in them, hasMany, belongsToMany, etc...

RelationShip Eloquent hasOne

I do not understand how the relationShips are working with Eloquent. Imagine an user with one role. I wrote this in my model User :
public function role()
{
return $this->hasOne('App\Models\Role');
}
And this in my model Role :
public function user()
{
return $this->belongsTo('App\User');
}
After that i would like to retrieve the role of the user connected , like that :
Auth::user()->role->role_name
But it throw an exception :
Undefined column: 7 ERROR: column roles.user_id does not exist
Does it not work like that?
You're missing the user_id foreign column in the roles table, Eloquent assumes that column to exist in order to link a User with a Role
Schema::create('roles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('role_name');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
Update: given a hasOne relationship
App\User model
public function role()
{
return $this->hasOne('App\Models\Role');
}
App\Model\Role model
public function user()
{
return $this->belongsTo('App\User');
}
DatabaseSeeder
$user = factory('App\User')->create();
$user->role()->create([
'role_name' => 'Admin'
]);
routes/web
use Illuminate\Support\Facades\Auth;
Route::get('/', function () {
return Auth::user()->role->role_name;
});
Results => Admin
You should use the belongsTo() relationship in your User model for the role relationship :
public function role()
{
return $this->belongsTo('App\Models\Role');
}

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.

Eloquent Relationship returning empty array

I'm New to laravel and I'm trying to achieve something very basic stuff but still getting stuck.
I have two models namely Post.php and Like.php
I'm trying to fetch all the likes linked to a post using eloquent relationship but it is returning an empty array. Here is my code-
Post.php
public function likes(){
return $this->hasMany('App\Like');
}
Route.php
Route::get('/', function(){
$posts = Post::all()->sortByDesc("post_id");
return view('index')->with(['posts' => $posts]);
});
View.blade.php
#foreach($posts as $post)
{{ $post->likes }}
#endforeach
What am I doing wrong here?
Update-
likes table migration
public function up()
{
Schema::create('likes', function (Blueprint $table) {
$table->increments('like_id');
$table->integer('post_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->foreign('post_id')->references('post_id')->on('posts')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
Post Migration
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('post_id');
$table->integer('user_id')->unsigned();
$table->string('post_message');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
Post Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
public function likes(){
return $this->hasMany('App\Like');
}
}
Laravel expects the primary key to be id, but you are using the custom post_id.
Specify it in your model and adjust the relationship:
class Post extends Model {
protected $primaryKey = 'post_id';
public function likes() {
return $this->hasMany('App\Like', 'post_id');
}
}

Resources