PHP undeclared static property - php

I have class defined like this:
class FileSystem
{
private static $_instance = NULL;
private function __construct()
{
...
}
public static function getInstance()
{
if (self::$_instance === NULL) { // <- line 83
self::$_instance = new FileSystem;
}
return self::$_instance;
}
...
}
The error I get when running it is:
Uncaught Error: Access to undeclared static property:
FileSystem::$_instance in
/var/www/html/.../FileSystem.php:83
Server on which the code is running has php 7.1.
Method that calls that class is in another class:
public function stream_close()
{
if (!is_resource($this->_stream)) {
return false;
}
FileSystem::getInstance()->fclose($this->_stream);
return true;
}

your code as posted in your question should work fine.
There is one reason of this kind of error and it's when you don't declare you static attribute so your error must be something like you forgot to save or that you have commented that declaration and so on.

Related

Uncaught Error: Using $this when not in object context when using __callStatic

I am trying to make it so that I can call a non-static method statically using __callStatic but I keep getting this error. I know it is possible because some frameworks (like Laravel) does this but I can't seem to be able to do it myself.
Fatal error: Uncaught Error: Using $this when not in object context
in Output.php:18 Stack trace:
index.php(4): Output::prepare()
1 {main} thrown in Output.php on line 14
index.php
$output = Output::prepare();
Output.php
class Output
{
public static function __callStatic($method, $args)
{
if ($method == 'prepare') {
$obj = new static();
return $obj->$method(...$args);
}
}
public function prepare()
{
// (!) Uncaught Error: Using $this when not in object context
if ($this->hasItems()) {
return print_r($_POST, true);
}
}
public function hasItems()
{
return true;
}
}
"__callStatic() is triggered when invoking inaccessible methods in a static context."
Your method prepare is accessible by its visibility. You would need to adjust the visibility of the prepare method if you want __callStatic to be used:
protected function prepare()
Your error sounds more like you declared prepare to be a static function:
public static function prepare()
Instead of Non-static method like:
public function prepare()
If your method was Non-Static you would be receiving something like this instead:
Non-static method Output::prepare() should not be called statically ...
PHP Manual - OOP - Magic Methods - __callStatic
You can't use that trick on the same class unless you remove visibility to your methods as #lagbox says. Otherwise, PHP will call directly the prepare() method without going through __callStatic().(in your case it leads to $this error with a warning for using a public method statically)
class Output
{
public static function __callStatic($method, $args)
{
if ($method == 'prepare') {
$obj = new static();
return $obj->$method(...$args);
}
}
private function prepare()//or protected to remove visibility and force the call for __callStatic()
{
if ($this->hasItems()) {
return print_r($_POST, true);
}
}
public function hasItems()
{
return true;
}
}
If you want to use the Facade trick, you need to forward the static call to another class (you can send some context to this second class to make it unique to Output class)
class Output
{
public static function __callStatic($method, $args)
{
if (!method_exists(self::class,$method)) {
return (new Forward('output'))->$method(...$args);
}
}
}
class Forward
{
private $context;
public function __construct($context = null)
{
$this->context = $context;
}
public function prepare()
{
if ($this->hasItems()) {
return print_r($_POST, true);
}
}
public function hasItems()
{
return true;
}
}
PS: laravel uses this trait to get this done on modelsIlluminate\Support\Traits\ForwardsCalls.
protected function forwardCallTo($object, $method, $parameters)
{
try {
return $object->{$method}(...$parameters);
} catch (Error | BadMethodCallException $e) {
$pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';
if (! preg_match($pattern, $e->getMessage(), $matches)) {
throw $e;
}
if ($matches['class'] != get_class($object) ||
$matches['method'] != $method) {
throw $e;
}
static::throwBadMethodCallException($method);
}
}
__callStatic() is triggered when invoking inaccessible methods in a static context.
You try use Output::prepare(). Magic Methods __callStatic not run. Because, you have been method prepare and it run method prepare instead of __callStatic. When throw a error:
Fatal error: Uncaught Error: Using $this when not in object context in Output.php
If you using it that similar in Laravel. Example for reference:
<?php
class Output
{
public static function __callStatic($method, $args)
{
if ($method == 'prepare') {
$obj = new Fix;
return $obj->$method(...$args);
}
}
}
class Fix
{
public function prepare()
{
if ($this->hasItems()) {
echo "Prepare";
}
}
public function hasItems()
{
return true;
}
}
$output = Output::prepare();
Or specific:
<?php
class OutputFacade extends Facade{
protected static function getClass()
{
return new Output();
}
}
abstract class Facade
{
public static function __callStatic($method, $args)
{
$instance = static::getClass();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
return $instance->$method(...$args);
}
}
class Output
{
public function prepare()
{
if ($this->hasItems()) {
echo "Prepare";
}
}
public function hasItems()
{
return true;
}
}
$output = OutputFacade::prepare();
Note: My english is not good, hope you understand
The method prepare inside your Output class is not static. It's only non static method you can call using $this-> in your case to call prepare you should make use of your Output class Use Output, then you can say $output = new Output and then $output->prepare(). If you want to use it as Output::prepare() you have to change the method inside your Output class to public static function prepare().
Hope that helps

