I executing the following code which creates a company_id as a UUID_SHORT in a temporary table.
This company_id will then be used to insert records in multiple tables with the UUID as the primary key. My issue is when I try retrieve the company_id that is $company_id in my code it is null. However if I json_encode ($tempResult) the company_id value is there. What am I doing wrong?
Any help is much appreciated, thank you!
try {
$conn = new PDO("mysql:host=localhost;dbname=$dbname", $db->id, $db->pass); //connect to db
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //error modes
$temp = $conn->prepare('CREATE TEMPORARY TABLE tempId (user_id VARCHAR(17) PRIMARY KEY, company_id VARCHAR(17))');
$temp->execute();
$temp = $conn->prepare('INSERT INTO tempId(user_id, company_id) VALUES(:user_id, UUID_SHORT())');
$temp->bindParam(':user_id', $_SESSION['username'], PDO::PARAM_INT);
$temp->execute();
$temp = $conn->prepare('SELECT company_id FROM tempId WHERE user_id = :user_id ');
$temp->bindParam(':user_id', $_SESSION['username'], PDO::PARAM_INT);
$temp->execute();
$tempResult= $temp->fetchAll(PDO::FETCH_ASSOC);
$company_id = $tempResult->company_id;
// $result[1] =$_SESSION('username');
} catch(PDOException $e) {
$result = $e->getMessage();
}
print json_encode($company_id);
Here:
$tempResult= $temp->fetchAll(PDO::FETCH_ASSOC);
If the fetchAll is successful, then $tempResult will be an array. For debugging, we can verify this using the convenient var_dump, e.g.
var_dump($tempResult);
If $tempResult is an array, I'm wondering about this expression:
$tempResult->company_id
What does that return? What do you expect that to return? Why?
EDIT: I know better than to answer a question with a question, or three questions.
However, I can't (in good conscience) bring myself to giving an "answer" to the problem with OP code...
at least not without (figuratively) scratching my head wondering about the actual SQL being used in the code.
What is the purpose of the TEMPORARY TABLE? Why is there an INSERT to it? Why is the UNSIGNED BIGINT datatype (returned by UUID_SHORT() function) being cast to a VARCHAR(17)? Is there some reason we want to lop off 1 or 2 digits when the function returns 18 or 19 decimal digits?
If the intent of this block of code is to return a value from MySQL UUID_SHORT() function, I'm not understanding why we need more than one statement. Obviously, there's something I'm missing, why this wouldn't suffice:
try {
$conn = new PDO("mysql:host=localhost;dbname=$dbname", $db->id, $db->pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sth = $conn->prepare('SELECT UUID_SHORT() AS company_id');
$sth->execute();
$company_id = $sth->fetchColumn();
} catch(PDOException $e) {
//var_dump($e->getMessage);
} finally {
if(isset($sth)){ $sth->close(); }
if(isset($conn)){ $conn->close(); }
}
(An application wouldn't churn database connections like this; there would either be a connection pool, or the connection would be passed in to this routine.)
Not sure, but as soon as fetchAll returns array, your code:
$company_id = $tempResult->company_id;
is invalid, you should:
$company_id = $tempResult[0]['company_id'];
or
$tempResult= $temp->fetch(PDO::FETCH_ASSOC);
$company_id = $tempResult['company_id'];
Related
I have a page as shown in the screenshot below. The idea is to enter the bus number and the list of all stops on a particular route, one per line.
The stops are already stored in a database table called 'stops' I need the ID of each stop from the textarea. My current code only gets the ID of the last stop in the textarea. I feel like I am missing something. 'busnumber' is my textfield and 'busroute' is my textarea. I would appreciate if anyone can point me out on what I need to change in order to get the ID of each stop entered in the textarea as an array. Thanks for your time in advance.
try {
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
if(isset($_POST["busnumber"]) && isset($_POST["busroute"])){
$stops = explode(PHP_EOL, $_POST["busroute"]);
$stopsArray = '"' . implode('","', $stops) . '"';
$sql = "SELECT * FROM stops WHERE stop_name IN ($stopsArray)";
echo $sql."</br>";
$query = $conn->prepare($sql);
$query->execute();
$query->setFetchMode(PDO::FETCH_ASSOC);
$results = $query->fetchAll();
foreach($results as $result){
echo $result['stop_id'].' '.$result['stop_name'].'</br>';
}
}
} catch (PDOException $pe) {
die("Could not connect to the database $dbname :" . $pe->getMessage());
}
UPDATE 1
I changed the code as follows
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
if(isset($_POST["busnumber"], $_POST["busroute"])){
$stops = explode(PHP_EOL, $_POST["busroute"]);
foreach($stops as $stop){
$sql = "SELECT * FROM stops WHERE stop_name = '".$stop."'";
$statement = $conn->query($sql);
echo $sql.'</br>';
$statement->setFetchMode(PDO::FETCH_ASSOC);
$results = $statement->fetchAll();
foreach($results as $result){
echo $result['stop_id'].' '.$result['stop_name'];
}
$statement = null;
}
}
and still get the same output, it only gives me the ID of the last item inside the textarea
I just realized that you have working code displayed above. I'm sorry for giving answers before (see history if ya want) that are already there above (*haha). Here, I've updated the code of yours (the first one). I changed the part where you display the result:
try {
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
if(isset($_POST["busnumber"]) && isset($_POST["busroute"])){
$stops = explode(PHP_EOL, $_POST["busroute"]);
$stopsArray = '"' . implode('","', $stops) . '"';
$sql = "SELECT * FROM stops WHERE stop_name IN ($stopsArray)";
$query = $conn->prepare($sql);
$query->execute();
if ($query->rowCount() > 0){
while ($row = $query->fetch(PDO::FETCH_ASSOC)){
echo '<br/>'.$row['stop_id'].' '.$row['stop_name'];
}
}else{
echo "No records found...";
}
}
} catch (PDOException $pe) {
die("Could not connect to the database $dbname :" . $pe->getMessage());
}
Note: As I have read some tutorials, using while loop is conventional than fetchAll().
Your db structure could help to give you a more precise info. Since it is lacking, I am going to speculate over it a little just to give you an idea.
Each bus (route) has several stops. That means there must be a foreign key defined in stops table and it points to route table.
In order to select all stops from stops table on a given route, what you need to do is to modify your select statement as follows:
Semantic code
SELECT * from stops where stops.routeId = <aGivenRouteId>
or
SELECT * from stops where stops.routeId in (an Array Of Route IDs)
Keep in mind that second form is slower.
I hope it makes sense to you.
__UPDATE__
If this is the case, there might be a many to many relationship. If this is the case, look for another table which connects stops and routes. That table should contain just route_id and stop_id in order to associate them to each other. From that table, you can select stop_ids on a given route, and then from stops table you can get names of the stops.
Hope it helps.
__UPDATE2__
Oh I see. You may need to modify your screen a bit. Something like this:
+Add Route-----------------------------------------+
|Bus Number |
|__________ |
| |
|Stops In This Route All Stops |
+--------------------------+-+--+------------------+
|Stop 2 |x| |Stop 1 |
|Stop 5 |x| |Stop 2 |
|Stop 9 |x|<<|Stop 3 |
| | |Stop 4 V|
+--------------------------+-+--+------------------+
|Add Route |
+----------------------------+--+------------------+
In All Stops part, you can show all the stops in DB (in your stops table). For stops in this route part, I suggest you to create another table where you associate stops and routes, basically a table containing stop_id and route_id.
Would it work for you this way?
I FIXED THE ERROR. The solution for anyone out there is simple, the PHP explode function was used to split the contents of a textarea into separate lines but it doesn't work if you use explode() with PHP_EOL. PHP EOL tells you the server's newline character from what I understand. I used the preg_split instead to perform the splitting and it works on both my localhost that runs on Windows and my server that runs on Linux. Thank you everyone for your help!!!
$conn = new PDO("mysql:host=$host;dbname=$db;charset=$charset", $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if(isset($_POST["busnumber"], $_POST["busroute"])){
$stops = preg_split("/\\r\\n|\\r|\\n/", $_POST['busroute']);
$sql = 'SELECT * FROM stops WHERE stop_name LIKE :stop';
$statement = $conn->prepare($sql);
foreach($stops as $stop){
$statement->bindValue(':stop', $stop);
$statement->execute();
while($result = $statement->fetch()){
echo $result['stop_id'].' '.$result['stop_name'].'</br>';
}
}
}
$conn = new PDO("mysql:host=$host;dbname=$db;charset=$charset",$user,$pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if(isset($_POST["busnumber"], $_POST["busroute"]))
{
$stops = preg_split("/\\r\\n|\\r|\\n/$_POST['busroute']);
$sql = 'SELECT * FROM stops WHERE stop_name LIKE :stop';
$statement = $conn->prepare($sql);
foreach($stops as $stop){
$statement->bindValue(':stop', $stop);
$statement->execute();
while($result = $statement->fetch())
{
echo $result['stop_id'].' '.$result['stop_name'].'</br>';
}
}
I have a users table where I want to update the scores each time a user finishes the game. Unityscript part is working fine but after I post the score to the database it appears doubled or tripled. I post the score as int and also the table column is of int format. My PHP looks like this:
try {
$db = new PDO("mysql:host=$host;dbname=$dbname", $db_user, $db_pass);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$data = array(
':username' => $_POST['username'],
':score' => $_POST['score']);
$statement = $db -> prepare ("UPDATE users SET score = score + :score
WHERE username = :username");
$statement->execute($data);
}
catch(PDOException $e) {
echo $e->getMessage();
}
Any help or advice is appreciated.
You are using prepared statements, but you are still allowing injection by directly implementing the $score variable. Do the same thing with score that you did with username.
What do you mean by double or triple? Do you mean that the number is two or three times bigger? If so, try using a SELECT statement to fetch the score and do the math in PHP. Then, UPDATE the users table.
Doing this will allow you to better understand what you are doing wrong. Have you tried echoing the value of score within your try and catch to see if the value repeats? The code may be running more than once.
$statement = $db -> prepare ("UPDATE users SET score = :score
WHERE username = :username");
use this, i think it will work
I have 3 tables which I have to add a record to them after registration of a new user:
List of Tables:
I. users
... ... ... id (auto_increment, primary)
... ... ... email (email address of new user)
II. blogs
... ... ... id (auto_increment, primary)
... ... ... owner_id (= 'id' in 'users')
III. events
... ... ... id (auto_increment, primary)
... ... ... owner_id (= 'id' in 'users')
... ... ... blog_id (= 'id' in 'blogs')
In this situation I found 2 solutions for adding sequential records:
Solution 1: Using lastInsertId
<?php
try {
// Step 1: add a record to 'users' table and get lastInsertId
$query = $conn->prepare("INSERT INTO users (email) VALUES (:email)");
$query->bindParam(':email', $email);
$query->execute();
$user_id = $conn->lastInsertId();
// Step 2: add a record to 'blogs' table and get lastInsertId
$query = $conn->prepare("INSERT INTO blogs (owner_id) VALUES (:owner)");
$query->bindParam(':owner', $user_id);
$query->execute();
$blog_id = $conn->lastInsertId();
// Step 3: add a record to 'events' table
$query = $conn->prepare("INSERT INTO events (owner_id, blog_id) VALUES (:owner, :blog)");
$query->bindParam(':owner', $user_id);
$query->bindParam(':blog', $blog_id);
$query->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
Solution 2: Using single execute()
<?php
try {
// Step 1
$query = $conn->prepare("INSERT INTO users (email) VALUES (:email);" .
"INSERT INTO blogs (owner_id) VALUES ((SELECT id FROM users WHERE email = :email));" .
"INSERT INTO events (owner_id, blog_id) VALUES ((SELECT id FROM users WHERE email = :email), (SELECT id FROM blogs WHERE owner_id = (SELECT id FROM users WHERE email = :email)));");
$query->bindParam(':email', $email);
$query->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
Which solution should I choose for a better performance and security? Is there a better solution for my purpose?
Note: the connection created using PDO:
<?php
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
);
try {
$conn = new PDO("mysql:host=" . App::DB_HOST . ";dbname=" . App::DB_NAME . ";charset=utf8", App::DB_USERNAME, App::DB_PASSWORD, $options);
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
I would use transactions as a modification of 1st option.
$conn->beginTransaction();
try {
// Step 1: add a record to 'users' table and get lastInsertId
$query = $conn->prepare("INSERT INTO users (email) VALUES (:email)");
$query->bindParam(':email', $email);
$query->execute();
$user_id = $conn->lastInsertId();
// Step 2: add a record to 'blogs' table and get lastInsertId
$query = $conn->prepare("INSERT INTO blogs (owner_id) VALUES (:owner)");
$query->bindParam(':owner', $user_id);
$query->execute();
$blog_id = $conn->lastInsertId();
// Step 3: add a record to 'events' table
$query = $conn->prepare("INSERT INTO events (owner_id, blog_id) VALUES (:owner, :blog)");
$query->bindParam(':owner', $user_id);
$query->bindParam(':blog', $blog_id);
$query->execute();
$conn->commit();
}
catch (PDOException $e) {
// roll back transaction
$conn->rollback();
echo $e->getMessage();
die();
}
If you do some benchmarks you will see most time will be lost making the request.
From personal benchmarks on simple queries like this the execution time is very low.
The only thing that realy took time is the initialisation/prepare function.
There for making 3 requests will be slower then creating one large one.
EDIT:
Option 1 is the correct one because you do need to use id's, never link using a string or somethign else allways use id's.
Appart from that 1 (prepared) big query is better then 3x a prepare.
Edit. I misread the question at first, thought you are using exec(), not execute().
So, in fact you can combine both, as lastInsertId is just a PHP wrapper for Mysql's LAST_INSERT_ID()
But, as you need two ids, it will require additional mess with setting a variable. So, I doubt second option would worth, although feasible.
Just note that second would work only if PDO emulation mode is turned off
And surely there is no such question like "performance". Both will go perfectly.
Like the title says, I want the id of a row to be returned after INSERT to the database.
I've got 2 functions, one to make a connection to the database:
function db_connect() {
$host = "host";
$user = "user";
$pwd = "pwd";
$database = "db";
$con;
try{
$conn = new PDO( "sqlsrv:Server= ".$host." ; Database = ".$database." ", $user, $pwd);
}
catch(Exception $e){
die(print_r($e));
}
return $conn;
}
And one to insert a new record:
function setTiptile($name,$cols,$rows) {
$connect = db_connect();
$query = "INSERT INTO data(ID, name, cols, rows) VALUES(NEWID(),?,?,?)";
$stmt = $connect->prepare($query);
$stmt->bindValue(1, $name);
$stmt->bindValue(2, $cols);
$stmt->bindValue(3, $rows);
$stmt->execute();
return $connect->lastInsertId('ID'); // This should work, but doesn't, why?
}
I need the last function to return the ID of the inserted row, how should I do this?
EDIT:
Like the title says, the ID is an uniqueidentifier, no idea if that changes things.
EDIT: Ok, apparently I've got to use:$connect->lastInsertId('ID');, but this isn't returning anything at all. What can be the cause of that? The new row ís created in the database.
From the Manual:
Returns the ID of the last inserted row, or the last value from a
sequence object, depending on the underlying driver. For example,
PDO_PGSQL() requires you to specify the name of a sequence object for
the name parameter.
It should be something like:
return $connect->lastInsertId('yourIdColumn');
Use lastInsertId
$conn->lastInsertId();
(My) solution:
The parameter of lastInsertId() has to be the table name instead of the row name. Besides that, the table must have a row with the parameter IDENTITY checked, this is the row which is returned.
That brings to the conclusion that it's impossible to return a uniqueidentifier with lastInsertId() since this cannot have the parameter IDENTITY checked.
why not first do a select newid()
and then use that id in the insert
Hi and thanks for reading.
I'm new to php (but I've been programming for a long time now) so I decided to use the pdo interface as a starter for my database queries. I did put a small script to test but it returns the database name as one of the columns name. Why?
Also for you pdo pros, once I instanciated a new pdo object without specifying the database name, how can I select it to prevent writing "databaseName.tableName" in my queries... See my script below:
try
{
$dbh = new PDO('mysql:host=localhost', 'root', '', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
}
catch (Exception $e)
{
echo 'Erreur : ' . $e->getMessage() . '';
echo 'N° : ' . $e->getCode();
die();
}
$sth = $dbh->prepare("CREATE DATABASE IF NOT EXISTS myTest DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci");
$sth->execute();
$sth = $dbh->prepare("CREATE TABLE IF NOT EXISTS myTest.user(
personID int NOT NULL AUTO_INCREMENT,
PRIMARY KEY(personID),
FirstName varchar(15),
LastName varchar(15),
Age int(3)
)");
$sth->execute();
$sth = $dbh->prepare("INSERT INTO myTest.user (FirstName, LastName, Age) VALUES(?, ?, ?)");
$sth->execute(array("Charles", "Gagnon", "28"));
$sth = $dbh->query("SELECT * FROM myTest.user");
$result = $sth->fetch(PDO::FETCH_ASSOC);
$json = json_encode($result);
print_r($json);
?>
So yeah, the print_r outputs this json:
{"personID":"1","FirstName":"Charles","user":"28"}
Pretty weird, it outputs the name of the table (user) instead of "Age" and the LastName field isn't there at all...
Any help will be appreciated, thanks!
Cannot replicate this. Using your exact code, I get
{"personID":"1","FirstName":"Charles","LastName":"Gagnon","Age":"28"}
Are you sure the myTest database and table user do not already exist with a different schema to what you're expecting (yet somehow still working for the INSERT statement)?
Edit: There's no way your insert statement would work if the schema was different.
Also for you pdo pros, once I instanciated a new pdo object without specifying the database name, how can I select it to prevent writing "databaseName.tableName"
Just re-instate the PDO object, specifying the dbname parameter in the DSN. Otherwise, I suppose you could try executing a use <database>; command.