Помощь Узнать имя переменной

Статус
Закрыто для дальнейших ответов.

Den1xxx

Разрушитель (V)
Сообщения
126
Симпатии
69
Баллы
1 016
Здравствуйте.
Вот у меня к примеру есть код:
PHP:
$a = new b();
class b
{
    function __construct()
    {
        return true;
    }
}
Имеется ли какая-то возможность узнать внутри класса b(), какой переменной он присвоен в данный момент?
В данном примере класс b() инициализирован через $a, есть ли возможность вернуть название переменной, например, через метод __construct()?
 
возможно, Вы неправильно подходите к проектированию вашего прожекта
я ему о чем и говорил еще вначале поста. я бы еще понял, если бы у него был проект сделанный классически и он его хотел бы переписать упрощенным образом и после проверить скорость под капотом обоих. а так - сделать нечто, а потом сидеть и думать, а чего же оно так долго думает, из-за того что я напрогал или из-за того, что я намудрил.
 
Разве, что eval использовать, но это еще хуже.
В приведённом классе
как раз таки используется eval()

PHP:
        $exec = '
            class ' . $className . ' extends NyanORM {
                public function __construct() {
                  parent::__construct();
                   $this->tableName = "' . $notOrmTable . '";
                 }
             }';

        eval($exec); //automatic models generation
Раз такие вопросы возникают, значит, возможно, Вы неправильно подходите к проектированию вашего прожекта )
Я начинаю новый проект и задаю верхнюю планку. Если не получится так, то придется планку снижать.
Но я почему-то уверен, что что-нибудь придумается. Мы еще не копали предопределённые (встроенные в PHP) классы.
Мне не хотелось бы с этим торопиться: проект «для души», никто в шею не гонит.
И потом. Вопрос-то интересный. Если найдётся решение, то это похоже на выход сознания на новый уровень при медитации, это как новая ступень)
Вот уже 2 рабочих решения есть, может не оч понятных и быстрых, но рабочих.
Я код с перебором $GLOBAL не проверял. Но если идея в принципе рабочая, то можно как-то напрямую обращаться к элементу массива $GLOBAL, не используя foreach. Тогда это будет быстро работать.
 
Последнее редактирование:
Я код с перебором $GLOBAL не проверял. Но если идея в принципе рабочая, то можно как-то напрямую обращаться к элементу массива $GLOBAL, не используя foreach. Тогда это будет быстро работать.
Перебор по GLOBALS довольно быстро будет работать, вы не ощутите. Т.к. проверяются только типы и ссылки на объекты. Возможно is_object там даже лишнее это я написал.
Т.е: == проверяет свойства и значения, т.е. два сравниваемых объекта итерируются, а === проверяет являются ли операнды ссылками на один тот же объект. Т.к в PHP два объекта идентично равны, если это один тот же объект. Может быть более опытные участники меня поправят.
И потом. Вопрос-то интересный.
Вопрос-то интересный. Но что-то я не нашел и в других языках нативной возможности получить доступ к имени переменной, как вы хотите. В js нет, в питоне нет, в java вроде тоже нет.
Напишите разработчикам языка... Кто знает, может быть им идея понравится и в следующих версиях запилят то, что вы хотите))
 
Последнее редактирование:
Крч. Я смог реализовать то что ты именно хочешь, без eval (но работать будет только на 7.*)
PHP:
<?php

$h = Hipster::forum();

echo $h->get();

class Hipster
{
    public static function __callStatic($name, $arguments)
    {
        return new class($name, $arguments) extends NyanORM
        {
            public function __construct($name)
            {
                $this->tableName = $name;
            }
        };
    }
}

class NyanORM
{
    public function get()
    {
        return $this->tableName;
    }
}
 
Крч. Я смог реализовать то что ты именно хочешь, без eval (но работать будет только на 7.*)
PHP:
<?php

$h = Hipster::forum();

echo $h->get();

class Hipster
{
    public static function __callStatic($name, $arguments)
    {
        return new class($name, $arguments) extends NyanORM
        {
            public function __construct($name)
            {
                $this->tableName = $name;
            }
        };
    }
}

