Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange error after migration to Phalcon 3.0.0 #12056

Open
vekyapps opened this issue Jul 30, 2016 · 163 comments

Comments

Projects
None yet
@vekyapps
Copy link

commented Jul 30, 2016

Hello,

yesterday, I migrated my project to Phalcon 3.0 (from 2.1 version). And everything worked fine, except now I got very "randomly" this error:

Fatal error: Uncaught Error: Access to undeclared static property: Phalcon\Di::$_default in C:\xampp-php7-0\htdocs\aplikacija\app\config\services.php:25 Stack trace:
#0 [internal function]: Phalcon\Di->__construct()
#1 C:\xampp-php7-0\htdocs\aplikacija\app\config\services.php(25): Phalcon\Di\FactoryDefault->__construct()
#2 C:\xampp-php7-0\htdocs\aplikacija\public\index.php(25): include('C:\\xampp-php7-0...')
#3 {main}

Next Error: Access to undeclared static property: Phalcon\Di::$_default in C:\xampp-php7-0\htdocs\aplikacija\app\config\services.php:25 Stack trace:
#0 [internal function]: Phalcon\Di->__construct()
#1 C:\xampp-php7-0\htdocs\aplikacija\app\config\services.php(25): Phalcon\Di\FactoryDefault->__construct()
#2 C:\xampp-php7-0\htdocs\aplikacija\public\index.php(25): include('C:\\xampp-php7-0...')
#3 {main} thrown in C:\xampp-php7-0\htdocs\aplikacija\app\config\services.php on line 25

On line 25 in my services.php file is where I create instance of DI factory class:

$di = new FactoryDefault();   ( this is line 25 - error line!)
$di->setShared('config', function () use ($config) {
    return $config;
});

I work on Windows, Xampp v3.2.2 with PHP 7.0.8 and Phalcon 3.0.

Can you help me with this?

Thanks in advance!

@Jurigag

This comment has been minimized.

Copy link
Member

commented Jul 31, 2016

My only guess it's beacause of windows perhaps ? Works on vagrant/ubuntu 14.04 without any problem.

@Studentsov

This comment has been minimized.

Copy link
Contributor

commented Jul 31, 2016

What is $config?

@googlle

This comment has been minimized.

Copy link
Contributor

commented Jul 31, 2016

Hello.
I have the same error

Fatal error: Uncaught Error: Access to undeclared static property: Phalcon\Di::$_default in C:\xamppwin\htdocs\phalcon\app\config\services.php:6 Stack trace:
#0 [internal function]: Phalcon\Di->__construct()
#1 C:\xamppwin\htdocs\phalcon\app\config\services.php(6): Phalcon\Di\FactoryDefault->__construct()
#2 C:\xamppwin\htdocs\phalcon\public\index.php(21): require('C:\\xamppwin\\htd...')
#3 {main}

Next Error: Access to undeclared static property: Phalcon\Di::$_default in C:\xamppwin\htdocs\phalcon\app\config\services.php:6 Stack trace:
#0 [internal function]: Phalcon\Di->__construct()
#1 C:\xamppwin\htdocs\phalcon\app\config\services.php(6): Phalcon\Di\FactoryDefault->__construct()
#2 C:\xamppwin\htdocs\phalcon\public\index.php(21): require('C:\\xamppwin\\htd...')
#3 {main} thrown in C:\xamppwin\htdocs\phalcon\app\config\services.php on line 6
//services.php line 6
$di = new \Phalcon\DI\FactoryDefault();
@Studentsov

This comment has been minimized.

Copy link
Contributor

commented Jul 31, 2016

This is a really strange error. I am using Phalcon 3 on Windows 10, PHP 7.0.8 x64, and similar errors do not occur.

@googlle

This comment has been minimized.

Copy link
Contributor

commented Jul 31, 2016

Try to reload the page many times and the error should appear

@Jurigag

This comment has been minimized.

Copy link
Member

