Laravel can I use pivot table as a model - php

I have three tables staff, customer, service.
I have created pivot for customer and service as customer_service(has extra fields).
Now I want to link the staff to customer_service. So i tried to use customer_service as a model 'Custserv' and tried to relate with staff. It didnt workout.
Because I don't want staff linking directly to customer and service
I had this following relationship working
/*Model - Service*/
public function customer(){
return $this->belongsToMany('customer')->withPivot(
'start_date',
'stop_date',
'rem_date',
'due_date',
'status'
);
}
/*Model - customer*/
public function services(){
return $this->belongsToMany('Service')->withPivot(
'start_date',
'stop_date',
'rem_date',
'due_date',
'status'
);
}
////These following relations didnt workout
/*Model - custserv*/ //uses the pivot table customer_service//
public function staff(){
return $this->belongsToMany('Staff');
}
/*Model - Staff*/
public function custservs(){
return $this->belongsToMany('Custserv');
}
/*schema for pivot table 'staff' and 'Custserv' */
Schema::create('customer_service_user', function(Blueprint $table)
{
$table->increments('id');
$table->integer('customer_service_id')->unsigned()->index();
$table->foreign('customer_service_id')->references('id')->on('customer_service')->onDelete('cascade');
$table->integer('staff_id')->unsigned()->index();
$table->foreign('staff_id')->references('id')->on('staff')->onDelete('cascade');
$table->timestamps();
});
Then I tried ...
$staff = User::find(1)->custservs;
return $staff;
It gave error
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'auditCrm_db.custserv_user' doesn't exist (SQL: select `customer_service`.*, `custserv_user`.`user_id` as `pivot_user_id`, `custserv_user`.`custserv_id` as `pivot_custserv_id` from `customer_service` inner join `custserv_user` on `customer_service`.`id` = `custserv_user`.`custserv_id` where `custserv_user`.`user_id` = 1)
If my relationshiop is correct how to get and set values between Staff and Custserv?

You may have figured it out, but I think you are doing it overly complicated. When using a many-to-many relationship Laravel provides the pivot property. You already have withPivot in your relationship.
Now you can access it like that:
$staff = User::find(1)->services()->first()->pivot; // or you could loop over services
return $staff;

Related

Many to Many Relationship with 2 FK referencing from same PK Laravel 8

