Eloquent many to many relationship is always empty - php

I know this question has been asked a lot but all answers didn't seem to work for me - or at least the questions I found were about the pivot table.
I have a many to many relationship (User - Appointment) which is joined by the pivot table "apointment_user", see migrations below.
Schema::create('appointment_user', function (Blueprint $table) {
$table->unsignedInteger('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->unsignedInteger('appointment_id')->nullable();
$table->foreign('appointment_id')->references('id')->on('appointments');
$table->primary(['user_id','appointment_id']);
$table->timestamps();
});
Schema::create('appointments', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->dateTime('date');
$table->string('location');
$table->dateTime('departure');
$table->timestamps();
});
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->date('last_login')->nullable();
$table->rememberToken();
$table->timestamps();
$table->softDeletes();
});
class User extends Model {
protected $with = ['appointments'];
public function appointments() : BelongsToMany {
return $this->belongsToMany(Appointment::class);
}
}
class Appointment extends Model {
public function users() : BelongsToMany {
return $this->belongsToMany(User::class);
}
}
I have a user with the ID 1 and about 10 appointments, which I do attach to the relationship in a seeder. The pivot table has 10 records, as intended (User ID is always 1).
However, if I dump my User object using dd(User::find(1)), the relationship is always an empty collection. However, a 1:n relationship (between a role works well).
Does anybody see what I'm missing? Any help is appreciated.
Many thanks and kind regards
Edit
I just tried some other kind of dumping. I've simply returned my User-Object as JSON-response and there the relationship is filled with 10 appointments... strange.

Though it seems that your table and column names are as Laravel would guess, have you tried expliciting the names?
class User extends Model {
protected $with = ['appointments'];
public function appointments() : BelongsToMany {
return $this->belongsToMany(Appointment::class, 'appointment_user', 'user_id', 'appointment_id');
}
}
class Appointment extends Model {
public function users() : BelongsToMany {
return $this->belongsToMany(User::class, 'appointment_user', 'appointment_id', 'user_id');
}
}

Related

Laravel: Order a model by "Has One Of Many" relationship

I have a customer model that has many contacts. I defined a relationship to get the most recent contact of the customer using the "Has One Of Many" relationship in Laravel 8:
Models
class Customer extends Model
{
use HasFactory;
public function contacts()
{
return $this->hasMany(Contact::class);
}
public function latestContact()
{
return $this->hasOne(Contact::class)->ofMany('contacted_at', 'max')->withDefault();
}
}
class Contact extends Model
{
use HasFactory;
protected $casts = [
'contacted_at' => 'datetime',
];
public function customer()
{
return $this->belongsTo(Customer::class);
}
}
Migration (contact model)
class CreateContactsTable extends Migration
{
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->softDeletes();
$table->foreignID('customer_id');
$table->string('type');
$table->dateTime('contacted_at');
});
}
}
In my view, I want to show all customers and order them by their latest contact. However, I can't figure out how to do that.
I tried to achieve it via the join method but then I obviously get various entries per customer.
$query = Customer::select('customers.*', 'contacts.contacted_at as contacted_at')
->join('contacts', 'customers.id', '=', 'contacts.customer_id')
->orderby('contacts.contacted_at')
->with('latestContact')
Knowing Laravel there must be a nice way or helper to achieve this. Any ideas?
I think the cleanest way to do this is by using a subquery join:
$latestContacts = Contact::select('customer_id',DB::raw('max(contacted_at) as latest_contact'))->groupBy('customer_id');
$query = Customer::select('customers.*', 'latest_contacts.latest_contact')
->joinSub($latestContacts, 'latest_contacts', function ($join){
$join->on([['customer.id', 'latest_contacts.customer_id']]);
})
->orderBy('latest_contacts.latest_contact')
->get();
More info: https://laravel.com/docs/8.x/queries#subquery-joins
I suspect there is an issue with your migration, the foreign key constraint is defined like this:
Check the documentation:
https://laravel.com/docs/8.x/migrations#foreign-key-constraints
Method 1: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->foreignId('consumer_id')->constrained();
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}
Method 2: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('customer_id');
$table->foreign('customer_id')->references('id')->on('customers');
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}

Laravel 8 relationship of three models which belongs to Parent model

