Here is the code for the class:
class Delete_Category extends Category {
private $idchain = array();
public function __construct($id) {
parent::__construct();
$this->check_id($id);
$this->get_delete_ids($this->id);
$this->delete_category($this->idchain);
}
// Get all the Children IDs from the DB and store them in the array
private function get_delete_ids($id) {
$this->query = $this->db->prepare("SELECT id FROM `shop_categories` WHERE parent_id = :id");
$this->query->execute(array("id" => $id));
while($result = $this->query->fetch(PDO::FETCH_ASSOC)) {
$this->get_delete_ids($result['id']);
}
$this->idchain[]= $id;
}
// Implode the array into an id string and throw it in the query
private function delete_category($id_array) {
$id = implode(",",$id_array);
try {
$this->query = $this->db->prepare("DELETE FROM `shop_categories` WHERE id IN (:id)");
$this->query->execute(array(':id' => $id));
}
catch(PDOException $e) {
// log it{
}
}
}
The thing is that this always ends up with only the last ID being deleted. The query seems to be working however because it looks totaly fine if i echo it and replace :id with $id.
// SQL output string if echoed:
DELETE FROM `shop_categories` WHERE id IN (11,6)
// If i manually add this to the Database it works as intended so the problem has to be somewhere at the PDO statement... Can anyone help me?
You can use FIND_IN_SET for that:
DELETE FROM `shop_categories` WHERE FIND_IN_SET(id, :id)"
Related
I am working to create a content class which will pull all content from the database via a PDO, then run the results through a method which will convert the results into objects, and the loop through the objects, and echo the object to a specific module of the webpage.
What is expected
When the class is activated, there will be an instance created via a PDO that will retrieve the needed data from the mysql database. Then this information will echo out and display on the webpage.
What is happening
I end up with no errors and the boolean number "1" where content should be. At first I thought this was an sql error. I get the same result "1" if I use print_r($query_result). See my tests below.
My class code is below
<?php
class Content {
// --- START OF ACTIVE RECORD CODE ---
public $n_id;
public $n_name;
public $n_text;
public $n_photo;
// Instantiating a STATIC Database Connection for the class to use
static protected $dbconnect;
static public function database($dbconnect) {
self::$dbconnect = $dbconnect;
}
// constructing arguments
public function __construct($args=[]) {
$this->n_id = $args['n_id'] ?? '';
$this->n_name = $args['n_name'] ?? '';
$this->n_text = $args['n_text'] ?? '';
$this->n_photo = $args['n_photo'] ?? '';
}
// Multi use method to pass in sql that will execute the PDO only two parameters are bound ID and contentText.
static public function find_by_sql($sql) {
// -------------BEGIN PDO-----------
// preparing PDO by loading sql, calling db connection, and storing in variable $stmt
$stmt = self::$dbconnect->prepare($sql);
// Binding Parameters for sql
$stmt->bindParam(':nid', $n_id, PDO::PARAM_INT);
$stmt->bindParam(':nall', $n_name, PDO::PARAM_STR);
$stmt->bindParam(':ntext', $n_text, PDO::PARAM_STR);
$stmt->bindParam(':nphoto', $n_photo, PDO::PARAM_INT);
// executing $stmt PDO and storing the result in $stmt
$query_result = $stmt->execute();
return $query_result;
// clearing the PDO after information is stored in $record
$stmt->closeCursor();
// ------------END PDO ----------
// Checking to see if a result exist. If nop result is stored in $stmt, then it will echo "Database query failed."
if(!$query_result) {
exit("Query doesn't exist.");
}
// -------- BEGIN TURNING RESULTS INTO OBJECTS --------
$object_array = [];
// The result $stmt will be stored in the variable $record
while($record = $query_result->fetchAll()) {
// Taking $record and passing it to the static method instantiate() - see below. This method will return the $object_array.
$object_array[] = self::instantiate($record);
}
return $object_array;
// ------------ END TURNING RESULTS INTO OBJECTS --------
}
// method to test passing $sql to method find_all_sql();
static public function find_all(){
$sql = "SELECT * FROM nmain WHERE nid = :id AND nall = :nall AND ntext = :ntext AND nphoto = :nphoto";
return self::find_by_sql($sql);
}
// --- BEGIN INSTANTIATE METHOD TO CREATE OBJECTS ---
static protected function instantiate($record) {
$object = new self;
// Auto assign values
foreach($record as $property => $value) {
if(property_exists($object, $property)){
$object->$property = $value;
}
}
return $object;
}
// ----- END INSTANTIATE OF RECORD TO CREATE OBJECTS ---
// ---END OF ACTIVE RECORD CODE---
}
?>
**On my html webpage:**
$contents = Content::find_all();
foreach ((array) $contents as $content) {
echo $content;
}
What I have tested
This is the output I get when I run var_dump($stmt);
object(PDOStatement)#3 (1) { ["queryString"]=> string(119) "SELECT * FROM ndb WHERE id = :id AND nall = :nall AND ntext = :ntext AND nphoto = :nphoto" }
If I copy the query and paste it in myphpadmin the query will run binding the params.
This is the output if I run var_dump($query_result):
bool(true) if I use print_r($query_result) I get "1"
This passes my if(!$query_result) test
If I run var_dump($record) or var_dump($query_result) I get nothing. It seems as if $query_result, because it is a bool, has no array to pass to $record.Therefore, there is nothing to convert to an object.I am at a loss here. Is it my PDO binding?
Your fetch should be on the statement and not the result of the execute (which is just to say the execute has succeeded or failed), also fetchAll will attempt to return all records, what you most likely want is fetch to process 1 record at a time. So you should have something like...
while($record = $stmt->fetch()) {
You can now remove the earlier return which is stopping further processing.
Ok this should be fairly simple.
I have a table which contains content of 3 different textboxes the method inside my class should get the content to insert into textboxes.
Example TextBoxes (TextArea) where content should be entered.
My Method
public function LoadBoxes(){
$db = DB::getInstance();
$sql = "SELECT * FROM beta_letsgocontent";
$stmnt = $db->prepare($sql);
$stmnt->execute();
$boxes = $stmnt->fetchAll();
foreach ($boxes as $box) {
$data[] = array('Low' => $box['boxLow'],
'Medium' => $box['BoxMedium'],
'High' => $box['BoxHigh']);
}
return $data;
}//function
Here is my table (image below) so data / content from table should get inserted into the textboxes.
So when I do a test on content.php where I call the class method as such:
require_once('../classes/class.content.php');
$boxes = new Contents();
$boxes->LoadBoxes();
var_dump($boxes);
I get the following back:
Problem
As can be seen the array keys get returned however the data from database is not matched to array keys or returned by the method...I am stumped and have no idea what I am doing wrong here?
Any suggestions where I am going wrong? Could it be that I am not connecting to database correctly?
However if it was a database connection error I believe I would have received an error
Please keep in mind im a student and still learning.
UPDATE
Connection Schema
class Db {
private static $instance = NULL;
private function __construct() {}
private function __clone() {}
public static function getInstance() {
if (!isset(self::$instance)) {
$pdo_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
self::$instance = new PDO('mysql:host=localhost;dbname=beta', 'root', '', $pdo_options);
}
return self::$instance;
}
}
UPDATE 2
I just did the following on a test.php page which returned correct results.
require('connection.php');
function LoadBoxes(){
$db = DB::getInstance();
$sql = "SELECT * FROM beta_letsgocontent";
$stmnt = $db->prepare($sql);
$stmnt->execute();
$boxes = $stmnt->fetchAll();
foreach ($boxes as $box) {
$box[] = array('Low' => $box['BoxLow'],
'Medium' => $box['BoxMedium'],
'High' => $box['BoxHigh']);
}
return $box;
}//function
print_r(LoadBoxes());
?>
2 issues primary issues;
You're returning $data from the class but not populating a variable with the returned array.
You are var dumping the object itself.
This should work;
require_once('../classes/class.content.php');
$boxes = new Contents();
$data = $boxes->LoadBoxes();
var_dump($data);
Right now, I'd wrote a function in my model as:
public function getRowsByZipCode($zip)
{
// SQL to get all the rows with the given zip code
$stmt = $this -> getAdapter()
-> query( "SELECT *
FROM
table_name
WHERE
table_name.status = 1 AND
table_name.zip={$zip}");
$resultRows = $stmt->fetchAll();
// -------------------------------------------------------- //
// Convert result set to an array of objects
$resultObjects = array();
// If there is atleast one row found in DB
if(count($resultRows) > 0)
{
// Loop throguh all the rows in the resultset
foreach($resultRows as $resultRow) {
// Create table row and fill it with the details got from DB
$h = $this->createRow();
$h->setFromArray($resultRow);
// Add to the array
$resultObjects[] = $h;
}
}
return $resultObjects;
// -------------------------------------------------------- //
}
Which is working perfectly as I needed. And it is returning me an array that contains the tables row objects(App_Model_TableName Objects), which will be used later for further operations like save and delete etc.
What I really want is to remove the code that loop through the rows I got from the result set and converting each row to an object of App_Model_TableName that I'd wrote inside the comments // --- //.
Thanks in advance.
Firstly, I am assuming you are using PDO.
Try the following
class App_Model_TableName
{
public $status;
public $zip;
// public $other_column;
}
class YourClass
{
protected function getAdapter()
{
// Do adapter stuffs
}
public function query($query, array $param)
{
// When Using PDO always use prepare and execute when you pass in a variable
// This will help prevent SQL injection
$stmt = $this->getAdapter()->prepare($query);
return $query->execute($param);
}
/**
* #return App_Model_TableName[]
*/
public function getRowsByZipCode($zip)
{
// SQL to get all the rows with the given zip code
// This way will help prevent SQL injection
$query = "SELECT * FROM table_name WHERE table_name.status = 1 AND table_name.zip = :zip";
$qData = array(':zip' => $zip);
$results = $this->query($query, $qData);
return $results->fetchAll(PDO::FETCH_CLASS, 'App_Model_TableName');
}
}
Calling YourClass::getRowsByZipCode() will then return you an array of App_Model_TableName objects. You can then access them like:
$data = $instance_of_yourclass->getRowsByZipCode(12345);
foreach ($data as $row)
{
echo $row->zip;
echo $row->do_stuff();
}
All these awesome functions I found on:
http://php.net/manual/en/pdostatement.fetchall.php
http://php.net/manual/en/pdostatement.execute.php
Disclaimer: this code was not tested :(
Be cool but stay warm
Finally, I had found the solution:
public function getRowsByZipCode($zip)
{
// SQL to get all the rows with the given zip code
$stmt = $this -> getAdapter()
-> query( "SELECT *
FROM
table_name
WHERE
table_name.status = 1 AND
table_name.zip={$zip}");
$resultObjects= array();
while($data = $stmt->fetch())
{
$h = $this->createRow();
$h->setFromArray($data);
// Add to array
$resultObjects[] = $h;;
}
return $resultObjects;
}
I had removed the code that do the fetchAll() and loop through each row in the resultset. Now, I am taking each row from the resultset and creating an row of App_Model_TableName object using the data we got from the resultset.
Working perfectly for me.
I have two PHP scripts that I included below. Both of them attempt to do the same thing, but one works and one does not. I'm looking for someone to explain what PHP is doing under the covers. I'm new to PHP and I suspect that my Java experience is poisoning my thought process when I work in PHP.
What I'm attempting to do is functionally very simple -- Insert a question into a mySQL database table, retrieve the primary key of the inserted row, and then insert five answers into another table with a foreign key relationship to the question.
My original logic looked like this:
ManageQuestions.php:
<?php
session_start();
include('query.php');
echo "begin <br>";
if (isset($_POST['submit'])) {
echo "manageQuestion <br>";
$query = new Query;
$query->createTransaction();
$query->executeCreateUpdateDelete("INSERT INTO question (question) VALUES ('".$_POST['question']."'); ");
$question_pid = $query->getLastInsertedId();
$query->commitTransaction(); // Need to figure out how to do dirty reads so I can remove this.
echo $question_pid."<br>";
$result = $query->executeRead("SELECT question_pid FROM question where question_pid = '".$question_pid."';");
echo count($result)."<br>";
//if (count($result) === 1) {
$query->createTransaction(); // Need to figure out how to do dirty reads so I can remove this.
foreach($_POST['answer'] as $answer) {
$correctAnswers = 0;
$query->executeCreateUpdateDelete("INSERT INTO answer (question_fid, answer, isCorrect) VALUES ('".$question_pid."','".$answer['answer']."','".$answer['isCorrect']."')");
if ($answer['isCorrect'] === 1) {
$correctAnswers = $correctAnaswers + 1;
if ($correctAnswers > 1){
echo "Failed to insert answers";
$query->rollBackTransaction();
break;
}
}
}
echo "Success";
$query->commitTransaction();
/* } else {
echo "Failed to insert question";
$query->rollBackTransaction();
} */
}
?>
Query.php:
<?php
session_start();
class Query
{
private $host="<censored>";
private $username="<censored>";
private $password="<censored>";
private $db_name="<censored>";
private $pdo;
private $pdo_statement;
private $pdo_exception;
public function executeCreateUpdateDelete($pQuery)
{
$this->pdo_statement = $this->pdo->prepare($pQuery);
return $this->pdo_statement->execute();
}
public function executeRead($pQuery)
{
try
{
$dbh = new PDO("mysql:host=$this->host;dbname=$this->db_name", $this->username, $this->password);
$result = $dbh->query($pQuery);
$dbh = null;
return $result->fetchAll();
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
public function createTransaction()
{
$this->pdo = new PDO("mysql:host=$this->host;dbname=$this->db_name", $this->username, $this->password);
$this->pdo->beginTransaction();
}
public function commitTransaction()
{
$this->pdo->commit();
}
public function rollBackTransaction()
{
$this->pdo->rollBack();
}
public function getLastInsertedId()
{
$this->pdo->lastInsertId();
}
}
?>
When I rewrote my logic to not use a separate query class, I was able to do what I wanted to do. The only thing I've been able to find online about the life cycle of a PHP object is that it begins at the start of a script and ends at the end of a script. Does that imply that my query object is instantiated every time I call one of its methods and garbage collected when that particular method ends? Moving the logic out of that class and into the script caused my logic to work. This is what it looks like now:
ManageQuestions.php:
<?php
session_start();
include('query.php');
echo "Begin <br>";
if (isset($_POST['submit'])) {
echo "manageQuestion <br>";
$host="<censored>";
$username="<censored>";
$password="<censored>";
$db_name="<censored>";
$pdo = new PDO("mysql:host=$host;dbname=$db_name", $username, $password);
$stmt = $pdo->prepare("INSERT INTO question (question) VALUES ('".$_POST['question']."'); ");
$stmt->execute();
$question_pid = $pdo->lastInsertId();
echo $question_pid."<br>";
$stmt = $pdo->query("SELECT question_pid FROM question where question_pid = '".$question_pid."';");
$result = $stmt->fetchAll();
echo count($result)."<br>";
foreach($_POST['answer'] as $answer) {
$correctAnswers = 0;
$stmt = $pdo->prepare("INSERT INTO answer (question_fid, answer, isCorrect) VALUES ('".$question_pid."','".$answer['answer']."','".$answer['isCorrect']."')");
$stmt->execute();
}
echo "Success";
}
?>
Even though this fixed my issue, I don't understand why. If someone could explain that, I would be extremely grateful.
Cheers!
Does that imply that my query object is instantiated every time I call one of its methods and garbage collected when that particular method ends?
No. It's per request, not per method call. So the query object is instantiated every time the script is called and it gets unset (and not necessarily garbage collected) when the script ends.
However you could better manage the resource of the PDO object inside your Query class because you create a new instance (which would mean that it connects again to the database server which is not that cheap). So some lazy loading does not seem bad:
class Query
{
...
/** #var PDO */
private $pdo;
...
private function getPdo() {
if (!$this->pdo) {
$this->pdo = new PDO("mysql:host=$this->host;dbname=$this->db_name", $this->username, $this->password);
}
return $this->pdo;
}
public function executeRead($pQuery)
{
try {
$dbh = $this->getPdo();
$result = $dbh->query($pQuery);
return $result->fetchAll();
} catch (PDOException $e) {
echo $e->getMessage();
}
}
public function createTransaction()
{
$this->getPdo()->beginTransaction();
}
...
class Application_Model_DbTable_Email extends Zend_Db_Table_Abstract
{
protected $_name = 'memberdetail';
function getUserid($email)
{
$subquery = $this->select()
->from('memberdetail', array('memberid'))
->where('email = ?', $email);
$select = $this->select()
->from('usertable', array('userid'))
->join('memberdetail', 'usertable.userid = memberdetail.memberid')
->where('usertable.userid = ?', $subquery);
$row = $select->query()->fetch();
if (!$row) {
echo "User id not found";
} else {
return $userid = $row['userid'];
}
}
}
Hi, I am trying to return the userid from the above queries. However, the queries does not seemed to be executed as I always get refreshed whenever I call this function.
P.S this set of queries were given to me by another member.
it looks like this is being over thought. According to the info provided usertable.userid = memberdetail.memberid with this being the case your function is simple.
/** this function assumes one and only one email will match a memberid
* this function can be improved by validating $email as existing in DB
* prior to querying DB, should be done at form level but could be accomplished here
* with Zend_Validate_Db_RecordExists()
*/
public function getUserIdFromEmail($email) {
$select = $this->select();
$select->where('email = ?',$email);
$row = $this->fetchRow($select);//fetch a single row
if (!is_null($row) {//fetchRow returns null if no row matched
return $row->memeberid;//return memberid as string/integer = usertable.userid
} else {
//handle error
}
}
It would have been useful to tell people you are using Zend framework.
You need to establish a connection to the database for $this as described in steps 1 and 2 in this link:
http://framework.zend.com/manual/en/zend.db.select.html/
You can try this, if it helps:
function getUserid($email){
$select = $this->select()
->setIntegrityCheck(false)
->from(array('m' => 'memberdetail'), array('b.userid'))
->join(array('b' => 'usertable'), 'b.userid = m.memberid')
->where('m.email = ?', $email);
$row = $this->getAdapter()->fetchAll($select);
if (!$row) {
throw new Exception("User id not found");
} else {
return $row->toArray();
}
}