The object is to make the name of the function shorter.
I have a function called somedescriptivefunctionName.
function somedescriptivefunctionName($a) {
echo $a;
}
I want to assign it to $this->f so that I do not litter the code with long names.
$this->f('Yahoo!!'); // will echo 'Yahoo!!'
e.g. I imagine something like this:
$this->f = $this->somedescriptivefunctionName; // wrong way
Is this possible?
Of course I could make a new function f, and return somedescriptivefunctionName(). But this is not the point.
You will store somewhere the string
$f = "somedescriptivefunctionName";
and then call the function by specifying its name in curly brackets:
$this->{$f}('Yahoo!!');
EDIT
According to the comment section, the aim is to call a method of an instance of another class by the same name. You can extend the config class to achieve a somewhat similar behavior, but I think that's not acceptable as a solution in this case. You can convert your class into a decorator, like
class SomeClassDecorator
{
protected $_instance;
public function myMethod() {
return strtoupper( $this->_instance->someMethod() );
}
public function __construct(SomeClass $instance) {
$this->_instance = $instance;
}
public function __call($method, $args) {
return call_user_func_array(array($this->_instance, $method), $args);
}
public function __get($key) {
return $this->_instance->$key;
}
public function __set($key, $val) {
return $this->_instance->$key = $val;
}
// can implement additional (magic) methods here ...
}
The code above was copied from Gordon's amazing answer here: How to add a method to an existing class in PHP?
An evolution of this idea could be to create a decorator for your config class as a base class and extend that base class for your classes that are configured by this, so you will implement a single decorator and (re)use it.
You can bind a property to a closure and invoke the property as a method:
class T{
private $f;
function abcdefghijklmnopqrstuvwxyz($param){
echo $param;
}
function __construct(){
$this->f = fn() => $this->abcdefghijklmnopqrstuvwxyz(...func_get_args());
}
function doWork() {
($this->f)('hello');
$g = $this->f;
$g('world');
}
}
(new T())->doWork();
In this code, the class f property is bound to a closure via an arrow function, which became available as of PHP 7.4, and we can dynamically get the arguments passed via func_get_args. If you are using a version less than 7.4 you can also just use a regular anonymous function.
Unfortunately, do to name resolution issues, properties cannot be invoked as methods without using an extra set of parentheses which means you have to do ($this->f)('hello'). If you want to skip that, you can further assign the class property to a local variable which can then be invoked normally as the $g is done.
edit
Here's a version of the constructor that doesn't use arrow functions, it is invoked in the same way.
function __construct()
{
$this->f = function () {
return $this->abcdefghijklmnopqrstuvwxyz(...func_get_args());
};
}
Related
I'am trying to make a reference to a static function inside a class:
class Test {
function __construct() {
$this->fn1 = self::fn2;
}
public static function fn2() {
}
}
then i get this error:
Undefined class constant 'fn2'
why?
Not sure if this is what you want, but at least this might give you a hint:
<?php
class Test {
function __construct() {
$this->fn = function(){
return self::realFn();
};
}
public function callFn (){
$fn = $this->fn ;//yes, assigning to a var first is needed. You could also use call_user_func
$fn();
}
public static function realFn() {
echo 'blah';
}
}
$x = new Test();
$x->callFn();
You can test it here: https://3v4l.org/KVohi
You have defined a static function:
Test {
function__construct()
{
$this->fn1 = self::fn2();
}
public static function fn2()
{
}
}
Updated
If you want to assign a function to a variable, it is best to do this
with annonymous aka lambda functions since they are first class citizens and may be freely passed, returned and assigned. PHP is not unique in dealing with static method references in this fashion as JAVA implements them similarly:
Method references ... are compact, easy-to-read lambda expressions for
methods that already have a name.
You may create an anonymous function based on a callable in PHP, and so the OP may wish to do as follows, which PHP 7.1.10 or higher supports:
<?php
class Test {
public static function fn2() {
return __METHOD__;
}
public static function getClosure (){
return Closure::fromCallable(["Test","fn2"]);
}
}
echo Test::getClosure()(),"\n";
See live code here
In this example an anonymous function is created and returned by the static getClosure method. When one invokes this method, then it returns the closure whose content is the same as static method fn2. Next, the returned closure gets invoked which causes the name of static method fn2 to display.
For more info re closures from callables, see the Manual and the RFC.
With PHP 7 on up, you may create a complex callable. In the code below the complex callable is an invocable array:
<?php
class foo
{
public static function test()
{
return [__CLASS__, 'fn2'];
}
public static function fn2()
{
echo __METHOD__;
}
}
echo foo::test()();
See live code.
Note: Starting with PHP 7.0.23 you could create a complex callable using a string containing the class and method names separated by the double colon aka paaamayim nekudotayim; see here.
A solution that has broader PHP support is as follows:
<?php
class Test {
public static function fn2() {
return __METHOD__;
}
public static function tryme(){
return call_user_func(["Test","fn2"]);
}
}
// return closure and execute it
echo Test::tryme();
See live code
Why some developers create one method that returns new static? What is the reason to have a method that returns new static? I am not asking what is the difference between static and self, or what static & self mean. For example, here is one simple class:
<?php
class Expression
{
public static function make()
{
return new static;
}
public function find($value)
{
return '/' . $value .'/';
}
public function then($value)
{
return $this->find($value);
}
public function hi($value)
{
return "hi";
}
}
As you can see, there is a static method make() which returns new static. Then, some developers call other methods like this:
$regex = Expression::make()->find('www');
What is the purpose of this? I see that here we don't use new Expression syntax, and if that's the point - then why not make all methods static? What is the difference, what is the reason to have that one method that returns new static (while other methods are not static)?
new static instantiates a new object from the current class, and works with late static bindings (instantiates the subclass if the class was subclassed, I expect you understand that).
Having a static method on a class which returns a new instance of same is an alternative constructor. Meaning, typically your constructor is public function __construct, and typically it requires a certain bunch of parameters:
class Foo {
public function __construct(BarInterface $bar, array $baz = []) { ... }
}
Having an alternative constructor allows you to provide different defaults, or convenience shortcuts to instantiate this class without having to supply those specific arguments and/or for being able to provide different arguments which the alternative constructor will convert to the canonical ones:
class Foo {
public function __construct(BarInterface $bar, array $baz = []) { ... }
public static function fromBarString($bar) {
return new static(new Bar($bar));
}
public static function getDefault() {
return new static(new Bar('baz'), [42]);
}
}
Now, even though your canonical constructor requires a bunch of complex arguments, you can create a default instance of your class, which will probably be fine for most uses, simply with Foo::getDefault().
The canonical example in PHP for this is DateTime and DateTime::createFromFormat.
In your concrete example the alternative constructor doesn't actually do anything, so it's rather superfluous, but I expect that's because it's an incomplete example. If there's indeed an alternative constructor which does nothing other than new static, it's probably just meant as convenience syntax over (new Foo)->, which I find questionable.
Complete answer here
TLDR
get_called_class().
class A {
public static function get_self() {
return new self();
}
public static function get_static() {
return new static();
}
}
class B extends A {}
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A
echo get_class(B::get_self()); // A
echo get_class(B::get_static()); // B
When calling a method in the same class from within another method, is it better to use $this or to avoid it, or is there no difference at all?
One benefit I can see with using $this is that it is explicit. For example:
class A {
public function a() {
$x = $this->b();// or $x = b()
}
public function b() {
//
}
}
Unlike other languages, like C++ and C# and Java, to access a member property of a class in PHP, you must always use $this as a qualifier upon the property.
For example:
class Test {
public $myVariable;
public function __construct($a) {
$this->myVariable = $a;
// $myVariable doesn't exist, must always use $this-><*>
}
}
how do i call a static method from another method inside the same class?
$this->staticMethod();
or
$this::staticMethod();
self::staticMethod();
More information about the Static keyword.
Let's assume this is your class:
class Test
{
private $baz = 1;
public function foo() { ... }
public function bar()
{
printf("baz = %d\n", $this->baz);
}
public static function staticMethod() { echo "static method\n"; }
}
From within the foo() method, let's look at the different options:
$this->staticMethod();
So that calls staticMethod() as an instance method, right? It does not. This is because the method is declared as public static the interpreter will call it as a static method, so it will work as expected. It could be argued that doing so makes it less obvious from the code that a static method call is taking place.
$this::staticMethod();
Since PHP 5.3 you can use $var::method() to mean <class-of-$var>::; this is quite convenient, though the above use-case is still quite unconventional. So that brings us to the most common way of calling a static method:
self::staticMethod();
Now, before you start thinking that the :: is the static call operator, let me give you another example:
self::bar();
This will print baz = 1, which means that $this->bar() and self::bar() do exactly the same thing; that's because :: is just a scope resolution operator. It's there to make parent::, self:: and static:: work and give you access to static variables; how a method is called depends on its signature and how the caller was called.
To see all of this in action, see this 3v4l.org output.
This is a very late response, but adds some detail on the previous answers
When it comes to calling static methods in PHP from another static method on the same class, it is important to differentiate between self and the class name.
Take for instance this code:
class static_test_class {
public static function test() {
echo "Original class\n";
}
public static function run($use_self) {
if($use_self) {
self::test();
} else {
$class = get_called_class();
$class::test();
}
}
}
class extended_static_test_class extends static_test_class {
public static function test() {
echo "Extended class\n";
}
}
extended_static_test_class::run(true);
extended_static_test_class::run(false);
The output of this code is:
Original class
Extended class
This is because self refers to the class the code is in, rather than the class of the code it is being called from.
If you want to use a method defined on a class which inherits the original class, you need to use something like:
$class = get_called_class();
$class::function_name();
In the later PHP version self::staticMethod(); also will not work. It will throw the strict standard error.
In this case, we can create object of same class and call by object
here is the example
class Foo {
public function fun1() {
echo 'non-static';
}
public static function fun2() {
echo (new self)->fun1();
}
}
call a static method inside a class
className::staticFunctionName
example
ClassName::staticMethod();
I have a variable on the global scope that is named ${SYSTEM}, where SYSTEM is a defined constant. I've got a lot of classes with functions that need to have access to this variable and I'm finding it annoying declaring global ${SYSTEM}; every single time.
I tried declaring a class variable: public ${SYSTEM} = $GLOBALS[SYSTEM]; but this results in a syntax error which is weird because I have another class that declares class variables in this manner and seems to work fine. The only thing I can think of is that the constant isn't being recognised.
I have managed to pull this off with a constructor but I'm looking for a simpler solution before resorting to that.
EDIT
The global ${SYSTEM} variable is an array with a lot of other child arrays in it. Unfortunately there doesn't seem to be a way to get around using a constructor...
Ok, hopefully I've got the gist of what you're trying to achieve
<?php
// the global array you want to access
$GLOBALS['uname'] = array('kernel-name' => 'Linux', 'kernel-release' => '2.6.27-11-generic', 'machine' => 'i686');
// the defined constant used to reference the global var
define(_SYSTEM_, 'uname');
class Foo {
// a method where you'd liked to access the global var
public function bar() {
print_r($this->{_SYSTEM_});
}
// the magic happens here using php5 overloading
public function __get($d) {
return $GLOBALS[$d];
}
}
$foo = new Foo;
$foo->bar();
?>
This is how I access things globally without global.
class exampleGetInstance
{
private static $instance;
public $value1;
public $value2;
private function initialize()
{
$this->value1 = 'test value';
$this->value2 = 'test value2';
}
public function getInstance()
{
if (!isset(self::$instance))
{
$class = __CLASS__;
self::$instance = new $class();
self::$instance->initialize();
}
return self::$instance;
}
}
$myInstance = exampleGetInstance::getInstance();
echo $myInstance->value1;
$myInstance is now a reference to the instance of exampleGetInstance class.
Fixed formatting
You could use a constructor like this:
class Myclass {
public $classvar;
function Myclass() {
$this->classvar = $GLOBALS[SYSTEM];
}
}
EDIT: Thanks for pointing out the typo, Peter!
This works for array too. If assignment is not desired, taking the reference also works:
$this->classvar =& $GLOBALS[SYSTEM];
EDIT2: The following code was used to test this method and it worked on my system:
<?php
define('MYCONST', 'varname');
$varname = array("This is varname", "and array?");
class Myclass {
public $classvar;
function Myclass() {
$this->classvar =& $GLOBALS[MYCONST];
}
function printvar() {
echo $this->classvar[0];
echo $this->classvar[1];
}
};
$myobj = new Myclass;
$myobj->printvar();
?>
The direct specification of member variables can not contain any references to other variables (class {public $membervar = $outsidevar;} is invalid as well). Use a constructor instead.
However, as you are dealing with a constant, why don't you use php's constant or class constant facilities?
You're trying to do something really out-of-the-ordinary here, so you can expect it to be awkward. Working with globals is never pleasant, especially not with your dynamic name selection using SYSTEM constant. Personally I'd recommend you use $GLOBALS[SYSTEM] everywhere instead, or ...
$sys = $GLOBALS[SYSTEM];
... if you're going to use it alot.
You could also try the singleton pattern, although to some degree it is frowned upon in OOP circles, it is commonly referred to as the global variable of classes.
<?php
class Singleton {
// object instance
private static $instance;
// The protected construct prevents instantiating the class externally. The construct can be
// empty, or it can contain additional instructions...
protected function __construct() {
...
}
// The clone and wakeup methods prevents external instantiation of copies of the Singleton class,
// thus eliminating the possibility of duplicate objects. The methods can be empty, or
// can contain additional code (most probably generating error messages in response
// to attempts to call).
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Deserializing is not allowed.', E_USER_ERROR);
}
//This method must be static, and must return an instance of the object if the object
//does not already exist.
public static function getInstance() {
if (!self::$instance instanceof self) {
self::$instance = new self;
}
return self::$instance;
}
//One or more public methods that grant access to the Singleton object, and its private
//methods and properties via accessor methods.
public function GetSystemVar() {
...
}
}
//usage
Singleton::getInstance()->GetSystemVar();
?>
This example is slightly modified from wikipedia, but you can get the idea. Try googling the singleton pattern for more information
I'd say the first two things that stand out to me are:
You don't need the brackets around the variable name, you can simply do public $system or public $SYSTEM.
While PHP may not always require it it is standard practice to encapsulate non-numeric array indexes in single or double quotes in case the string you're using becomes a constant at some point.
This should be what you're looking for
class SomeClass {
public $system = $GLOBALS['system'];
}
You can also use class constants which would instead be
class SomeClass {
const SYSTEM = $GLOBALS['system'];
}
This can be referenced within the class with 'self::SYSTEM' and externally with 'SomeClass::SYSTEM'.