Получите идентификатор экземпляра объекта в PHP

Я имею, узнают только что на StackOverflow, что мы можем получить "идентификатор экземпляра" любого ресурса, например:

var_dump(intval(curl_init()));  // int(2)
var_dump(intval(finfo_open())); // int(3)
var_dump(intval(curl_init()));  // int(4)
var_dump(intval(finfo_open())); // int(5)
var_dump(intval(curl_init()));  // int(6)

Я нуждаюсь в чем-то подобном, но обратился к классам:

class foo {
    public function __construct() {
        ob_start();
        var_dump($this); // object(foo)#INSTANCE_ID (0) { }
        echo preg_replace('~.+#(\d+).+~s', '$1', ob_get_clean());
    }
}

$foo = new foo();  // 1
$foo2 = new foo(); // 2

Вышеупомянутые работы, но я надеялся на более быстрое решение или, по крайней мере, то, которое не включило буферы вывода. Обратите внимание на то, что это будет не обязательно использоваться в конструкторе или даже в самом классе!

spl_object_hash() не то, что я ищу, потому что два объекта производят идентичные хеши

Вопрос ранее содержал неправильный пример spl_object_hash вывод; обеспечение, чтобы оба объекта существовали одновременно, производит хеши, которые тонко отличаются:

var_dump(spl_object_hash($foo));  // 0000000079e5f3b60000000042b31773
var_dump(spl_object_hash($foo2)); // 0000000079e5f3b50000000042b31773

Кастинг к интервалу как ресурсы, кажется, не работает на объекты:

Уведомление: Объект нечто класса не мог быть преобразован в интервал.

Существует ли быстрый способ захватить тот же вывод, не используя свойства объектов?

Кроме того, var_dump(), Я обнаружил методом проб и ошибок это debug_zval_dump() также производит экземпляр объекта, к сожалению, он также должен произвести буферизацию, так как он не возвращает результат.

28
задан Community 23 May 2017 в 11:46
поделиться

7 ответов

spl_object_hash () может вам помочь. Он

возвращает уникальный идентификатор объекта

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

ИЗМЕНИТЬ после комментария OP:

Вы можете реализовать такое поведение, используя свойство статического класса, например:

class MyClass 
{
    private static $_initialized = false;

    public function __construct()
    {
        if (!self::$_initialized) {
            self::$_initialized = true;
            // your run-only-once code 
        }
    }
}

Но на самом деле это не имеет ничего общего с вашим исходным вопросом.

34
ответ дан 28 November 2019 в 02:55
поделиться

Взгляните на spl_object_hash () . Пример использования:

$id = spl_object_hash($object);

Обратите внимание, что для работы вам потребуется PHP 5> = 5.2.0.

3
ответ дан 28 November 2019 в 02:55
поделиться

У меня нет включенного пакета запуска PECL, чтобы проверить это, но это может позволить вам удалить код конструктора из определения класса после первого создания экземпляра класса. .

Можно ли удалить конструктор из конструктора, было бы интересным экспериментом.

0
ответ дан 28 November 2019 в 02:55
поделиться

Ну да, с расширением.

Обратите внимание, что дескрипторы, используемые для объектов, которые тем временем были уничтожены, можно использовать повторно.

Сборка с помощью phpize && ./configure && make && make install

testext.h

#ifndef PHP_EXTTEST_H
# define PHP_EXTTEST_H
# ifdef HAVE_CONFIG_H
#  include<config.h>
# endif
# include <php.h>
extern zend_module_entry testext_module_entry;
#define phpext_testext_ptr &testext_module_entry
#endif

testext.c

#include "testext.h"

PHP_FUNCTION(get_object_id)
{
    zval *obj;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj)
            == FAILURE) {
        return;
    }

    RETURN_LONG(Z_OBJ_HANDLE_P(obj));
}

static zend_function_entry ext_functions[] = {
    PHP_FE(get_object_id, NULL)
    {NULL, NULL, NULL, 0, 0}
};

zend_module_entry testext_module_entry = {
    STANDARD_MODULE_HEADER,
    "testext",
    ext_functions, /* Functions */
    NULL, /* MINIT */
    NULL, /* MSHUTDOWN */
    NULL, /* RINIT */
    NULL, /* RSHUTDOWN */
    NULL, /* MINFO */
    NO_VERSION_YET,
    STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(testext)

config.m4

PHP_ARG_ENABLE(testext,
  [Whether to enable the "testext" extension],
  [  enable-testext         Enable "testext" extension support])

if test $PHP_EXTTEST != "no"; then
  PHP_SUBST(EXTTEST_SHARED_LIBADD)
  PHP_NEW_EXTENSION(testext, testext.c, $ext_shared)
fi

Тестовый скрипт

<?php
$a = new stdclass();
$b = new stdclass();
var_dump(get_object_id($a));
var_dump(get_object_id($b));

Вывод

int(1)
int(2)
19
ответ дан 28 November 2019 в 02:55
поделиться

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

class MyBase
{
    protected static $instances = 0;
    private $_instanceId  = null;
    public function getInstanceId()
    {
        return $this->_instanceId;
    }

    public function __construct()
    {
        $this->_instanceId = ++self::$instances;
    }
}

class MyTest extends MyBase
{
    public function Foo()
    {
        /* do something really nifty */
    }
}

$a = new MyBase();
$b = new MyBase();

$c = new MyTest();
$d = new MyTest();


printf("%d (should be 1) \n", $a->getInstanceId());
printf("%d (should be 2) \n", $b->getInstanceId());
printf("%d (should be 3) \n", $c->getInstanceId());
printf("%d (should be 4) \n", $d->getInstanceId());

Результатом будет:

1 (should be 1) 
2 (should be 2) 
3 (should be 3) 
4 (should be 4) 
1
ответ дан 28 November 2019 в 02:55
поделиться

Если вы не хотите использовать буферизацию вывода ... возможно, используйте var_export вместо var_dump ?

0
ответ дан 28 November 2019 в 02:55
поделиться

То, что вы пытаетесь сделать, на самом деле является аспектно-ориентированным программированием (АОП).

На данный момент существует как минимум пара фреймворков для АОП в PHP:

  • Seasar (ранее PHPaspect) - это более крупный фреймворк, интегрируемый с Eclipse - на снимке экрана показан небольшой фрагмент кода, который отвечает на ваши вопросы. вопрос, сплетая некоторый код вокруг определенного нового оператора на протяжении всего проекта.
  • php-aop - это облегченная структура для АОП.
  • typo3 имеет встроенный фреймворк АОП.

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

Такие языки, как PHP, были разработаны для решения задач программирования - концепция APO была разработана для решения задач программиста . Когда обычно вам нужно думать о том, как обеспечить выполнение определенной задачи каждый раз в вашей кодовой базе, вы можете думать об этом как о просто «аспекте» того, как вы программируете, реализовать его напрямую в этих терминах и посчитать о ваших проблемах, которые будут реализованы каждый раз.

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

В любом случае может стоить 5 минут вашего времени; -)

Удачи!

1
ответ дан 28 November 2019 в 02:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: