Update parent model with the HasOne child relationship - php

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' );

Related

Laravel Eloquent where statement returns no attributes

So from my previous post, I was advised to start using Eloquent models, which I did.
My end goal, is to print out specific gifts, that belongs to that specific box.
Migrations:
gift_items:
public function up()
{
Schema::create('gift_items', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->float('unit_price');
$table->integer('units_owned');
});
}
gift_campaigns:
public function up()
{
Schema::create('gift_campaigns', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->foreignId('user_foreignK')->constrained('users');
$table->integer('gift_item_count')->nullable();
$table->string('status');
$table->date('dispatch_date');
$table->date('delivery_date');
});
}
Pivot table:
public function up()
{
Schema::create('campaigns_gifts', function (Blueprint $table) {
$table->foreignId('gift_id')->constrained('gift_items');
$table->foreignId('campaign_id')->constrained('gift_campaigns');
});
}
Controller:
function box($id){
$data = Campaign::with('gifts')->where('id', $id)->get();
return view('DBqueries.boxView', ['data'=>$data]);
}
Error that I receive using this way:
Seems like the updated version is trying to call the gift_campaigns table id, instead of the pivots table campaign_id.
Once again, I need that Request $id would match the pivots table campaign_id, and print out all of the gifts that this specific id holds
First of all as I sense the campaigns_gifts is a pivot table for campaigns and gifts having a Many-to-Many relation. You are doing it completely against the conventions of Laravel.
You generally do not use a Model for pivot table.
You generally do not fetch data from the pivot table directly. Instead use the relation on one of the related Models.
Note: Laravel does allow a Model for a Pivot, and you can query the pivot table directly, just check the documentation.
The correct way:
Pivot
Make a pivot table (that you already have) with column gift_id and campaign_id. i.e., the convention for naming keys as [table_name_singular]_[primary_key_on_table]
Model
One each model, define relationship for the other data as:
Gift.php Model:
public function campaign() {
return $this->belongsToMany(Campaign::class, 'campaign_gift');
}
Campaign.php Model:
public function gifts() {
return $this->belongsToMany(Gift::class,'campaign_gift');
}
since gift have a hasMany relation, the gifts table must contain a foreign key to campaigns table named campaign_id (same as the one on pivot).
Controller
Now in your controller:
function box($id){
$data = Campaign::where('id',$id)->with('gifts')->get();
return view('DBqueries.boxView', ['data'=>$data]);
}
You don't need to tell Laravel which columns, tables etc are you referring to, as long as you follow the conventions, Laravel will magically do things that otherwise would have been much more painful.

Laravel eloquent get details from related table

I don't understand how to return info back to blade template if I have two related tables:
First table is standard Laravel 'users' table
Second table:
Schema::create('recipes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('code', 10);
$table->string('description');
$table->float('size');
$table->bigInteger('created_by')->unsigned();
$table->string('status')->default('pending');
$table->boolean('deleted');
$table->timestamps();
$table->foreign('created_by')
->references('id')
->on('users')
->onDelete('cascade');
}
Than I have two Controllers: User and Recipe
Recipe have
public function user()
{
return $this->belongsTo(\App\User::class);
}
and User have
public function recipes()
{
return $this->hasMany(\App\Recipe::class);
}
actual output looks like this (RecipesController):
$recipes = Recipe::latest()->paginate($perPage);
return view('admin.recipes.index', compact('recipes'));
everything looks OK but column created_by contain users primary key witch is integer. How can I display users name? This is something like inner join but is it possible to do that in eloquent? Or I completely misunderstanding those public functions in a Model?
Your user relationship in your Recipe model is missing the foreignKey:
public function user()
{
return $this->belongsTo(\App\User::class, 'created_by');
}
You can then eager load the users with your recipes in the controller:
$recipes = Recipe::with('user')->latest()->paginate($perPage);
return view('admin.recipes.index', compact('recipes'));
And finally you can access the user in the view:
#foreach($recipes as $recipe)
{{ $recipe->user->name }}
#endforeach
You can read more about the inverse of the one-to-many relationship in the docs.

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
]);

Laravel relationship with single column

I have a table called "fields":
Schema::create('fields', function (Blueprint $table) {
$table->increments('id');
$table->string("label");
$table->string("name")->unique();
$table->text("options")->nullable();
$table->timestamps();
});
I want to have another table which simply stores the ids of some of the fields. I will call this default_fields.
I basically want a relationship or logic that allows me to grab these default_fields like I would with any other relation:
Schema::create('default_fields', function (Blueprint $table) {
$table->increments('id');
$table->integer("field_id");
});
How can I create a relationship that grabs all the fields whose id's are present in this table? I also want to be able to sync().
Would I just make a model for DefaultField and then do something like Field::whereIn('id', DefaultField::get()->pluck('id'))?
And then code my own sync() logic? Is there a super easy way to do this that I'm missing? I'd also like to be able to sort this like I would any other relation.
You can have a model Field that has this relationship:
public function defaultFields()
{
return $this->hasMany('App\DefaultField');
}
In you controller, you can fetch the Field with his related DefaultFields like:
$fields = Field::with('defaultFields')->get();
You can have a similar method field in your DefaultField model:
public function field()
{
return $this->belongsTo('App\Field');
}
In you controller, you can fetch the DefaultField with his parent Field:
$defaultFields = DefaultField::with('field')->get();
In your case, more productive will be 'is_default' boolean property in the fields table.

Laravel 4 - Select related models

I have following table
Schema::create('jokes_categories', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('is_active');
$table->timestamps();
});
Schema::create('jokes', function(Blueprint $table) {
$table->increments('id');
$table->string('content', 200)->unique();;
$table->enum('is_active', array('Y', 'N'));
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('jokes_categories');
$table->timestamps();
});
In the jokes table category_id is a foreign key and it has a one-to-many relationship with jokes_categories
In the model I have the following:
class Joke extends \Eloquent {
public static $rules = array();
// Don't forget to fill this array
protected $fillable = array();
public function JokesCategory(){
return $this->belongsTo('JokesCategory');
}
}
In the controller I have the following:
$jokes = Joke::all();
But it does not pull through joke_categories.name (I was under the impression that the model definition will directly help to pull related models)
What could be the solution?
Your query is just on the Joke table.
You could eagerload the categories ie.
$jokes = Joke::with('JokesCategory')->get();
See docs: http://laravel.com/docs/eloquent#eager-loading
The convention is actually camel case instead of pascal case, otherwise Laravel doesn't seem to automatically load the relationships. I made the same mistake and couldn't figure out why my relationships where not loading automatically.
public function jokesCategory()

Categories