Laravel Seeding using Factory for one to one relation - php

I want to create a test data using laravel seed. I can seed for one table. Here is :
ModelFactory.php:
/** #var \Illuminate\Database\Eloquent\Factory $factory */
$factory->define(App\User::class, function (Faker\Generator $faker) {
static $password;
return [
'email' => $faker->unique()->safeEmail,
'password' => $password ?: $password = bcrypt('secret'),
'remember_token' => str_random(10),
'type' => '0'
];
});
UsersTableSeeder.php :
<?php
use Illuminate\Database\Seeder;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run() {
factory(App\User::class, 50)->create()->each(function ($u) {
$u->posts()->save(factory(App\Post::class)->make());
});
}
}
I have two tables which are users and user_information. They have one-to-one relation. I want to seed user_information with users. But i have no idea, how i can do...
My models relation functions :
User.php
public function userInformation() {
return $this->hasOne('App\UserInformation', 'user_id', 'id');
}
UserInformation.php
public function users() {
return $this->belongsTo('App\User', 'user_id', 'id');
}
Laravel version is 5.3
I followed these docs :
https://laravel.com/docs/5.3/seeding
https://laravel.com/docs/5.3/database-testing#writing-factories

Answering because this came up in a Google search and might help others:
AFAIK the model hasn't got anything to do with seeding, that's used for query building and constraints.
What can do is create a user, every time you call on your factory that requires the user_id.
Credit to prodigy10 for this answer.
$factory->define(User_Information::class, function ($faker) use ($factory) {
return [
'name' => $faker->company(),
'user_id' => factory(User::class)->create()->id
];
});

For one-to-one relationships, its good practice to make the relationship methods singular
User.php
public function userInformation()
{
return $this->hasOne('App\UserInformation', 'user_id', 'id');
}
UserInformation.php
public function user()
{
return $this->belongsTo('App\User', 'user_id', 'id');
}
Above solution for Laravel 8, userInformation factory will have :
'user_id' => User::factory()->create()->id,
if you need to create userInformation table only when there's a corresponding user, the above solution will seed new user_ids into the userinformation table and you may end up with more userinformation rows than users. To fix this, you need to seed only UserInformation Factory seeder in DatabaseSeeder run method and not UserFactory. it will automatically seed the users table.
Alternatively, if you have the users table already defined and wants to seed userInformation table for your number of users.
For Laravel 8, its is shown below:
public function definition()
{
$users = User::all();
return [
'name' => $this->faker->company,
'user_id' => $this->faker->unique()->numberBetween(1, $users->count())
];
}
Since its a one to one relationship. You can generate the list of users and use unique and numberBetween functions to fill unique user_ids.

This works in Laravel 9. Amend your DatabaseSeeder.php such as:
public function run()
{
User::factory(10)->create()->each(function ($user) {
$phone = Phone::factory()->make();
$user->phone()->save($phone); // phone() is hasOne ralationship in User.php
});
}
You don't need to define user_id column in PhoneFactory.php. The Laravel automatically saves corresponding user_id in the database.

Related

Data not Saving into pivot table using Laravel Api Resource

please I am new to Laravel, I want to use Laravel API Resource to store database inside database.
I have 3 Tables
Users
Category
Category_User (this is a pivot table)
In my Controller (OnboardsControllers), I have this to store data
public function store(Request $request)
{
$category_user = Category_User::firstOrCreate(
[
'user_id' => $request->user()->id,
'category_id' => $request->$category->id,
],
);
return new CategoryUserResource($category_user);
}
In my CategoryUserResource I have this
public function toArray($request)
{
return [
'user_id' => $this->user_id,
'category_id' => $this->category_id,
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
];
In my Pivot Table, I have this
public function up()
{
Schema::create('category_user', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('category_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->timestamps();
});
}
In my model, I added this
protected $fillable = [
'user_id', 'category_id',
];
In my route/api
Route::post('/category_user', 'OnboardsController#onboardupdate');
I believe the error is here
'user_id' => $request->user()->id,
When I removed it, it didn't returned any error
When I tried to save to my database using Postman to test, it not saving. Please, I don't know what I am doing wrong.
Thanks
To be honest, you do not need a model Category_User (but you need a table).
In Laravel a more concise approach is used:
public function store(Request $request)
{
$user = User::find($request->input('user_id'));
$user->categories()->attach($request->input('category_id'));
}
Also I'm not sure if you have declared a method categories() in model User:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
}
I also strongly doubt the existence of method user() of class Request.
If the request parameter has a name category_id, then you need to access it like this:
$request->input('category_id');

