 afternoon, and welcome to this talk, building RESTful APIs with symphony components. My name is Victoria, I work at Lee Menus, there we build tailor-made projects for clients using mainly symphony for the backend and React for the frontend. In most of the projects we build, there is a need for an API. Maybe because you want to serve the data to the frontend or to the mobile apps or for some other uses that we will review later. We are very comfortable with the symphony framework, and today I would like to show you how with only a few symphony components, you can have a lot of help for building your API. And also, which other tools do you have if you decide to use the whole framework? Okay, first of all, I'm going to start with an introduction, answering a few questions that may arise from the title of the talk. The first of them is why would I want my API to be RESTful, okay? So after some time reading a lot about REST and so on, some people, some one may think, okay, this is fine, but actually I can think of a better way of structuring an API. Why should I use REST, is it that good? Or even you can think, okay, I've been reading a lot and probably there are some very, or a few confusing and controversial points, and I don't think this must be so good if people are arguing so much about it, right? Well, those are first thoughts, in my opinion, but on the other hand, you have two very, at least two very powerful reasons for having your API RESTful. The first of them is that REST makes the most of the HTTP specification. That means that it makes the most of the best features of HTTP. It's about headers, status codes, verbs, and this is something really, really good, okay? On the other hand, there is another very good reason, is that you will be using a common language and you will know which are the advantages of that, to have a common language with the others. That in the long run, it saves time, it makes your life easier, okay? But even so, you can say, okay, but is it really worth it, all these things? You all have seen this, the three levels that you are supposed to reach and so on. Well, I think that you can follow a sane approach to REST, okay? It has also three levels, but they are different levels. The first one is learn the stuff that is commonly accepted, which is most of it. Learn all the things that everyone agrees on, okay? Like use nouns for resources, use HTTP verbs, return meaningful status codes, and so on. Most of this stuff, okay, everyone agrees on it and you need to really know how it works and use it. Second step is be aware that there are a few gray areas or controversial points. Things like, do I have to return the created or updated resource? Can I actually have two different URIs when I have two different representations? So these things, you can see people discussing them for a long time without actually knowing which one is better. Even experts, so for example, this second question, you can see Lucas Smith, which is the author of the Fossilist Bundle, saying, no, you cannot. You cannot have two URIs for two different representations because that goes actually against the concept of restful itself. But then you go somewhere else and you see the author of the concept and he says, well, I never said that you have to use content negotiation all the time. I never said that and he's actually having different URIs in his site for different representations. So what to do, actually? What you can do in these cases is to choose a site. You can choose a site simply because you think it makes more sense because your colleague thinks that it makes more sense or if you don't know what to do, you can even flip a coin if you want. But the thing is, at the end, you have to choose a way of doing that thing and stick to it. That's the really important thing to do, to be really, really, really consistent when building your API. So if you want to summarize this, try to be civilized and be consistent. The first part is kind of optional. You can also get totally mad about defending your ideas if you want. But the second part is absolutely necessary. You need to be the cool, calm and very, very consistent guy, even boring guy, when it comes to implement your API. All right? Well, second question. Why symphony and rest? Why are we putting those two things together? This one is very simple to answer. Rest is several things. It's a very strict definition. It's sometimes a battlefield. But it's a way to make the most of the HTTP. And symphony, on the other hand, was also built with the very same idea. It was built totally around the HTTP specification. So this is why those two fit so well together because both of them really love HTTP. Okay? That's the answer. And third and last question regarding the title. Why symphony components? Why are we talking about components and not just symphony? As some of you may know, symphony is two things. It's a full stack framework that you can use as just one thing. But it's also a set of independent components that you can use isolately in your own code and then actually many popular PHP projects are using already for some time. For example, these are some of the components and Doctrine uses them, Propel as well, Silex, the micro framework uses many of them. Drupal since version 8 I think as well, Laravel 2. So these components have brought a bit of standardization to the PHP community in the last years. Okay? So in this talk, we are going to see in detail these five components. HTTP foundation, serializer, validator, form, and guard. The knowledge that you get from these components, you can apply it later in a few different situations. When you decide to use the whole framework, when you find these components in some other framework, or even when using some of them in your own code, or even developing your own framework. Okay? You cannot be interested in developing your own framework, but it is a very nice exercise to do actually. And in this resource, you can see how could you do it. I did it and it's very interesting because you actually learn what a framework has, which are the different parts. It's really, really good. So actually in this repository, what we did was to put together the five components that we are going to see now. So if you want to check the whole code of some examples that I'm going to show you, and mostly if you want to see how to use those components isolated, you can check that repository. All right. Let's see what do those guys actually do. Let's see. First of them is HTTP foundation. This one is going to be the foundation of our API and is going to provide an object oriented lawyer for the HTTP specification. What does it mean? As you know, in PHP, the request is represented by a few global variables and the response is generated by some functions. So with this component, this component is going to replace those variables and those functions with two nice objects, response and request. Okay? Let's see how are they. The request, we can create one of those using create from global. This is similar to doing actually this. We are just creating our request object based on our current PHP global variables. All right? The response. For creating a response, we have to pass three arguments, the content, the status code and an array of headers which is basically what we will need to show in our API. All right. We have response and request. How can we create a post endpoint with that? The requirement is very simple. Whenever we send a post request there, we need to receive a 201 status code in the response. Okay? Let's do that. We have the request. We create it from globals, the code, the content. We do whatever we want to do in there with the data, per sees, whatever. This is not the interesting thing now. And then we build a response where we can very easily put the status code and here two headers, content type and location. Okay? Right. If you want a shortcut, you can also use JSON response that will set the content type and also encode to JSON. You will be saving one more line. It's even shorter. With only a few lines, you already have your endpoint. What about PSR7? Maybe some of you have heard of this. This is a standard that was approved two years ago. What happens with this? What is it about? The HTTP foundation has helped in the way of standardizing this object-oriented layer in the PHP community. But since this standard was approved, this is a step farther in this direction. So very likely, Symphony 4, that which will be released next November, it will embrace this standard. Until then, you can actually transform your HTTP foundation objects into objects that implement this standard, simply using this Symphony bridge. Okay? It's quite simple. Using that, your objects will be using this standard. And why would you want to do this? Well, if becoming more standardized is not enough for you, well, by the way, you have a link here to read more about this if you want. If this is not enough for you, you can, for example, use middle words if you are using this standard, which are basically very thin layers implementing some functionality, okay? For example, authentication or whatever. So everything that is moving towards or using more code, don't do the same thing many times, it's good for you. So that's why I wanted to mention this. Okay, let's move into the next one. Serializer. The Serializer is gonna be one of our best friends because he's going to help us creating the exact representations that we want in our API. All these things is about creating representations. So with the Serializer, you are going to be able to create representations from your objects and the other way around. How? If we didn't have this one, we should do something like this. If we want to update our object from the request, we will have to type something like this. So for each property, we need to type some code and it's something that looks repetitive and tedious to do. In the opposite direction, it's similar. It would be something like this. We will use our object to produce a response, okay? But this is all things that we don't like to do because here we have three properties, but what if we have like 50 or something? We need something easier, cleaner. So the Serializer is helping with this. Instead of having to write all these, you just need to call it, please serialize this recipe, converting our object into a JSON response, all right? And in the opposite direction, deserializing, you can simply do something similar. Hey Serializer, please deserialize this, this content into my recipe class. It comes from an JSON format, all right? Just one line instead of lots of them. Okay, the schema of the Serializer looks like this. It may seem a bit complicated at the beginning, but it is not. You are basically turning objects into some format and the other way around. You can see that there is something intermediating there, this array. This is only because we are splitting the task in two. We have the encoders that take care of transformations between arrays and JSON, for example, and then we have the normalizers that take care of this part of transforming between arrays and objects. Usually the heavy work is done by the normalizers, okay? So before being able to use it, we actually need to do some setup. We have to say which encoders are we going to use and which normalizers. In this case, we are saying, hey, we're going to use XML and JSON encoder and we are going to use object normalizer. Object normalizer is the most powerful normalizer, but you have others out there. You can check the documentation for that. Instead of explaining things that you can check there, I want to focus in the main idea of all this. The main idea is your representations doesn't need that they are not the same thing that you have in your database. You actually need to make sure to show in your API exactly what you want to show. The representations that you really need are useful for you. For example, imagine that you have this user, okay? But maybe this is in your database, but maybe you want that this property is called username and maybe you don't want to show the password. You want the email to be shown in the profile but not in the list. Perhaps you can want to add a prefix there. Maybe there are some properties that you want to show in one version of the API but not in another version. Or you have things like this and you want to turn them into normal other properties. Okay, for doing all this, the serializer is going to help, okay? For example, it brings a set of tools, for example, these two annotations. Max depth is simply saying, hey, please serialize but just do it until one point, second level or third level. Because if you have one object that is related to another one, another one, another one, maybe you don't want to serialize all that, you only want the first two levels. This is very useful when you are working with large trees and also when you have circular references, okay? There is another interesting annotation here is are the groups. Groups are useful to serialize specific sets of properties. Let's see it with an example. In your end, we are going to create that end point but we want it to, we want to receive only these properties. Name and servings. So in our entity, we are going to set the groups saying, okay, all of them have the group detail but only some of them have the group overview. All right, so when we serialize passing the group overview, we are going to get a representation only with those properties. This is really, really useful. All right, another thing that you are going to do very often when working with a serializer is to write your own normalizers, okay? Remember that this is the part that deals between the object and the arrays. For example, a very simple example is when you want to serialize attributes with different names. In this case, you will have to write something like this. This is a name converter interface that has two methods, normalize and denormalize. When you normalize, you are going to add a prefix and please when you denormalize, remove this prefix. As you can imagine with this, you can do whatever you want in this changing what you have in your representation. All right, that was about the serializer. Validator is our third best friend because we have to make sure that whatever goes to our database is meeting some constraints. We cannot leave that work to the database. We have to do it before and the validator is the one that is going to help us with this. Okay, provides tools for this task. In this very simple example that is only validating a string, you can see what do you have in there. There are two things. There are constraints, which are simply the rule formulations. So where you are saying, hey, I want this to happen. And then you have the validators. That is where the actual logic is. If at some point, you need to write your own constraints and validators, you will have to put your logic in there. Okay? But what happens when we want to validate more complex things like objects, which is our case. So then the important thing is that the validator needs to know which constraints apply to each of the properties of the object. Okay? You can do that with annotations like here, which I find very handy. But if you prefer, you could do it with YML, XML or whatever you want. The validator component comes with 50 something constraints, and of course you can write your own if you want. All right. Which is also really, really important here. If the validation is not passing, if the constraints are not being met, then you have to return some errors. In an API, it's as important to have a good validation as having a good handling of the errors. This is extremely important because otherwise the consumers of your API can get very angry about this. We will talk a bit more about this later. Now we are going to review the form component. You might think, why are we going to use a form component if there are no forms in here? Well, the thing is that dealing with the data that comes through an HTML form and dealing with the data that comes through your API are two quite similar things. We are going to use the form component to deserialize that data and validate, okay? Using this component has a few advantages. It has a very powerful serializer and also if you are not only building an API but also having actual forms somewhere, you are going to save quite a bit of work reusing that code, all right? So it provides powerful validation and serialization. Okay, in this resource, you can learn quite a bit about this. Actually, this whole course of KNP University is very interesting, if you want to have a look. What we are going to do with our form component is to create a put endpoint. We want simply that it returns a 200 code, all right? So we'll do something like this. First of all, I want to point out something. If you are using the components without the framework, of course, you will have to do more work. You will have to write more things. For example, things like this. You will have to create your form factory adding the extension that validates and so on. All these details, you can check them out in our repository because here I want to focus in what is most important from the components. In this case, we are getting the request, the content and we simply have to build our form and bind the data to it. So simply with that, you can now check if the form is valid or not. If it's valid, you will return the successful response and otherwise, some errors. For example, this thing of serializing the form to return the errors also needs some work from your site. It's another thing that you can check in the full examples, all right? Now that we have created a put endpoint to update a resource, it's a good moment to ask this question because I didn't want to review all the rest theory, but there are a few questions that is good to review from time to time. So it's actually a post to create and a put to update. Well, that's the common knowledge, okay? But it's not true. It's not true, but if you follow it, you will be kind of okay, right? But the whole truth is you have to use put if those two are true. The operation is important, which means it doesn't matter if you perform it once or several times. It will have the same result. And second, the URI is the address of the resource that you are updating or creating. If those two are true, it's put. Otherwise, it's post. Actually, this is not one of the controversial areas that I was mentioning before. This is quite clear. It's only that at the beginning it's a bit difficult to remember it for some reason. And second question a bit related to this, do I have to return the resource? All right, well, many say that you don't have to, but some clients will assume that you will do it. So it depends. Depends on who are you writing your API for. It's a bit up to you. But as always, choose and then be consistent with your choices. Okay, final component, guard. Guard is going to help us with the authentication. Actually, in Symphony, we have a more complex component which is called security. It's really big, it's powerful, it's very flexible, but it's really a bit too complex. So they decided to create this guard component which is kind of quite new to simplify this security. They have simplified it so much that actually you only have to implement this interface, guard authentication interface. It has seven methods that you can see here. They are very thin and simple methods. If you check out the documentation, you will see that they are very easy to understand and implement. Of course, having this, you also have them to implement some mechanism for authentication. JSON, web token, OAuth, whatever you want. This is not saving you from that, but this is like making the work easier, preparing you for this. Okay. At this point, with these five components, when you arrive here, what you find out is, well, you would probably feel that you need more things. You have been needing more things that you usually have in a real framework. Like, well, routine, even dispatcher, and all these things. So maybe it's a good time to ask, what if we use the whole framework? So now, I'm going to show you which of the things would you have if you decide to use the whole framework. Let's see. How, what do we have with that? The framework uses all these components and a few more. And the thing is, as you already know, a component is an independent library. But in Symphony, you also have bundles. Bundles are tied to the framework, right? Not like components. Usually, or sometimes, or often, you have the library plus a bundle that is basically integrating the library in the framework. So now, I'm going to show you a few bundles that can be useful for your API if you use the whole framework. First of them is this JMS Serializer. This one is an alternative to the Serializer that we have already seen. I cannot tell you which one is best because both are very, very good, but they are a bit different. This one is perhaps a bit easier to set up and start working with it. It comes with lots of annotations and then there are a lot of things that you can do very easily, a lot of standard things that are very quick to do. The other one, the Symphony Serializer, is more about very often writing your own normalizers, which also gives you more flexibility. Then it depends a bit on what you want to do or what are you feeling more comfortable with. But both are very nice choices. Some cool things that this one has are three exclusion strategies. Apart from groups, you can exclude some strategies with annotations too. Versions where you can say these properties are in this version of the API, these are not. You can have virtual props, events that provide extra flexibility. If you work with XML, it's very configurable, so you have a lot of cool things. Next bundle is the forced-res bundle. The forced-res bundle is not one tool, actually. It's more like a toolbox. So it provides a set of tools that are useful for building your API. I chose some of them, these are some of them, but basically it helps a lot when you have to deal with different representations of the resource. It has a body request that goes there. It has a listener that performs content negotiation deciding which format is the appropriate one. So those are a set of tools that if you don't know them, you can live without them. But actually, when you start using this, you cannot picture yourself building an API without it somehow. So it is worth as well to have a look at it. The next one is going to allow us to have JSON web token authentication. We can use this together with the guard component that we already have seen. It's based on a couple of libraries that, of course, you could use without the bundle if you are not using the whole framework. The goal is this about this authentication in case you don't know. Well, it's basically that you send some credentials, username and password, to an endpoint that you have configured in your security, okay? And then with that, you will receive a token. And from that point, using that token, you will be able to send requests, okay? It's as simple as that. It's a very simple way to be authenticated, okay? Which other choice you have? You could go for OAuth. In my personal experience, that makes sense if you have a good reason for having OAuth in your project because it's quite a bit more complex. Many times with this is more than enough for your APIs. Okay, this bundle is going to allow us to reach level three, okay? Level three is about returning the links that make possible to discover, auto discover your API. All right, in case that you want to do this, this bundle is going to help a lot because you are going to return instead of just this thing, the proper link, all right? And you are going to return the proper link in a very simple way because you have an annotation that is taking care to generate the proper route. So you don't have to, of course, hard code your routes because you will get the proper ones with this, okay? Potentially allows you to reach level three. Do we want to reach level three? Well, theoretically, if you don't do it, your API is not rushed. In the real world, there are not so many APIs are implementing it. So again, it depends on what you need and what you think is best for your AP consumers and so on. You have to decide by yourself. Okay, and the last bundle I want to mention is this Nelmio that is going to help with documenting. While you are coding, you will be writing some annotations that will produce a very nice documentation. Why is this good? Because if you leave the documentation for later, you probably will never do it. But if you can do it while you are coding, it's much better. It uses a lot introspection. That means it's taking information from the code to output the documentation. It looks like this. There is an annotation. You put there some tags and it produces something that looks like this, okay? This data has been just taken from the code. It's easy to keep your documentation updated with something like this. All right, that were the tools I wanted to show you that some were components and others were bundles, okay? And now I want to take a moment to talk about testing. Why? Because testing is extremely important when you are building an API. Because you cannot be there in your browser trying it. You actually need some tools that make very comfortable to check out what you are doing is right or not. It's a case in which this you cannot avoid. You really need to do it and you really need to have an environment you feel comfortable with. So, which things can you use? You can use Postman, it's the first thing you can use. This is okay if you want to show to someone, for example, hey, I have this endpoint, they are working, check them out here. But for yourself, you probably need to set up something that looks like this. For yourself, you probably need to set up something a bit more powerful that allow you to code some real tests. These tools, this tool is very, very simple to use as well. Gassel and PHP Unit, okay? You will be implementing functional tests that simply let you check that your API is doing what you want it to do. One test could be simply like this. With Gassel, you can very easily send post requests and then print the response, that's all. So, another thing that we already mentioned is that it's very important to handle properly the errors. What do I mean with this? Imagine, for example, that you will be receiving something like this already. So, it is worth it to take some time to implement some code that saves you a lot of time with this. For example, to check if these errors exist. Errors, children, servings, error. Is it there or not? So, whenever you find yourself taking things like in a not very comfortable way is because you are missing something that you should have copied. So, take your time to do these things. Another example, at some point, you could receive an HTML error, which you shouldn't, but it can happen. So, if you see this in your browser, it's okay. You can read it, but if you see this in your command line, it's really annoying. You will lose your eyes looking in there. So, perhaps is it worth it to call something that can extract the meaningful information, the title in this case. This doesn't take so much time and it will save you later a lot. If you can only see the things that you want to see in there. For example, with the symphony crawler, you can do a simple tool like this. Okay, of course, it's basic to have an isolated database. Using SQLite is a good option because you'll lose less time dropping database and so on. And related to this is extremely, extremely important to have good fixtures for your tests. Good real fake data that looks like real. And these two tools, Alice and Faker, are very useful. Actually, we use those for not only for building APS for every project. There are two completely different things to show a new project with nice fixtures and to show one without. It doesn't, it's not the same thing at all. So, this looks something like this. You can have fixtures with fixed values because maybe you want to check that they are like this or just generate a lot with generators. You have many, Faker is providing a lot of generators that will actually build very, very real looking fixtures. Okay, finally, I'd like to review, well, a few cases of when can you need an API but especially one. Of course, it's to serve data to your frontend or to your mobile apps. Also, when you want to isolate one functionality, you may want to have an API to communicate with the rest of the system. But one use that we have found that is very interesting in the last year, it's sometimes to undertake a migration. Okay, imagine that you go to a company where they want to undertake a migration, changing, for example, a big legacy code from PHP to something like SIMFON. So, there are a few approaches that you can follow. First of them is simply to start coding in the new framework and you keep replacing functionalities one route at a time and replacing them with the old system. Okay, so the SIMFON is in front of the legacy code and step by step, at some point, you can remove the old thing. If you want to learn more about this in this presentation, you have quite a lot of information. But this approach is very good when you have a team that knows quite a bit about the new technology because the tough part, the hard work is going to be done in the new language, the routing, all these things. So many times, actually, the team is not an expert in the new technology. They actually want to learn it. So, there is a second approach that is more appropriate for these cases because the team, in these cases, is an expert in the legacy code. So, what can you do? In those cases, you have your legacy code and you can start coding the new functionalities in SIMFON and building an API with all the things that we have reviewed here and then the old system will be getting thinner and thinner while it replaces the calls to the API, right? Now, since the team is expert in this case in the legacy code, this approach is sometimes much more useful for them, okay? So, this is a case in which we can apply all these things regarding APIs. At some point, of course, you can remove the legacy code by front-end in SIMFON. Okay, just some final thoughts to summarize what we have seen. We have seen why REST and SIMFON fit so well together. It's because both of them were built thinking of the HTTP specification. We have seen how a few components can provide a lot and how you have more stuff if you want to use the whole framework. Also, we have seen that it's very important to set a proper test environment. But if you want to get only one idea that's sometimes what we want to do to have only one idea from this, that would be that all these things of building nice APIs and doing things right is to sometimes finding a good balance between these two. Okay, you can fight for your ideas and say how good your API is, but the real work is to become this cool, calm and also boring guy that is focusing in being very, very, very consistent with his decisions in his API. And that's all, thank you. If you have any questions? If they don't have it, it's okay as well. One of the other arguments that I've seen with REST APIs before is about versioning. Where do you stand on that? Do you put version strings at the start or do you put them as get variables afterwards? Sorry, I can't understand from here. Can you speak it slowly because there is some noise? Okay, I was wondering what your opinion was on versions of REST APIs. So do you prefer to put the version strings at the start or as get variables afterwards or no, it's a hotly debated topic? Did you hear that? I'm not sure. It's a thing about the ideas that might ease you as a point string monitor. You can just go to the side of the path. Yeah? Some headers are even in the set and you can place one version of the other. Yeah? Or is it just tougher? Well, actually, I don't have a preference or a preference with that. It depends a lot as many times of what you want to do. So honestly, I don't have a preference. Not really. Any other questions? Do you keep the form controllers separate from the API controllers, like the normal HTTP twig type pages separate from your API endpoints? Yeah, that's a good question. Yes, we keep them separate, but of course, since you have to do your controllers very, very thin, that's not a very big problem because you will have two very thin controllers doing two similar things. But we actually, yes, we prefer to keep those separated. Something else? Do you write any acceptance tests around the API endpoints to ensure they're returning the right things? If we return, of course, that's a very important thing to do. You have to make sure all the time that you are returning the... That's why I was talking about implementing some tools that really let you see what is coming from there. That's a very important thing to do. Yeah. How do you feel about exception handling? Do you use exception listeners by using the kernel? Yes, exception listeners are... I didn't want to enter into much detail with that, but are one of the most powerful things to use. That's why... So you have those in one of the serializers. I think you have them both. It's very, very, very useful. We use it always, yeah. Do you have any thoughts on the use of Swagger or the open API standard? Yeah, I knew you were going to ask, but I haven't used Swagger, actually, so I cannot say. Correct. What about JSON schema validation? Well, about JSON schema validation, you have a very good talk now in another... We use it quite a lot, and it's really interesting. Yeah, yeah. Thank you. What is your thoughts on things like, for example, using Fractal? Because if you use your serializer, you're basically sort of putting what your database has into your response, but maybe there's a few things that you might want to do, like relationships and using something like Fractal. What are your thoughts on that? Well, if you need that, of course, something like the serializer will help you with this. I have not needed that yet, but yeah, it's something that you can do with that serializer, too. Okay. Thanks. Thank you. Thank you.