Issue with Laravel model relationships - php

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.

Related

Eloquent relationship between Hospital and Unit models in Laravel is not working as expected

I am trying to establish a one-to-many relationship between Hospital and Unit models in Laravel. A hospital can have many units, while a unit belongs to one hospital. However, the association doesn't seem to work as expected.
Here is my Hospital model:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Hospital extends Model
{
use HasFactory;
protected $primaryKey = 'id';
protected $keyType = 'string';
public $incrementing = false;
public function units()
{
return $this->hasMany(Unit::class);
}
}
And here is my Unit model:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Unit extends Model
{
use HasFactory;
protected $primaryKey = 'id';
protected $keyType = 'string';
public $incrementing = false;
public function hospital()
{
return $this->belongsTo(Hospital::class);
}
public function benefits()
{
return $this->belongsToMany(Benefit::class, 'benefit_unit');
}
}
Here is the code that I use to associate a hospital with a unit:
$unit = Unit::create($unitData);
$unit->hospital()->associate($hospital)->save();
manual code works for me:
$hospitalUnitData = [
'hospital_id' => $hospital->id,
'unit_id' => $unit->id,
];
DB::table('hospital_unit')->insert($hospitalUnitData);
schemas:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateHospitalsTable extends Migration
{
public function up()
{
Schema::create('hospitals', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('name');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('hospitals');
}
}
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUnitsTable extends Migration
{
public function up()
{
Schema::create('units', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('name');
$table->uuid('hospital_id');
$table->timestamps();
$table->foreign('hospital_id')->references('id')->on('hospitals');
});
}
public function down()
{
Schema::dropIfExists('units');
}
}
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateHospitalUnitTable extends Migration
{
public function up()
{
Schema::create('hospital_unit', function (Blueprint $table) {
$table->id();
$table->uuid('hospital_id');
$table->uuid('unit_id');
$table->timestamps();
$table->foreign('hospital_id')->references('id')->on('hospitals')->onDelete('cascade');
$table->foreign('unit_id')->references('id')->on('units')->onDelete('cascade');
});
}
public function down()
{
Schema::dropIfExists('hospital_unit');
}
}
Pivot table is only needed for many-to-many relationship.
For one-to-many relationship, all you need is a refernce ID on the model that belongs to a certain, model,
Simply think of them like this, you have hospital and unit model unit,
how do you get all units of hospital A? You simply query the Unit table with hostpal_id of hospital A (HasMany)
how do you determine what is the hospital of a unit? you get the hospital based on hostpal_id stored on that unit column (BelongsTo)
you see, you dont need an intermediate (pivot) table to connect hospital and unit.
when you call this $unit->hospital()->associate($hospital)->save(); its not updating your hospital_unit table because it updates the relationship of your Hospital and Unit relationship which is one-to-many,
which mean its just updating/adding the Hospital id to the hospital_id from the Unit table and not creating pivot entry in hospital_unit table as the relationship is not many-to-many

SQLSTATE[42S22]: Column not found: 1054 Unknown column in laravel

I'm trying to make a shopping cart with laravel and am having trouble with one of the methods
this is the error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'pedidos__produtos.pedidos_id' in 'where clause' (SQL: select id_produto, sum(total) as Total, count(1) as qtd from pedidos__produtos where pedidos__produtos.pedidos_id = 1 and pedidos__produtos.pedidos_id is not null group by id_produto order by id_produto desc)
I searched the entire code, but I did not refer this field "pedidos_id" anywhere
This error happens when I call "$pedidos[0]->pedido_produtos," in Carrinhocontroller.php
These are the related methods and migrations:
CarrinhoController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Pedidos;
use Illuminate\Support\Facades\Auth;
class CarrinhoController extends Controller
{
function __construct(){
$this->middleware('auth');
}
public function index(){
$pedidos = Pedidos::where([
'id_user' => Auth::id()
])->get();
dd([
$pedidos,
$pedidos[0]->pedido_produtos,
//$pedidos[0]->pedidos_produtos[0]->produto
]);
return view('carrinho.index', compact('pedidos'));
}
}
Pedidos.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Pedidos extends Model
{
public function pedido_produtos(){
return $this->hasMany('App\Pedidos_Produtos')
->select( \DB::raw('id_produto, sum(total) as Total, count(1) as qtd'))
->groupBy('id_produto')
->orderBy('id_produto', 'desc');
}
}
Pedidos_Produtos.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Pedidos_Produtos extends Model
{
public function produto(){
return $this->belongsTo('App\Produtos', 'id_produto', 'id');
}
}
Migration from Pedidos:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePedidosTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('pedidos', function (Blueprint $table) {
$table->increments('id');
$table->integer('id_user')->unsigned();
$table->foreign('id_user')->references('id')->on('users');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('pedidos');
}
}
and from pedidos_produtos
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePedidosProdutosTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('pedidos__produtos', function (Blueprint $table) {
$table->increments('id');
$table->integer('id_pedido')->unsigned();
$table->integer('id_produto')->unsigned();
$table->decimal('total', 6, 2)->default(0);
$table->timestamps();
$table->foreign('id_pedido')->references('id')->on('pedidos');
$table->foreign('id_produto')->references('id')->on('produtos');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('pedidos__produtos');
}
}
Can Anyone help me with that?
It generates automatically if foreignKey attribute is not defined on hasMany method.
it generates field name from classname_id pattern. Also localKey default value is class PK.
public function hasMany($related, $foreignKey = null, $localKey = null)
You can use like this.
return $this->hasMany('App\Pedidos_Produtos','id_pedido')
The problem you are experiencing is probably to do with this line:
return $this->hasMany('App\Pedidos_Produtos')
If you do not explicitly tell Laravel what the IDs are called on each table when defining a hasMany relationship, it will assume that the id is {table_name}_id which is where the pedidos_id is coming from.
Try adding the foreign and local keys to the hasMany, something like this:
return $this->hasMany('App\Pedidos_Produtos', 'id_pedido', 'id')

