This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 9 years ago.
Is it possible to bind a table name?
I want to make a class to read the columns from a tables and, depending on field type, generate the form inputs for me. When I do $form = new form("users");, the constructor is supposed to start with getting the field names from the table with the following code:
class form{
public function __construct($table, $skip = array("id")){
$pdo = new PDO('mysql:host=localhost;dbname=site;',USER,PASS);
$query = $pdo->prepare("DESCRIBE :table");
$query->bindValue(':table', $table, PDO::PARAM_STR, strlen($table));
$query->execute();
while($field = $query->fetch(PDO::FETCH_NUM)){
var_dump($field);
echo "<br /><br />";
}
unset($pdo);
}
}
This works just fine when I specify "users" instead of ":table" in the prepare statement, but the bind it's working, and I'm pretty sure it's because it's trying to bind a table name. Also, this needs to be binded because I'd like to have the ability to pass my table names through $_GET and the such.
Is it possible to bind a table name?
No.
You have to whitelist table names. I doubt you want to let a user to browse any table from your database.
Given you are using a class, it will be no-brainer to add a table name as a property. It will be simple, elegant and safe. Create an abstract parent class first
abstract class abstractTable {
private $table;
private $db;
public function __construct($pdo){
$this->db = $pdo;
}
public function describe() {
return $db->query("DESCRIBE `$this->table`")->fetchAll();
}
}
Then create a specific class for your table
class someTable extends abstractTable {
private $table = 'sometable';
}
and so you will be able to get the required list of columns
$pdo = new PDO(...);
$table = new someTable($pdo);
$fields = $table->describe();
simple, concise, powerful, safe.
There is a PDO wrapper class at - http://www.phpclasses.org/package/5997-PHP-Database-access-abstraction-layer.html that lets you do this (though I am new to PDO so maybe it isnt using prepared statements)
His suggested usage is:
$db = new DatabaseConnection('someMysqlServer', 'user', 'pass', 'database');
$result = $db->exec($db->filterForSql('SELECT * FROM '.$tableName.';'));
I would interested if others think this is a 'safe' way of using PDO or not.
Related
This question already has answers here:
What does the variable $this mean in PHP?
(11 answers)
Closed 4 years ago.
I was always taught and used $con->prepare for prepared statements. However, this article two answers posted people where using $con->sqli->prepare. I also saw a few others using it in other articles.
Is this something to be concerned with?
What is the difference?
Usually some people make database connection class with constructor of connection. It means that when you initialize the object of that class, the constructor is executed automatically.
For example here is Database class
<?php
class db
{
public $conn;
public function __construct()
{
$this->conn=mysqli_connect("localhost","root","","prepared");//A constructor is a function that is executed after the object has been initialized (its memory allocated, instance properties copied etc.). Its purpose is to put the object in a valid state.
if($this->conn)
{
echo "";
}
else{
echo $this->conn->error;
}
}
}
$db = new db();
?>
Child class
include("db.php");
class childclass extends db
{
public function database_query()//here you don't need to put $conn in parameters
{
$sql = "SELECT * FROM table";
$result = $this->conn->query($sql);//Here you can see how we can call conn from db class
print_r($result);
}
}
I hope you got my point.
I am relatively new to PHP OOP and i know that there are numerous questions here on SO, but none of them seam to be pointing me in the right direction. I have created the class user, and I am calling this in another file.
I am trying to get the method 'reset' to call up 'connect', connect to the mysql db and then query it and set various properties to the row contents.
I am receiving no errors but for some reason it is not feeding the properties any data from the database.
I have tried placing the mySQL connect in the reset method, just to see if the variables cannot be passed between methods. But still no joy.
Can anyone point me in the right direction?
class user(){
public function reset(){
$this->connect();
$sql ='SELECT * FROM users WHERE user_id="'.$user_id.'"' ;
$result = mysqli_query($con,$sql);
while($row = mysqli_fetch_array($result))
{
$this->user_name=$row['dtype'];
$this->user_id=$row['user_id'];
$this->atype=$row['atype'];
$this->user_email=$row['user_email'];
$this->group1=$row['group1'];
$this->group2=$row['group2'];
$this->group3=$row['group3'];
$this->group4=$row['group4'];
$this->group5=$row['group5'];
$this->group6=$row['group6'];
}
// Test that these properties are actually being echoed on initial file... it is
// $this->user_name = "john";
// $this->user_email = "john#gmail.com";
// $this->dtype = "d";
// $this->atype = "f";
}
public function connect(){
//GLOBALS DEFINED IN INDEX.PHP
if ($db_open !== true){
$con=mysqli_connect(DB_HOST,DB_USER,DB_PASS,DB_NAME);
// Check connection
if (mysqli_connect_errno())
{
$debug_system .= 'Error on user.php: ' . mysqli_connect_error().'<br\/>';
} else {
$db_open = true;
$debug_system .= 'user.php: user details grab successful. <br\/>';
}
}
}
}
If you are relatively new to PHP OOP, it is strongly recommended not to mess with awful mysqli API but learn quite sensible PDO first, and only then, making yourself familiar with either OOP and prepared statements, you may turn to mysqli.
Nevertheless, there shouldn't be no function connect() in the class user. You have to have a distinct db handling class, which instance have to be passed in constructor of user class
The problem lies in this line:
$sql ='SELECT * FROM users WHERE user_id="'.$user_id.'"' ;
At no point do you actually define $user_id. Presumably you actually mean $this->user_id.
$sql ='SELECT * FROM users WHERE user_id="'.$this->user_id.'"' ;
Better still would be to make full use of parameterized queries, which might look like this:
$sql ='SELECT * FROM users WHERE user_id=?' ;
You would then prepare the statement and bind the user ID, then execute the query:
$stmt = mysqli_prepare($sql);
mysqli_stmt_bind_param($stmt, $this->user_id);
mysqli_stmt_execute($stmt);
And then fetch the results:
while($row = mysqli_stmt_fetch($result))
As you can see, there is a whole load more to modern MySQL libraries. I'd advise you to do more research into how MySQLi and parameterized queries work (and perhaps PDO as well: it's a superior library) before you use them further. It will be worth the effort.
This question already has answers here:
Can PHP PDO Statements accept the table or column name as parameter?
(8 answers)
Closed 9 years ago.
Is it possible to bind a table name?
I want to make a class to read the columns from a tables and, depending on field type, generate the form inputs for me. When I do $form = new form("users");, the constructor is supposed to start with getting the field names from the table with the following code:
class form{
public function __construct($table, $skip = array("id")){
$pdo = new PDO('mysql:host=localhost;dbname=site;',USER,PASS);
$query = $pdo->prepare("DESCRIBE :table");
$query->bindValue(':table', $table, PDO::PARAM_STR, strlen($table));
$query->execute();
while($field = $query->fetch(PDO::FETCH_NUM)){
var_dump($field);
echo "<br /><br />";
}
unset($pdo);
}
}
This works just fine when I specify "users" instead of ":table" in the prepare statement, but the bind it's working, and I'm pretty sure it's because it's trying to bind a table name. Also, this needs to be binded because I'd like to have the ability to pass my table names through $_GET and the such.
Is it possible to bind a table name?
No.
You have to whitelist table names. I doubt you want to let a user to browse any table from your database.
Given you are using a class, it will be no-brainer to add a table name as a property. It will be simple, elegant and safe. Create an abstract parent class first
abstract class abstractTable {
private $table;
private $db;
public function __construct($pdo){
$this->db = $pdo;
}
public function describe() {
return $db->query("DESCRIBE `$this->table`")->fetchAll();
}
}
Then create a specific class for your table
class someTable extends abstractTable {
private $table = 'sometable';
}
and so you will be able to get the required list of columns
$pdo = new PDO(...);
$table = new someTable($pdo);
$fields = $table->describe();
simple, concise, powerful, safe.
There is a PDO wrapper class at - http://www.phpclasses.org/package/5997-PHP-Database-access-abstraction-layer.html that lets you do this (though I am new to PDO so maybe it isnt using prepared statements)
His suggested usage is:
$db = new DatabaseConnection('someMysqlServer', 'user', 'pass', 'database');
$result = $db->exec($db->filterForSql('SELECT * FROM '.$tableName.';'));
I would interested if others think this is a 'safe' way of using PDO or not.
I need to know how many sql queries are being executed per page request. As the site is already done and I am just running optimization analysis, I would prefer if any solution offered doesnt require that i change the entire website structure.
I use a single connection to send all queries to the MySQL database:
define('DATABASE_SERVER', '127.0.0.1');
define('DATABASE_NAME', 'foco');
define('DATABASE_USERNAME', 'root');
define('DATABASE_PASSWORD', '');
$DB_CONNECTION = new mysqli(
DATABASE_SERVER,
DATABASE_USERNAME,
DATABASE_PASSWORD,
DATABASE_NAME,
3306
);
Then to execute a query i use:
$query = "SELECT * FROM `sometable`";
$queryRun = $DB_CONNECTION->query($query);
Is there a way to count how many queries have been sent and log the answer in a text file just before php closes the connection?
You can extend the mysqli object and override the query method:
class logging_mysqli extends mysqli {
public $count = 0;
public function query($sql) {
$this->count++;
return parent::query($sql);
}
}
$DB_CONNECTION = new logging_mysqli(...);
One of the best ways would be to run a log function inside your $DB_CONNECTION->query().
That way you can either log each individual query to a db table, or perform basic test on query speed and then store this, or just increment the count (for number of queries) and store this.
Create class extending mysqli, make $DB_CONNECTION object of that class and do your statistics in your implementation of query() method. Eventually it shall call parent::query() to do real job.
Create a proxy that you use instead of mysqli directly...
class DatabaseCounter {
private $querycount = 0;
private $mysqli = null;
// create mysqli in here in constructor
public function query(...) {
$this->queryCount++;
$this->mysqli->query(...);
}
}
$DB_CONNECTION = new DatabaseCounter();
I just started switching my project form the mysql to PDO. In my project a new PDO Object is created more or less right a the beginning of the programm.
$dbh_pdo = new PDO("mysql:host=$db_url;dbname=$db_database_name", $db_user, $db_password);
Now I would like to use this handler (is that the correct name?) in some functions and classes. Is there a way to make objects global just like variables or am I trying something unspeakably stupid, because I couldn't find anything when searching the web ...
Yes, you can make objects global just like any other variable:
$pdo = new PDO('something');
function foo() {
global $pdo;
$pdo->prepare('...');
}
You may also want to check out the Singleton pattern, which basically is a global, OO-style.
That being said, I'd recommend you not to use globals. They can be a pain when debugging and testing, because it's hard to tell who modified/used/accessed it because everything can. Their usage is generally considered a bad practice. Consider reviewing your design a little bit.
I don't know how your application looks like, but say you were doing this:
class TableCreator {
public function createFromId($id) {
global $pdo;
$stmt = $pdo->prepare('SELECT * FROM mytable WHERE id = ?');
$stmt->execute(array($id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
// do stuff
}
}
}
You should do that instead:
class TableCreator {
protected $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function createFromId($id) {
$stmt = $this->pdo->prepare('SELECT * FROM mytable WHERE id = ?');
$stmt->execute(array($id));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
// do stuff
}
}
}
Since the TableCreator class here requires a PDO object to work properly, it makes perfect sense to pass one to it when creating an instance.
You'll use $GLOBALS['dbh_pdo'] instead of $dbh_pdo inside any functions. Or you can use the global keyword, and use $dbh_pdo (i.e. global $dbh_pdo).
You could also try using a Singleton to pass back a PDO object to you. That way you only ever have one PDO object (and one database connection) in any request which saves on memory/server resources.