commented Jul 31, 2016

Are you using maybe opcache ? Try to check it disabled for instance.

@andresgutierrez

This comment has been minimized.

Copy link
Contributor

commented Aug 1, 2016

This seems to be affecting only Windows installations, I'll have to set up a Windows environment to check

@toddlxt

This comment has been minimized.

Copy link

commented Aug 1, 2016

I have the same error.
My env: Win 10 x64 + Apache 2.4.23 + PHP 7.0.9 x64 ZTS.
Also tried Apache 2.4.18, PHP 7.0.8 x86 ZTS, PHP 7.0.8 x64 ZTS.
This error only happens when a lot of requests come.
Just create an "index.php" with 2 lines:

use Phalcon\Di\FactoryDefault;
$di = new FactoryDefault();

And keep refreshing this page or use apache ab.exe:
ab -n 100 -c 10 "http://localhost/index.php"
Then you can see this error in php_error.log.

Update:
I tried nginx+php and php cli mode(5.6.19, 7.0.8, 7.0.9), no error appeared. I think this only affects apache+php.

@Jurigag

This comment has been minimized.

Copy link
Member

commented Aug 1, 2016

As i wrote, did you have opcache enabled ? Can you disable it for instance ?

@MitchellMacpherson

This comment has been minimized.

Copy link

commented Aug 1, 2016

I've also got the same issue with WAMP3, (Which uses Apache) PHP 7.0.4 (TS).
Haven't checked if opcode caching is enabled by default, and I haven't tried compiling Phalcon myself yet, but I'll try it tonight and see if it makes a difference.

@toddlxt

This comment has been minimized.

Copy link

commented Aug 1, 2016

@Jurigag After I set opcache.enable=0 in php.ini and restarted apache, I still got this error.
In phpinfo():

Opcode Caching  |   Disabled
Optimization    |   Disabled
SHM Cache       |   Enabled
File Cache      |   Disabled

Do you need me to do more tests?

Update:
I set opcache.enable=1 to enable opcache, still got the error.

@Jurigag

This comment has been minimized.

Copy link
Member

commented Aug 1, 2016

No, i just thought it might be opcache, but looks like not.

@stamster

This comment has been minimized.

Copy link
Contributor

commented Aug 1, 2016

Yet another Window$ dev environment with strange behaviour.

I wouldn't consider this as a bug unless the issue can be reproduced on production system (i.e. GNU/Linux).

IMHO, just like Phalcon 3.0.0 has dropped support for Oracle RDBMS due to the noted reasons, same should have happened with DLL / Microsoft support.

@andresgutierrez

This comment has been minimized.

Copy link
Contributor

commented Aug 1, 2016

@stamster why?

@Jurigag

This comment has been minimized.

Copy link
Member

commented Aug 1, 2016

@stamster well, more interesting is that @Studentsov don't have this problem ? :D

Sometimes people just want to use phalcon on their dev enviroment without using any virutal machine.

@Studentsov

This comment has been minimized.

Copy link
Contributor

commented Aug 3, 2016

For example, I prefer to program in Windows because switching PHP versions, web servers and DBMS I make one click. Isn't that progress? :D
Seriously, I am aware of the possible differences of behaviour, so always spend additional testing on a production-like environment.
Error when using PHP 7 with Apache I have neither...

@Jurigag

This comment has been minimized.

Copy link
Member

commented Aug 3, 2016

Studentsov - i make the same on linux:

phpbrewswitch 7.0.5
phpbrewswitch 5.6.19

Just phpbrew and proper script.

@makerlabs

This comment has been minimized.

Copy link
Contributor

commented Aug 6, 2016

http://stackoverflow.com/questions/38235349/fatal-error-access-to-undeclared-static-property-phalcon-di-default-pub
owncloud/core#22370
Definitely something not related to the framework but the PHP or PHP setup I guess

@pedro151

This comment has been minimized.

Copy link

commented Aug 24, 2016