Hello everyone I'm currently working on a laravel project where I have a parent table that has the id's of three tables referenced to it. These table migrations also have their models respectively. Here are the table migrations files respectively:
create_products_table.php
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('product_id', 10);
$table->string('product_name');
$table->string('image');
$table->string('images');
$table->string('product_description');
$table->bigInteger('size_id')->unsigned();
$table->string('color');
$table->string('product_quantity');
$table->string('old_price');
$table->string('discount');
$table->string('product_price');
$table->bigInteger('user_id')->unsigned()->nullable();
$table->bigInteger('category_id')->unsigned();
$table->bigInteger('gender_id')->unsigned();
$table->timestamps();
$table->foreign('size_id')->references('id')->on('sizes')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->foreign('gender_id')->references('id')->on('genders')->onDelete('cascade');
});
create_genders_table.php
Schema::create('genders', function (Blueprint $table) {
$table->id();
$table->string('gender_class');
$table->timestamps();
});
create_categories_table.php
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('cat_name');
$table->timestamps();
});
create_sizes_table.php
Schema::create('sizes', function (Blueprint $table) {
$table->id();
$table->string('sizes');
$table->timestamps();
});
Also this is how I defined the relationships on their models respectively
Product.php
public function category()
{
return $this->belongsTo(Category::class);
}
public function gender()
{
return $this->belongsTo(Gender::class);
}
public function size()
{
return $this->belongsTo(Size::class);
}
Category.php
public function products()
{
return $this->hasMany(Product::class);
}
Gender.php
public function products()
{
return $this->hasMany(Product::class);
}
Size.php
public function products()
{
return $this->hasMany(Product::class);
}
I'm actually a laravel beginner and I studied eloquent model relationships at laravel.com so what I did was just based on my understanding of one to many relationships. When I check all my request with dd($request), category_id, gender_id, size_id all show null and I believe it's because I didn't define the relationship properly. Now this is where I seriously need your assistance.
So please my experienced developers I seriously need your help I'll really be grateful if I get your replies today. Thanks in advance.
=>Everything is right, just make changes in the products migration add this code.
$table->foreign('size_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('category_id')->references('id')->on('products')->onDelete('cascade');
$table->foreign('gender_id')->references('id')->on('products')->onDelete('cascade');
=>and migrate table

laravel foreign key for string type (null issue)

I'm trying to get(then display) the creator/author name with foreign key in articles table from users table. I'm merely new with laravel I hope you can help me out with that issue. I have no issue with int type F-key(s) but with string types I'm probably missing something somewhere. Sometimes it's giving me some errors sometimes everything works fine but user_name on articles table is just staying null.
If you need more info about something please leave a comment.
Thanks in advance!
article's Schema
Schema::create('articles', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('user_name')->nullable();
$table->string('title');
$table->text('body');
$table->timestamps();
$table->timestamp('published_at');
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->foreign('user_name')
->references('name')
->on('users')
->onDelete('cascade');
});
user's Schema
Schema::create('users', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name')->unique();
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
Do not save the user name in the article.
You only save the user id and create the relation in the models like
class User extends Model {
public function articles() {
return $this->hasMany('App\Article');
}
}
class Article extends Model {
public function user() {
return $this->belongsTo('App\User');
}
}
If your relations are correct set up you can access the username like this:
$article->user->name
In the other direction you can a users articles with:
$user->articles
Note: The relations are handled like properties and not like functions.
My advice would be...
remove user_name from the article. Let the user_id lead to user data.
use laravel's built in User class which extends Model
make an article class to extend Model
setup relationships between them
App/User.php
namespace App;
use Illuminate\Database\Eloquent\Model;
use ...
class User extends ...{
public function Articles(){
return $this->hasMany(Articles::class)
}
}
App/Article.php
use Illuminate\Database\Eloquent\Model;
namespace App;
class Article extends Model{
public function User(){
return $this->belongsTo(User::class);
}
public function getAuthorAttribute(){
return $this->User->name;
}
}
Now you can access data as...
$user->Articles;
$article->User
$article->author
To refine access, you can get the query builder by calling any relationship as a function.
$user->Articles()->where('title, 'like', 'cars')->get()
To look at what's going on...
$user->Articles()->where('title, 'like', 'cars')->toSql()

Laravel follower/following relationships

I am trying to make a simple follower/following system in laravel, nothing special, just click a button to follow or unfollow, and display the followers or the people following you.
My trouble is I can't figure out how to make the relationships between the models.
These are the migrations:
-User migration:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('email');
$table->string('first_name');
$table->string('last_name');
$table->string('password');
$table->string('gender');
$table->date('dob');
$table->rememberToken();
});
-Followers migration:
Schema::create('followers', function (Blueprint $table) {
$table->increments('id');
$table->integer('follower_id')->unsigned();
$table->integer('following_id')->unsigned();
$table->timestamps();
});
}
And here are the models:
-User model:
class User extends Model implements Authenticatable
{
use \Illuminate\Auth\Authenticatable;
public function posts()
{
return $this->hasMany('App\Post');
}
public function followers()
{
return $this->hasMany('App\Followers');
}
}
-And the followers model is basically empty, this is where I got stuck
I tried something like this:
class Followers extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
but it didn't work.
Also, I'd like to ask if you could tell me how to write the "follow" and "display followers/following" functions. I've read every tutorial I could find but to no use. I can't seem to understand.
You need to realize that the "follower" is also a App\User. So you only need one model App\User with these two methods:
// users that are followed by this user
public function following() {
return $this->belongsToMany(User::class, 'followers', 'follower_id', 'following_id');
}
// users that follow this user
public function followers() {
return $this->belongsToMany(User::class, 'followers', 'following_id', 'follower_id');
}
User $a wants to follow user $b:
$a->following()->attach($b);
User $a wants to stop following user $b:
$a->following()->detach($b);
Get all followers of user $a:
$a_followers = $a->followers()->get();

Laravel one to many relationship results

Hello i am trying to create one to many relationship. One user from user table could have many companies, on other side company could have only one user.
my migration for company table is
public function up()
{
Schema::create('companies', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('address');
$table->string('city');
$table->string('state');
$table->string('contact_person');
$table->string('phone');
$table->string('industry');
$table->string('website');
$table->integer('id_user')->unsigned();
$table->foreign('id_user')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
}
my user model is
/**
* Get the posts for the user.
*/
public function companies()
{
return $this->hasOne('App\Company','user_id');
}
my company model is
public function users()
{
return $this->belongsTo('App\User','id');
}
i am trying to get all companies for specific user
try with whereHas but no data in relation object
$results = Company::whereHas('users', function ($query) {
$query->where('users.id',1);
})->get();
Where is my error?
First thing you should change is companies() relation. It has to be hasMany, not hasOne:
public function companies()
{
return $this->hasMany('App\Company');
}
Then get user with all his companies:
$result = User::where('id', $id)->with('companies')->first();
Or, if you want to use Company model like in your example and get only companies:
$result = Company::where('user_id', $id)->get();
Also, you're using id_user in migration. Change it to user_id.

Categories