laravel can't delete a row with one to many relation - laravel

I have one to many relation in my project ( the user has many details ), and when i delete any user row it says
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`sehhatys_saudi`.`details`, CONSTRAINT `details_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)) (SQL: delete from `users` where `id` = 9)
the details table migration
Schema::create('details', function (Blueprint $table) {
$table->id();
$table->bigInteger('user_id')->unsigned();
$table->string('check_date', 100);
$table->string('result_date', 100);
$table->string('result', 100);
$table->string('check_center', 100);
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
the User model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use HasFactory;
protected $fillable = ['name', 'name_en', 'national_id',
'birth_date', 'user_password', 'nationality', 'nationality_en',
'vaccine_type_one', 'vaccine_type_one_en', 'date_one',
'batch_number_one', 'vaccine_type_two', 'vaccine_type_two_en',
'date_two', 'batch_number_two', 'report_id', 'qr_url', 'access_token',
'phone', 'email', 'social', 'social_en', 'weight', 'height', 'mass',
'blood_pressure', 'blood_sugar', 'waist', 'hypertension',
'hypertension_en', 'diabetes', 'diabetes_en', 'city', 'city_en',
'health_center', 'health_center_en'];
public function details(){
return $this->hasMany('App\Detail');
}
}
the Detail model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Detail extends Model
{
use HasFactory;
protected $fillable = ['user_id', 'check_date', 'result_date',
'result', 'check_center'];
public function user(){
return $this->belongsTo('App\User');
}
}
the delete function for the user row
public function delete($id)
{
User::findOrFail($id)->delete();
return redirect(route('users.all'));
}
even when edited the delete function and make it like this
public function delete($id)
{
$user = User::findOrFail($id);
$user->details()->delete();
$user->delete();
return redirect(route('users.all'));
}
it returns this error
Class "App\Detail" not found

The name space for your Detail Model is namespace App\Models; While you are using App\Detail in User.php.
The relation in User model should be:
public function details(){
return $this->hasMany('App\Models\Detail');
}
If you are using laravel-8 it should be like:
public function details(){
return $this->hasMany(App\Models\Detail::class);
}

Related

How to add information to a pivot table in laravel?

I have a many:many relation between student and course.
Here are my models and my pivot table:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
use HasFactory;
protected $fillable = [
'name',
'surname',
'age',
'tdah',
'description',
'hobbies',
];
/* public function course(){
return $this->belongsTo(Course::class);
} */
public function data(){
return $this->hasMany(Datum::class, 'student_id', 'id');
}
public function configurations(){
return $this->hasMany(Configuration::class, 'student_id', 'id');
}
public function courses(){
return $this->belongsToMany(Course::class, 'course_student', 'student_id', 'course_id');
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Course extends Model
{
use HasFactory;
protected $fillable = [
'name',
'academic_course_id',
'user_id',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function academicCourse()
{
return $this->belongsTo(AcademicCourse::class);
}
public function planification(){
return $this->hasOne(Planification::class, 'course_id', 'id');
}
public function subjects(){
return $this->hasMany(Subject::class, 'course_id', 'id');
}
/* public function students(){
return $this->hasMany(Student::class, 'course_id', 'id');
} */
public function students(){
return $this->belongsToMany(Student::class, 'course_student', 'course_id', 'student_id');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('course_student', function (Blueprint $table) {
$table->id();
$table->foreignId('course_id')->constrained()->onDelete('cascade');
$table->foreignId('student_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('course_student');
}
};
I'd like to create a student that belongs to a group. I know how to create a student and a group, but I'd like to create a register for that student in my course_student pivot table. My StudentController method store is:
public function store(Request $request)
{
Student::create($request->all());
$courses = Course::all();
$academicCourses = AcademicCourse::all();
return view('course.index', compact('courses', 'academicCourses'));
}
It creates a new student but I don`t know how to create a new register for the pivot table.
I thought about doing something like:
course_student::create(request)
in my store method but I think it isn`t that way.
In Laravel you can do it by using attach function, Attach() function has two parameters :
1- the another foreign key in you case attach(course_id).
2-(this is optional) array for any another columns inside pivot table for example :
attach(course_id,['users_id'=>$usersId])
In your case you will create the records inside the pivot table (course_student) via the object from student model .
$student->courses()->attach($course_id);
note :
there is another method which does the opposite detach() but you need to use it carefully if you write it without any parameter it will remove all the records inside (course_student) that belong to the student object so specify the course that you want to remove it by that way :
$student->courses()->detach($course_id);
I hope that will help you ...
$student->courses()->attach($courseId);
https://laravel.com/docs/9.x/eloquent-relationships#updating-many-to-many-relationships
Edit :
You can use attach() method on the relationship. In your code it would look like this :
public function store(Request $request, Course $course) //add parameter course to know which course needs to be attached
{
$newStudent = Student::create($request->all()); // create() returns instance of created Student
$newStudent->courses()->attach($course->id);
$courses = Course::all();
$academicCourses = AcademicCourse::all();
return view('course.index', compact('courses', 'academicCourses'));
}

How to correctly use relationships with() in Laravel?

I just wanted to clarify using the relationship in tables. Right now, I wanted to fetch records of designation names from designation_id in employees table.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\{
Designations,
Positions
};
class Employees extends Model
{
use HasFactory;
protected $table = 'employees';
protected $primaryKey = 'id';
public $timestamps = true;
protected $casts = [
'designation_id' => 'array',
'position_id' => 'array',
'basic_pay' => 'decimal:2',
];
protected $dates = ['created_at', 'updated_at'];
protected $fillable = [
'first_name',
'last_name',
'designation_id',
'position_id',
'basic_pay',
];
public function designations()
{
return $this->hasMany(Designations::class, 'id', 'designation_id');
}
public function positions()
{
return $this->hasMany(Positions::class, 'id', 'position_id');
}
}
Here's my designation model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\Employees;
class Designations extends Model
{
use HasFactory;
protected $table = 'designations';
protected $primaryKey = 'id';
public $timestamps = true;
protected $dates = ['created_at', 'updated_at'];
protected $fillable = [
'name',
'description'
];
public function employees()
{
return $this->belongsTo(Employees::class, 'designation_id');
}
}
Here's my EmployeeController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\{
Employees,
Designations
};
class EmployeesController extends Controller
{
public function index()
{
$employees = Employees::with('designations', 'positions')->get();
return array_reverse($employees);
}
}
I checked my api url, http://localhost:8000/api/employees and got this error:
SQLSTATE[HY093]: Invalid parameter number (SQL: select * from designationswheredesignations.id in (52))
I would recommend you to install phpstorm, it gives you hints of function parameters and you won't have this kind of issues anymore.
correct format is:
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
in your designations model:
public function DesignationNames()
{
return $this->hasMany(\App\Models\Employees::class, 'designation_id', 'id');
}
When you retrieve them in your controller you need to use the with() method as:
Designations::with('DesignationNames')->get();
And then to access properties in the related employee collection you would need to:
$designation->DesignationNames->DesignationProperty
Your relationships parameters are wrong. It's
hasMany(class, foreignKey, relatedPrimaryKey)
# Employee
public function designations()
{
return $this->hasMany(Designations::class, 'employee_id', 'id');
}
public function positions()
{
return $this->hasMany(Positions::class, 'employee_id', 'id');
}
If you're eager loading more than 1 relationship, use array notation.
Also, $employees will be an instance of a Collection, so you can't use it as an argument to array_reverse.
You can either use collection methods to achieve the same result, or use $employees->all() to get the underlying array.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Employees;
class EmployeesController extends Controller
{
public function index()
{
$employees = Employees::with(['designations', 'positions'])->get();
return $employees->reverse()->values()->all();
// OR
return array_reverse($employees->all());
}
}
This is assuming your tables have a structure like this:
Schema::create('employees', function (Blueprint $table) {
$table->id();
...
});
Schema::create('designations', function (Blueprint $table) {
$table->id();
$table->foreignId('employee_id')->constained('employees');
...
});
Schema::create('positions', function (Blueprint $table){
$table->id();
$table->foreignId('employee_id')->constained('employees');
...
});
Since you're using increments instead of id(), the code has to be a little different.
Schema::create('employees', function (Blueprint $table) {
$table->increments('id')->unique();
...
});
Schema::create('designations', function (Blueprint $table) {
$table->increments('id')->unique();
$table->unsignedInteger('employee_id');
$table->foreign('employee_id')->references('id')->on('employees');
...
});
Schema::create('positions', function (Blueprint $table){
$table->increments('id')->unique();
$table->unsignedInteger('employee_id');
$table->foreign('employee_id')->references('id')->on('employees');
...
});

Database relations in Laravel Module

I've a problem in using database relationships together with Laravel module.
for example:
I've User module & Profile Module
I've One-to-One relation between user & profile (in 2 separated modules)
I need to get profile information when I have user data (example: $user->profile)
But I think because of creating relation between two modules, I cannot access to this relation.
My received error:
"message": "SQLSTATE[42S02]: Base table or view not found: 1146 Table 'user.profiles' doesn't exist (SQL: select * from profiles where profiles.user_id = 2 and profiles.user_id is not null limit 1)",
"exception": "Illuminate\Database\QueryException",
User Module/Entities/User.php
<?php
namespace Modules\User\Entities;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\VofourCourse\Entities\Profile;
class User extends Authenticatable
{
use HasFactory;
protected $connection = 'user';
protected $guarded = [];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function profile()
{
return $this->hasOne(Profile::class);
}
}
Profile Module/Entities/Profile.php
<?php
namespace Modules\Profile\Entities;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Modules\User\Entities\User;
use RichanFongdasen\EloquentBlameable\BlameableTrait;
class Profile extends Model
{
use HasFactory, SoftDeletes, BlameableTrait;
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
}
Profile Module/Controller/ProfileController.php
<?php
namespace Modules\Profiole\Http\Controllers;
use Illuminate\Routing\Controller;
class ProfileController extends Controller
{
public function showProfile()
{
$user = auth('api')->user();
return $user->profile;
}
}
Profile migration
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->onDelete('cascade');
$table->string('whatsapp_mobile', 15)->unique();
$table->string('phone', 15)->unique();
$table->string('national_code', 10)->nullable();
$table->string('postal_code', 10)->nullable();
$table->text('address')->nullable();
$table->string('job_title')->nullable();
$table->foreignId('city_id')->nullable();
$table->string('father_name')->nullable();
$table->enum('marital_status', ['married', 'single', 'widow', 'divorced', 'unknown'])->default('married');
});
User migration
Schema::connection(config('modules.connections.user_database'))->create('users', function (Blueprint $table) {
$table->id();
$table->string('firstname')->nullable();
$table->string('lastname')->nullable();
$table->string('email')->unique()->nullable();
$table->string('vofour_id' , 10)->nullable();
$table->string('username', 20)->nullable();
$table->timestamp('email_verified_at')->nullable();
$table->string('password')->nullable();
$table->date('birth_date')->nullable();
$table->enum('gender', ['male', 'female'])->nullable();
$table->string('mobile', 15)->unique();
$table->enum('status', ['active', 'inactive'])->default('active');
$table->rememberToken();
});```
thanks a lot for your helps & guidance
You've a typing error in your relationship. The error states there should be a relation profiles where as from your code there's a profile.
public function profile()
{
return $this->hasOne(Profile::class);
}
What you can do is return user->with('profile') which will return the user with it's relational details. I.e.
<?php
namespace Modules\Profiole\Http\Controllers;
use Illuminate\Routing\Controller;
class ProfileController extends Controller
{
public function showProfile()
{
$user = auth('api')->user();
return $user->with('profile');
}
}
Also update your profiles migration line where user_id is written from:
$table->foreignId('user_id')->onDelete('cascade'); to $table->foreignId('user_id')->constrained('users');.
This will link up the user_id as a foreign key to users table id. and return the correct collection of users with their profiles.