same error occurs in:
Phalcon version:3.0.0
PHP Version:7.0.10
Operating System:Windows 10 / Apache 2.4 x86 (php7_module) / PHP 7.0.10 x86

@Jurigag

This comment has been minimized.

Copy link
Member

commented Aug 24, 2016

As you see above it's not phalcon problem really.

@pedro151

This comment has been minimized.

Copy link

commented Aug 24, 2016

what is the solution for this error?

@Jurigag

This comment has been minimized.

Copy link
Member

commented Aug 24, 2016

Don't use windows xD And/or apache php7 module. Try maybe using fpm and check if it works ?

@david-duncan

This comment has been minimized.

Copy link

commented Aug 24, 2016

Also don't develop in an environment that is not like your production environment unless you want issues

@Jurigag

This comment has been minimized.

Copy link
Member

commented Aug 24, 2016

Actually you can write code in windows - just use vagrant/docker.

@MitchellMacpherson

This comment has been minimized.

Copy link

commented Aug 24, 2016

If Phalcon didn't want to support developers on the Windows platform, they wouldn't compile the PHP module for Windows environments.
So the solution of "Don't use windows" doesn't really apply unless Phalcon completely drops Windows support, which by extension should/would only happen if Zephir dropped Windows support?

@andresgutierrez

This comment has been minimized.

Copy link
Contributor

commented Aug 24, 2016

@Mechzeit That is @Jurigag 's opinion, it's not the official position about Windows, of course this must be fixed

@AlexanderSk

This comment has been minimized.

Copy link

commented Jan 14, 2019

Hi, i can confirm i got it working with latest wamp 64 bit with php7.2.14nts
download from apache mod_fcgid place it in apache/modules folder
also download phalcon nts for your php and...

On http.conf set (wamp wont start without php7apache enabled for some reason):
LoadModule php7_module "${INSTALL_DIR}/bin/php/php7.2.13/php7apache2_4.dll"

LoadModule fcgid_module modules/mod_fcgid.so

FcgidInitialEnv PHPRC "${INSTALL_DIR}/bin/php/php7.2.14nts/"
FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 1000
FcgidMaxRequestsPerProcess 1000
FcgidMaxProcesses 15
FcgidIOTimeout 120
FcgidIdleTimeout 120
AddType application/x-httpd-php .php
MaxRequestLen 314572800

    <Files ~ "\.php$>"
      Options +Indexes +Includes +FollowSymLinks +MultiViews +ExecCGI
      AddHandler fcgid-script .php
      FcgidWrapper  "${INSTALL_DIR}/bin/php/php7.2.14nts/php-cgi.exe"  .php
    </Files>
@sergeyklay

This comment has been minimized.

Copy link
Member

commented Feb 21, 2019

Could someone help us here phalcon/zephir#1530 (comment)
We want to reproduce this bug but I have no ide how to do it without Apache installation

@metaliciouz

This comment has been minimized.

Copy link
Contributor

commented Feb 26, 2019

@sergeyklay, Is this problem specific only to this apache server?

@vymc

This comment has been minimized.

Copy link

commented Mar 9, 2019

Hi, again, GOOD NEWS about these errors, Phalcon 3.4.2 on XAMPP completely works without any errors if your MVC bootstrap DI use with built in classes, e.g phalcon Router, Dispatcher and not yours extended router...
When i extend e.g Phalcon\Mvc\Tag my apps work superslowly or sometimes i get on browser "did not send any data..." or Fatal error: Uncaught Error: Access to undeclared static property: Phalcon\Di::$_default.
Solution was found, using components or DI custom services when accesing PHALCON, because you 100% still can access PHALCON MVC built in objects.
When you coding with framework is become buggy framework if you extending core classes :)

