I have a database that has a users first and last name. Some cases i display the users full name, but in other cases i just show the first name. i have a function that gathers user information.
within the function, i use an sql query to gather the first and last name, but i also concat the first and last name and label it full_name.
Example..
$q = "SELECT first_name, last_name, CONCAT_WS(' '. first_name, last_name) AS full_name
/* A lot of other information */
FROM users WHERE user_id=$user_id";
My question is, is this too much, is it unnecessary to get the same data in different forms straight out of the database, or would it be better to just take the first and last name from the database and then concat afterward in php like so...
echo $user['first_name'].' '.$user['last_name'];
I would just use the database for information storage and retrieval as much as possible, and leave things like the "full name" (which is really probably used only for display purposes) to the application, i.e. php logic.
It doesn't really matter. Setting one variable takes a small fraction of a second either way. If you're expecting lots of requests, then setting it in MySQL will be faster, as when you do it in PHP, it has to search for the array key in the returned array and set that value to a variable. If you set it in MySQL, you just use the value straight out of the array without the in-between steps.
Unless you're getting a HUGE volume of people requesting that data however, you won't notice a difference.
Related
I have a checkbox asking the user to put his/her favorite courses. I want to store all the selected courses in one column separated by delimiters in MySQL database
This is the way I insert it into mysql database. How should I be doing this?
$sql="INSERT INTO Students(FirstName, LastName,gender,Major,Favorite_courses,GPA,Date_of_reg)
VALUES
('$_POST[firstname]','$_POST[lastname]','$_POST[sex]','$_POST[major]','$_POST[favorite]','$_POST[GPA]',SYSDATE())";
$_POST[favorite] is the field in question.
$sql="INSERT INTO Students(FirstName, LastName,gender,Major,Favorite_courses,GPA,Date_of_reg) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[sex]','$_POST[major]','implode(\',\',$_POST[\'favorite\'])','$_POST[GPA]',SYSDATE())";
If you REALLY want to put all favorite courses into a single field, you can make this field a string, and store the PHP array in it by serializing it. You can use the serialize() function, or JSON, json_encode(), or any other similar method. To retrieve the data, just use unserialize(), or json_decode(), and you will have your array back in PHP.
But keep in mind that using a SELECT statement to filter who likes course foo or course bar, will be quite dificult. The best approach is to follow jeroen's suggestion, normalizing your data.
Well, for security and normalization reasons you shouldn't do that.
However, you can do it, if you really want to by using the function serialize() of php.
$myFavorites = serialize($_POST[favorite]);
$sql="INSERT INTO Students (FirstName, LastName, gender, Major, Favorite_courses, GPA, Date_of_reg) VALUES
('$_POST[firstname]' ,'$_POST[lastname]' ,'$_POST[sex]' ,'$_POST[major]', '$myFavorites', '$_POST[GPA]', SYSDATE())";
You'll be able to unserialize it after you got it from your database with
$serializedCourses = myFunctionToGetItFromMyDatabase();
$unserializedCourses = unserialize($serializedCourses);
What I would do would be to create another table in your database for the Courses, and link it to the user via the user's id.
For example you could create as much columns as there is type of courses, and that will make you able to get easily the list of people who like Maths (for example) or even Maths and Geometry.
You won't be able to do that with your solution easily.
I have php page thats taking values for startdate, enddate, hotelname, city, price and type from the user.
Now i need to check my database for only the values that are entered by the user. Is that possible? For any entry that is left blank, the corresponding condition is not applied (e.g., if city is left blank, all cities are considered).
Like if the user enters only the hotelname then i need to select * from hotel where hname = hotelname.
If i go on checking for all the possible set of conditions then it will be to long like 63 combinations are possible!! so is there any way out? please help! Thanks.
You should write a method that loops through the input vars and looks for valid column names instead of handling each input individually. Then make sure you are using prepared statements in your SQL (mysqli, PDO).
To check for specific input vars, you should perform an
if (isset($_POST['var']) && !empty($_POST['var']))
If each field needs special attention or separate database tables, then you will most likely need to handle each field individually.
It ultimately depends on your needs. But in my experience there is always a way to do it pro-grammatically.
When you build your query in your code, only include the items that have values in them.
You ARE building your query dynamically aren't you?
OK, I know the technical answer is NEVER.
BUT, there are times when it seems to make things SO much easier with less code and seemingly few downsides, so please here me out.
I need to build a Table called Restrictions to keep track of what type of users people want to be contacted by and that will contain the following 3 columns (for the sake of simplicity):
minAge
lookingFor
drugs
lookingFor and drugs can contain multiple values.
Database theory tells me I should use a join table to keep track of the multiple values a user might have selected for either of those columns.
But it seems that using comma-separated values makes things so much easier to implement and execute. Here's an example:
Let's say User 1 has the following Restrictions:
minAge => 18
lookingFor => 'Hang Out','Friendship'
drugs => 'Marijuana','Acid'
Now let's say User 2 wants to contact User 1. Well, first we need to see if he fits User 1's Restrictions, but that's easy enough EVEN WITH the comma-separated columns, as such:
First I'd get the Target's (User 1) Restrictions:
SELECT * FROM Restrictions WHERE UserID = 1
Now I just put those into respective variables as-is into PHP:
$targetMinAge = $row['minAge'];
$targetLookingFor = $row['lookingFor'];
$targetDrugs = $row['drugs'];
Now we just check if the SENDER (User 2) fits that simple Criteria:
COUNT (*)
FROM Users
WHERE
Users.UserID = 2 AND
Users.minAge >= $targetMinAge AND
Users.lookingFor IN ($targetLookingFor) AND
Users.drugs IN ($targetDrugs)
Finally, if COUNT == 1, User 2 can contact User 1, else they cannot.
How simple was THAT? It just seems really easy and straightforward, so what is the REAL problem with doing it this way as long as I sanitize all inputs to the DB every time a user updates their contact restrictions? Being able to use MySQL's IN function and already storing the multiple values in a format it will understand (e.g. comma-separated values) seems to make things so much easier than having to create join tables for every multiple-choice column. And I gave a simplified example, but what if there are 10 multiple choice columns? Then things start getting messy with so many join tables, whereas the CSV method stays simple.
So, in this case, is it really THAT bad if I use comma-separated values?
****ducks****
You already know the answer.
First off, your PHP code isn't even close to working because it only works if user 2 has only a single value in LookingFor or Drugs. If either of these columns contains multiple comma-separated values then IN won't work even if those values are in the exact same order as User 1's values. What do expect IN to do if the right-hand side has one or more commas?
Therefore, it's not "easy" to do what you want in PHP. It's actually quite a pain and would involve splitting user 2's fields into single values, writing dynamic SQL with many ORs to do the comparison, and then doing an extremely inefficient query to get the results.
Furthermore, the fact that you even need to write PHP code to answer such a relatively simple question about the intersection of two sets means that your design is badly flawed. This is exactly the kind of problem (relational algebra) that SQL exists to solve. A correct design allows you to solve the problem in the database and then simply implement a presentation layer on top in PHP or some other technology.
Do it correctly and you'll have a much easier time.
Suppose User 1 is looking for 'Hang Out','Friendship' and User 2 is looking for 'Friendship','Hang Out'
Your code would not match them up, because 'Friendship','Hang Out' is not in ('Hang Out','Friendship')
That's the real problem here.
I'm trying to figure out how and which is best for storing and getting multiple entries into and from a database. Either using explode, split, or preg_split. What I need to achieve is a user using a text field in a form to either send multiple messages to different users or sharing data with multiple users by enter their IDs like "101,102,103" and the PHP code to be smart enough to grab each ID by picking them each after the ",". I know this is asking a lot, but I need help from people more skilled in this area. I need to know how to make the PHP code grab IDs and be able to use functions with them. Like grabbing "101,102,103" from a database cell and grabbing different stored information in the database using the IDs grabbed from that one string.
How can I achieve this? Example will be very helpful.
Thanks
If I understand your question correctly, if you're dealing with comma delimited strings of ID numbers, it would probably be simplest to keep them in this format. The reason is because you could use it in your SQL statement when querying the database.
I'm assuming that you want to run a SELECT query to grab the users whose IDs have been entered, correct? You'd want to use a SELECT ... WHERE IN ... type of statement, like this:
// Get the ids the user submitted
$ids = $_POST['ids'];
// perform some sanitizing of $ids here to make sure
// you're not vulnerable to an SQL injection
$sql = "SELECT * FROM users WHERE ID IN ($ids)";
// execute your SQL statement
Alternatively, you could use explode to create an array of each individual ID, and then loop through so you could do some checking on each value to make sure it's correct, before using implode to concatenate them back together into a string that you can use in your SELECT ... WHERE IN ... statement.
Edit: Sorry, forgot to add: in terms of storing the list of user ids in the database, you could consider either storing the comma delimited list as a string against a message id, but that has drawbacks (difficult to do JOINS on other tables if you needed to). Alternatively, the better option would be to create a lookup type table, which basically consists of two columns: messageid, userid. You could then store each individual userid against the messageid e.g.
messageid | userid
1 | 1
1 | 3
1 | 5
The benefit of this approach is that you can then use this table to join other tables (maybe you have a separate message table that stores details of the message itself).
Under this method, you'd create a new entry in the message table, get the id back, then explode the userids string into its separate parts, and finally create your INSERT statement to insert the data using the individual ids and the message id. You'd need to work out other mechanisms to handle any editing of the list of userids for a message, and deletion as well.
Hope that made sense!
Well, considering the three functions you suggested :
explode() will work fine if you have a simple pattern that's always the same.
For instance, always ', ', but never ','
split() uses POSIX regex -- which are deprecated -- and should not be used anymore.
preg_split() uses a regex as pattern ; and, so, will accept more situations than explode().
Then : do not store several values in a single database column : it'll be impossible to do any kind of useful work with that !
Create a different table to store those data, with a single value per row -- having several rows corresponding to one line in the first table.
I think your problem is more with SQL than with PHP.
Technically you could store ids into a single MySQL field, in a 'set' field and query against it by using IN or FIND_IN_SET in your conditions. The lookups are actually super fast, but this is not considered best practice and creates a de-normalized database.
What is nest practice, and normalized, is to create separate relationship tables. So, using your example of messages, you would probably have a 'users' table, a 'messages' table, and a 'users_messages' table for relating messages between users. The 'messages' table would contain the message information and maybe a 'user_id' field for the original sender (since there can only be one), and the 'users_messages' table would simply contain a 'user_id' and 'message_id' field, containing rows linking messages to the various users they belong to. Then you just need to use JOIN queries to retrieve the data, so if you were retrieving a user's inbox, a query would look something like this:
SELECT
messages.*
FROM
messages
LEFT JOIN users_messages ON users_messages.message_id = messages.message_id
WHERE
users_messages.user_id = '(some user id)'
I have a two separate tables that contain parts of user name (don't ask why)...
t1
---------------
firstName
lastName
t2
---------------
middleName
stage_firstName
stage_middleName
stage_lastName
So before I output the name I run it through a function that capitalizes First letter of Name and uses Stage name if provided.
It works OK, but I now have a case where I need to display multiple names. The question I have, is: shall I use mySQL to store properly formatted name when the user formats it initially, or keep the values in multiple tables and keep on using the function to format them. For some reason I think I can improve some performance by utilizing a single value from a table, even if I add additional table column rather than keeping the fields separately in two separate tables and then parsing each name through this huge function.
Am I wrong with these assumptions?
And if, at some point, you need to extract the name and display/use it in a different format, you will need to then perform some kind of translation on the already formatted string.
You could write the formatting into the query though.