laravel get user id in users table at the time of validation exists|users on call of api?

I have started using laravel and I am loving it.
I write APIs for mobile developers.
I use lot of tables with joins on id_user.
thus I always need id_user.
I have table users which has columns as follows:
1. id
2. token
3. full_name
I do validation as follows:
$result=$request->validate([
'token' => 'required|unique|exists:users'
]
]);
with above code I always get true or false in $result.
but I want the id of this token, which I use as unique in other tables.
thus
I fire the below query as follows:
$users=DB::table('users')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('orders')
->whereRaw('orders.user_id = users.id');
})
->get();
$id_user=$users->id;
but my question is if in laravel validation, "unique|exists:users" checks for unique record existing in users table, and when it finds the record, it validates this constraint and (returns true), it must be storing this unique record somewhere.
Where can I get this record?
If laravel doesn't have this feature they must add it.
Why should I join user table (or fire another query again?) and make the process expensive?
you need to create models and set relationships (User and Order)
class User extends Authenticatable{
protected $fillable = [
'name', 'email','token', 'password',
];
public function order()
{
return $this->hasMany(Order::class);
}
}
class Order extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
set foreign key on orders table
$table->foreign('user_id')->references('id')->on('users');
then this should be the query
'token' => 'required|unique:users|exists:users'
$order = Order::find(1)->user()->where('token_in_orders_table', 'token_in_users_table')->first();
return $order;
Or create a Resource for the Order Model
class OrderController extends Controller
{
public function index(Request $request)
{
//validate token
'token' => 'required|unique:users|exists:users'
//then
return new OrderResource(Order::find(1));
}
}
Resource
class OrderResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'order_details' => $this->order_details,
'user' => $this->user()->where('token', $request->token)->first(),
];
}
}
enter image description here

when register, insert data in 3 tables LARAVEL

