PHP call to static function fails - php

All,
I'm getting an error with the code below. Here is the error message I get:
Notice: Undefined variable: userDAO in C:\wamp\www\Projetv0.2\Model_User.php on line 15
and then
Fatal error: Call to a member function checkRecordExists() on a non-object in C:\wamp\www\Projetv0.2\Model_User.php on line 15
The relevant code is below. What I try to do with the code is have a unique class (DAO_DBrecord) to access several tables in a db. In the case below, I want to access my users table. To do that I have created a specific static function createUserDAO inside the DAO_DBrecord class that calls the constructor with the right table name, users. However, it doesn't work, and I can't figure why.
Model_User.php:
<?php
require_once('Class_DB.php');
require_once('DAO_DBrecord.php');
class Model_user{ // Represents a connection to the users table in the DB
private $db;
private $userDAO;
function __construct($db){
$this->db=$db;
$userDAO=DAO_DBrecord::createUserDAO($this->db);// static function - calls constructor w/ 'user' table name parameter
$this->userDAO=$userDAO;
}
function userInfoExists($userInfo, $colName){
return $userDAO->checkRecordExists($userInfo, $colName);
}
//Other stuff
}
?>
DAO_DBrecord.php:
<?php
require_once('Class_DB.php');
class DAO_DBrecord {
private $db;
private $table;
private function __construct($db,$table){
$this->db=$db;
$this->table=$table;
}
public static function createUserDAO($db) {
return new DAO_DBrecord($db, 'users');
}
//Other stuff
}
?>
Thank you all for your help!
JDelage

That's not a problem with the static function. The problem is that PHP doesn't have an implicit $this. When you're referring to the member variable within the class (as you are in userInfoExists), you have to say $this->userDAO rather than just $userDAO.
Of course, all this assumes that the DAO_DBrecord class has or inherits a checkRecordExists function. If it doesn't, you're going to have other problems.

Related

Using $this when not in object context in

I'm stuck probably at a fairly simple question... I'm working on a implementation with YAML to enable the duplication of the application.
However, setting up the config model is the part where I'm stuck.
class ConfigModel {
public $configSection = null;
private $configArray = array();
public function loadYML(){
$this->configArray = Spyc::YAMLLoad('../config/config.yml');
}
public function setConfigSection($configSection){
$this->configSection = $configSection;
}
public function getConfig($configSection){
$this->loadYML(); //Line 33
}
}
Through a test script I request the specific contents of the YML file:
$mysqlSettings = ConfigModel::getConfig('mysql');
But then I'm getting the error:
Fatal error: Using $this when not in object context in Line 33
The loadYML works and outputs a Array. And to my onderstanding the this->loadYML(); is allowed to be used there...
You trying to call ConfigModel::getConfig() as static method. It is is wrong to use $this in static method. You must declare $configArray as static property and loadYML() and getConfig() as static methods if you need to call getConfig() as static

unserialize() ... Function spl_autoload_call() hasn't defined the class it was called for

