Laravel hasOne (one to one relationship) - laravel

I am trying to learn Laravel-> one to one relationship.
In given code link(join) should be dependent on name(user2s table) and title(post2s table) but the link(join) is dependent on my_id(user2s table) and title(post2s table)
My full codes
Migrations:-
user2s table
Schema::create('user2s', function (Blueprint $table) {
$table->increments('my_id');
$table->string('name');
$table->string('email');
$table->string('password');
$table->string('remember_token');
$table->timestamps();
});
post2u table:
Schema::create('post2s', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('title');
$table->text('content');
$table->timestamps();
$table->tinyInteger('is_admin');
});
Model User2
protected $primaryKey = 'my_id';
public function postx(){
return $this->hasOne(Post2::class, 'title', 'name');
}
My Route Code
Route::get('user/{id}/post', function($id){
return User2::find($id)->postx;
});
http://localhost:8000/user/abc/post
error: Trying to get property of non-object
user2s table
post2s table

Let me explain what is your issue.
error: Trying to get property of non-object, it means it can't find the result. The result object is null, so when you looking for null->postx, it can't get them anything.
You search for User2::find($id), when you use find(), it is looking for primary key. And you User2 Model primary key is my_id, and you are looking for Post2->title. It not able to find it.
More infor about find()
https://laravel.com/docs/5.5/eloquent#retrieving-single-models
Since you are looking for the Post2 title. And you are referencing from User2. It is not correct.
What you should do is
In your route.php
Route::get('user/{title}/post', function($title){
//return Post2::all();
$post = Post2::with('userx')->where('title', $title)->first();
dump($post);
dump($post->userx)//<- you can get user info via
});
In Post2 Model.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post2 extends Model
{
public function userx(){
return $this->belongsTo(User2::class, 'user_id');
}
}

Related

Do i need a One-to-Many polymorphic relationship?

I've got a problem i can't get through, here are my models:
Cloth.php​
public function selling(): BelongsTo
{
return $this->belongsTo(Selling::class);
}
Selling.php​
public function clothes(): HasMany
{
return $this->hasMany(Cloth::class);
}
​And now it's anything ok and pretty basic... but then came this model:
Accessory.php​
public function selling(): BelongsTo
{
return $this->belongsTo(Selling::class);
}
And now it's the problem: I need (i think) a polymorphic relationship but i can't understand how to make it in this specific case.
I have 2 starting models to morph to 1 model but every example i found have 1 starting model to morph to 2 models.
Do i need a polymorphic relationship?
I can't really get out of this.
Thanks!
You are basically looking for a one to many polymorphic relationship. Here is how to do it:
Let's say your tables are structured like bellow;
Schema::create('sellings', function (Blueprint $table) {
$table->id();
$table->integer('relation_id');
$table->string('relation_type');
$table->timestamps();
});
Schema::create('accessories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('details');
$table->timestamps();
});
Schema::create('cloths', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('description');
$table->timestamps();
});
Selling.php
public function relation(){
return $this->morphTo();
}
Cloth.php
public function selling(){
return $this->morphOne(Selling::class, 'relation');
}
Accessories.php
public function selling(){
return $this->morphOne(Selling::class, 'relation');
}
Then, you can query using bellow approach;
$selling = Selling::findOrFail(1)->relation;
Now when you dd($selling) you get exactly what you are looking for from a correspondent table;
Please remember that the relation_type field needs to exactly correspond the model. See bellow screenshot for example;
What happens here is when you create a polymorphic function called test the database fields need to follow with test_type corresponding to model and test_id corresponding to the id of the model/database table.

Laravel 8 - Foreign key constraint is incorrectly formed