Hello I am working on a Laravel project, that i have to assign for one Mentorship «Mentoria», one Mentor «Mentor» and one student «Mentorando». The data of the student and the mentor, came from the Users table (i assigned them roles, using Spatie) , and the other table is called «Mentoria» Since there exists a many to many relation i created the pivot table that is called «utilizador_mentoria» and has ID_Mentor, ID_Mentorando (both are FKs coming from the users table),and ID_mentoria (coming from Mentoria table). I defined both models as this:
User Model:
protected $casts = [
'email_verified_at' => 'datetime',
];
public function interesses(){
return $this->belongsToMany(AreaInteresse::class, 'utilizador_interesse', 'id_utilizador', 'id_interesse');
}
public function mentorias(){
return $this->belongsToMany(Mentoria::class, 'utilizador_mentoria', 'id_mentoria', 'id_mentorando', 'id_mentor');
}
ps: I have interesses function with other model, that is working properly. my problem is with the «mentorias»
Mentoria Model:
public function users(){
return $this->belongsToMany(User::class, 'utilizador_mentoria','id_mentor','id_mentorando','id_mentoria');
}
With this, i am trying to get the data from all Mentorias, and the data of the Mentor that is assigned to that that Mentoria, however when i am doing this code on the controller, the data coming from the user appears empty, despite i have the DB filled with data. I tried a echo for testing, and it only shows the data of the Mentoria, and where it should appear the data of the Mentor assigned to that MEntoria, it is empty
the code from the controller:
public function mentorias(){
$mentorias = Mentoria::with('users')->get();
echo $mentorias;
return view('admin/mentorias/admin_mentorias', ['mentorias' => $mentorias]);
}
the output of the echo
[{"id":2,"titulo":"teste","titulo_en":"test","descricao":"fe","descricao_en":"ewfwe","created_at":"2021-12-28T01:32:10.000000Z","updated_at":"2021-12-28T01:32:10.000000Z","users":[]}]
Since as i already said, i already used data from 2 tables with Many to Many relation, however with only 1 FK per PK, and it is working properly, i have no idea why it is not working this way . I already checked for similar questions, however with no luck
Edit:
For testing purposes, i removed the column of one of the two FK that reference from the same PK, and i managed to work, however with this aditional FK i am not managing to make it work . I believe that the problem is with the relation, in the models but i have no idea how to make it work
I rearranged the funcitons in the models as they are now
User Model:
public function mentorias(){
return $this->belongsToMany(Mentoria::class, 'utilizador_mentoria', 'id_mentor', 'id_mentorando', 'id_mentoria');
}
Mentoria Model:
public function users(){
return $this->belongsToMany(User::class, 'utilizador_mentoria','id_mentoria','id_mentorando','id_mentor');
i also tried to took out,example «id_entorando» from the main () and put it after with the «withPivot» method, but it still didn't worked
I don't know if I properly understood the problem but your relationship is not a single "many to many", but two "one to many". In the end I'll show why it's convenient to consider them as two separated relationships.
First: If a user can have multiple mentorships but a mentorship can have only 1 mentor (which I suppose is what's happening), then you should use the "hasMany/belongsTo" pair:
User Model:
public function mentorias(){
return $this->hasMany(Mentoria::class);
}
Mentoria Model:
public function user(){
return $this->belongsTo(User::class);
}
Second: Complete the scenario with the other relationship bewteen the mentorship and the students:
User Model:
public function mentorias(){
return $this->hasMany(Mentoria::class);
}
public function mentoria(){
return $this->belongsTo(Mentoria::class);
}
Mentoria Model:
public function user(){
return $this->belongsTo(User::class);
}
public function mentorandos(){
return $this->hasMany(User::class);
}
There should be a user_id column in the mentorias table that represents the Teacher which the mentorships belong to:
Schema::table('mentorias', function (Blueprint $table) {
$table->unsignedInteger('user_id')->nullable();
});
And there should also be a mentor_id column in the users table that represents the mentorship which the students belong to:
Schema::table('users', function (Blueprint $table) {
$table->unsignedInteger('mentoria_id')->nullable();
});
Third: This double representation of the User Model could lead to confusion, since two different objects (teacher and student) are using the same model but are not meant to have both relationships simultaneously: A teacher shouldn't be mentored and a student shouldn't lead mentorships.
In order to roperly manage Teachers and Students and prevent confusion, you could create additional models that inherit the User Model and define the relationships for them (instead of the User Model), so you can limit the fields and the relationships for each one of them.
User Model:
// No relationships
Teacher Model:
// Extending from User allows you to have all the User Model functionality
class Teacher extends User
{
public function mentorias(){
return $this->hasMany(Mentoria::class)->with('students');
}
}
Student Model:
// Extending from User allows you to have all the User Model functionality
class Student extends User
{
public function mentoria(){
return $this->belongsTo(Mentoria::class)->with('teacher');
}
}
Mentoria Model:
public function teacher(){
return $this->belongsTo(Teacher::class);
}
public function students(){
return $this->hasMany(Student::class);
}
In the end, you'll have all the info you need from the mentorship when you call objects like this:
Teacher::with('mentorias')->get();
// This will show the Teacher's mentorias and the students in each one
Student::with('mentoria')->get();
// This will show the Student's mentoria and its teacher
Mentoria::with(['teacher', 'students'])->get();
// This will show the teacher and the students for each mentoria

error occured when save data using hasmany relationnship in laravel

Create hasmany relatioship in vehicle model and insert data in vehicle and vehicle_staff table. data successfully insert in vehicle table but when store in vehicle_staff following error appear.
Error Comes:
Type error: Argument 1 passed to
Illuminate\Database\Eloquent\Relations\HasOneOrMany::save() must be an
instance of Illuminate\Database\Eloquent\Model, array given, called in
E:\xampp\htdocs\laravel-projects\collegeaccounting\app\Http\Controllers\Transport\VehicleController.php
on line 53
Vehicle Staff Table Schema:
Schema::create('vehicle_staffs', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->unsignedInteger('vehicles_id');
$table->unsignedInteger('staffs_id');
$table->boolean('status')->default(1);
});
Has Many Relationship on Vehicle Model:
class Vehicle extends BaseModel
{
protected $fillable = ['created_by', 'last_updated_by', 'number', 'type', 'model', 'description', 'status'];
public function staff(){
return $this->hasMany(Staff::class);
}
}
Store Function:
public function store(AddValidation $request)
{
$request->request->add(['created_by' => auth()->user()->id]);
$vehicle = Vehicle::create($request->all());
if ($request->has('staffs_id')) {
$staffs = [];
foreach ($request->get('staffs_id') as $staff) {
$staffs[$staff] = ([
'vehicles_id' => $vehicle->id,
'staffs_id' => $staff
]);
}
$vehicle->staff()->save($staffs);
}
$request->session()->flash($this->message_success, ' Created Successfully.');
return redirect()->route($this->base_route);
}
It seems you are creating many to many relationships, that is to say, a vehicle can belongs to many staffs, and a staff can have many vehicles. So, vehicle_staffs is a intermediate table (or pivot table) between vehicle model and staff model.
For Vehicle model, you should change the staff method to:
public function staff(){
return $this->belongsToMany(Staff::class, 'vehicle_staffs', 'vehicles_id', 'staffs_id');
}
To update many to many relationships, you can attach the staff ids to vehicle:
$vehicle->staff()->attach($staffIds);
and the code change of your store function:
if ($request->has('staffs_id')) {
$staffIds = $request->get('staffs_id');
$vehicle->staff()->attach($staffIds);
}
I don't know what version of Laravel you are using, so I assume you are on Laravel 5.x.
You should probably use saveMany() if you want to save more than one object. It takes a Collection or an array of Models as a parameter.
From the documentation:
If you need to save multiple related models, you may use the saveMany method:
$post = App\Post::find(1);
$post->comments()->saveMany([
new App\Comment(['message' => 'A new comment.']),
new App\Comment(['message' => 'Another comment.']),
]);

Laravel 5.4 relationship

Hi I need to display users items from table name Items.
I have 3 models.
User model:
public function userItem()
{
return $this->hasMany('App\UserItem', 'item_id');
}
UserItem model:
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
What to write to Item Model to make this relationship successful. So I could display items from items table.
If I now do this:
I get info from user_items table from DB.
when I do this #foreach(Auth::user()->userItem as $item) I get this:
Column not found: 1054 Unknown column 'user_items.user_items' in
'where clause'
I think you want to use many to many relation
you have 2 models User and Item
and 3 tables : -users -items -user_items
User Model should be like this:
public function userItem()
{
return $this->belongsToMany('App\Item','user_items','user_id','item_id');
}
and Item Model:
public function user()
{
return $this->belongsToMany('App\User','user_items','item_id','user_id');
}
and you need a table that you named it user_items
and you dont need to define userItem model you can remove relations in this model
in your blade use this code:
#foreach(Auth::user()->userItem as $item)
You are exhibiting a many-to-many relatioship, and yet using methods for one-to-many relationships. For a many to many relationship, use the following code in your models:
//user model:
public function userItem()
{
return $this->hasMany('App\UserItem', 'user_items', 'user_id', 'item_id');
}
//userItem Model:
public function user()
{
return $this->hasMany('App\User', 'user_items', 'item_id', 'user_id');
}
For a many-to-many relationship, you need a hasMany method on both your models.
For information on the parameters to the hasMany method as well as other information on many-to-many relationships, please read the documentation on many-to-many relationships: https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
Hope this helps.

Querying with relationship not working

I am trying to grab an InvoiceDetails record and the matching Product record via the product foreign key.
This isn't working:
$r = InvoiceDetail::with('products')->find(52184)->toArray();
The 2 database calls are
SELECT * FROM `invoice_details` WHERE `id` = '52184' LIMIT 1
SELECT * FROM `products` WHERE `products`.`id` in ('0')
Where am I going wrong?
Table Structure of invoice details:
Schema::create('invoice_details', function (Blueprint $table) {
$table->increments('id');
$table->integer('invoice_id')->unsigned();
$table->integer('product_id')->unsigned();
$table->integer('quantity');
$table->foreign('product_id')->references('id')->on('products')->onDelete('restrict')->onUpdate('cascade');
$table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade')->onUpdate('cascade');
});
Table structure for Products:
Schema::create('products', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
});
Products Model:
class Product extends \Eloquent
{
public function products()
{
return $this->hasMany('InvoiceDetail');
}
}
Invoice Details Model:
class InvoiceDetail extends \Eloquent
{
public function details()
{
return $this->belongsTo('Invoice');
}
public function products()
{
return $this->belongsTo('Product');
}
}
Your relationships are weird. (Okay, that wasn't really any longer.)
Assuming that an Invoice can belong to many Products (with specific details about each such as quantity), and that a Product can belong to many Invoices, you have a classic pivot table scenario. In which case, you're doing extra work and making life more difficult for yourself than it has to be.
If that's the case, there are a few steps you can take to reduce your code and make life easier:
Remove the InvoiceDetails model. Laravel can handle pivot tables on its own pretty well. So unless you have something really custom that you need the pivot table model to handle, you don't need it.
Update your Product model. You have a products() method in the Product model. That doesn't really make any sense. Don't products belong to invoices? Let's fix that.
class Product extends Eloquent
{
public function invoices()
{
return $this->belongsToMany('Invoice', 'invoice_details', 'product_id', 'invoice_id');
}
}
The additional parameters indicate the pivot table name, the column name for the Product model identifier, and the column name for the Invoice model identifier, respectively.
Update your Invoice model. You didn't paste it here, but I'll assume it has a relationship for invoice details. If not, well, oops! Because an invoice can belong to many products, essentially the inverse of the products relationship we just defined, it's defined it pretty much the exact same way.
class Invoice extends Eloquent
{
public function products()
{
return $this->belongsToMany('Product', 'invoice_details', 'invoice_id', 'product_id');
}
}
You now have a many-to-many relationship between Products and Invoices, that is retrieved using intuitive relationship methods! Huzzah.
Hey wait, where's my quantity?
You'll have to figure that one out on your own. :)
Got the answer (there is 2 hours of my life I'm never getting back) I had to manually add the fk and pk. So in my InvoiceDetails model it should have looked like this
public function products()
{
return $this->belongsTo('Product', 'product_id', 'id');
}

How to link data from one table to another using Laravel 4?

I have a customers migration table
Schema::create('customers', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('address');
$table->string('phone');
$table->string('email');
});
and a tripsheet migration table which goes like this
Schema::create('tripsheets', function(Blueprint $table) {
$table->increments('id');
$table->integer('tripsheet_num');
$table->integer('customer_id');
$table->string('date');
$table->string('customer_name');
$table->string('customer_address');
$table->string('customer_phone');
$table->string('rep_address');
$table->string('rep_phone');
});
I have also created a customer eloquent,
class Customer extends Eloquent {
public $timestamps = true;
public $table = 'customers';
protected $fillable = ['name', 'address', 'phone', 'email'];
public function tripsheets(){
return $this->belongsTo('Tripsheet', 'name', 'address', 'phone');
}
}
and a tripsheet model,
class Tripsheet extends Eloquent {
public $timestamps = true;
public $table = 'tripsheets';
protected $fillable = [];
public function customer(){
return $this->hasMany('Customer', 'name', 'address', 'phone');
}
}
and my routes.php goes like this,
Route::get('/', function()
{
return View::make('hello');
});
Route::controller('/customers', 'CustomerController');
Route::controller('/tripsheets', 'TripsheetController');
I would like to link the customer_name, customer_address, customer_phone from the tripsheet table to the name, address, phone of the customer table. I also want to know how to route them and fetch them as a json data to be used by angular JS to display the result.
now should i create a third table to link these two? Or should i call it with Customer::with('tripsheets')->all();in the routes/controller?
I also want to know how to route them and fetch them as a json data to be used by angular JS to display the result.?
I overlooked your code and after user315.. answer I see the problem. The belongsTo and hasMany has wrong arguments.
You need to change your code to the following to make it work:
class Customer extends Eloquent {
public function tripsheets(){
return $this->belongsTo('Tripsheet', 'tripsheet_num');
}
}
class Tripsheet extends Eloquent {
public function customer(){
return $this->hasMany('Customer', 'tripsheet_num');
}
}
The problem is that you have the field tripsheet_num in the table tripsheets. Laravel tries to find a field called tripsheet_id inside the tripsheets table when you use the belongsTo(Tripsheet) on Customer. In your case this key field is named different and is not found, and so the relation is not set.
Same goes for hasMany() only then it looks in the other table for the key field.
See the relation documentation for more info: One-to-one relation & hasMany
You only need the first argument in your belongsTo and hasMany method. The others are likely the reason why it's not working. They are meant for telling Eloquent what the foreign key is, and if you are specifying the foreign key as name, then it's obviously not going to work right.
Since you have proper naming conventions, Eloquent can accurately guess what they should be and you shouldn't need them.

Categories