Laravel Eloquent relationships in Sports - mysql

I'm learning Laravel 8.x and I decided to do a website project for our community where we have different sport events for our youth throughout the year. Football, volleyball, basketball, etc.
While I think I managed to get pretty far, I have problems understanding how I should design the matches table.
Here is a partial diagram of my current database, which I will explain in more detail:
Each sport is played in form of tournaments throughout the year. Each tournament can have 1 or more groups and 1 or more playoffs. Depending on teams available we create 1-4 groups and usually to let all kids play longer, but still keep it competitive, we could form 2 different playoffs for each tournament, depending on group positions.
I created Models:
Sport
public function tournaments() {
return $this->hasMany('App\Models\Tournament');
}
Team
public function tournaments() {
return $this->belongsToMany('App\Models\Tournament')->withTimestamps();
}
public function groups() {
return $this->belongsToMany('App\Models\Group')->withTimestamps();
}
public function playoffs() {
return $this->belongsToMany('App\Models\Playoff')->withTimestamps();
}
Group
public function tournaments() {
return $this->belongsToMany('App\Models\Tournament')->withTimestamps();
}
public function teams() {
return $this->belongsToMany('App\Models\Team')->withTimestamps()->withPivot(
'position',
'points',
'wins',
'losses',
'draws',
'off',
'def'
);
}
Playoff
Similar to Groups
Tournament
public function sport() {
return $this->belongsTo('App\Models\Sport');
}
public function groups(){
return $this->belongsToMany('App\Models\Group')->withTimestamps();
}
public function playoffs(){
return $this->belongsToMany('App\Models\Playoff')->withTimestamps();
}
public function teams() {
return $this->belongsToMany('App\Models\Team')->withTimestamps();
}
As groups / playoffs belong to tournaments, I decided to use the group_team / playoff_team as a "team signup to a tournament", instead of creating another table with tournament entries and tournament standings.
What I have problem now is creating the matches table. How should I do it?
Real example would be:
We have a tournament in Basketball. Team A and Team B are both in Group A. They play a match and Team A wins 21:19. Since we are in group stage still, the group_team table should get updated.
With already doing all these many-to-many relationships until this point, I am not sure how to design a match table, which should probably have:
team1_id
team2_id
team1_score
team2_score
group_id (?)
Thank you for suggestions.

I ended up creating Match model:
public function team1() {
return $this->belongsTo(Team::class, 'team1_id');
}
public function team2() {
return $this->belongsTo(Team::class, 'team2_id');
}
public function group() {
return $this->belongsTo(Group::class,);
}
public function playoff() {
return $this->belongsTo(Playoff::class,);
}
with
$table->foreign('group_id')
->references('id')->on('groups')
->onDelete('cascade');
$table->foreign('playoff_id')
->references('id')->on('playoffs')
->onDelete('cascade');
$table->foreign('team1_id')
->references('id')->on('teams')
->onDelete('cascade');
$table->foreign('team2_id')
->references('id')->on('teams')
->onDelete('cascade');
Maybe not the best approach and something I will need to revisit down the line, but it works.

Related

Laravel belongs to (more than 1 table)

has a rookie in laravel i don't no very well where and how to do this.
I have 3 tables that have almost the same fields, but they all have in comon ID
public function book(){
return $this->belongsTo('App\Models\table1', 'book_id', 'id');
}
this works but can i do something like this??
What should i use?
public function book(){
return $this->belongsTo('App\Models\table1','App\Models\table2', 'book_id', 'id');
}
Thanks for sharing your knowlege.
You may define 2 separate belongsTo functions
//...
public function book(){
return $this->belongsTo('App\Book', 'foreign_key', 'primary_key');
}
public function author(){
return $this->belongsTo('App\Author', 'foreign_key', 'primary_key');
}
//...
No, you can't create a single relationship with two tables in that way, that's not the way Laravel reads the method.
It would be pretty easy, and likely most clear for code readability to just make two separate relationships:
public function book(){
return $this->belongsTo('App\Models\table1', 'foreign_key');
}
public function otherBook(){
return $this->belongsTo('App\Models\table2', 'foreign_key');
}
But, it may be worth your time to consider the overall architecture of your models and tables first. If these tables share a common ID, that's going to get quite confusing over time, and carry a lot of overhead to make sure you don't over-write. Why not just make one table with some kind of flag to identify the different types of book?
Hope this helps.

