getting lastInsertId from PDO class - php

I'm using this class to connect to database. It works just fine, except I couldn't get the lastInsertId().
<?php
class connDB
{
public function connDB()
{
require_once( 'dbconfig/config.php' );
$this->confPDO = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_PERSISTENT => false,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES UTF8"
);
try
{
$this->dbc = new PDO( "mysql:host=$this->dbHost;dbname=$this->dbName",
$this->dbUser, $this->dbPass, $this->confPDO );
}
catch( PDOException $errMsg )
{
return false;
}
}
public function exec( $sql, array $params = array() )
{
try
{
$this->stmt = $this->dbc->prepare( $sql );
if ( count( $params ) > 0 )
{
foreach ( $params as $k=>$v )
{
$this->bind($k, $v);
}
}
return $this->stmt->execute();
}
catch( PDOException $errMsg )
{
$this->dbc = null;
return false;
}
}
public function bind( $param, $value, $type = null )
{
if ( is_null( $type ) )
{
switch ( true )
{
// Boolen parameter
case is_bool( $value ):
$type = PDO::PARAM_BOOL;
break;
// Integer parameter
case is_int( $value ):
$type = PDO::PARAM_INT;
break;
// Null parameter
case is_null( $value ):
$type = PDO::PARAM_NULL;
break;
// String parameter
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue( $param, $value, $type );
}
public function single()
{
return $this->stmt->fetch(PDO::FETCH_ASSOC);
}
public function resultset()
{
return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function rowCount()
{
return $this->stmt->rowCount();
}
}
Usage: [SELECT]
$sql = "SELECT * FROM < table >";
$db->exec($sql, $params);
$rows = $db->resultset();
foreach ($rows as $row)
{
echo $row['< column >'] . "\n";
}
Usage: [INSERT]
$sql = "INSERT INTO < table > (< column_1 >, < column_2 >, ... ) VALUES
(:valuename_1,
:valuename_2, ...)";
$params = array(':valuename_1' => 'value', ':valuename_2' => 'value', ...);
$db->exec($sql, $params);
I tried to do it this way:
include_once'classe.php';
$db = new connDB();
$sql = "INSERT INTO < table > (< column_1 >, < column_2 >, ... ) VALUES
(:valuename_1,
:valuename_2, ...)";
$params = array(':valuename_1' => 'value', ':valuename_2' => 'value', ...);
$db->exec($sql, $params);
$id = $db->lastInsertId();
I am getting an error:
Fatal error: Call to undefined method connDB::lastInsertId() in
I've tried adding a method into the class:
public function lastinsert()
{
// Return result
return $this->stmt->lastInsertId();
}
Then I called it like this this:
$db = new connDB();
$id = $db->lastinsert();
The error this time was
Fatal error: Call to undefined method PDOStatement::lastInsertId() in

There is no lastInsertId() method in your class.
You need to add it to the connDB class.
you need to call $dbc, not $stmt to get lastInsertId();
$this->dbc->lastInsertId();
as this function belongs to PDO class, not PDO statement class
Also, this piece of code may cause the problem
catch( PDOException $errMsg )
{
$this->dbc = null;
return false;
}
}
Make your exec() function this way
public function exec( $sql, array $params = array() )
{
$this->stmt = $this->dbc->prepare( $sql );
foreach ( $params as $k=>$v )
{
$this->bind($k, $v);
}
return $this->stmt->execute();
}

Using the same database class and was able to use lastInsertId like this:
$db = new connDB();
...
$_SESSION['users_id'] = $db->dbc->lastInsertId('id');

If you are using the model's save function:
$row->save();
You can use:
return $row->save();
which returns the id

Related

weird pdo sql update behaviour

I have a sql UPDATE query in PDO that should update a name and a permissions string.
But instead it just places the id of that row inside all columns.
Here is my code:
public function saveRole($roleID, $name, $permissions)
{
$sql = "UPDATE roles SET name = :name, permissions = :permissions WHERE id = :id";
//this one sets a string variable in the PDO wrapper class
PDO::setSQL($sql);
//this one sets an array inside the PDO wrapper class
PDO::setData([
'name' => $name,
'permissions' => $permissions,
'id' => $roleID,
]);
PDO::execute();
return PDO::getResponse(true);
}
As you see, I've written a wrapper for PDO, which looks like this:
static function execute($sql = null, $data = null, $fetchmode = \PDO::FETCH_OBJ)
{
//check if data and SQL are set in function call, if so, use function call params, if not use class params ($this->SQL & $this->data)
self::connect();
try
{
$stmnt = self::$con->prepare(self::$sql);
$stmnt->setFetchMode($fetchmode);
if (sizeof(self::$data) > 0)
{
foreach (self::$data as $key => $value)
{
$stmnt->bindParam(':' . $key, $value);
}
}
$stmnt->execute();
self::$stmnt = $stmnt;
self::$data = [];
self::$sql = '';
self::$lastResponse = new pdoReturn(true, $stmnt);
return;
} catch (\PDOException $exception)
{
self::$data = [];
self::$sql = '';
self::$lastResponse = new pdoReturn(false, $exception);
return;
}
}
function setSQL($sql) {
if (!is_string($sql))
return false;
if (strlen($sql) == 0)
return false;
$this->sql = $sql;
return true;
}
function setData($data) {
if (!is_array($data))
return false;
$this->data = $data;
return true;
}
As you see, I've written a wrapper for PDO
For the immediate fix, change
$stmnt = self::$con->prepare(self::$sql);
$stmnt->setFetchMode($fetchmode);
if (sizeof(self::$data) > 0)
{
foreach (self::$data as $key => $value)
{
$stmnt->bindParam(':' . $key, $value);
}
}
$stmnt->execute();
to
$stmnt = self::$con->prepare(self::$sql);
$stmnt->setFetchMode($fetchmode);
$stmnt->execute(self::$data);
Then read about your first database wrapper's childhood diseases and fix other issues such as statefulness and error reporting.

Updating MySQL tables throwing error

I never thought i would trip up on such an easy task, what i'm doing is getting rows from MySQL, and showing them on a form, the user can then update the values if needed:
<?php
include('includes/db_connection.php');
include('includes/sessions.php');
include('includes/functions.php');
include('includes/header.php');
include('includes/navbar-logged.php');
// AUTHENTICATION //
$row = DB::getInstance()->selectOneByField('membership', 'member_username', $member);
if ($row['member_user_class'] != 'Site Administrator') {
stderr("Sorry, <b>no authorization</b> to access this page.");
}
// AUTHENTICATION //
// CLOUD KEYS //
if (isset($_POST['submitCloudKeys']))
{
// TRY/CATCH //
try {
foreach ($_POST['cloudId'] as $val) {
DB::getInstance()->update(
'clouds',
'cloud_id',
$val,
[
'cloud_key' => $_POST['cloud_key'][$val]
]);
stdmsg('Cloud keys \'<b>'.$_POST['cloud_key'][$val].'</b>\' have been <b>updated</b>.');
}
} catch (Exception $e) {
stderr($e);
}
}
$rows = DB::getInstance()->select('SELECT * FROM `clouds`');
?>
<div class="panel panel-primary">
<div class="panel-heading">Current cloud hosts.</div>
<div class="panel-body">
<form action="clouds.php" method="post" class="form-horizontal container-fluid" role="form">
<?php $x = 0; ?>
<?php $z = 0; ?>
<?php foreach ($rows as $row) { ?>
<div class="row form-group">
<div class="col-sm-4 text-right"><label for="txtNetwork" class="control-label"><?php echo htmlspecialchars($row['cloud_name']) ?>:</div>
<div class="col-sm-8">
<input type="text" name="cloud_key[]" value="<?php echo htmlspecialchars($row['cloud_key']) ?>" size="30" class="form-control" />
<input type="hidden" name="cloudId[]" value="<?php echo $row['cloud_id']; ?>" />
</div>
</div>
<?php } ?>
<div class="row form-group">
<div class="col-sm-12 text-right">
<button type="submit" name="submitCloudKeys" class="btn btn-default">Update</button>
</div>
</div>
</form>
</div>
<div class="panel-footer">Update the <b>cloud hosts</b> keys.</div>
</div>
<?php
include('includes/footer.php');
I'm getting an error:
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'b447297ddb6be7377......................' in 'field list' in /home/admin/web/wraithpbns.com/public_html/includes/DB.php:268
Stack trace: #0 /home/admin/web/wraithpbns.com/public_html/includes/DB.php(268): PDOStatement->execute()
#1 /home/admin/web/wraithpbns.com/public_html/clouds.php(26): DB->update('clouds', 'cloud_id', '1', Array)
#2 {main}
The table names in MySQL are all correct, i don't see why i'm not able to update the form values, the "Unknown column" part is showing me the key value i'm trying to update, i have never had this issue before, any help would be appreciated guys!
UPDATED METHODS:
<?php
class DB
{
private static $instance;
public static function getInstance() {
if(is_null(self::$instance)) {
self::$instance = new DB();
}
return self::$instance;
}
public static function map(array $rows = array(), $keyColumn, $valueColumn = null) {
$result = array();
foreach($rows as $row) {
if(is_null($valueColumn)) {
$result[$row[$keyColumn]] = $row;
} else {
$result[$row[$keyColumn]] = $row[$valueColumn];
}
}
return $result;
}
private $pdo;
private function __construct() {
try {
$this->pdo = new PDO(
sprintf('%s:host=%s;dbname=%s',
DRIVER,
HOST,
DATA
),
USER,
PASS,
array(
PDO::ATTR_PERSISTENT => true,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8; SET CHARACTER SET utf8;'
)
);
} catch(Exception $ex) {
throw new Exception('Cannot connect to database.');
}
}
public function execute($query, array $params = []) {
$normParams = $this->normalizeParams($params);
$command = $this->pdo->prepare($query);
$command->closeCursor();
$status = $command->execute($normParams);
if(!$status) {
throw new Exception('DB::execute(): Can\'t execute query:');
}
return $status;
}
public function select($query, array $params = [], $fetchType = PDO::FETCH_ASSOC) {
$normParams = $this->normalizeParams($params);
$command = $this->pdo->prepare($query);
$command->closeCursor();
foreach($normParams as $paramName => $paramValue) {
if(is_array($paramValue)
&& isset($paramValue['type'])
&& isset($paramValue['value'])) {
$command->bindValue($paramName, $paramValue['value'], $paramValue['type']);
} else {
$command->bindValue($paramName, $paramValue);
}
}
if(!$command->execute()) {
throw new Exception('DB::select(): Can\'t execute query.');
}
return $command->fetchAll($fetchType);
}
public function selectValues($query, array $params = [], $fetchType = PDO::FETCH_ASSOC) {
$row = $this->selectOne($query, $params, $fetchType);
if(empty($row)) {
throw new Exception('DB::selectValues(): No values selected.');
} else {
return $row;
}
}
public function selectValue($query, array $params = []) {
$values = $this->selectValues($query, $params, PDO::FETCH_NUM);
return $values[0];
}
public function selectAll($tableName, $fetchType = PDO::FETCH_ASSOC) {
return $this->select(
sprintf('
SELECT *
FROM `%s`',
$tableName
),
[],
$fetchType
);
}
public function selectByField($tableName, $fieldName, $value, $fetchType = PDO::FETCH_ASSOC) {
return $this->select(
sprintf('
SELECT *
FROM `%s`
WHERE `%s` = :value',
$tableName,
$fieldName
),
[
':value' => $value
],
$fetchType
);
}
public function selectOne($query, array $params = [], $fetchType = PDO::FETCH_ASSOC) {
$rows = $this->select($query, $params, $fetchType);
return array_shift($rows);
}
public function selectOneByField($tableName, $fieldName, $value, $fetchType = PDO::FETCH_ASSOC) {
$rows = $this->selectByField($tableName, $fieldName, $value, $fetchType);
return array_shift($rows);
}
public function get($tableName, $fieldName, $value, $fetchType = PDO::FETCH_ASSOC) {
return $this->selectOneByField($tableName, $fieldName, $value, $fetchType);
}
public function insert($tableName, array $fields) {
$normParams = $this->normalizeParams($fields);
$paramNames = implode(', ', array_keys($normParams));
$fieldNames = '`' . implode('`, `', array_keys($fields)) . '`';
$command = $this->pdo->prepare(
sprintf('
INSERT INTO `%s` (%s)
VALUES (%s)',
$tableName,
$fieldNames,
$paramNames
)
);
$command->closeCursor();
if(!$command->execute($normParams)) {
throw new Exception('DB::insert(): Can\'t execute query.');
}
return $this->pdo->lastInsertId();
}
public function bulkInsert($tableName, array $rows = []) {
if(empty($rows)) {
return;
}
$fieldNames = array_keys($this->normalizeParams($rows[0]));
$normParams = [];
$paramNames = '';
$counter = 0;
foreach($rows as $row) {
$paramNames .= ((0 < $counter)? ',': '') . '(';
$nextParamNames = [];
foreach($row as $paramKey => $paramValue) {
$nextParamNames[] = ':' . $paramKey . $counter;
$normParams[':' . $paramKey . $counter] = $paramValue;
}
$paramNames .= implode(',', $nextParamNames);
$paramNames .= ')';
$counter++;
}
$command = $this->pdo->prepare(
sprintf('
INSERT INTO `%s` %s
VALUES %s',
$tableName,
$fieldNames,
$paramNames
)
);
$command->closeCursor();
if(!$command->execute($normParams)) {
throw new Exception('DB::bulkInsert(): Can\'t execute query.');
}
}
public function update($tableName, $fieldName, $fieldValue, array $updateFields, $updateAll = false) {
if(is_null($fieldName)) {
if(!$updateAll) {
throw new SystemException('Attempt to update all table records without confirmation.');
}
$sqlWhere = '';
} else {
$sqlWhere = sprintf('WHERE `%s` = %s', $fieldName, $fieldValue);
}
// echo $sqlWhere;
//
// exit;
$normUpdateFields = $this->normalizeParams($updateFields);
$sqlSetRows = [];
foreach($updateFields as $updateFieldName => $updateFieldValue) {
$sqlSetRows[] = sprintf('`%s` = %s', $updateFieldName, $updateFieldValue);
}
$sqlSet = implode(', ', $sqlSetRows);
$command = $this->pdo->prepare(
$sql = sprintf('
UPDATE `%s`
SET %s
%s',
$tableName,
$sqlSet,
$sqlWhere
)
);
$command->closeCursor();
foreach($normUpdateFields as $updateFieldName => $updateFieldValue) {
if(is_array($updateFieldValue)
&& isset($updateFieldValue['type'])
&& isset($updateFieldValue['value'])) {
$command->bindValue($updateFieldName, $updateFieldValue['value'], $updateFieldValue['type']);
} else {
$command->bindValue($updateFieldName, $updateFieldValue);
}
}
if(!empty($sqlWhere)) {
$command->bindValue(':' . $fieldName, $fieldValue);
}
if(!$command->execute()) {
throw new Exception('DB::update(): Can\'t execute query.');
}
}
public function remove($tableName, $fieldName = null, $value = null, $removeAll = false) {
$isExecuted = false;
if(is_null($fieldName)
&& is_null($value)
&& $removeAll) {
$isExecuted = $this->execute(sprintf('DELETE FROM `%s`', $tableName));
} else if(!is_null($fieldName)
&& !is_null($value)) {
$isExecuted = $this->execute(
sprintf('
DELETE FROM `%s`
WHERE `%s` = :value',
$tableName,
$fieldName
),
[
':value' => $value
]
);
}
if(!$isExecuted) {
throw new Exception('DB::remove(): Can\'t execute query.');
}
}
protected function normalizeParams(array $params = []) {
$normParams = [];
foreach($params as $paramKey => $paramValue) {
$normParams[(strlen($paramKey) && (':' === $paramKey{0}))? $paramKey: ':' . $paramKey] = $paramValue;
}
return $normParams;
}
/**
* Replaces any parameter placeholders in a query with the value of that
* parameter. Useful for debugging. Assumes anonymous parameters from
* $params are are in the same order as specified in $query
*
* #param string $query The sql query with parameter placeholders
* #param array $params The array of substitution parameters
* #return string The interpolated query
*/
public function interpolateQuery($query, $params) {
$keys = array();
# build a regular expression for each parameter
foreach ($params as $key => $value) {
if (is_string($key)) {
$keys[] = '/:'.$key.'/';
} else {
$keys[] = '/[?]/';
}
}
$query = preg_replace($keys, $params, $query, 1, $count);
#trigger_error('replaced '.$count.' keys');
return $query;
}
}
You have an logic issue within your update method ,
first , you are assigning a value then you are trying to bind a value,
$sqlWhere = sprintf('WHERE `%s` = %s', $fieldName, $fieldValue);
// ^^ ^^^^^^^^^^^^
and the same for your set clause :
$sqlSetRows[] = sprintf('`%s` = %s', $updateFieldName, $updateFieldValue);
// ^^ ^^^^^^^^^^^^^^^^^^
then as I told, you are trying to bind those values again using bindValue whether in your where clause :
$command->bindValue(':' . $fieldName, $fieldValue);
or in your this loop :
foreach($normUpdateFields as $updateFieldName => $updateFieldValue) {
....
$command->bindValue($updateFieldName, $updateFieldValue);
to solve you have two ways :
1 ) fix this by passing the write keys as follows :
$sqlWhere = sprintf('WHERE `%s` = :%s', $fieldName, $fieldName);
and for your set clause :
$sqlSetRows[] = sprintf('`%s` = :%s', $updateFieldName, $updateFieldName);
2 ) directly inject those values and leave your bindValue method which is not preferable:
$sqlSetRows[] = sprintf('`%s`="%s"', $updateFieldName, $updateFieldValue);
and $sqlWhere = sprintf('WHERE%s="%s"', $fieldName, $fieldValue);

