Get data from different table based on Id - php

I'm building a small e-commerce website and I want to display the reviews, and I want to create screen names for people (first letter of first name concatenated onto the last name), but I can't figure out how to get the information from my clients table. Let me show you the code I've done so far:
$invId = filter_input(INPUT_GET, 'invId', FILTER_SANITIZE_NUMBER_INT); // this is taken from a name value pair from the view
// Gets the raw data from the database
function getProRev($invId){
$db = acmeConnect();
$sql = "SELECT * FROM reviews WHERE invId = :invId ORDER BY reviewId DESC";
$stmt = $db->prepare($sql);
$stmt->bindValue(':invId', $invId, PDO::PARAM_STR);
$stmt->execute();
$tn = $stmt->fetchAll();
$stmt->closeCursor();
return $tn;
}
// Builds the simple review display
function buildReviewDisplay($reviews){
$rd = "<div id='reviewView'>";
foreach ($reviews as $review){
$rd .= "<h2>$review[clientId]</h2>";
$rd .= "<h3>$review[reviewDate]</h3>";
$rd .= "<p>$review[reviewText]</p>";
$rd .= "<hr>";
}
$rd .= "</div>";
return $rd;
}
As you can see, I'm displaying the clientId (a number) which is not what I want, and now this is where I'm stuck. I have the relationship between the two tables (clients and reviews) set up, but I can't figure out how to get the data. Here is the function I tried to write, but it didn't work:
// Trying to get the dang client info
function getUsername($clientId){
$db = acmeConnect();
$sql = "SELECT * FROM clients WHERE clientId = :clientId";
$stmt = $db->prepare($sql);
$stmt->bindValue(':clientId', $clientId, PDO::PARAM_STR);
$stmt->execute();
$cd = $stmt->fetchAll();
$stmt->closeCursor();
$fletter = substr($cd['clientFirstname'], 0, 1);
$scrnam = $fletter . $cd['clientLastname'];
return $scrnam;
}
And I understand that this didn't work because there was nothing passing the $clientId parameter to the function, but the is contained in the $tn[] array, so there has to be a way that I can take the $clientId from the $tn[] array and query the database for the first and last name, but I can't figure out how.

You can join the clients table to the reviews table in your first query.
SELECT * FROM reviews
LEFT JOIN clients ON reviews.clientId = clients.clientId
WHERE invId = :invId ORDER BY reviewId DESC
Then you'll have access to the client name columns without needing to execute an additional query for each review you display.
That way you can use your code from getUsername in buildReviewDisplay.
foreach ($reviews as $review) {
$fletter = substr($review['clientFirstname'], 0, 1);
$scrnam = $fletter . $review['clientLastname'];
$rd .= "<h2>$scrnam</h2>";
$rd .= "<h3>$review[reviewDate]</h3>";
$rd .= "<p>$review[reviewText]</p>";
$rd .= "<hr>";
}

Related

Merge two SELECT statements and return one JSON response

I would like to merge the results of two select statements and return one single JSON response. Basically, I want to return id, name, company, and email for every record found, but also return the signature column if the ticket matches the POST data.
Also, is it possible to remove any duplicate records in the final array?
$selectTable = "tickets_info";
$selectColumns = "id, name, company, email";
$stmt = $conn->prepare("SELECT $selectColumns FROM $selectTable WHERE created BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW() ORDER BY id DESC");
$stmt->execute();
if (isset($_POST['ticket'])) {
$stmt2 = $conn->prepare("SELECT signature FROM tickets_info WHERE ticket = ?");
$stmt2->execute(array($_POST['ticket']));
}
$results = $stmt->fetchAll();
if (isset($_POST['ticket'])) {
$results = $stmt2->fetchAll();
}
if ($results) {
header("Content-Type: application/json");
echo json_encode($results);
}
I would loop through the query response with something along these lines:
$stmt = $conn->prepare("SELECT id, name, company, email, signature, ticket FROM tickets_info WHERE created BETWEEN DATE_SUB(NOW(), INTERVAL 30 DAY) AND NOW() ORDER BY id DESC");
$stmt->execute() ;
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
$response[$i]['id'] = $row['id'] ;
$response[$i]['name'] = $row['name'] ;
$response[$i]['company'] = $row['company'] ;
$response[$i]['email'] = $row['email'] ;
if ($row['ticket'] == $_POST['ticket']) $response[$i]['signature'] = $row['signature'] ;
else $response[$i]['signature'] = NULL ;
$i++ ;
}
header("Content-Type: application/json");
echo json_encode($response);
You only do one SQL query and loop through the response once. If that row matches the AJAX ticket query, we add the signature to the array of objects. If not, we set the signature value to null.
The right way to do is use Join . If you don't want to do it with join you can first put the results in two different arrays. then merge those two seperate arrays and then filter any duplicate arrays.
Remember you want to have the same keys for both Sql Queries.