Joining Two Tables to a Reference Table Laravel

I Have three tables
#1 Table timeline which is my reference table with an Auto incremented ID which is stored in column id
#2 timeline_videos
#3 timeline_else
What happens is on post if a video is uploaded with the post
it will go into Table #2 ,anything else goes into Table #3.
#2-3 have the Auto Increment Id from the Table timeline stored in a column pid
On query of The Timeline I need to join both tables data using id=pid
so I can use the rest of the Relational Data with the post.
I have done a bit of research and can't seem to find a method for doing so.
So far the code I have
Controller
$groupposts = timeline::where([
['owner','=',$owner],['id','<',$lastid],
])
->join('timeline_videos','timeline.id','=','timeline_videos.pid')
//->join('timeline_else','timeline.id','=','timeline_else.pid')
->orderBy('id','desc')
->limit(5)
->get();
This works with no errors with the second Join commented out but I need to also grab the timeline_else data .
Update --
I have now decided to use Eloquent Relationships to join the tables,
my question now is what type of relationship do I have between the
tables?
I realize it basically needs to be able to switch between two tables to
grab data based on the fact that timeline_videos and timeline_else will not be "JOIN" but separated by type .
The tables need to Join with table #1 timeline based on a column I now have named type for clarifying where to look and matching/joining using the id = pid
You can use relationships.
it sounds like timelines has many videos and has many video failures
https://laravel.com/docs/5.5/eloquent-relationships#one-to-many
you would have a model for each table and set up the relationships
timelines model:
public function videos()
{
return $this-> hasMany('App\Videos');
}
public function videoFailures()
{
return $this-> hasMany('App\videoFailures');
}
videos model:
public function timeline()
{
return $this->belongsTo('App\Timelines');
}
videos failures model:
public function timeline()
{
return $this->belongsTo('App\Timelines');
}
You can then go:
$timeLine = Timmeline::find($id);
to find videos of the time lines you would do:
$videos = $timeLine->videos();
to find else:
$videoElse = $timeLine-> videoFailures();
By using some of what Parker Dell supplied and a bit more trial and error
My Models Looks like
timeline
class timeline extends Model
{
protected $table ='timeline';
public $timestamps = false;
public function videos()
{
return $this->hasMany('App\timeline_videos','pid','id');
}
public function else()
{
return $this->hasMany('App\timeline_ect','pid','id');
}
}
timeline_ect.php ,I changed the name of the table
class timeline_ect extends Model
{
protected $table='timeline_ect';
public $timestamps = false;
public function timeline()
{
return $this->belongsTo('App\Models\timeline','pid','id');
}
}
timeline_videos
class timeline_videos extends Model
{
protected $table='timeline_videos';
public $timestamps = false;
public function timeline()
{
return $this->belongsTo('App\timeline','id','pid');
}
}
Then Lastly my Controller
$timeline = timeline::with('videos','else')
->orderBy('id','desc')
->limit(5)
->get();
So far no Problem query is correct.

Include specific column from related-models table

Using Laravel 5.1: Given two related models, User and Item, with through table Item_User, how can I include a specific column from the through table, item_count using a with statement?
Item_User table:
Query:
$userGameProfile = User::with([
'items' => function($query) use ($profile_id) {
$query->with(['phrases'])->where('profile_id', '=', $profile_id);
}])->find($id);
Adding ->select('item_count') to this query only returns item count, and not the related item objects. Adding ->select('*') gets me the items and fields I want, but breaks the nested with(['phrases']) relationship I need to get related phrases to items.
I was told I should use withPivot, but I cannot find documentation or examples on how to use this.
Preferably, I'd like to add this to the relationship, rather than each query.
Models:
User:
public function items()
{
return $this->belongsToMany(Item::class, 'user_item');
}
Item:
public function users()
{
return $this->belongsToMany(User::class, 'user_item');
}
public function phrases()
{
return $this->belongsToMany(Phrase::class, 'item_phrase');
}
Phrase:
public function items()
{
return $this->belongsToMany(Item::class, 'item_phrase');
}
This article highlights how to include additional information from the pivot table.
In User model, I know I will always want to include item_count from user_items pivot table, so you can add withPivot to the relation to items:
public function items()
{
return $this->belongsToMany(Item::class, 'user_item')
->withPivot('item_count');
}
User now comes back with items and pivot data:

