Cakephp Model data retrieval - php

I have several models that are related to one another through a HABTM relationship.
Workouts has many Exercises |
Exercises has many Workouts |
Exercises has one Logs |
Users has many Exercises_Workouts
All of these table relations are set in one table
What I would like to do:
As you can see, user_id and workout_id are not unique but exercise_id and log_id will always be unique.
I want to find the data for one user then all workouts and have it return all the exercises and their corresponding information as well as each exercise's log information.
Final output would look something like this.
I have tried several methods and none of them have returned positive results. I would also like to hear how someone much more experienced than myself would handle this situation. The only thing I can think of that would possibly get what I want is multiple SELECT statements.
thank you for your help.
cheers!

"All of these table relations are set in one table": What do you call that table? And that's not the usual way to define relationships.
"Workouts has many Exercises | Exercises has many Workouts | Exercises has one Logs | Users has many Exercises_Workouts": Workouts HABTM Exercises, (if logs is not connected to any other table, include its fields in exercises table), User hasMany Workouts.
I have tried several methods and none of them have returned positive results. I would also like to hear how someone much more experienced than myself would handle this situation. The only thing I can think of that would possibly get what I want is multiple SELECT statements.
How much are you familiar with SQL, PHP, and CakePHP? If you are new to all those, it's kinda hard to explain how to do what you want. Show us what approaches you have used so far.

Thank you for your help. I ended up figuring out my own answer.
The reason all these have to be in one table is that I need to be able to access a single ID that relates to all of these branches. Also, each of the branches are not to be updated only referenced. What I ended up doing is using the containable behavior. I actually found this answer looking through my own code. I had a sneaking suspicion that I had come across this problem earlier.
The containable behavior allowed me to go deeper into my association than I was able to before.
Originally I was only pulling data from Workout->Exercise->Log but I also needed LogDay(individual entries). So I used the containable behavior to get that data as well as remove other unnecessary data.
thanks again!

Related

MYSQL PHP jump through many tables by one query

Is it possible to get data from one table when necessary data is in the other one(and so on a few times)? I mean, I have to get result, fetch array, pull all the data in php, make another query... and repeat it a several times before I get the wanted result. Could it be done in one query or have you guys got any ideas about optimization for such issue? I've been searching, but I really didn't find anything what makes sense for me.
UPDATE:
Thanks! JOIN fixed my problems but I got some more to work on. Let's say I've got tables like this
Users:
ID Name
1 Adam
2 John
3 Lana
Roles(with users ids)
ID Name Cleaner Soldier Doctor
1 Ship crew 2 1 3
How can I get my result like:
[1,Ship crew,John,Adam,Lana] in php without making many queries? I mean I'd like to load records from another table for a several fields depending on primary key ID.
EDIT:
OK I got it, I just needed some practice with mysql. It's not so hard as I thought it could be. Thanks for that join now I know what I was looking for :)
It is possible yes, you can use the "JOIN" technique to collate the tables or you can use the "IN" clause in your query .
http://www.tutorialspoint.com/mysql/mysql-in-clause.htm

MySQL database optimization for 20.000 users or more

I have been looking for some optimization tips since I´m doing a RPG modification which uses MySQL to store data by PHP.
I´m using one unique table to store all user information in columns by his unique ID, and I have to store (many?) data for each user. Weapons and other information.
I´m using explode and implode as a method to store the weapons, for example, in one column with the 'text' value. I don´t know if that´s a good practice and I don´t know if I will have performance problems if I get thousands of players doing tons of UPDATES , SELECT , etc, requests.
I read that a Junction table may be better to store the weapons and all those information, but I don´t know if that will get better information that you request it by the explode method.
I mean, I should store all the weapons in a different table, each weapon with his information (each weapon have some information, like different columns, I use multiple explode for that inside the main explode) and the user owner of that weapon to identify the weapon than just have them in one column.
It can be 100 items at least to store, I don´t know if it´s good to make 100 records per user on a different table and call all of them all the time better than just call the column and use explode.
Also I want to improve my skills and knowledge to make the best performance MySQL database I can.
I hope somebody can tell me something.
Thanks, and sorry for my stupid english grammar.
It is almost always best practice to normalize your table data. There are some exceptions to this rule (especially in very high volume databases), but you probably do not need to worry about those exceptions until you get to the point of first understanding how to properly normalize and index your tables.
Typically, try to arrange your tables in a way that mimics real-world objects and their relations to each other.
So, in your case you have users - that is one table. Each user might have multiple weapons. So, you now have a weapons table. Since multiple different users might have the same weapon and each user might have multiple weapons, you have a many-to-many relationship between them, so you should have a table "users_weapons" or similar that does nothing but relate user id's to weapon id's.
Now say the users can all have armor. So now you add an armor table and a users_armor table (as this is likely many-to-many as well).
Just think through the different aspects of your game and try to understand the relationships between them. Make sure you can model these relationships in database tables before you even bother writing any code to actually implement the functionality.
Yes it is better to use several tables instead of one. It's better to db performance, easier to understand, easier to maintain and simplier to use as well.
Let's suggest that one user has several weapons with multiple features(but not unique among all weapons). And in one place in your game you just need to know the value of one specific feature:
doing it by your way you'll need to find user row in users table, fetch on column, explode it several times, and there you have your value, but it complicates even more if you want to change it and save then.
better way is having one table for user details(login, password, email etc), another table which keeps user weapons(name of weapon, image maybe) and table in which will be all features, special powers of weapons kept. You could keep all possible features of all weapons in extra table as well. This way you if you already know user id from user table, you'll have to only join 2 tables in your sql query, and there you got value of feature of specific weapon of user.
Example pseudo schema of tables:
users
user_id
user_name
password
email
weapons
weapon_id
user_id
weapon_name
image
weapons_features
feature_id
weapon_id
feature_name
feature_value
And if you really want to use some ordered data in text field in database encode it to JSON or serialize it. This way you don't have to explode and implode it!
As all guys said, typically you should start from normalized database structure.
If performance is ok, then great, nothing to do.
If not, you can try many different things:
Find and optimize query which works slow.
Denormalize queries - sometimes joins kill performance.
Change data access pattern used in application.
Store data in file system or use NoSQL/polyglot persistence solution.

