I am using a nice piece of code to reorder db content using drag and drop. I can get it to work locally by enabling the PDO extension in the php.ini file but my hosting package (shared) does not allow PDO and MySQLi simultaneously. I am unfamiliar with PDO and I would appreciate any help in rewriting the following segment to work with MySQLi, if possible.
Thanks.
<?php
if (isset($_POST['orders'])) {
} else {
echo json_encode(array('error' => true));
}
$orders = explode('&', $_POST['orders']);
$array = array();
foreach($orders as $item) {
$item = explode('=', $item);
$item = explode('_', $item[1]);
$array[] = $item[1];
}
try {
$objDb = new PDO('mysql:host=localhost;dbname=test', 'user', 'pw');
$objDb->exec("SET CHARACTER SET utf8");
foreach($array as $key => $value) {
$key = $key + 1;
$sql = "UPDATE `artwork`
SET `listorder` = ?
WHERE `id` = ?";
echo $sql;
$objDb->prepare($sql)->execute(array($key, $value));
}
echo json_encode(array('error' => false));
} catch(Exception $e) {
echo json_encode(array('error' => true));
}
My recommendation? Find another host. Going from PDO to mysqli is not a good idea, because you will waste time porting code into a less portable state.
-- Edit --
You can try the following code snippet, if it doesn't work it should get you started. I couldn't test it because none of my servers have mysql* modules compiled.
$dbo = new mysqli('localhost', 'user', 'password', 'database');
if (mysqli_connect_error()) {
echo sprintf('Unable to connect: ErrNo: (%d), ErrMsg: (%s)', mysqli_connect_errno, mysqli_connect_error());
exit;
}
foreach ($array as $key => $value) {
$key = $key + 1;
$sql = "UPDATE `artwork` SET `listorder` = " . (int) $key . " WHERE `id` = " . (int) $value;
$dbo->query($sql);
}
$dbo->close();
You can get more information on mysqli query and other functions here.
Anyway, good luck.
Related
I've pieced together some code I've gleaned from the internet: I'm trying to scan a directory to insert file names and index into MariaDB table. My last hurdle it seems is this PDO error: PDO::exec() expects exactly 1 parameter, 2 given on line 55. I've tagged line(55) with '//error thrown here'.
My novice guess is it doesn't like the parameters escaped in []??
As noted above novice here...
Any insight/help is greatly appreciated. Thanks in advance.
<?php
$host = 'localhost';
$dbname = 'dirdb';
$username = 'root';
$password = '';
// Create connection
try {
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Connected successfully";
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$dir = './recipes';
$GLOBALS['I'] = 0; // root folder given index 0
function dirToArray( $dir , $parent) {
$result = array();
$cdir = scandir($dir);
foreach ($cdir as $key => $value) {
if (!in_array($value, array(".", ".."))) {
if (is_dir($dir . DIRECTORY_SEPARATOR . $value)){
$result[$value] = [++$GLOBALS['I']]; // add folder index
$result[$value][] = $parent; // add parent folder index
$result[$value][] = dirToArray($dir . DIRECTORY_SEPARATOR . $value, $GLOBALS['I']);
} else {
$result[] = $value;
}
}
}
return $result;
}
$res = dirToArray($dir, $GLOBALS['I']);
function dirToDb($res, $parentId = 0)
{global $conn;
foreach ($res as $key => $value) {
if (is_array($value)) {
$conn->exec ("insert into sp_files (path, parentId) VALUES (?, ?)", [$key, $parentId]); //error thrown here
dirToDb($value, $conn->fetch("SELECT LAST_INSERT_ID()"));
} else {
$conn->exec ("insert into sp_files (path, parentId) VALUES (?, ?)", [$value, $parentId]);
}
}
}
//$res = dirToArray($dir);
dirToDb($res);
You can't use $conn->exec() to execute a query with parameters. You have to use prepare() to create a statement, then execute the prepared statement.
There's also no $conn->fetch() method. fetch() is a method of the PDOStatement class, you can use it either with a prepared statement or the result of a query. But you don't need to perform a query to get LAST_INSERT_ID(), PDO has an insertId() method for this.
function dirToDb($res, $parentId = 0) {
global $conn;
$stmt = $conn->prepare("insert into sp_files (path, parentId) VALUES (?, ?)");
foreach ($res as $key => $value) {
$stmt->execute([$key, $parentId]);
if (is_array($value)) {
dirToDb($value, $stmt->insertId);
}
}
}
Forgive me if the question is a little odd
I can clarify if needed:
I have the code that can connect to a mysql database as normal, however i have encapsulated it as a class:
<?php
define("HOST", "127.0.0.1"); // The host you want to connect to.
define("USER", "phpuser"); // The database username.
define("PASSWORD", "Secretpassword"); // The database password.
class DBConnection{
function conn($sql, $database){
$DB = new mysqli(HOST,USER,PASSWORD,$database);
if ($DB->connect_error){
die("Connection failed: " . $DB->connect_error);
exit();
}
if ($result = $DB->query($sql)){
return TRUE;
$DB->close();
}
else{
echo "Error: " . $sql . "<br>" . $DB->error;
$DB->close();
}
}
}
?>
I have done it this way so i can include this class in any subsequent php page and allow them to send it an sql statment and the database, see below as an example:
$sql = ("INSERT INTO users (first_name, last_name, username, email, password, group_level) VALUES ('John', 'Doah','JDoah', 'example#email', 'password', 'user')");
$DB = new DBConnection;
$result = $DB->conn($sql,"members");
if ($result ==TRUE){
return "Record added sucessfully";
}
This works fine.
however, im looking to send other sql statments to DBConnection.
How do i do that and to have it pass back any results that it recives? errors, boolean, row data etc. The caller will worry about parsing it.
Hopefully that makes sense.
This is an old class I used to use way back in the days of mysql still works but will need to be updated for mysqli or newer
class DBManager{
private $credentials = array(
"host" => "localhost",
"user" => "",
"pass" => "",
"db" => ""
);
function DBManager(){
$this->ConnectToDBServer();
}
function ConnectToDBServer(){
mysql_connect($this->credentials["host"],$this->credentials["user"],$this->credentials["pass"]) or die(mysql_error());
$this->ConnectToDB();
session_start();
}
function ConnectToDB(){
mysql_select_db($this->credentials["db"]) or die(mysql_error());
}
function Insert($tableName,$data){
$parameters = '';
$len = count($data);
$i = 0;
foreach($data as $key => $value){
if(++$i === $len){
$parameters .= $key . "='$value'";
}else{
$parameters .= $key . "='$value'" . ", ";
}
}
$query = "INSERT INTO $tableName SET $parameters";
mysql_query($query) or die(mysql_error());
return true;
}
function GetRow($tableName,$select,$where){
$selection = '';
$len = count($select);
$i = 0;
foreach($select as $key){
if(++$i === $len){
$selection .= $key;
}else{
$selection .= $key . ",";
}
}
$whereAt = '';
foreach($where as $key => $value){
$whereAt .= $key . "='$value'";
}
$query = "SELECT $selection FROM $tableName WHERE $whereAt";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)){
return $row;
}
}
}
The key things here is you can create a persistent connection to your database without rewriting a bunch of code
Example
global $DB;
$DB = new DBManager();
Since the connection happens in the constructor you will now have a connection on the page you call this code and can begin getting and setting to the database through use of $DB->GetRow() and $DB->Insert() which makes things much easier and was modeled after the $wpdb instance which is a class that manages the database in wordpress sites
Examples
For these examples we will assume you have a table as such
Insert new student
//create an associative array
$data = array(
"student_id" => 1,
"birth_date" => "02/06/1992",
"grade_level" => 4
);
//Send Call
$dm->Insert("student",$data);
Get data
//Create selection
$selection = array("grade_level");
//Create associative array for where we want to find the data at
$where = array(
"id" => 1
);
//Get Result
$result = $dm->GetRow("student",$selection,$where);
//do something with result
echo $result->grade_level;
I am trying to add query results to an array. My while statement works but I am not getting anything in my array. Here is my code:
$res=$pdo->query("select * from questions where category_id='$category' ORDER BY RAND()");
$rows = $res->rowCount();
if ($rows < 1){
echo "There is no question in the database";
exit();}
$questionsArray = array();
while ($item = $res->fetch(PDO::FETCH_ASSOC)){
$questionsArray[] = $item;
echo "There should be some info here<br>";
}
You might want to consider something like this, with thru PDO prepared statements.
Also, a while loop with a fetch is bad and slow and was good 15 years ago with MySQL.
Here is the proper way to do it.
define("SQLHOST", "127.0.0.1");
define("SQLUSER", "user");
define("SQLPASS", "password");
define("SQLSGBD", "database");
try {
$con = new PDO('mysql:host=' . SQLHOST . ';dbname=' . SQLSGBD . ';charset=UTF8', SQLUSER, SQLPASS);
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
var_dump('Connection failed: ' . $e->getMessage());
}
$categories = ['A', 'B', 'C'];
$questionsArray = array();
$stmt = $con->prepare("select * from questions where category_id=? ORDER BY RAND()");
foreach ($categories as $key => $cat) {
$stmt->bindParam(1, $cat, PDO::PARAM_STR);
$stmt->execute();
$obj = $stmt->fetchall(PDO::FETCH_ASSOC);
if (count($obj) !== 0) {
foreach ($obj as $key2 => $item) {
$questionsArray[] = [$cat => $item];
}
}
}
I have the following code. Is there any way to combine and simplify it?
The output in the json.html file should be like this: ["abc","def","ghi"].
<?php
// Make a MySQL Connection
mysql_connect("localhost", "root", "admin") or die(mysql_error());
mysql_select_db("test1") or die(mysql_error());
// Get all the data from the "example" table
$result = mysql_query("SELECT * FROM test_auto_complete") or die(mysql_error());
$menu = array();
while($row = mysql_fetch_assoc($result))
{
$menu[] = array("id" => $row['username'],);
}
foreach($menu as $key=>$value)
{
$menu[$key] = $value['id'];
}
$my_json_content = json_encode($menu);
$file = 'json.html';
$current = file_get_contents($file);
file_put_contents($file, $my_json_content);
?>
I know the code looks bad, but even so, can someone help me?
Thanks
Haan
If you want to put content in file than just use file_put_contents
$my_json_content = json_encode($menu);
$file = 'json.html';
file_put_contents($file, $my_json_content);
And use this while loop without foreach
while($row = mysql_fetch_assoc($result))
{
$menu[] = $row['username'];
}
I won't even give you solution with mysql_* because they are depracated look at the solution in PDO
<?php
$dsn = 'mysql:dbname=test1;host=127.0.0.1';
$user = 'root';
$password = 'admin';
try{
$dbh = new PDO($dsn, $user, $password);
$menu = array();
foreach ($conn->query("SELECT * FROM test_auto_complete") as $row)
$menu[] = $row['username'];
file_put_contents('json.html', json_encode($menu));
}catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
?>
Tips:
Mysql_* functions are depracated and they don't support a lot of features of MySQL
Foreach in your case was senseless.
File_get_contents() in your code does not have any sense for me, what do you need the content of file for?
Variables are used for data which is going to be changed. For example in your case you use variable for json.html which seems to be constant, if so, then use constant string.
I am selecting data from a database. The database field names are exactly the same as the class variable names. Is there a way to store this data into the class variables without specifying each one individually?
//gets info about a specified file.
//chosen based on a supplied $fileId
function getFileInfo($fileId)
{
//select info from database
$sql = "SELECT id, companyId, url, name, contentType, fileSize, saved, retrieved
FROM files
WHERE id = $fileId";
$results = $this->mysqli->query($sql);
$results = $results->fetch_object();
//store info into class variables
$this->id = $results->id;
$this->companyId = $results->companyId;
$this->url = $results->url;
$this->name = $results->name;
$this->contentType = $results->contentType;
$this->fileSize = $results->fileSize;
$this->saved = $results->saved;
$this->retrieved = $results->retrieved;
}
A quick and dirty way would ba a loop:
foreach($result as $var => $value) {
$this->$var = $value;
}
I'd propose this approach:
$nameMap = array(
'id',
'companyId',
'url',
'name',
'contentType',
'fileSize',
'saved',
'retrieved',
);
foreach( $nameMap as $attributeName ) {
$this->$attributeName = $results->$attributeName ;
}
While one could write
foreach($result as $var => $value) {
...
}
the outcome fully depends on backing table's structure. If you add further attributes to the table, your code might break.
Using $nameMap, the application still works.
Just use foreach structure:
foreach ($result as $column => $value) {
$this->$column = $value;
}
Not nice but will work.
Humm. Well, PDO has native functions for that, if you're not married to mysqli for some reason:
<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();
$result = $sth->fetch(PDO::FETCH_OBJ);
print $result->NAME;
The biggest disadvantage I've found is that PDO doesn't support SSL connections between the PHP machine and the MySQL machine.