Here I'm trying to save article's category with given id which exists in categories table,I have set the relationships but when trying to save, Laravel tries to insert new row in articles table not in the pivot table .
Here is the error:
*Unknown column 'category_id' in 'field list' (SQL: update `articles` set `category_id` = 1, `updated_at` = 2015-11-16 13:15:32 where `id` = 53)*
And these are relations and pivot table
class Article extends Model implements SluggableInterface
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
class Category extends Model implements SluggableInterface
{
public function articles()
{
return $this->hasMany('App\Article','article_category');
}
}
//pivot table
Schema::create('article_category',function(Blueprint $table){
$table->integer('article_id')->unsigned()->index();
$table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
And here is my save function
public function store(ArticleRequest $request)
{
$article=Auth::user()->articles()->create($request ->all());
$category =Category::find($request ->input('category'));
$article->category()->associate($category)->save();
}
Your relationship type is many to many relotionship, not one to many.
Your models should be like this:
class Article extends Model implements SluggableInterface
{
public function categories()
{
return $this->belongsToMany('App\Category', 'article_category');
}
}
class Category extends Model implements SluggableInterface
{
public function articles()
{
return $this->belongsToMany('App\Article', 'article_category');
}
}
If you want one to many relationship not need 'article_category' table your migrations should like this:
Schema::create('articles',function(Blueprint $table){
$table->integer('id')->increments();
$table->string('title');
$table->text('content');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
and models:
class Article extends Model implements SluggableInterface
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
class Category extends Model implements SluggableInterface
{
public function articles()
{
return $this->hasMany('App\Article');
}
}
Not sure but it looks to me that the relations should be:
articlass Article extends Model implements SluggableInterface
{
public function category()
{
return $this->belongsTo('App\ArticleCategory', 'category_id');
}
}
and
class Category extends Model implements SluggableInterface
{
public function articles()
{
return $this->hasMany('App\ArticleCategory','article_id');
}
}
so it references to the pivot table
Related
I have 2 model user and team, every team can have multiple users and each user can be in any team , so I wanna make a many to many relation.
I'm trying to customize something , I don't wanna use the laravel convention for pivot table.
Here is my User Migration:
class CreateUsersTable extends Migration
{
protected $collection = "table_users";
public function up()
{
Schema::create( $this->collection
, function (Blueprint $table) {
$table->string('_id');
$table->string('username')->unique();
$table->string('password');
}
}
}
And here is my Team Migration :
class CreateTeamTable extends Migration
{
protected $collection = "table_team";
public function up()
{
Schema::create( $this->collection
, function (Blueprint $table) {
$table->string('_id');
$table->string('name')->unique();
}
}
}
So my problem is when I want to create method for the relation in User Model and Team Model.
in Team Model :
public function users()
{
return $this->belongsToMany(User::class, '??', '??' , '??'); // what should I insert in '??'
}
in User Model :
public function teams()
{
return $this->belongsToMany(Team::class, '??', '??' , '??'); // what should I insert in '??'
}
And also how to create Pivot table without using any convention:
pivot table that I created so far:
class CreateUsersTeamTable extends Migration
{
protected $collection = "team_user_pivot";
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create( $this->collection
, function (Blueprint $table) {
$table->id();
$table->string('??'); // please help me to fill this field
$table->string('??'); // please help me to fill this field
$table->timestamps();
});
}
There are '??' in User Model and Team model and Pivot table . help me to fill up each of them
It's not quite as simple as filling in the fields, as you're using a string for the foreign key as well as not follwing the standard namig conventions.
create_team_user_pivot
protected $collection = "team_user_pivot";
public function up()
{
Schema::create($this->collection, function (Blueprint $table) {
$table->id();
$table->string('team__id')->references('_id')->on('teams');
$table->string('user__id')->references('_id')->on('users');
$table->timestamps();
});
}
You also need to edit the models:
User
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
public $table = 'table_users';
public $incrementing = false;
public $keyType = 'string';
protected $primaryKey = '_id';
protected $fillable = [
"_id",
"username",
"password"
];
public function teams()
{
return $this->belongsToMany(Team::class, 'team_user_pivot', 'user__id', 'team__id');
}
}
Team
class Team extends Model
{
use HasFactory;
public $table = 'table_teams';
public $incrementing = false;
public $keyType = 'string';
protected $primaryKey = '_id';
protected $guarded = [];
public function users()
{
return $this->belongsToMany(User::class, 'team_user_pivot', 'team__id', 'user__id');
}
}
you have to create another model with migration
class UserTeam extends Model
{
public $timestamps = false;
protected $table = 'user_has_team';
protected $fillable = ['user_id', 'team_id'];
}
in your team model
public function users()
{
return $this->belongsToMany(User::class, 'user_has_team', 'user_id', 'team_id');
}
in your user model
public function teams()
{
return $this->belongsToMany(Team::class, 'user_has_team', 'team_id', 'user_id');
}
I'm trying to retrieve all product categories with all their respective products, one product belongs to one product category and one product category can have many products.
When I retrieve productCategories I get the following error:
Illuminate \ Database \ QueryException (42S22)
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'products.product_category_id' in 'where clause' (SQL: select * from `products` where `products`.`product_category_id` in (1, 2, 3))
This is my migrations file for product and categories:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class ProductsAndCategories extends Migration
{
public function up()
{
//CREATE PRODUCT CATEGORIES TABLE
Schema::create('productcategories', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->string('description')->nullable();
$table->string('image')->nullable();
$table->timestamps();
});
// CREATE PRODUCTS TABLE
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('productcategory_id')->index();
$table->foreign('productcategory_id')->references('id')->on('productcategories');
$table->string('title');
$table->string('description')->nullable();
$table->string('body')->default('');
$table->string('image')->nullable()->default(config('globals.dummy_image'));
$table->boolean('isVisible')->default(true);
$table->integer('stockLeft')->default(0);
$table->decimal('halfPrice', 5,2)->default(0.00);
$table->decimal('fullPrice', 5,2)->default(0.00);
$table->decimal('finalPrice', 5,2)->default(0.00);
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('products');
Schema::dropIfExists('productcategories');
}
}
And my two related models:
Product:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $table = 'products';
public function productcategory()
{
return $this->belongsTo('App\Models\ProductCategory', 'productcategory_id');
}
}
ProductCategory:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ProductCategory extends Model
{
protected $table = 'productcategories';
public function products()
{
return $this->HasMany('App\Models\Product');
}
}
First of all you need to define right keyword for hasMany relation. Change HasMany to hasMany();
and Model look like this:-
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $table = 'products';
protected $primary_key = 'product_id';
public function productcategory()
{
return $this->belongsTo('App\Models\ProductCategory', 'productcategory_id');
}
}
and second model look like this: -
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ProductCategory extends Model
{
protected $table = 'productcategories';
protected $primary_key = 'id';
public function products()
{
return $this->HasMany('App\Models\Product', 'id');
}
}
and Query will be look like this: -
$product_list = Product::with('productcategory')->get();
this query will give you all records and category of particular record.
I have database like this
opportunities
Id
contact_id
contacts
Id
User_id
users
id
User model :
class User extends Authenticatable
{
public function Contact()
{
return $this->hasMany('Customer\model\Contact');
}
}
Contact model:
class Contact extends Model
{
public function Opportunity()
{
return $this->hasMany('Sale\Model\Opportunity');
}
public function User()
{
return $this->belongsTo('App\User');
}
}
Opportunity model
class Opportunity extends Model
{
public function Contact()
{
return $this->belongsTo('Customer\Model\Contact');
}
public function User()
{
return $this->hasManyThrough('App\User','Customer\Model\Contact','user_id','id');
}
}
When on controller
$Opportunity = Opportunity::with('User')->paginate(10);
print_r($Opportunity->User);
Show me wrong data.
I'm new to Laravel and am having a bit of a hard time cracking how relationships work. I'm building a simple e-commerce application, where each user has some orders, and order has one or many sub-orders, and each sub-order is linked to only one item (please don't comment on my scheme yet; for now I just need to figure out Eloquent and will be doing refactoring later :) ).
Following are my models:
class Order extends Model
{
//timestamp
protected $created_at;
public function sub_orders() {
return $this->hasMany('App\SubOrder');
}
public function user() {
return $this->belongsTo('App\User');
}
}
class SubOrder extends Model
{
protected $fillable = array('delivery_date', 'quantity', 'total_price', 'delivery_status');
public function item() {
return $this->hasOne('App\Item');
}
public function order() {
return $this->belongsTo('App\Order');
}
}
class Item extends Model
{
//note - slug is kind of categorization and is common to many items
protected $fillable = array('sku', 'name', 'slug', 'unit_price');
}
And here are the migrations:
class CreateOrdersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('orders', function (Blueprint $table) {
$table->increments('id');
$table->timestamp('created_at');
//foreign keys
$table->unsignedInteger('user_id')->after('id');
$table->foreign('user_id')->references('id')->on('users') ->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('orders');
}
}
class CreateSubOrdersTable extends Migration
{
public function up()
{
Schema::create('sub_orders', function (Blueprint $table) {
$table->increments('id');
$table->date('delivery_date');
$table->decimal('quantity', 5, 2);
$table->decimal('total_price', 7, 2);
$table->enum('delivery_status', ['pending_from_farmer', 'ready_for_customer', 'out_for_delivery', 'delivered']);
//foreign keys
$table->unsignedInteger('order_id')->after('id');
$table->foreign('order_id')->references('id')->on('orders') ->onDelete('cascade');
$table->unsignedInteger('item_id')->after('order_id');
$table->foreign('item_id')->references('id')->on('items') ->onDelete('cascade');
});
}
public function down()
{
Schema::dropIfExists('sub_orders');
}
}
class CreateItemsTable extends Migration
{
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->increments('id');
$table->string('sku')->unique();
$table->string('name');
$table->string('slug');
$table->decimal('unit_price', 5, 2);
});
}
public function down()
{
Schema::dropIfExists('items');
}
}
The problematic expression is why I write App\Order::all()[0]->sub_orders[0]->item in my web.php and get the following error:
SQLSTATE[42703]: Undefined column: 7 ERROR: column items.sub_order_id does not exist
LINE 1: select * from "items" where "items"."sub_order_id" = $1 and ...
^ (SQL: select * from "items" where "items"."sub_order_id" = 1 and "items"."sub_order_id" is not null limit 1)
I don't understand why it's looking for sub_order_id in the items table. And what's the right way to go about doing it?
Overall: define the 1-to-1 relationship using hasOne or belongsTo will affect the target table where Laravel find the foreign key. hasOne assume there is a my_model_id in target table.And belongsTo assume there is a target_model_id in my table.
class SubOrder extends Model
{
public function item() {
return $this->hasOne('App\Item', 'id', 'item_id');
}
}
or
class SubOrder extends Model
{
public function item() {
return $this-> belongsTo('App\Item');
}
}
According to Laravel Doc
class User extends Model
{
/**
* Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('App\Phone');
}
}
Eloquent determines the foreign key of the relationship based on the model name. In the above case, the Phone model is automatically assumed to have a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method:
$this->hasOne('App\Phone', 'foreign_key', 'local_key');
Or Defining The Inverse Of The Relationship
class Phone extends Model
{
/**
* Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('App\User');
}
}
In the example above, Eloquent will try to match the user_id from the Phone model to an id on the User model.
Your SubOrder item has relationship of type OneToOne (hasOne is bidirectional) with an Item.
So Eloquent expects to have sub_order_id in the items table.
So the solution is to define the inverse of this relationship (belongsTo) in the Item model
I have the following table I can't use Order hasMany Product b/c Product don't have a foreign order_id. I want to access everything through Invoice, is that possible?
I try to use Has Many Through but that is a A->B->C Relationship, I think want I setup need A->B<-C Relationship.
users table
| id |
invoice table
| id | user_id |
order table
| id | invoice_id | product_id |
product table
| id |
I wish to access all data through invoice table
INVOICE MODEL
class invoice extends Model {
public function user() {
return $this->belongsTo('App\User');
}
public function order() {
return $this->belongsTo('App\Order');
}
}
ORDER MODEL
class Order extends Model
{
public function invoice()
{
return $this->belongsTo('App\Invoice');
}
}
PRODUCT MODEL
class product extends Model
{
protected $table = 'products';
public function order()
{
return $this->belongsTo('App\Order');
}
}
This is how your models should look like according to the schema.
INVOICE MODEL
class invoice extends Model {
public function user() {
return $this->belongsTo('App\User');
}
public function order() {
return $this->hasMany('App\Order');
}
public function products() {
return $this->belongsToMany('App\Product', 'order', 'invoice_id', 'product_id');
}
}
ORDER MODEL
class Order extends Model
{
public function invoice()
{
return $this->belongsTo('App\Invoice');
}
public function product()
{
return $this->belongsTo('App\Product');
}
}
PRODUCT MODEL
class product extends Model
{
protected $table = 'products';
public function orders()
{
public function products() {
return $this->belongsToMany('App\Invoice', 'order', 'product_id', 'invoice_id');
}
}
If this is not what you want, you will probably need to change the schema.