I want to use a associative array (outcome of a PDO query) in a class, so that I can construct a DIV with some database content.
How to get the array inside the Class? In the while loop I want to make an object, in the Class of this object I want to construct the HTML.
while($data = $stmt->fetch( PDO::FETCH_ASSOC )){
$html = new class;
echo $html;
}
If you want your while loop to be able to work about like you've written it, you can write the constructor of the class so that it accepts the data as an argument, then implement the div output in the __toString method.
class HtmlDivFormatter {
private $data;
public function __construct($data) {
$this->data = $data;
}
public function __toString() {
return '<div>' . $this->data['column_name'] . '</div>';
// whatever HTML you have in mind
}
}
while ($data = $stmt->fetch( PDO::FETCH_ASSOC )) {
$html = new HtmlDivFormatter($data);
echo $html;
}
see PDO::FETCH_CLASS or PDO::FETCH_INTO
more info here http://php.net/manual/en/pdostatement.fetch.php and this
PHP PDO fetching into objects
and some example code:
<?php
$sql = 'SELECT firstName, lastName FROM users';
$stmtA = $pdo->query($sql);
$stmtA->setFetchMode(PDO::FETCH_CLASS, 'Person');
$objA = $stmtA->fetch();
var_dump($objA);
//first create the object we will fetch into
$objC = new Person;
$objC->firstName = "firstName";
$objC->lastName = "lastName";
$stmtC = $pdo->query($sql);
$stmtC->setFetchMode(PDO::FETCH_INTO, $objC);
$objC = $stmtC->fetch(); // here objC will be updated
var_dump($objC);
class Person{
public $firstName;
public $lastName;
}
Related
I'm wanting to create a new instance of my Class and assign it's attributes the values that are returned. The reason for this is I'm creating a series of methods inheriting from the calling class, as opposed to using static methods which I already had working.
Example of what I'm using currently:
public static function findById($id) {
$id = self::escapeParam($id);
$idVal = is_int($id) ? "i" : "s";
$sql = "SELECT * FROM ".static::$db_table." WHERE id = ? LIMIT 1";
return static::findByQuery($sql,$idVal,$id);
}
public static function findByQuery($sql,$bindChar = '',$bindVal = '') {
try {
$callingClass = get_called_class();
$object = new $callingClass;
$statement = Database::$connection->prepare($sql);
if(!empty($bindChar)) :
$statement->bind_param($bindChar, $bindVal);
endif;
if($statement->execute()) :
$result = $statement->get_result();
$object = $result->fetch_object();
endif;
$statement->close();
if(!empty($object)) :
return $object;
endif;
} catch(Exception $e) {
}
}
What I tried was writing an instantiation method that creates a new instance of my class, and then assign each attribute of the object the value it returns from an array from a tutorial I did. However, the tutorial was fairly outdated and didn't use any new syntax or binding, so I was trying to rework this.
Example from the tutorial below:
public static function find_by_id($id) {
global $database;
$the_result_array = static::find_by_query("SELECT * FROM " . static::$db_table . " WHERE id = $id LIMIT 1");
return !empty($the_result_array) ? array_shift($the_result_array) : false;
}
public static function find_by_query($sql) {
global $database;
$result_set = $database->query($sql);
$the_object_array = array();
while($row = mysqli_fetch_array($result_set)) {
$the_object_array[] = static::instantation($row);
}
return $the_object_array;
}
public static function instantation($the_record){
$calling_class = get_called_class();
$the_object = new $calling_class;
foreach ($the_record as $the_attribute => $value) {
if($the_object->has_the_attribute($the_attribute)) {
$the_object->$the_attribute = $value;
}
}
return $the_object;
}
private function has_the_attribute($the_attribute) {
return property_exists($this, $the_attribute);
}
What I was trying to do from the tutorial, was to return my result as an array using a while, and then assigning a variable by passing the built array into the static::instantation() method, but it doesn't seem to ever be working correctly, as any public functions I create in my calling class (Admin for example) aren't called after as they don't exist due to the Class not being instantiated.
mysqli_result::fetch_object() accepts the class name as the first argument. You can pass the class name as an argument to that method and get the instance of the model. I am not sure why you have that much code but consider my example which I wrote based on your own code:
<?php
class Model
{
public static function findByQuery(string $sql, ?string $bindChar = null, ?string $bindVal = null): ?static
{
$statement = Database::$connection->prepare($sql);
if ($bindChar) :
$statement->bind_param($bindChar, $bindVal);
endif;
$statement->execute();
$result = $statement->get_result();
return $result->fetch_object(static::class);
}
}
class User extends Model
{
private $id;
}
class Database
{
public static mysqli $connection;
}
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
Database::$connection = new mysqli('localhost', 'user', 'password', 'test');
$user = User::findByQuery('SELECT ? as id', 's', 'Dharman');
var_dump($user);
The output from that example is:
object(User)#4 (1) {
["id":"User":private]=>
string(7) "Dharman"
}
As you can see, the code created an instance of the class using late-static binding and it also assigned the value to a private property, which you can't do otherwise.
P.S. My example is a little bit tidier. I added parameter typing and removed a lot of unnecessary code. In particular, I remove empty try-catch which is a terrible practice.
I have now got this working, although I feel this is probably not the best way of doing it.
I'm primarily front end so please comment if there are improvements or best practices.
public static function findByQuery($sql,$bindChar = '',$bindVal = '') {
try {
$statement = Database::$connection->prepare($sql);
if(!empty($bindChar)) :
$statement->bind_param("$bindChar", $bindVal);
endif;
if($statement->execute()) :
$result = $statement->get_result();
$output = $result->fetch_object();
endif;
$statement->close();
if(!empty($output)) :
$class = get_called_class();
$object = new $class;
foreach(get_object_vars($output) as $key => $value) :
$object->$key = $value;
endforeach;
endif;
if(!empty($object)) :
return $object;
endif;
} catch(Exception $e) {
}
}
My initial thoughts were declaring an object and then I thought that the PHP fetch_object call would have just assigned my object it's properties after initiating the Class but that wasn't the case.
So what I've done is that if the statement is successful and a results object is created, I then get the object properties and values with the get_object_vars() command, and then loop through these as a key value pair, assigning each attribute it's returned value.
I can confirm this works as I can now run $admin->remove() from my removal script, as opposed to what I was having to do before which was Admin::remove($id);
Hi i am using foreach in php oops to output data from the mysqlbut each data outputs twice please check my code and help it i have tried but no correct result
Here is the code below i have used
class getdata extends db{
public function getdata(){
$sql = "SELECT * FROM users";
$results = $this->connect()->query($sql);
$numrows = $results->num_rows;
if($numrows > 0){
while($row = $results->fetch_assoc()){
$data[] = $row;
}
return $data;
}
else{
echo 'no values';
}
}
}
class showusers extends getdata{
//show users
public function showusers(){
$datas = $this->getdata();
foreach($datas as $data){
echo $data['id'].'<br>';
echo $data['name'].'<br>';
}
}
}
$showusers = new showusers();
$showusers->showusers();
Don't give your function the same name as your class.
With $showusers = new showusers(); you are already executing the showusers function.
To cite php.net:
For backwards compatibility with PHP 3 and 4, if PHP cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class.
Source:https://www.php.net/manual/en/language.oop5.decon.php
So your function showusers() is treated as a constructor for your showusers class and therefore is executed twice. Once when you create an object of the class and once when you call the method.
your code is a bit convoluted I'd suggest passing the database connection object rather than extending continiously.
In this case your constructor showUsers() outputs a list of users. therefore it repeats because you are calling this function twice.
$showusers = new showusers(); // prints users
$showusers->showusers(); // prints users again
move your display function
class showusers extends getdata{
$data;
//initialize
public function showusers(){
$this->data = $this->getdata();
}
//show users
public function displayUsers(){
foreach($this->data as $data){
echo $data['id'].'<br>';
echo $data['name'].'<br>';
}
}
}
$showusers = new showusers();
$showusers->displayUsers();
I have a PHP class called Product:
class Product {
$id;
$name;
}
And another class that get data from database:
$stm = $this->dsn->prepare($sql);
$stm->execute();
$rst = $stm->fetchAll(PDO::FETCH_ASSOC);
How can I convert this PDO resultset ($rst) to an array of objects Product?
Use the PDO::FETCH_CLASS argument.
class Product {
public $id;
public $name;
}
$stm = $this->dsn->prepare($sql);
$stm->execute();
$result = $stm->fetchAll( PDO::FETCH_CLASS, "Product" );
http://php.net/manual/en/pdostatement.fetchall.php
Just change the way you're calling fetchAll()
$rst = $stm->fetchAll(PDO::FETCH_CLASS, 'Product');
My approach in this case would be to use a helper function within the Product class that builds a new instance of the object and returns it provided the inputs from the PDO.
Such as
public static function buildFromPDO($data) {
$product = new Product();
$product->id = $data["id"];
$product->name = $data["name"];
return $product;
}
Then inside of your PDO call, loop through the return and array_push onto an array containing all your products built via this function.
$products = array();
foreach ($rst as $r) {
array_push($products, Product::buildFromPDO($r));
}
You also might want to consider using an ORM if it seems like you'll be doing a ton of this kind of stuff.
You have to write a method to do it.
class Product {
$id;
$name;
public function loadData($data){
$this->id = $data['id'];
$this->name = $data['name'];
}
}
$Product = new Product();
$Product->loadData($database_results);
Or, if you're going to be doing this for every object, use a constructor..
class Product {
$id;
$name;
public function __construct($id, $pdo){
$pdo->prepare("select * from table where id = :id");
// do your query, then...
$this->id = $data['id'];
$this->name = $data['name'];
}
}
$Product = new Product($id, $pdo);
You can use constructor arguments (http://php.net/manual/en/pdostatement.fetchall.php)
$result = $stm->fetchAll( PDO::FETCH_CLASS, "Product", array('id','name'));
Note: properties must be public
$sql=$pardConfig->prepare("SELECT * FROM ".$this->menu); i want to call to the db table dynamically.in here it was selecting only the menu.i want to call it from object ???
<?php
$dbhost=null;
$dbname=null;
$dbuser=null;
$dbpass=null;
$file = __DIR__ ."/config.json";
$array = file_get_contents($file);
$dbConfig=json_decode($array);
$pardConfig=new PDO('mysql:host='.$dbConfig[0].';'.'dbname='.$dbConfig[1],$dbConfig[2],$dbConfig[3]);
class pardDb
{
public $config = "pard_admin_config";
public $article = "pard_article";
public $menu = "pard_menu";
public $user = "pard_user";
public $images = "pard_images";
function pardTemplate($pardConfig,$pardDbTable){
$sql=$pardConfig->prepare("SELECT * FROM ".$this->menu);
$sql->execute();
$result=$sql->fetchALL(PDO::FETCH_OBJ);
$item = array_reverse($result);
return $item;
}
}
$pardDbTable = new pardDb();
$pardDbTable->pardTemplate($config,$pardConfig);
?>
I want one object and need to call it like this ?
echo $obj->menu;
echo $obj->article;
Try refactory this in one designe patterns (start your studing by Active Record and Data Mapper) add inheritance:
http://martinfowler.com/eaaCatalog/
after see the Magic Methods __get and __set
http://php.net/manual/en/language.oop5.overloading.php#object.get
I have seen these codes:
$result = $db->result($query);
$rows = $result->fetchAll();
how can I do similar effect? ($result contains methods?)
I think this is what you are looking for:
<?php
class test{
private $value = 0;
function foo(){
$this->value = 1;
return $this;
}
function bar(){
$this->value = 2;
echo $this->value;
}
}
$test = new test();
$result = $test->foo();
$result->bar();
?>
By having the method return itself, you can chain them together in this fashion.
Strictly speaking, you're asking about OOP in PHP, in which case, this is a reasonable example:
class HasResultMethod
{
public function result( $query )
{
return new HasFetchAllMethod();
}
}
class HasFetchAllMethod
{
public function fetchAll(){}
}
// you have a variable with a result method that has one parameter.
$result = $db->result($query);
// that returns an object which has a fetchAll method.
$rows = $result->fetchAll();
You probably are dealing with some wrapper around PDO, a library to interface with databases. Their query methods will return a PDOStatement which has methods which will allow you to get results from the DB. result is either a typo, or it behaves in a very similar way.
I got it already. What a great hint Headspin
http://sandbox.phpcode.eu/g/147bd.php
<?php
class foo{
function bar(){
return $this;
}
function fetch(){
echo "yeah";
}
}
$foo = new foo();
$result = $foo->bar();
$result->fetch();
That is easy
$db is instance of class that returnes class, so when you say
$db->result($query);
$db will return object
e.g.
//this method is inside $db class
function result($query)
{
$result = new Result();
$result->rows = mysql_query...
return $result;
}
and when you say
$result->fetchAll();
that is method inside class Result that will fetch all rows saved inside $result->rows;
e.g.
//method inside Result class
function fetchAll()
{
//fetch rows inside variable $this->rows
}
So basically what you can do with ORM (object relational mapping), you can return Array of objects, each object will represent one record from db
e.g.
Class User
{
var $ID;
var $Name;
var $LastName;
var $Email;
function load($row)
{
$this->ID = $row["ID"];
... etc
}
function save()
{
$sql = "update tbl_users set Name=:Name, LastName=:LastName, Email=:Email where ID=:ID";
//then execute your query
}
}
so how to get list of objects, its easy
select all records and add them into array
$ar = new Array();
for($i = 0; $i < count($rows); $i++)
{
$r = new User();
$r->load($rows[$i]);
}
return $ar;
simple as that...