class NyanORM
{
    public function get()
    {
        return $this->tableName;
    }
}
+ за старания.

Но я хотел уйти от
PHP:
$articles = new Publications('articles');

Чтобы писать
PHP:
$articles = new Publications;
а в настройках само магически инициировалось, что это articles и считывался конфиг к примеру articles.ini

Конструкция
PHP:
$articles = Publications::articles();
пока ничем не выигрышней: название переменной дублируется и там и там.

Ну либо Вы мне на что-то ещё намекаете, а я этого не вижу, хз
:search:
 
Последнее редактирование:
+ за старания.

Но я хотел уйти от
PHP:
$articles = new Publications('articles');

Конструкция
PHP:
$articles = Publications::articles();
пока ничем не выигрышней: название переменной дублируется и там и там.

Ну либо Вы мне на что-то ещё намекаете, а я этого не вижу, хз
:search:
PHP:
$articles = UniClass::articles();
$category = UniClass::category();
$topics = UniClass::topics();
 
$articles = UniClass::articles(); $category = UniClass::category(); $topics = UniClass::topics();
Сие ничем не лучше, бро, чем $articles = new Publications('articles');

И чего так слабо извратились?

Вот как надо:
PHP:
$a = new b();
$bla_Bla123 = new b();

echo varName($a).'<br/>';
echo varName($bla_Bla123).'<br/>';

class b {

}

function varName($v) {
    $trace = debug_backtrace();
    $vLine = file( __FILE__ );
    $fLine = $vLine[ $trace[0]['line'] - 1 ];
    preg_match( "#\\$(\w+)#", $fLine, $match );
    return $match[1];
}
Но я уж лучше 2 раза название напишу, ну его нах)))
 
В принципе про это тебе с самого начала говорили.
Но мой класс, это просто элегантная реализация автозагрузки от nightflyza
Ну а если тебя напрягает наименование класса, сделай его коротким a::forum()
 
В принципе про это тебе с самого начала говорили.
Но мой класс, это просто элегантная реализация автозагрузки от nightflyza
Ну а если тебя напрягает наименование класса, сделай его коротким a::forum()
Если рассматривать эти вещи в этом контексте, то так вроде бы красивей и «магичнее».
Правда Ростиславу этот код бесполезен. У него легаси тянется с PHP 5.3, так что он даже массивы нигде квадратными скобками не инициирует.
Абстрагируясь же от nightflyza, скажу, что Ваша реализация хороша, Вы молодец)))
 
Эврика!
До меня дошло, что при инициализации объекта нельзя узнать имя переменной, т.к. этой переменной ещё не существует.
Можно узнать только позже строкой, а это уже не то.

Зато можно сделать проще, через функцию! Например, инициация модуля статей выглядеть может так:
PHP:
init_magic('articles');
Просто и без повторов.
А внутри функции уже создавать объект и прочее.

Пример магической магии:
PHP:
function init_magic($obj) {
    global $$obj;
    $$obj = new Magic($obj);
}

class Magic {
    var $module = '';
    function __construct ($obj) {
        $this->module = $obj;
    }
}

init_magic('articles');
init_magic('shop');
echo $articles->module.'<br/>';
echo $shop->module.'<br/>';
echo PHP_VERSION;
/* Output:
articles
shop
5.3.27
*/
Думаю, раз в PHP 5.3 работает, так и уж в текущих популярных тоже будет)
 
Всю магию и лаконичность убивает global. Использовать global в данный момент это моветон.
Но на вскус и цвет все фломастеры разные.
 
Всю магию и лаконичность убивает global. Использовать global в данный момент это моветон.
Но на вскус и цвет все фломастеры разные.
Есть немного. Но как лучше сделать, пока не придумалось. Суперглобальный массив $GLOBALS испоользовать ещё хуже: в 8 версии он вообще ридонли.
 
Есть немного. Но как лучше сделать, пока не придумалось. Суперглобальный массив $GLOBALS испоользовать ещё хуже: в 8 версии он вообще ридонли.
Я бы через мультитон реализовал. И тогда вообще переменная нафиг не нужна. Единственное лишних четыре символа каждый раз писать. Но это уже экономить на спичках.
_::forum()->get()
При этом не нужно беспокоиться о самой инициализации, она будет автоматическая, а не вручную как в твоём случае.
 
