Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Lucky you! You found an early release chapter - it will be fully polished and published shortly!

Serialization Tricks

This Chapter isn't
quite ready...

Rest assured, the gnomes are hard at work
completing this video!

Browse Tutorials

Coming soon...

We've kind of tricked the system to allow a text description field when we send data. This of course, is made possible thanks to our set text description method, which we added so that we could run NL two b r on any description that is sent to our api. So this means that the user sends a text description field when they're editing or creating a treasure, but then when they're reading, we send back a field called description and that's totally legal. You are allowed to have different input fields versus output fields, but it would be a little cooler in this case if both of these were called description. So the question is, can we control what the name of a field is in the serializer? The answer is absolutely not surprisingly, via another attribute. This one is called serialized name. And we can pass description. This won't change how the field is read, but now if we refresh this page and look at the put endpoint, yep, we can now send description. All right, what about structor arguments in our N entity? Because one, for example, when we make a post request, we know it's using our

Setr methods to set all these properties. So let's see what happens if we remove the set method. So find set name and let's remove this and instead find the constructor and we'll add a string name argument there. And then this arrow name equals name. If you think about it from an object-oriented perspective, this field can't can be set when the object is created, but after that it's read only. Heck, if you wanted to get really fancy, you could even add read only to the property right now. So it's read only inside of php. And


See how it looks in our documentation. If you open up the post request, it looks like we can still send a name field. So let's actually try this. Let's hit try it out.


Talk about that giant slinky. We got cool factor eight and let's see what happens. Hit execute and it worked. And you can see for the response that the name was set, how is that possible? If you go down and look at the put end point, you'll see that it does advertise name here, but let's actually see my ID was four. So let's try this out. Say ID four. And when you execute here, it doesn't change. So it's read only in our code and it's also read only in our api. But how did the post request work at all? If we don't have a setter, the answer is that the serializer is smart enough to set construct arguments, but the matching is done by name. So the fact that this argument is called name and the property is called name is what makes this work like watch, check this out. Let's change this argument to treasure name in both spots. Announcement over refresh and check out our post endpoint. The field is gone. APM platform sees that we have a treasure name field that could be, that could be sent, but since treasure name doesn't correspond to any property, that field doesn't have any serialization groups. And so it's not actually used. So I'm gonna change that back to name. So by using name, it goes and looks at the name property and reads and uses the serialization groups off of it to figure out if it should be set.

Now there's still one other problem with Structor arguments that I want you to be aware of. So hit try it out on the post endpoint again.

Actually let me refresh to make sure we have fresh documentation. So let's pretend that we, what happens if the U, our user actually doesn't pass a name at all and they execute? You can see it airs with a 400 status code, but it's not a very good error. It says cannot create an instance of dragon treasure from serialized data because it's construction requires a name parameter. So not a great error they wanna show you to use. Or what you really want is to allow validation to take care of that. We're gonna talk about validation in a little while, but in order for validation to work, the serializer needs to be able to actually do its job. So in this case, what I'm gonna do is just allow the name argument to optional and then in a few minutes we're gonna talk about validation and we'll add validation to make sure that's set.

But that's gonna give us a much nicer validation error than this error right here. So if we try that again, right now it's actually a worse error. It's a 500 error cause it fails in the database. But the point is it allowed our object to be created. And in a few minutes, once we add Val validation rules, you'll see the really nice air that we get here. All right, next to help us while we're developing, let's add a rich set of data fixtures, then we are gonna enjoy and play with a great feature that API platform gives us for free Page Nation.

Leave a comment!

Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": ">=8.1",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "api-platform/core": "^3.0", // v3.0.8
        "doctrine/annotations": "^1.0", // 1.14.2
        "doctrine/doctrine-bundle": "^2.8", // 2.8.0
        "doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
        "doctrine/orm": "^2.14", // 2.14.0
        "nelmio/cors-bundle": "^2.2", // 2.2.0
        "nesbot/carbon": "^2.64", // 2.64.1
        "phpdocumentor/reflection-docblock": "^5.3", // 5.3.0
        "phpstan/phpdoc-parser": "^1.15", // 1.15.3
        "symfony/asset": "6.2.*", // v6.2.0
        "symfony/console": "6.2.*", // v6.2.3
        "symfony/dotenv": "6.2.*", // v6.2.0
        "symfony/expression-language": "6.2.*", // v6.2.2
        "symfony/flex": "^2", // v2.2.4
        "symfony/framework-bundle": "6.2.*", // v6.2.3
        "symfony/property-access": "6.2.*", // v6.2.3
        "symfony/property-info": "6.2.*", // v6.2.3
        "symfony/runtime": "6.2.*", // v6.2.0
        "symfony/security-bundle": "6.2.*", // v6.2.3
        "symfony/serializer": "6.2.*", // v6.2.3
        "symfony/twig-bundle": "6.2.*", // v6.2.3
        "symfony/ux-react": "^2.6", // v2.6.1
        "symfony/validator": "6.2.*", // v6.2.3
        "symfony/webpack-encore-bundle": "^1.16", // v1.16.0
        "symfony/yaml": "6.2.*" // v6.2.2
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
        "symfony/debug-bundle": "6.2.*", // v6.2.1
        "symfony/maker-bundle": "^1.48", // v1.48.0
        "symfony/monolog-bundle": "^3.0", // v3.8.0
        "symfony/stopwatch": "6.2.*", // v6.2.0
        "symfony/web-profiler-bundle": "6.2.*", // v6.2.4
        "zenstruck/foundry": "^1.26" // v1.26.0