Laravel relationship many to many count related data by foreign key

I have 3 models in my project:
User model code:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
protected $guarded = [];
public function professions()
{
return $this->belongsToMany('App\Models\Profession', 'user_professions');
}
}
Profession model code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Profession extends Model
{
protected $guarded = [];
public function users()
{
return $this->belongsToMany('App\Models\User', 'user_professions');
}
}
Migration:
$table->id();
$table->string("name");
$table->timestamps();
UserProfession model code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class UserProfession extends Model
{
//
}
Migration:
$table->id();
$table->foreignId('user_id')
->constrained()
->onDelete('cascade');
$table->foreignId('profession_id')
->constrained()
->onDelete('cascade');
When I try this code where I search users by his name and get there professions name then count users in that professions.
Code:
$query = $request->get("query");
$users = User::where("name", "like", "%".$query."%");
$userIds = $users->get()->pluck("id")->toArray();
$professions = Profession::whereHas("users", function($q) use($userIds) {
$q->whereIn('id', $userIds);
})->get()->toArray();
I get error with message:
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity
constraint violation: 1052 Column 'id' in where clause is ambiguous
(SQL: select * from professions where exists (select * from users
inner join user_professions on users.id = user_professions.user_id
where professions.id = user_professions.profession_id and id in (11,
43, 82)))
Where I have error in my code and how I can fix it?
There are three tables users,user_professions and professions that all have id column.
You need to specify which table's id that you want:
$professions = Profession::whereHas("users", function($q) use($userIds) {
$q->whereIn('users.id', $userIds); // specify the table name
})->get()->toArray();