`
//its bad coding when u owerwriting built in functions using PHALCON property access.
class Tag extends Phalcon\Mvc\Tag
{
public static function setTitle($title)
{
/* dont do this*/ self::$_documentTitle = $title;
}
}

$di->set('tag', Tag::class)

// this is better logic
class MyTag extends Component
{
public static function setTitle($title)
{
Phalcon\Mvc\Tag::setTitle($title);
}
}
`
Why exists Component, Plugin abstracts and are you using theses classes right way?

@vymc

This comment has been minimized.

Copy link

commented Mar 9, 2019

Untitled-1

@stamster

This comment has been minimized.

Copy link
Contributor

commented Mar 11, 2019

@vymc that is not a solution but yet another hacky workaround (if any). Just stop using XAMPP and such stuff. Install real VM/server and forget about Windows and the issue is resolved.

@metaliciouz

This comment has been minimized.

Copy link
Contributor

commented Mar 11, 2019

@vymc that is not a solution but yet another hacky workaround (if any). Just stop using XAMPP and such stuff. Install real VM/server and forget about Windows and the issue is resolved.

It is not Windows problem.

@dreamsxin

This comment has been minimized.

Copy link
Member

commented Apr 16, 2019

Use lasted zephir regenerate code

git clone https://github.com/phalcon/zephir.git
git fetch origin
git checkout origin/development -f

cd cphalcon-3.4
../zephir/zephir fullclean
../zephir/zephir generate
cd ext/
make -j4 && make install
``
@zhaoyanliang2

This comment has been minimized.

Copy link

commented May 13, 2019

This issue is a thread-safe bug, all internal classes with static member variables can trigger this bug.
The internal classes are shared between different threads and their static member variables are not shared, so their static member variables are stored in CG(static_members_table) and not in zend_class_entry::static_members_table. Static member variables are lazy initialized when the internal class is about to be used for the first time.
https://github.com/php/php-src/blob/05fb10165081cb4fb55a9943b44cab62c627db7a/Zend/zend_API.c#L1090
zend_update_class_constants() will mark the internal class with ZEND_ACC_CONSTANTS_UPDATED. If one thread have called zend_update_class_constants() with Phalcon\Di, Phalcon\Di's static member variables have been initialized, and Phalcon\Di's ce_flags has been marked with ZEND_ACC_CONSTANTS_UPDATED. In another thread Phalcon\Di's ce_flags has been marked with ZEND_ACC_CONSTANTS_UPDATED too, but Phalcon\Di's static member variables has not been initialized.

Although this is php's bug and not phalcon's bug, php does not use this feature and is not affected.
I think the php development team has no motivation to fix it.
Are you considering fixing it in Phalcon?@sergeyklay @niden


All above analysis is based on php7.2, some changes have occurred in php7.3 and php7.4, I am not sure if there is still a bug.
But php7.3 has only a few release versions and php7.4 has no release, so I don't think about using them now.


It seems that this bug has been fixed after php7.3.0
php/php-src@f78e681#diff-08f540d7b52da02794ca86b2de87ca69
https://bugs.php.net/bug.php?id=77498


something help to fix:

  1. compiler_globals_ctor() https://github.com/php/php-src/blob/d58cc9c9e5516d10d3227aecc0623151cd81192d/Zend/zend.c#L630
  2. php_request_shutdown() -> zend_deactivate() -> shutdown_executor() -> zend_cleanup_internal_classes() -> zend_cleanup_internal_class_data()
  3. There is the bug after this commit : php/php-src@ca64b41#diff-246862e485897a77cdcef1c52d473a52
@sjinks

This comment has been minimized.

Copy link
Contributor

commented May 13, 2019

@zhaoyanliang2 are you sure? zend_update_class_constants() is called from zend_do_inheritance() which, in turn, is called from zend_register_internal_class_ex(). Classes are registered during MINIT phase; thus, all internal classes should have ZEND_ACC_CONSTANTS_UPDATED flag in their ce_flags by the end of MINIT.

@zhaoyanliang2

This comment has been minimized.

Copy link

commented May 14, 2019

@sjinks