PHP syntax for static attribute of attribute

I have implemented a singleton pattern class, and who can be used in another classes like this :
class myClass {
private $attr;
public function __construct() {
$this->attr = Singleton::getInstance;
echo $this->attr::$sngtAttr; // Throw an error
// witch syntax use whithout pass by a temp var ?
}
}
Is $sngtAttr a static property?
If not, then just:
echo $this->attr->sngtAttr; instead of echo $this->attr::$sngtAttr;
will do it.
Otherwise since is static:
echo Singleton::$sngtAttr;
What is your question exactly ?
This is how you do a singleton :
<?php
class ASingletonClass
{
// Class unique instance. You can put it as a static class member if
// if you need to use it somewhere else than in yout getInstance
// method, and if not, you can just put it as a static variable in
// the getInstance method.
protected static $instance;
// Constructor has to be protected so child classes don't get a new
// default constructor which would automatically be public.
protected final function __construct()
{
// ...
}
public static function getInstance()
{
if( ! isset(self::$instance)) {
self::$instance = new self;
}
return self::$instance;
}
// OR :
public static function getInstance()
{
static $instance;
if( ! isset($instance)) {
$instance = new self;
}
return $instance;
// In that case you can delete the static member $instance.
}
public function __clone()
{
trigger_error('Cloning a singleton is not allowed.', E_USER_ERROR);
}
}
?>
Also don't forget the () when you call getInstance, it's a method, not a member.

How do I call a static method of a class stored as a variable?

Why, in a class instance context, don't calls of the form $this->className::staticMethod work, but calls of the form $className::staticMethod do work?
In the example below callDoSomething2 works, but callDoSomething does not work (I get a parser error). I'm using PHP version 5.3.15.
<?php
class A {
private $className;
public function __construct($className) {
$this->className = $className;
}
public function callDoSomething() {
$this->className::doSomething();
}
public function callDoSomething2() {
$className = $this->className;
$className::doSomething();
}
}
class B {
public static function doSomething() {
echo "hello\n";
}
}
$a = new A('B');
$a->doSomething();
callDoSomething2 is one way to do it, the other would be to use something along the lines of
call_user_func("{$this->className}::doSomething");

How can I create a singleton in PHP?

