Php static called class

Php static called class

You can pass arguments to your constructor through your getInstance method, assuming you are running php5.

public static function getInstance($params = null) if (self::$objInstance == null) $strClass = static::getClass();
self::$objInstance = new $strClass($params);
>
return self::$objInstance;
>

This would pass the params to your constructor. Love for php.

In the above example (#3) in order to make it work, you can change the child’s method from ‘private’ to ‘protected’ (or public) and it will be called through ‘static’.

class A private function foo () echo «success!\n» ;
>
public function test () $this -> foo ();
static:: foo ();
>
>

class B extends A /* foo() will be copied to B, hence its scope will still be A and
* the call be successful */
>

class C extends A protected function foo () < //note the change here
echo ‘hello world!’ ;
>
>

$b = new B ();
$b -> test ();
$c = new C ();
$c -> test (); // ‘success’ ‘hello world’
?>

I have implemented enum using late static binding.

interface IEnum /**
* Only concrete class should implement this function that should behave as
* an enum.
*
* This method should return the __CLASS__ constant property of that class
*
* @return string __CLASS__
*/
public static function who ();
>

/**
* The selected value for the enum implementation
*
* @var mixed
*/
public $value ;

public function __construct ( $value ) $this -> value = $value ;
>

/**
* The factory method that creates the corresponding enum class.
*
* @param integer $type
* @return false|\class
*/
public static function Factory ( $type ) if (empty( $type )) return false ;
>

// use of late static binding to get the class.
$class = static:: who ();

if ( array_key_exists ( $type , static:: $_enums )) return new $class ( $type );
>

public function getValue () return $this -> value ;
>

public static function getValues () return array_keys (static:: $_enums );
>

public function getString () return static:: $_enums [ $this -> value ];
>

public function __toString () return static:: $_enums [ $this -> value ];
>

class Fruits extends Enum implements IEnum

public static $_enums = array(
1 => ‘Apple’
2 => ‘Orange’
3 => ‘Banana’
)

public static function who () return __CLASS__ ;
>
>

// user input from dropdown menu of fruits list
$input = 3 ;

$fruit = Fruits :: Factory ( $input );

$fruit -> getValue (); // 3
$fruit -> getString (); // Banana
?>

Suprisingly consts are also lazy bound even though you use self instead of static:
class A const X = 1 ;
const Y = self :: X ;
>
class B extends A const X = 1.0 ;
>
var_dump ( B :: Y ); // float(1.0)
?>

At least as of PHP 5.3.0a2 there’s a function get_called_class(), which returns the class on which the static method is called.

class a static public function test () print get_called_class ();
>
>

This function can be used as a workaround for late static binding in PHP >= 5.1.0. There was another similar version of this function elsewhere, but used eval.

$class = new ReflectionClass ( $class );
return $class -> getStaticPropertyValue ( $name );
>

About static parameters, these work as expected.
class A protected static $__CLASS__ = __CLASS__ ;
public static function constructor () return static:: $__CLASS__ ;
>
>

class B extends A protected static $__CLASS__ = __CLASS__ ;
>

Just a quick reminder to always check your syntax. While I love LSB, I thought it wasn’t working:

…until I realized that I’d completely forgotten to make it a variable variable:

…of course this applies anywhere in PHP, but because of the (current) newness late static bindings, I’ve seen lots of code with this particular snafu in it from others.

PHP5.3 unavailable, yet in the need for ‘static’, I did the following.

Any objections? Personally I hate using the the eval() statement.

class mother
function setStatic ( $prop , $val ) // After this, self:: refers to mother, yet next $class refers to.
//
$class = get_class ( $this );
eval( » $class ::\$ $prop = \$ $val ;» );
>
>

class child extends mother
protected static $sProp ;

function writer ( $value ) parent :: setStatic ( ‘sProp’ , $value );
>
function reader ()
return self :: $sProp ;
>
>

$c = new child ();
$c -> writer ( 3 );
echo $c -> reader (); // 3

I discovered an interesting thing. The class name string must be accessed directly from «flat» variable. Late static binding code that get’s it’s variable from array that is passed by class instance, throws an syntax error. Bug?

public $metadata = array( ‘class’ => ‘A’ );

public static function numbers ()
return 123 ;
>

// This throws an error
// Parse error: syntax error, unexpected ‘::’ (T_PAAMAYIM_NEKUDOTAYIM)
var_dump ( $instance -> metadata [ ‘class’ ]:: numbers () );

// Get the class name and store it in «flat» variable and now it’s ok
$class_name = $instance -> metadata [ ‘class’ ];
var_dump ( $class_name :: numbers () );

// This works too.
var_dump ( $arr [ ‘class’ ]:: numbers () );
?>

Example of setting up static property in child class from parent only if it isn’t already defined, many people would expect that output will be «Foo Bar» but instead we get «Foo Foo»:

class Foo
public static string $A ;

public static function init () return «Foo» ;
>
public static function get () if (!isset(static:: $A )) static:: $A = static:: init ();
>
return static:: $A ;
>
>

class Bar extends Foo public static function init () return «Bar» ;
>
>

$foo = new Foo ();
$bar = new Bar ();

echo $foo -> get ();
echo $bar -> get ();
?>

Output:
Foo
Foo

Word of caution static::class doesn’t always work as you might expect
namespace NameSpace;

class Class
static function getClass ()
return static::class;
>
>

Class:: getClass ()
?>
may return \NameSpace\Class or Class depending on context

Simplest way to understand is to run this script:

class ParentClass
<
static $A = ‘ParentVariable’ ;

static function parentCall ()
<
echo get_called_class () . ‘, self: ‘ . self :: $A . «\n» ;
echo get_called_class () . ‘, static: ‘ . static:: $A . «\n» ;
echo «—\n» ;
>
>

class ChildClass extends ParentClass
<
static $A = ‘ChildVariable’ ;

static function childCall ()
<
echo get_called_class () . ‘, self: ‘ . self :: $A . «\n» ;
echo get_called_class () . ‘, static: ‘ . static:: $A . «\n» ;
echo get_called_class () . ‘, parent: ‘ . parent :: $A . «\n» ;
echo «—\n» ;
>
>

echo «Late Static Bindings:\n» ;
ParentClass :: parentCall ();
ChildClass :: parentCall ();
ChildClass :: childCall ();
?>

—-
Output:

Late Static Bindings:
ParentClass, self: ParentVariable
ParentClass, static: ParentVariable

ChildClass, self: ParentVariable
ChildClass, static: ChildVariable

ChildClass, self: ChildVariable
ChildClass, static: ChildVariable
ChildClass, parent: ParentVariable

class P_Class <
public static $val = «Parent»;
public static function setVal($val) <
static::$val = $val;
>
public static function getVal() <
return static::$val;
>
>

class C_Class extends P_Class<>

Output:
string(5) «Child»
string(5) «Child»

You must be careful when getting static property of extended class from parent class, in example below you can see that using property_exists (method getA2) instead of isset with static keyword (method getA1) to check if the static property exist gives much more intuitive result:

class Foo
public static string $A ;

public static function init () return static::class;
>

public static function getA1 () if (!isset(static:: $A )) static:: $A = static::class;
>
return static:: $A ;
>

public static function getA2 () if ( property_exists (static::class, ‘A’ )) static:: $A = static::class;
>
return static:: $A ;
>
>
class Bar extends Foo <>

$foo = new Foo ();
echo $foo -> getA1 ();
echo $foo -> getA2 ();
echo $foo -> getA1 ();

$bar = new Bar ();
echo $bar -> getA1 ();
echo $bar -> getA2 ();
echo $bar -> getA1 ();
?>

Output:
Foo
Foo
Foo

Notice how $bar->getA1() returns «Foo» instead of «Bar» that many people would expect to see.

/**
* Return called class name
*
* @author Michael Grenier
* @param int $i_level optional
* @return string
*/
function get_called_class ( $i_level = 1 )
<
$a_debug = debug_backtrace ();
$a_called = array();
$a_called_function = $a_debug [ $i_level ][ ‘function’ ];
for ( $i = 1 , $n = sizeof ( $a_debug ); $i < $n ; $i ++)
<
if ( in_array ( $a_debug [ $i ][ ‘function’ ], array( ‘eval’ )) ||
strpos ( $a_debug [ $i ][ ‘function’ ], ‘eval()’ ) !== false )
continue;
if ( in_array ( $a_debug [ $i ][ ‘function’ ], array( ‘__call’ , ‘__callStatic’ )))
$a_called_function = $a_debug [ $i ][ ‘args’ ][ 0 ];
if ( $a_debug [ $i ][ ‘function’ ] == $a_called_function )
$a_called = $a_debug [ $i ];
>
if (isset( $a_called [ ‘object’ ]) && isset( $a_called [ ‘class’ ]))
return (string) $a_called [ ‘class’ ];
$i_line = (int) $a_called [ ‘line’ ] — 1 ;
$a_lines = explode ( «\n» , file_get_contents ( $a_called [ ‘file’ ]));
preg_match ( «#([a-zA-Z0-9_]+) < $a_called [ 'type' ]>
< $a_called [ 'function' ]>( )*\(#» , $a_lines [ $i_line ], $a_match );
unset( $a_debug , $a_called , $a_called_function , $i_line , $a_lines );
if ( sizeof ( $a_match ) > 0 )
$s_class = (string) trim ( $a_match [ 1 ]);
else
$s_class = (string) $a_called [ ‘class’ ];
if ( $s_class == ‘self’ )
return get_called_class ( $i_level + 2 );
return $s_class ;
>
?>

I think this will be pretty helpful too.
My question is, can just ‘static’ by itself resolve to the late static class?
I ask this because it could help in making new instances of the derived class, from a base class, by calling a derived class’s static method instead of having to create a new instance of the derived class — or explicitly defining a ‘getClass’ method for each derived class.
Example:
//There isn’t really any purpose for this example I posted
//Just a random implementation
class Base static function useful () //Create a list of instances of the derived class
$list =array();
for ( $i = 0 ; $i < 10 ; $i ++) $list []=new static(); //Here's the point in question
return $list ;
>
>
class Derived extends Base static function somethingElse () //.
$list =static:: useful ();
>
>
?>
I’m not sure what kind of lexical / whatever-it’s-called problems this would make with parsing. I don’t think it could really collide with any contexts where you would use static otherwise — variable / method declaration.

Even more so, is there a way to get the class’s name to which the keywords ‘self’, ‘parent’, or ‘static’ refer?
Example:
class Base static function stuff () echo «Self: » . get_class ( self );
echo «Parent: » . get_class ( parent );
echo «Derived: » . get_class (static);
>
>
class Derived extends Base static function stuff () static:: stuff ();
>
>
?>

I don’t think there should be a massive bloat in the PHP core to support all of this, but it would be nice to take advantage of the dynamic nature of PHP.

And yet another side note:
If you’re in the instance-level scope in a method of a base, and you want to get a top-level static, here’s an ugly workaround (from Thacmus /lib/core.php — see SVN repo):
//Get reference [?] to static from class
//$class — Class name OR object (uses get_class())
//$var — Not gonna say
function& get_static ( $class , $var ) < //'static_get'?
if (! is_string ( $class )) $class = get_class ( $class );
if (!@ property_exists ( $class , $var )) trigger_error ( «Static property does not exist: $class ::\$ $var » );
//debug_callstack(); //This is just a wrapper for debug_backtrace() for HTML
return null ;
>
//Store a reference so that the base data can be referred to
//The code [[ return eval(‘return &’.$class.’::$’.$var.’;’) ]] does not work — can not return references.
//To establish the reference, use [[ $ref=&get_static(. ) ]]
eval( ‘$temp=&’ . $class . ‘::$’ . $var . ‘;’ ); //using
return $temp ;
>
?>

Источник

Читайте также:  Как сгенерировать пароль java
Оцените статью