Track multiple booleans with laravel's many to many relationship - php

My migration code for relation table:
Schema::create('users_games', function (Blueprint $table) {
$table->bigInteger('user_id')->unsigned();
$table->index('user_id');
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->bigInteger('game_id')->unsigned();
$table->index('game_id');
$table->foreign('game_id')
->references('id')
->on('games')
->onDelete('cascade');
$table->boolean('liked')->default(false);
$table->boolean('played')->default(false);
$table->boolean('wishlisted')->default(false);
// composite primary key
$table->primary(['user_id', 'game_id']);
});
basically a user can mark a game like, played or add to wishlist. I want to track all those actions in the same table.
I want to represent the same in Elloquent Model for users and games, however I dont know how to. can anyone tell me how these properties inside respective models should look like please?

in your User Model:
<?php
namespace App\Models;
class User extends Model
{
public function games()
{
return $this->hasMany(Game::class);
}
}
in your Game model:
<?php
namespace App\Models;
class Game extends Model
{
public function user()
{
return $this->belongsToMany(User::class);
}
}
then you can get the value of played property from the first game in the Eloquent like this:
$user = auth->user()
$user->games->first()->liked

Related

Update parent model with the HasOne child relationship

I have a League model and a Season model their respective migrations and relationships.
League migration and relations
Schema::create('leagues', function (Blueprint $table) {
$table->unsignedBigInteger("id")->primary();
$table->boolean("active");
$table->string("name");
$table->unsignedBigInteger("current_season_id")->nullable();
$table->timestamps();
});
public function current_season()
{
return $this->hasOne(Season::class);
}
Season migration and relations
Schema::create('seasons', function (Blueprint $table) {
$table->unsignedBigInteger("id")->primary();
$table->string("name");
$table->unsignedBigInteger("league_id");
$table->boolean("is_current_season");
$table->timestamps();
});
public function league()
{
return $this->belongsTo(League::class);
}
I have two vars with my models:
$league = League::find(1);
$season = Season::find(10);
With this line, I know automatically league_id in the Season model is filled with the $league->id
$season->league()->associate($league)->save();
I want do the inverse, and fill the current_season_id without doing:
$league->current_season_id = $season->id;
$league->save();
Is it possible?
Following the comments from #M Khalid Junaid, I think it´s better this way:
Remove current_season_id from League model.
Rewrite the current_season relation to this way:
public function current_season()
{
return $this->hasOne(Season::class)->where("is_current_season", true);
}
Now, in this way, I can access the current season of the league in the form: $league->current_season
Thank you.
You do not need $table->unsignedBigInteger("current_season_id")->nullable(); in leagues table, if you are using hasOne relationship, otherwise you need another type of relationship.
I'd strong recommend in seasons table, to use a foreign key declaration in your migration
$table->unsignedBigInteger("league_id");
$table->foreign( 'league_id' )->references( 'id' )->on( 'leagues' );

Is ti posible to get value name from related table this way