I work at a project, I started to learn Laravel and I wanted to create a register form where you can put all your information and all the information to be sent in 3 tables.
You have to select if you are a candidate or a employer.
In my database i have those 3 tables: users, profile_employee and profile_employer.
Can someone show me how to create the RegisterController to insert in the table users only email and password, and if they selected candidate to send the rest of information to profile_employee, and if they selected employer to send them to the table profile_employer. Thanks!
This is are my models for ProfilasdasdasdasdasdasdasdasdasdeEmployeer and ProfileEmployee
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ProfileEmployee extends Model
{
protected $table = 'profasdasdasdasdile_emploasdasdasdasdyee';
protected $fillable = [
'id','usasdasdasder_id', 'fiasdasdasdasdasdst_name', 'laasdasdst_namasdasdasdasdasde','phonasdasdasde', 'casdasdv', 'picasdasdasdasdture', 'adrasdasdasdasdasdess', 'toasdasdasdasdasdasdwn',
];
protected $hidasdasdasdasdasdden = [];
}
and
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ProfileEmployer extends Model
{
protected $tablasdasdasdasde = 'profileasdasdasdasdasdasdasd_emplasdasdasdasdasdasdoyer';
protected $fillabasdasdasdasdle = [
'iasdasdasdd','useasdasdr_iasdasdasdasdasdasd', 'coasdasdasdasdasdmpany_naasdasdasdasdasdme', 'CasdasdasdU_asdasdI', 'phoasdasdasdasdasdne', 'pictasdasdasdasdasdure', 'adasdasdasdasdress', 'towasdasdasdasdasdn',
];
protected $hidasdasdasdden = [];
}
How can I do the RegistasdasdasdasdasdasdasderController?
Without writing any code I think the best way would be to create a polymorphic relationship, there’s some example code in the documentation-
https://laravel.com/docs/5.8/eloquent-relationships#one-to-one-polymorphic-relations
So in your users table you’d have a userable_type and userable_id (not sure if them names are correct). The userable_type column would contain the model name for either your ProfileEmployee table or your ProfileEmployer table and the userable_id the foreign key of the relationship.
As you can see in the documentation you can then retrieve the relationship and laravel will know which model to use by the userable_type column.
Looking at your tables though I think you could merge the profiles into one table and maybe have a metadata column for data which isn’t always stored for both user types.
I think you can do it by creating two separate method for user type to create them by passing user instance in RegisterControlle just like as follow. and dont forget to return user after creating profile.
class RegisterController extends Controller{
use RegistersUsers;
protected $redirectTo = '/home';
public function __construct()
{
$this->middleware('guest');
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'type' => 'required|in:employee,employer',
]);
}
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
// check the user type
$data['type'] = 'employee' ? $this->createEmployee($user) : $this->createEmployer($user);
}
public function createEmployee($user)
{
// here you can create Employee profile
return $user;
}
public function createEmployer($user)
{
// here you can create Employer profile
return $user;
}
}
Here we need to overwrite two method which is validator and create.

Laravel - Eloquent attach() not working for models

TL;DR
Trying to get three models to interact using eloquent for a rest api.
User - belongsToMany(pulls)
Pull - belongsToMany(user) && belongsToMany(boxes)
Box - belongsToMany(pulls)
The pull_user table is working perfectly, I can just attach a user after I save a pull. Saving a box works fine but the attach doesn't work/enter anything into the pivot table (I get no errors though).
The Problem
I can't get a pivot table that associates two of my models together to attach() after a save. I have the three models listed above, the pivot is working for pull_user but not for pull_box even though the save for box is working perfectly. I am able to save a box without an error but the association just never occurs (no error).
The Code
pull_box.php
class PullBox extends Migration
{
public function up()
{
Schema::create('pull_box', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->integer('pull_id');
$table->integer('box_id');
});
}
public function down()
{
Schema::dropIfExists('pull_box');
}
}
Pull.php
class Pull extends Model
{
protected $fillable = ['from', 'to', 'runit_id', 'start_time', 'end_time', 'box_count', 'pull_status', 'audit_status', 'status', 'total_quantity', 'accuracy'];
public function users(){
return $this->belongsToMany('App\User');
}
public function boxes(){
return $this->belongsToMany('App\Box');
}
}
Box.php
class Box extends Model
{
protected $fillable = ['user_id','from', 'to', 'runit_id', 'start_time', 'end_time', 'pull_id', 'total_quantity', 'status', 'accuracy'];
public function pulls(){
return $this->belongsToMany('App\Pull');
}
}
BoxController.php
public function store(Request $request)
{
$this->validate($request, [
'user_id' => 'required|integer',
...
]);
$user_id = $request->input('user_id');
...
$box = new Box([
'user_id' => $user_id,
...
]);
$pull = Pull::whereId($pull_id)->first();
if($box->save()){
$pull->boxes()->attach($box->id);
$box->view_box = [
'href' => 'api/v1/box/' . $box->id,
'method' => 'GET'
];
$message = [
'msg' => 'Box created',
'box' => $box,
'pull' => $pull_id
];
return response()->json($message, 201);
}
$response = [
'msg' => 'Box creation error, contact supervisor',
];
return response()->json($response, 404);
}
The Solution
I need to know how I can get this association working. I am going to need to add a new layer in under the pull for Item, but I don't want to move one before I solve this. I think that my problem has to stem from a syntactical/logical error on my part but I can't see it. There are a bunch of questions on SO that are very close to giving me a solution, but after reading them I wasn't able to solve my problem.
Any help is appreciated.
Try renaming your pull_box table to box_pull, pivot tables on laravel must be in alphabetical order. If you want to use custom name on pivot table you have to extends your pivot, for example:
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class PullBox extends Pivot
{
protected $table = 'pull_box';
}
And your many to many relationships:
class Pull extends Model
{
protected $fillable = ['from', 'to', 'runit_id', 'start_time', 'end_time', 'box_count', 'pull_status', 'audit_status', 'status', 'total_quantity', 'accuracy'];
public function users(){
return $this->belongsToMany('App\User');
}
public function boxes(){
return $this->belongsToMany('App\Box')->using('App\PullBox');
}
}
class Box extends Model
{
protected $fillable = ['user_id','from', 'to', 'runit_id', 'start_time', 'end_time', 'pull_id', 'total_quantity', 'status', 'accuracy'];
public function pulls(){
return $this->belongsToMany('App\Pull')->using('App\PullBox');
}
}

