Laravel 5.6 - relation one to many(invert) - doesn't work - laravel

I'm learning relations.
Where is the mistake in my student - gender relation?
Students table:
Schema::create('students', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('gender_id')
->unsigned()
->references('id')
->on('genders')
->onDelete('cascade');
$table->timestamps();
});
Genders table:
Schema::create('genders', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
StudentsController
use App\Student;
use App\Gender;
class StudentsController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$students = Student::all();
return view('index', compact('students'));
}
Index.blade
<pre>{{var_dump($students[0]->gender_id->name)}}</pre>
error msg. There are no object in $students.
Trying to get property of non-object
Gender model:
public function students() {
return $this->hasMany('App\Student');
}
Student model:
public function gender() {
return $this->belongsTo('App\Gender');
}

You need to access the relationship using the relationship method/attribute, not the related field. So, you need to use gender, not gender_id.
<pre>{{var_dump($students[0]->gender->name)}}</pre>
Be aware that you will get the same error if the student doesn't have a related gender.

why do you create a new table for gender ? every student will have only one gender ( female / male ) so there is no need to save it in another table, just set a column for gender in the students table, if you need all males students you run this one :
male students :
$males = Student::where('gender', 'male')->get();
female students :
$females = Student::where('gender', 'female')->get();

Related

many to many relationship with custom keys and custom pivot table Laravel 9

I have a many to many relationship between two tables : products and orders and the pivot is order_details
the pivot has two columns :
order_id reference on id in orders
sku reference on sku in products
I have defined the relation in the models of the tables like this :
Order Model
public function products()
{
return $this->belongsToMany(Product::class , 'order_details' , 'order_id' , 'sku');
}
Product Model
public function orders()
{
return $this->belongsToMany(Order::class , 'order_details' , 'sku' ,'order_id') ;
}
so when I try to reach the products from Order model I get an empty array even if there was product related to this order
order_details migration
public function up()
{
Schema::create('order_details', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('quantity');
$table->string('sku') ;
$table->foreign('sku')->references('sku')->on('products')->cascadeOnDelete() ;
$table->double('price') ;
$table->double('price_before_discount') ;
$table->foreignIdFor(Order::class)->constrained()->cascadeOnDelete();
$table->timestamps();
});
}
products migration
*
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->double('price');
$table->unsignedBigInteger('quantity');
$table->integer('discount')->default(0);
$table->foreignIdFor(\App\Models\Brand::class)->constrained()->cascadeOnDelete();
$table->unsignedFloat('rating')->default(0);
$table->string('slug')->unique();
$table->string('sku');
$table->boolean('is_active')->default(1);
$table->boolean('is_available')->default(1);
$table->foreign('sku')->references('sku')->on('skus')->cascadeOnDelete();
$table->timestamps();
$table->softDeletes();
});
orders migration
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('order_number')->unique();
$table->double('total');
$table->string('status')->default('pending');
$table->double('total_before_discount');
$table->string('invoice')->nullable();
$table->foreignIdFor(PromoCode::class)->constrained()->cascadeOnDelete();
$table->foreignIdFor(Customer::class)->constrained()->cascadeOnDelete();
$table->foreignIdFor(Address::class)->constrained()->cascadeOnDelete();
$table->timestamps();
});
Try this code hope it will help you
In Product Model:
public function orders()
{
return $this->belongsToMany(Order::class , 'order_details' , 'sku' ,'order_id' , 'sku' , 'id');
}
In Order Model
public function products()
{
return $this->belongsToMany(Product::class , 'order_details' , 'order_id' , 'sku' , 'id' , 'sku');
}

Laravel8 Many To Many change id for custom attribute