Reading spatial data from MySQL using PHP

I have a website that manages points of interest, using PHP and MySQL. I decided to look at MySQL's Spatial Data features instead of saving the coordinates in two separate fields.
I managed to get the inserting of data into the database using the following:
// Update new records
$query = "UPDATE users SET users_address = :uaddress, users_placeid = :uplace, users_coords = POINTFROMTEXT(:location) ";
$query .= "WHERE users_id = :uid ";
// echo "Query: $query <br>";
$stmt = $conn->prepare($query);
$stmt->execute(array(':uaddress' => $users_address,
':uplace' => $users_placeid,
':location' => $location,
':uid' => $users_id));
$result = $stmt;
Now I want to read the data and get the coordinates out, using PHP and PDO. There does not seem to be any examples on the Internet for using PDO, PHP and MySQL for spatial data.
My normal SELECT code is:
$stmt = $conn->prepare("SELECT * FROM users WHERE users_id = :uid ");
$stmt->execute(array(':uid' => $users_id));
$result = $stmt;
if ($result->rowCount() > 0) {
foreach($result as $row) {
$users_address = $row['users_address'];
$users_placeid = $row['users_placeid'];
$users_lat = $row['x.users_coords'];
echo "Lat: $users_lat <br>";
}
}
I've tried various options and each one gives an error. The code above returns:
Notice: Undefined index: x.users_coords
I want to stick to using SELECT * instead of SELECT users_address, etc. if possible.
The other option is to just return to using two fields for the coordinates, but that makes it more difficult to do distance measurements etc later.
Any idea how to extract Latitude and Longitudes?
After much frustration I managed to solve the problem. You have to specify the spatial data in the SELECT string and then it is easy to read the data. Here is full code to read the data:
$stmt = $conn->prepare("SELECT *, X(users_coords) AS users_lat, Y(users_coords) AS users_long FROM users WHERE users_id = :uid ");
$stmt->execute(array(':uid' => $users_id));
$result = $stmt;
if ($result->rowCount() > 0) {
foreach($result as $row) {
$users_address = $row['users_address'];
$users_placeid = $row['users_placeid'];
$users_lat = $row['users_lat'];
// echo "Lat: $users_lat <br>";
$users_long = $row['users_long'];
// echo "Long: $users_long <br>";
}
}
?>

check if last row or not when running loops in PHP

