Okay, so I have been using a PDO wrapper for a project I'm working on, and I'm trying to find out whether a DELETE query was successful or not. Here is the code I am using:
/**
* A pretty straight-forward query to delete a row from the verification
* table where user_id is $user_id and code is $code
*/
$result = $this->database->query("DELETE FROM verification " .
"WHERE user_id = %u AND code = %s",
$user_id,
$code);
/**
* This function will grab the PDO's exec() return, which should
* return the number of rows modified.
*/
if($this->database->getNumAffected($result) > 0)
return true;
else
return false;
The problem is, whether the DELETE query actually deletes a row or not, $this->database->getNumAffected($result) always returns '0'.
You can check out the wrapper, but basically $this->database->getNumAffected($result) simply returns exactly the same value PDO::exec() would return.
I tried this code without the wrapper (directly into PDO,) and I had the same problem but reverse: it always returned '1' (whether a row was deleted or not.)
Any help would be greatly appreciated.
EDIT: Based on this SO question, I'm doing everything right... I don't understand why this isn't working.
$query = $this->database->prepare("DELETE FROM verification WHERE user_id = :user_id AND code = :code", array('user_id' => $user_id, 'code' => $code));
$query->execute();
if ($query->rowCount() > 0) {
return TRUE;
}
return FALSE;
It doesn't work as you expect because the 'wrapper' that you're using doesn't ever use PDO::exec() - it wraps everything in a PDO statement. According to a quick read of the source code for version 2.2.6 of the 'database' class from the URL you provided, the 'query' method should return an array which contains the statement handle:
502 $statement = $this -> getDatabaseConnection () -> prepare ( $query );
...
587 $ret = array ( $statement, func_get_args (), $lastIndex );
588
589 return ( $ret );
So, assuming your $this->database->query() is calling this database class' query method, you should be able to do $result[0]->rowCount().
Note that your assertion to the earlier response that "the wrapper that [you are] using uses a different version of rowCount() because of an error that exists with the rowCount() function" is not true - the wrapper implements a numRows, but this is not the same thing as PDOStatement::rowCount(), which is intact inside of the statement handle returned from database::query().
Related
I am new in PHP as well as in Codeigniter.
public function test_table()
{
$q = $this->db
->where('id',$id)
->get('table_name');
return $q->row();
}
// test_table() is a function written to models in codeigniter .
Can anyone please share me in details Why we are used return statement to insert or retrieve data in database ?
From the php manual:
If called from within a function, the return statement immediately ends execution of the current function, and returns its argument as the value of the function call
http://php.net/manual/en/function.return.php
That means the "return" statement will return the data to the parent method who called it.
The behavior of DB operations will depend on the frameworks/libraries you are using.
From the codeigniter manual:
insert([$table = ''[, $set = NULL[, $escape = NULL]]])
RETURNS: TRUE on success, FALSE on failure
https://www.codeigniter.com/userguide3/database/query_builder.html
When selecting, the "return" statement will return the row from the database or "false" if not found.
I am currently in the process of updating my web application from PHP 5.6 to PHP 7, therefore I need to alter the database abstraction class that has been using the old MySQL-Extension.
The class has a method "Query()" where SQL statements are being prepared and executed and a method "Fetch()" which fetches a single row and returns it. See the simplified versions:
function Query($query='')
{
$result = $this->connection->Prepare($query);
$result->Execute();
return $result;
}
function Fetch($resource=null)
{
return $resource->Fetch(PDO::FETCH_ASSOC);
}
So basically what I am trying to do is this:
$statement = Query('SELECT * FROM Test');
$firstRow = Fetch($statement);
print_r($statement) shows me this:
PDOStatement Object
(
[queryString] => SELECT * FROM Test
)
But when I call "Fetch", there is no row returned. Can someone tell if it's possible to return PDOStatement objects and pass them into other functions/methods for "later use"?
PS: Of course I know that this is not best practice but I am trying to avoid having to alter thousands of lines of code in the application.
I am working in a legacy system that uses row() plus limit() to get one result. I didn't understand why, because row() already give me one result, but a coworker said that improves performance. Example:
$this->db
->select()
->select('extract(epoch from cadevolucao.dt_sistema) as data_sistema')
->select('extract(epoch from cadevolucao.dt_previsao_alta) as data_previsao')
->select('cadevolucao.cd_evolucao, cadevolucao.dt_sistema')
->join('contatnd', 'cadevolucao.num_atend = contatnd.num_atend')
->join('cadplanejamento', 'cadevolucao.cd_evolucao = cadplanejamento.cd_evolucao')
->where('contatnd.cd_pessoa', $cd_pessoa)
->where('tp_evolucao', -1)
->where('tipo', 1)
->order_by('cadevolucao.cd_evolucao','desc')
->limit(3)
->get('cadevolucao')
->row();
I looked for in the CI Documentation and Google, not founding anything useful about that.
Can someone explain if it's needed the limit() when using row() in Active Record's CI and why?
According to what i know row method returns a single result row. If your query has more than one row, it returns only the first row.But internally its still fetching all the rows fetched by the query and storing it in an array. Yes i think i must agree with your co-worker indeed limit will have a performance impact.
this is what row method does internally
/**
* Returns a single result row - object version
*
* #param int $n
* #return object
*/
public function row_object($n = 0)
{
$result = $this->result_object();
if (count($result) === 0)
{
return NULL;
}
if ($n !== $this->current_row && isset($result[$n]))
{
$this->current_row = $n;
}
return $result[$this->current_row];
}
as you its either returning the first element or the argument supplied i.e the row index.
row is actually an alias to this row_object
I am working on a very small PHP and MySQL application. I have a class called User for manipulating user data in the database which contains a createUser method as shown below:-
/**
* Creates a new user record in the users table for a new user
*
* #return void
*/
public function createUser($user_id, $user_name, $location_id) {
// query to execute
$query = "INSERT INTO
users(user_id,user_name,location_id)
VALUES(:id,:name,:location)";
// query parameters
$parameters = array (
':id' => $user_id,
':name' => $user_name,
':location' => $location_id
);
$databaseInteractions = new DatabaseInteractions();
$databaseInteractions->executeUpdate($this->_connection, $query, $parameters);
}
I have another class that will contain common methods for interacting with the database called DatabaseInteractions as shown in the above code. This class contains a method called executeUpdate for executing DML queries as shown below:-
/**
* A function for executing DML queries using a prepared statement
* #param $connection The database connection object
* #param $query The dml query to be executed
* #param $parameters The input parameters for the query as a hash
*/
public function executeUpdate($connection,$query, $parameters) {
if ($stmt = $connection->prepare($query)) {
//bind query parameters
foreach ($parameters as $key => $value) {
$stmt->bindParam($key, $value);
}
//begin transaction
$connection->beginTransaction();
$stmt->execute();
$stmt->closeCursor();
//commit transaction
$connection->commit();
}
}
When i call the createUser method in the User class as shown below,
$user->createUser(3,"NewUser",1);
The values inserted in the database are as follows:-
user_id user_name location_id
1 1 1
I spent some time debugging the code but still can't seem to find the reason why this is happening. user_id is the PK and is an int. user_name is varchar and location_id is FK and is int.
I am a Java developer and new to PHP so any inputs related to php naming conventions, coding standards, etc are always welcome.
Answer: reference semantics gotcha.
The second parameter of bindParam is passed by reference:
Binds a PHP variable to a corresponding named or question mark
placeholder in the SQL statement that was use to prepare the
statement. Unlike PDOStatement::bindValue(), the variable is bound as
a reference and will only be evaluated at the time that
PDOStatement::execute() is called.
Therefore, when the statement is executed all three parameters will evaluate to whatever the last value of $value was -- in this case, 1.
To solve the problem, use the optional parameter of execute instead of explicitly binding the parameters:
public function executeUpdate($connection,$query, $parameters) {
if ($stmt = $connection->prepare($query)) {
$connection->beginTransaction();
$stmt->execute($parameters);
$stmt->closeCursor();
//commit transaction
$connection->commit();
}
}
im using codeigniter 2.0.2 and this is from its userguide
$data = array(
'title' => $title,
'name' => $name,
'date' => $date
);
$this->db->where('id', $id);
$this->db->update('mytable', $data);
my question is once this executed how do you find its executed correctly or not?
The update function returns a value:
$result = $this->db->update('mytable', $data);
Check that value for either being TRUE (success) or FALSE (failure). update runs query internally and then returns the return value of query (Ref):
The query() function returns a database result object when "read" type queries are run, which you can use to show your results. When "write" type queries are run it simply returns TRUE or FALSE depending on success or failure.
Use
$this->db->affected_rows()
to see how many rows have been affected on write type queries (update, insert, etc...)
http://codeigniter.com/user_guide/database/helpers.html
Both answers was valid. You just have to use each one depending on the case. If you are just checking if the query was executed use this method:
$result = $this->db->update('mytable', $data);
if you really want the number of rows affected the second method is better:
$this->db->affected_rows()
however I always use the second method. The update query is a good example why. A query can be successful and still there was nothing updated on the database because the value that you were trying to update was actually equal to the value you are sending in the query.
This would be a false positive. And the affected rows would be 0.
I hope it helped =)
When developing CodeIgniter model methods, I find that I consistently return desirable values depending on the type of database write that is executed. It is often important to differentiate between a query that has run successfully versus a query that has actually changed a record.
For an update or delete query, I'll return the number of affected rows -- this will be most helpful to controller methods that call it. If you are performing logging (to keep track of change history), then ONLY log something if there is a change to the row; otherwise you are unnecessarily bloating your change history logs.
public function update(int $id, array $newData) :int
{
$oldData = $this->db->get_where('mytable', ['id' => $id])->row_array();
if ($this->db->update('mytable', $newData, ['id' => $id])) {
$affectedRows = $this->db->affected_rows();
if ($affectedRows) {
$this->Log->mytableUpdate($id, $newData, $oldData);
}
return $affectedRows;
}
return 0;
}
For insert queries, I always return the auto-incremented id of the newly inserted row via insert_id().
If using the PDO driver with PostgreSQL, or using the Interbase driver, this function requires a $name parameter, which specifies the appropriate sequence to check for the insert id.
public function insert(array $newData) :int
{
if ($this->db->insert('mytable', $newData)) {
$newId = $this->db->insert_id(); // or insert_id('mytable')
$this->Log->mytableInsert($newId, $newData);
return $newId;
}
return 0;
}
Having consistent return types in your model methods will make your project easier to develop and maintain. The script that calls these model methods will be able to quickly assess the outcome by making a "falsey" check.