I created a relationship many-to-many between Faculties and Departments(im Working in a prototype timetable problem). For a petition, these tables need a validation code vcode. The problems are in the relationship of this, I don't know why the relationship recognize only the id´s tables for the eloquent query and not the vcode.
attached my migrations and model relationship.
Migration Faculties Table
public function up()
{
Schema::create('faculties', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('vcode')->index()->unique();
$table->string('code');
$table->string('name');
$table->string('website');
$table->string('email');
$table->string('phone');
$table->timestamps();
});
}
Relationshop on Faculty Model
public function departments()
{
return $this->belongsToMany(Department::class, 'faculty_departments','faculty_vcode','department_vcode');
}
Migration Departments Table
public function up()
{
Schema::create('departments', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('vcode')->index()->unique();
$table->string('code');
$table->string('name');
$table->string('phone');
$table->string('email');
$table->string('website');
$table->timestamps();
});
}
Relationshop on Department Model
public function faculties()
{
return $this->belongsToMany(Faculty::class, 'faculty_departments', 'department_vcode','faculty_vcode',);
}
Migration FacultyDepartments (Relationship)
public function up()
{
Schema::create('faculty_departments', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('faculty_vcode')->nullable()->index();
$table->foreign('faculty_vcode')
->references('vcode')
->on('faculties')
->cascadeOnUpdate()
->nullOnDelete();
$table->unsignedBigInteger('department_vcode')->nullable()->index();
$table->foreign('department_vcode')
->references('vcode')
->on('departments')
->cascadeOnUpdate()
->nullOnDelete();
$table->timestamps();
});
}
I provocate a error for get the query and tested the error (getting id´s table).
faculty::with('departments')->get() gives me:
select `departments`.*, `faculty_departments`.`faculty_vcode` as `pivot_faculty_vcode`, `faculty_departments`.`department_vcode` as `pivot_department_vcode`
from `departments`
inner join `faculty_departments` on `departments`.`id` = `faculty_departments`.`department_vcode`
where `faculty_departments`.`faculty_vcode` in (1, 2, 3, 4, 5, 6, 7)
Since you're not providing the field names for the faculties table or the departments table Laravel will assume it's the primary key (id) for those tables.
You need to update your belongsToMany method to be:
public function departments()
{
return $this->belongsToMany(
Department::class, // The related model
'faculty_departments', // The intermediate (pivot) table name
'faculty_vcode', // The pivot field relating to faculties
'department_vcode', // The pivot field relating to departments
'vcode', // The field on the faculties table
'vcode', // The field on the departments table
);
}

ErrorException Trying to get property 'name' of non-object in Hasmany relationship