I am using this PHP Code to run queries to a MySQL Database:
$i=0;
$display='[';
$stmt = $pdo_conn->prepare("SELECT * from tickets where status = :status and deleted = :deleted ");
$stmt->execute(array(':status' => 'Open', ':deleted' => ''));
$records = $stmt->fetchAll(PDO::FETCH_ASSOC);
$counter = count($records);
foreach($records as $result) {
$i++;
$stmt = $pdo_conn->prepare("SELECT * from contacts where sequence = :sequence ");
$stmt->execute(array(':sequence' => $result["contact"]));
$contact = $stmt->fetch();
$display.='{';
$display.='"customer":"'.$contact["forename"].' '.$contact["surname"].'",';
$display.='"subject":"'.$result["subject"].'"';
if($counter == $i) {
$display.='},';
} else {
$display.='}';
}
}
$display.=']';
I would ideally like the end result to show as the below:
[{"customer":"Carol","subject":"Fax not working"}{"customer":"Clive","subject":"VoIP Issues"}{"customer":"Leigh ","subject":"company Antaeus"}{"customer":"Debbie","subject":"emails"}{"customer":"Kim","subject":"Printer setup"}{"customer":"Sue ","subject":"Phone"}{"customer":"Sandra","subject":"Debbie's computer "}{"customer":"Daniel","subject":"Email Attachments"}{"customer":"Lara","subject":"Internet Issues"}]
However, at the moment it looks like:
[{"customer":"Carol","subject":"Fax not working"}{"customer":"Clive","subject":"VoIP Issues"}{"customer":"Leigh ","subject":"company Antaeus"}{"customer":"Debbie","subject":"emails"}{"customer":"Kim","subject":"Printer setup"}{"customer":"Sue ","subject":"Phone"}{"customer":"Sandra","subject":"Debbie's computer "}{"customer":"Daniel","subject":"Email Attachments"}{"customer":"Lara","subject":"Internet Issues"},]
Notice the comma on the end before the ]
How can i make sure that comma does not show at the end, I tried using the if statement in my loop with the counters ($counter and $i) but that didn't work
You can do this without any loops and a single inner join. Instead of manually constructing a JSON string, you are advised to use json_encode() to do it for you. Run a single join query, and collect the rows into a single array which is encoded as JSON..
This eliminates the need for all your other machinery - loops, and counters.
// A single join query will return everything you need from both tables.
// Customer names can be concatenated here into a single Customer field
// You only appear to need tickets.subject.
// And reading your queries, the table relation appears to be tickets.contact = contacts.sequence
$sql = '
SELECT
t.subject AS Subject,
CONCAT(c.forename, ' ', c.surname) AS Customer
FROM
tickets t
INNER JOIN contacts c ON t.contact = c.sequence
WHERE status = :status AND deleted = :deleted;
';
$stmt = $pdo_conn->prepare($sql);
if ($stmt) {
$stmt->execute(array(':status' => 'Open', ':deleted' => ''));
// Fetch all rows...
$rows = $stmt->fetchAll();
// Now $rows looks like the 2D array needed, you can directly JSON encode it
$output = json_encode($rows);
}
// Inspect it...
echo $output;
I'll point out that although you are absolutely right to be in the habit of bound parameters, there actually isn't a need for them here since the strings 'Open' and '' are static and known. You can just call a plain query() on this instead of prepare()/execute().
// No user input, static strings only, means no need for params
$sql = "
SELECT
t.subject AS Subject,
CONCAT(c.forename, ' ', c.surname) AS Customer
FROM
tickets t
INNER JOIN contacts c ON t.contact = c.sequence
WHERE status = 'Open' AND deleted = '';
";
// Just a simple query() call
$result = $pdo_conn->query($sql);
if ($result) {
$rows = $result->fetchAll();
// etc...
}

Php stuck because to long load on mysqli query in php function, how to fix?

i'm using a php function to get dome mysql data from other mysql host than my webserver.
Function:
public function theMysqli($build){ // $build is given by othe code (no usedata)
$mysqli = new mysqli($server, $user, $password, $database);
$catid = array( /* +/- 40 id's */ ); //data is $catid = configs::songcats();
$type = array( /* +/- 15 captical letters */ ); //data is $type = configs::songtype();
$limit = 20;
$lstart = $_post['page'];
if($lstart == ''){
$lstart = 0;
}
else{
$lstart = $lstart * $limit;
}
$sletter = $_POST['letter'];
$search = $sletter.'%';
$catquery = "SELECT songid FROM category WHERE catID IN('".implode("', '", $catid)."')";
if ($db = $mysqli->query($catquery)){
while($row = $db->fetch_array()){
$idsong[] = $row;
}
$db->close();
}
foreach($idsong as $gt){
$songid[] = $gt['songid'];
}
// songid is a array over the 30000 values
$countquery = "SELECT id FROM songlist WHERE songtype IN('".implode("', '", $type)."') AND id IN('".implode("', '", $songid)."') AND songname LIKE '".$search."'";
if ($db = $mysqli->query($countquery)){
$countr = $db->num_rows;
$db->close();
}
$pages = ceil($countr / $limit);
$songquery = "SELECT id, songname, artist, copyright, duration FROM songlist WHERE songtype IN('".implode("', '", $type)."') AND id IN('".implode("', '", $songid)."') AND songname LIKE '".$search."' ORDER BY songname ASC LIMIT $lstart, $limit";
if ($db = $mysqli->query($songquery)){
while($row2 = $db->fetch_array()){
$result[] = $row2;
}
$db->close();
}
if($built == 'counter'){
$final == $pages;
}
else if($build == 'gresult'){
$final == $result;
}
return $final;
}
Now my problem is the load time he need for this script it will be to long. Even when i set php.ini so that execute may be 300sec he will stuck by loading the page. Now i know you can get data grom mutiple mysql tables by one query but i can't find any solution to do that in combination with php implode function.
Total rows i must get by $_POST['letter'] M is +/- 1200; (web radio mp3 database)
Can someone help me to fix this function so i get no timeout's anymore.
Thanks
The problem here is that you're fetching a list from the database, and then sending that list back as part of a query. You should really be doing most of this stuff in SQL, using either JOIN or nested queries. This will make your program much faster.
First, create a table for all of your catids and types. Your catquery should then be:
SELECT songid
FROM category
WHERE catID IN (
SELECT id
FROM catids
)
Use the same sort of pattern to join your queries together. It looks like you can cut down most of your code here to just one SQL query. You'll save a ton of time and memory by not having to send all that data back and forth between your program and the database.
Some reading material for you:
SQL Joins: http://beginner-sql-tutorial.com/sql-joins.htm
SQL Subquery: http://beginner-sql-tutorial.com/sql-subquery.htm