I'm using factory to create an object and the static method to unserialize this object:
public static function factory($idText) {
$fetchedObject = self::fetchStoredObject($idText);
return $fetchedObject;
}
private static function fetchStoredObject($idText) {
$fetchedText = DB::select()
->from(table)
->where('idText', '=', $idText)
->execute()->as_array();
if (!empty($fetchedText)) {
return unserialize(base64_decode($fetchedText[0]['txtContent']));
} else {
return NULL;
}
}
The object is created in this way:
$text = Article::factory($idText);
But I get the following error:
unserialize() [<a href='function.unserialize'>function.unserialize</a>]:
Function spl_autoload_call() hasn't defined the class it was called for
On this line of fetchStoredObject method:
return unserialize(base64_decode($fetchedText[0]['txtContent']));
Why does this error occur?
EDIT
My class has the following structure:
class Article {
private $phpMorphy;
private $words; //contains instances of class Word
...
private function __construct($idText) {
$this->initPhpMorphy(); // $this->phpMorphy gets reference to the object here
}
public function __sleep() {
return Array(
'rawText',
'idText',
'properties',
'words',
'links'
);
}
public function __wakeup() {
$this->initPhpMorphy();
}
}
The Word class doesn't contain the reference to phpMorphy as own property, but uses it in its methods as function parameter.
Here is the part of the serialized string:
" Article words";a:107:{i:0;O:4:"Word":10:{s:5:" * id";O:9:"phpMorphy":7:{s:18:" * storage_factory";O:25:
It appears the phpMorphy is serialized with connectrion to the Word class. Am I right?
The error occurs because inside your serialized string there is a reference to a class that hasn't been included yet - so the PHP autoloading mechanism is triggered to load that class, and this fails for some reason.
Your steps for debugging would be:
Identify which class is included in that serialized string.
Check if you have code for that class somewhere.
Make sure this code can be loaded via autoloading. Alternatively make sure that code is included before unserializing.
What version of PHP did you use? Where did you store your Article class? Try to require() it manually.
The problem is fixed thanks to Sven suggestions. The object of class Word (part of the class Article) contained reference to the phpMorphy class (which happened because I changed parameters order when creating an instance of the word!).

Static and non static function class togheter

Can someone explain me and make some example for a static and non static class that works together?
like:
App::MySQL()->insert();
App::User()->name;
i can't find anything on web.
Thanks
The first part (e.g. App::MySQL(), App::User()) is calling a static method on a class in order to return a singleton instance (meaning if an instance of that class exists return it, else create a new one and return it), this makes sure that you have at most one instance of that class. Then you call its methods or get its properties (the second part: ->insert(), ->name)
<?php
class App {
public static function MySQL() {
return new MySQL();
}
}
class MySQL {
public function insert() {
echo "inserting some stuff\n";
}
}
App::MySQL()->insert();
gives
ivo#atmycomputer ~$ php test.php
inserting some stuff
ivo#atmycomputer ~$

Pass the current class as parameter

I have a class like this:
// file /models/person.php
class Person
{
public function create_path()
{
self::log();
path_helper($this); //a global function in other php file
}
public function log()
{
echo "trying to create a path";
}
}
This is the way how Person is instanciated:
//file /tools/Builder.php
include('/models/Person.php');
class Builder
{
public function build()
{
$type = 'Person';
$temp = new $type();
$temp->create_path();
}
}
As you note in Person class, I am calling the object in question with $this reference. But this is not correct because an error is showed:
Message: Undefined variable: this
I suppose that $this reference point to other object or it is unable to work because the object is created from another script. Also, I tried to use self because there was not problem calling methods with that, but as parameter I get:
Message: Use of undefined constant self - assumed 'self'
So, can you guide me to the right direction?
I tested your code out for myself, with a few minor changes. It appears to work properly.
Changed self::log() to $this->log()
Added global function path_helper (I have no idea what this does)
PHP
function path_helper(Person $object)
{
var_dump($object);
}
class Person
{
public function create_path()
{
$this->log();
path_helper($this); //a global function in other php file
}
public function log()
{
echo "trying to create a path";
}
}
class Builder
{
public function build()
{
$type = 'Person';
$temp = new $type();
$temp->create_path();
}
}
$Build = new Builder();
$Build->build();
Result
trying to create a path
object(Person)[2]
Your code is correct and your going in the right direction.
You should call the log method like this:
$this->log();
because using self:: is reserved for static methods.
Also, try calling the path_helper function like this:
path_helper(self);
Hope I could help you. Couldn't test it, but it should work.

PHP: Trying to use late static bindings (LSB) for database. Maybe my understanding wrong of LSB

I have been creating PHP projects for years, and have previously written Database classes, that are called and created statically, i.e.:
class Database {
private static $objConnection;
public static function connect() {
self::$objConnection = #mysqli_connect(/* Username, password, etc */);
// Do connection checking etc....
}
public static function get_row($strSQL) {/*Do Stuff here*/};
public static function get_rows($strSQL) {/*Do Stuff here*/};
}
I then in my code can use methods to call: $objResult = Database::get_rows('SELECT * FROM User'); for example.
I have the need for multiple databases now (i.e. more than one database for one project), and therefore wanted to extend a base database class, and then extend it for different databases with different settings, so that the 20 or so static calls don't have to be re-written every time I want to use a new database. So therefore I want to call within my code: MainDatabase::get_rows($strSQL);, and UserDatabase::get_rows($strSQL); for the user database for example. I had read up on LSB previously, and thought this would allow me to do it, but I was stuck with pre 5.30 until now! I went to implement this system using LSB, and ran into problems. Heres the basis of my code (a lot of details removed):
abstract class DatabaseBase {
abstract protected static function get_db_hostname();
abstract protected static function get_db_user();
abstract protected static function get_db_password();
abstract protected static function get_db_database();
/**
* Connects to the database
* Will retur true or false, depending on if it could connect or nots
*
* #return boolean
*/
final private static function connect() {
$strHost = static::get_db_hostname();
$strUser = static::get_db_user();
$strPassword = static::get_db_password();
$strDatabase = static::get_db_database();
static::$objConnection = #mysqli_connect(/*Users, pass, etc*/);
}
final public function run_query($strSQL) {
/* Check and parse the SQL, etc, etc*/
return(static::$objConnection->query($strSQL));
}
}
class MainDatabase extends DatabaseClass {
protected static $objConnection;
protected static function get_db_hostname() {return('localhost')};
/* Etc etc*/
}
class UserDatabase extends DatabaseClass {
protected static $objConnection;
protected static function get_db_hostname() {return('user_db_host')};
/* Etc etc*/
}
This works if called and tested from index.php for example not IN a class. The problem is when I call MainDatabase, and UserDatabase::run_query from within another class. Such as the following:
class User {
public function load($idUser) {
$objRow = UserDatabase::run_query('SELECT * FROM User WHERE idUser = $idUser');
}
}
If I call the load method on the User class, then I get the error: "Fatal error: Access to undeclared static property: User::$objConnection in DatabaseBase.php on line xx"
If I output the results of get_called_class() in the run_query() method it also says User.
User does NOT extend database in anyway, and is NOT static. Maybe this is my understanding of LSB, but can someone help. My DatabaseBase class will define lots of static methods that can be used on database connections, and the child classes will just contain the static connection object, and connecting/settings information. I am getting a little disappointed with this, as I have been waiting 6 months to try out LSB as a solution to this, and found that this is not what I wanted.
Regards, Gunja
If you run UserDatabase::connect() it should store the objConnection from
static::$objConnection = #mysqli_connect(/*Users, pass, etc*/);
indeed in the UserDatabase class (and not in the DatabaseBase class). Then,
UserDatabase::run_query('SELECT * FROM User WHERE idUser = $idUser');
should work, but you might want to make run_query static as well!

Categories