I am a new in Laravel and I am trying to get the value from third column id in pivot table
I have 3 tables and 4th table is pivot table, so my table structure is as follow
TABLE Product Structure
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->foreignId('category_id')->constrained();
$table->timestamps();
});
Table Attributes Structure
Schema::create('attributes', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Table Attribute Value Structure
Schema::create('attribute_values', function (Blueprint $table) {
$table->id();
$table->string('value');
$table->foreignId('attribute_id')->constrained();
$table->timestamps();
});
and I also make pivot table attribute_product
Schema::create('attribute_product', function (Blueprint $table) {
$table->foreignId('product_id')->constrained();
$table->foreignId('attribute_id')->constrained();
$table->foreignId('attribute_value_id')->constrained();
});
<<<<<<<<<<< MODELS OF TABLE >>>>>>>>>>>>>>>>>>>>>>
1.Table Product
class Product extends Model
{
use HasFactory;
public function attributes()
{
return $this->belongsToMany(Attribute::class)->using(AttributeProduct::class)->withPivot('attribute_value_id');
}
}
2.Table Attribute
class Attribute extends Model
{
use HasFactory;
public function products()
{
return $this->belongsToMany(Product::class)->using(AttributeProduct::class)->withPivot('attribute_value_id');
}
}
Table Attribute Value
class AttributeValue extends Model
{
use HasFactory;
protected $guarded = [];
public function attribute_product()
{
return $this->hasMany(AttributeProduct::class, 'attribute_value_id');
}
}
AND also I make a model of pivot table
use Illuminate\Database\Eloquent\Relations\Pivot;
class AttributeProduct extends Pivot
{
use HasFactory;
public function value()
{
return $this->belongsTo(AttributeValue::class,'attribute_value_id');
}
}
<<<<<<<<<<<<<< DATA IN TABLES >>>>>>>>>>>>>>>>>>>>>>>>
TABLE PRODUCT
ID TITLE category_id
6 Samsung S22 2
TABLE ATTRIBUTE
ID NAME
1 SIZE
2 COLOR
TABLE ATTRIBUTE VALUES
ID VALUE attribute_id
1 SM 1
2 M 1
3 RED 2
4 BLUE 2
Pivot Table values attribute_product
product_id attribute_id attribute_value_id
6 1 1
6 2 4
Now I am using these commands in controller to find the value
$p = Product::find(6);
foreach($p->attributes as $value){
echo $value->name." = ". $value->pivot->attribute_value_id->value."<br>";
}
when I try to get the value on base of attribute_value_id from pivot table its give me this error
ErrorException
Attempt to read property "value" on int
So how I can solve this problem.
Thanks
The pivot relation value should be a hasOne, not a belongsTo.
class AttributeProduct extends Pivot
{
use HasFactory;
public function value()
{
return $this->hasOne(AttributeValue::class, 'id', 'attribute_value_id');
}
}
So in your foreach, you can now do:
foreach($p->attributes as $attribute){
echo $attribute->name." = ". $attribute->pivot->value->value."<br>";
}
Also try to keep your variable names straight. Don't write $p->attributes as $value if $value is clearly an $attribute.
Related
There are two Models. One is TradeLicence and another is BusinessCategory.
I have already established relationship between them. In TradeLicence there is a foreign key category_id which local key is id of BusinessCategory.
Trade Licence Model
class TradeLicence extends Model
{
use SoftDeletes;
protected $fillable = ['slug', 'name', 'category_id'];
public function businessCategories()
{
return $this->belongsTo(BusinessCategory::class,'category_id','id');
}
}
trade_licences migration Table:
class CreateTradeLicencesTable extends Migration
{
public function up()
{
Schema::create('trade_licences', function (Blueprint $table) {
$table->id();
$table->string('slug')->unique();
$table->foreignId->('category_id');
$table->string->('name');
$table->timestamps();
});
}
}
Business Category Model:
class BusinessCategory extends Model
{
use SoftDeletes;
protected $fillable = ['slug', 'name', 'fees'];
}
business_categories migration table:
class CreateBusinessCategoriesTable extends Migration
{
public function up()
{
Schema::create('business_categories', function (Blueprint $table) {
$table->id();
$table->string('slug')->unique();
$table->string('name');
$table->double('fees');
$table->timestamps();
});
}
For adding a "Trade Licence", I need to select a "Business Category" and it stores the value
incategory_id column of trade_licencestable. I'm able to retrieve the name and fees value through the relationship inside TradeLicense model.
The problem is:
There is a another Model named DailyEarning. The show() method of DailyEarningController will display fees amount (fee of selected category, which was selected at the time of creating a new trade licence) and created_at and updated_at value of each Trade License.
My Question is:
How to get the values of fees, created_at and updated_at or which Query should I use to retrieve the values by using "Eloquent"?
I have a small question on my LARAVEL API. How can I return and concatenate the data of a pivot table in the same resource? I have 3 tables, inventories, products and inventories_products. This last table has stock and price data (of the product, because they vary depending on the inventory) and I want to list the products and show that price and stock (which comes from the pivot table)
I upload the product controller, the inventory and product models and the product resource. By the way, as I am doing it right now price and stock returns null.
So far, in my ProductController:
public function index()
{
return ProductResource::collection(Product::with('inventories')->paginate(25));
}
In my product model:
class Product extends Model
{
public function inventories()
{
return $this->belongsToMany('App\Inventory','inventory_product')->withPivot('price','stock')->withTimestamps();
}
}
In my inventory model:
class Inventory extends Model
{
public function products()
{
return $this->belongsToMany('App\Product','inventory_product')->withPivot('price','stock')->withTimestamps();
}
}
In my product Resource:
public function toArray($request)
{
return [
'id'=>$this->id,
'name'=>$this->name,
'description'=>$this->description,
'short_description'=>$this->short_description,
'category'=>$this->category,//category_id
'url'=>$this->url,
'image'=>$this->image,
'relevant'=>$this->relevant,
'month'=>$this->month,
'price'=>$this->price,
'stock'=>$this->stock
];
}
my migration inventory table:
Schema::create('inventories', function (Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->unsignedInteger('city_id');
$table->timestamps();
$table-> foreign('city_id')->references('id')->on('cities')->onDelete('cascade');
});
my migration product table:
Schema::create('products', function (Blueprint $table)
{
$table->increments('id');
$table ->string('name');
//$table ->integer('stock');
$table ->string('description');
$table ->string('short_description');
$table ->unsignedInteger('category');//category_id
//$table ->integer('price');
$table ->string('url');
$table ->string('image');
$table ->boolean('relevant');
$table ->boolean('month');
$table->timestamps();
$table-> foreign('category')->references('id')->on('categories')->onDelete('cascade');
});
And my inventory_product migration table:
$table->increments('id');
$table->integer('inventory_id')->unsigned();
$table->integer('product_id')->unsigned();
$table ->integer('price');
$table ->integer('stock');
$table->timestamps();
$table-> foreign('inventory_id')->references('id')->on('inventories')->onDelete('cascade');
$table-> foreign('product_id')->references('id')->on('products')->onDelete('cascade');
with that, I'm getting:
{
"id": 1,
//staff on product,
"price": null,
"stock": null
}
and I should be getting:
{
"id": 1,
//staff on product,
"price": 123,//data on the pivot table
"stock": 123//data on the pivot table
}
EDIT: Actually I should get something like:
{
"id": 1,
//staff on product,
[
"inventory_id": 1,//data on the pivot table
"price": 123,//data on the pivot table
"stock": 123//data on the pivot table
]
[
"inventory_id": 2,//data on the pivot table
"price": 333,//data on the pivot table
"stock": 333//data on the pivot table
]
}
In the case that the product would be on more than one inventory, right?
Thank you in advance :)
your product might be in more than 1 inventory , you are not identifying which inventory your are getting items from , you can access it using $this->inventories
put you don't need that ,
the answer depends on your logic , if 1 product might be in more than inventory you should return the collection of the inventories or sum the stock or what ever you need to view ,
if 1 product exist in 1 inventory you should edit the function to belongsTo and your code should work
I think the problem is your index() function is trying to return a collection of Product Models which will only have parameters of that Model. If you want just the whole array you could do a join on that collection:
https://laravel.com/docs/5.8/queries#joins
your relation is many to many
if you need to access pivot table for this relation can be get one product and first related inventory or other related from related rows than can access pivot
for example
in your Resource
public function toArray($request)
{
return [
'id'=>$this->id,
'name'=>$this->name,
'description'=>$this->description,
'short_description'=>$this->short_description,
'category'=>$this->category,//category_id
'url'=>$this->url,
'image'=>$this->image,
'relevant'=>$this->relevant,
'month'=>$this->month,
'price'=>$this->inventories->first->price,
'stock'=>$this->inventories->first->stock
];
}
I have 2 models and both they aren't using the ID from the table, but the field internal_id. So i customized my pivot schema but i got stuck on connecting them. Im getting the error:
General error: 1215 Cannot add foreign key constraint (SQL: alter table `seoshop_category_product` add constraint seoshop_category_product_category_id_foreign foreign key
(`category_id`) references `seoshop_categories` (`internal_id`) on delete cascade)
The code for the migration is:
Schema::create('seoshop_category_product', function(Blueprint $table)
{
$table->increments('id');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('internal_id')->on('seoshop_categories')->onDelete('cascade');
$table->integer('product_id')->unsigned()->index();
$table->foreign('product_id')->references('internal_id')->on('seoshop_products')->onDelete('cascade');
$table->timestamps();
});
Both fields as seoshop_products.internal_id as seoshop_categories.internal_id are existing, column types are both int(11).
Can someone tell me what is going wrong?
Migrations for the tables seoshop_categories and seoshop_products
//seoshop_products
public function up()
{
Schema::create('seoshop_products', function(Blueprint $table)
{
$table->increments('id');
$table->integer('shop_id');
$table->integer('internal_id')->signed()->index();
$table->integer('internal_variant_id');
$table->string('visible');
$table->string('tags');
$table->timestamps();
});
}
//Table seoshop_categories
public function up()
{
Schema::create('seoshop_categories', function(Blueprint $table)
{
$table->increments('id');
$table->integer('internal_id')->signed()->index();
$table->datetime('seoshop_created_at');
$table->datetime('seoshop_updated_at');
$table->text('full_description');
$table->timestamps();
});
}
Okay so now i've create my table, and its working as how it should. I need to get my product with categories (many-2-many). So i use
SEOshopProduct::find(1)->with('categories')->get();
After a dd() the categories are empty and i've looked into my query how it is called:
[8] array(3) {
["query"] "select `seoshop_categories`.*, `seoshop_category_product`.`product_id` as `pivot_product_id`, `seoshop_category_product`.`category_id` as `pivot_category_id` from `seoshop_categories` inner join `seoshop_category_product` on `seoshop_categories`.`id` = `seoshop_category_product`.`category_id` where `seoshop_category_product`.`product_id` in (?)"
["bindings"] array(1) {
[0] 8
}
["time"] 0.37
}
The internal_id's of both products and categories is greater then 10.000 and i dont see it back in the query.
My models:
Product:
public function categories(){
return $this->belongsToMany('SEOshopCategory', 'seoshop_category_product', 'product_id', 'category_id');
}
Categories:
public function products(){
return $this->belongsToMany('SEOshopCategory', 'seoshop_category_product', 'category_id', 'product_id');
}
To setup the foreign key constraint, the field definitions need to match exactly. In this case, however, the seoshop_category_product.category_id field is defined as an UNSIGNED INT, but the referenced seoshop_categories.internal_id field is defined as a SIGNED INT. The same is true for the foreign key for your products.
So, you can either update the internal_id fields on your categories and products tables to be unsigned, or you can update your foreign key fields on your pivot table to be signed.
You can tell Laravel what the local and foreign keys are when you define the relationship in your model...
class Product extends Eloquent
{
public function categories() {
return $this->hasMany('Category', 'internal_id', 'id');
}
}
class Category extends Eloquent
{
public function products() {
return $this->hasMany('Product', 'internal_id', 'id');
}
}
I have a table column which holds an array of subject ids selected by the user. There is another table for these subjects and their values. I need to return the values corresponding to the ids saved in the subjects column. To make it more clear suppose that a user have chosen 5 subjects out of 34 subjects and the corresponding ids are saved in the subjects column as a string like this: 2,5,11,21,23
Each of these numbers corresponds to the id of a subject in the subjects table.
//This is the subjects table
public function up()
{
Schema::create('subjects', function (Blueprint $table) {
$table->increments('id');
$table->string('subject', 20);
$table->timestamps();
});
}
//and this is the user_info table
public function up()
{
Schema::create('user_info', function (Blueprint $table) {
...
$table->string('subjects');
...
});
}
How can I return an array of subject values to a view?
// Find whichever user
$user = \App\User::find(1);
// Convert the string of subjects from a string to an array
$subjectIds = explode(',', $user->subjects);
// Load all subjects which match the ids within the subjectIds array
$subjects = \App\Subjects::whereIn($subjectIds)->get();
// Do something with the subjects
foreach($subjects as $subject) {
// Output the subject name
var_dump($subject->name);
}
After some searching around I found that maybe the best solution for my problem was to use the Many to Many relationship. So I removed the subjectscolumn from user_info table. Then I created the pivot table subject_user to save the id of user and their subjects ids in this table.
This is the pivot table schema:
Schema::create('subject_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->index();
$table->integer('subject_id')->index();
$table->timestamps();
});
Then in the User and Subject models I established the proper many to many relationship as follows:
//User Model
public function subjects()
{
return $this->belongsToMany('App\Subject')->withTimestamps();
}
//Subject Model
public function users()
{
return $this->belongsToMany('App\User');
}
Finally in the controller i used the attach() and sync() methods to populate or update the pivot table.
//In store method
$user->subjects()->attach($subjects);
//In update method
$user->subjects()->sync($subjects);
The difference between attach and syn is described here.
I have this two tables a User Table and the Attendance table, Here is what I want to do:
While inserting a User on the User table, the Attendance table will also be updated (the user_id of the User Table will be Inserted to the Attendance Table as a foreign key), the Primary key of my User table is Auto Increment, that's why I can't insert it manually to the Attendance Table, what should I do? Is there any cheat in laravel that can do this easily?
Here is my Controller for Register
public function register()
{
$myemployee=Employee::all();
return View::make('registration',compact('myemployee'));
}
public function registerEmp()
{
$input = Input::all();
$command = new Employee;
$command->firstname=$input['firstname'];
$command->lastname=$input['lastname'];
$command->position=$input['position'];
$command->save();
return Redirect::action('EmployeesController#register');
}
Here is my Migration
public function up()
{
Schema::create('employees',function($table)
{
$table->increments('id');
$table->text('firstname');
$table->text('lastname');
$table->text('position');
$table->timestamps();
});
public function up()
{
Schema::create('attendances', function(Blueprint $table)
{
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('employees');
$table->timestamp('intime');
$table->timestamp('offtime');
});
}
Employee.php file
<?php
class Employee extends Eloquent
{
}
?>
You can get the last inserted ID in users table by assigning the return value of User::create(), which is a static Illuminate\Database\Eloquent\Model, to a variable, then use that variable to insert user_id in your attendances table.
Here is an example:
public function registerEmp() {
$input = Input::all();
// Create an employee.
$employee = Employee::create($input);
// Create an attendance entry as well.
Attendance::create([
'user_id'=>$employee->id,
// other columns...
]);
return Redirect::action('EmployeesController#register');}