zend_declare_property_null(phalcon_di_ce, SL("_default"), ZEND_ACC_PROTECTED|ZEND_ACC_STATIC TSRMLS_CC);

after
zend_register_internal_class() -> do_register_internal_class
ZEND_ACC_CONSTANTS_UPDATED flag was set

then, after
zend_declare_property_null() -> zend_declare_property() -> zend_declare_property_ex()
ZEND_ACC_CONSTANTS_UPDATED flag was unset

And each of thread will call these before exit
php_request_shutdown() -> zend_deactivate() -> shutdown_executor() -> zend_cleanup_internal_classes() -> zend_cleanup_internal_class_data()
ZEND_ACC_CONSTANTS_UPDATED flag was unset too.

See the php7.2 source, some changes have occurred in php7.3 and php7.4

@sjinks

This comment has been minimized.

Copy link
Contributor

commented May 14, 2019

7.3, zend_declare_property_ex()

As far as I understand, the only case when the ZEND_ACC_CONSTANTS_UPDATED gets cleared is when the property is of IS_CONSTANT_AST type (which is a constant array and is not applicable to PHP extensions — it is in the else branch of if (ce->type == ZEND_INTERNAL_CLASS)).

@zhaoyanliang2

This comment has been minimized.

Copy link

commented May 14, 2019

7.3, zend_declare_property_ex()

As far as I understand, the only case when the ZEND_ACC_CONSTANTS_UPDATED gets cleared is when the property is of IS_CONSTANT_AST type (which is a constant array and is not applicable to PHP extensions — it is in the else branch of if (ce->type == ZEND_INTERNAL_CLASS)).

This bug has been fixed after php7.3

@sjinks

This comment has been minimized.

Copy link
Contributor

commented May 14, 2019

Ah, sorry, I misread what you wrote

@Jurigag

This comment has been minimized.

Copy link
Member

commented May 14, 2019

So we could possibly just backport this fix for php 7.2, 7.1 and 7 to zephir kernel and that's it?

@sjinks

This comment has been minimized.

Copy link
Contributor

commented May 14, 2019

Well, in theory this should work then:

diff --git a/Library/ClassDefinition.php b/Library/ClassDefinition.php
index 43cb5c6e..bdd20651 100644
--- a/Library/ClassDefinition.php
+++ b/Library/ClassDefinition.php
@@ -1227,6 +1227,10 @@ final class ClassDefinition
             }
         }

+        $codePrinter->output('#if PHP_VERSION_ID < 70300');
+        $codePrinter->output('zend_update_class_constants('.$this->getClassEntry().');');
+        $codePrinter->output('#endif');
+
         $codePrinter->output('return SUCCESS;');

         $codePrinter->outputBlankLine();
@sjinks

This comment has been minimized.

Copy link
Contributor

commented May 14, 2019

Or maybe not… CG() is probably not available during MINIT, and then the fix is not trivial… zend_update_constants() need to be called on every thread and it must somehow ignore ZEND_ACC_CONSTANTS_UPDATED flag (we probably need to clear it for every class when CE_STATIC_MEMBERS(ce) && ce->default_static_members_count is true).

@sjinks

This comment has been minimized.

Copy link
Contributor

commented May 14, 2019

