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 .
Related
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
I have a polling app.
Admins can create new polls. I have a belongsTo relation in my polls Model so I can later track which user created the poll.
Now I want to allow the poll admin to add users from the list of registered users so that only these users can access the poll.
Adding another hasMany relation to users to the poll model does not work because it already has the belongsTo. But what would the best way be? Simply add a field to my poll model and fill it with a list of user ids? Auth? But does that make sense for possibly hundreds of polls?
I feel like I am not seing an obvious solution here...
Thanks
Poll Model
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Poll extends Model
{
use HasFactory;
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
}
}
User model
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable, HasRoles;
...
/**
* poll relationship
*/
public function polls()
{
return $this->hasMany(Poll::class);
}
}
Poll migration
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('polls', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('name');
$table->timestamp('start_time')->nullable();
$table->timestamp('end_time')->nullable();
$table->timestamps();
$table->index('user_id');
});
}
}
User migration
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('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
}
You might want to create a a different, many to many relationship between polls and users. I call it participants.
table poll_user
poll_id
user_id
class Poll extends Model
{
public function participants()
{
return $this->belongsToMany(User::class, 'poll_user');
}
}
I have the 'people' table and each 'person' must have some 'furniture'.
I run 'migrate' and this error message appears:
QLSTATE[HY000]: General error: 1005 Can't create table
my_database.furniture (errno: 150 "Foreign key constraint is
incorrectly formed") (SQL: alter table furniture add constraint
furniture_person_id_foreign foreign key (person_id) references
people (id))
LARAVEL VERSION: 5.8
Here are my files:
2021_04_15_132404_create_persons_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePeopleTable extends Migration
{
public function up()
{
Schema::create('people', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('cpf');
$table->string('phone');
$table->softDeletes();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('people');
}
}
2021_04_16_233323_create_furniture_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateFurnitureTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('furniture', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('type');
$table->string('name');
$table->integer('person_id')->unsignedBigInteger()->nullable();
$table->foreign('person_id')->references('id')->on('people');
$table->softDeletes();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('furniture');
}
}
Person.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Person extends Model
{
use SoftDeletes;
}
Furniture.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Furniture extends Model
{
use SoftDeletes;
}
Does anyone know how to solve?
Remove $table->integer('person_id')->nullable(); from CreateFurnitureTable migration, leave the unsignedBigInteger since that's the integer column type. Just using that method us also recommended by Laravel as per the documentation on foreign keys for Laravel 5.8
$table->unsignedBigInteger('person_id');
$table->foreign('person_id')->references('id')->on('people');
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.
this is my posts table
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('prf_id')->unsigned();
$table->foreign('prf_id')->references('id')->on('profiles')->onDelete('cascade');
$table->longText('status');
$table->timestamps();
});
}
public function down()
{
Schema::drop('posts');
}
}
this my Post model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $table='posts';
protected $fillable = ['status'];
protected $hidden = [];
public function profile(){
return $this->belongsTo('App\Profile');
}
public function user(){
return $this->belongsTo('App\User');
}
}
this is profile model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
protected $table='profiles';
protected $fillable = ['user_id','name','position','roles','username','college','phone','location','graduation','skill'];
protected $hidden = [];
public function posts(){
return $this->hasMany('App\Post');
}
}
this is User model
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
protected $fillable = [
'fname','lname', 'email','sex', 'password','user_id','roles'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function posts(){
return $this->hasMany('App\Post');
}
}
when i try {{$status->user->fname}} this.its show the correct value but when i try {{$status->profile->username}} this ,every time it shows me Trying to get property of non-object (View: C:\xampp\htdocs\abc\resources\views\pages\profile.blade.php)
i really don't know why :(
In your Post class try the following code:
public function profile(){
return $this->belongsTo('App\Profile', 'prf_id');
}