Laravel 5 - Query Multiple Associative Tables in Database - php

Description:
I'm working on a database setup that's requiring that I use multiple associative tables and I want to know how associative tables work within Laravel while taking advantage of the Eloquent Relationships.
I have a dataset containing soccer games. I need to store players, games, and specific player information for a game. So my structure should look something like:
Player Table:
+------------+---------+
| id | integer |
+------------+---------+
| name | string |
+------------+---------+
| team | string |
+------------+---------+
| country | string |
+------------+---------+
| average | string |
+------------+---------+
| updated_at | Date |
+------------+---------+
| created_at | Date |
+------------+---------+
Game Table
+--------------+---------+
| id | integer |
+--------------+---------+
| name | string |
+--------------+---------+
| country | string |
+--------------+---------+
| tournament | string |
+--------------+---------+
| score | string |
+--------------+---------+
| started_at | Date |
+--------------+---------+
| ended_at | Date |
+--------------+---------+
| updated_at | Date |
+--------------+---------+
| published_at | Date |
+--------------+---------+
The issue being that I need a table that associates the two together as a player can have many games and a game has many players.
Question:
How would I go about structuring my code?
Do I write a player_game model?
Do I store associations in a different way than usual because this is Laravel?
Intuitively I would want to write a player_game migration that contains game specific information for a player. But how does that work with Laravel 5 and the hasMany() attributes?

Follow your intuition. You were right, what you are looking for is called a Many to Many Relationship.
Create the intermediate table and then you can play with different queries, if Laravel HasMany type methods doesn't fill your needs, you can always query the intermediate table directly.

you need to create a pivot table named game_player many to many relationship. you can store your game specific information inside this table.
relationship in Game Model,
public funtion players()
{
return $this->hasMany('Player');
}
to access the game specific information from the pivot table,
foreach ($game->player as $player)
{
echo $player->pivot->created_at;
}

Related

Laravel eloquent find max(date) with additional search criteria

