How to Define Persistent Constants in a PHP 7.x Extension

This article explains step‑by‑step how to add, register, and correctly clean up persistent constants in a PHP 7.x extension, covering the necessary macro calls, hash‑destroy functions, and a common fatal‑error pitfall with its solution.

21CTO
21CTO
21CTO
How to Define Persistent Constants in a PHP 7.x Extension

In PHP extensions you can define constants just like in scripts, but the process differs when you need persistent constants that survive across requests. This guide shows how to add three constants—an array, a string, and a namespaced string—inside the PHP_MINIT_FUNCTION of a custom say extension.

Adding the code

// destroy a hash table
static void say_hash_destroy(HashTable *ht) {
    zend_string *key;
    zval *element;
    if ((ht->u.flags & HASH_FLAG_INITIALIZED)) {
        ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, element) {
            if (key) {
                free(key);
            }
            switch (Z_TYPE_P(element)) {
                case IS_STRING:
                    free(Z_PTR_P(element));
                    break;
                case IS_ARRAY:
                    say_hash_destroy(Z_ARRVAL_P(element));
                    break;
            }
        } ZEND_HASH_FOREACH_END();
        free(HT_GET_DATA_ADDR(ht));
    }
    free(ht);
}

// destructor for persistent entries
static void say_entry_dtor_persistent(zval *zvalue) {
    if (Z_TYPE_P(zvalue) == IS_ARRAY) {
        say_hash_destroy(Z_ARRVAL_P(zvalue));
    } else if (Z_TYPE_P(zvalue) == IS_STRING) {
        zend_string_release(Z_STR_P(zvalue));
    }
}

PHP_MINIT_FUNCTION(say) {
    zend_constant c;
    zend_string *key;
    zval value;

    ZVAL_NEW_PERSISTENT_ARR(&c.value);
    zend_hash_init(Z_ARRVAL(c.value), 0, NULL, (dtor_func_t)say_entry_dtor_persistent, 1);
    add_index_long(&c.value, 0, 2);
    key = zend_string_init("site", 4, 1);
    ZVAL_STR(&value, zend_string_init("www.bo56.com", 12, 1));
    zend_hash_update(Z_ARRVAL(c.value), key, &value);
    c.flags = CONST_CS|CONST_PERSISTENT;
    c.name = zend_string_init("__ARR__", 7, 1);
    c.module_number = module_number;
    zend_register_constant(&c);

    REGISTER_STRINGL_CONSTANT("__SITE__", "www.bo56.com", 12, CONST_PERSISTENT);
    REGISTER_NS_STRINGL_CONSTANT("say", "__SITE__", "bo56.com", 8, CONST_CS|CONST_PERSISTENT);
    return SUCCESS;
}

PHP_MSHUTDOWN_FUNCTION(say) {
    zval *val = zend_get_constant_str("__ARR__", 7);
    say_hash_destroy(Z_ARRVAL_P(val));
    ZVAL_NULL(val);
    return SUCCESS;
}

Code explanation

Only a few constant types (null, bool, long, double, string) are supported by the kernel; the macros for defining them reside in Zend/zend_constants.h. For strings you can use REGISTER_STRINGL_CONSTANT, and for namespaced strings the macro REGISTER_NS_STRINGL_CONSTANT where the first argument is the namespace.

The last parameter of these macros contains flags: CONST_PERSISTENT makes the constant live in persistent memory, and CONST_CS makes it case‑sensitive. Note the case difference between the defined name __SITE__ and the lookup name __site__.

Common error and fix

When the extension is unloaded, Zend’s internal destructor tries to free the persistent array and reports a fatal error:

Fatal error: Internal zval 's can’t be arrays, objects or resources

. The fix is to manually destroy the array in PHP_MSHUTDOWN_FUNCTION before Zend’s destructor runs, as shown in the shutdown code above.

After applying this change, the extension compiles and runs without the fatal error, and the defined constants are available throughout the request lifecycle.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PHPExtension DevelopmentConstantspersistent
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.