Unable to seed db table with relationship in Laravel - php

In a laravel 5.8 application, I want to seed the users & products table. There is a relationship between the users & products like this
User.php model (users can have one or more products)
public function products()
{
return $this->hasMany(Product::class, 'user_id');
}
Product.php model (a product can belong to one or more users)
public function users()
{
return $this->belongsToMany(User::class);
}
I am trying to use the UsersTableSeeder below to seed both the users table & products table at the same time
public function run()
{
factory(App\User::class, 3)->create()->each(function ($user) {
$user->products()->save(factory(App\Product::class, 3)->make());
});
}
and the 'DatabaseSeeder`looks like this
public function run()
{
$this->call(UsersTableSeeder::class);
}
When I run the command php artisan db:seed, only the users table is seeded and I get this error
Symfony\Component\Debug\Exception\FatalThrowableError : Argument 1 passed to Illuminate\Database\Eloquent\Relations\HasOneOrMany::save() must be an instance of Illuminate\Database\Eloquent\Model, instance of
Illuminate\Database\Eloquent\Collection given, called in C:\Users\Elomena\Projects\Clients\Pramopro\database\seeds\UsersTableSeeder.php on line 15
This is line 15 $user->products()->save(factory(App\Product::class, 3)->make());
I really don't understand why I am getting this error as I have followed the exact thing from the https://laravel.com/docs/5.8/seeding#using-model-factories
Please how should seeding with relationships be done?

This can be solve your problem:
public function run()
{
factory(App\User::class, 3)->create()->each(function ($user) {
$user->products()->saveMany(factory(App\Product::class, 3)->create());
});
}

The error message suggests that you're using a collection instead of a model.
The error is caused by this function, it returns a collection and not a model, because it's a hasMany relationship.
public function products()
{
return $this->hasMany(Product::class, 'user_id');
}
So, you should change your seeder to saveMany instead of save.
public function run()
{
factory(App\User::class, 3)->create()->each(function ($user) {
$user->products()->saveMany(factory(App\Product::class, 3)->create());
}); // ^ saveMany instead of save
}

Related

Accessing an item from a key value pair object derived from a parent relationship

I am trying to implement a created_by column in my users' table.
I created a migration file to add the new column to the users' table:
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedInteger('created_by')->default(0);
});
}
I have a User model which has the following relationships:
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function createdBy()
{
return $this->belongsTo(self::class, 'created_by');
}
In the UsersController, I have this method:
public function view($id)
{
$user = User::with(['roles', 'createdBy'])->where('created_by', Auth::id())->find($id);
return $user;
}
When I return the user variable, I get this result:
Now, I want to access the value from "email" in "created_by". I tried to do this:
return $user->created_by
What I'm getting is 2 but what I want to get is "biodunna#mailnator.com".
I also tried return $user->created_by->email but it returned an error since the result I'm getting from return $user->created_by is just a number.
I want to fetch the email value "biodunna#mailnator.com".
Please change the createdBy relationship function with the createdByUser.
here we just change the function name to avoid conflict between column name and relationship name.
public function createdByUser()
{
return $this->belongsTo(self::class, 'created_by');
}
so now, you can access like
$user->createdByUser->email
According to your JSON response this should work:
$user[0]->created_by->email

Loading values from many-to-many realtionship plus values from auto-generated table in Laravel

I am working on some kind of ambulance app and I need help on how to load relationship.
So, I have table appointment_statuses (and it is populated over the seeder because I need only 3 states - Done, In Progress, Not Performed), I have also the many-to-many relationship between the User model and Appointment model (appointment_user table which holds only IDs of both models) and now I am working on EMR system which means I can check all appointments that patient had in history.
Here is the image of the issue
So under "Status" I want to load name of that ID from appointment_statuses table instead to have only ID.
These tables have this structure:
Appointments
Status
These tables have these values:
Appointments table
Appointment statuses table
These are relations:
User:
public function role()
{
return $this->belongsTo(Role::class);
}
public function patient()
{
return $this->hasOne(Patient::class);
}
public function appointments()
{
return $this->belongsToMany(Appointment::class);
}
Appointment:
public function users()
{
return $this->belongsToMany(User::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class);
}
Appointment_Statuses:
public function patient()
{
return $this->belongsTo(Patient::class);
}
public function appointment()
{
return $this->belongsTo(Appointment::class);
}
Here is a controller which is responsible for emr:
After I have added to controller this:
$user = User::with(['appointments', 'appointments.appointmentStatus'])->where('id', $id)->firstOrFail();
I get this in frontend:
{{ dd($user->toArray()) }}
SOLUTION TO THIS ISSUE
For anyone in future who gets this kind of issue just check the convention about the naming of the foreign keys. In my example, it was the issue, and if you are not sure that your foreign key name is correct then just in the model provide more information like this:
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class,'appointment_statuses_id','id');
}
You can use nested relationship
$user=User::with(['appointments','appointments.appointmentStatus'])
->where('id',$id)
->first();
Also you have to modify relationship
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class,'appointment_statuses_id','id');
}
For anyone in future who gets this kind of issue just check the convention about the naming of the foreign keys. In my example, it was the issue, and if you are not sure that your foreign key name is correct then just in the model provide more information like this:
public function appointmentStatus()
{
return $this->belongsTo(AppointmentStatus::class,'appointment_statuses_id','id');
}