Hello I am trying to access the Brand of a Vehicle through a HasMany relationship and receive the Property error, how can I fix it?
Migrations
Vehicles
Schema::create('vehicles', function (Blueprint $table) {
$table->id();
$table->integer('year');
$table->string('color');
$table->timestamps();
});
Brands
Schema::create('brands', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->foreignId('vehicles_id')->constrained()->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
Models
Vehicles
public function Brands()
{
return $this->BelongsTo(Brand::class,'vehicles_id');
}
Brand
public function Vehicles()
{
return $this->hasMany(Vehicle::class,'vehicles_id');
}
Method
$V = Vehicle::find($id);
dd($V->Brands->name);
You have relationship the incorrect way.
In your current code One brand (BMW) can be attached only to one vehicle. But in reality it is the other way. Vehicle belongs to one Brand, but one Brand can have multiple Vehicles.
Just flip the relationship
Schema::create('vehicles', function (Blueprint $table) {
$table->id();
$table->integer('year');
$table->string('color');
$table->foreignId('brand_id')->constrained()->onUpdate('cascade')->onDelete('cascade');;
$table->timestamps();
});
Foreign key should be in vehicles table
Vehicle belongs to Brand
// Models/Vehicle.php
// singular, because vehicle belong only to one Brand
public function brand()
{
return $this->belongsTo(Brand::class);
}
Brand has many vehicles
// Models/Brand.php
// plural because one Brand has many vehicles
public function vehicles()
{
return $this->hasMany(Vehicle::class,'vehicles_id');
}
Then in you controller:
$vehicle = Vehicle::with('brand')->find($id);
dd($vehicle->brand->name);

How to get parent_id count?

Users table
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('first_name');
$table->string('last_name');
$table->string('referral_code')->nullable();
$table->integer('parent_id')->unsigned()->nullable();
$table->string('mobile')->unique();
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Order table
public function up()
{
Schema::create('oreders', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->bigInteger('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->timestamps();
});
}
I tried first and whereHas('user') replaced it
$orderCount = Order::whereHas('user')->withCount('parent_id')->get();
return $orderCount;
I get this error.
Call to undefined method App\Order::parent_id() (View: C:\xampp\htdocs\site\bazar\resources\views\Admin\master.blade.php)
You first need to define the relationship in your models App\User and App\Order
App/User.php
class User extends Model
{
public function orders()
{
return $this->hasMany(Order::class);
}
public function parent()
{
return $this->belongsTo(User::class, 'parent_id');
}
public function children()
{
return $this->hasMany(User::class, 'parent_id');
}
}
App/Order.php
class Order extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
I do believe you want to count the number of order for a user.
But first of all, we will fix some issues / I'm suspecting you have.
Table name orders is called oreders
You don't need to verify if an order has a user Order::whereHas('user') since $table->bigInteger('user_id')->unsigned(); is not nullable. It means an order cannot exists without a user.
Not an issue but a suggestion $table->bigInteger('user_id')->unsigned(); can be simplified with $table->unsignedBigInteger('user_id');
Now the interesting part
$orderCount = Order::whereHas('user')->withCount('parent_id')->get();
return $orderCount;
In my understand you're trying to get the number of orders of of a parent of the user. I will show you some use case that may help your understanding.
// Get the total number of orders
$orderCount = Order::count();
// Get the total number of orders of a user
$userOrderCount = $user->orders()->count();
// Include the number of orders in the user attributes
$user = User::withCount('orders')->find($userId); // notice 'order' is, in fact `orders()` from the App\User methods
// Include the number of orders in the parent attributes
$parent = User::withCount('orders')->find($user->parent_id);
// Number of orders of the parent
$parentOrderCount = Order::where('user_id', $user->parent_id)->count();
// Edit: As you commented, you also want to know "The marketers can see how many people bought their code"
// I'm assuming this is the number of children (I have added the relation in the model above)
$childrenCount = $user->children()->count()
Note : when you do Order::where('user_id', $user->parent_id)->count(); you don't need to verify that the user has a parent first. parent_id will return null and user_id cannot be null. So it will just return 0

How to use relationship in laravel?

I use work with relationship in laravel 5.6.
I create product table with migration:
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('slug');
$table->text('description');
$table->string('tags');
$table->string('original_price');
$table->integer('view_order')->default(0);
$table->unsignedInteger('admin_id');
$table->foreign('admin_id')->references('id')->on('admins');
$table->boolean('status');
$table->timestamps();
});
And i create category table with migration:
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->boolean('status');
$table->timestamps();
});
And create product_categories table with migration:
Schema::create('product_categories', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('product_id');
$table->foreign('product_id')->references('id')->on('products');
$table->unsignedInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories');
$table->timestamps();
});
Now, I use Bootstrap Multiselect for categories in one product.
In category model:
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products()
{
return $this->belongsToMany(Product::class);
}
In Product model:
/**
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function categories()
{
return $this->belongsToMany(Category::class);
}
How to add category_id and product_id in product_categories table with relationship?
Check the documantation related to Many to many Relationships.
Your pivot table doesn't follow Laravel's convention, either update your table name or update your relationships to address this issue.
The convention is the alphabetical order of the two models, thus your pivot table should be named: category_product
If you do not want to update the table name, update your relationships.
public function categories()
{
return $this->belongsToMany(Product::class, 'product_categories')
}
public function products()
{
return $this->belongsToMany(Category::class, 'product_categories')
}
Now to "save an entry to the pivot table" -or in other words: to create the relationship between the two models- you may use attach or sync method.
$product->categories()->attach($category);
$product->categories()->attach([$categoryId1, $categoryId2]);
sync is different.
The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table.
To detach (delete entry in pivot table), simple use the detach method.
$product->categories()->detach([1, 2]);
Of course, do the same for Category.
Your model names are Product and Category and the derived relational table will be category_product because category came before product in alphabetical order.
You only have to add the pivot table:
public function categories()
{
return $this->belongsToMany(Product::class, 'product_categories')
}
public function products()
{
return $this->belongsToMany(Category::class, 'product_categories')
}
Now for save with relationship:
$product->categories()->attach($category);
$product->categories()->attach([$category_id_1, $category_id_2]);
You only have to add the pivot table:
public function products()
{
return $this->belongsToMany(Product::class, 'product_categories');
}
public function categories()
{
return $this->belongsToMany(Category::class, 'product_categories');
}
By default, laravel derives the table name from the alphabetical order of the related model names. Here your model names are Product and Category and the derived relational table will be category_product because category came before product in alphabetical order. Either you can change the table name or you can override this my mentioning the table name as the second parameter in the relational method as follows.
public function products()
{
return $this->belongsToMany(Product::class, 'product_categories');
}
public function categories()
{
return $this->belongsToMany(Category::class, 'product_categories');
}

Resources