I'm trying to figure out the best way to retrieve results from the database such that the created_at is the most recent, and also checking that another value (in this case Temps->value) matches a specific criteria..
For example (some information abbreviated)
LOCATIONS
+----+---------+
| ID | CITY |
+----+---------+
| 1 | DALLAS |
| 2 | CHICAGO |
| 3 | ATLANTA |
+----+---------+
TEMPS
+----+-------+----------+------------+
| ID | VALUE | CITY_ID | CREATED_AT |
+----+-------+----------+------------+
| 1 | 70 | 1 | 2010 |
| 2 | 95 | 1 | 2015 |
| 3 | 90 | 2 | 2010 |
| 4 | 80 | 2 | 2015 |
| 5 | 99 | 3 | 2015 |
+----+-------+----------+------------+
my location model.
class Location extends model
{
...
public function latestValue()
{
return $this->hasOne('App\Temp')->latest();
}
In this case I would only like the Locations in which the latest temperature reading is > 90..
In my controller if have
$highTemps = Location::with('latestValue')->get();
without iterating through every city explicitly, is there a way to adjust my eloquent relationship, or even use a collection method to filter the results?
I've looked at filter() but I'm not sure how to use that on a relationship. Especially if you're trying to filter 2-3 relationships deep. (imagine I'm starting off with Country->states->locations->temps->latestValue etc)
It would be great to have the initial query filter the results. But I can't figure out the combination of groupBy() and max() and having() etc to make the eloquent statement work.
I think the Relationship you are establishing, it's wrong..
The Problem is very simple if the relationship hasMany() will be used..
First all the latest entries will be fetched , followed by filtering the max out of them.
class Location extends model
{
...
public function latestValue()
{
return $this->hasMany('App\Temp')->latest();
}
rest is not that much typical i assume.

Laravel Eloquent complex query building

I have trouble to achieve my goal to build a filterable complex query.
I have 5 tables. One of them is a time tracking table. To keep that global, I just store the item_id and the time_categories_id to recognize which item it is.
I also need some additional information which is not directly in relation, so for example, I need the client informations which are assigned to a task.
So I have following tables (in short form listed):
times
--------------------------------------------------------
| id | name | description | item_id | time_category_id |
--------------------------------------------------------
time_categories
-------------
| id | name |
-------------
clients
------------------------------------
| id | company| name | description |
------------------------------------
(client has many projects and projects may have many clients)
projects
------------------------------------
| id | company| name | description |
------------------------------------
tasks
----------------------------------------
| id | name | description | project_id |
----------------------------------------
tickets
------------------------------------------------
| id | company| name | description | client_id |
------------------------------------------------
Now I want to create a filter function in which the return should depend on if client or project id is submitted.
For this filter, I created following query:
$timeQuery = Time::select(array(
'times.*',
'time_categories.name as type',
'tasks.name as task_name',
'tasks.description as task_description',
'tickets.name as ticket_name',
'tickets.description as ticket_description'))
->join('time_categories','times.time_category_id','=','time_categories.id')
->leftJoin('tasks',function($join) use ($project){
if(!empty($project))
{
$join->on('times.item_id', '=', 'tasks.id')
->where('tasks.project_id','=',$project);
}else{
$join->on('times.item_id', '=', 'tasks.id');
}
})
->leftJoin('tickets',function($join) use ($client){
if(!empty($client))
{
$join->on('times.item_id','=','tickets.id')
->where('tasks.project_id','=',$client);
}else{
$join->on('times.item_id','=','tickets.id');
}
});
So I ended up here. I don't get an error, but I receive all data instead of filtered data only dependent on client or project id.
Does anyone have an advice?

PHP & MySQL Tagging system logic

I am a beginner developer and i would like to ask some advice.
I am currently building a platform where people will be allowed to upload images and tag them.
I was reading through some articles with the following structure to store tags
Storing Logic 1
| photo_id | name | tags |
| 1 | some photo | flower, sun. island, beach |
| 2 | some photo2 | hawaii, travle. surf |
Lot of people said this is not such a good idea
So my logic.
I was reading around about Many-to-Many relations and i came up with this logic
Tags table
| tag_id | name |
-----------------------
| 1 | flower |
| 2 | hawaii |
| 3 | surfing |
| 4 | island |
| 5 | travel |
Photos table
| photo_id | name |
---------------------------
| 1 | some photo |
| 2 | some photo2 |
Relation table
| tag_id | photo_id |
---------------------------
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
I have chosen to use Laravel framework to make the development easier
But my problem is with logic 2 and what i am scared of is it will generate a huge load time.
Because there will be no default just user based tags i thought about the following logic.
User uploads the image with tags, before image is saved, check if the actual tags exsit if not save it, than return tags_id and save it to the relation table with photo_id
So i have 2 questions
Which logic is better and why?
If logic 2, is it good the way i thought it up? and should i worry about the load time in the future when lot of tags will be there?
thank you
I would go with the second one. I wouldn't worry about load times. You can easily get the categories with joins.
However, you should add an id column on the relation table so that multiple images can share a category.
In your second example, your relation table should have indexes, so that when you look for all the tags based on a specific photo_id, the answer will be rapidly returned.
See also Foreign Keys
In your relation table, tag_id is a foreign key into your tag table and photo_id is a foreign key into the photo table. Tags may have a relationship to more than 1 photo and a photo may have a relationship to more than one tag.
Similarly the names of your tags (and photos) should also be indexed for rapid searching.

Database design with undetermined data

Recently I have been planning a system that allows a user to customize and add to a web interface. The app could be compared to a quiz creating system. The problem I'm having is how to design a schema that will allow for "variable" numbers of additions to be made to the application.
The first option that I looked into was just creating an object for the additions and then serializing it and putting it in its own column. The content wouldn't be edited often so writing would be minimal, reads however would be very often. (caching could be used to cut down)
The other option was using something other than mysql or postgresql such as cassandra. I've never used other databases before but would be interested in learning how to use them if they would improve the design of the system.
Any input on the subject would be appreciated.
Thank you.
*edit 29/3/14
Some information on the data being changed. For my idea above of using a serialized object, you could say that in the table I would store the name of the quiz, the number of points the quiz is worth and then a column called quiz data that would store the serialized object containing the information on the questions. So overall the object could look like this:
Questions(Array):{
[1](Object):Question{
Field-type(int):1
Field-title(string):"Whats your gender?"
Options(Array):{"Female", "Male"}
}
[2](Object):Question{
Field-type(int):2
Field-title(string):"Whats your name?"
}
}
The structure could vary of course but generally i would be storing integers to determin the type of field in the quiz and then a field to hold the label for the field and the options (if there are any) for that field.
In this scenario I would advise looking at MongoDB.
However if you want to work with MySQL you can think about the entity-attribute-value model in your design. The EAV model allows you to design for entries that contain a variable number of attributes.
edit
Following your update on the datatypes you would like to store, you could map your design as follows:
+-------------------------------------+
| QuizQuestions |
+----+---------+----------------------+
| id | type_id | question_txt |
+----+---------+----------------------+
| 1 | 1 | What's your gender? |
| 2 | 2 | What's your name? |
+----+---------+----------------------+
+-----------------------------------+
| QuestionTypes |
+----+--------------+---------------+
| id | attribute_id | description |
+----+--------------+---------------+
| 1 | 1 | Single select |
| 2 | 2 | Free text |
+----+--------------+---------------+
+----------------------------+
| QuestionValues |
+----+--------------+--------+
| id | question_id | value |
+----+--------------+--------+
| 1 | 1 | Male |
| 2 | 1 | Female |
+----+--------------+--------+
+-------------------------------+
| QuestionResponses |
+----+--------------+-----------+
| id | question_id | response |
+----+--------------+-----------+
| 1 | 1 | 1 |
| 2 | 2 | Fred |
+----+--------------+-----------+
This would then allow you to dynamically add various different questions (QuizQuestions), of different types (QuestionTypes), and then restrict them with different options (QuestionValues) and store those responses (QuestionResponses).

Relate two MySQL tables?

I'm kind of stuck in a pickle trying to make two separate database tables related to each other by two columns.
On my website I have a set of classes along with a set of objectives which belong to each class. Classes are stored in their own database table, and so do the objectives in their own table as well.
I want the user to be able to manually set the start and end dates for any objective for an active class, and when this happens it needs to update in the database as well. My trouble comes from trying to visualize how this is all supposed to happen, and how the tables in the database should handle this. All help is greatly appreciated on this. Thanks
EDIT: This is my current table design. (I don't know how to make a proper table on here yet, so I'll just create a rough draft of the design.)
Classes
class_id | instr_id | class_name | start_date | end_date |
1 | 1 | Class1 | 2013-05-10 | 2013-05-30 |
2 | 2 | Class2 | 2013-05-10 | 2013-05-30 |
3 | 3 | Class3 | 2013-05-10 | 2013-05-30 |
.. and so on for each class.
Objectives
class_id | objective_id | start_date | end_date |
1 | 1 | 2013-05-10 | 2013-05-30 |
1 | 2 | 2013-05-10 | 2013-05-30 |
1 | 3 | 2013-05-10 | 2013-05-30 |
2 | 1 | 2013-05-10 | 2013-05-30 |
2 | 2 | 2013-05-10 | 2013-05-30 |
2 | 3 | 2013-05-10 | 2013-05-30 |
... and so on so every class has every objective_id, assuming each
class has only 3 objectives.
I really hope this helps clarify some things.
Where there is a many-to-many relationship between two relational tables (as described here - one objective can be set for many classes, and each class can have many objectives), this should normally represented by a link table, which will have a many-to-one relationship with each of the parent tables.
Here, the link table could be called something like objective_assigned (as shortened form of "Objective assigned to Class") - it might have a structure like:
class_id
objective_id
start_date
end_date
- with a compound primary key on class_id and objective_id.
I would also expect an Objective table to exist, with a primary key of objective_id and a column to hold the objective title/name.

Categories