MarkE Posted November 16, 2021 Share Posted November 16, 2021 In the process of refactoring and improving my FieldtypeMeasurement module, I came across an odd behaviour in the Tracy console. My module uses config php files including measurement conversion details which are in arrays which may include anonymous and named functions. Previously I used $data = include $path; to get these config files, but that meant that I had to test for function existence (for named functions) in the config files. $data = include_once $path; doesn't work because include_once returns true (not the return value) on subsequent calls, so I decided on this: $data = include_once $path; if($data === true) { $data = $this->session->get($quantity . '_data'); } else { $this->session->set($quantity . '_data', $data); } That does the business, but if $data has anonymous function and I run the code from the console, I get this error: Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in [no active file]:0 Stack trace: #0 {main} thrown in [no active file] on line 0 The odd thing is that the code all executes and outputs as expected - the 'fatal error' appears to be not at all fatal. Furthermore, if I run the exact same code from API calls in the main program, no exceptions are generated. I can't track down where the exception is being generated or why. I'm not particularly worried as everything seems to work OK, but it is a bit off-putting. Any ideas? Link to comment Share on other sites More sharing options...
adrian Posted November 17, 2021 Share Posted November 17, 2021 Hi @MarkE - could you show how the anonymous function in the included file is set up. Is it like: function() { echo 'test'; }; or echo function() { return 'test'; }; Link to comment Share on other sites More sharing options...
MarkE Posted November 17, 2021 Author Share Posted November 17, 2021 Hi @adrian - It is like: return array( ///////Units Of Temperature/////// "dimension" => new Dimension([Dimension::TEMPERATURE => 1]), 'base' => 'Kelvin', 'units' => array( "Kelvin" => array("shortLabel" => "K", "conversion" => 1, "plural" => "Kelvin"), //Kelvin - base unit for temperature "Celsius" => array("shortLabel" => "degC", "conversion" => function ($val, $tofrom) { return $tofrom ? $val - 273.15 : $val + 273.15; }, "plural" => "Celsius"), "Fahrenheit" => array("shortLabel" => "degF", "conversion" => function ($val, $tofrom) { return $tofrom ? ($val * 9 / 5 - 459.67) : (($val + 459.67) * 5 / 9); }, "plural" => "Fahrenheit"), ) ); Link to comment Share on other sites More sharing options...
adrian Posted November 18, 2021 Share Posted November 18, 2021 So that is the entire contents of the file at $path? I just tested like this: where test.php contains: return array( ///////Units Of Temperature/////// "dimension" => 'dfg', 'base' => 'Kelvin', 'units' => array( "Kelvin" => array("shortLabel" => "K", "conversion" => 1, "plural" => "Kelvin"), //Kelvin - base unit for temperature "Celsius" => array("shortLabel" => "degC", "conversion" => function ($val, $tofrom) { return $tofrom ? $val - 273.15 : $val + 273.15; }, "plural" => "Celsius"), "Fahrenheit" => array("shortLabel" => "degF", "conversion" => function ($val, $tofrom) { return $tofrom ? ($val * 9 / 5 - 459.67) : (($val + 459.67) * 5 / 9); }, "plural" => "Fahrenheit"), ) ); All I did was change the value of dimension because I don't have that class set up. What am I missing? Link to comment Share on other sites More sharing options...
MarkE Posted November 18, 2021 Author Share Posted November 18, 2021 39 minutes ago, adrian said: So that is the entire contents of the file at $path? Yes - apart from <?php namespace MetaTunes\MeasurementClasses; which is probably irrelevant to your test. The exception is not generated on the first include_once. It arises from the next bit which is to avoid $data just being == true on subsequent calls: if($data === true) { $data = $this->session->get($quantity . '_data'); } else { $this->session->set($quantity . '_data', $data); } EDIT: Of course, I don't know what actually generates the exception , so it may be in the code which executes the conversion function. All I do know is that without the above snippet, no exception is generated (and that it is not generated in any case outside the Tracy console context). Link to comment Share on other sites More sharing options...
adrian Posted November 18, 2021 Share Posted November 18, 2021 It's due to setting that $data to a session. PHP serializes data saved in sessions, so that's the reason for the error. Here are a couple of suggestions: https://stackoverflow.com/questions/39885355/php-serialization-of-a-closure-is-not-allowed This isn't an issue with the Console panel - I get exactly the same error in a template file. Link to comment Share on other sites More sharing options...
MarkE Posted November 18, 2021 Author Share Posted November 18, 2021 (edited) Thanks @adrian. That's curious because I'm not getting the exception in a template file. It executes normally with the correct result and no exceptions: DATA1 is the result of the include_once and DATA2 is after the test - i.e. if DATA1 is == true it is the session variable. Also, even in the console panel everything executes normally - the exception message seems to be spurious. However, I will investigate the stackoverflow link and report back anything of interest. EDIT - should have expanded that second DATA2 to show the closure: Edited November 18, 2021 by MarkE Additional info Link to comment Share on other sites More sharing options...
MarkE Posted November 19, 2021 Author Share Posted November 19, 2021 Hi @adrian. What did you do to get an error in a template file - I can't replicate that? See above post - executes correctly with no errors - the code in the template was: $data = include_once 'M:\laragon\www\BawdHall\site-admin\modules\FieldtypeMeasurement\Config\Temperature.php'; bd($data, 'data 1'); if($data === true) { $data = $session->get('quantity' . '_data'); } else { $session->set('quantity' . '_data', $data); } bd($data, 'data 2'); $data = include_once 'M:\laragon\www\BawdHall\site-admin\modules\FieldtypeMeasurement\Config\Temperature.php'; bd($data, 'data 1'); if($data === true) { $data = $session->get('quantity' . '_data'); } else { $session->set('quantity' . '_data', $data); } bd($data, 'data 2'); The link you provided yielded no insights as it failed to catch the supposed error. Also, it seems like the 'error' is not caught by tracyConsoleShutdownHandler() in CodeProcessor.php, so I'm not sure how further to track it down. Link to comment Share on other sites More sharing options...
adrian Posted November 20, 2021 Share Posted November 20, 2021 Template file contains: $quantity = 'testing'; $data = include_once '/Users/ajones/Sites/ecoreportcard/test.php'; $this->session->set($quantity . '_data', $data); and test.php contains: return array( ///////Units Of Temperature/////// "dimension" => 'dfg', 'base' => 'Kelvin', 'units' => array( "Kelvin" => array("shortLabel" => "K", "conversion" => 1, "plural" => "Kelvin"), //Kelvin - base unit for temperature "Celsius" => array("shortLabel" => "degC", "conversion" => function ($val, $tofrom) { return $tofrom ? $val - 273.15 : $val + 273.15; }, "plural" => "Celsius"), "Fahrenheit" => array("shortLabel" => "degF", "conversion" => function ($val, $tofrom) { return $tofrom ? ($val * 9 / 5 - 459.67) : (($val + 459.67) * 5 / 9); }, "plural" => "Fahrenheit"), ) ); and the result when viewing a page with that template is: Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in [no active file]:0 Stack trace: #0 {main} thrown in [no active file] on line 0 I think it really is a simple matter of what the error says. You aren't allowed to serialize closures (and there are two of them in test.php) and saving to $_SESSION serializes the data. There are lots of topics discussing it: https://www.google.com/search?q=php+session+"Serialization+of+'Closure'+is+not+allowed" 1 Link to comment Share on other sites More sharing options...
MarkE Posted November 30, 2021 Author Share Posted November 30, 2021 FWIW, my solution to this was to use a $config setting rather than a session var. Thanks for the help @adrian Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now