Laravel relationship one to one doesnt work with single page view - laravel

I have created two models called video and file using Laravel 6.
A video can have only one file.
This is the relationship I created:
Video
public function file() {
return $this->hasOne('App\File');
}
File model
public function video() {
return $this->hasOne('App\Video');
}
If I loop all videos then I get the related media
#foreach($videos as $video)
{{$video->link->media}}
#endforeach
If I go to the related video single page it doesnt work.
{{$video->link->media}
Here the route:
Route::get('/video/{slug}', 'HomeController#singleVideo')->name('single');
I get following error:
Trying to get property 'media' of non-object
I also add the table Schema:
Schema::create('files', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('media')->default('none');
$table->unsignedBigInteger('video_id');
$table->timestamps();
});
Schema::create('videos', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title',128);
$table->string('slug')->unique();
$table->text('description');
$table->string('url',247);
$table->string('category',128);
$table->unsignedBigInteger('views')->default(200);
$table->string('video_youtube_status')->default('off');
$table->string('video_status')->default('off');
$table->string('status')->default('off');
$table->timestamps();
});
Model Video
protected $guarded = [];
public function file() {
return $this->hasOne('App\File');
}
....

According to the Laravel documentation, the relation "hasOne" is not applied in this way, the primary model(let's say it's File) will have hasOne like in your code, but the secondary Model will have the Inverse Of The Relationship, which is 'belongsTo' so, in your video Model you should write:
public function file() {
return $this->belongsTo('App\File','file_id');
}
This will allows you to access to the entities like:
$video->file->some_property
$file->video->another_property
and another major problem in your videos table:
this table must have a foreign key to files table, which means:
in your videos migration you should add :
$table->unsignedBigInteger('file_id')->nullable(false);
$table->foreign('file_id')->references('id')->on('files');

According to Laravel documentation
You should implement the use of belognsTo relationship
and your query to get your results set must include the use of method with()
$users = User::with('podcasts')->get();
foreach ($users->flatMap->podcasts as $podcast) {
echo $podcast->subscription->created_at;
}

Related

Relationship not working and looking for a strange table name?

I have created a migration for a lookup table with a many to many relationship.
Schema::create('user_partner__organization', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('partner_organization_id');
$table->foreign('user_id')
->references('id')
->on('users');
$table->foreign('partner_organization_id')
->references('id')
->on('partner_organizations');
});
}
Then I am setting up the relationships to be able to go through the user_partner__organization table
In UserPartnerOrganization model
public function partnerOrganizations()
{
return $this->hasMany(PartnerOrganization::class);
}
And in PartnerOrganization
public function userPartnerOrganizations()
{
return $this->belongsToMany(UserPartnerOrganization::class);
}
And finally I am trying to go through the relationship to get a user_id when I know the partner_organization_id which I have in the $organization
$test = $organization
->partnerOrganization()
->first()
->userPartnerOrganizations()
->first();
The partnerOrganization relationship is working nicely but when I try to implement the userPartnerOrganizations I get this error in my log file
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'homestead.partner_organization_user_partner_organization' doesn't exist in /home/vagrant/api/vendor/laravel/framework/src/Illuminate/Database/Connection.php:359
Don't understand where this strange table name is coming from or why the relationship is not working.
since your not following Laravel convention in tables name, you have to provide the pivot table name in relation declaration:
public function partnerOrganizations()
{
return $this->belongsToMany(PartnerOrganization::class,'user_partner__organization','user_id','partner_organization_id');
}
public function userPartnerOrganizations()
{
return $this->belongsToMany(UserPartnerOrganization::class,'user_partner__organization','partner_organization_id','user_id');
}
also note that the relation from both side should be belongsToMany
more about many to many relation in Laravel doc.

Laravel ManyToMany relation with singular table names

