Jump to content

Recommended Posts

Posted

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?

Posted

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';
};

 

Posted

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"),
	)
);

 

Posted

So that is the entire contents of the file at $path?

I just tested like this:

image.png.789a44c8251476c51fb4fcf8a5b54621.png

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?

Posted
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).

Posted (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:

1000694451_Measurementdebug.thumb.jpg.db9074a28e81eb8860ae10908fa9b0fc.jpg

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:

885539978_Measurementdebuga.jpg.30bdc591b01507ffa9526269fb48ea49.jpg

Edited by MarkE
Additional info
Posted

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.

 

Posted

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"

 

  • Like 1
  • 2 weeks later...

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...