Do I need to Instantiate Php Database class for every query?

I have a php database class for managing all my database queries:
class DatabaseConnection()
{
private $link;
public $filter;
public function log_db_errors( $error, $query )
{
if( MY_DEBUG )
{
echo $message;
}
}
public function __construct()
{
global $connection;
mb_internal_encoding( 'UTF-8' );
mb_regex_encoding( 'UTF-8' );
$this->link = new mysqli( MY_HOST, MY_USER, MY_PASS, MY_DB );
$this->link->set_charset( "utf8" );
if( $this->link->connect_errno )
{
$this->log_db_errors( "Connect failed", $this->link->connect_error );
echo 'Server error. Please try again sometime. DB';
exit();
}
}
public function __destruct()
{
$this->disconnect();
}
public function filter( $data )
{
if( !is_array( $data ) )
{
$data = trim( htmlentities( $data ) );
$data = $this->link->real_escape_string( $data );
}
else
{
$data = array_map( array( 'DB', 'filter' ), $data );
}
return $data;
}
public function query( $query )
{
$full_query = $this->link->query( $query );
if( $this->link->error )
{
$this->log_db_errors( $this->link->error, $query );
$full_query->free();
return false;
}
else
{
$full_query->free();
return true;
}
}
public function my_table_exists_create( $table, $variables = array() ) {
$check = $this->link->query("SELECT * FROM '$table' LIMIT 1");
if( $check ) return true;
else {
if( empty( $variables ) ) {
return false;
exit;
}
$sql = "CREATE TABLE IF NOT EXISTS ". $table;
$fields = array();
$values = array();
foreach( $variables as $field ) {
$fields[] = $field; //$values[] = "'".$value."'";
}
$fields = ' (' . implode(', ', $fields) . ')';
$sql .= $fields;
$query = $this->link->query( $sql );
if( $this->link->error ) {
$this->log_db_errors( $this->link->error, $sql );
return false;
}
else return true;
}
}
public function my_num_rows( $query )
{
$num_rows = $this->link->query( $query );
if( $this->link->error )
{
$this->log_db_errors( $this->link->error, $query );
return $this->link->error;
}
else
{
return $num_rows->num_rows;
}
}
public function exists( $table = '', $check_val = '', $params = array() )
{
if( empty($table) || empty($check_val) || empty($params) )
{
return false;
exit;
}
$check = array();
foreach( $params as $field => $value )
{
if( !empty( $field ) && !empty( $value ) )
{
if( $this->db_common( $value ) )
{
$check[] = "$field = $value";
}
else
{
$check[] = "$field = '$value'";
}
}
}
$check = implode(' AND ', $check);
$rs_check = "SELECT $check_val FROM ".$table." WHERE $check";
$number = $this->my_num_rows( $rs_check );
if( $number === 0 )
{
return false;
}
else
{
return true;
}
exit;
}
public function disconnect()
{
$this->link->close();
}
}
I use this class to manage all my queries, like insert to the database :
$database = new DatabaseConnection();
$Item_Details = array(
'item_title' => trim($_POST['title']),
'item_content' => trim($_POST['content']),
'item_updated' => date('Y-m-d H:i:s'),
'item_updatedby' => $my_loginid,
);
$where_clause = array('itemid' => $itemid);
$updated = $database->as_update( 'my_item', $Item_Details , $where_clause, 1 );
Now I need to know I can use this class without having a lot of connections that can slow down connection to the server which leads to timeout and having too many connection. I thought I could use a global variable
function my_constant_initialize()
{
global $databasecon;
$databasecon = new DatabaseConnection();
return $databasecon;
}
So please advice how to avoid too many connections. Also as well as tell whether it is necessary to instanciate the database class for every query or I can just call it once because I have used a lot of Include and require functions in my php code.
Reaching the MySQL database connection limit is hard in OOP PHP because it destructs the connection object if the script is finished. Just to be safe, have a destruct function in your class and unset the object at the end of the script. If you are really worried about reaching the connection cap you can go into MySQL and modify the max_connection_limit from I think 1000 to higher and increase the buffer pool.
Additionally you might look into switching languages to like Java which has a technique called "connection pooling." Works better than PHP's version. No this is not the same as p_connect or whatever it is in PHP.
At least you don't have to initiate the connection every time you are calling your class.
To see how you could use your database class without having to instantiate it every time, we would need to see some more of your code. The already mentioned singleton pattern is the way to go, but it is hard to judge if it would really improve your code without knowing how you are actually programming.
This shows an implementation of your class as singleton:
class DatabaseConnection {
protected static $instance = null;
private $link;
public $filter;
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new self;
}
return self::$instance;
}
protected function __construct() {
global $connection;
mb_internal_encoding( 'UTF-8' );
mb_regex_encoding( 'UTF-8' );
$this->link = new mysqli( MY_HOST, MY_USER, MY_PASS, MY_DB );
$this->link->set_charset( "utf8" );
if( $this->link->connect_errno )
{
$this->log_db_errors( "Connect failed", $this->link->connect_error );
echo 'Server error. Please try again sometime. DB';
exit();
}
}
protected function __clone() {
}
// add your other methods
}
You can call the connection by using
$databasecon = DatabaseConnection::getInstance();
By implementing it this way, when you call getInstance it checks if the connection has already been initialised so you can reuse it.
You set the __construct() as protected so the class can not be called without using the getInstance() method, same for __clone().

