Using data from multiple tables - php

Here's my issue: I have 3 tables, with overlapping information (specifically, the username) in each. Except the username row isn't named the same thing in every table. Because the username is specific to the user, it makes sense to get all the other information about the user based on the username. Here's what I have. (The first function returns the query, the second function returns the information in an array (or is supposed to, anyway).
function get_user_by_id($id) {
global $connection;
$query = "SELECT * FROM ownerOrganization, owner, queue_acl";
$query .=" WHERE owner.ownerId=ownerOrganization.ownerId";
$query .=" AND owner.ownerId=queue_acl.user_id";
$query .= " AND owner.ownerId ='{$id}'";
$result_set = mysql_query($query);
confirm_query($result_set);
if ($user = mysql_fetch_array($result_set)) {
return $user;
} else {
return NULL;
}
}
function get_user_id() {
if (isset($_GET['ownerId'])) {
return get_user_by_id($_GET['ownerId']);
}
}
But when I do something like, $sel_user = get_user_id(); on another page, it doesn't actually pull up any of the selected users information... I assume that this is happening because my syntax regarding working with multiple tables is incorrect. Anyway, any input would be much appreciated.

To use JOINS, take this snipcode in example :
$query = "SELECT * FROM (ownerOrganization INNER JOIN owner ON owner.ownerId=ownerOrganization.ownerId) INNER JOIN queue_acl ON owner.ownerId=queue_acl.user_id";
$query .=" WHERE owner.ownerId ='{$id}'";
Regards

I was typing what more or less what #MTranchant wrote. I would suggest renaming your columns for easier query authoring and to avoid confusion. For instance your ownerOrganization.ownerid could be named oo_ownerid, and the other columns in the table could follow that naming convention.
Also, have you run the query against the database with a hard-coded $id that you know exists?
Lastly in the query string being sent to the next page, does a ownerId parameter appear that looks like "&ownerId="?

Related

Query: select specific fields from specific table

I am trying to create a login function that would allow me to specify what table I want to select the data from, and also what fields I want to select.
I have managed to pass the table value to the function, and select data from the desired table, but my tables have different fields. How can I specify in the query it is one table select: user_id, user_first_name, user_password , or if it is the other table select member_id, member_first_name, member_password.
Here is what I have coded so far:
public function logIn($id, $password, $table){
$dataArray = array();
$t = ($table === 'employers') ? 'employers' : 'members');
$query = "SELECT user_id, user_first_name, user_password FROM $t";
$stmt = $this->link->prepare($query);
if ($stmt->execute())
{
$result = $stmt->get_result();
while($row = $result->fetch_array(MYSQLI_ASSOC))
{
$dbuser_id = $row['user_id'];
$dbpassword = $row['user_password'];
$dbuser_first_name = $row['user_first_name'];
}
//and so on...
Also, one quick question: Is this a bad programming practice, or should I have 2 login(members, and users)?
Thanks :)
The Single Responsibility Principle in programming is intended to prevent things like this from happening - the goal is for one class/function to have one responsibility, rather than having to manage 2 (or potentially more) as you have here. In short, it is a bad programming practice and you should have 2 login functions like you said. After making 2 different functions, a switch statement might help to check the case of a member logging in versus a user.
Note: There are exceptions to this. However, in your case, it would make more sense to separate the two.
Here is a link to further explain SRP and SOLID design principles:
Single Responsibility Principle on TutsPlus

Only one query instead of two

I have 2 tables, one is called post and one is called followers. Both tables have one row that is called userID. I want to show only posts from people that the person follows. I tried to use one MySQL query for that but it was not working at all.
Right now, I'm using a workaround like this:
$getFollowing = mysqli_query($db, "SELECT * FROM followers WHERE userID = '$myuserID'");
while($row = mysqli_fetch_object($getFollowing))
{
$FollowingArray[] = $row->followsID;
}
if (is_null($FollowingArray)) {
// not following someone
}
else {
$following = implode(',', $FollowingArray);
}
$getPosts = mysqli_query($db, "SELECT * FROM posts WHERE userID IN($following) ORDER BY postDate DESC");
As you might imagine im trying to make only one call to the database. So instead of making a call to receive $following as an array, I want to put it all in one query. Is that possible?
Use an SQL JOIN query to accomplish this.
Assuming $myuserID is an supposed to be an integer, we can escape it simply by casting it to an integer to avoid SQL-injection.
Try reading this wikipedia article and make sure you understand it. SQL-injections can be used to delete databases, for example, and a lot of other nasty stuff.
Something like this:
PHP code:
$escapedmyuserID = (int)$myuserID; // make sure we don't get any nasty SQL-injections
and then, the sql query:
SELECT *
FROM followers
LEFT JOIN posts ON followers.someColumn = posts.someColumn
WHERE followers.userID = '$escapedmyuserID'
ORDER BY posts.postDate DESC

Bigger & less or smaller & more queries?

