I'm having a little trouble making something work with a PDO. I will explain as I provide the code.I'm not expecting an answer, but I'm hoping that somebody could provide an explication on what I'm doing wrong and how a correct solution would work like.
I'm working on a CMS and trying to implement a MVC pattern, hence the use of PDOs.
Here is the section of my index.php file where we have the PDO declaration:
<?php
include_once 'models/USER_mapper.php';
$USER_mapper = new USER_mapper( 'localhost', 'root', 'root', 'online_magazine' );
$user = new User();
$user->setIDUser("JohnnyBoy");
$USER_mapper->registerUser($user);
?>
In the USER_mapper I have the connect function which is called on creation of a new USER_mapper and I also have the registerUser() function which takes a User object as a parameter and it should insert into the DB the info from the User object that was used.
Below is the registerUser() function:
public function registerUser($userOBJ) {
try {
$q = $this->DBH->prepare ( "INSERT INTO online_magazine.USER_TABLE (id_user, permission) VALUES (:id_user, :permission)" );
$q->execute ( ( array ) $userOBJ );
$this->DBH->commit ();
echo "it works";
} catch ( Exception $e ) {
echo "it doesn't work";
echo $e->getMessage ();
}
}
The table into which I am inserting has two columns: ID_USER and PERMISSION. Permission's has a default value, which is why I only provide the ID_USER with the setter function and leave the permission blank.
What I'm trying to achieve is to insert data into a table using a User object that has the right values and passing the User object to USER_mapper which will recuperate the info and put it in the respective table.
I hope I have been clear enough to highlight my problem. Let me know if I should add more detail and where.
EDIT1: I forgot to mention that when I use the method above I get a php error that looks like this:
[22-Nov-2013 03:18:08 Europe/Berlin] PHP Fatal error: Uncaught exception 'PDOException' with message 'There is no active transaction' in directory
EDIT2: I found out how to do it using bindParam() as follows:
$id_user = $userObject->getIDUser ();
$this->DBH->beginTransaction ();
$stmt = $this->DBH->prepare ( "INSERT INTO online_magazine.USER_TABLE (id_user) VALUES (:id_user)" );
$stmt->bindParam ( ':id_user', $id_user, PDO::PARAM_STR );
$stmt->execute ();
$this->DBH->commit ();
Thank you all!!
Related
In my class 'uzytkownikclass.php' i have a variable which is called '$handler'. That variable store connection with my MySQL database. Before, i created few methods that query database for data. Those functions are working fine. But i created a new method called 'hasRole' which check user role (Administator, moderator etc). But i have a error, PDO is new for me and i can not fix this alone.
Here is my code:
public function hasRole()
{
$email=$_SESSION['email_session'];
$stmt = $this->handler->prepare("SELECT COUNT(*) FROM users INNER JOIN rolausera ON users.id = idusera INNER JOIN rola ON idroli = rola.id WHERE email = :email AND rola.id = :rola");
$stmt->bindValue(':email',$email, PDO::PARAM_STR);
$stmt->bindValue(':rola',$rola, PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchAll();
if($result[0]>0)
{
return TRUE;
}
else
{
return FALSE;
}
}
Here is an error:
Fatal error: Call to a member function prepare() on null in D:\Programy\XAMPP\htdocs\logic\uzytkownikclass.php on line 120
As i said before, i have working methods:
$stmt = $this->handler->prepare("SELECT id, login, email, haslo FROM users WHERE email=:email1 ");
$stmt->execute(array(':email1'=>$email1));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
and here is my connection method:
public $handler;
public function connection()
{
$this->handler = new PDO('mysql:host=localhost;dbname=blog', 'root', '',array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
if($this->handler==false)
{
echo 'Blad';
}
}
I tried to delete relation in query and use simple 'SELECT * FROM user' and i had same error.
Greetings.
The question is: did you call the connection() method before calling the hasRole(), or perhaps you closed the connection somewhere in your code? Anyway, I would check in all methods, that try to query the database, if the connection is established and call the connection() method if not. Php's is_null() function helps determining if a variable has been set. I would also check if $handle is false.
i think it's a problem with PHP 5.6 [Beta].
Check your active PHP version, if you have PHP 5.6 [Beta], change to 5.4.
I haved the same problem, a class for connection with PDO working fine, and without changes into the code, this error: Fatal error: Call to a member function prepare() on null in...
For experience, when i have these errors, i see into my PHP version. On my case the hosting changes the PHP version without advise :(
See: PHP bugs
I have been developing a wrapper class inside a small PHP framework and I am experiencing something weird with one of the method in my class.
First here is the class code :
<?php
namespace Framework;
header('Content-Type: text/html; charset=UTF-8');
class cConnexion
{
public $m_log;//This will be instantiate as a cLog object (another class in the namespace)
private $m_DB;//PDO instance
private $m_Host;//Host of the conneciton string
private $m_DBName;//Name of the DB to connecte to
private $m_Driver;//Driver name, mysql for MySQL, sqlsrv for MSSQL
private $m_Login;//Username for authentification
private $m_Password;//Password for authentification
public function __construct($p_Driver = "mysql", $p_host, $p_DBName, $p_login, $p_password)
{
$this->m_Host= $p_host;
$this->m_Driver = $p_Driver;
$this->m_DBName = $p_DBName;
$this->m_Login = $p_login;
$this->m_Password = $p_password;
$this->m_log = new cLog('', '', true, false, false);
}
public function SecureExecute($p_query, $p_param)
{
try
{
$stmt = $this->m_DB->prepare($p_query);
$status = $stmt->execute($p_param);
$this->m_log->setMessageFR("Aucune exception ne s'est levé. ");
$this->m_log->setMessageEN("No exceptions were raised. ");
$this->m_log->setSuccess($status);
return $status;
}
catch(\PDOException $e)
{
$this->m_log->setMessageFR("Une exception de type PDO est levé. ".$e->getMessage());
$this->m_log->setMessageEN("A PDO exception was raised. ".$e->getMessage());
$this->m_log->setSuccess(false);
return false;
}
}
}
?>
Note that I have remove every other method that are not relevant to the question but kept the constructor and all the properties. Also note that there is a method to connect the $m_DB property to the DB, you might want to assume it has already been called.
Here is the problem I need help solving:
Step by Step description of what is going on:
I create an instance of cConnexion and use the connecteToDB method that isn't described in here but it is working properly because I can use another method to do MySQL 'SELECT' statement.
I tried to UPDATE a row which doesn't exist in a MySQL table but the object still tell me that the UPDATE was successful.
Is that normal? I read the PDO::PDOStatement::execute Doc and is says that the return value of PDO::PDOStatement::execute is either true (on success) or false(if fails).
Here is an exemple of code using the method:
$sql = "UPDATE Employes SET CieNo = 3, Nom = :Name, Dept = :Department WHERE EmplCode = :Code";
$params = array
(
'Code'=>$EmplCode,// = 123
'Name'=>($lname." ".$fname),// = Lalonde Sebastien
'Department'=>$dep,// = INFO
);
$cn = new cConnexion(/*Connection string and params here*/);
$cn->connectToDB();
if($cn->SecureExecute($sql, $params))
{
echo "SQL1: true";
}
The following code always output "SQL1: true" even when the UPDATE shouldn't had work...(because the Employes table doesn't contains an EmplCode = 123).
Can someone suggest a way to change my class so that the method SecureExecute() return false when this happen?
The execute method returns true on success, which in your case is true: The mysql query was executed successfully, however no rows were effected.
If you need to check whether the update actually altered anything, you need to use "rowCount":
$stmt = $this->m_DB->prepare('Update ...');
$stmt->execute();
$effected = $stmt->rowCount();
You can then decide if you want to return a true/false value from your method.
http://www.php.net/manual/en/pdostatement.rowcount.php
You'll only receive an error if the SQL command itself is in error. So if Employes is a valid table, and CieNo, Nom, Dept, and EmplCode are all valid columns, then your SQL statement is valid, even though it doesn't always find a row to UPDATE. Technically, it was "successful", just not in the way you're wanting.
Take a look at rowCount()
for info on how to determine whether 0 or more rows were affected by your query.
In fact, this whole class appears to be utterly useless. Exactly the same outcome can be achieved with raw PDO, with very small addition.
$cn = new PDO(/*Connection string and params here*/);
$cn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $cn->prepare($sql);
$stmt->execute($params);
I am using CakePHP 2.4.1 and I need to get direct access to PDO in order to pull a set of records from my MySQL DB, row by row.
This is the piece of code that I am using and that is generating the issue:
// Get PDO access
$this->_pdo = $this->Event->getDataSource();
try {
// Start transaction
$this->_pdo->begin();
// All the past events
$stm = $this->_pdo->prepare("SELECT `id` FROM `events` WHERE `stop_time` < '" . date('Y-m-d H:i:s') . "'");
// Loop through the events
if( $stm->execute() ) {
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
// ....
}
}
// Commit transaction
$this->_pdo->commit();
} catch (Exception $e) {
// Rollback transaction
$this->_pdo->rollback();
CakeLog::write('error', $e );
}
However as soon as I launch the script I get back this error message
PHP Fatal error: Call to undefined method Mysql::prepare()
but I have seen that this framework is supporting PDO and in particular the prepare() function.
CakePHP PDO Documentation
Any ideas?
Thanks a lot
Actually the class you are using is http://api.cakephp.org/2.4/class-DataSource.html
No prepare() method there. Use this to get PDO
$myPDO = $this->SomeModel->getDataSource()->getConnection();
Hi im using PDO to update some fields of a MySQL database. I've written a class called "bakeIT" which connects to a DB and updates some fields depending on the parameters of the method simple_update().
Somehow the first instantiation call to BakeIT()->simple_update() is working but not the second one? Why is that? I'm getting really crazy on that...
Edit:
I found out some errors:
string(85) "SQLSTATE[28000] [1045] Access denied for user
'ODBC'#'localhost' (using password: NO)" Fatal error: Call to a member
function prepare() on a non-object in
BakeIT.php
The table looks like the following:
class BakeIT {
function simple_update(
$tablename,
$fieldname,
$value,
$id,
$idname,
$token,
$tokenvalue){
$conn=$this->connect_db();
$sql= "UPDATE $tablename SET $fieldname=? WHERE $idname=? AND $token=?";
$q = $conn->prepare($sql);
$q->execute(array($value,$id,$tokenvalue));
$conn = null;}
}
//This as the first query works!
$saveanchor = new BakeIT();
$saveanchor->simple_update('navigation','anchor','whoo',5,'idnavigation','hash','3234');
//This as the second query not!
$savetitle = new BakeIT();
$savetitle->simple_update('navigation','linkname','kawoom',5,'idnavigation','hash','3234');
The field linkname doesn't exists.
To my comment about the security: So far I know the prepred statemend prevents an attacker to inject any bad values into the field content.
function example($value, $primarykey, $condition) {
$q = $conn->prepare("UPDATE table SET somefield=? WHERE $primarykey=?");
$q->execute(array($value,$condition));
}
It is not possible to manipulate the parameters $value and $condition but you can set $tableid to 1=1 -- which would override your compleate table.
E.g. example(12, 34, "1=1 --");that would execute this here:
UPDATE table SET somefield=12 WHERE 1=1 --=34
okay i got it! It's the require_once for the external db-access data. with only "require" the data.php (script with db-access variables) everything works fine...
Thanks for helping though!
I'm using an Articles class to pull data off my DB about ..articles. I can use instances to insert data, modify it but I can't seem to use it from a different set of pages.
Folder structure looks like this
/cms/conf.php (with proven to work define("DB_DSN" [..] etc)
/cms/classes/Article.php
/about.php
in about.php I want to pull out data off my DB using a static function in my Article class:
public static function getById($id) {
$conn = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
$sql = "SELECT * FROM articles WHERE id = :id";
$st = $conn->prepare($sql);
$st->bindValue(":id", $id, PDO::PARAM_INT);
$st->execute();
$row = $st->fetch();
$conn = null;
if ($row) return new Article($row);
}
I call it like this:
echo Article::getById(17)->content;
To get a Fatal error: Uncaught exception 'PDOException' with message 'invalid data source name' [...] PDO->__construct('DB_DSN', 'DB_USERNAME', 'DB_PASSWORD') #1
However I can use the same method and the same method call syntax in my toy file /cms/dataentry.php without problems (from either command line or web browser).
I'm making wrong environment assumptions I suppose? apps.php does have include 'cms/classes/Article.php';
PHP version 5.3.2
DB_DSN looks like it isn't defined when you try to create a new PDO instance.
PHP automatically quotes undefined constants, which is why you're getting this in your error:
PDO->__construct('DB_DSN', 'DB_USERNAME', 'DB_PASSWORD')
You'll probably want to require_once the file that defines these constants wherever you need them