I'm using PDT and Aptana on Eclipse Indigo with PHP 5.3 and I want to create a singleton in a class.
By singleton, I mean I want to just have one instance of that object, and for other objects or classes to get that single instance via a function that returns that object (so this would mean I'm trying to create an object within the class that defines that object, ie: creating objA within the class objA)
I understand you can't just go a head and do this:
public $object = new Object();
with in a class definition, you have to define it in the constructor.
How can I go ahead and do this? I'm coming from Java, so it could be I'm confusing some basic stuff. Any help is greatly appreciated. Here's the code:
<?php
class Fetcher{
private static $fetcher = new Fetcher(); //this is where I get the unexpected "new" error
static function getFetcherInstance(){
return $this->$fetcher;
}
}
?>
Solved! Thanks for all the help guys!
try this:
<?php
class myclass{
private static $_instance = null;
public static function getInstance() {
if (self::$_instance === null) {
self::$_instance = new myclass();
}
return self::$_instance;
}
}
?>
and call it with:
<?php
$obj = myclass::getInstace();
?>
You cannot assign a class property in PHP like that. It must be a scalar, or array value, or the property must be set in a method call.
protected static $fetcher;
static function getFetcherInstance(){
if (!self::$fetcher) {
self::$fetcher = new Fetcher();
}
return self::$fetcher;
}
Also, notice that I did not use $this->, as that only works for object instances. To work with static values you need to use self:: when working within the class scope.
You might want to just read common design patterns on the php site. There are pretty good examples with good documentation:
http://www.php.net/manual/en/language.oop5.patterns.php
Else, a singleton is simply a method that returns one single instance of itself:
class MySingletonClass {
private static $mySingleton;
public function getInstance(){
if(MySingletonClass::$mySingleton == NULL){
MySingletonClass::$mySingleton = new MySingletonClass();
}
return MySingletonClass::$mySingleton;
}
}
Building on #periklis answer you might want separate singletons for different application scopes. For example, lets say you want a singleton of a database connection - fine. But what if you have TWO databases you need to connect too?
<?php
class Singleton
{
private static $instances = array();
public static function getInstance($name = 'default')
{
if ( ! isset(static::$instances[$name]))
{
static::$instances[$name] = new static();
}
return static::$instances[$name];
}
}
Class DB extends Singleton {}
$db_one = DB::getInstance('mysql');
$db_two = DB::getInstance('pgsql');
Alse define __clone method
class Fetcher {
protected static $instance;
private function __construct() {
/* something */
}
public static function getInstance() {
if (self::$instance === null) {
self::$instance = new Fetcher();
}
return self::$instance;
}
private function __clone() {
/* if we want real singleton :) */
trigger_error('Cannot clone', E_USER_ERROR);
}
}
Basically implementing a singleton pattern means writing a class with a private constructor and a static method to build itself. Also check PHP site for it: http://www.php.net/manual/en/language.oop5.php and http://it2.php.net/manual/en/book.spl.php
class A {
protected $check;
private function __construct($args) {
}
static public function getSingleton($args) {
static $instance=null;
if (is_null($instance)) {
$instance=new A();
}
return $instance;
}
public function whoami() {
printf("%s\n",spl_object_hash($this));
}
}
$c=A::getSingleton("testarg");
$d=A::getSingleton("testarg");
$c->whoami(); // same object hash
$d->whoami(); // same object hash
$b= new A("otherargs"); // run time error
<?php
class MyObject {
private static $singleInstance;
private function __construct() {
if(!isset(self::$singleInstance)) {
self::$singleInstance = new MyObject;
}
}
public static function getSingleInstance() {
return self::$singleInstance;
}
}
?>
class MyClass {
private static $instance;
public static function getInstance() {
if( !isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}
Then call get instance using
MyClass::getInstance();

PHP Class throws an error, what is wrong

I have the class.
Class User {
private $_name;
private $_email;
public static function factory() {
return new __CLASS__;
}
public function test() {
}
}
and when i make a static method call using the syntax below.
User::factory();
it throws me following syntax error.
Parse error: syntax error, unexpected T_CLASS_C in htdocs/test/index.php on line 8
the error is being thrown because the Static factory() method is unable to create the object during the static method call.
and when i change the magic constant __CLASSS__ to the name of the current class i.e to User then it works.
what am i missing?
Try:
Class User {
private $_name;
private $_email;
public static function factory() {
$class = __CLASS__;
return new $class;
}
public function test() {
}
}
Not really sure why your example doesn't works. But what does work is:
public static function factory()
{
return new self();
}
Try this:
$class = __CLASS__;
return new $class;
Why don't you return self or $this?
Check out the singleton patterns: http://www.phpbar.de/w/Singleton and http://php.net/manual/language.oop5.patterns.php
Other solution would be
return clone $this;

Categories