SQLSTATE[42S02]: Base table or view not found: 1146 error laravel

I have been trying to solve a problem for couple hours.
Basically I'm getting:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'tp-laravel.image_location' doesn't exist (SQL: select location_id from image_location where image_id = 3) error.
Is this coming from a bad controller/model/migration? This is happening when I try to add an image in my website.
I have been trying to change stuff, add stuff and look on google a lot, but nothing solved it.
Image.php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
class Image extends Model
{
protected $fillable = ['name'];
public function locations()
{
return $this->belongsToMany(Location::class);
}
public function getUpdatedAtAttribute($date)
{
return Carbon::parse($date)->locale('fr')->diffForHumans(Carbon::now());
}
}
Location.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Location extends Model
{
protected $fillable = ['name'];
public function locations()
{
return $this->belongsToMany(Image::class);
}
}
Here are the create and store methods from my controller:
public function create()
{
$locations = Location::pluck('name', 'id');
$users = User::pluck('name', 'id');
return view('posts.create', compact('locations'));
}
public function store(Request $request)
{
$image = Image::create(request()->all());
$image->locations()->sync(request()->get('locations'));
$user->users()->sync(request()->get('users'));
return redirect('/accueil');
}
And finally my image migration
Schema::create('images', function (Blueprint $table) {
$table->bigIncrements('id');
$table->BigInteger('location_id')->unsigned()->index();
$table->BigInteger('user_id')->unsigned()->index();
$table->foreign('location_id')->references('id')->on('locations')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('name', 100);
$table->timestamps();
});
When I press the create button in my view, the submit it's supposed to add the image in the database with user and location linked to it as a foreign key but the above error pops up.
Thanks!
The error is coming from
public function locations()
{
return $this->belongsToMany(Location::class);
}
Laravel assumes that you have intermediate table named alphabetically, for that is image_location and this table does not exist on your database.
The only way is to create such table, or if you have created the table with different name you can pass second parameter as table name. So it became:
public function locations()
{
return $this->belongsToMany(Location::class, 'TABLE_NAME');
}

Resources