PHP Many to Many Set Ids

For the purpose of this question, lets assume we have a many to many relationship set up using three tables:
courses - with a id and name
students - with id and name
enrollment - with course_id and student_id
In rails, if you do a has_and_belongs_to_many, you can do
course.student_ids = [1,2,3,4,5]
And rails says that it will add / delete ids as necessary. I would like to do something similar in PHP. Something like
set_courses($student_id, array(1,2,3,4,5));
What I was wondering is if there is a good way to implement this efficiently in PHP. I can think of a way to do it in 3 queries (one to get current ids, one to delete unnecessary ones, and one to add new ones). Is there a way to do this in one or even two queries?
Thanks!
If I'm understanding you correctly than you can do it in 2:
delete all current enrollments
insert enrollments
I'd use transactions, though, to make sure both are executed.

Should I still use many-to-many db structure if I only have a few-to-many?

I'm new to web development and could really use some advice. Thank you all in advance!
I have a form where I ask users to rate their experience in several areas (Mental, Physical, Fun) from 1 - 10. There are about 10 areas in all. Is it worth it to make a table of areas and a intersection table with areaID and userID? In this case, wouldn't it be easier to just create one table with 11 columns (one for each area plus a userID)?
I understand that a table of 'areas' with a key of areaID would be the most robust, and allow me to later add more areas but I really don't see myself doing that. Also, as I only expect <1000 users, would adding another column to a MySQL db be a lot of work?
Finally, what is the cutoff point where I actually should use a many-to-many structure? Later in the form I have users rate ~30 fields from 1 - 4. Should I use the two table system there?
Thanks again!
It'd be better to use the separate child table. The SQL overhead for a join is minimal, and you get total flexibility in how many/few entries you want to allow, without ever having to change the database structure.
It may only be 10 areas now, but PHBs are notorious for changing their minds about something that was "bedrock" on the hour before launch.
I would always model a many-to-many relationship with a proper intersection table because you can never predict what the future will bring.
Suppose you want to count the number of areas per user. How would you do that if you use a single table with 11 columns?
Implement this with the intersection table. You will be glad you did.
Both makes sense, but I would choose the many-to-many approach as you can then specify in the areas table the name of each area (and maybe add some comments what 1 or 10 for that specific area means, etc..)
There's no wrong answer to this, but consider this: are you sure that that number will remain fixed at ten?
Personally, I would still use the many-to-many relationship. It's the more elegant solution, and, in my mind, better. However, doing a job well is often a waste of time.

Should a two-to-many data relationship be treated as many-to-many?

I have 2 database tables: Teams and Games.
For the purpose of this question, we are dealing with football (soccer) teams and games.
Each Game has exactly 2 teams, generally a home team and an away team although occasionally both teams can be neutral.
My question is whether I should represent this data relationship using 2 foreign keys in the Games table (home_team_id, away_team_id) or whether I should use a many-to-many relationship with a games_teams table to link the two, in which case I would need to also store whether the team was the home or away team and seems a little overkill.
To add to the confusion, I am using the ORM libs in KohanaPHP and these would expect an fk to be called team_id or a link table to contain only 2 columns. If you have experience with this problem in KohanaPHP then please leave a reply, else any general advice is also much appreciated.
Just use the two columns, otherwise you'd just need to qualify it in the joiner table. It's not as if this is a sleeping time bomb and suddenly one day you'll discover you need to have a real many to many.
2 columns is perfectly appropriate here in my opinion. The fact that there can only possibly be two teams for any game is reflected in your database schema by having two columns. By introducing a linking table, you introduce the possibility that a single game could have 2 home teams, 2 away teams, and you would need additional validation to ensure that this scenario never occurs. By keeping things isolated to the two columns, your schema inherently enforces data integrity.
If you want to be able to pin a "Xth Normal Form" badge on your database server, then it should probably be treated as many-to-many, otherwise, I should think you'll reduce your query overheads with 1 fewer table that you're just going to join through every time you want some useful data out.
In terms of normalization: Yes. There is only a one-to-many or a many-to-many that gets broken down into one or more one-to-many relationships.
But realistically speaking, if I were to save something like GENDER. Would I really need a multi-state and a datetime stamp attached to this?
The surprising answer is YES - but only if I need to track gender changes for business reasons - for most practical purposes the answer is NO.
I would keep one table with two keys - unless there is a business reason to track it as such.
Depending on how you have abstracted it, I would say that soccer game MUST have two teams, in which case having the columns in the Game table is not only more convenient, it's more correct.
I could even imagine the team id's being natural parts of the primary key of Game.
Totally think you should NOT have a separate table for this. Easier on the programmer, easier on the DB. Good to think about the what ifs, but sounds like you already have. Don't get caught thinking that normalization is always the way to go for everything.
I respect the answers of the other in saying that using the two columns is the best choice, however, you mention that you are using the ORM library in Kohana. By using two columns in the games table you lose the ORM features for many-to-many relationships. If you set up a games_teams pivot table, you can do the following:
$game = ORM::factory('game', 1); // 1 is the game id
Then you can loop through the teams in that game:
foreach ($game->teams as $team) {
// do stuff with $team
}

Categories