 Hi everyone, welcome to this session about symphony. So symphony started 10 years ago, actually. So we are celebrating the 10 years of symphony this year. And a bit like Drupal, it started by being a one-man show. It was just me coding symphony. It's a bit different from DRISC because at that time, I was in a web agency called Senseio. And so I created symphony not just for the fun of it, but because I needed something for my customers. So symphony was created because we needed to create good projects, good projects with PHP. And 2005 was the first release of PHP 5. So symphony actually started as a PHP 5 only project, which means that from day one, we were able to use all the nice features that come with PHP 5. So nowadays, symphony 2 started different from the project that I created 10 years ago. Symphony 1, version 1 was a totally different project. We started from scratch about six years ago, trying to learn about all our mistakes and all the things that we got wrong with the first version. And also because we realized that beside being a framework, symphony has the potential to become a set of libraries that you can use independently. And that was the key point with symphony 2, being able to give you, developers, a lot of independent components that you can use for your own projects. The second thing for symphony 2 was trying to stick with best practices. That's why we have an HTTP foundation and HTTP kernel components. The goal was really to try to stick to HTTP as much as possible, trying to not reinvent the wheel, trying to not have a symphony way of doing things. That's also why we have dependence injection. That's why we have a dependence injection container. Symphony was actually the first framework in the PHP world to propose such a container. And again, not because it was fun, just because at some point we had so many different components that we needed a way to create the glue between all the components. And the only way to be able to do that in a decoupled way was to actually use dependence injection. And then, to create a full stack framework, being able to configure all those services, having access to a container, made things really easy. So, I'm not going to talk too much about symphony and the storage behind the framework, but nowadays, if you have a look at packages, which is the website where all the composer packages are referenced, symphony and all its components have been downloaded millions of times already, which means that we have a great community of developers using the components. For open source projects like Drupal, so we have something like 50 different major PHP projects using more, one or more components, components coming from symphony, but also for your private project, of course. And the fact that we are used, and symphony is used by so many projects out there, means that we have a great responsibility, right? The framework is the baseline. It is the foundation you are using to build something on top of it. Which means that we can't do bad things like breaking backward compatibility every other year. So, we need to have good practices there. We need to give you visibility on what's happening in the code, things like that. And I'm going to talk about this challenge and how we built a methodology and tools to help us be sure that we can guarantee backward compatibility between all the versions. The latest version of symphony is 2.6. The next one is going to be 2.7 to be released at the end of the month, actually. So, in a couple of weeks from now. 2.7 is just an evolution from 2.6. But we still have 100 new features, big and small, really. And I think the main point of symphony, 2.7 is performance. And some of the components were quite slow and we worked out making sure that they are actually much faster than they used to be. And that's the case, for instance, for the translation component and a few other ones. We also work a lot on the serializer component which is used by Drupal. It's going to be super useful for you as well. Okay, so, the first thing is we want predictability. Projects depend on symphony. You must know when version is coming out so that you can plan, out of time, the migration to the new version. Which means that symphony is not... the releases are not based on features but on a date. So we know that the symphony 2.7 version is going to be released by the end of the month and I can tell you when the next version is going to be released as well and the next 10 releases. And that's very important for a project but that's also very, very useful for open source wants. Which means that some projects, like Laravel, they try to sync their releases with symphonies so that they can upgrade from the current version they are using to the next one easily. So you know what to expect. If you want to have more information about our run map you can go to symphony.com slash run map. I think I'm going to switch to browser here. So here you can see... So this is a page, so the current version is 2... Okay, so the current version is actually 2.6 which is what we call a standard release. A standard release is maintained for a year and six months after that for security issues. We also have long-term support releases and the current one is 2.3 and an LTS is maintained for three years and one year for security issues. So four years in total. And the next LTS is going to be 2.7. So if you want to know anything about a version you can just type your version, you can check and we give you all the dates when it was released, the end of support, the end of support for security fixes. You can also get the same information as a JSON file so that you can integrate that into your tools if that makes sense. So, okay, I'm going to talk about this later on. So, we also have a Backwork Compatible promise. So there is a page on the symphony.com website. Okay, I'm going to switch... So this page, not this one, this one, symphony.com slash bc. And then we list exactly our rules regarding Backwork Compatibility. So you can know exactly what to expect and upgrade from one version to the next one. It's very detailed. So I'm not going to talk about everything here but you can see all the use cases for classes, methods, interfaces, and so on. So we tell you what we can do with regular methods or API ones. I'm going to talk about the API later on. So I only recommend you to read this document if you're working with symphony because it tells you everything you need to know about Backwork Compatibility in the symphony world. And, by the way, it took us a lot of time to get to this point. So if you want to do the same things, you can probably just copy and paste what we've done here and that to your project. It's open source so feel free to get inspiration from what we've done. So basically we try to follow semantic versioning and semantic versioning is easy to grasp, easy to understand, very difficult to actually make it work for a project. It's always very easy to break Backwork Compatibility in some ways in a version. So semantic versioning means that any 2.x plus 1 versions are compatible with the previous ones, 2.x. It's not the case for the development versions, alpha versions, beta versions, release candidates. Everything under test directory so all the tests, of course, we don't need to maintain Backwork Compatibility. That's also not the case for any class or method tagged with add internal and private stuff obviously. So we do have some public methods tagged with internal just because of PHP limitation and the fact that we are still supporting PHP 5.3. So that's not going to be the case anymore in Symphony 3 because we're going to drop Compatibility with all the version of PHP. But right now we do have probably 10 methods that are public but really private. And everything public or protected can be a class, a property, a method, arguments, type ints cannot be modified in any way. So if for any given set of input we must have the same output. That's the biggest problem that we are facing and that's also why in Symphony we have a lot of private methods, a lot of them. By default, everything is private in Symphony. Protected and public are only when we want to provide an extension point. If not, everything is private. It makes our lives as maintenance much, it makes our lives much easier because then we know that everything is private, we can refactor it the way we want. And it helps a lot. And even for protected method, for instance, we need to be sure that we keep inheritance working the right way. Which means that even if we duplicate a protected method, we still need to call it because if you override a class with a protected method and you rely on this specific behavior, we need to keep it. So it can be a bit complex. So let me show you an example, a quick one here. So kernel here. We have an init method here. It has been deprecated in 2.3. And if you actually call this method, you will have a deprecation notice. I'm going to talk about this later on. But then we still call it here in the constructor because if not, we are breaking backward compatibility. But as you can't see to be able to do that, it's a bit complex. It's not true. Because we need to be sure that when you create an init method in a class that extends kernel, you must have the deprecation notice. If not, you should not. So internally, we are calling the method but we don't want to have the trigger. So it's not really interesting for developers using Symphony as a framework. It's very interesting to understand that it takes us a lot of time to maintain backward compatibility between all other releases. So here is an example. Simple stuff like moving things around. So we have this class which was part of HTTP kernel, but at some point we decided it would have been better to actually move that to the debug component. And actually when we created this class, the debug component did not exist. So we decided to move the namespace but we keep backward compatibility. And if we have a look at the code, it's not that easy to get right. So if... So this... It's here. So this one is the old one. And if you call it directly, so if you instantiate this class directly, it's going to trigger the auto-loading. And then we're going to have this trigger error method that is called which is going to add a notice in your logs telling you that you can't use this method anymore because it is deprecated. And then it loads the new one. But if you have a look at the new one, it's here. But we extend this class which is defined here in the old namespace. And that's because we keep backward compatibility with type-ins. So even if you added a type-in for the old class, we need to make it work with the new namespace. So that's a lot of code that we need to add to make sure that whatever you're doing with the code, we do maintain backward compatibility. Okay, so 2.x plus 1 is compatible with 2.x or 2.x minus 1 minus 2, etc. 3.0 can break backward compatibility. But what we are not doing is we do not add new features in 3.0 because there is no need to wait for 3.0 to actually add new features, which means that all the new features that you will have in 3.0 are actually already available in 2.x. So whenever we want to add a new feature, we add that in the 2.x branch. And of course, if this new feature means that we need to duplicate something, all the duplication notices are also part of the 2.x plus 1 version. So do not expect any new features in 3.0, as I said before. 3.0 is mainly the latest 2.x version minus all the duplication notices and all the deprecated features, really. And also the compatibility layers. So it's more about cleaning the code than anything else. We are breaking backward compatibility because we are removing this layer of compatibility. But of course, whenever possible, we try to keep backward compatibility between Symphony 2 and Symphony 3. So Symphony 2.7 We thought it was the last version of Symphony 2, and actually it won't be. We are going to have an additional version for 2.x branch, which is going to be 2.8, and 2.8 is going to be released at the same time as 3.0, for a very simple reason. We want you to be able to wait until the next 3.x LTS version to upgrade from 2.0 something to 3.0 something else. If it's not clear, please interrupt me asking any questions anytime. So let me recap. If you are using a Symphony standard version, you need to upgrade every six months. And we give you six months to upgrade. So you can upgrade every year, something like that. But sometimes you don't want to upgrade every six months. So we also have the LTS releases. We have one LTS release every two years, which means that we need to synchronize all the LTS releases, right? But the thing is, if 2.7 is the last LTS release and 3.2 is the next one, you won't have a year to upgrade but just six months. Just because of that, we decided to add another LTS release for Symphony 2, which is going to be 2.8. That's the first reason. The second one is, if we didn't have this 2.8 release, it would have meant that the 2.7 release was the last time where we would have been able to add new features. Remember, we do not add new features in 3.0, which means that from now to November we would not have been able to add any new features. And that's a big problem. So that's also why we added 2.8. So 2.8 and 3.0 are going to be released at the end of November this year. Same feature set. Big difference. 3.0 will have all the compatibility layer removed. So 2.8 is 3.0 plus the compatibility layers. Okay. So now, we want to provide a very simple path of migration from 2.8 to 3.0. So how can we do that? So whenever we add a new feature, we add it in the changelog. So if you want to learn more about the new features, you can go to changelog. We reference everything there. All the duplications are also part of the upgrade file. So that's how you can upgrade your project from one version to the next one, which means also that if you want to be compatible with 3.0, you can start to do it today. Just have a look at the upgrade file and do all the new changes there. And we also add a deprecity tag with some commands about the new way of doing things in the code directly. So that's also something that you can have a look at. So in November, during the symphony con in Madrid, we decided to add all those deprecation notices. So it took us a lot of time. It took us about three months to add all the deprecation notices everywhere. So this is just one big pro-request doing that, but we had many of them, really. So the goal is that whenever you run your code in the PHP logs, you have all the warnings telling you you can't use this method anymore because it is deprecated, so please use this other one or something like that. And of course, we got a lot of frustrated users because symphony itself used deprecated stuff, right? So just by running symphony itself on Hello World, just the unit test, we had more than 200,000 notices for symphony itself. And that's why at some point people tried to get rid of all those notices. So the second step for us was to add an extension to PHP unit so that whenever we run the test, at the end of the test shoot, you have a summary of all the deprecated stuff that you are using, right? And we started to update the code of symphony to reduce those number of notices from 200,000 to zero today. And it took a lot of time. This is one such commit. And then we realized that it was not enough. It was not enough because dynamic code is much more complex and one such example is interfaces, for instance. So because we need to keep the type ints working for your code, we need to be able to load all those... We need to type int internally with deprecated interfaces, but we don't want to have the notices in this case. We only want the notice if you are using a deprecated interface. So we need to do that dynamically. So again, we added in the debug class loader of symphony a check that actually warns you if you are using the interface and doesn't do anything if it is internal. So we have a lot of examples like that and it took a lot of time for us to make the process work the right way. And then what we're going to change now is that we realize that adding all those notices at the end, so we edit and we deprecated stuff since symphony 2.3 so in 2.4, 2.5, 2.6, 2.7 it's really a nightmare to add all those notices after the fact. So for symphony 2.8 and for any version of 3.x really, whenever we add a new feature we will add the deprecated tag right away so that we don't have to do that in two or three years from now. And we also add a trigger to the notice in the code where appropriate. And of course we enforced that we should not and we must not use any deprecated stuff in symphony, so zero notices in symphony itself and the symphony components. Is it enough? Unfortunately no. It's not enough because in your project you might use some of the components in the 2.3 version, some of them in the 2.6 version and then some other ones in 3.0 which means that we need to be sure that all those combinations can work actually. But by default composer use the latest version of all the components in your requirement. So if you are using symphony 2.7 you will get all the symphony 2.7 dependencies but in your composer.json file you might say I'm compatible with any version starting from symphony 2.3 but how can you be sure that is still the truth? And the fact is you can't really because in composer there was no way to do that. So what we want to be able to do is to say for any 2.x component I want to check that it works for any other 2.x version of all the components that I'm using as dependencies here and also with 3.0. And for 3.0 I want to make sure that it works for 3.0 of course but also for 2.8. That way we can be sure that we are compatible all the way from 2.x to 3.0. So we edit two new flags to composer to make it work prefer lowest and prefer stable. That way we can say whenever we are running a test we are running the test for the lowest stable version but also for the latest version that is not necessarily stable. If you want to have a look at how it works have a look at travis.tml file in symphony so we are testing on a lot of different versions of PHP and then you can see an environment variable your depths low or depths high. What it means is that in this case I want to use the lowest versions possible. It also helped us upgrade our composer.json files because we realized that we were saying that we were compatible with this version of symphony component A but actually the code did not work so we tweaked all the composer.json files to reflect the reality of the code and not just what we had a few years ago really. So have a look at the code here it's pretty straightforward really. The tests themselves because in the 2.x versions we deprecated stuff but we still do have the test for them of course because we don't want to break stuff but in 3.0 the code is not there anymore which means that if we want to make the test run for all the versions we need a way to say you can't run this test in 3.0 because the code is not there anymore. So what we had is we have a group legacy tag for all our deprecated tests so whenever we have a test there is about something that is not relevant anymore we add this group legacy tag to the test which means that by default we exclude this group when running the test on Symphony 3.0 and you can't see that on the Travis in the Travis configuration really. Is it clear enough? Yeah? I'm sure. Okay so that's how we can make sure in the code that things work the way they need to work really and then we can guarantee that because the core team makes sure that you are doing the right thing you are adding the deprecated stuff whenever it is needed we check with Travis that we don't break a unit test so we have a lot of tools and methodology to make sure that we actually have a backup compatibility between all the versions. So it was the first step it's done now with Symphony 2.7 but then what about the ecosystem? So what about your code? What about open source libraries using Symphony? And the thing is you must do the exact same thing that we are doing if you want to be sure that you will be able to upgrade from Symphony 2.6 to Symphony 3.0 So we did the work with some of the main Symphony bundles and libraries really so we fixed all the deprecation notices and we enabled the test on Symphony 3.0 So I earlier recommend you that you are doing the same with Drupal just to see what you are using today and if you are not using too many deprecated features and the good news is that you can migrate today to be sure that you don't have any notices that's totally possible it's even easier for you because you can break backup compatibility on Drupal 2.8 Drupal 8 you can still break PC or not somehow So do that on Friday during the sprints I can help you if you need to To make it easy we also published a PHP unit bridge that automates a lot of what I've just talked about and again it took month for us to get it right so you might want to reuse what we've done So the way it works is that you just require the symphony slash PHP unit dash bridge library in your composer.json file in the require dash dev section and then it's going to be enabled whenever you run a PHP unit so that's how we have I haven't shown you that it's interesting so if you go on this window this one, if you go on Travis you can see at the end you have this line here and it says that we have this many deprecation notices which is fine because we are actually testing old stuff but if those deprecation notices were coming from code that is not deprecated you would have a warning the test would have been read to be sure that we never ever merge a request which is such a problem I don't think that I have an example here because we are very strict now about that but hmm let's have a look at this one for instance no, that's something different so this is the methodology that you can take for your own project if you depend on symphony you can read the upgrade file so you need to read all the upgrades files from all the versions of symphony really to upgrade your code so starting from 2.3 you must not ignore any notices that's why we have the PHP unit bridge of course you need tests on your code to make it work if you do not have tests for some features we won't be able to tell you that you have problems one thing is that we cannot give you any information but we have a lot of complicated constants and we have some of them these ones so I'm not sure if you are using those you should not but those should be done by end and also I think that there is the same problem with Drupal the very first request is very different from the next ones because in the next request we warm up the cache which means that we are running some code that won't run anymore for all the other requests so you need to be careful to actually check all the notices coming from this very first request when the cache is actually warmed up if not you are going to have some problems PHP storm is also a good IDE because it has a very complicated text which means that within the IDE it's going to tell you that you are using something that is obsolete so that's also a good way to spot problems and to easily upgrade those problems last but not the least as we are triggering complicated notices you should exclude them so at first you might have thousands of such notices so if you enable them in production you are going to have a lot of notices in the logs it can be a problem so you can fill up your disk pretty fast so at first disable that on your production servers enable that only in your staging so then I'm just going to talk about this slide for instance which is about twig because we are also duplicating a lot of stuff in twig the most important ones are the two first ones for Drupal the first one is the render tag the second one is the include tag I'm not sure if you are using them I haven't checked recently but if you are doing that you must replace them with and the names are exactly the same so for the render tag you must choose the render function and for the include tag you must choose the include function so just use Drup, it's really easy to make the change here the class loader so again you must upgrade to the latest versions of the classes so we have done that way back in the past we have upgraded to a grade from the old one to the new one it's mainly about renaming of the classes and that's all dependent injection so Drupal is using dependent injection and the container coming from symphony a lot scopes are going to be removed from symphony 3.0 because we don't need them anymore it was a big mistake to actually introduce them in the first place we were mainly using it to manage the request but it was the problem was not that we did not have the right way to manage to manage the request in the DIC it was just because adding the request as a service was a big mistake a request, an HTTP request is actually not a service so in symphony starting from symphony 2.0 I don't remember 4 instead of the request service you must use the request stack service where this is a service that gives you access to the current request or the parent one if you are using stacked request really and synchronized is also duplicated because it was added again just because we add request as a service and that's an interesting story by itself just because we did this big mistake of defining the request as a service we added a bunch of features in the container just to be able to deal with this mistake it took us a lot of time adding those crazy stuff the scopes and synchronized and actually it was really nightmare to maintain and we have so many HKCs and stuff going on and then we just realized that the request is not a service but everything was really easier and we can remove so many lines of code from symphony just because we did this mistake and the last one is about factories so the way we configure factories is a bit different now it was not a big deal but it was mostly because now we have more flexibility with the new way of defining the factories so again this change in the configuration should not be difficult to change in your code and in Drupal code are you using synchronized the synchronized feature in Drupal at some point I know that you were using that but I'm not sure if it's the case anymore not anymore and you're not using scopes anymore that's great, that's great news small changes in routing we renamed pattern to path because it makes more sense we also removed we had specialized routing classes for Apache and the goal was to make it really fast or faster when you are using Apache but at some point we realized that those classes made the routing stuff slower instead of faster because of caching problems they are removed from symphony 3.0 in the console here it's mainly about factoring mistakes that we did we actually made a lot of mistakes so we are trying to fix them step by step which takes time because we need to maintain backward compatibility again it's mainly about best practices here for the event spatcher we've removed those methods mainly because they are not that useful it makes the event spatcher slower so that's why we removed them we removed the logger interface from HTTP kernel because back then PSR 4 TouchMember 3, 4 PSR about the logging stuff did not exist it exists so we can't remove that now I've talked about in it everything else is really not that interesting the serializer we removed those methods because they did not really make sense they were not available in the interfaces anyway so we now have exceptions everywhere so you don't have to do this weird PHP mechanism of dealing with errors really and that's it so let's do it if you need any help upgrading Drupal for symphony 2.7 please don't hesitate we are here to help and if you want to celebrate the 10 year anniversary of symphony you can come to the symphony conference in Paris conference it's going to be at the beginning of December this year it's going to be at Follie Berger which is a very well known theater in Paris we expect more than 1,000 people there so it's going to be fun and that's all for today if you have any questions feel free to ask so I think we never actually talked about this mechanism probably because we did not have any use that many use cases where it would have been Follie so in symphony we try to standardize on one way of doing things as much as possible and I think the number of use cases where it would have been interesting it was just not enough that's a very good question the remaining version is not that high for us what we're doing is whenever we fix a bug we merge a pre-request in the oldest version of symphony that is still maintained and then we merge this version into the most recent one that way we are sure that all a fix is actually available in all versions that are maintained and the thing is it is almost always easier to merge from all versions instead of jumping from one version to a much newer one because you can resolve conflicts step by step we are not doing that right now because at some point you need to say we are going to maintain that for that many years and then we need to stop that being said again maintaining a version for longer is not really a big deal so that's something we can do I know that 2.4 and 2.5 are not maintained anymore but we could do that so I'm doing all the releases so it is a lot of time but actually it's a lot of time because we need to release the symphony package all the components so those are such a split one git repository for every component so that takes time and then we have the symphony standard edition we have the zen packages for our zen server we have a bunch of stuff so that's why it takes time but if we are just talking about being able to release just symphony and all the components and tag that and be done with it it's much easier so it's possible it's not that hard to be doing Drupal for 5 years yeah, random so actually do you have LTSs? no, you don't have LTSs for Drupal it's just all the versions are maintained for how many years oh ok, 2 versions so it can be 5 years it can be longer obviously so that's probably a discussion that we can have when Drupal 8 is released so depending on which version we are going to use for Drupal 8 we might say that we are going to maintain 2.8 for 3 years or the time it takes for Drupal to release Drupal 10, right? something like that so we can discuss that I'm not sure yet so what I wanted to be able to do is having tweak 2 to be compatible with tweak 1 then people convinced me that it was not needed which means that the current version of tweak 2.0 which is the master version it's not released yet is not compatible anymore with tweak 1 and then people started arguing that tweak 2 should be compatible with tweak 1 2 years ago so yeah I think it's a big problem because even if I say that I was going to use tweak 2 it means that all the dependency that you are using in your project should also have a version compatible with tweak 2 and just because tweak 1 and tweak 2 are not compatible it means that you need two different versions of your open source library and you need to maintain those two versions which is really not that cool especially for small libraries really so the thing is the language itself is compatible so a template itself is compatible between tweak 1.x and tweak 2.x the problem is the way we create extensions so if you have extensions then it's not compatible if you are just using tweak the language that's not a problem so what we are trying to do right now is make the extensions compatible between the two versions which should take care of 99% of all the use cases