So this should go to RINIT then… we will suffer performance penalty during RINIT for every request :-(

@zhaoyanliang2

This comment has been minimized.

Copy link

commented May 14, 2019

@sjinks In a multi-thread environment, ZEND_ACC_CONSTANTS_UPDATED will be set or unset at any time. Calling zend_update_class_constants() in RINIT doesn't always work.
copy zend_intenal_class_init_statics()(in php7.3) to our extension and call it in RINIT may works.

@zhaoyanliang2

This comment has been minimized.

Copy link

commented May 14, 2019

@Jurigag
Why is this bug in php7 for such a long time?
Why is it fixed so quickly in php7.3?
This is not a coincidence.

The php official team fixed the bug but did not merge it into php7.2.
Because they probably don't know that php7.2 has this bug.
They found this bug in 7.3 because some changes in php7.3 caused this bug to appear in non-thread safe mode.

php/php-src@f78e681#diff-08f540d7b52da02794ca86b2de87ca69
This commit is to fix the bug in non-thread-safe mode.
Whether it completely fixes the bug in thread-safe mode may require careful testing.

@Jurigag

This comment has been minimized.

Copy link
Member

commented May 14, 2019

Oh, so you suggest to try compiling php 7.2 with this fix and check if issue we have in phalcon still apears? That's actually good idea. If not then obviously php team should merge this fix to other php 7.x as well.

@zhaoyanliang2

This comment has been minimized.

Copy link

commented May 14, 2019

Fixing this bug is not easy, and it is likely to cause performance problems, too many changes may break the compatibility of the PHP API.
Submitting a bug to php on behalf of the phalcon team can attract enough attention.
The following code can be used to fix bug in extension without considering performance.

void zend_class_init_statics(zend_class_entry *class_type) /* {{{ */
{
	int i;
	zval *p;

	if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
		if (class_type->parent) {
			zend_class_init_statics(class_type->parent);
		}

		CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count);
		for (i = 0; i < class_type->default_static_members_count; i++) {
			p = &class_type->default_static_members_table[i];
			if (Z_ISREF_P(p) &&
				class_type->parent &&
				i < class_type->parent->default_static_members_count &&
				p == &class_type->parent->default_static_members_table[i] &&
				Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
			) {
				zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];

				ZVAL_NEW_REF(q, q);
				ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
				Z_ADDREF_P(q);
			} else {
				ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
			}
		}
	}
}

void fix_class_static_member_thread_safe_bug()
{
	zval *val;
	ZEND_HASH_FOREACH_VAL(CG(class_table), val) {
		zend_class_entry *ce = Z_PTR_P(val);
		if ( ce->type == ZEND_INTERNAL_CLASS
			&& !CE_STATIC_MEMBERS(ce)
			&& ce->default_static_members_count
		) {
			zend_class_init_statics(ce);
		}
	} ZEND_HASH_FOREACH_END();
}

call fix_class_static_member_thread_safe_bug() in PHP_RINIT_FUNCTION(ext_name)

The above code is for php7.2, not tested under 7.0 and 7.1.
It is not clear whether this fix will cause other problems.

@sjinks

This comment has been minimized.

Copy link
Contributor

commented May 14, 2019

@Jurigag I am afraid they won't :-( 7.2 active support ends on 30 Nov 2019, and they will likely let this bug expire :-( See, for example, https://bugs.php.net/bug.php?id=76301, https://bugs.php.net/bug.php?id=76302 (all these bugs came either from Zephir or Phalcon) :-(

@dreamsxin

This comment has been minimized.

Copy link
Member

commented May 14, 2019

Maybe, we can manage static variable lists.

@vGhost2000

This comment has been minimized.

Copy link

commented May 16, 2019

@zhaoyanliang2, thanks for investigation. Im sove this problem for myself. Im write console multi-threading application with https://github.com/krakjoe/pthreads extension. In threads i have "Fatal error: Uncaught Error: Access to undeclared static property: Phalcon\Di::$_default". After read this thread i have invented 2 solutions.

In both cases, first add in phalcon config.json:

        "core.use_globals_instead_static": {
            "type": "bool",
            "default": false
        }

