Description
Description
Currently, the yaml parser allows custom tags, such as these:
!bar some-text
When Yaml::parse
is called on this, with the Yaml::PARSE_CUSTOM_TAGS
flag, it will return a Symfony\Component\Yaml\Tag\TaggedValue
that has a tag
of "bar", and a value
of "some-text".
I believe it would be useful if custom classes could be used, by creating a factory class that an application can hook into to add custom classes that implement a TaggedValueInterface
. And the factory should be used to create new instances when parsing. If there's no available class to use for a given tag, TaggedValue
would still be used.
Additionally, when dumping, if a value implements TaggedValueInterface
, it would dump it as a custom tag, rather than a dictionary.
Implementation
I would be happy to write the implementation, and submit a PR. I wanted to see if there was interest in such a feature before I went to the work.
Additionally, I was thinking that an additional flag might be necessary to enable this behavior in the parser to preserve backwards compatibility.
Example
# In application bootstrap
use App\Models\User; // Implements TaggedValueInterface
use Symfony\Component\Yaml\Tag\TagFactory;
TagFactory::addTaggedClass(User::class);
// This will call a static `getYamlTags` method, which should
// return an array of tags that this class can be used, and
// add it to an array of classes on the factory.
# Alternate bootstrap
use App\Models\User; // Implements TaggedValueInterface
use Symfony\Component\Yaml\Yaml;
Yaml::addCustomTag(User::class);
# To dump yaml
use App\Models\User;
use Symfony\Component\Yaml\Yaml;
$user = User::find($id); // Will fetch a user from the database
return Yaml::dump(['user' => $user]);
// Will return something like 'user: !user <id>',
// depending on the implementation in the User class
# To parse this yaml
use App\Models\User;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Tag\TaggedValue;
$yaml = "user: !user 5\ntagged: !other-tag text";
// Yaml::PARSE_CUSTOM_TAG_OBJECTS would be a new flag necessary to enable the behavior and preserve backwards compatibility
$userData = Yaml::parse($yaml, Yaml::PARSE_CUSTOM_TAGS | Yaml::PARSE_CUSTOM_TAG_OBJECTS);
// Since !user is a known tag, a static method will be called
// on the User class, passing the tag and value in, same as
// the TaggedValue constructor, and this method will handle
// fetching from the database and returning an instance of User
/** @var User $user */
$user = $userData['user'];
/** @var TaggedValue */
$tagged = $userData['tagged']