SQLite Prepared Statements not Inserting

I'm trying to insert into a database using PDO but after finishing the script and testing it out and I am not seeing any sort of input from inserting into the database, I've tried returning errors from PDO but nothing. I'm not sure what's happening
I've updated the parameter names and they do not seem to change anything with the result of the code. Seems the q() function is just having issues.
Database is initialized and looks like:
function __construct() {
if ( ! file_exists( dbpath . DB ) ) {
$this->db = true;
$this->open( dbpath . DB, SQLITE3_OPEN_CREATE|SQLITE3_OPEN_READWRITE ) or $this->db = false;
if ( $this->db == false ) {
return false;
}
$table = "CREATE TABLE link_hits( id INTEGER PRIMARY KEY AUTOINCREMENT, link TEXT NOT NULL, hits INT NOT NULL, date_added datetime default current_timestamp)";
$this->exec($table);
} else {
$this->db = true;
$this->open( dbpath . DB, SQLITE3_OPEN_CREATE|SQLITE3_OPEN_READWRITE ) or $this->db = false;
if ( $this->db == false ) {
return false;
}
}
}
Prepared statement function
function q ( $q, $v ) {
if ( $this->db ) {
$this->securedb = $this->prepare( $q );
foreach ( $v as $k=>$vv ) {
if ( is_numeric( $vv ) ) {
$this->securedb->bindValue($k, $vv, SQLITE3_INTEGER);
} else {
$this->securedb->bindValue($k, $vv, SQLITE3_TEXT);
}
}
$this->errorInfo = $this->errorInfo();
return ( ( $this->handle = $this->execute() ) == true ) ? $this->handle : false;
}
return false;
}
Add link function
function addlink ( $link ) {
if ( $this->linkexists( $link ) ) {
return false;
}
$this->que = "INSERT INTO link_hits (link, hits) VALUES (:link, :hits)";
$this->input = array(
':link' => $link,
':hits' => 0
);
return ( $this->q( $this->que, $this->input ) ) ? true : false;
}
Am I not forming my statement correctly? I followed several tutorials. I'm really used to MySQL but will not have access to it where this will be. :(
Even my linkexists function throws a false. And yes, the link is there, I forced it in with a normal query.
function linkexists( $link ) {
$this->que = "SELECT link FROM link_hits WHERE type='table' AND link=':link'";
$this->input = array(
':link' => $link
);
return ( ( $this->handle = $this->q( $this->que, $this->input ) ) == true ) ? true : false;
}
Parameter names must not end with a semicolon:
$this->que = "INSERT ... VALUES (:link, :hits)";