Undefined table: 7 ERROR: relation "expenses" does not exist

Since i am a spanish speaker, i wrote the controllers and models of income and expense in spanish; while all the rest were on english..
I renamed and changed manually Routes, Controllers, Migrations and even Models.
And when i run php artisan migrate:reset this is my error.
Undefined table: 7 ERROR: relation "expenses" does not exist (SQL: alter table "expenses" drop column "location_id")**
I use psgql and laravel 5.3
This is my code:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Expense extends Model
{
protected $fillable = ['id', 'description', 'quantity'];
public function locations()
{
return $this->hasMany('App\Location');
}
public function icons()
{
return $this->hasMany('App\Icon');
}
public function types()
{
return $this->hasMany('App\Type');
}
public function stores()
{
return $this->hasMany('App\Store');
}
}
Migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateExpensesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('expenses', function (Blueprint $table) {
$table->increments('id');
$table->float('quantity');
$table->string('description');
$table->integer('location_id')->unsigned();
$table->integer('icon_id')->unsigned();
$table->integer('type_id')->unsigned();
$table->integer('store_id')->unsigned();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('expenses');
}
}
Location Migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateLocationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('locations', function (Blueprint $table) {
$table->increments('id');
$table->string('address');
$table->float('lat');
$table->float('long');
$table->integer('store_id')->unsigned();
$table->timestamps();
$table->foreign('store_id')->references('id')->on('stores')->onDelete('cascade');
});
Schema::table('expenses', function (Blueprint $table) {
$table->foreign('location_id')->references('id')->on('locations')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('expenses', function (Blueprint $table) {
$table->dropColumn('location_id');
});
Schema::dropIfExists('locations');
}
}
Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Location extends Model
{
protected $fillable = ['id', 'address', 'lat', 'long'];
public function expenses()
{
return $this->belongsTo('App\Expense');
}
public function stores()
{
return $this->hasOne('App\Store');
}
}
Hope you can help me.
When it says
relation "expenses" does not exist
It usually happens when your expenses table must have been dropped before migration:reset rolled back CreateLocationsTable.
Check the order of execution of your migrations.
As you were trying to reset, to fix it now, open your database, drop all tables manually and execute migrate again.
Schema::table('expenses', function (Blueprint $table) {
$table->foreign('location_id')->references('id')->on('locations')->onDelete('cascade');
});
change this to
Schema::alter('expenses', function (Blueprint $table) {
$table->foreign('location_id')->references('id')->on('locations')->onDelete('cascade');
});
I had this error. I had to resolve it by adding the prefix of the database to my model. There is a way to change this in the database, and it is supposed to be changed. it's something, like $user, public. It's the schema profile. Mine is changed when I login, but for some reason the model is not binding to schema. So I had to specify it in the model. Instead of
protected $table = 'table_name';
I had to do
protected $table = 'schema_name.table_name';
Note: By schema_name or table_name, I'm not referring for you to put schema_ then the name. That is just so it's easier to read.
The model is located in the model folder under the App/Models folder depending on which version of Laravel you using and how your Models are organized. If your model name is not the same as the table name, then you will need to put the protected $table. But if the schema is not there, then you will need to add that.
I do have this set in my DB_DATABASE_SECOND= in .env file. But it somehow still doesn't pick up the prefix.
But yeah. Pretty much I couldn't find the answer anywhere, but I
Solution found in:
Laravel assumes the database table is the plural form of the model name
https://laravel.com/docs/8.x/eloquent#table-names
you need to declare the singularity name of your table.
add this line
protected $table = 'expense'
at the end of your model file
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Expense extends Model
{
protected $fillable = ['id', 'description', 'quantity'];
public function locations()
{
return $this->hasMany('App\Location');
}
public function icons()
{
return $this->hasMany('App\Icon');
}
public function types()
{
return $this->hasMany('App\Type');
}
public function stores()
{
return $this->hasMany('App\Store');
}
protected $table = 'expense';
}

How to make one to many relationship in laravel

I'm trying to make a one to many relationship using eloquent model and want to show the products in the specified category
that is my product model :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\softDeletes;
class Product extends Model
{
use softDeletes;
protected $table='products';
public function category(){
return $this->belongsTo('App\Category');
}
}
And that is my category model :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\softDeletes;
class Category extends Model
{
use softDeletes;
protected $table='category';
public function product(){
return $this->hasMany('App\Product','category_id','id');
}
}
And that's the product controller :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Product;
use App\Category;
class productsController extends Controller
{
public function getShow($id,Request $request){
$in=$request->get('id');
$category=Category::all();
$product=Product::find($id);
$products=$product->category()->where('category_id','=',$in);
return view ('contents.products')->with('products',$products)
->with('category',$category);
}
}
And this is the product table :
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('category_id');
$table->string('describtion');
$table->string('image_name');
$table->timestamps();
$table->softDeletes();
});
}
And that is the category table :
public function up()
{
Schema::create('category', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
$table->softDeletes();
});
}
And it gives me this error : Call to a member function category() on a non-object
So how can i solve it ?
As far i understand your question :
In your controller:
$category = Category::find($id);
$products = $category->product;
Better yet you could use eager loading and forget about assigning products manually:
Controller:
$category = Category::with('product')->where('id', 1)->first();
Hope this help you .

Wrong table when updating "Belongs To" relationships in Laravel

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

Categories