I can't make a simple echo.
I have an admin.class.php
public static function get_quota() {
return self::find_by_sql("SELECT * FROM quota");
}
public static function find_by_sql($sql="") {
global $database;
$result_set = $database->query($sql);
$object_array = array();
while ($row = $database->fetch_array($result_set)) {
$object_array[] = self::instantiate($row);
}
return $object_array;
}
And my echo code in index.php
<?php
$admin = User::find_by_id($_SESSION['user_id']);
$admin_class = new Admin();
$get_quota = Admin::get_quota();
$sql = "SELECT * FROM quota";
$get_quota = Admin::find_by_sql($sql);
?>
.
.
.
<?php echo $get_quota->daily_a; ?>
So my problem is, that the code is not working. I cannot echo my data. Can you help me, please?
You have a couple of problems here:
<?php echo $get_quota->daily_a; ?>
This line references the $get_quota variable and searches for a member field daily_a. Try this:
<?php echo "Quota is:".var_export($get_quota->daily_a,true); ?>
This will show that that is simply an empty variable.
However, also note:
$get_quota = Admin::get_quota();
$sql = "SELECT * FROM quota";
$get_quota = Admin::find_by_sql($sql);
Here you are calling two separate methods from Admin and setting the variable $get_quota to the result. The second overwrites the first. Therefore the get_quota() method doesn't help us here: we need to know what your find_by_sql() method returns.
EDIT (Post new code added to question)
You can implement logging/echoing within the function you've a problem with:
public static function find_by_sql($sql="") {
global $database; //Note this is bad practice (1).
$result_set = $database->query($sql);
echo "Result Set: ".var_export($result_set,true)."\n";//This should return something if you're getting something back from the database. Also, remove this for runtime (obviously).
if (count($result_set) <= 0) { //constraint checking is always good! And cheap!
error_log("An unexpected number of rows (0) was received from the database for query='".$sql."'.");
}
$object_array = array();
while ($row = $database->fetch_array($result_set)) {
$object_array[] = self::instantiate($row); //Ensure that the instantiate function returns something!
}
echo "Object Array: ".var_export($object_array, true)."\n";//double-check your instantiate function is working
return $object_array;
}
Based on this code, your problem is likely with the instantiate function; if it's not returning anything, $object_array is probably empty. (But not null!).
(1) You should avoid grabbing global variables like this. Instead, instantiate a class that holds and manages your database connection. Then make your find_by_sql function non-static and have a member field pointing to your database.
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);
I've created an anonymous function to get some sql results so i don't have to write it everytime :
function select($sql){
global $connexion; // config connection
$query = $connexion->prepare($sql);
$query->execute();
return $query->setFetchMode(PDO::FETCH_OBJ);
}
I've created a class to get the meta information from my DB :
class PageInfo {
public function get_meta($page_name){
$sql = "SELECT description, keywords FROM pages WHERE titre='$page_name'";
select($sql); //call the first function
global $query;
while( $results = $query->fetch() ){
echo "test";
}
}
}
Then i call the class like that:
$PageInfo = new PageInfo();
$PageInfo->get_meta('homepage');
Don't understant why i get this fatal error :
Fatal error: Call to a member function fetch() on a non-object
Thanks for your precious help
You never did global $query inside your select() function. That means $query in there is a local variable, and your DB results will get trashed/destroyed once the function returns.
Plus, using global variables is just plain horrible. Especially for this. You're limiting yourself to a SINGLE query in-flight at any given time. Why not return the actual result instead?
function query($sql) {
$result = $connextion->execute($sql);
return $result;
}
$results = query($sql);
while($row = $results->fetch()) {
...
}
I'm learning PHP and am trying to create some code outside of the tutorial I've been watching to understand it better and I can't seem to figure out where I'm going wrong with the code below. I have lots of other functions working just fine, just not this one. Can anyone point me in the right direction? Thanks.
The result I get is Catchable fatal error: Object of class User could not be converted to string on line 20, which is echo $user . "<br /><br />";
Here is my index.php
<?
$users = User::db_fields();
foreach($users as $user) {
echo $user . "<br /><br />";
}
?>
Here is my class User in user.php
<?php
class User extends OtherStuff {
public static function db_fields() {
global $db;
return static::find_by_sql("SHOW COLUMNS FROM my_table");
}
}
<?
Here is some of my OtherStuff class in other_stuff.php
class OtherStuff {
public static function find_by_sql($sql="") {
global $db;
$result_set = $db->query($sql);
$object_array = array();
while($row = $db->fetch_array($result_set)) {
$object_array[] = static::instantiate($row);
}
return $object_array;
}
public static function instantiate($record) {
$class_name = get_called_class();
$object = new $class_name;
foreach($record as $attribute => $value){
if($object->has_attribute($attribute)) {
$object->$attribute = $value;
}
}
return $object;
}
}
?>
Well....Your calling db_fileds() statically.
User::db_fields();
So it needs to be a static function..
public static function db_fields() {
EDIT
You could do this as a workaround...
Change your query
return static::find_by_sql("SELECT * FROM mytable LIMIT 1");
Then do this...
$fields = User::db_fields();
foreach($fields as $key=>$value ) {
echo $key; // This will give the field name
}
EDIT 2
To preserve the column names linked to the fields.
Although this is likely wrong, because now its instantiating multiple times, and what happens in a case where an object doesnt find an attribute and doesn't get written, then you miss a column.
But the idea is there...
while($row = $db->fetch_array($result_set)) {
foreach($row as $k=>$v){
$object_array[$k] = static::instantiate($row);
}
}
Well the array you're iterating over is $users, and the values you're getting from $users are going into $user.
But you're echoing $users (the Array). If the values in your $users array are all strings (or some other scalar value) you should be fine by changing your code to:
<?
$users = User::db_fields();
foreach($users as $user) {
echo $user . "<br /><br />";
}
?>
(I also added in your missing brace at the end)
You made a silly:
echo $users . "<br /><br />"; should have $user as the echo param
<?
$users = User::db_fields();
foreach($users as $user) {
echo $user . "<br /><br />";
?>
You were printing the original array every time
Edit:
The new error is a reflection of the fact that your User class does not explicitly define a way for objects of the class to be converted to strings. If you want to do a quick n dirty output, you can var_dump() your objects, but eventually you'll want to override the __toString() method. Check this out.
You can also simply make a function in the User class that returns the string you want and just call it with $user->StringifyUser(). The (main) difference between this approach is that PHP will not implicitly convert your User class objects to strings when used in your originally context.
Edit 2:
I would also check out the other answers, especially that of KyleK who addresses several key points that I did not touch on.
I am using PHP with OOP to select rows from the database (MySQL).
When I execute the query, it returns an empty row.
Here is the classe I am using:
<?php
class EmploiManager
{
private $_db;
public function __construct($db)
{
$this->setDb($db);
}
public function category($category)
{
$q = $this->_db->prepare('SELECT * FROM DemandeEmploi WHERE category = :category');
$q->execute(array('category' =>$category));
$donnees = $q->fetch(PDO::FETCH_ASSOC);
return new Emploi($donnees);
}
public function setDb(PDO $db)
{
$this->_db = $db;
}
}
$type = $_GET['category'];
$manager = new EmploiManager($db);
$row = $manager->category($type);
foreach ($row as $demandeE)
{
?>
<div class="list"><h4><? echo $demandeE->title();?></h4> </div>
<?php
}
?>
Can any one tell me what's wrong with that code?
Thanks!
It's my bad, I didn't use a loop to select all the rows.
I corrected the code and it works fine now, here is what it looks like:
public function category($category)
{
$datas = array();
$q = $this->_db->prepare('SELECT * FROM DemandeEmploi WHERE category = :category');
$q->execute(array('category' =>$category));
while ($donnees = $q->fetch(PDO::FETCH_ASSOC))
{
$datas[] = new Emploi($donnees);
}
return $datas;
}
$q->fetch() just returns one row of the results. If you want all the results, you must use $q->fetchAll().
Since you specified PDO::FETCH_ASSOC, the elements of $row will be associative arrays, not objects; aren't you getting errors saying that you're trying to call a method on a non-object? So $demandeE->id() should be $demandeE['id'], and $demandeE->title() should be $demandeE['title'].
Alternatively, you could specify PDO::FETCH_OBJ. Then, the values will be properties, not methods, so it should be $demandeE->id and $demandeE->title (no parentheses).
Can anyone see why my check_multi function would return a --
Fatal error: Call to undefined function check_multi() in
/var/www/vhosts/aero.onelinksoftware.com/application/models/Design.php
on line 21
The above error shows up and I am not sure what I am doing wrong. I tried setting my function as public, private, static, and other combinations but no matter what I try; the system still errors out. Can you not call a function inside a Model in Zend? I don't understand why I cannot use a function I created if it is inside a class I made.
If I echo and die before the check_multi call; I can see my text and such. I have also performed a php test for syntax and it is valid as far as it reports.
class Model_Design
{
/**
* Constructs our partials.
*
* #return void
*/
public function __construct($key)
{
// Get the DB Connection
$db = Zend_Registry::Get('db');
// Setup the SQL Statement
$sql = $db->select()->from('design', array('id'));
// Get the Result
$result = $sql->query();
// Get our Row
$row = $result->fetchAll();
if(check_multi($key, $row)) {
echo "omg"; die();
}
// Make sure the id isn't empty
if (empty($key)) {
throw new Exception('You have a disturbing lack of variables.');
}
// Store the id
$this->variables = $key;
// Construct our query
$sql = $db->select()->from('design')->where('`id` = ?', $key);
// Get the result
//$result = $sql->query();
//$row = $result->fetch();
}
private function check_multi($n, $arr)
{
foreach ($arr as $key => $val) {
if ($n===$key) {
return $key;
}
}
return false;
}
}
Try:
$this->check_multi($key, $row);
To access a variable or function from inside its container class you must use $this. $this is the current instance of the class.
How do you call the function ? use $this->check_multi($n,$arr); or you can try function_exists() to check if function really exist