Laravel relationship doesn't return data

I am trying to get my data in table by ajax and it's successfull but some of data are id of other tabels and those data i cannot get somehow!
Example
Sample data returned by JS:
customers":[
{
"id":2,
"group_id":3,
"industry_id":2,
"name":"fwgvwrg",
"companyName":"bget"
}
]
In this data if i use like: i.group.name (same as in blade if we say {{$customer->group->name}} for group_id it returns error of
Uncaught TypeError: Cannot read property 'name' of undefined
Basically there is no issue from JS it's about my models relations here are my models:
Customer model
public function group()
{
return $this->belongsTo(GroupCustomer::class, 'id', 'group_id');
}
public function industry()
{
return $this->belongsTo(Industry::class);
}
Groups model
public function customers() {
return $this->hasMany(Customer::class, 'id', 'group_id');
}
Industry model
public function customers() {
return $this->hasMany(Customer::class);
}
Any idea?
Seems the problem is your model relationship about foreign key parameter position:
public function group()
{
return $this->belongsTo(GroupCustomer::class, 'group_id', 'id');
}
See model doc here
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
In Blade view you can call laravel relationship directly. it will work fine.
but in Js it won't work. you can't call relationship
so when you have to use with() like below
Ex : Customer::with('group')->get();

laravel 5.2 belongsTo relation not work

I'd like to get some additional user information from the divisions table.
But not work why?
BadMethodCallException in Macroable.php line 81: Method division does
not exist.
class AdminsController extends Controller
public function getUserIndex()
{
$users = User::all()->division();
dd($users);
}
class User extends Authenticatable
public function division()
{
return $this->belongsTo('App\Division', 'division_id');
}
class Division extends Model
public function users()
{
return $this->hasMany('App\User');
}
Users table
$table->foreign('division_id')->references('id')->on('divisions')->onUpdate('cascade');
Divisions table
$table->increments('id');
The division() relationship is defined for each individual table row. By calling it on all(), you're attempting to get the relationship for all rows.
You should be able to use something like:
public function getUserIndex()
{
$users = User::all();
foreach ($users as $user) {
dd($user->division());
}
}

Laravel 5.1 eloquent query syntax

I have the following model relationships. If a user logs in as an employee, I want them to be able to get a list of employees for a their company and the roles they have been assigned:
class User {
// A user can be of an employee user type
public function employee()
{
return $this->hasOne('App\Employee');
}
//
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
class Employee {
// employee profile belong to a user
public function user()
{
return $this->belongsTo('App\User');
}
// employee belongs to a company
public function company()
{
return $this->belongsTo('App\Company');
}
}
class Company {
public function employees()
{
return $this->hasMany('App\Employee');
}
}
But the following query doesnt work. I get error Column not found: 1054 Unknown column companies.id in WHERE clause:
$employee = Auth::user()->employee;
$companyEmployees = Company::with(['employees.user.roles' => function ($query) use ($employee) {
$query->where('companies.id', '=', $employee->company_id)
->orderBy('users.created_at', 'desc');
}])->get();
The users and the employees table have a one to one relationship.
All employees have a base role type of employee in addition they may also have other roles such as manager, supervisor etc.
How do I write a query that gives me a company with all its employees and their roles?
I've tried to add a hasManyThrough relation to the Company model but that doesn't work either?
public function users()
{
return $this->hasManyThrough('App\User', 'App\Employee');
}
I think you're ring to get a list of coworkers for the current user and eager load the user and role?
$employee = Auth::user()->employee;
$companyEmployees = Company::with(['employees.user.roles')->find($employee->company_id);
Or perhaps:
$companyEmployees = Company::find($employee->company_id)->employees()->with('user.roles')->get();
$sorted = $companyEmployees->sortBy(function($employee){ return $employee->user->created_at; });
That might be a more direct route. Is your employee id in the user table or vice versa? The eloquent relationships are easy to set backwards.
Users::select('table_users.id')->with('roles')->join('table_employes', function($join) use ($employee) {
$join->on('table_employes.user_id','=','table_users.id')->where('table_employes.company_id', '=', $employee->company_id);
})->orderBy('tables_users.created_at')->get();
1. Create relationship for database table columns in migrtaion :
User Role
$table->foreign('user_id')->references('id')->on('users');
Users
$table->increments('id');
2. Create a model for each database table to define relationship
User.php (model)
public function userRoles()
{
return $this->hasOne('App\UserRoles', 'user_id', 'id');
}
Userroles.php (model)
public function user()
{
return $this->belongsTo('App\User', 'user_id', 'id');
}
3. Let controller handle database calls recommended to use REST api
Controller
use App\User;
use App\UserRoles;
class UserController extends Controller
{
public function index()
{
return User::with('userRoles')->orderBy('users.created_at', 'desc')->paginate(50);
}
}

Categories