For a school assignment we have two tables and models players and countries
I know its either my models or my controller (I've had this problem before but in another assignment their was only one country so i just looped through a country variable and used arrays instead but this wont work for multiple countries)
When I try to display in the view i get "Trying to get property of non-object 'name' on the {{$player->country->name}} and this is the way the teacher has explicitly said we are to display it.
Currently before anything else id like to display all my players and their country names
Models
class Country extends Model
{
//
protected $table = 'countries';
protected $fillable=['name','flag'];
public function player(){
return $this->hasMany(Player::class);
}
}
class Player extends Model
{
//
protected $fillable =['name','age','role','batting','bowling','image','odiRuns','countries_id'];
public function country()
{
return $this->belongsTo(Country::class);
}
}
Tables
public function up()
{
Schema::create('countries', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('flag');
$table->timestamps();
});
}
public function up()
{
Schema::create('players', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('age');
$table->string('role');
$table->string('batting');
$table->string('bowling');
$table->string('image');
$table->string('odiRuns');
$table->integer('countries_id')->unsigned();
$table->foreign('countries_id')->references('id')->on('countries');
$table->timestamps();
});
}
Controller
use App\Player;
use App\Country;
use Illuminate\Http\Request;
class PlayerController extends Controller
{
public function index()
{
//
$players=Player::all();
return view('index',compact('players'));
}
View
#extends('layout')
#section('content')
#foreach ($players as $player )
{{$player->name}}
{{$player->age}}
{{$player->role}}
{{$player->batting}}
{{$player->bowling}}
{{$player->odiRuns}}
{{$player->country->name}}
#endforeach
#endsection
Edit
players all have country id's relating to the countries table
Tables
players table
countries table
The problem is your missing foreign key in relation. When you are defining a relationship, if you explicitly don't tell which foreign key to use for the relationship, Laravel looks for a foreign key like relationname_primarykeyoftheparenttable. In your case its country_id but in your players table the column name is countries_id. So relationship is not building and you are getting error. Change the column name or tell the relationship which foreign key to use to build the relationship.
class Player extends Model
{
protected $fillable =['name','age','role','batting','bowling','image','odiRuns','countries_id'];
public function country()
{
return $this->belongsTo(Country::class,'countries_id');
}
}
Laravel Doc
Related
if instead of having a users table where one user can follow many users. I would have a cows table where each cow has a single father and a single mother, where the parents can have many children. do I require an external table to store that or can I just add in my cows table the fields cow_father_id and cow_mother_id?
-referring to making 2 eloquent relationships of cows table with same cows table
and what this migration would look like?
You could do this. I've tested as well.
Migration
Schema::create('cows', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->integer('father_id')->nullable();
$table->integer('mother_id')->nullable();
$table->timestamps();
});
Model
class Cow extends Model
{
use HasFactory;
public function father()
{
return $this->belongsTo(self::class, 'father_id');
}
public function mother()
{
return $this->belongsTo(self::class, 'mother_id');
}
public function children()
{
return $this->hasMany(self::class, 'father_id')->orWhere('mother_id', $this->id);
}
}
I'm working on a Laravel 8 project.
I have a payments table, it's the migration:
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->enum('gateway',['idpay','zarinpal']);
$table->unsignedInteger('res_id')->nullable();
$table->char('ref_code',128)->nullable();
$table->enum('status',['paid','unpaid']);
$table->unsignedBigInteger('order_id');
$table->foreign('order_id')->references('id')->on('orders')->onDelete('cascade');
$table->timestamps();
});
as you can see this table has a foreign key that references on orders table, and it is orders migration:
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('amount');
$table->char('ref_code',128)->nullable();
$table->enum('status',['unpaid','paid',]);
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
I created a one to one relationship in Order model:
class Order extends Model
{
use HasFactory;
protected $guarded = [];
public function payment()
{
return $this->hasOne(Payment::class);
}
}
The problem is that when I want to use order() method on Payment class it does not work.
for example:
Payment::find(10)->order()->update(['status' =>'paid']);
I get this error:
BadMethodCallException Call to undefined method
App\Models\Payment::order()
UPDATE:
Here is Payment model:
class Payment extends Model
{
use HasFactory;
protected $guarded = [];
}
Thank you for helping me.
You should use like this a method in the payment model.
public function order()
{
return $this->belongsTo(Order::class);
}
Because you still don't have any relationship in the payment model to order.
You can check here for detailed information.
https://laravel.com/docs/8.x/eloquent-relationships#one-to-one-defining-the-inverse-of-the-relationship
You have to describe the order relation ship in the Payment model
class Payment extends Model
{
use HasFactory;
protected $guarded = [];
public function order()
{
return $this->belongsTo(Order::class);
}
}
and after that you can access the payment's order like this:
Payment::find(10)->order->update(['status' =>'paid']);
Yet another eloquent relationship issue :) I hope somebody can help me out!
ProductionOrder.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ProductionOrder extends Model
{
public function workOrders()
{
return $this->hasMany('App\WorkOrder');
}
}
WorkOrder.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class WorkOrder extends Model
{
public function productionOrder()
{
return $this->belongsTo('App\ProductionOrder');
}
}
So a ProductionOrder should have one or more WorkOrders.
Production order migration
public function up()
{
Schema::create('production_orders', function (Blueprint $table)
{
$table->bigIncrements('id');
$table->unsignedBigInteger('production_order_id')->unique();
$table->longText('notes')->nullable();
$table->timestamps();
});
}
Work order migration
public function up()
{
Schema::create('work_orders', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('work_order_id')->unique();
$table->unsignedBigInteger('production_order_id');
});
}
The reason the ID names are not just 'id' is because i am importing the order data from a external API. I think this is the reason why the relationship does not work but I can't seem to fix it.
ProductionOrder::with('workOrders')->get();
The above returns an empty array in the work_orders attribute for each production order, however there are definitely work orders located in the database with existing production_order_id.
Fixed it, had to add two times the production_order_id to the hasMany relationship:
public function workOrders()
{
return $this->hasMany('App\WorkOrder', 'production_order_id', 'production_order_id');
}
use query like this you will get data surely
class ProductionOrder extends Model
{
public function workOrders()
{
//use this
//return $this->hasMany(WorkOrder::class, 'id of workorder table which forigne key of', 'primary key of this table');
return $this->hasMany(WorkOrder::class, 'production_order_id', 'id');
//instead of
//return $this->hasMany('App\WorkOrder');
}
}
ProductionOrder::where('production_order_id', '=', 70600)->with('workOrders')->first();
I create a table post__post_category_relations to save categories of post.
Schema::create('post__post_category_relations', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('post_id')->unsinged();
$table->integer('category_id')->unsinged();
$table->timestamps();
});
At blade template edit post, I want show list categories of post.
In Post model I wrote:
public function categories(){
return $this->belongsTo(PostCategoryRelations::class,'id','post_id','category_id');
}
But it only return one category. Can you show me how to show all categories? Thank so much!
This looks similar to Many To Many approach between posts and categories. And a junction table which connects post and category table should have post_id, category_id and other columns are not required like id , timestamps() i guess you won't be using them in your application.
Migration would minimize to
Schema::create('post__post_category_relations', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->integer('post_id')->unsinged();
$table->integer('category_id')->unsinged();
});
For many to many you can add definitions in your models like
class Post extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class, 'post__post_category_relations', 'post_id');
}
}
class Category extends Model
{
public function posts()
{
return $this->belongsToMany(Post::class, 'post__post_category_relations', 'category_id');
}
}
If you still want to keep other columns from junction table post__post_category_relations you can access them by defining as pivot attributes in your model like
class Post extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class, 'post__post_category_relations', 'post_id')
->withPivot('id','cols')
->as('post__post_category_relation_cols');
}
}
I have 2 tables A and B.
I make a many to many Relationship with a pivot table called A_B
Now I need to make other ManyToMany Relationship between A_B and User ( U )
So I have another table A_B_U
Now, What I need and can't do it, is writing a relationship from A to A_B_U.
I set U to a vale, so A_B -> A_B_U is now a belongsTo Relationship, I should be able to access it easily, but I can't write it, I can write the first relationship, but then, I can't write the second one.
I don't know neither how to pass a param in ManyToMany Rel.
In fact, it shoud be a belongsTo, not ManyToMany so I'm a bit lost in all that....
Any Idea how to do it?
What it looks like
category_tournament_user
/ \
category_tournament users
/ \
tournaments categories
Migrations
Schema::create('tournaments', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('categories', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('category_tournament', function(Blueprint $table) {
$table->increments('id');
$table->integer('category_id');
$table->integer('tournament_id');
$table->timestamps();
});
Schema::create('category_tournament_user', function(Blueprint $table) {
$table->integer('category_tournament_id');
$table->integer('user_id');
});
Models
class Tournament extends Model
{
public function categories()
{
return $this->belongsToMany(Category::class);
}
public function categoryTournaments()
{
return $this->hasMany(CategoryTournament::class);
}
}
class Category extends Model
{
public function tournaments()
{
return $this->belongsToMany(Tournament::class);
}
public function categoryTournament()
{
return $this->hasMany(CategoryTournament::class);
}
}
class CategoryTournament extends Model
{
protected $table = 'category_tournament';
public function category()
{
return $this->belongsTo(Category::class);
}
public function tournament()
{
return $this->belongsTo(Tournament::class);
}
public function users()
{
return $this->belongsToMany(User::class, 'category_tournament_user');
}
}
class User extends Authenticatable
{
public function categoryTournaments()
{
return $this->belongsToMany(CategoryTournament::class, 'category_tournament_user');
}
}
Get all users of a tournament
$tournament = App\Tournament::with('categoryTournaments.users')->find(1);
foreach($tournament->categoryTournaments as $categoryTournament) {
// To get the category of the tournament, this will return an App\Category
$category = $categoryTournament->category;
// If you have a name column on your categories table...
$categoryName = $category->name;
// To get the tournament.
$tournament = $categoryTournament->tournament;
// To get the name of the tourament (if there is a name column)
$tournamentName = $tournament->name;
$tournament->created_at; // etc...
// To get all the people participating in this tournament category
foreach($categoryTournament->users as $user) {
echo $user->email;
}
}
If you need to figure out how to traverse the relationships (getting all tournaments and categories a user is participating in, etc...) please feel free to ask.
Starting at the User
// This will list all tournament and category names a user belongs to.
$user = App\User::with('categoryTournaments.tournament', 'categoryTournaments.category')->find($userId);
foreach($user->categoryTournaments as $categoryTournament) {
echo 'Category Name: '.$categoryTournament->category->name;
echo 'Tournament Name: '.$categoryTournament->tournament->name;
echo '<br>';
}
Edit
users and category_tournament make a belongsToMany relationship.
categories and tournaments make a belongsToMany relationship.
category_tournament also has a belongsTo to both tournaments and categories
There is a possibility we can further simplify this if you remove the tables tournaments and categories and drop all their columns right into category_tournament. That way, you end up with only one belongsToMany relationship to manage.