Я бы через мультитон реализовал.
Собственно это что-то вроде мультитона и получилось. Объект того же типа, а доступ к его настройкам по ключу.
При этом не нужно беспокоиться о самой инициализации, она будет автоматическая, а не вручную как в твоём случае.
Ну у меня тоже автоматическая же. В модуле инициализация объекта получится очень простой, через вызов магической функции:
PHP:
init_magic('articles');
И получится то же самое, как если бы я написал:
PHP:
$articles=new Magic('articles');
Собственно никто не запрещает писать и так, и так.
Кстати функцию можно сделать совсем короткой, например create('articles'); или даже born('articles');
Сам класс и функция инициализации будет в АПИ, в модуле только вызов функции и всё.
Проблема в моем варианте только в неоправданном засирании глобальной области видимости.
Возможно, если сделать строго как мультитон (т.е. инициализация по ключу если объекта нет и создание его, если он есть), то и засирание глобальной области будет уже не проблема, т.к. нельзя будет дважды создать объект с одинаковым ключом.
Надо подумать.
 
Как по мне, но так лаконичнее, и не нужно помнить про инициализацию init_magic.
Т.е. просто берешь и вызываешь в любо месте.
PHP:
<?php

class _
{
    private static $instances = [];

    public static function __callStatic($name, $arguments)
    {
        if (!array_key_exists($name, self::$instances)) {
            self::$instances[$name] = new Magic($name, $arguments);
        }

        return self::$instances[$name];
    }

    private function __construct()
    {
    }

    private function __clone()
    {
    }

    private function __wakeup()
    {
    }
}

class Magic
{
    public $module = '';

    function __construct($obj, $arg)
    {
        $this->module = $obj;
    }
}

//init_magic('articles');
//init_magic('shop');

//echo $articles->module.'<br/>';
//echo $shop->module.'<br/>';
echo _::articles()->module . '<br/>';
echo _::shop()->module . '<br/>';
 
Autoloader + Namespace (как и говорилось выше). Если все порождено от одной абстракции и интерфейса (с обязательной реализацией одних и тех же методов). И дальше будет: use \Articles\Publication as Publication; или же use \Forum\Publication as Publication; а порождение объектов всегда будет new Publication(); да и все. Что там породилось - instanceof на проверку/get_class внутри (последним можете сразу писать в переменную имя породившего класса и возвращать, если не уверены. Вы изобретаете функциональную фабрику классов? Или фасад?
 
Вы изобретаете функциональную фабрику классов? Или фасад?
Я пытаюсь понять, как можно внутри функции или класса узнать имя переменной, которая инициировала эту функцию/класс.
И как сделать это проще для понимания и меньшим количеством символов. См. первоначальный вопрос.
 
Дополнение
Попробовал с $GLOBALS создать переменную под PHP 8.0 — успешно.
Слухи, что это не будет работать, видимо, преувеличены.
Screenshot 2021-12-09 at 08-44-23 PHP tester online.png
 
Я пытаюсь понять, как можно внутри функции или класса узнать имя переменной, которая инициировала эту функцию/класс.
И как сделать это проще для понимания и меньшим количеством символов. См. первоначальный вопрос.
Так я и говорю: спасает namespace. И внутри namespace Ты можешь всегда вернуть get_class в объекте класса. Твою проблему решает шаблон проектирования Фабрика классов и наследование от единого интерфейса.
 
Твою проблему решает шаблон проектирования Фабрика классов и наследование от единого интерфейса.
К сожалению, не знаю такого шаблона «Фабрика классов». Наследование от единого интерфейса вообще имхо не при делах. При таком раскладе мне вместо генерации 1 класса, но с разными ключами, придется создавать и описывать каждый класс по отдельности.
Меня больше устраивает один класс, но с разными ключами. Как правильно заметил @CAPAXA — это похоже больше на мультитон.
 
Статус
Закрыто для дальнейших ответов.
Назад
Верх