I want to create ManyToMany relation between samples and supposed_origins.
In my firm, our convention is to have singular table names, so as mentioned in https://laravel.com/docs/8.x/eloquent#table-names, I defined :
migrations
Schema::create('v3_sample', function (Blueprint $table) {
$table->increments('id');
$table->string('number_canonical', 6)->unique(); // business key
$table->string('name')->nullable();
};
Schema::create('v3_supposed_origin', function (Blueprint $table) {
$table->increments('id');
$table->integer('location_id')->unsigned(); // from other database
$table->string('description');
});
Schema::create('v3_sample_supposed_origin', function (Blueprint $table) {
$table->increments('id');
$table->integer('sample_id')->unsigned();
$table->foreign('sample_id')->references('id')->on('v3_sample')->onDelete('cascade');
$table->integer('supposed_origin_id')->unsigned();
$table->foreign('supposed_origin_id')->references('id')->on('v3_supposed_origin')->onDelete('cascade');
});
models
class Sample extends Model
{
protected $table = 'v3_sample';
public function supposed_origins() {
dd($this);
return $this->belongsToMany('App\SupposedOrigin');
}
}
class SupposedOrigin extends Model
{
protected $table = 'v3_supposed_origin';
public function samples() {
return $this->belongsToMany('App\Sample');
}
}
and controller
class SampleController extends Controller
{
// […]
public function edit(Request $request, $number_canonical)
{
$sample_record = DB::table('v3_sample')->where('number_canonical', $number_canonical)->first();
$supposed_origins = $sample_record->supposed_origins;
dd($supposed_origins); // returns ErrorException Undefined property: stdClass::$supposed_origins
and SampleController returns ErrorException Undefined property: stdClass::$supposed_origins
As I have singular table names, the rule that define to have pivot table with singular table names (sample_supposed_origin) to plural table names (samples and supposed_origins instead of my sample an supposed_origin) are not followed !
Questions :
Is singular naming the reason it can't find the relation?
Is there a way to specify it correctly? Add pivot table model?
Additional informations : Laravel Framework 7.28.4, PHP 8.0.3, mariadb Ver 15.1 Distrib 10.1.47-MariaDB
Your issue is that you are using the Query Builder, and not the Eloquent Query Builder.
DB::table('v3_sample')->where('number_canonical', $number_canonical)->first() will return an object representing the results from the database, but it is just a standard PHP Object.
You want:
Sample::query()->where('number_canonical', $number_canonical)->first()
This will return a Sample Model and you will have access to the relation you need.
In your case $sample_record->supposed_origins.
As #KurtFriars mentionned in his answer, I change my controller to :
public function edit(Request $request, $number_canonical)
{
$sample_record = Sample::query()->where('number_canonical', $number_canonical)->first();
$supposed_origins = $sample_record->supposed_origins;
and previous error disappears but I have an other error :
SQLSTATE[42S02]: Base table or view not found: 1146 Table dbname.sample_supposed_origin' doesn't exist`
To have my supposed_origins, It requires also to improve my Sample model like this :
public function supposed_origins() {
return $this->belongsToMany(
'App\SupposedOrigin',
'v3_sample_supposed_origin',
'sample_id',
'supposed_origin_id'
);
}

laravel hasMany polymorphic relationship in where clause

I am trying to select the picture with the most likes within a specific category from my database. I have a database table storing the pictures and a table storing the likes. The pictures table is related to likeable table through a hasMany polymorphic relationship.
Like model:
public function likeable()
{
return $this->morphTo();
}
Picture model:
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
Home Controller:
Picture::where('picture_type', 'food')->orderBy(likes(), 'desc')->first();
Likeable Migration:
public function up()
{
Schema::create('likeable', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('likeable_id');
$table->string('likeable_type');
$table->timestamps();
});
}
So far, the above line of code, in my home controller returns an error. From what I understand, the likes method has to be called on a specific instance. However, I do not know how to implement this all the while keeping my where clause.
Thank you for your help.
I assume you are wanting to order pictures by the most likes.
In which case, you want something like this:
Picture::withCount('likes')->where('picture_type', 'food')->orderBy('likes_count', 'desc')->first();

Eloquent Relationships Not Working as Expected

I am trying to understand what I am missing here.
Apps migration
Schema::create('apps', function (Blueprint $table) {
$table->increments('id');
$table->integer('show_id')->unsigned()->index();
$table->string('name');
$table->integer('provider_id')->unsigned()->index();
$table->timestamps();
});
Show migration
Schema::create('shows', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
So I create an apps model that has the following function
public function Show() {
return $this->hasOne(Show::class);
}
But in php artisan tinker when I do $app->Show; I get the following error:
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1 no such column: shows.app_id (SQL: select * from "shows" where "shows"."app_id" = 1 and "shows"."app_id" is not null limit 1)'
Am I mis-understanding the relationships?
Your relation should be as:
Apps model:
public function show() {
return $this->hasOne(Show::class, 'id', 'show_id');
}
Or it can be:
public function show() {
return $this->belongsTo(Show::class);
}
Docs
You do not have an app_id in your shows migration.
edit: Taking from the Laravel Docs and changing it to fit your situation
Eloquent determines the foreign key of the relationship based on the model name. In this case, the show model is automatically assumed to have a app_id foreign key.
A one-to-one relationship consists of a hasOne and a belongsTo. The table that contains the foreign key field must be on the belongsTo side of the relationship.
Since your apps table contains the show_id field, it is stated that apps belong to shows, and shows has one (or many) apps.
Given this, you need to change your Show relationship on your Apps model to use the belongsTo relationship.
public function Show() {
return $this->belongsTo(Show::class, 'show_id');
}
Unless you rename your relationship method so that it is lowercase (function show()), the second parameter is required. If you renamed the relationship, Laravel could build the proper key name and you could leave off the second parameter:
public function show() {
// For belongsTo, second parameter defaults to {function_name}_id.
return $this->belongsTo(Show::class);
}
In your apps model :
public function Show() {
return $this->belongsTo('yourmodelnamespace\Show','id','show_id');
}
And you need create Show model too ..
Hope it will works~~
You can use relation like this
public function Show() {
return $this->hasOne(Show::class, 'id','id');
}

How to retrieve Nested Relationship data in laravel 5 using eloquent?

Having some problems retrieving nested relationship data. Here are my models:
class Partner extends Model
{
public function admins()
{
return $this->hasMany(Resource::class)->where('resource_type', 'Admin');
}
}
class Resource extends Model
{
public function details() {
return $this->belongsTo(ResourceDetail::class);
}
}
class ResourceDetail extends Model
{
}
When I try $this->partner->admins[0]->details it's giving null. The sql it generated is: "select * from resource_details where resource_details.id is null". I'm not quite sure why is it null in the query. I must have done something wrong with the relations. I tried $this->partner->with('admins.details')->find($this->partner->id)->toArray();. It's getting the admins, but details is still null. I also tried hasManyThrough, like: return $this->hasManyThrough(ResourceDetail::class, Resource::class)->where('resource_type', 'Admin'); it finds "unknown column". This is my database structure:
Schema::create('partners', function (Blueprint $table) {
$table->increments('id');
});
Schema::create('resources', function (Blueprint $table) {
$table->increments('id');
$table->integer('partner_id')->nullable()->unsigned();
$table->foreign('partner_id')->references('id')->on('partners')
->onUpdate('cascade')->onDelete('set null');
$table->enum('resource_type', constants('RESOURCE_TYPES'))->nullable();
$table->integer('resource_detail_id')->unsigned();
$table->foreign('resource_detail_id')->references('id')->on('resource_details')
->onUpdate('cascade')->onDelete('cascade');
});
Schema::create('resource_details', function (Blueprint $table) {
$table->increments('id');
});
Do I need to change the structure? Or, how can I get the data from current structure? All I want is, a partner has many resources, and a resource has one details.
From that error I think you may be trying to call $this->partner->admins[0]->details from a model that doesn't have an id. What is $this in context to?

Resources