So lets say I had two tables, and one (lets call it person) had a field called type that stored an integer linking to another table (lets call it types with a field called id. What would be more performance enhancing?
One larger query storing all the values of type and then looping over the person table and grabbing a value from the array we got from the types query.
On every loop of person grab a value from types
Use the JOIN query to join the type onto the person query.
Note: in the examples I used some fake variables such as $db (obviously). Just think of these like a CodeIgniter database class or something...
Example Code of BP #1:
<?php
$types = $this->db->query("SELECT * FROM `types`")->result_array();
$query = $this->db->query("SELECT * FROM `person`");
foreach($query->result_array() as $value)
{
$type = $types[$value['type']];
}
Example Code of BP #2: (Edited to add of form of caching)
<?php
$query = $this->db->query("SELECT * FROM person");
$types = [];
foreach($query->result_array() as $value)
{
if(empty($types[$value['type']]))
{
$types[$value['type']] = $this->db->query("SELECT * FROM types WHERE id = {$value['type']} LIMIT 1")->row_array();
}
$type = $types[$value['type']];
}
Example Code of BP #3: (NB: I haven't used JOIN at all so please forgive any errors in the query, and feel free to fix it up...)
<?php
$query = $this->db->query("SELECT * FROM person JOIN types ON person.type = types.id");
foreach($query->result_array() as $value)
{
// type is already there for us in $value
}
Note: person and types both (will) have over 100k+ rows, we're expecting.
The join approach (option 3) should certainly be the most efficient - the other two approaches are essentially re-inventing the processing that the database is designed to do in the first place, and all the relevant data has to be sent to the web server before it can be done!

mySQL fetch column based on another column in PHP

I'm trying to write my first PHP script with mySQL and I desperately need some help. I'm sure this is relatively simple, but if I have one field in my table (username, for example), and I want to fetch another field (name, for example), that is in the same row as the given username, how do I do that?
Again, I'm sure this is easy, but I'm lost, so I'd really appreciate any help. Thanks!
$sql = "SELECT username, name FROM table";
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result)) {
echo "This {$row['username']} has the name {$row['name']}\n";
}
halfdan's answer sort of works, but it fetches all rows and displays them. What you want is a WHERE clause, which lets you filter the contents of the table so the query only returns the row(s) you want:
SELECT username, name
FROM sometable
WHERE (username = 'johndoe');
This will return only the rows where the username field is equal to 'johndoe'. Conceptually, it's equivalent to:
$results = mysql_query("SELECT username, name FROM table");
while($row = mysql_fetch_assoc($results)) {
if ($row['username'] == 'johndoe') {
// do something, this is a row you want
} else {
// not a row you want. ignore it, or deal with it some other way
}
}
the main difference is that for large data sets in the database, doing client-side filtering like this is expensive, as the entire contents of the table has to be transferred over. Using a WHERE clause to limit things to just what you want is far more efficient in the long run.

Using sql JOIN

I'm a sql noob trying to get this query to use 2 tables.
tables & columns are:
person:
department_id,
name,
etc...
department:
department_id,
dept_name,
etc...
I have a 'select' html form that the user will choose a dept_name from, and I need my php script to return every person with a matching department_id. Here is my code & query so far, I'd appeciate any help.
$search_dept = $_POST['search_dept'];
$conn = odbc_connect($odbc_name, $user_name, $pass_wd);
if ($conn) {
$query = "SELECT person.*
FROM department
JOIN person
ON department.department_id=person.department_id
WHERE department.name=$search_dept";
if($result = odbc_exec($conn, $query)) {
echo '..stuff';
while ($row = odbc_fetch_array($result)) {
...echo stuff
}
echo '...stuff';
}
else {
echo 'Query was unsuccessful';
}
}
else {
echo 'Unable to connect to database';
}
First of all, you are going about this the wrong way. You don't want to execute a WHERE clause against a text-type column if you can avoid it. Since your person table already has the department_id as a foreign key, you will want to use that value to do your selection. This means you will have to modify your select element to contain the department IDs as the options' values.
<!-- Example -->
<select name="dept_id">
<option value="1">Sales</option>
<option value="2">Support</option>
<option value="3">Fulfillment</option>
</select>
So now, not only will just the raw selection occur faster since you'll be executing against an indexed column (you did make it a proper FK so it's indexed, right?), but you will also be removing the join altogether! (which is another boost to the query's speed)
// Here is injection-safe code for the ODBC driver
$stmt = odbc_prepare( "SELECT * FROM person WHERE department_id = ?" );
$success = odbc_execute( $stmt, array( $_POST['dept_id'] ) );
// Here is the old, non-secure version, but is db-driver agnostic
$deptId = $_POST['dept_id']; // escape this please!
$query = "SELECT * FROM person WHERE department_id = $deptId";
Try this query, also make sure to escape any user input. What if the user would provide:
$_POST['search_dept']= "'; DROP TABLE person;";
Never ever ever thrust userinput!
$search_dept = mysql_escape_string($_POST['search_dept']); //make sure to escape this! you can use other functions for this as well. I'm not sure if PDO has some.
$query = "SELECT *
FROM person
JOIN department
ON department.department_id=person.department_id
WHERE department.name='$search_dept'";

Categories