I want to output the fetched array onto the frontend. It works fine until the array returns as empty. It throws a PHP error that 'undefined variable $data on php line X'. I've looked for solutions though they have not fully suited what I have in mind. Please assist.
public function search($search) {
try {
$query = $this->connection->prepare ( "SELECT * FROM files WHERE number=$search ORDER BY id" );
$query->execute ();
while ( $row = $query->fetch ( PDO::FETCH_ASSOC ) ) {
$data [] = $row;
}
return $data;
} catch ( PDOException $e ) {
$e->getMessage ();
}
}
You are running your query wrong way.
The only proper way to add a variable into PDO query is to add it through a parameter. It is very important to understand that simply adding quotes around a variable is not enough and will eventually lead to innumerable problems, from syntax errors to SQL injections. On the other hand, due to the very nature of prepared statements, it's a bullet-proof solution that makes it impossible to introduce any problem through a data variable.
$this->connection->prepare ( "SELECT * FROM files WHERE number=? ORDER BY id" );
$query->execute ([$search]);
while to eliminate the error you should use the appropriate fetch mode. So the full code would be
public function search($search) {
$this->connection->prepare ( "SELECT * FROM files WHERE number=? ORDER BY id" );
$query->execute ([$search]);
return $query->fetchAll(PDO::FETCH_ASSOC);
}
note that you should never catch an error to report it
Related
When I dump the array just before the return statement all seems good.
However, when I dump the result it seems empty.
Should be more clear with the code included. I call GetRow from DatabaseHandler, I can see there is an array when I make a dump before the return. (see the var_dump)
public static function GetRow($sqlQuery, $params = null,
$fetchStyle = PDO::FETCH_ASSOC)
{
// Initialize the return value to null
$result = null;
// Try to execute an SQL query or a stored procedure
try
{
// Get the database handler
$database_handler = self::GetHandler();
// Prepare the query for execution
$statement_handler = $database_handler->prepare($sqlQuery);
// Execute the query
$statement_handler->execute($params);
// Fetch result
$result = $statement_handler->fetch($fetchStyle);
}
// Trigger an error if an exception was thrown when executing the SQL query
catch(PDOException $e)
{
// Close the database handler and trigger an error
self::Close();
trigger_error($e->getMessage(), E_USER_ERROR);
}
// Return the query results
exit(var_dump($result)); // SHOWS A PROPER ARRAY
return $result;
}
In the other function which calls it, there is nothing to be seen (false):
// Gets the details of a specific order
public static function GetOrderInfo($orderId)
{
// Build the SQL query
$sql = 'CALL orders_get_order_info(:order_id)';
// Build the parameters array
$params = array (':order_id' => $orderId);
// Execute the query and return the results
$result = DatabaseHandler::GetRow($sql, $params);
exit(var_dump($result)); // SHOWS FALSE
return $result
}
Don't call exit. There's nothing special about arrays in PHP in terms of arguments/return values - the problem is that you're terminating with the exit() call.
From the docs http://php.net/manual/en/function.exit.php:
Terminates execution of the script
In other words, the return statement is unreacheable. So your code never returns because the process exits before it.
While PDO returned an Array, it was unusable for functions like foreach, while, or json_encode (invalid argument).
The solutions was to use MySQLi, it returned exactly the same Array, only this time it was usable for functions like foreach, while, or json_encode.
I'm new to the world of OOP and PDO and just need a bit of a hand when returning data in one function and wanting to use that inside another function.
Below is my function to get all gecko data from my database, at the moment i have it printing out the array so i know it's working.
function getGecko:
public function getGecko($geckoName){
$dbh = $this->dbh;
try {
if (!$geckoName) {
throw new Exception("No gecko name set!");
}
$stmt = $dbh->query("SELECT * FROM geckos WHERE gecko_name = '$geckoName'");
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$row_count = $stmt->rowCount();
$row = $stmt->fetch();
if($row_count > 0){
print_r($row);
return true;
} else {
echo 'No information found for '.$geckoName.'!';
return false;
}
}
catch (Exception $e) {
echo $e->getMessage();
}
}
which outputs as - Array ( [gecko_id] => 1 [gecko_name] => Zilly [gecko_aquisition_date] => 0000-00-00 [gecko_type] => Normal [gecko_gender] => Male [gecko_traits] => [gecko_bio] => Hench bastard [gecko_health_check] => All good! [gecko_bred] => 0 [gecko_hatchling] => 0 [gecko_clutch] => [gecko_photo] => ) - no problem.
But i want to use that data inside a function called getMorph to utilise [gecko_type] => Normal. I have tried things like:
public function getMorph($geckoName){
$this->getGecko($geckoName);
echo $row['gecko_type'];
}
But it returns nothing at all. I am quite used to php in the procedural sense, i'm just trying to better myself and my code and wanted to get stuck into OOP. I do apologise if this is considered a 'noob' question but as i say, i am trying to learn.
Thank you for your time :)
The problem with your first function is that you're returning a boolean value. No actual data is returned. Also, in the getMorph() function, you're trying to use the $row variable. This won't work as the $row variable only exists inside the local scope of the function getGecko(). This would actually cause PHP to print an error message. Had you enabled error reporting, you'd have found this out.
To fix the issue, you can modify your first function to return the array:
if($row_count > 0){
// print_r($row);
return $row;
} else {
echo 'No information found for '.$geckoName.'!';
return false;
}
Then, in your second function, you can access the array like so:
public function getMorph($geckoName){
// $morph now contains the entire array
// returned by the other function
$row = $this->getGecko($geckoName);
// output the array contents
echo '<pre>' . print_r($row, TRUE), '</pre>';
// return the specific gecko_type value
return $row['gecko_type'];
}
I suggest you read up on variable scope. It's going to be very useful. Also, completely unrelated the issue above, you're directly inserting the user input in your SQL query. Don't do that! Use parameterized queries instead - that way, you'll be able to avoid SQL injection attacks.
The following questions has more details on the subject:
How can I prevent SQL injection in PHP?
How does PHP PDO's prepared statements prevent sql injection?
Your function getGecko returns only a Boolean and $row is only a local variable in that method. So you can either change the return value to return the actual data or you can create a private variable in your PHP Class.
For changing the return type, you could in getGecko change that return to something like this:
if($row_count > 0){
// ...
return $row;
}
And then in your getMorph function do something like:
public function getMorph($geckoName){
$row = $this->getGecko($geckoName);
echo $row['gecko_type'];
}
I have a pretty stupid question, but I can't get it to work immediately.
How do I load only one field of the result array of a query into a session (array) using a single PDO statement?
I commented the missing code below:
public function getPermissions($user_role_id){
if(!isset($user_role_id) || empty($user_role_id)){
$_SESSION['user']['user_permissions'] = '';
}else{
$db = Database::get_database();
$query = "
SELECT
rp.role_id, rp.permission_id
FROM
role_permission_tbl rp
WHERE
rp.role_id = :role_id";
$query_params = array(
':role_id' => $user_role_id
);
try
{
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch(PDOException $ex)
{
die("Failed to run query: " . $ex->getMessage());
}
$row = $stmt->fetchAll();
if($row){
//I only want to retrieve the field "permission_id"
$_SESSION['user']['user_permissions'] = $row;
}else{
$_SESSION['user']['user_permissions'] = '';
}
}
}
Thanks
After seeing your later comments, it looks as though you're wanting to save all permission data in a session variable so that you can look it up by permission ID:
$rows = $stmt->fetchAll();
foreach($rows as $row){
//Add to session, keyed by permission ID.
$_SESSION['user']['user_permissions'][$row['permission_id']] = $row;
}
//Then, if you want to see if said permission ID #21 exists:
if(isset($_SESSION['user']['user_permissions'][21])){
echo 'This user has permissions with ID 21!';
$permissionDetails = $_SESSION['user']['user_permissions'][21];
var_dump($permissionDetails);
}
Like any other "get it to work immediately" this question has contradicting conditions.
Like any other PHP code, it is ten times long than needed.
Like many other SO questions, it can be solved by quick manual lookup.
In case you need your permissions in array
public function getPermissions($user_role_id){
$sql = "SELECT permission_id FROM role_permission_tbl WHERE role_id = ?";
$stm = Database::get_database()->prepare($sql);
return $stm->execute(array($user_role_id))->fetchAll(PDO::FETCH_COLUMN);
}
note that assigning variables inside functions is a very bad practice. So, better call it this way
$_SESSION['user']['user_permissions'] = $user->getPermissions($user_role_id);
isset() is useless in conjunction with empty() as latter covers the former.
both isset() and empty() are useless for the function variable too, as it is always set by design
a verification for this particular input variable can be done, but for the sanely designed application it would be unnecessary.
setting a variable you are going to test with in_array() to an empty string will produce an error.
there is no use for the alias with single table.
PDO methods can be called dramatically shorter way, there is no use for stretching one simple query call to a whole screen of code.
echoing a system error message to a site user is an awful practice.
the very manual page for the fetchAll() contains an exact example for this very question of getting single column out of the query result.
there is no use for testing returned value explicitly, as it already contains either result or empty value (and luckily, fetchAll() will return even empty value of desired type).
Can you try $row = $stmt-> fetch(); instead of $row = $stmt->fetchAll(); if it is fetch only one record from table,
$row["permission_id"];
I try to get something like this from a MySQL-database via PHP and PDO query:
return array(
"Jungle Book" => new Book("Jungle Book", "R. Kipling", "A classic book."),
"Moonwalker" => new Book("Moonwalker", "J. Walker", ""),
"PHP for Dummies" => new Book("PHP for Dummies", "Some Smart Guy", "")
);
Each row of the database should be stored in an object.
Can anyone help me with this?
I tried this:
return array(
foreach ($dbh->query("SELECT * FROM books") as $row) {
$row['name'] => new Book($row['name'], $row['author'], $row['description']);
}
)
...but foreach isn't allowed in arrays...
Background: for learning purposes I'm following this tutorial: http://php-html.net/tutorials/model-view-controller-in-php/ and I'm trying now to replace the static list of books with code that is working with a real database.
This question has nothing to do with mvc or pdo actually, but rather with PHP syntax at all.
Your task is rather simple, only you need is to refrain from idea of having all the code in one single operator:
$data = array();
$stmt = $dbh->query("SELECT * FROM books");
foreach ($stmt->fetchAll() as $row) {
$data[$row['name']] = new Book($row['name'], $row['author'], $row['description']);
}
return $data;
Although PDO has a syntax sugar for you, in my opinion one have to learn the underlying basic statements first.
You can set the fetch type to FETCH_CLASS.
Creating and returning the array in a single statement is an artificial and needless requirement. I wouldn't do that, it makes one's code hard to debug, hard to test, and hard to maintain. Also the query() method may return false on error, so it will be a fatal error if you try to use it in a foreach statement.
$stmt = $dbh->query("SELECT * FROM books");
if ($stmt === false) { /* do something to handle the error */ }
$results = $stmt->fetchAll(PDO::FETCH_CLASS, 'Book');
return $results;
Or if you want a results array indexed by name:
$stmt = $dbh->query("SELECT * FROM books");
if ($stmt === false) { /* do something to handle the error */ }
$results = array();
while ($book = $stmt->fetch(PDO::FETCH_CLASS, 'Book')) {
$results[$book->name] = $book;
}
return $results;
You're probably wanting to return associative array values. In your current code, you cannot run a foreach while inside the array. But you can do this:
return $dbh->query("SELECT * FROM books")->fetchAll(PDO::FETCH_ASSOC);
I have the following code, not written bymyself, but I am wondering if you could spot anything wrong with it?
$query = "SELECT * from #__properties_type where published = 1 AND parent = ".$Category_id." OR parent = 0";
$db->setQuery( $query );
$types = $db->loadObjectList();
$nP = count($types);
$mitems[0]->id=0;
$mitems[0]->name='Type';
foreach ( $types as $item ) {
$mitems[] = $item;
}
It seems to work fine but sometimes I will see a random Warning: Invalid argument supplied for foreach() in etc/etc/etc/
Any ideas?
Your loadObjectList function seems to return a non-array sometimes, maybe when the SQL query fails.
Quick fix:
if (is_array($types))
foreach ( $types as $item ) {
$mitems[] = $item;
}
but you should look for the deeper cause why the function fails, and handle the error accordingly if there is one.
It probably means your $types variable isn't being set.
This will set a PHP warning off.
Unless $mitems[0] is predefined before your code snippet, there's no way PHP can know about $mitems[0] contains an object, hence $mitems[0]->id will throw an warning.
To solve this:
$mitems[0] = new YourObject();
$mitems[0]->id=0;
$mitems[0]->name='Type';