The first option involves the use of superglobal variables, for example _SERVER. For this you need to change the di.zep in the following way:

	/**
	 * Phalcon\Di constructor
	 */
	public function __construct()
	{
		var di;
		if globals_get("core.use_globals_instead_static") {
		    if ! isset _SERVER["__phalcon__di__"] {
                        let _SERVER["__phalcon__di__"] = this;
                    }
		} else {
                    let di = self::_default;
                    if !di {
                        let self::_default = this;
                    }
		}
	}


    /**
    *   For phpinfo(), hi try convert this clss instance to string,
    *   and throw error without this method
    */
	public function __toString()
	{
	    return get_class(this);
	}

	/**
	 * Set a default dependency injection container to be obtained into static methods
	 */
	public static function setDefault(<DiInterface> dependencyInjector)
	{
		if globals_get("core.use_globals_instead_static") {
                    let _SERVER["__phalcon__di__"] = dependencyInjector;
                 } else {
		    let self::_default = dependencyInjector;
		}
	}

	/**
	 * Return the latest DI created
	 */
	public static function getDefault() -> <DiInterface>
	{
		if globals_get("core.use_globals_instead_static") {
		    if ! isset _SERVER["__phalcon__di__"] {
                        throw new Exception("Di not initialized");
                    } else {
                      return _SERVER["__phalcon__di__"];
                    }
		} else {
		    return self::_default;
                }
	}

	/**
	 * Resets the internal default DI
	 */
	public static function reset()
	{
		if globals_get("core.use_globals_instead_static") {
                     let _SERVER["__phalcon__di__"] = null;
                 } else {
		    let self::_default = null;
		}
	}

The second option (which I use in my project) requires that you use the user space class in php. For this you need to change the di.zep in the following way:

	/**
	 * Phalcon\Di constructor
	 */
	public function __construct()
	{
		var di;
		if globals_get("core.use_globals_instead_static") {
		    call_user_func("PhStaticStorage::set", "di_default", this);
		} else {
                    let di = self::_default;
                    if !di {
                        let self::_default = this;
                    }
		}
	}
	/**
	 * Set a default dependency injection container to be obtained into static methods
	 */
	public static function setDefault(<DiInterface> dependencyInjector)
	{
		if globals_get("core.use_globals_instead_static") {
                    call_user_func("PhStaticStorage::set", "di_default", dependencyInjector, true);
                 } else {
		    let self::_default = dependencyInjector;
		}
	}

	/**
	 * Return the latest DI created
	 */
	public static function getDefault() -> <DiInterface>
	{
		if globals_get("core.use_globals_instead_static") {
		    return call_user_func("PhStaticStorage::get", "di_default");
		} else {
		    return self::_default;
               }
	}

	/**
	 * Resets the internal default DI
	 */
	public static function reset()
	{
		if globals_get("core.use_globals_instead_static") {
                    call_user_func("PhStaticStorage::set", "di_default", null, true);
                } else {
		    let self::_default = null;
		}
	}

in php script must be added before instantiating di:

class PhStaticStorage
{
    private static $_store = [];

    public static function set(string $name, $value = null, bool $force = false)
    {
        if (!isset(self::$_store[$name]) || $force) {
            self::$_store[$name] = $value;
        }
    }

    /**
     * @param string $name
     * @param bool $silent
     *
     * @return mixed
     *
     * @throws Exception
     */
    public static function get(string $name, bool $silent = false)
    {
        if (!isset(self::$_store[$name])) {
            if ($silent) {
                return null;
            }
            throw new Exception('Variable not exists');
        }
        return self::$_store[$name];
    }
}

Build

In the archive I attach the config of the build of both versions of the docker images with a fixed di, as well as a test
test.zip

Build by commandЖ

cd 7.2.13-zts-alpine-usf
docker build -t test-usf  .
cd ../7.2.13-zts-alpine-srv
docker build -t test-srv  .

Testing

The test script differs only in the presence of the user class PhStaticStorage for the second option.

<?php


use Phalcon\Di\FactoryDefault\Cli as CliDi;

if (!empty($_SERVER['argv'][1]) && $_SERVER['argv'][1] === 'set-ini') {
    ini_set('phalcon.core.use_globals_instead_static', true);
}

class PhStaticStorage
{
    private static $_store = [];

    public static function set(string $name, $value = null, bool $force = false)
    {
        if (!isset(self::$_store[$name]) || $force) {
            self::$_store[$name] = $value;
        }
    }

