Hi this is kind of an upgraded version of this question:
query mysql database from inside a class
The difference from the previous question, is i need a dynamic query not a static one or l$query = "SELECT col_1 FROM db.table"; So in order to have a dynamic query i need to use properties (or variables) so i can call different tables from that same class, or something like this "SELECT ‘$data’ FROM ‘$table’ ";
So far my class looks like this, similar to the previous question:
$mysqli = new mysqli("localhost", "root", "", "intranetpugle");
class crudmum {
private $table;
private $data;
private $mysqli;
function __construct($mysqli) {
$this->mysqli = $mysqli;
}
function runQuery($data2, $table2)
{
$this->table = $table2; $this->data = $data2;
$query = "SELECT '$this->data' FROM '$this->table' ";
$stmt = $this->mysqli->prepare($query);
$stmt->execute();
$stmt->bind_result($r);
while($stmt->fetch())
{
echo "<option>" . $r . "</option>";
}
}
};
This is how i run it:
$showme = new crudmum($mysqli);
$showme->runQuery("priority", "trackboards" );
Note: When i dont use variables or properties inside the query or somethng like this, SELECT priority FROM trackboards, the query does work, only when i input the properties or variables (like the given example) it does not work.
I get this error:
Fatal error: Call to a member function prepare() on a non-object in C:\xampp\htdocs\devserv\i+d\bootstrap\functions.php on line 76
Anyone see what am i doing wrong, of course there is a mistake with the database query any ideas on how to query the database right in a dynamic way within a class, sorry new with OOP with PHP!
found the mistake which was to add 'quotes' on the variables, like shown below:
$query = "SELECT '$this->data' FROM '$this->table' ";
The correct way would be to take out those 'quotes' on the variables or like this:
$query = "SELECT $this->data FROM $this->table ";
With that fix, the query runs just fine, guess i lacked attention to detail, thanx everyone for their help.
Ok, similar questions has been asked and answered before. However, I want to count prepared queries as well. I thought I could just use the prepare() function to increment the query count but that provided me some questionable results. Right now, it's telling me 10 queries are being executed... Generally I only use prepared statements unless the data is static or cannot be modified in anyway.
I found this code from another question that was identical to this. Except that the code only was counting queries that were executed using the query() and exec() functions. I tried to modify it but as I said before it isn't counting any prepared queries but the queries are still executed and return results...
class PDOEx extends PDO
{
private $queryCount = 0;
public function query($query)
{
++$this->queryCount;
return parent::query($query);
}
public function exec($statement)
{
++$this->queryCount;
return parent::exec($statement);
}
public function execute($args = null)
{
++$this->queryCount;
if (!is_array($args)) {
$args = func_get_args();
}
return parent::execute($args);
}
public function GetCount()
{
return $this->queryCount;
}
}
I just want to say thanks in advance. Please, if you can point me in the right direction it would be much appreciated, thanks!
The reason prepared queries aren't being counted is because it returns a PDOStatement, which is different than PDO. You could just ask the database how many queries were run on a given session, so as long as you don't keep create new \PDO objects then the result will be correct. Keep in mind even that query is counted as a query, so if you want to exclude it subtract 1 from the value.
Code
$db = new \PDO('mysql:host=127.0.0.1;dbname=sandbox', 'localuser', 'password');
$db->query('SELECT * FROM user WHERE id = 5');
$db->query('UPDATE user SET name = 'Demo' WHERE id = 5');
$db->query('DELETE FROM user WHERE id = 5');
echo $db->query('SHOW SESSION STATUS LIKE "Questions"')->fetchColumn(1);
Output
4
I'm new to PDO CLASS programming, here's my question, I have this class that retrive some infos from DB and I really need something like that, I get the error on title:
Call to a member function prepare() on a non-object on query line:
$stmt = $this->db->prepare()
What I'm doing wrong?
class map{
private $db;
public $dir;
public $query;
function mapWant($query,$db,$dir){
$stmt = $this->db->prepare("SELECT ".$this->query." WHERE ID = :dir");
$stmt->execute(array(':dir'=>$this->dir));
$row=$stmt->fetch(PDO::FETCH_LAZY);
echo $row[0]; //I want retrive the only field that the result has
}
}
$map = new map();
$map->mapWant($dir,$db,"Breve");
$dir is a $_GET method that retrive only a number
$db = is PDO connection (that's work);
thank you in advance.
You are passing the $db reference as a parameter, but then trying to access it within the scope of your class. The same goes for $query and $dir.
You seem to be under the impression that any parameters passed to a method will be applied as class properties. This is not the case.
The following line:
$stmt = $this->db->prepare("SELECT ".$this->query." WHERE ID = :dir");
Should simply be:
$stmt = $db->prepare("SELECT ".$query." WHERE ID = :dir");
Provided that $db passed to $map->mapWant() is a valid database resource.
I am new to OOP in PHP and i am trying to create a class, and then query the database. ATM the code looks like this and i am stuck in the query part. The query is ok, but it should use the class created. Can anyone help me please?
<?php
class Products {
//objekto kintamieji
public $category_id;
public $product_id;
public function __construct($category_id, $product_id){
$this->category_id = $category_id;
$this->product_id = $product_id;
}
public function query_the_database() {
if($xml->action == 'getProducts') {
$query = mysql_query("SELECT * FROM product WHERE category_id = 1 ORDER BY product_id");
while($row = mysql_fetch_object($query)){
$row->pvm = $row->price - round($row->price*100/121, 2);
$prod[] = $row;
}
}
}
}
You really should be using MySQLi or, even better, PDO on your class.
And, I highly recommend that you establish your connection in a separate class. So you have two pages: db.class.php and products.class.php.
Well, basic tutorial:
Establishing a connection:
$db=new PDO("mysql:host=HOST_NAME;port=PORT;dbname=DB_NAME");
Executing normal queries:
$db->execute("select * from table");
Executing queries with parameters (prepared statements):
$sql=$db->prepare("select * from table where param1=:p1 and param2=:p2");
$sql->bindParam(":p1", $p1); //bindParam only accepts variables
$sql->bindValue(":p2", "Value"); //bindValue only accepts raw values
$sql->execute();
Fetching values of prepared statements:
$array=$sql->fetchAll(); //that will be an array containing values in column names that are in row numbers. Like this: Array([0]=>Array([0]=>"value1" [column1]=>"value1") [1]=>Array([0]=>"value2" [column1]=>"value2"))
But please, go read about it since it will help you A LOT.
Because I find PDO executions extremely hard to remember and find myself looking back at previous projects or other websites just to remember how to select rows from a database, I decided that I would try and create my own functions that contain the PDO executions and just plug in the data I need. It seemed a lot simpler than it actually is though...
So far I have already created a connect function successfully, but now when it comes to create a select function I'm stumped for multiple reasons.
For starters there could be a variating amount of args that can be passed into the function and secondly I can't figure out what I should pass to the function and in which order.
So far the function looks like this. To keep me sane, I've added the "id" part to it so I can see what exactly I need to accomplish in the final outcome, and will be replaced by variables accordingly when I work out how to do it.
function sql_select($conn, **what to put here**) {
try {
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = :id');
$stmt->execute(array('id' => $id));
$result = $stmt->fetchAll();
if ( count($result) ) {
foreach($result as $row) {
print_r($row);
}
} else {
return "No rows returned.";
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
}
So far what I've established that the function will need to do is
Connect to the database (using another function to generate the $conn variable, already done)
Select the table
Specify the column
Supply the input to match
Allow for possible args such as ORDER by 'id' DESC
Lastly from this I would need to create a function to insert, update and delete rows from the database.
Or, is there a better way to do this rather than functions?
If anyone could help me accomplish my ambitions to simply simplify PDO executions it would be greatly appreciated. Thanks in advance!
First of all, I have no idea where did you get 10 lines
$stmt = $conn->prepare('SELECT * FROM myTable WHERE id = ?');
$stmt->execute(array($id));
$result = $stmt->fetchAll();
is ALL the code you need, and it's actually three lines, which results with a regular PHP array that you can use wherever you wish. Without the need of any PDO code. Without the need of old mysql code.
Lastly from this I would need to create a function to insert, update and delete rows from the database.
DON'T ever do it.
Please read my explanations here and here based on perfect examples of what you'll end up if continue this way.
accomplish my ambitions to simply simplify PDO executions
That's indeed a great ambition. However, only few succeeded in a real real simplification, but most resulted with actually more complex code. For starter you can try code from the first linked answer. Having a class consists of several such functions will indeed improve your experience with PDO.
. . . and find myself looking back at previous projects or other
websites just to remember how to select rows from a database . . .
FYI, we all do that.
You had a problem with the PDO API and now you have two problems. My best and strongest suggestion is this: If you want a simpler/different database API, do not roll your own. Search http://packagist.org for an ORM or a DBAL that looks good and use it instead of PDO.
Other people have already done this work for you. Use their work and focus instead on whatever awesome thing is unique to your app. Work smart, not hard and all that.
Writting a wrapper, should start form connecting the DB, and all the possible method could be wrapped. Passing connection to the query method, doesn't look good.
A very rough example would be the code bellow, I strongly do not suggest this mixture, but it will give you the direction.
You connection should be made either from the constructor, or from another method called in the constructor, You can use something like this:
public function __construct($driver = NULL, $dbname = NULL, $host = NULL, $user = NULL, $pass = NULL, $port = NULL) {
$driver = $driver ?: $this->_driver;
$dbname = $dbname ?: $this->_dbname;
$host = $host ?: $this->_host;
$user = $user ?: $this->_user;
$pass = $pass ?: $this->_password;
$port = $port ?: $this->_port;
try {
$this->_dbh = new PDO("$driver:host=$host;port=$port;dbname=$dbname", $user, $pass);
$this->_dbh->exec("set names utf8");
} catch(PDOException $e) {
echo $e->getMessage();
}
}
So you can either pass connection credentials when you instantiate your wrapper or use default ones.
Now, you can make a method that just recieves the query. It's more OK to write the whole query, than just pass tables and columns. It will not make a whole ORM, but will just make the code harder to read.
In my first times dealing with PDO, I wanted everything to be dynamically, so what I achieved, later I realized is immature style of coding, but let's show it
public function query($sql, $unset = null) {
$sth = $this->_dbh->prepare($sql);
if($unset != null) {
if(is_array($unset)) {
foreach ($unset as $val) {
unset($_REQUEST[$val]);
}
}
unset($_REQUEST[$unset]);
}
foreach ($_REQUEST as $key => $value) {
if(is_int($value)) {
$param = PDO::PARAM_INT;
} elseif(is_bool($value)) {
$param = PDO::PARAM_BOOL;
} elseif(is_null($value)) {
$param = PDO::PARAM_NULL;
} elseif(is_string($value)) {
$param = PDO::PARAM_STR;
} else {
$param = FALSE;
}
$sth->bindValue(":$key", $value, $param);
}
$sth->execute();
$result = $sth->fetchAll();
return $result;
}
So what all of these spaghetti does?
First I though I would want all of my post values to be send as params, so if I have
input name='user'
input name='password'
I can do $res = $db->query("SELECT id FROM users WHERE username = :user AND password = :password");
And tada! I have fetched result of this query, $res is now an array containing the result.
Later I found, that if I have
input name='user'
input name='password'
input name='age'
In the same form, but the query remains with :user and :password and I submit the form, the called query will give mismatch in bound params, because the foreach against the $_REQUEST array will bind 3 params, but in the query I use 2.
So, I set the code in the beginning of the method, where I can provide what to exclude. Calling the method like $res = $db->query("SELECT id FROM users WHERE username = :user AND password = :password", 'age'); gave me the possibility to do it.
It works, but still is no good.
Better have a query() method that recieves 2 things:
The SQL string with the param names
The params as array.
So you can use the foreach() logic with bindValue, but not on the superglobal array, but on the passed on.
Then, you can wrap the fetch methods
public function fetch($res, $mode = null)
You should not directly return the fetch from the query, as it might be UPDATE, INSERT or DELETE.
Just pass the $res variable to the fetch() method, and a mode like PDO::FETCH_ASSOC. You can use default value where it would be fetch assoc, and if you pass something else, to use it.
Don't try to be so abstract, as I started to be. It will make you fill cracks lately.
Hum... IMHO I don't think you should try to wrap PDO in functions, because they're already "wrapped" in methods. In fact, going from OOP to procedural seems a step back (or at least a step in the wrong direction). PDO is a good library and has a lot of methods and features that you will surely lose if you wrap them in simple reusable functions.
One of those features is the BeginTransaction/Rollback (see more here)
Regardless, In a OOP point of view you can decorate the PDO object itself, adding some simple methods.
Here's an example based on your function
Note: THIS CODE IS UNTESTED!!!!
class MyPdo
{
public function __construct($conn)
{
$this->conn = $conn;
}
public function pdo()
{
return $this->conn;
}
public function selectAllById($table, $id = null)
{
$query = 'SELECT * FROM :table';
$params = array('table'=>$table);
if (!is_null($id)) {
$query .= ' WHERE id = :id';
$params['id'] = $id;
}
$r = $this->conn->prepare($query)
->execute($params)
->fetchAll();
//More stuff here to manipulate $r (results)
return $r;
}
public function __call($name, $params)
{
call_user_func_array(array($this->conn, $name), $params);
}
}
Note: THIS CODE IS UNTESTED!!!!
ORM
Another option is using an ORM, which would let you interact with your models/entities directly without bothering with creating/destroying connections, inserting/deleting, etc... Doctrine2 or Propel are good bets for PHP.
Howeveran ORM is a lot more complex than using PDO directly.