Ok so I need to get data from the table this way but I would like to get
Vehicle Maker name too
I tried using join or
just doing auth()->user()->vehicles->VehicleMaker but it doesn't work
Migration of Table Vehicle
Schema::create('vehicles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id');
$table->bigInteger('category_id');
$table->bigInteger('vehicle_maker_id');
$table->string('name');
$table->double('price', 8 , 2);
$table->year('manufacture_year');
$table->bigInteger('mileage');
$table->string('vehicle_image');
$table->boolean('admin_verification')->nullable();
$table->timestamps();
});
Migration of vehicle_makers
Schema::create('vehicle_makers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Controller
public function show(){
$vehicles = auth()->user()->vehicles; -- what shoul i add here
return view('/home', [
'vehicles' => $vehicles
]);
}
Edit
I forget to mention that I already made a relationship and they work in artisan tinker when I try to do something like this:
Vehicles->find(1)->VehicleMaker
What I want is to do is
auth()->user()->vehicles and get vehicle teble with vahicle_maker name not id so some kind of join that would work in this case
Okay base on Laravel Model Relationship.
You first need to create a migration.
Vihicle Migration
Schema::create('vehicles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('category_id');
$table->unsignedBigInteger('vehicle_maker_id');
$table->string('name');
$table->double('price', 8 , 2);
$table->year('manufacture_year');
$table->bigInteger('mileage');
$table->string('vehicle_image');
$table->boolean('admin_verification')->nullable();
$table->timestamps();
});
I used unisignedBigInteger to determine it is a foreign key or you can also use index().
In your model you should place what relation ship you will use. In your case I assumed you are using One To Many Relationship. So that your user model should look like this:
User Model
...
public function vehicles() {
return $this->hasMany(Vehicle::class);
}
So that you can use the convention auth()->user()->vehicles;.
Note: the auth()->user()->vehicles; return a array of object you can loop it in foreach.
Vehicle Model
public function user() {
return $this->belongsTo(User::class);
}
In when you have this in your model you can use it 2 way.
In your controller you can call the relationship of those 2.
Controller
$vehicles = auth()->user()->vehicles;
dd($vehicles);
INFO
You can also refer to this tutorial.
EDIT
Controller
$vehicles = auth()->user()->vehicles();
foreach($vehicles as $vehicle) {
dd($vehicle->VehicleMaker);
}
Note: The $vehicles is returning an array of object. So you can loop it through foreach loop to throw a single instance.
There should be a relationship between the user and vehicles then another relationship between vehicles and vehicle_makers. If you already created your models(Vehicle, VehicleMaker) with their migrations, You can do the following
//add this to your User model.
public function vehicle(){
return this->belongsTo(App\Vehicle);
}
// add this to your Vehicle model
public function user(){
return this->hasMany(App\Vehicle); // implying that a user can have many vehicles
}
//add this to your vehicleMaker model
public function vehicle(){
return this->belongsTo(App\Vehicle);
}
When that is done, you can use Laravel's lazy loading to fetch relationships. You can do something like
$vehicles = auth()->user()->vehicle
return view('/home', [
'vehicles' => $vehicles
]);

Seeding Relationship one to many in Laravel

