Как я могу получить доступ к статическим членам класса, используя $this? [дубликат]


Я пытаюсь получить доступ к статическим членам класса класса ActiveModel в другом классе.

$class = "\ActiveModel\User";
$class::create(); //WORKS!

$this->class = "\ActiveModel\User";
$this->class::create(); //DOESN'T WORK :( - Throws "Incorrect access to static class member" error

Как правильно получить к нему доступ с помощью $this->var?

Другой пример: enter image description here

Author: Adrian Cid Almaguer, 2015-03-15

3 answers

Вы не можете сделать что-то вроде $this->class::create(). Если вы хотите получить доступ к статическому члену, вы должны использовать Class::Member. Текущая реализация синтаксического анализатора Zend PHP поддерживает только статические вызовы методов, которые выполняются непосредственно с именем класса или переменной. Вот грамматика:

%token T_PAAMAYIM_NEKUDOTAYIM ":: (T_PAAMAYIM_NEKUDOTAYIM)"

function_call:
    name argument_list
        { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); }
|   class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
        { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); }
|   variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
        { $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); }
|   callable_expr argument_list
        { $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); }

Объявление свойств или методов класса статическими делает их доступными без необходимости создания экземпляра класса. Свойство, объявленное как статическое, не может быть доступно с помощью экземпляра объекта класса (хотя статический метод может).

Поскольку статические методы могут вызываться без экземпляра созданного объекта, псевдопеременная $this недоступна внутри метода, объявленного как статический.

Статические свойства не могут быть доступны через объект с помощью оператора стрелки ->.

Пример статического свойства

<?php
class Foo
{
    public static $my_static = 'foo';

    public function staticValue() {
        return self::$my_static;
    }
}

class Bar extends Foo
{
    public function fooStatic() {
        return parent::$my_static;
    }
}


print Foo::$my_static . "\n";

$foo = new Foo();
print $foo->staticValue() . "\n";
print $foo->my_static . "\n";      // Undefined "Property" my_static 

print $foo::$my_static . "\n";
$classname = 'Foo';
print $classname::$my_static . "\n"; // As of PHP 5.3.0

print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";
?>

Пример статического метода

<?php
class Foo {
    public static function aStaticMethod() {
        // ...
    }
}

Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
?>

Подробнее читайте по адресу:

Http://php.net/manual/en/language.oop5.static.php

Вызов статического метода с именем класса, сохраненным в качестве переменной экземпляра

Https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L890

 4
Author: Adrian Cid Almaguer, 2017-05-23 11:54:05

Язык PHP запрещает такого рода конструкции. Есть и другие примеры. (например, ранее вы не могли напрямую обращаться к массиву, возвращаемому функцией)

$elem = get_array()[0] // Doesn't work until PHP 5.4.0

Основная причина этих ограничений заключается в том, что синтаксическому анализатору это не нравится. Потому что они сложны, или вызывают двусмысленность, или они хотят зарезервировать такие конструкции для будущего использования.

Вы можете просто обойти это ограничение, назначив временную переменную:

$className = $this->class;
$className::create(); // This will work.
 4
Author: Tippisum, 2015-03-15 07:19:08

Потому что PHP не поддерживает такого рода оценку до версии 5.6.2 (Похоже, что более новые версии все еще не поддерживают ее).

Если вам действительно нужно это сделать, несмотря ни на что, используйте call_user_func() или call_user_func_array() вот так:

call_user_func_array(
    array(
        $this->modalClassName, 
        'create'
    ), 
    array()
);

И добавьте метод setHasMany для вашего модального класса с помощью

call_user_func_array(
    array(
        $this->modalClassName, 
        'setHasMany'
    ), 
    array(['user_level'])
);

Вместо прямой установки переменной $hasmany.

Хотя я бы не рекомендовал этого делать. Вы можете попробовать что-то вроде Внедрения зависимостей для подобных случаев.

 2
Author: NICK, 2015-03-20 10:11:43