    /**
     * @param string $name
     * @param bool $silent
     *
     * @return mixed
     *
     * @throws Exception
     */
    public static function get(string $name, bool $silent = false)
    {
        if (!isset(self::$_store[$name])) {
            if ($silent) {
                return null;
            }
            throw new Exception('Variable not exists');
        }
        return self::$_store[$name];
    }
}



$di = new CliDi();


class MyWorker extends Worker
{
    public function run()
    {
        (new CliDi())->setShared('test', function () {
            return (object)['var' => 1];
        });
    }
}

class Task extends Threaded
{
    private $value;

    public function __construct(int $i)
    {
        $this->value = $i;
    }

    public function run()
    {
        usleep(rand(250000, 950000));
        $test = CliDi::getDefault()->get('test');
        $test->var++;
        echo "Task: {$this->value}, var: {$test->var}\n";
    }
}

$pool = new Pool(10, MyWorker::class);
for ($i = 0; $i < 25; ++$i) {
    $pool->submit(new Task($i));
}

while ($pool->collect());

$pool->shutdown();

Test result with disabled ini option:

$ docker run --rm -it test-usf php test.php

Fatal error: Uncaught Error: Access to undeclared static property: Phalcon\Di::$_default in /test.php:51
Stack trace:
#0 [internal function]: Phalcon\Di->__construct()
#1 [internal function]: Phalcon\Di\FactoryDefault->__construct()
#2 /test.php(51): Phalcon\Di\FactoryDefault\Cli->__construct()
#3 [internal function]: MyWorker->run()
#4 {main}

Next Error: Access to undeclared static property: Phalcon\Di::$_default in /test.php:51
Stack trace:
#0 [internal function]: Phalcon\Di->__construct()
#1 [internal function]: Phalcon\Di\FactoryDefault->__construct()
#2 /test.php(51): Phalcon\Di\FactoryDefault\Cli->__construct()
#3 [internal function]: MyWorker->run()
#4 {main}
  thrown in /test.php on line 51

Fatal error: Uncaught Error: Access to undeclared static property: Phalcon\Di::$_default in /test.php:51
Stack trace:
#0 [internal function]: Phalcon\Di->__construct()
#1 [internal function]: Phalcon\Di\FactoryDefault->__construct()
#2 /test.php(51): Phalcon\Di\FactoryDefault\Cli->__construct()
#3 [internal function]: MyWorker->run()
#4 {main}
.....

Test result with enabled ini option:

$ docker run --rm -it test-usf php test.php set-ini
Task: 0, var: 2
Task: 6, var: 2
Task: 1, var: 2
Task: 7, var: 2
Task: 9, var: 2
Task: 10, var: 3
Task: 4, var: 2
Task: 3, var: 2
Task: 2, var: 2
Task: 5, var: 2
Task: 16, var: 3
Task: 14, var: 3
Task: 8, var: 2
Task: 19, var: 3
Task: 17, var: 3
Task: 13, var: 3
Task: 18, var: 3
Task: 15, var: 3
Task: 11, var: 3
Task: 24, var: 4
Task: 20, var: 4
Task: 12, var: 3
Task: 21, var: 4
Task: 23, var: 4
Task: 22, var: 4

Testing the second build is done by commands:

$ docker run --rm -it test-srv php test.php 
$ docker run --rm -it test-srv php test.php set-ini

The result will be the same.

@zhaoyanliang2

This comment has been minimized.

Copy link

commented May 16, 2019

@vGhost2000
There are other classes in phalcon that use static member variables.
You may also need to modify other classes if you want to use them.

@vGhost2000

This comment has been minimized.

Copy link

commented May 16, 2019

Yes, I saw, but there are not so many of them and for the most part those that are not used in the console application, so I didn’t touch them. At the moment, so far this has solved my problem. If there is a need for others, I will correct them too. That's why I passed the PhStaticStorage universal, so that in case it could be used in other places.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.