I need to seed a relationship in Laravel, where each user has many devices
The User model
public function devices()
{
return $this->hasMany(Device::class);
}
The Device model
public function users()
{
return $this->belongsTo(User::class);
}
}
The device_user table
Schema::create('device_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('device_id')->unsigned()->index();
$table->foreign('device_id')->references('id')->on('devices')->onDelete('cascade');
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
The seeder
factory(App\Device::class, 20)->create()->each(function(App\Device $device) {
$device->users()->attach([
rand(1,5),
rand(6,15),
rand(16,20),
]);
});
But, when I run the migration with seeder, I get this message
Call to undefined method Illuminate\Database\Query\Builder::attach()
Please, help
attach for many to many relationships, you don't need device_user table for one to many relationship, in one to many you should create a column with name user_id in device table and just it. after that you can insert data in device table with user_id. and get user relationship with
Device::user()->get();

Many to many relationship in laravel need a specific name for the table?

I have created three table which is country table, countryevents table, and country_countryevents table.
The first question i would like to know, is that need the specific name for the table?
Here is how i create the table:
The first one is country table:
Schema::create('country', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
The second one is countryevents table :
Schema::create('countryevents', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->string('description');
$table->string('start');
$table->string('end');
$table->string('type');
$table->timestamps();
});
The last one is my country_countryevents table:
Schema::create('country_countryevents', function (Blueprint $table) {
$table->increments('id');
$table->integer('country_id')->unsigned();
$table->foreign('country_id')->references('id')->on('country')->onDelete('cascade');
$table->integer('country_events_id')->unsigned();
$table->foreign('country_events_id')->references('id')->on('countryevents')->onDelete('cascade');
$table->integer('editable');
$table->timestamps();
});
I not sure what is going on with my code here, cause i cant attach the event with my country.
Illuminate\Database\QueryException with message 'SQLSTATE[42S02]: Base table or view
not found: 1146 Table 'calendar.country_country__events' doesn't exist (SQL: insert into `cou
ntry_country__events` (`country__events_id`, `country_id`, `created_at`, `updated_at`) values
(1, 1, 2016-01-27 15:31:03, 2016-01-27 15:31:03))'
This is my error when i run the php artisan tinker, and want to connect them.
I am sure my model is correct, here is the Country.php model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country extends Model
{
//
protected $table='country';
public function country_events(){
return $this->belongsToMany('App\Country_Events')->withTimestamps();
}
}
This is my Country_Events.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Country_Events extends Model
{
protected $table='countryevents';
public function country(){
return $this->belongsToMany('App\Country')->withTimestamps();
}
}
Could anyone tell me what is my error there?Thanks.
Yes, you will need to reference the table name and probably the foreign and local keys as well.
Country Model:
public function country_events(){
return $this->belongsToMany(
'App\Country_Events',
'country_countryevents',
'country_id',
'country_events_id'
)->withTimestamps();
}
Country_Events Model:
public function country(){
return $this->belongsToMany(
'App\Country',
'country_countryevents',
'country_events_id',
'country_id'
)->withTimestamps();
}
The problem is your reference to the table country_countryevents as country_country__events
Check the tablename in your database to see how it created this table in the end.
for more info check out this question
Convention table names (with underscore)
please also keep in mind to add this to your model if you don't plan to use conventional table names:
public $table = 'your_table_name';
Make sure the name of the database is link with your country_countryevents. Then it should be works fine.

Migration Foreign Key Vs Eloquent Relationships in Laravel

In Laravel 5.1 I can see that table column relationships can be set-up in 2 ways:
1) Defining Foreign Keys in the Migration table.
2) Defining the Eloquent relationships in the Models.
I have read the documentations and I am still confused on the following:
Do I need to use both or only 1 is needed?
Is it wrong to use both at the same time? Or does it make it
redundant or cause conflicts?
What is the benefit of using Eloquent relationships without mentioning the
Foreign keys in migration column?
What is the difference?
These are the codes I have now. Its still unclear to me if I need to remove the foreign keys I have set-up in my migration file.
Migration:
public function up()
{
Schema::create('apps', function (Blueprint $table) {
$table->increments('id');
$table->string('app_name');
$table->string('app_alias');
$table->timestamps();
$table->engine = 'InnoDB';
});
// This is the second Migration table
Schema::create('app_roles', function (Blueprint $table) {
$table->increments('id');
$table->integer('app_id')->unsigned()->index();
$table->integer('user_id')->unsigned()->index();
$table->integer('role_id')->unsigned()->index();
$table->engine = 'InnoDB';
$table->unique(array('app_id', 'user_id'));
$table->foreign('app_id')
->references('id')
->on('apps')
->onDelete('cascade');
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')
->on('roles')
->onDelete('cascade');
});
}
Model with Eloquent Relationships:
// App Model
class App extends Model
{
public function appRoles() {
return $this->hasMany('App\Models\AppRole');
}
}
// AppRole Model
class AppRole extends Model
{
public function app() {
return $this->belongsTo('App\Models\App');
}
public function user() {
return $this->belongsTo('App\User');
}
public function role() {
return $this->belongsTo('App\Models\Role');
}
}
// User Model
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
.....
public function appRole() {
return $this->belongsToMany('App\Models\AppRole');
}
}
// Role Model
class Role extends EntrustRole
{
public function appRole() {
return $this->hasMany('App\Models\AppRole');
}
}
Can someone help me understand this please?
Both go hand in hand. One is in-complete without the other one. If you want your relations to work properly, you need to define both of these things.
If you have just defined the foreign key in a migration file, the relation would work just in case you write a raw query. It won't work on your models since, you haven't written anything about relations in your models.
So, as soon as you write hasMany in one of your models, and corresponding function in the other model, only then your models know about each other, and then you can successfully query things through your model as well as in your database.
Also note that if you have properly defined relations through hasMany and belongsTo in your models, but haven't provided foreign key in the table of the model who belongsTo other table, your relations won't work.
In short, both are equally compulsory.
Eloquent assumes the foreign key of the relationship based on the model name. In this case, the App model is automatically assumed to have an app_id foreign key, so in your migrations you do not need to specify:
$table->foreign('app_id')
->references('id')
->on('apps')
->onDelete('cascade');
Documentation

Categories