how to laravel API resources add property in Row collection auto increment for row by row
"id" => (int)$this->id,
"fullname" => $this->fullname,
"city" => $city ? $city->name : 'نا مشخص',
"avatar" => ($this->avatar()->first()) ? img($this->avatar()->first()->path, '124x124') : '',
"count" => (int)$this->user_referral_count,
"rate" => autoincrement
if you set a field in your migration as increments it will be automatically incremented.
like bellow:
public function up() {
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
...
...
...
});
}
and after that, when you create a new instance of User model. it's id will increase itself.
create new user like this:
$user = new User;
$user->name = 'hossein';
$user->email= '#hossein#k.t';
...
...
$user->save();
I have 3 tables, the schema is below.
Employees,
EmployeeDB.php
$factory->define(Employee::class, function (Faker $faker) {
return [
'emp_id' => $faker->randomDigit,
'name' => $faker->name,
'dept_id' => $faker->numberBetween($min = 1, $max = 15),
'salary_id' => $faker->randomDigit(),
'gender' => $faker->randomElement(['M', 'F', 'T']),
/*if I remove these next 2 statements, I receive an error for
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'employee_id' in 'field list' (SQL: insert into `employees` (`emp_id`, `name`, `dept_id`, `salary_id`, `gender`, `date_of_joining`,
`date_of_birth`, `employee_id`, `updated_at`, `created_at`) values (2, Jamaal Beer, 3, 9, T, 2018-05-05 18:59:40, 2005-07-05 13:17:23, ?,
2019-12-11 11:15:42, 2019-12-11 11:15:42))
*/
'employee_id' => $faker->randomDigit,
//Same for this one as well
'department_id' => $faker->randomDigit,
'date_of_joining' => $faker->dateTimeBetween($startDate = '-5 years', $endDate = 'now', $timezone = null),
'date_of_birth' => $faker->dateTimeBetween($startDate = '-20 years', $endDate = 'now', $timezone = null),
Employee Migration table:
Schema::create('employees', function (Blueprint $table) {
$table->bigIncrements('emp_id');
$table->integer('dept_id')->unsigned();
$table->foreign('dept_id')->references('id')->on('departments');
$table->integer('salary_id')->unsigned();
$table->foreign('salary_id')->references('id')->on('salaries');
$table->string('name');
$table->string('gender');
$table->timestamp('date_of_joining');
$table->dateTime('date_of_birth');
/*SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'employee_id' cannot be null
(SQL: insert into `employees` (`emp_id`, `name`, `dept_id`, `salary_id`, `gender`, `employee_id`, `department_id`,
`date_of_joining`, `date_of_birth`, `updated_at`, `created_at`)
values (6, Martina Wuckert, 7, 3, F, ?, 3, 2018-09-14 05:59:15, 20
*/
$table->string('employee_id')->nullable();
$table->string('department_id')->nullable();
$table->timestamps();
//added to prevent errors
Departments
DepartmentsDB.php
factory->define(Department::class, function (Faker $faker) {
return [
//Yes, this is a hack. Use Multidimensional Arrays the next time.
'id' => $faker->numberBetween($min = 1, $max = 15),
'dept_name' => $faker->randomElement(['Production', 'Purchase & Quality', 'Operations', 'Sales', 'Customer Serice', 'Business Development', 'Maketing', 'Tech Support', 'Finance', 'Human Resources', 'Research & Development', 'IT', 'Legal']),
];
DepartmentsMigration
Schema::create('departments', function (Blueprint $table) {
$table->increments('id');
$table->string('dept_name');
$table->timestamps();
});
Salaries
SalaryDb.php
$factory->define(Salary::class, function (Faker $faker) {
return [
'id' => $faker->randomDigit(),
'monthlySalary' => $faker->randomNumber($nbDigits = 3),
//Yes this is a hack. Use MultiDimensional Arrays the next time.
];
});
SalariesMigration
$factory->define(Salary::class, function (Faker $faker) {
return [
'id' => $faker->randomDigit(),
'monthlySalary' => $faker->randomNumber($nbDigits = 3),
//Yes this is a hack. Use MultiDimensional Arrays the next time.
];
});
App\Department
class Department extends Model
{
//
public function employee()
{
return $this->hasMany(Employee::class);
}
public function salary()
{
return $this->hasMany(Salary::class);
}
}
App\Employee
class Employee extends Model
{ //belongsto block
public function department()
{
return $this->hasOne(Department::class);
}
public function Salary()
{
return $this->hasOne(Salary::class);
}
}
App\Salary
class Salary extends Model
{
//
public function employee()
{
return $this->belongsTo(Employee::class);
}
}
DatabaseSeeder.php
factory(App\Employee::class, 25)->create()->each(function ($employee) {
$department = factory(App\Department::class)->make();
$employee->department()->save($department);
$salary = factory(App\Salary::class)->make();
$employee->salary()->save($salary);
});
When I run the below command, this is the error I get
php artisan db:seed
Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`volga_2`.`employees`, CONSTRAINT `employees_dept_id_foreign` FOREIGN KEY (`dept_id`) REFERENCES `departments` (`id`))")
What I am trying to do is: for every Employee Record, One Department and One Salary is assigned.
This is for later: Departments cannot be duplicated within its own table. Ie. Once a department id with name is created, it cannot be recreated again.
I know I am going wrong, else there wouldn't be errors. When I run the dbSeeder for departments and salaries, it works fine. But whenever there is a duplicate department entry it throws up an error. But the data stored in the db is fine.
I would like a solution or a few pointers, because I'm still learning Laravel.
Thanks!
EDIT
When I execute
php artisan migrate
Order of Migrations
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.44 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (1.18 seconds)
Migrating: 2019_12_09_105432_create_departments_table
Migrated: 2019_12_09_105432_create_departments_table (0.29 seconds)
Migrating: 2019_12_09_105743_create_salaries_table
Migrated: 2019_12_09_105743_create_salaries_table (0.21 seconds)
Migrating: 2019_12_10_104739_create_employees_table
Migrated: 2019_12_10_104739_create_employees_table (2.04 seconds)
Just change the order of the migrations. I am guessing you are trying to make relation before the table created. Make the first migration of the parent table
Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`volga_2`.`employees`, CONSTRAINT `employees_dept_id_foreign` FOREIGN KEY (`dept_id`) REFERENCES `departments` (`id`))")
this error says that it cant generate relation with departments table for some reason. as you write, you try to generate Employee with relation to 2 other table before generate them, by changing name of your migration, you can reorder migration. that means you can change order of running your migration with changing time in migration name so that you migrate with this order:
1) DepartmentsMigration
2) SalariesMigration
3) Employee Migration
Thank you all for providing solutions and ideas to help me solve this issue. But after tinkering with it, I worked out a solution that works fine.
I will just be posting the changes i made to keep it easier to keep a track of and it may be of help to someone else.
Here it is.
EmployeeDB.php
$factory->define(Employee::class, function (Faker $faker) {
return [
'emp_id' => $faker->unique()->randomNumber($nbDigits = 3, $strict = true),
'name' => $faker->name,
//dept_id and salary_id pulls the data from their respective tables and then //randomly assigns an id from the id column
'dept_id' => App\Department::all()->random()->id,
'salary_id' => App\Salary::all()->random()->id,
'gender' => $faker->randomElement(['M', 'F', 'T']),
'date_of_joining' => $faker->dateTimeBetween($startDate = '-5 years', $endDate = 'now', $timezone = null),
'date_of_birth' => $faker->dateTimeBetween($startDate = '-20 years', $endDate = 'now', $timezone = null),
];
});
EmployeeMigration
public function up()
{
Schema::create('employees', function (Blueprint $table) {
$table->unsignedInteger('emp_id', true);
$table->unsignedInteger('dept_id');
$table->foreign('dept_id')->references('id')->on('departments');
$table->unsignedInteger('salary_id');
$table->foreign('salary_id')->references('id')->on('salaries');
$table->string('name');
$table->string('gender');
$table->timestamp('date_of_joining');
$table->dateTime('date_of_birth');
$table->timestamps();
//added to prevent errors
});
Departmentdb
$factory->define(Department::class, function (Faker $faker) {
return [
//Yes, this is a hack. Use Multidimensional Arrays the next time.
'id' => $faker->unique()->numberBetween(1, 12),
'dept_name' => $faker->randomElement(['Production', 'Purchase & Quality', 'Operations', 'Sales', 'Customer Serice', 'Business Development', 'Maketing', 'Tech Support', 'Finance', 'Human Resources', 'Research & Development', 'IT', 'Legal']),
];
});
DepartmentMigration
protected $dept_id = 'id';
public function up()
{
Schema::create('departments', function (Blueprint $table) {
$table->unsignedInteger('id', true);
$table->string('dept_name');
$table->timestamps();
});
}
SalaryDB
$factory->define(Salary::class, function (Faker $faker) {
return [
'id' => $faker->unique()->randomNumber($nbDigits = 5, $strict = true),
'monthlySalary' => $faker->randomNumber($nbDigits = 3),
//Yes this is a hack. Use MultiDimensional Arrays the next time.
];
});
Salary Migration
public function up()
{
Schema::create('salaries', function (Blueprint $table) {
$table->unsignedInteger('id', true);
$table->string('monthlySalary');
$table->timestamps();
});
}
DatabaseSeeder.php
public function run()
{
$this->call([UsersTableSeeder::class]);//this is not important
factory('App\Department', 12)->create();
factory('App\Salary', 50)->create();
factory('App\Employee', 55)->create();
}
}
What is happening is that, I first seeded the Departments table, with the department ID's and their respective names. Then, I seeded, the salaries table, with just the salary id's and the salary amounts.
Then the employees seeder ran, which referenced the departments, and salaries table through the foreign key relations and inserted the data from the id columns in those respective tables into the dept_id and salary_id columns in my employees table.
Another important aspect to this, to set up the Primary Key is using
protected $id = 'Primary Key Table name'
See DepartmentMigration code block above. This needs to be defined outside the scope of the up() function, and must be present wherever a primary key needs to be defined.
I have done this over 3 hours, working out each individual DB Seeder, so I am happy this works. There is possibly a better more elegant solution out there, but I will get on to that tomorrow. :)
Thank you for reading, and I hope that this has help you.
I will answer any questions regarding this to the best of my ability. :)
I am trying to check if data exist in a table before saving. I can save to the table
public function read($book_id)
{
MyBook::create([
'book_id' => $id,
'user_id' => Auth::id()
]);
$readBooks = Book::where('id', $book_id)->get()->first();
return view('read')->with('data', $readBooks);
}
But when I tried to use firstOrCreate to check before saving it returned this error
SQLSTATE[42S22]: Column not found: 1054 Unknown column '1' in 'where
clause' (SQL: select * from my_books where (1 is null and 1 is
null) limit 1)
This is the method I am using
public function read($book_id)
{
$mybook = MyBook::firstOrCreate([
['book_id' => $book_id],
['user_id' => Auth::id()]
]);
$readBooks = Book::where('id', $book_id)->get()->first();
return view('read')->with('data', $readBooks);
}
My my_book table schema
public function up()
{
Schema::create('my_books', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('book_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->timestamps();
});
}
I don't know what I am doing wrong, I hope I can find help here.Thanks.
You are passing array inside it also 2 array. But that is not correct. You must be use like this
$mybook = MyBook::firstOrCreate(
['book_id' => $book_id],
['user_id' => Auth::id()]
);
You are passing a single array of arrays as the first argument to firstOrCreate. It takes associative arrays for the arguments.
$mybook = MyBook::firstOrCreate(
['book_id' => $book_id],
['user_id' => Auth::id()]
);
Argument 1 and 2 are associative arrays.
Laravel 6.x Docs - Eloquent - Other Creation Methods firstOrCreate
I have problem with my seeds. Here is my structure of my tables:
1.Complaints:
Schema::create('complaints', function (Blueprint $table) {
$table->uuid('id');
$table->unsignedInteger('origin_id');
$table->timestamps();
$table->primary('id');
});
2.Complaint_bill
Schema::create('complaint_bills', function (Blueprint $table) {
$table->uuid('complaint_id');
$table->string('symbol')->nullable();
$table->string('item_name');
$table->timestamps();
$table->primary('complaint_id');
$table->foreign('complaint_id')->references('id')-
>on('complaints');
Now I have seeds :
factory(Complaint::class, 10)->create()->each(function ($c) {
$product = Product::inRandomOrder()->first();
factory(ComplaintBill::class, 10)->create([
'complaint_id' => $c->id,
'item_id' => $product->id,
'item_name' => $product->name,
'item_numeric_index' => $product->numeric_index,
'item_gross_price' => $product->sell_price_gross,
]);
})'
I have problem/error like this:
SQLSTATE[23505]: Unique violation: 7 ERROR: duplicate key value
violates u
nique constraint "complaint_bills_pkey"
DETAIL: Key (complaint_id)=(ea302ab8-67dc-3bed-afc8-4215a99f1f68)
already exists.
When I comment primary in Complaint_bill ( column - complaint_id )then everything is ok. It looks like the problem is that I have primary key on uuid on Complaint_bill, which is foregin on Complaint->id. Why it is doing like this? I can't have primary on foregin when I have relation with two primary's?
The reason you are seeing this issue is that a UUID is not an auto-incrementing value in the traditional sense that an INTEGER AUTO_INCREMENT is when defining a primary key. When using factory methods to insert a set of data, the value doesn't "go up by one" automatically on each insert.
You would need to initialise each model generated with a boot function to generate the UUID for yourself prior to storage. From the below article:
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->{$model->getKeyName()} = Uuid::generate()->string;
});
}
The below article explains it in a bit more detail.
https://medium.com/#steveazz/setting-up-uuids-in-laravel-5-552412db2088
Try this: \Ramsey\Uuid\Uuid::uuid4()->toString()
`DB::table('customers')->insert([
['id' => \Ramsey\Uuid\Uuid::uuid4()->toString(), 'name' => 'Test', 'color' => '#aaa', 'created_at' => $now],
]);`
This is pretty weird and I have no idea what i'm doing wrong.
I have 2 models:
class Project extends Eloquent {
public function status()
{
return $this->belongsTo('ProjectStatus','status_id');
}
}
and
class ProjectStatus extends Eloquent {
protected $table = 'PStatus';
public function projects()
{
return $this->hasMany('Project');
}
}
The table "projects" has the proper foreign keys:
Schema::create('PStatus', function($table) {
$table->increments('id');
$table->string('name', 64);
$table->unique('name');
});
Schema::create('Projects', function($table) {
$table->increments('id');
$table->string('name', 100);
$table->integer('status_id')->unsigned();
$table->foreign('status_id')->references('id')
->on('PStatus')
->onDelete('cascade');
});
In the database (for example) I have only 1 project: "Project_1" (id = 1) with status_id = 1 (Lets say status name = "Open"). If I execute the following query:
$projects = Project::with(array('status' => function($query){
$query->where('name', '<>', 'Open');
}))->get();
I'm still getting the project in the results!!. This is the sql log:
array (size=3)
'query' => string 'select * from `PStatus` where `PStatus`.`id` in (?) and `name` <> ?' (length=67)
'bindings' =>
array (size=2)
0 => int 1
1 => string 'Open' (length=4)
'time' => float 0.36
if I print:
var_dump($projects->count());
I still get 1 project! How come?
I can easily solve my problem by changing the query to something like:
$projects = Project::where('status_id', '<>', 1)->get(); //assuming that status_id=1 => "Open"
but i prefer not to use ids directly when I guess the method with should work. What am I doing wrong here???
Actually this is the answer:
Eloquent Nested Relation with Some Constraint
A huge confusion with the with method. I should have used a join.