 Hello everyone. Hey there, that's a huge room. Not so many people though. No, I'm really happy that you're here, that you're coming to my session. I'll be talking about Pooley today, which is a tool kit that me and some other people have been working on for like one and a half years now at a slow pace, but it's coming on and it's coming on nicely. So I wanna talk about it today. I'm happy that you're here too. Yeah, listen to it. So for those that don't know me, I'm known as WebMozart on Twitter, or in my real life, my name is Bernhard Schussig, which is a German name. I'm from Austria, but we speak German. It's a horrible name internationally. Nobody is able to spell it and pronounce it, which is why I rather go with WebMozart. I'm a symphony core developer for like plenty of years now. Like since 2009, I've been developing a lot of components of symphony and as you know, Drupal 8 builds on several symphony components. Who has used symphony before in this room? Oh, that's some of you. And who has used Drupal 8 before? So you have used symphony. All right, so I'm also the symphony thick representative who has heard about the thick framework interoperability group, right? So Larry's here, Larry's the representative of Drupal. It's basically a group that tries to make it easier for different projects, different PHP projects to work together so that, for example, Drupal is able to integrate packages or modules or any kind of codes by other projects without being isolated in just the Drupal world. And it's the same for every other PHP project. So we try to build interfaces between different projects to make it easier to share what we are working on. And Puli is very much about the same thing as you will see today. So I'm Puli Core Developer since 2014. That's when the project started. And in my professional life, I am a PHP and symphony trainer and coach. So especially for the parts that I'm specializing in symphony, which is the forms component and forms related stuff I'm doing training. So if you're interested in that, head over to my website on webmodes.io and check it out and get in touch with me or come to talk to me after the session. I'm a bit sick today, so please bear with me if I'm low on energy, but I'll try to give my best. All right, so what is Puli? To start with, I wanna show you a little video. It's also nice to wake up. Max, you're killing me. Hey, everybody, John May. See, John May? And Dave, John May, too. Can I run and get a Bud Light, man? For the great taste that won't fill you up and never let you down, make it a Bud Light. We've seen this one before. So where's the connection to Puli? You might ask, and it's a good question. So the connection to Puli is that this dog that you saw in the video is actually called a Puli. It's a Hungarian dog and it's pretty cool because when you see it running, it looks pretty funky, you see, like this. And if it's sitting there, you don't really see its eyes. It's kind of a little bit spooky as well. You never know if it's watching you or not. It's a pretty cool dog, my sister had one, and I thought, oh, if I wanna start a project, I will call it after this really cute dog with this great character that's so ambitious. And so I did. It's a very special dog in Hungary, which is why they have it all over the place even on the stamps. It's kind of crazy. Anyway, I'm not talking about dogs, I'm talking about PHP development, right? So who is a PHP developer in here? Right, so most of you are, I guess so. So you know that back in the 2000s, early 2000s, when we developed an application in PHP, and some people still do, but I hope not too many, developed it like this, all the application, all the code that was contained in that application was written by ourselves, right? So you knew every line of code, you perfectly knew what you were writing and what the application was doing, because it was all yours. Today, and since we had Composer, things changed a little bit. Who knows Composer? Who used it before, right? So as you know, Composer is a package manager that facilitates reusing code, like using packages that other people developed, much like aptitude, apt-get on Linux, or RPM on Fedora or similar systems, on Node.js, for Node you have NPM. So Composer is basically the same thing, but for PHP. And Composer became possible to write an application, but not write everything ourselves, but to take existing pieces of software that like open source packages and reuse them in our application. The Drupal is doing the same thing with Symphony, right? Symphony provides a set of components to build web applications. And Drupal thought, why should we build everything ourselves when there is existing code that works and that somebody else is maintaining and fixing bugs for? So we can just take advantage of that. And you should be doing the same thing in your applications. In fact, you already are if you're using Drupal, because then much of the code in your application isn't written by yourself and isn't maintained by yourself, but by the Drupal community. And as a rule of thumb, the more third party code you use in your project, the faster you can develop and the less bugs you introduce, because normally every time you write the line of code, there's a probability that you have a bug. And the more lines of code you write, the more potential bugs you have in your project. So the reuse of existing high quality packages, like the ones from Drupal and the ones from Symphony or any other PHP project is key to success in your applications. Now if you're looking at Composer, then the responsibility of Composer is to install packages, right? You can type Compose install and Composer will automatically fetch packages and download them from different sources. But Composer will also resolve the dependencies of each package. So if your package or the package you install depends on another package, Composer will install both of them. And at last Composer also takes care of auto loading. If you're using a class in your application in one of these packages, then Composer makes sure that this class is found. If we look at a Composer package, then painted graphically, then it more or less looks like this. You have some PHP code in a directory. The directory is the Composer package. It contains some PHP code and the Composer.json file that configures how Composer should install the package and its dependencies. In your application, Composer is kind of at the bottom level, bottom layer. You have these different Composer packages like a translator or a templating engine or a block module or a dependency injection container or whatever you have. And you install them with Composer and then on top of all these packages you build your application. So at the very top you have your domain logic, your business logic and in between you need some codes to integrate the packages that you installed. But what does it mean package integration? I'll give you an example. If you're using a translator in your project and I'm like just set back for a minute and imagine that you're not using a framework or something like Drupal but you're actually writing everything from scratch, right? Let's just keep that in mind. So if you're using a package for example, a translator, then you need to tell the translator in some way where the different translation files of your application are located. So a translation file is a file that contains translations from one language like English to another language like Spanish, right? And if we have such translation files in our application and in different packages that we installed then we need to tell the translator where all these translation files can be found. I'll give you another example for package integration. If you set up a templating engine like Twig then you need to tell Twig where to find the templates that you are using. So for example, your applications templates might be located in some use directory in your project. And then there might be some templates in all the packages that you installed. It's still easy enough to follow. Very good. Another example is a dependency injection container. If you install that in your project then you need to tell the dependency injection container which services you want to load and how they should be configured. And you could probably add some classes that can be found in different packages in your application. All of that is package integration of what I call package integration. Taking the packages that we have and making sure that they work together. And if we look at this, then we see that there's really a lot of work necessary to make sure these packages work together. And in the worst case, each time we install a new package we need to integrate it with all the other packages that we already have, right? That's not what we want. Developers generally are lazy. Who in here is lazy? I am, definitely. And the rest is just lying. Otherwise you wouldn't be developers. Developers are so lazy that they enjoy finding or taking time to invent some sort of solution for being lazy tomorrow, right? You write so much code tomorrow because then tomorrow, today, because tomorrow you can just run this script and then you don't need to spend the time anymore. We kind of forget to think that we are really spending a lot of time today. But nevertheless, tomorrow we can just hit the button. It's awesome. So I want to do the same thing with packages. I want to just install them, plug and play, like in a WordPress application where I just install this plugin and it just works. I don't really know what's happening in the background that I don't want to know, but it works. So we want, or I want to minimize the effort that is needed to install a package with Composer. And luckily frameworks are doing that for us. So something like Drupal or something like Symphony or Laravel, whatever other PHP framework you want to mention does those things that I was talking about. And the way to solve this is by inventing a type of framework specific package. So for Symphony, these are called bundles. In Sand Framework, they're called modules. Then type of three, for example, has extensions. In Drupal, you have modules as well. And all these are concepts of packages that are custom to a specific platform, right? If we abstract this package concept a little bit, then it's very similar to the package concept we had before. It's still some kind of directory that contains PHP code. But this time the directory can also contain resource files. That's something like a CSS file or a template, HTML template, or a JavaScript, whatever. Anything basically that you need in your project that is not PHP code, I'm referring to as resources, okay? So your framework package has PHP code, resource files, and then if it's distributed with Composer, it also has still this ComposerChaseIn file that tells Composer how to install the package. And you know how it looks in Drupal. Here's an example for Symphony. A Symphony bundle contains PHP code, then it has some extension class for the dependency injection container. It has some predefined directory names where you can put all the translation files and CSS files and templates and all that stuff. So if you follow these conventions, then Symphony is able to use this package, this bundle. The problem is you can't install the same bundle in a Drupal application because Drupal modules expect different conventions than Symphony. And it's the same for Laravel. If you want to use this bundle in a Laravel application, it doesn't work. Laravel has different conventions. If we look at the layering of our application with framework-specific packages, and we see that things changed a little bit, we still have Composer on at the bottom that is used to install different packages. We still have our domain logic of our application at the top. And now in between, we have some sort of framework or platform. And the platform or framework does mainly two things. It's a standard toolkit. So it provides you with a select set of libraries that you use in your application. And it's a set of conventions which help you and all the other co-developers in your team to work together effectively, right? You have the same conventions as the framework. So it's also easy to hire a new developer that is familiar to these conventions. Then the framework also does the package integration work that I was talking about before. So you don't have to configure these translation files anymore because that's all handled by the framework or the platform that you're using. Now, there's a problem about that. If we look at packages, who in here has used packages before? Who knows what it is? So packages is, as you know, an online repository of Composer packages. So anytime you call your type Composer install, Composer is actually contacting packages and downloading the packages from there. And if you look at packages and look for packages, then you see that there are many kinds, many different kinds of packages. So at one hand, we have regular libraries that you can simply install and configure in your project. But then you also have all these framework-specific packages like symphony bundles. Drupal modules actually in packages. What's happening about them? Does anyone? Not yet, okay. Are you working on that? Okay, so it's possible, but it's not the case yet. But for other frameworks and platforms that use their own package concepts, you can find the packages and that used Composer as well. You can find the packages on packages. And that's kind of a problem. You see all these little dots and all these different silos, you could say. If you're a symphony developer, then all you really care about is independent libraries and symphony bundles. If you're a sent framework developer, all you really care about is those, still those independent libraries and sent framework models. And if you write a project that is not based on some platform, then all you're really able to use are those libraries in the middle, right? Anything else on packages is practically useless to you. And I think that's a bad thing. I'm referring to that, this package fragmentation. We have all these different sub-communities of their own frameworks working on their separate things instead of working together. So for example, if you're looking for twig and packages, you can find twig bundle, a twig module for sent framework, twig integration for key, which is another framework, twig integration for lithium and many other frameworks. And you see that all these framework-specific packages that are used to integrate the templating engine into some framework are basically doing the same thing. So all these communities are really wasting time solving the same problems. If we look at what all, what these framework-specific packages do, we can basically find five responsibilities. One is to access resources in a package. So for example, if you have a template in a package, then the framework provides a mechanism for loading that template. Or for accessing that template. The second responsibility is to publish public resources. If your Drupal module, for example, bundles some CSS files or JavaScript, these files need to be published on the web server in the document root in some way so that users, when they open your page or your application in the browser, can download them and use them. The third responsibility is to generate the URLs of these public resources. Once they have been published, we still need to put the right URL in our HTML so that the browser is able to find our image, our CSS file. And the last two responsibilities are access of specialized resources. So before we had the example of a translator and translation files that can be located in different packages, and our framework usually gives us a way to connect the two. And it's the same thing for classes. If your package has some special classes that need to be found by the framework or by some other package, then the framework implements a mechanism for that. And since all these frameworks are implementing these different packages and solving the same problem, again, we have a lot of waste of time and waste of efforts going on in the community. So about two years ago, like me and some other people, like Bo Simons and Amy Stevens, recognized these problems and started thinking about possible solutions and basically found that PHP needs some sort of unified package integration tool, something like Composer, but with more power, right? And so some time later, I started working on that and the result is what you see is Puli. In Puli, a package is still very much the same thing as you know right now. If you have a Drupal module, that won't be very similar or very different to what a Puli package is. In general, it's still a directory that contains some PHP code and resource files. And if you just reviewed it with Composer, it contains the ComposerChaseInFile telling Composer how to install the package. But then additionally, you can find the Puli.ChaseInFile that tells Puli how to integrate the package in your application. And the nice thing compared to before is that here we don't have to follow the conventions of the framework anymore. You can lay out your package any way you like. You can call your classes any way you like so you can follow the conventions given by Drupal, for example, as long as the Puli.ChaseInFile that you bundle in your package tells Puli what those conventions are. If we look at different layers, they look very similar to before, but still a bit different. We still have Composer packages. At the bottom domain logic at the top, we still have our framework or our platform that is providing some standard toolkit or ant conventions. And then between those two, you have Puli which is taking care of integrating all the packages you have. And the nice thing is now, if you use Composer packages with Puli, it doesn't really matter which framework you use on top of that, right? You can use Puli packages with any framework and any platform that supports Puli. The goal is to be able to install and enable packages simply by running Composer install. So plug and play, just install and everything should work. Basically, that's not all true, but that's the goal. And the second goal that I have is to have to use different high level packages, like a blog engine or some web debug toolbar or a profile or something like that, but in different frameworks and different tools, platforms. So right now, if you develop a profile for Drupal, you can't use it in your symphony application. If you're working on a different project where you want to reuse that code, and I want to make that possible. So if we look at Puli's architecture, it looks basically like this. We have our application, and all these boxes are basically Composer packages and components. Our application uses Puli's repository, discovery and URL generator component. I will be talking about those later so that you hopefully understand better what they are. And then you have a Puli command line interface that you run on your console, on your terminal, to interact with these components. I will show you later how that works. The command line interface reads the Puli.json file in your package and all the packages that you have installed, and then configures how Puli works in your application. So let's talk about some features of Puli to get a better idea of how it is used and how it's working. The first feature I want to talk about is resource access. Resource access is some way of finding files in your packages, like a template. And with Puli, if you want to render a tweak template in a package that is called Batman Block in this case, you would use this so-called Puli path to access that file in the package. So a Puli path very much looks like a UNIX path, which is a good thing, it's very familiar. You can use existing tools and PHP's functions to process paths. And basically, every Puli path consists of two paths. One part is the path prefix. In this case, that's batman slash batman slash block, which is mapped to some physical location in your project. Here to the resource directory in the batman block package. And you see, by convention, we're using the same path prefix as the package that contains the files. So it's very obvious if you read such a path like this one in your code base where Puli is looking for these files. So the path prefix is mapped to this resource directory in this package and then Puli just appends anything that you write after that path prefix and tries to find the files. It's very straightforward. Has any of you used a class autoloader from Composer before? I guess each of you did. So basically, that's the same thing. In Composer, you tell the autoloader what the prefixes of your classes are, of your namespaces, and you tell Composer where to find the classes. Then Composer basically just appends or transforms your class names and the namespaces into directories. The same thing is here. In practice, this looks something like this. You use Puli's command line interface to create the mapping. So you write Puli map slash batman slash block to the directory RES for resource. And then Puli will create a Puli.json file in your current directory, which is your package, and add that mapping to the Puli.json file. It's very simple. For applications that are not shared, that are not going to be published on packages, you can use a very simple slash app prefix to have kind of global files. So the path become a lot shorter this way. And now using these paths in Twig is very straightforward. You simply pass the paths whenever you include or extend or import a different template in Twig, for example. But the good thing is, if the template that you are currently working in has already been loaded with Puli, then you can simply use relative paths, right? So it's the same thing as you use in your file system. You load a template from the same directory or from parent directory, and that's very convenient. Puli takes all the Puli.json files in the packages that you have installed in your application, reads all the mappings that are contained in these JSON files, and then puts the result in what is called the Puli repository. So the Puli repository is very much like a virtual file system. You can visualize it with the Puli tree command, and you see here all the files of application, here all the files of the Batman block package, and here all the files of the Thor Transator package. When you run the command line that is during build time, then Puli reads all the JSON files installed in your application and creates an optimized data store. And during runtime, Puli simply uses that data store to locate the files that you have. So as you see during runtime, there is almost no performance overhead to any other way that you would use to locate files or to hard coding files, if you want it that way. Ideally, you're also using the cache like varnish in production, so in that case, your Puli's not accessed at all and there's little to no performance impact in production. So I'm already using Puli in the live in a production project. It's still in beta. You shouldn't do that if you don't. Expect to be changing your code, but I'm doing that and there's no performance difference. There's also a very big project in Germany that are using it for configuring the way that packages work and they're very happy with it. Also with the performance, it's very nice. All right, are there any questions so far? There's a question here. The question is how Puli integrates with Twig. There is an extension that is integrating Puli and Twig with each other, right? Okay, let's talk about a different feature or subsequent feature which is overriding resources in other packages. So very frequently when you use a module or something like that in your application and then module contains Twig or HTML templates or CSS files also, then you come into the position that you want to customize some of these files, right? So for example, if we have some block module which contains a template which extends from a generic layout with HTML and HTML hat and HTML body and the generic layout of your application, then you don't want to use the layout file provided by the package, but to use the one in your application since usually you have some special design with a sidebar and a menu and a header. And you want to use that even for the block, right? So the question is how can we change the file in this package? Now you could just move into the package and change the file there, but then the next time you hit Composer Install or Composer Update, the change will be lost. That's not what we want. With Puli, this becomes a lot easier. You simply copy the file to your project where you can safely change it and run Composer Install. You do the changes that you want to do and you tell Puli that this file should be used instead of that file in the package. The way you do that is like the precondition is we still have our application with the two packages with those different package like path mappings from slash app to the resource directory in the application and slash Batman block to the resource directory in the Batman block package. Now you can add another mapping to the application for a different directory and tell Puli to look for files with the Batman block prefix in that directory. So that's nothing new, right? You simply have a new directory in your application that is supposed to override some other directory in a package. But in this case, you can explicitly tell Puli to do so. Puli will recognize that the Batman slash Batman slash block prefix has already been mapped by a different package and it will remember to override that package when it is installed. So on the command line interface, you use the same command as before, Puli map slash Batman slash block to this like block directory in your resource directory and then Puli will add that mapping to you. Puli.json file and also remember that your package is overriding the Batman slash block package. So whenever somebody else installs your package and the Batman block package, then Puli will follow all these override statements and respect them. And one important thing to notice about overriding resources is that you don't need to copy all the files in the package to your custom location. You can just copy individual files and customize them and Puli will first look into this directory and then if a file is not found there, look into the original mapping. And that's all. That's really as simple as overriding can get and with this override graph, it can have very like complex relationships between packages. You could have, for example, theme packages with a sort of base theme and then a more specialized theme and then maybe an even more specialized theme that add and partially override their base themes and use this as a way to create themes for your application. Are there any questions about this? The next feature I want to talk about is URL generation for resources. So usually if you bundle public resources in your package, like CSS files or images or something like that, then there is some specific directory that contains these packages. And with Puli, you can do the same thing. You can bundle your public resources in some directory that you can name any way you like. In this case, unnamed public and then generate resource URLs with the URL generator. So in Twig, for example, there is a resource URL function where you simply pass this Puli path and the function will return the URL of the resource. Again, this supports relative paths, which makes it very convenient to use in practice. And at some point, this could also be supported in CSS files. So as you know, right now in a CSS file, you have to use the URL function with the actual URL, but you could implement some gulp plugin or something like that to turn Puli paths into actual URLs. And why is this needed? The reason we need this or the benefit that we have is now we are independent of where the resource will be published on the server. So if you were writing a package or a module that is shared with someone else, then people who installed your module can decide where your resources are going to be published and placed. You just refer to all of the resources with their Puli paths, which are universal, right? They don't change. The next step before your L generation is actually possible is to register a web server. So whoever installed your package also has some directory that is the document root of your web server, like here, for example, public HTML. And in this root package, you register a new web server for that directory. You do that with the command line again. Puli server dash dash add public HTML, which is the directory, and you can name this with some arbitrary name. I used local host here, but you can use anything you want. It's just the name, it's just a way to refer to this later on. The second step is to publish your resources. So if you have your public resources in the slash app slash public directory, you would call Puli publish slash app slash public and then the name of the server you want to publish it to. For example, local host. If you use a CDN, a content delivery network, you could also add a new server for the content delivery network and use the name of that here. And now as soon as you did that, you can generate the URL for your resources in the slash app slash public directory. For example, slash app slash public logo PNG will become simply slash logo PNG, right? Since this directory is mapped to the document route. You can also map on publish files to subdirectories of the document route. For example, Puli publish Batman block public to the block sub directory. And then any URL you generate for that package will have the prefix of that sub directory. So that's a very convenient way to manage the public resources of your different packages and to actually control where those public assets are published. There's a question over there. So the question is, if it's possible to have different mappings for the development server and the production server, right? At the moment, it's not, but that's something that is an open issue actually. You can also change the way that URLs are generated, like for all of your projects. For example, if you want to implement a very simple versioning mechanism, not a lot of people are doing that, but it's just an example. You can change the URL format of your server. It sees a simple print F string where person S is the public path of the resource. And you have slash person S and then some query parameter. Now, when you generate the URL for that file, the logo PNG file in the Batman block package, you see that the query parameter for the version is expanded automatically. And the good thing here is that if you want to change the version, you only need to change the configuration of your server, then all your URLs will be generated correctly. That's a question. Yes, the command alters the JSON, the pool.json file that stores the configuration, right? So the same mechanism can be used to generate absolute URLs. If you again change the configuration with the URL format in this case, hdbexample.com and again person S, then all the generated URLs will have the prefix of the hostname. Technically, this works very much like the repository that we saw before. So during build time, when you execute the command line, pool you read all the pool.json file in your project, generate some optimized data store and in production, this optimized data store is used. So again, there's very little performance impact. And also like before, if you use some sort of cache or compilation step, for example, tweak templates are first compiled to PHP and then executed as PHP on the server. If you have a compilation step like that, then pooly is not used in production at all, which is very nice for performance. Now the obvious next feature of the generating the URLs of our public assets is to actually publish the assets to the server. So we want to move CSS and image and JavaScript files to the appropriate location on our server. The good thing here is that we already added a lot of information to our configuration that tells pooly where our files are located since that configuration is necessary to generate the URLs. Now we can reuse the same configuration to actually publish those assets by running pooly publish dash dash install. And here all those assets will be installed into the appropriate location automatically. And as soon as you did this, all the URLs that you generated before will work. So you see it's very simple. The problem is that this is not really a responsibility of pooly or something that pooly should solve because there are already so many gulp and grunt and different JavaScript front end toolkit plugins that you can use to, for example, install files with SSH or different protocols. So in the final version, I would like to move this functionality out of pooly and to some plugin for a front end tool. And any questions about this? All right, then let me talk about the last feature of pooly that is probably the coolest one as well. For that I need a volunteer. So Larry, I'm sure you want to volunteer. You always do. Awesome, thank you. So if you would come to the stage, it would be nice. Thanks. So this is completely unscripted. He doesn't know about it. Scary. So let's talk about resource discovery, consumers and producers. We have an example that I gave before. I set up with application and two different packages that we installed. And one of those packages is a translator which uses some kind of loader to load messages or message files. And those message files could be contained in other applications and packages. And there needs to be some way for that loader to discover where those files are, right? So pooly calls these different kinds of packages, consumers and providers. It's very much like a message queue, which is a similar concept. You have a topic and then some publishers can publish messages to the message queues and subscribers can subscribe to messages for the same topic. Here it's a very similar thing, although it's not a message queue, it's basically just packages that want to communicate with each other. In this example, we have a consumer which is the package that Larry created, the translator package. So an example, Larry is the developer of the translator package and I am the developer of some block module, right? So Larry creates the translator and wants to have some way to find translation files and catalogs. And I, as a user of the block package, know about Larry's translator package, I want to use and support that in my package and add a translation file that should be found by Larry's translator package. The way to do that and to achieve that is that Larry defines an API, a topic, some string, this is called a binding type in Puli. And a binding type is a simple string that is prefixed with Larry's vendor name, which is Thor, pretty awesome. And an arbitrary name that specifies the kind of resource that you want to load, right? So catalog in this case. And then Larry is able to use this binding type to fetch all the resources that match the type. So Larry finishes his package, uploads it to packages, writes some documentation, of course, because we all do, and publishes in the documentation that there is a binding type, a Puli binding type called Thor Catalog that you can use in your own packages. So I read that and I think pretty awesome. I want to use that too because it's nice. So I bind my message file to the Thor Catalog binding type. And now as soon as you, as end user of both of these packages, install both packages at the same time, they will be wired up and use each other automatically without anything else that you need to do. Technically it works like this. You, like Larry in this case, uses the Puli type define command to define a new binding type. This binding type will be added to the Puli.json file of Larry's package. And then he's using the resource discovery of Puli to find all the resources that are bound to that type. So ignore this double loop for a second. It's not so important anymore. The important thing is that it can get all the resources for this binding type and then do something with them. I, as a supporter or as a provider for Larry's resources, I'm using the Puli bind command to bind resources in my package to that binding type. And use the end user, simply create a new translator from Larry's package, use Larry's Puli message loader that is using a discovery, and then start using the translator. And that's all you need to do. Any package that you install that binds resources to the binding type of Larry's package will automatically be recognized. Thank you very much. If we summed it up, then we saw that Puli has different Puli.json files here with bindings and the binding type at the bottom. All of that together is under the umbrella of Puli's resource discovery mechanism. The architecture is very much the same as before. Whenever you enter a Puli CLI command, a console command, Puli is creating a data store, an optimized data store that is used during runtime. So again, there's very little performance overhead. Are there any questions about this? There's a question here. Yes, the question is if there's a direct dependency between the provider and the consumer, yes there is, but they don't need to be installed at the same time. It's an optional support for each other. That's the first thing. And the second thing is at the moment, you would need to bind your resources to different binding types of different consumers, but there's room for the framework interoperability group, for example, to define common binding types. For example, to say, okay, we have a message file format that uses a fake binding type, then anybody that wants to use that common format, that standardized format, can bind to that standardized binding type. All right, so actually there's one more topic I want to talk about, but it's a very short one because it's not implemented yet. And that's the loading of services in different packages. So service in this example is some PHP class that implements some interface. Here the interface is called extension. And very often you want to load different classes from different packages that implement a specific interface. That's what I call the service loading. And that's something that Puli will support pretty soon, but that's not finished yet. So I don't want to talk about it too much. All right, to conclude this very technical talk, I want to talk a little bit about the future of PHP and PHP development as I see it. That's very exciting because with Puli, it's possible to write truly plug-and-play packages that can be hooked in your application and configured automatically to work with all the other packages that you have. And for example, if you want to install Twig with Puli, suppose that Twig supports Puli, which it doesn't at the moment, then you would simply require Twig with Composer, instantiate Twig's environment, which is basically the engine pass the Puli repository to Twig, and that's it. Now any package that supports Puli, as soon as it is installed in your system, you don't need to configure anything anymore in order for Twig to find the resources in that package, right? It all has been done for you. By having these universal plug-and-play packages that work across different frameworks, we can achieve much less community fragmentation than we have right now. So we get rid of all these sub-communities like Sanford, Morgan, Drupal, and whatever, and instead start working on universal PHP packages together. And I think that's a huge opportunity because we get so much workforce that is divided on solving the same problems in different ways right now and can start working together on the same problems and common solutions. So in the future, instead of installing something like a Twig module or extension or package, you will simply install Twig and it will work, no matter if you're working with Drupal or anything else. With this, we can achieve much less code application in the community and much more collaboration. We can have more collective time as a community to work together on great features. And I think that's a good thing. So talking about the current status of Puli, it's in beta, right now it's in beta seven. So I would like to release the next beta version next Sunday, I hope that's possible. And there is a stable release planned for 2015. I'm not quite sure if we can make that. It depends a lot on the contributions that we get because right now we're about three or four core developers and we need to be more. But if you're interested, just send me a message or come to talk to me after the talk. Yeah, I can show you some give us some information. You can find extensive documentation. So everything that works right now is documented. On docs.puli.io, I'm also working on a website that presents what Puli is in very simple terms and simple concepts. On Puli.io, it's not finished yet, but very soon. Puli's used successfully in production at the moment. There is a symphony bundle that integrates Puli into symphony applications if you're using symphony. And there's also a symphony distribution that is basically readily configured with Puli. There's also a couple of projects that want to support Puli out of the box in the future. So one of them is symphony, of course, since I'm a color developer there. But also type of three and Nios want to use Puli for solving or organizing their extension systems. Elkuli, which is an e-commerce platform, also do the same thing. And I was talking to Taylor Ottwell from Laravel and people from Sand Framework that are also interested in using Puli for organizing their packages. And that's a good thing because if many frameworks and big frameworks start using Puli, then only then we can actually have true interoperability between those frameworks. If you have any feedback, please shout out to at PuliPHP on Twitter or follow PuliPHP on Twitter. Go to puli.io when it's done. Get involved, there's an issue tracker on GitHub. And that's all I have to say. Follow me on Twitter if you want to have any updates about Puli or a symphony or any other work that I'm doing. And that's it. Any questions? Do you maybe want to go to the microphone? It would be easier. Thank you. So I have a question. So you'll say that the idea between Puli is to integrate the packages. So I don't have to make a package for symphony or for Laravel and all that. I didn't understand from the talk where I can, for example, I use Gazel, okay? So I'm using Laravel and I did a service provider and a facade, so it's easier to use on the framework. And this presentation was more based I think on physical files and mapping them. So I don't see how I could use Puli. So my Gazel package would work on symphony and Laravel and all that. That's because this kind of problem can only partially be solved by Puli. That's more something that should be solved by the framework interoperability group by, or maybe it can be solved, maybe it can at least it can at the moment by defining some common service provider interface for integrating services into any framework. Okay, so the framework would need to be supporting Puli to make that work. Yes. And Laravel I have to put in the config file that the service provider and the facade. So I need a specific package for that. Okay, yeah, well if Laravel supports Puli out of the box, then you can load that service provider, or Laravel could load that service provider automatically using this discovery mechanism that I showed. Okay, so at the current state I can't do that. I can't make a package to wrap Gazel and work the way I want. I still have to use the package that exists for Laravel to wrap all of that. Right, at the moment that's necessary. I don't know if it's something related that you told about the service loader that you didn't talk too much on the presentation. Exactly, it's related to the service loader I was talking about. And also another thing that is important to mention is that Puli doesn't solve all the interoperability problems that we have. It's just one building stone like we had the PSR4 auto loading standard that was the very first building stones for having interoperable code. We have Composer, Puli is another building stone and now we need many more standards from the framework interoperability group like PSR7 for request and response for unified requests and responses and more of that to have truly interoperable packages. Okay, thank you. That's important. All right, so I think I'm out of time. Thank you very much. If you want to talk to me, come to me. I'll be around. Thank you.