I don't know what's wrong because I'm very new to this.
// Product Model
class Product extends Model
{
use HasFactory;
public function store()
{
return $this->belongsTo(Store::class);
}
}
// Store Model
class Store extends Model
{
use HasFactory;
public function products()
{
return $this->hasMany(Product::class);
}
}
// Products table migration
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->float('price');
$table->string('description');
$table->timestamps();
$table->foreignId('store_id')->constrained()->onDelete('cascade');
});
// Stores table migration
Schema::create('stores', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('image_url');
$table->string('phone');
$table->timestamps();
});
When I run the migration, it gives me this error
I've tried changing the data type of the 'id' but still not working. I've also tried with
$table->foreign('store_id')->references('id')->on('stores')->onDelete('cascade');
but still not working.
What I want is a relation so that when I delete a store, all products that belong the store are also deleted.
Thanks 🙏
Change the name of the stores migration file to a date prior to 2021-07-28 so the table stores is migrated before the table products
Example: 2021_07_27_004700_create_stores_table
Laravel uses the name of the migration files for the order of migration. With the format of the date as the start of the file name, it is dependant on the date of the creation of the file.

issue with laravel elquent relation

I have a column name creator in the table storing the user id. When fetching records, I am using belongs to relation. I receive data, but I am not able to display it.
Note: This thread doesn't solve my issue
Category table scheme
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->unique();
$table->string('slug')->unique();
$table->string('banner')->nullable();
$table->boolean('status')->default(false);
$table->bigInteger('creator');
$table->bigInteger('moderator');
$table->timestamps();
});
user table scheme
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Category Model:
public function creator(){
return $this->hasOne(User::class, 'id', 'creator')->select('id', 'name');
}
Category Controller code:
$records = Category::with(['creator'])->paginate(env('REC_LIMIT'));
data I get it:
"data":[{"id":1,"name":"Uncategorized","slug":"uncategorized","banner":null,"status":1,"creator":{"id":1,"name":"demon slayer"},"moderator":1,"created_at":"2019-11-03 12:08:33","updated_at":"2019-11-04 11:11:01"},
note if with clause is removed in the query, I get:
"data":[{"id":1,"name":"Uncategorized","slug":"uncategorized","banner":null,"status":1,"creator":1,"moderator":1,"created_at":"2019-11-03 12:08:33","updated_at":"2019-11-04 11:11:01"},
in blade file, I what am doing is below code to print creator user name instead of their record id.
$record->creator->name
//or
$record->creator[0]->name
currently i get this:
Facade\Ignition\Exceptions\ViewException
Trying to get property 'name' of non-object (View: /Users/dragonar/Dev/pdp/resources/views/backend/category/index.blade.php)
Have you tried instead of
public function creator(){
return $this->hasOne(User::class, 'id', 'creator')->select('id', 'name');
}
This:
public function creator(){
return $this->hasOne(User::class, 'user_id')->select('id', 'name');
}
Or change the name of the function from creator() to user().
And then in your blade $record->user->name.
This what I found on the laravel docs:
Eloquent determines the foreign key of the relationship based on the model name. In this case, the Phone model is automatically assumed to have a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method: return $this->hasOne('App\Phone', 'foreign_key');
Source
I ended up renaming creator to creator_id and in model, function is creator. like this now i can access desired data $record->creator->name or $record->creator->id.
what i wanted was instead of creator returing me id from original code, i could have been able to do $record->creator->name or $record->creator->id, directly.

Relationship to users table without using the standard 'user_id' column name

I have 2 tables, one has different columns to record different users names based on authorisation level. but i would like to link to two together. at the moment i have tried the following:
User.php
public function approvals()
{
return $this->hasMany(Approval::class);
}
Approval.php
public function qs() {
return $this->belongsTo(User::class, 'id', 'qs');
}
index.blade.php
<td>{{ $approval->qs->name }}</td>
approvals db structure
Schema::create('approvals', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('project_id');
$table->integer('stage');
$table->unsignedBigInteger('qs')->nullable();
$table->unsignedBigInteger('pm')->nullable();
$table->unsignedBigInteger('rcm')->nullable();
$table->unsignedBigInteger('doc')->nullable();
$table->unsignedBigInteger('vpoc')->nullable();
$table->unsignedBigInteger('vpof')->nullable();
$table->timestamps();
});
users db structure
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email', 100)->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Am i going about this all wrong, the qs table column needs to be linking to the users.id?
It seems qs is the user id of the User model. So the relation to the Approval model is
public function qs()
{
return $this->belongsTo(User::class, 'qs');
}
And in User model
public function approvals()
{
return $this->hasMany(Approval::class, 'qs');
}
Now you can use
{{ $approval->qs->name }}
Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with a _ followed by the name of the primary key column. However, if the foreign key on the Model is not parent_id, you may pass a custom key name as the second argument to the belongsTo method.
Laravel Documentation
If a parent model does not use id as its primary key, or you want to join the child model to a different column, you may pass a third argument to the belongsTo method:
public function qs() {
return $this->belongsTo(User::class, 'foreign_key_here_from_child_table', 'custom_column_from_parent_table');
}

Get data from 2 tables connected using a pivot table (Laravel 5.3)

How to get data from 2 tables connected using a pivot table ? for example, in my case I have users table connected to journal table using a pivot table (penulis table). Now I want to get journals data that belonged to specific user. I tried this :
$journal_list = DB::table('journal')->where('id_user', '=','id_journal')->orderBy('id', 'desc')->paginate(20);
That code above doesn't work. Below are my migrations :
Users table :
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('username')->unique();
$table->string('userslug');
$table->string('nameslug');
$table->string('email')->unique();
$table->string('phone')->nullable();
$table->string('address')->nullable();
$table->string('password');
$table->rememberToken();
$table->enum('level', ['admin', 'author']);
$table->timestamps();
});
}
Journal table :
public function up() {
Schema::create('journal', function (Blueprint $table) {
$table->increments('id');
$table->string('title', 255);
$table->text('abstract');
$table->text('file');
$table->integer('id_edition')->unsigned();
$table->string('journalslug');
$table->timestamps();
});
}
Penulis table (the pivot table)
public function up()
{
Schema::create('penulis', function (Blueprint $table) {
// Create tabel penulis
$table->integer('id_user')->unsigned()->index();
$table->integer('id_journal')->unsigned()->index();
$table->timestamps();
// Set PK
$table->primary(['id_user', 'id_journal']);
// Set FK penulis --- user
$table->foreign('id_user')
->references('id')
->on('users')
->onDelete('cascade')
->onUpdate('cascade');
// Set FK penulis --- journal
$table->foreign('id_journal')
->references('id')
->on('journal')
->onDelete('cascade')
->onUpdate('cascade');
});
}
View composer :
public function boot()
{
View::composer('user/show', function ($view) {
$journal_list = User::where('id', $user_id)->with('journal')->first();
$view->with('journal_list', $journal_list);
});
}
If you want to use Eloquent, you should setup belongsToMany() relation first:
class User extends Authenticatable
{
public function journals()
{
return $this->belongsToMany('App\Journal');
}
Then use eager loading to load the data:
User::where('id', $userId)->with('journals')->first();
If you don't want to use Eloquent and just need journals:
$journal_ids = DB::table('penulis')->where('id_user', $userId)->get(['id_journal'])->toArray();
$journal_list = DB::table('journal')->whereIn('id', $journal_ids)->paginate(20);
Or do the same by using join().
Why not make use of the Eloquent if you are using Laravel
First define the relations in your models
class User extends Model {
public function journal(){
return $this->belongsToMany('App\Journal', 'penulis', 'id_user', 'id_journal');
}
}
class Journal extends Model {
public function user(){
return $this->belongsToMany('App\User', 'penulis', 'id_journal', 'id_user');
}
}
Of course you need to define the table and fillables in your model with table name and table columns respectively.
And to get the specific data related to users you can use eloquent,
User::with('journal')->paginate(20);
This will load 20 users(paginated) with related journal data.
To know further about the eloquent relationships, take a look at this link.
Hope it solves your problem.

Resources