Laravel 5 DB Seeder “Column not found” error on foreign key

I’ve followed the Laravel docs, as well as a few tutorials, but I must be missing something as I’m getting a “Column not found” error on a foreign key. I’m hoping someone may be able to point it out.
I think the problem is that I don’t know how to “pass” the id for each User I create when trying to create a UserDetail record in the following:
factory(User::class, 3)
->create()
->each(function($u) {
$u->userdetail()->save(factory(UserDetail::class)->create());
});
The actual error is:
[Illuminate\Database\QueryException]
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'where clause'
(SQL: update `userdetails` set `user_id` = 1 where `id` = 0)
My users table has an auto-incrementing id field which is a foreign key to the user_id field in the userdetails table.
Here are the Models:
/*
* User Model
*/
class User extends Model {
// …
public function userdetail() {
# User has a User Detail
return $this->hasOne('Models\Users\UserDetail');
}
// …
}
/*
* UserDetail Model
*/
class UserDetail extends Model {
// …
public function user() {
# UserDetail belongs to User
return $this->belongsTo('Models\Users\User');
}
// …
}
Here are the Seeders:
/*
* UserTableSeeder
*/
class UserTableSeeder extends Seeder {
public function run() {
User::truncate();
UserDetail::truncate();
factory(User::class, 3)
->create()
->each(function($u) {
$u->userdetail()->save(factory(UserDetail::class)->create());
});
}
}
/*
* DatabaseSeeder
*/
class DatabaseSeeder extends Seeder {
DB::statement('SET FOREIGN_KEY_CHECKS = 0'); // disable foreign key constraints
Model::unguard();
$this->call('UserTableSeeder');
Model::reguard();
DB::statement('SET FOREIGN_KEY_CHECKS = 1'); // enable foreign key constraints
}
And, finally, the Model Factories:
$factory->define(User::class, function (Faker\Generator $faker) {
return [
'uname' => $faker->userName,
'pass' => bcrypt(str_random(8)),
'email' => $faker->email,
];
});
$factory->define(UserDetail::class, function (Faker\Generator $faker) {
return [
'street' => $faker->streetName,
'city' => $faker->city,
'state' => $faker->stateAbbr,
'zip' => $faker->postcode,
'phone' => $faker->phoneNumber,
];
});
Thanks for any guidance!
The problem is when you're assigning the relationship. You have to use the make() method instead of the create() as the create() method will cause your model to be stored in the database while the make() method only creates the instance then the save() method will be the one to assign the required FK and store it in the database.
factory(User::class, 3)
->create()
->each(function($u) {
$u->userdetail()->save(factory(UserDetail::class)->make());
});

Categories