Keeping a counter

*Here is what I am trying to acheive: *
Basically I have a form where people can submit events to our database. In the CMS I have a page which displays a record of the number of events.
*Here is what I have: *
After the button is clicked, this script is called:
if($subject_type == 'Event') {
$query = "SELECT town, update_id, event_validex ";
$query .= "FROM dev_town ";
$query .= "LEFT JOIN updates ON dev_town.town_id = updates.town ";
$query .= " WHERE sitename = '".SITENAME."'";
$query .= " AND month = " .date('m')." AND year =" .date('Y');
$querys = $this->tep_db_query($query);
$rows = $this->tep_db_fetch_array($querys);
extract($rows); //extract rows, so you don't need to use array
$eventid = $event_validex + 1;
$sql_data_array = array('event_validex' => $eventid);
$submit_to_database = $this->tep_db_perform('updates', $sql_data_array, 'update', "town='".$town."'");
This works fine, however I cant seem to solve the next bit
This is the Problem
As you can see, it checks the database for the current month and adds it, this is providing that the sitename and that month are there, not a site and another month.
How would I get it to add the row in IF the sitename and month are not there?
I have been manually adding the months in now so that it works, and I am sure you can agree that's a ball ache.
Cheers peeps
if you want to check if site A + Month 11 exists do a select query against it and store the number of rows returned in a variable. ( $exists = mysql_num_rows("your query here"); )
then do an if statement against the $exists variable and proceed as you wish
if($exists) {
// update
} else {
// add
}
$insert = "INSERT INTO updates ('town','month','year','event_validex') VALUES ('".$town."','". date('m')."','". date('Y')."','1')";
$eventid = 1;
$sql_data_array = array('event_validex' => $eventid);
$submit_to_database = $this->tep_db_perform('updates', $sql_data_array, 'update', "town='".$town."'");
}
}
this is what I have for the else statement there, however it will add one to the value if its there but will not add a new entry if its isnt.. ?
I don't see exactly how your method "checks the database for the current month and adds it "; I'll just assume that the tep_db_perform() method of your class handles this somehow.
(uhk! n00bed it; rest of the post was somehow chopped off?) Since you're already hitting the database with the select with the intent of using the data if a record is found, then you could use the resultset assigned to $rows as a means of checking if a record exists with SITENAME and Month.
See below:
if($subject_type == 'Event') {
// build query to check the database for sitename, month and year.
$query = "SELECT town, update_id, event_validex ";
$query .= "FROM dev_town ";
$query .= "LEFT JOIN updates ON dev_town.town_id = updates.town ";
$query .= " WHERE sitename = '".SITENAME."'";
$query .= " AND month = " .date('m')." AND year =" .date('Y');
// Execute Query(wrapper for $result = mysql_query I guess?)
$querys = $this->tep_db_query($query);
// Get a resultset from database. --> you could merge this into one method with $this->tep_db_query
$rows = $this->tep_db_fetch_array($querys);
if(count($rows) > 0) {
extract($rows); //extract rows, so you don't need to use array --> I try to stay away from extract() as it makes for random variables being created.
$eventid = $event_validex + 1;
$sql_data_array = array('event_validex' => $eventid);
$submit_to_database = $this->tep_db_perform('updates', $sql_data_array, 'update', "town='".$town."'");
} else {
// insert new record into database
// updated with code to execute insert SQL query.
$insert = "INSERT INTO updates ('town','month','year','event_validex') VALUES ('".$town."','". date('m')."','". date('Y')."','1')";
$result = $this->tep_db_query($query);
}
....
}
If I've misunderstood something, please let me know, happy to work through it with you.
Hope this helps. :)

Categories