Laravel 5.1 Distant relationships with one-to-many and many-to-many models

I have 5 models configured. Customer, Environment, Object, ServiceRole and Service. I've set up the appropriate eloquent relationships in each of the models.
Customers have many Environments.
//Customer Model
public function environments()
{
return $this->hasMany('App\Environment');
}
Environments belong to one Customer.
Environments belong to many Objects.
//Environment Model
public function customer()
{
return $this->belongsTo('App\Customer');
}
public function objects()
{
return $this->belongsToMany('App\Object');
}
Objects belong to many Environments.
Objects belong to many ServiceRoles.
//Object Model
public function environments()
{
return $this->belongsToMany('App\Environment');
}
public function serviceRoles()
{
return $this->belongsToMany('App\ServiceRole');
}
ServiceRoles belong to many Objects.
ServiceRoles belong to one Service.
//ServiceRole Model
public function objects()
{
return $this->belongsToMany('App\Object');
}
public function service()
{
return $this->belongsTo('App\Service');
}
Services belong to many ServiceRoles.
public function serviceRoles()
{
return $this->hasMany('App\ServiceRole');
}
--SQL--
customers: id, name
objects: id, name
environments: id, name, customer_id
environment_object: id, environment_id, object_id
service_roles: id, name, service_id
object_service_role: id, object_id, service_role_id
services: id, name
1) What would be the simplest method to retrieve all of the Objects that associated to the Customer (across all of the related Environments)?
Looking to do something like: $customer->objects
2) How can I then retrieve all the Services of the Objects associated to the Customer, as each Object has a ServiceRole that maps to a Service.
Looking to do something like: $customer->services
It will be good to post all your relationships. But if you say you have appropriatly set up your relationships then the following should work.
1. Customer::with('environments.objects')->get();
but if its for only a customer do
Custmer::with('environments.objects')->find($id);
2. Customer::with('environments.objects.roles')->get();
for only a customer do
Customer::with('environments.objects.roles')->find($id);

Using relationships in Laravel Eloquent with bridge table

I have an app that handles user info, and one of the pieces of data we collect is what school(s) they're attending. We have a User object, School object, and a UserSchool object.
This is the user_schools table:
user_id (int),school_id (int)
With the following records for instance:
100, 20
200, 500
200, 10
300, 10
I'm trying to get all schools for the current user (say user 200). This is my UserSchool object:
class UserSchool extends Model
{
var $table = 'user_schools';
function user() {
return $this->belongsTo('User');
}
function school() {
return$this->belongsTo('School');
}
}
In User I have the following relations defined:
public function schools()
{
return $this->hasManyThrough('School', 'UserSchool');
}
public function userSchools()
{
return $this->hasMany('UserSchool');
}
When I var_dump($user->schools) I get no results, even though I know it should be returning multiple Schools. What am I doing wrong? I'm sure this must have been asked before but I don't know what the actual term for this intermediate type of relationship is (bridge table? pivot table?).
Edit: Either way, most of the examples I've looked at haven't worked. I've also tried:
public function schools()
{
return $this->hasManyThrough('School', 'UserSchool', 'school_id');
}
In fact you don't need to have UserSchool object here for this relationship
For User model you can use create the following relationship:
public function schools()
{
return $this->belongsToMany(School::class, 'user_schools');
}
And now you can get schools of user using something like this:
$user = User::find(1);
foreach ($user->schools as $school)
{
echo $school->name;
}
This is standard many to many relationship