PHP 8.1 DOMDocument serialization - php

I'm trying to make the following class compatible with native PHP serialization, specifically when running on PHP 8.1.
class SerializableDomDocument extends DOMDocument
{
private $xmlData;
public function __sleep(): array
{
$this->xmlData = $this->saveXML();
return ['xmlData'];
}
public function __wakeup(): void
{
$this->loadXML($this->xmlData);
}
}
It's all fine and dandy on lower PHP versions, but 8.1 yields Uncaught Exception: Serialization of 'SerializableDomDocument' is not allowed whenever such an object is attempted to be passed to serialize() function. Here's a sample of the code that would produce such an exception: https://3v4l.org/m8sgc.
I'm aware of the __serialize() / __unserialize() methods introduced in PHP 7.4, but using them doesn't seem to be helping either. The following piece of code results into the same exception as can be observed here: https://3v4l.org/ZU0P3.
class SerializableDomDocument extends DOMDocument
{
public function __serialize(): array
{
return ['xmlData' => $this->saveXML()];
}
public function __unserialize(array $data): void
{
$this->loadXML($data['xmlData']);
}
}
I'm quite baffled by this problem, and would really appreciate any hints. For the time being it seems like the only way forward would be to introduce an explicit normalizer/denormalizer, which would result in a breaking change in the codebase API. I'd like to avoid that.

On 10 Aug 2021, this change was commited to version 8.1 RC1:
Mark DOM classes as not serializable
So you can no longer serialize those classes.

It seems this is related to invalid methods or invalid XML content in your DOMDocument. If you do not use it, this works just fine https://3v4l.org/K91Vv

Related

Is there a type hint for an array of objects of a specific class in PHP 8.1?

Is there a type hint in PHP 8.1 which allows using ExampleClass[] for declaring it is an array of objects of the class ExampleClass?
In my specific case, ExampleClass is called Task
What I want but does not work:
private Task[] $tasks;
My PHPStorm IDE tells me that Plural types are allowed only in doc types - speaking that only in PHPDoc using Tasks[] would be totally fine. But I want to use plain PHP.
The error is:
PHP Parse error: syntax error, unexpected token "[", expecting variable
If I would only need one object Task and not an array of objects Task[] it would work with:
private Task $task;
This is my current, working workaround:
private array $tasks;
The short answer is no.
My understanding is that enforcing such a thing has terrible performance problems. Some people want to go all the way and have full blown generics, others just want type-safe collections. Some people worry that implementing the latter first might hinder the development of the former in the future. So we’re at a standstill.
There’s the occasional discussion in the community such as this: https://externals.io/message/108175
While there is not a type hint available for such compound types, there is a workaround that enforces type. Create a subclass from ArrayObject and validate all values added to the ArrayObject. Then you can type hint your new subclass.
<?php
class Collection extends ArrayObject
{
public function __construct(array $items = [])
{
foreach ($items as $item) {
$this->validate($item)
}
}
public function append($value): void
{
$this->validate($value);
parent::append($value);
}
public function offsetSet($key, $value): void
{
$this->validate($value);
parent::offsetSet($key, $value);
}
protected function validate($value): void
{
if (!$value instanceof Task) {
throw new InvalidArgumentException(
'Not an instance of Task'
);
}
}
}
Now you can return objects with a type hint of Collection and it will behave exactly as an array of Task objects.

PocketMine (PHP) Command Context possible?

As of 1.13 of Minecraft (and im not sure when it came out for bedrock) they added in the "command ui" with syntax and autofilling for commands (see below)
Command Syntax
I know on java edition it is possible to hijack the "Command Context" functions to create custom syntax for a command but on Bedrock it seems to all be stuck as [args: text] Is there any way to change that?
There is a very handy library/virion that handles all this for you. Take a look at https://github.com/CortexPE/Commando and if you need any examples you can look at https://github.com/CortexPE/Hierarchy. With this library you can add custom argument types.
<?php
namespace mohamed205\example\argument;
use CortexPE\Commando\args\StringEnumArgument;
use pocketmine\command\CommandSender;
class ExampleArgument extends StringEnumArgument
{
protected const VALUES = [
// put valid values for your argument here
];
public function parse(string $argument, CommandSender $sender)
{
return $this->getValue($argument);
}
public function getTypeName(): string
{
return "exampleArgument";
}
}

Why does invoking callable properties in PHP 7 work?

Consider the following code:
interface Doll
{
/**
* #return string
*/
function __invoke();
}
class LargeDoll
{
private $inner;
function __construct(Doll $inner)
{
$this->inner = $inner;
}
function __invoke()
{
return $this->inner() . ' world';
}
}
This won't work because it is expecting $this->inner to be a method, rather than a callable property.
Then it occurred to me, just like having (new LargeDoll)(); would work, what about if the property was wrapped in paranthesis also? So I tested it on 3v4l:
return ($this->inner)() . ' world';
And found that it works for PHP 7, but not for previous versions.
However, I can't find any mention of this in the changelogs.
Where can I find more information about this feature?
The ability to use IIFE's (which ($this->inner)() effectively is) was added as part of the Uniform Variable Syntax RFC by Nikita Popov, which was implemented in PHP7.
It's a consequence of better variable syntax handling in the parser. Considering one of the goals of PHP7 was to overhaul syntax parsing, I think they've achieved some real progress there.

Error creating new form elements in Phalcon

I get this error when trying to create a new form element:
Declaration of Phalcon\Forms\FileUpload::render() must be compatible with that of Phalcon\Forms\ElementInterface::render()
This is my code:
namespace Phalcon\Forms;
class FileUpload extends Element implements ElementInterface
{
public function __construct(string $name, $options, array $attributes)
{
}
public function render(array $attributes)
{
return 'my form element html';
}
}
I have tried every different notation of parameters at this point but I still receive the same error.
So I am wondering if it is possible at all to create form elements like this in Phalcon, or if it's just something I missed in the documentation.
http://phalcon.agent-j.ru/en/1.3.0/Phalcon/Forms/Element/
http://docs.phalconphp.com/en/latest/api/Phalcon_Forms_ElementInterface.html
I am using version 1.3.2
In the phalcon documentation this protoytype is defined:
abstract public string render (array $attributes=?);
So i changed my code to this:
public function render($attributes = false)
{
return 'my form element html';
}
i was just not familiar with the =? notation.
Are you using Phalcon 2 right?! In this version signatures should be followed more strictly. I've too got a bunch of errors like this one when I switched to Phalcon 2 but thankfully this version is written Zephir that makes the source code easier to read.
As you can see in the ElementInterface definition, the signatures aren't much consistent yet but we can easily see that render() has just one parameter without the array type hint. Just remove the array type from your interface implementation to match the current signature.

Type-hinting return value/functions in PHP

I did some research and came over this RFC which discusses type hinting for functions in PHP:
https://wiki.php.net/rfc/returntypehint2
For example
public string getName()
{
return 'martinmine';
}
Would be valid PHP code. Returning for example an array would yield an error in this case. Does anyone know the status on the RFC or if it got removed/added? I cannot seem to be able to make this function above work. I am using PHP 5.5.9.
Type hinting for return types are postponed to PHP 7 (as of this article), but the syntax is different than of the old purpose one:
function foo(): array {
return [];
}
But it is already available in PHP 5 for parameters of type class of a method or function(as of this article):
public function test_array(array $input_array) {
print_r($input_array);
}

Categories