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.
Related
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'));
}
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');
...
});
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);
}
I have a user model that is related to a enduser model with a hasOne relationship.
I want to save the inputs of a form field in both user and enduser model in one go.
here is my code;
$user = new User();
$user->first_name = $request->first_name;
$user->last_name = $request->last_name;
$user->phone_number = $request->phone_number;
$user->email = $request->email;
$user->password = $request->password;
$user->enduser->username = $request->username;
$user->save();
return user;
my relationships are
Class User extends Authenticable
{
public function enduser()
{
return $this->hasOne('App\Enduser');
}
}
my migration for users is thus
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('first_name');
$table->string('last_name');
$table->string('phone_number');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->enum('roles',['admin', 'enduser', 'organization', 'radio', 'employee'])->nullable();
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
and for enduser is thus
public function up()
{
Schema::create('endusers', function (Blueprint $table) {
$table->increments('id');
$table->text('address')->nullable();
$table->string('lga')->nullable();
$table->string('city')->nullable();
$table->string('state')->nullable();
$table->string('username');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('endusers');
}
i get an error that says 'unknown column 'username' in where clause'. How can i save such relationship?
Your user model should look like this.
User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'first_name','last_name','phone', 'email', 'password',
];
public function enduser() {
return $this->hasOne('App\EndUser');
}
}
and your EndUser model should look like this
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class EndUser extends Model
{
use Notifiable;
protected $fillable = [
'username',
];
public function user() {
return $this->belongsTo('App\User');
}
}
Then you can write this code in your controller
//first becrypt your password
$request->merge('password',bcrypt($request->password));
$user = User::create(
$request->only(['first_name','last_name','phone','email','password'])
);
$user->enduser->create([$request->username]);
return $user;
Therefore, in order to accomplish what you're trying to do, you can do first create the user then associate the enduser with it by doing the following:
$user = new User();
$user->first_name = $request->first_name;
$user->last_name = $request->last_name;
$user->phone_number = $request->phone_number;
$user->email = $request->email;
$user->password = $request->password;
$user->save();
$endUser = new EndUser();
$endUser->username = $request->username;
$user->enduser()->save($endUser);
return $user;
However, prior to doing this, you must ensure your User and enduser models have their relationships set up correctly.
Maybe you can solve it using laravel observers:
php artisan make:observer UserObserver --model User
This command will create a UserObserver.php file inside app/Observers folder.
Add this to the created function:
public function created(User $user)
{
EndUser::create([
'username' => $user->username,
'user_id' => $user->id,
]);
}
You also need to edit the AppServiceProvider file, inside the app/Providers folder. Add this to the boot method:
public function boot()
{
User::observe(UserObserver::class);
}
Now, every time that a User get registered, it will create a EndUser with the user data.
Hope it helps.
I have form create team.blade.php below this
Form Team index.blade.php
display the name of the one-team user with that user, and display the project that is being done by the user, and display the user as what (role).
the relationship of one user has many teams. and one team has many users. therefore, I choose many to many relations. but when I create team, I want to insert user_id and team_id in the pivot user_teams table as the relation table between user and team.
but when I tried to create team failed, he did not save data to the user_teams table.
and in the team index, he does not display the name of a team user with that user, and displays the project that is being done by the user, and displays the user as what.
my user models
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Presence;
use App\Models\Project;
use App\Productivity;
use App\Sick_leave;
use App\Annual_leave;
use App\Models\Team;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'role_id',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function role()
{
return $this->belongsTo(Role::class, 'role_id');
}
public function teams()
{
return $this->belongsToMany(Team::class, 'user_teams');
}
public function projects()
{
return $this->belongsToMany(Project::Class, 'user_projects');
}
}
Team Models
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\User;
use App\Role;
use Auth;
class Team extends Model
{
use SoftDeletes;
protected $table = 'teams';
protected $fillable = [
'id',
'project_id',
];
public function users()
{
return $this->belongsToMany(User::class, 'user_teams');
}
public function project()
{
return $this->belongsTo(Project::class);
}
public function role()
{
return $this->belongsTo(Role::class);
}
}
Project Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Project extends Model
{
use SoftDeletes;
protected $table = 'projects';
protected $fillable = [
'project_id',
'project_name',
'start_date',
'end_date',
'project_category',
];
public function users()
{
return $this->belongsToMany(User::class, 'user_projects');
}
public function team()
{
return $this->hasOne(Team::class);
}
}
UserTeam model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class UserTeam extends Model
{
use SoftDeletes;
protected $table = "user_teams";
public function team()
{
return $this->belongsTo(Team::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Team Controller
public function index()
{
$users = auth()->user()->name;
$users = User::all();
return view ('teams.index', compact ('teams', 'users', 'projects'));
}
public function create()
{
$users = User::all();
$projects = Project::pluck('project_name', 'id');
return view ('teams.form', compact('projects', 'users'));
}
public function store(Request $request)
{
$team = Team::create($request->all());
$userIds = User::find(2);
$team->users()->attach($userIds);
return redirect()->route('team.create');
}
In user_teams has fields user_id and team_id. how do i overcome this??
You have to create the team and then attach the users that belong to it.
Example from the docs:
Attaching
Eloquent also provides a few additional helper methods to make working
with related models more convenient. For example, let's imagine a user
can have many roles and a role can have many users. To attach a role
to a user by inserting a record in the intermediate table that joins
the models, use the attach method:
$user = App\User::find(1);
$user->roles()->attach($roleId);
In your case:
Team Controller
public function store(Request $request)
{
$team = Team::create($request->except('user_id'));
$team->users()->attach($request->get('user_id', []));
return redirect()->route('team.create');
}