PDOException in PHP, no error in MySQL [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
This is the Query that is being run:
SELECT `fleet_pilots`.`user_id` , `pilot_tracker`.`start_time` , `fleets`.`fleet_cta`
FROM `fleet_pilots`
LEFT JOIN `fleets` ON `fleets`.`fleet_id` = `fleet_pilots`.`fleet_id`
LEFT JOIN `pilot_tracker` ON `pilot_tracker`.`user_id` = `fleet_pilots`.`user_id`
AND `pilot_tracker`.`end_time` = '0000-00-00 00:00:00'
WHERE `fleet_pilots`.`fleet_id` = '26'
AND `fleet_pilots`.`user_approved` = '1'
When I run the query in mysql I have no issues and get the results as I expect.
The problem occurs when I use the results in php:
$sql = "SELECT `fleet_pilots`.`user_id`, `pilot_tracker`.`start_time`, `fleets`.`fleet_cta`
FROM `fleet_pilots`
LEFT JOIN `fleets` ON `fleets`.`fleet_id` = `fleet_pilots`.`fleet_id`
LEFT JOIN `pilot_tracker` ON `pilot_tracker`.`user_id` = `fleet_pilots`.`user_id` AND `pilot_tracker`.`end_time` = '0000-00-00 00:00:00'
WHERE `fleet_pilots`.`fleet_id` = :fleet_id AND `fleet_pilots`.`user_approved` = '1'";
$this->db->query($sql);
$args = array(
':fleet_id' => $this->input['fleet_id'],
);
$this->db->execute($args);
$fleet_users = array();
while ( $row = $this->db->fetch_row() )
{
$fleet_users[] = $row['user_id'];
if (isset($row['start_time']) && $row['fleet_cta'])
{
$sql = "UPDATE `pilots`
SET `user_total_points` = `user_total_points` + :user_total_points, `user_points` = `user_points` + :user_points
WHERE `user_id` = :user_id";
$this->db->query($sql);
$args = array(
':user_id' => $row['user_id'],
':user_points' => $this->conf->Config['point_per_min'] * ((strtotime('now') - strtotime($row['start_time']))/60),
':user_total_points' => $this->conf->Config['point_per_min'] * ((strtotime('now') - strtotime($row['start_time']))/60),
);
$this->db->execute($args);
}
}
I get this error message:
<br />
<b>Fatal error</b>: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error' in /usr/local/apache2/vhosts/trifectas.org/htdocs/fleetmaster/libs/database.class.php:109
Stack trace:
#0 /usr/local/apache2/vhosts/trifectas.org/htdocs/fleetmaster/libs/database.class.php(109): PDOStatement->fetch(2)
#1 /usr/local/apache2/vhosts/trifectas.org/htdocs/fleetmaster/libs/common.class.php(1170): Database->fetch_row()
#2 /usr/local/apache2/vhosts/trifectas.org/htdocs/fleetmaster/libs/common.class.php(1226): Common->submit_end_fleet()
#3 /usr/local/apache2/vhosts/trifectas.org/htdocs/fleetmaster/libs/common.class.php(225): Common->process_end_fleet()
#4 /usr/local/apache2/vhosts/trifectas.org/htdocs/fleetmaster/index.php(25): Common->__construct()
#5 {main}
thrown in <b>/usr/local/apache2/vhosts/trifectas.org/htdocs/fleetmaster/libs/database.class.php</b> on line <b>109</b><br />
Line 1170 is the while ( $row = $this->db->fetch_row() ) line.
Any help is appreciated.
EDIT: The following change fixed the problem for me.
$sql = "SELECT `fleet_pilots`.`user_id`, `pilot_tracker`.`start_time`, `fleets`.`fleet_cta`
FROM `fleet_pilots`
LEFT JOIN `fleets` ON `fleets`.`fleet_id` = `fleet_pilots`.`fleet_id`
LEFT JOIN `pilot_tracker` ON `pilot_tracker`.`user_id` = `fleet_pilots`.`user_id` AND `pilot_tracker`.`end_time` = '0000-00-00 00:00:00'
WHERE `fleet_pilots`.`fleet_id` = :fleet_id AND `fleet_pilots`.`user_approved` = '1'";
$this->db->query($sql);
$args = array(
':fleet_id' => $this->input['fleet_id'],
);
$this->db->execute($args);
$row = $this->db->fetch_array();
$fleet_users = $result = array();
foreach ( $row AS $key => $value )
{
$result[$key] = $value;
}
foreach ( $result AS $row )
{
$fleet_users[] = $row['user_id'];
if ( isset($row['start_time']) && $row['fleet_cta'] )
{
$sql = "UPDATE `pilots`
SET `user_total_points` = `user_total_points` + :user_total_points, `user_points` = `user_points` + :user_points
WHERE `user_id` = :user_id";
$this->db->query($sql);
$args = array(
':user_id' => $row['user_id'],
':user_points' => $this->conf->Config['point_per_min'] * ((strtotime('now') - strtotime($row['start_time']))/60),
':user_total_points' => $this->conf->Config['point_per_min'] * ((strtotime('now') - strtotime($row['start_time']))/60),
);
$this->db->execute($args);
}
}
This is my PDO wrapper.
<?php
defined('IN_APP') || die('Hands off!');
class Database
{
protected $connection;
protected $result;
protected $params;
protected $executed = false;
protected $_queryCounter = 0;
public function __construct($dsn, $username = null, $password = null, $driver_options = null)
{
try
{
$this->connection = new PDO($dsn, $username, $password, $driver_options);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e)
{
$this->get_error($e);
}
}
public function query($sql, $params = array())
{
$this->result = $this->connection->prepare($sql);
$this->params = is_array($params) ? $params : array($params);
$this->executed = false;
}
public function bind($pos, $value, $type = null)
{
if ( is_null($type) )
{
switch (true)
{
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->result->bindValue($pos, $value, $type);
}
public function bindParam($pos, $value, $type = null)
{
if ( is_null($type) )
{
switch (true)
{
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->result->bindParam($pos, $value, $type);
}
public function execute($vars = array())
{
$this->_queryCounter++;
$this->executed = true;
foreach ( $vars as $k => $v )
{
$this->bind($k, $v);
}
return $this->result->execute();
}
public function fetch_array($vars = array())
{
if ( !$this->executed )
{
$this->execute($vars);
}
return $this->result->fetchAll(PDO::FETCH_ASSOC);
}
public function fetch_row($vars = array())
{
if ( !$this->executed )
{
$this->execute($vars);
}
return $this->result->fetch(PDO::FETCH_ASSOC);
}
public function lastInsertId()
{
return $this->connection->lastInsertId();
}
public function rowCount($vars = array())
{
if ( !$this->executed )
{
$this->execute($vars);
}
return $this->result->rowCount();
}
public function beginTransaction()
{
$this->connection->beginTransaction();
}
public function commit()
{
$this->connection->commit();
}
public function queryCounter()
{
return $this->_queryCounter;
}
public function debugDumpParams()
{
return $this->result->debugDumpParams();
}
public function get_error($e)
{
$this->connection = null;
die($e->getMessage());
}
public function getConnection()
{
return $this->connection;
}
public function __destruct()
{
$this->connection = null;
}
}
PDO::fetchRow does not exist. Assuming your $this->db object is a PDO instance, this doesn't work. PDO::query returns a PDOStatement result object. You need to fetch rows from it, not from the PDO object. If this doesn't help, you need to show what your database class is doing.

Categories