Entities 201: Creating custom entities

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
you people are not going to be here anything now they can okay cool awesomesauce alrighty folks but we start this over okay so before I get started how many people I would imagine most people um use Drupal 8 okay good it's a better than Lyon session at the con um anybody done a custom module anybody done a custom entity okay cool well then this should be a lot of fun anybody that is comfortable with object-oriented programming in general okay nice so that's kind of this about so entities 201 creating custom entities we're going to go through this example and we're going to create a module with custom entity and use that to kind of talk through some of the different pieces some of the different systems we work with and I'll talk about kind of my process as I go through this and then also how I figured out how to do this hint I just cut copy and paste a lot that's kind of my secret so I'm Ron Northcutt I'm doing Drupal for awhile and a bunch of different levels I'm a taqueria I'm online is RL Northcutt in most places except G+ for some reason No so today we're going to go through and we're going to talk about the the tools that you need and the setup for what we're gonna do today and then we're going to generate a basic custom entity in under five minutes actually takes like maybe two just because in my Drupal con session I said that that I would do that show people how to create a custom in under five minutes kind of a kitschy little thing it worked and then we'll take a look at some of the basic code that comes out of that and how that works without touching anything that's just a few minutes and then we'll kind of dive into a more complex example that kind of is actually a little bit more interesting so the first thing is tools and setup so you're going to need a local development environment I'm using dev desktop here which is works pretty well you can also use Drupal vm or you can roll your own Wham mam all that fun stuff some type of base site just stock Drupal should be fine I'm using lightning Drupal console which is kind of a it's a command-line tool kind of like trush only different based on symphony console everybody familiar with that or dit maybe it's actually very powerful it does a lot of really interesting cool things we're going to see today an interesting note I actually just found out at the con that the when when Drupal console generates the scaffolding code for a plug-in or an entity or whatever you're asking it to do that that pattern is actually stored as a twig template in Drupal console so if you have something that you'd like to see Drupal console help you do it's actually not that hard kind of stick that stuff in place which is actually kind of cool and then some type of IDE or text editor I'm going to use phpstorm even though it's a memory hog because it'll tell me if I do something wrong which I actually did during Drupal con and it caught me so that saved me from looking too stupid which was nice so the first thing I want to do is we're going to create a basic entity called a thingy and a thingy is just that for those who remember my session on entities 101 and entity is a loadable thingy that's optional field goal so I figured it was suiting so the steps are pretty simple first we have to generate a module for it to live in then we actually generate the entity take a look and see kind of what spits up from that and then final step is we'll turn it on make sure it doesn't blow up and see what the results the commands we're going to be using for Drupal console are pretty simple and then we'll be using Drudge you can actually enable modules with with Drupal console I think but I still used rush because that's what I'm used to and that's it pretty simple pretty best so let's take a look at this and we will get started we see this okay bigger maybe we go okay so I'm in the dock root for my local environment so if you take a look at the list of things that Drupal console that you do it's quite sizable my system is running very slow today it's because I turn on phpstorm there we go so there's a lot of really cool things that you can do and most of what I've used it for has predominantly been around writing code like if I needed to plug in or something like that this makes it really easy to do but there's a ton of power here that not everybody uses so definitely want to look into that so the first thing we want to do is we want to generate module go and then we're just going to go through and answer a series of questions and then it's going to spit out the code so this is where it's taking in the variables that it's going to fill in to the twig template that will then generate the code from so we're going to call this thingy chain name is the same custom keys for all custom package we don't need a module file so well we'll just keep it I don't want it to be a feature don't need a composer don't have any dependencies don't want any test today and we don't need a template so there's a lot of cool things it's asking you to do that you can have a lot of cool code spit out in this case we can see here it's actually created this and there we go very simple very basic which honestly is not too big a deal right you could have written your info gamal file and that basically would have done it but again it's nice when it's it's simple like that if you were doing some of the other things like you want to mess around some tests or the templates it's nice to have a kind of starting place before you get going so the next thing we need to do is we need to generate an entity that's it and this is going to be somewhat similar I'm going to go through answer some questions and it's going to spit out some code so here we have thingy and we will be in e same the same time I'll just take the defaults and we'll let it have bundles why not sure is it revisional it should be why not and base path will be fine now this did a little bit more work you'll notice here it's actually created quite a few more things and I wonder if I can make this a little larger for you guys I know of a good way to do that or I'm happy to I have to go in and mess with the font sizes I take in both space bar it looks weird but that was a command plus now I think I have to go in and mess with the font sizes there's a very short cut okay well is this good enough we're not going to get too deep into this this should be fine I can't breathe in your bed I was listening you could actually yeah okay well most of the code we're going to be looking at is going to be bigger and it's going to be in the slideshow and I'm just cutting and pasting it over so we shouldn't have to worry too much about that so at this point let's see if it works so we're going to enable thingy go mouse wheel control mouse wheel never film is really where you this if you have a mouse that I don't have a mouse mouse yeah mass we're you know we're fine it would be okay cool so now we've enabled it nothing has blown up yet so that's good and let's go check it out in my local dev environment this I can make quicker so really well again we will see what we see so right now with the the custom entity that I just created is pretty bare-bones I didn't do anything crazy I didn't do anything fancy and as a result I really don't have a whole lot of cool stuff I can go in and I can add types of thingies those are the bundles right just like the content type and I can go in and I can add thingies themselves and then I can add fields to thingies and do all the normal stuff I don't have a have a type how to create that so I mean really at this point though the only thing I've done is I've kind of created the node entity without any of the nodes stuff that usually goes with it so not horribly useful I mean I suppose this could be handy if you for some reason wanted to have a completely separate entity for storing data or you're going to tie into it or maybe I'm going to take this now and I'm going to you know add some different functions that do different things on pre save or post save or or whatever I'm going to do but that's the next piece so right now I think the most important thing is that we did actually get a custom entity created and enabled in less than five minutes so I think it's good right okay so the rest of it from here would be expert um could be yeah and then you could call that take the config and stick in your module and do all the stuff do okay so very cool but not overly exciting so let's let's talk a little bit more about creating custom entity in this case the entity that I've that I'm going to be creating I'm just calling an asset it's basically like asset injector in the ACE although in our originally created this that didn't exist or like CSS injector d7 so the idea is that you can add anything CSS JavaScript you could potentially add like a user to store like CSS images whatever you like we want to go through and do the basic stuff make it revisional that's one problem I have with asset injector I mean in production it's gross do that with CSS but if you're doing something quick or you don't have access to code base or you're doing a quick demo it's not nice what I don't like is that it as an injector does not it's not revisional so if I change something and screw it up I can't go back so that actually is kind of cool the other thing that we're going to be doing is we're going to as part of that is we're going to take the code we're writing it through the UI it's going to save it in the database but then we're going to actually save it down to the file system the public file system that way it can be wrapped up when the rest of the CSS is aggregated and it's not going to require a corner of the database to get it and then finally we have to attach those just attaching a library in d8 of course we don't know now what those files are going to be called or even necessarily where they're located yet so that's going to be an interesting piece but what I liked about this approach is that it gives us the ability to have a a custom schema we can go through and we're going to have to write some stuff around some custom functions on how things are done what happens when you say we're going to have to deal with the file system so we get to explore that a little bit and we're going to talk about libraries and how you attach those and deal with those so it's actually a pretty solid example so the basic idea is we're going to do exactly what we just did generate a module generate identity and then we're going to go in we're going to start taking our custom code and sticking it into place and as I mentioned before all of my code snippets are actually in the slideshow so we're actually going to build it and I'm just going to cut and paste it should work unless I screw something out but hopefully you guys will be watching and let me know if I miss something the so what we need to do is we're going to have to define the database schema which defines which fields the entity has we're going to create an interface although that's kind of not necessary it's just kind of a stop point because at this point nothing else is going to be using that interface we could skip that but I think it's a good thing to keep in mind as you're going through developing your modules we're going to have to add some methods to the entity to do some of the interesting things that we want and then we're going to have to do some stuff on install to make sure that when we go save those files that there are folders there that are ready to take them we're going to write the code to save the files attached to libraries and then hopefully it works and doesn't blow anything out so I like a plan so step one you guys already know this step we generate the the module woops I just do this like that and this time we'll just call it a set because that's easier okay same machine name um good yes we need a module file no that's we don't have any dependencies right now I'm gonna have tests in this or templates although that would be kind of cool will generate go and let's do this again now in theory at some point in the future writing code is going to be as easy as this right computers are gonna be able to do all of it for us okay yeah word yeah hey it's okay they'll need us for something else don't worry okay one thing I don't like about this I'm not going to mess that now because you have to mess with the links you have to do some other weird stuff is where it's sticking it but it doesn't really matter because we can change that later we're not going to but we could no bundles although that is an interesting question right one of the things I thought about with this exercise was I'm not using bundles here but that does that is an interesting point should there should I'd split out the CSS the JavaScript and you know CSS images or whatever other assets I want to add as bundles because then they could add additional functionality and fields on top I'm not doing that but it's an interesting question we don't need to translate and revision will please also right so now we just did the exact same thing that we did before only now we have things are called asset instead of thing okay now the fun begins so the first thing that we need to do is we modify the base field definitions and make sure that we have those fields that we need so if I jump back over here and this really is ridiculously small you can pinch to zoom oh do you figure that out while we were yeah good man look at you saving the day on both sides no okay thank you that is helpful so I'm going to actually where are we I'm going to close my thingy open my asset and you'll notice we've got all of this stuff here ready to go for us but the thing we're going to be most concerned about is the actual entity that we created right here that's fantastic okay so on this section for the base field definitions you can see it's already put some stuff in place here so the basic boilerplate who the user is the name of this actual entity we can be whether or not it's published and created in change date nothing too exciting there the thing that's really cool about this that is that we actually have the ability to go through and do more than just to find the schema so if you'll notice some of the options that are already set here like if you look at name we've got the field settings for that particular field we also have some different options that are put in place for both the view as well as the form display on what those settings are so you could go in after the fact and make changes to these things but it's kind of cool that you can modify this stuff as you're defining it and then of course as you're going through your development you're gonna tweak it and come back and refine this stuff over time in fact that's the thing I found was the drush p.m. uninstall asset and then drush enable again was like my best friend until i blew things up which is going to happen that's why you want to have a dev environment that's not your main so you blow up that and then once it's relatively stable then you can pull it into your main and go to town I'm just config delete last week hey there you go so the first thing that we got is we need to actually have a place to store the the CSS or whatever it is we're using we're going to add a content field here a long string we've got our descriptions we're making it required we're making sure that this particular field is provisional no default value and then we've got some information on how it should be displayed and then we're going to be able to configure how that's displayed on the the actual display the view display so like the View mode for example nothing too crazy about this right we also need to go through and put in what type of asset this is where I potentially could have done a bundle but I thought that was a little bit overkill in this case we really only it's just a this would be the same thing is a select list you are adding a field through the UI and in this case we only have two values CSS and jazz again nothing that you haven't seen is just maybe a different way of doing it then I believe this is the last one and this is the URI for actually accessing the file this is what's going to tell Drupal where the file actually lives and you'll notice that it's a URI so we could have potentially done a URL but what I wanted to do was to be able to rely on the fact that you could use the whatever file system you had set up so public private s3 other whatever it is I think that's a lot more flexible and probably a good way to go some interesting things here some little cool things I found like add constraint so it actually has to be unique which is going to be on the entity validation just cool so we'll take care of that for me it's not translatable it's not visional it just is what it is for right now and it is case sensitive so cool stuff for this stuff I went through and there's not a lot of really good documentation like existing out there on this so pretty much what I did is I went through and looked at a bunch of core modules and other modules and that's how I figured out what some of my options were and what those things did and luckily I mean if you're looking at this it it most of it is kind of self-explanatory and there weren't many instances where something didn't do what I assumed it did which is honestly one of the things that's really great about Drupal 8 it makes a lot more sense you know in Drupal 7 you have to learn how things are and then you have to learn the quirks and then you have to learn the things that don't work the way you would think they should work because we haven't gotten there yet Drupal 8 has tons of warts but not as many and they tend to be smaller I'll go ahead and save that down and any questions about that so far pretty straightforward so um before we get going into all the actual methods that we're going to use for this remember I said we're going to go through and modify the interface now right now I'm only going to be adding three methods the interface and the ability to grab what the type is J S or CS the file name my you know global dot CS and then the file URI so can I can actually grab and do what I need to do at this point like I said I'm not expecting that there's going to be any other integrations it's just an example but again we could go through and change these things and add stuff if we needed to later so let's add the interface file and you'll notice that there's a lot of things that are already in here and this is another thing to think about too so what I am not doing in this particular demonstration is I'm not kind of going through and cleaning out any of the boilerplate and getting rid of the stuff I don't want a lot of this stuff depending on what I was trying to do I might go ahead and just do that because it's got its got stuff in here that I probably wouldn't need but we again we don't have to worry about that right now and in fact I think that's one of the big things that stops a lot of people when they start doing development is they forget that we're supposed to be agile now and they fall back into like a waterfall mentality where we try and figure everything out and plan the whole roadmap and get it all worked out at the same time and it's an easy trap to call into so my advice is to focus on trying to get something that just works and then kind of go through and tweak it and clean it up and once you have it that MVP that's pretty stable then take a look at your list of all the other hey it wouldn't be cool if we could do this kind of things and start working those things in you'll get it's a lot it's a lot more I think it's probably more efficient but I know it's a lot more productive for me to actually have something that works and then it's citing and then I want to keep working on it rather than spending you know three times as long making something that would be really cool if I really ever finish it and then I just and I'm just tired of this and whatever so hack your brain make sure that you're being excited about this stuff okay step four this a little small but not too bad because what we basically have to do is the methods that we're adding for the interface we now have to make sure they're added to the actual entity itself so that if and when something calls them there's something for it to call and this is really where the actual kind of coding starts to begin everything up until now has just been kind of getting things set up laying the foundation now we're actually getting in it and making stuff happen so I'm just going to add it to I like to keep my my field definitions at the bottom we'll put this stuff here I'm just going to drop these in don't kind of take a quick look at these so the first thing that we've got here is that we want to get the type and you'll remember down here type is the field that's CSS or jazz so all we're doing with this method so if we called up the asset the asset get type and it would return CSS or jazz so we're gonna get that field return the value I mean that's that's about as simple as it gets right you get a function that just returns a value um then it gets a little bit more complex and now we're going to actually get the file name I might have called this something different like generate file name because that's actually what I'm doing I'm not retrieving it but it's I'm lazy so get is fewer characters to type and so what we want to do is we want to grab the name of the actual file and and that's that actually the name of the asset could be anything it could be my new CSS or adjustments for the home page it could have spaces it could have weird characters etc we want to then add that extension onto the end of it so my a CSS dot CSS then just to make sure that it's going to play nicely with file systems we're going to make it all lowercase and we're going to strip out anything that's non alphanumeric and replace it with an underscore and this code is basically I stole it from in core where we doing machine names for things it's slightly modified because I made it a little took out like one extra line that I didn't think was necessary but I mean that's that that same thing right I didn't know how to do something but I knew Drupal did so I just wanted to found out where it did it and I took what I wanted which is great and then the last step is we oh yes we actually put the file name in extension together and so now we have my underscore awesome underscore stuff dot CSS so now regardless of what the asset is or how it changes or what it's called we can generate a file name we're going to do it the same way every time so whether we're saving it or retrieving it it should be the same and then finally in this in this last one get file URI we've got the file name well now we can generate it so that's easy we know the type and we're going to use that for the subfolder that it's going to be living in and so then we know that this is where it's going to live and right here I've just hard-coded it to be in the public filesystem in the assets folder now in the grander scheme of things that's a potential limitation and it'd be better if we could choose what the file system was and if we could potentially choose what that subfolder is maybe but again focusing on MVP this is a great saying I can drop in you know an app to do comment here and maybe I'll get to it maybe I want pretty good so far that's that's exactly how this entire session should go 90% of this should be yeah that makes sense like um are we good yeah okay but but you see how there each piece is simple you don't have to worry about the rest of it right and then you'll see how they kind of add together and this is a change from kind of the way a lot of Drupal 7 stuff is done where you have usually a lot more complexity there's a lot less uniformity in your approach here we're really trying to focus on getting those methods to be very simple and in fact this is probably my third or fourth iteration overall where I actually went through and made things even simpler like I took one files like you know what if it's more than like five lines in that method I should probably break it to something else because this is so simple it shouldn't be that huge so this is cool with your blade but if you're not familiar with oh oh your faces or something like that you have an additional step to sort of understand what an interface is methods are so I don't know if the application recommendation for hook tutorials and they're not about you or any tutorials out there yeah they're tons of own dependency that's that's almost half of what you're doing here no exactly that's what that did this that you see right there this is means it's talking about the object that you're working with now and you're right there's tons of object-oriented stuff out there honestly what I found most helpful was to go and start to read some of that stuff until it it really wasn't making sense anymore and then go and play with some code see how far I could get and then I would learn something or have a question and then I'd go back and read some more it's like oh now this makes sense to that context so you could actually go myself independent of Drupal grabs PHP Marmite people swim and learn basic auto functions interfaces overloading that result all those words it pendency injection yeah yeah this is not unique to Drupal at all I'm in fact it's not trivial to go to right no it's it's much scarier to look at than it is to do especially if you've got some cheat kit like Drupal console that does the scaffolding for you and you just have to worry about the PC why but I was actually looking you're talking about the serverless stuff I was looking at some sample code a week or two ago and I noticed if you look at the code you know there's um I think Java and go and Python and there's a it looks familiar if you know object-oriented I think Java was actually the closest to PHP that I saw so I was like oh I know what that means I don't necessarily know what those individual function calls me and I could look them up but once you know the patterns they repeat often alrighty so we've added the interface methods and we're just going through that recipe that I'd created and often when I'm doing some some custom code like this that's kinda know they'll make an outline of the things that that I need to do the steps in the order that I'm going to work through them in so this is actually similar to the flow that I had in my mind is I was writing this in the first place you know I had the type add the name and I had the or I when I got to this point I was like oh you know what that folder doesn't exist I should probably make sure that it exists and then it's put in and so I just go step by step and do each little piece so um the first thing we have to do for this though is that we've got to make sure that when this module is enabled and installed that it's going to go and create that folder structure that I need so for that I need to use need to create this install file so I'm going to go back to the root of my module and I'm going to create a new file the module name is asset and the file is a dot install now the good news for folks that come from d7 this is going to be incredibly familiar to you because it is very largely unchanged so first thing is we've got this hook install does everybody familiar with the concept of hooks in Drupal anybody not mostly Drupal we had these kind of magic functions called hooks and that it's called that because it's in this case we're using hook install you replace hook with the name of your module in this case asset install and so what's going to happen is that at certain points in in Drupal runtime it's going to look for things that that have this special name and that's how it's going to know how to do it so same thing with like a hook form alter or note load or any of those although we don't really use those too much anymore and so in this particular case all I want to do is as soon as this model's installed I'm going to go through and I'm going to create so I'm setting whatever the file default scheme which is going to be public um I'm going to say that this public asset whatever the public file system is is what I need to create and then I'm going to go through and I'm going to create it using the file prepare directory functions again this is something that I stole from image styles in core and then I'm doing the same thing for slash CSS since last J s so again there's a lot of room here where I could go through and improve this I could instead of doing it like this I could loop through and look at what those types were and the schema and use that to define what was being added so that it didn't matter how many types I added over time I would always my module would keep up you'll notice on the other side I was hard coding public and here I'm using file default scheme so what if that changes what if you make private the defaults that can screw something up but again what we really care about is just getting something that works today and what will get it going tomorrow the next step is we actually want to go through and make sure that we're removing on these folders when we uninstall and again I get the hook install I went over and I installed my module and I was like oh cool look you created the folders that worked and then I uninstalled the module and I was doing some other stuff and I came back like Oh crud those folders are still there I need to make sure that I'm in garbage collection so then I went and I did the hook uninstall so it's that same process you just go through and you try and think your way through it and then as you get in you're invariably going to forget things and so you just go in and do each little piece in this case there's a lovely function called file unmanaged delete recursive which I think also I got from the image styles in core um and it takes care of everything you just say the you know public asset folder and everything underneath it get rid of it so it's always nice when you can just have a single single line of code there which you know as we're starting to work with the file system you can see there's a lot of power here and stuff that it's doing and we're going to see some more of that as we keep going oh um now we've got a way to determine what this assets can be called we can store it through the UI I could actually go and start putting assets in through the UI right now if I turn it on that's all ready to go we've got a place to put it but we don't have the stuff that's actually adding it so now we need to go through and write that so the first thing I've got here and we'll jump back over to my asset PHP the actual entity is to save it as a file so this again is pretty simple and you'll notice I don't know maybe this is just me but you'll notice that as I'm going through and adding these methods a lot of times I'm using the one that I just created in the next one that I did so in this case we're using the get file URI method that we just created right above and that's how we're getting the name we're grabbing from the database the actual content that would be the CSS that we've entered into the user interface and then we're going to do file unmanaged save data and we're going to stick the content save it in that place and if it already exists we're just going to overwrite it now there is you can use file managed save data if you are if you're doing it unmanaged then you're just sticking a file out there and Drupal is like it's out there I'm done you do managed Drupal is actually going to create a file entity and it's going to track that in the UI for you which is very cool but I don't want to do that because I don't I don't need to muddy things up with that I want to manage everything within this module and I don't to confuse anybody because see well why is there a CSS file in my file let it do that must be a speed those Russian hackers again okay so now that we've got a way to save the file we should also have a way to delete the file because we're going to need to do that at some point and this is a kind of a similar thing here actually this is the first time so far we actually are passing through a parameter and in this case if it's empty we're just going to generate it automatically based on what the asset is called however I want to make sure that we had that in place because there may be times when it might have a different name or we might want to call it differently or different things can happen so this is just kind of hedging my bets here and then file unmanaged delete I mean seriously this is like ridiculously easy of course under the covers of what's going on with all this other stuff is ridiculously complex but we don't have to worry about that we let trip we'll worry about that stuff so one thing I noticed and actually I don't think I have this working quite right um actually need to tweak this is of course after I save the CSS I want to make sure that it automatically clears the aggregated CSS so it'll show up again I don't have to manually do that every single time so I've got a clear file cache for clearing out the CSS and JavaScript I took that from the clear all caches function in core and it's actually a little bit longer than that but I just took out the pieces that I need although think that this is actually not working yeah Drupal flush all caches is where I grab this from but that's okay you get the idea so now that we've got all that stuff done the next step is we actually have to go through and we have to put some of these things in place so one of the things that we've got here kind of take a step back is that you'll notice we created this this object of this class asset by extending revisional content entity base which is a base class which I think inherits from content entity base which I think inherits from entity base so there's levels of inheritance going all the way down what that means is that any of the methods that are available for revisional content entity base are also available here even if I haven't explicitly defined them and if I do explicitly define them I can actually overwrite them which is actually a very cool thing so for example if you wanted to create something like a node but you wanted to change the way that nodes did things you can actually extend the node class and then overwrite those functions with your own and so that's why object-oriented programming works so well in Drupal 7 the only way to really do that kind of stuff is either using hooks or by hacking which can get messy the nice thing about object or image is we actually have the ability to completely change anything upstream and override it if we need to so one of the things that we've got in here and actually this is actually relatively new about six months or so ago this got put into scaffolding is they actually did put these um the pre save and I think there's a there may not be a post save in this one I won't pull it up now but if you go dig in Drupal core and you take a look at the revisional content and be base and the content any base database in there you'll see there are other methods that are being called the things that are being used and that's always a good idea because you you want to know what's available and you also want to know what's going on you don't have to worry about everything else just those individual pieces you need so one of the things that is available that is not listed is the post save and to keep with my pattern I'm going to keep it with the other code that I've added here we go so post save is a method that already exists on the parent class um so when to by defining it here I'm actually overriding it which is great because now I can add my own stuff the problem is there's probably other stuff that it's doing that I don't want to get rid of unless I explicitly choose to so the lovely thing is I don't have to get rid of it and that's what this first line is so basically when it the first line in this method is to call the method on the parent and and do whatever else it does so in my post save method step one is I'm going to do whatever my parents post save method is and then do my stuff although I can also switch that around I could do my stuff first and then do that stuff or vice versa mix it out but this is great because I don't have to worry about what's happening in that in that post save method I don't have to know all the specifics and I don't have to worry about if that's doing something else that some other modules relying on and now sudden it's not there and it's going to break something in a way that I expect I don't have to go down that rabbit hole all I can do is say for right now whatever it does it's fine and in addition to that I want to do my save file which is again function method I just created and then I want to do the clear file cache so now every time I save or create an new asset and UI and it's going to go through and save the file and it's going to go through and clear the cache in the same vein there's a post delete method which you guys can probably guess what I'm going to do there basically I'm going to go through and I'm going to run my delete file function so now I've got both ends covered I'm going to be creating the file it needs to be created and then I'm going to be deleting it when it needs to be deleted pretty nice any questions so far you overload as well as a cache it two different types and do different things they module like like buddy I mean like what's like we use this for different Indies that you've fed you're designing it for one thing but you could do it at a higher level of this overloaded inside so that he would personal perform the same function but on different types of entities so if I was going to do that I would I would inherit this one so I would like extend the asset and to be like if I wanted to write stuff to files for example I would extend the asset entity I mean suppose you could yeah but I mean if I was going to go that route I would probably abstract it more and then have my asset inherit from that but be specific to CSS and JavaScript and then that other one maybe it's writing text files or PDF files or whatever it may be I know that worked in PHP but I've done some jobs John there might be a way that could be something cool to investigate and to come back and do an ADA around in the way he's arguing that we had to be revisable whatever they the revision abolish video is is content entity base is in here I returned from another right right actually so I mean it's already bad I mean see yeah what you're talking about is there it's just that yeah so it should work yeah I just don't know if we can go do it yeah I just I don't know how you go the other way and I go how are you doing I was like my one group that's a mom then you just create another way means they're just there's layers of objects entities all the way down yeah well that's good as long as that when you're trying to hear from as everything modular just broken out some really good argument to have all your functions do one thing that's exactly as if they're not then you can't overwrite those functions to do what you want you have this function this monolithic thing screws you over and you can't read and why is that you don't know you're breaking it yeah it makes it unusable but I like the question because that's what hackers do as I ask questions that figure out how to do stuff that shouldn't be done okay we're getting pretty close to the end here we've got the ability to do to create files add the files to all the cool stuff we need but now we need to figure out once we've created a file or an asset excuse me and then it creates a file we need to add that and attach it to pages is anybody attached libraries in Drupal 8 yeah it's a it's kind of weird it's it's not quite as easy as it was in 7 to me I mean that maybe it makes sense I understand why it's done just feels like it's kind of a kind of a pain although it works pretty well in this case so in order to do that we're going to actually have to go to my trusty handy-dandy module file that the scaffolding created for me now the problem here is that the module file has no idea about the entities that we're creating it's it's kind of dumb the module file just knows about whatever kind of publicly expressed functions exist outside of particular objects and so if I try and ask you know Drupal at this point to go grab me one of my assets it's going to be like oh so we have to define where we're going to get that information from so you have to have a used statement in this case the use statement is for this particular module so it's the asset module it's the we're looking for an entity and the entity is called asset which corresponds to over here in the file system where we've got the asset module SRC source and then entity and then asset PHP that um psr-4 right it's a naming convention I'm used in object-oriented with that works out pretty well so now what this means and I actually already had one there I should probably put it in place with the other one what this means is it now this um this module file will now be able to lazy load this code when I need it how I need it because in Drupal seven you could pretty much call any function that existed at any point in time because they were all there like when Drupal starts up in bootstraps it looks at every single module all the code that it has every single function and it's there which is super handy because you just call them the problem is every single time you boot up everything you do you can around all that baggage so the nice thing about object-oriented programming and especially in d8 is we're getting a little bit smarter with this the upside is that we don't have to load every single thing on every single page and every single request so I don't know if you guys have tried like I'm checking out like you know Apache bench or anything else with Drupal's API it actually gets ridiculously fast and you're making like a bunch of calls on something simple because it's especially was just returning JSON it doesn't have to render anything because it's basically calling the database formatting in the JSON and spin it back and then of course it's cached so that's what enables us to do this stuff in d8 you could do some of that if you used there's a module called js2 ever use the Jaso jewel it actually creates you have to put in a file in your doc route called JSP HP which lives next to your index.php and what JSF PHP allows you to do is instead of using hook menu you use hook J s in your module and it goes through and for each route that you define you actually define what level of bootstrap you want it to take like just the basics or you want to get at the database you want to get access control or you want to do like rendering stuff um not quite as elegant as this but it was the same idea where in that approach you actually do have to go through and define these are the explicit modules these are the explicit include files that I need to be loaded for this particular route this is a lot more elegant but it gets us there so this is where it kind of gets a little weird because typically when you're in Drupal 8 when you're um when you're trying to load a library you'll actually have a yamo file in your module that defines that library and that ya know file is going to tell you like if it's JavaScript or if it's CSS if there's any dependencies involved it's going to tell you excuse me where those things are located etc but here we can't rely on that because we don't know how many assets we're going to have what they're going to be called or even potentially where they're going to live so we have to generate that on the fly luckily there's a hook hook library info build which will allow us to do that so basically what this does is this is when Drupal is going and it's looking at all of the modules and it's looking at those library diagonal files and it's building its internal list of those libraries and what they're called and where they're locating all of that it's going to call this hook and so instead of looking at a llamó file the hook is going to generate the same thing so the first thing I'm doing is I'm generating this library blank so there's it's got the placeholders for all of the things that it's looking for but there's nothing there and then here is kind of where this magic happens this is where I'm actually instantiating the asset and I'm loading up all of the assets that happen to be there maybe it's 0 maybe it's 1 maybe it's 50 we're loading them all up and I didn't create the load multiple method some of you guys noticed but that's because it's already built in it was one of those that I don't have to worry about so now what I've got is I've got a an array of objects these are asset objects and what I have to do is I'm going to pass and I'm going to loop through this array and for each one of these what I'm going to do is I'm going to grab the information I need for each object so the first thing I'm going to do is I'm going to get the type so as we said before this is pretty simple it's just asset get type then I'm going to get the path once I have that I'm just going to determine if it's CSS or if it's JavaScript and then based on that I'm just going to go through and put it in that placeholder and start filling out that that array the way that I need it to be so now it doesn't matter how many I create when I create them what I call them how that changes the system is going to automatically build that library list based on my list of assets for me and it's going to do it regardless of what they look like makes sense this was this wasn't very tricky to figure out but there was a little bit of fiddling with it to get some of this stuff right and then going back and forth and trying to refine it and make it look a little prettier and all that fun stuff this pretty coat does matter honestly it's important so at this point we now we've done the weird thing we roll right back into what the kind of normal stuff is again and so when we're going to attach that library to a page I'm actually using this is one of the default methods for doing that this is brute force and it's basically attaching it to every single page on the site again we're thinking MVP because ideally like asset injector or CSS injector in seven you'd want to be able to say hey let's only load this for specific content types or on specific paths or in specific themes so if I was to add those features over time then this might actually get a little bit more complicated over time or I might you even use some other hooks to attach it in different places or I'm attaching it to forms or whatever undo sky's the limit but the big thing is we want to get something that works and then we can add complexity from that we're getting close the end guys I swear hope you fall asleep yet any questions so far we don't okay okay cuz you know there's a quiz right if en I'm supposed to wrong I would fail the quiz you kidding okay so the next thing we need to do is I presented an early version of this as a webinar like like a year ago and somebody actually called me out on it because I hadn't done this yet he was like um why do you have the get file your eye because you're not you didn't use it anywhere I was like well that was one of those things I was thinking about I would probably use that because file names change and I need to or was i storing it rather why am i storing the file URI if I'm not using it so let's say I go in and I'm going to create my CSS file my awesome CSS so it'd be my underscore awesome underscore CSS dot CSS because that's cool and this is great and I'm adding my CSS and it's working and then I decide that I'm going to change it I'm going to make another C another asset file and this one I'm going to take some of it out because it's not just going to be for everything I want one for the global for the global and I want one for the home page so I'm going to change my awesome CSS to global and I'm going to take some of it I'm going to put it on home page that's smart right we're going to divide things out but make it nice and tidy well the problem is that when I do that my awesome CSS CSS as far as Drupal is concerned it doesn't exist anymore so when I go and I change the name and I save it it's going to save that file down with that new name global dot CSS but that old one that my awesome CSS it's still going to be there only now it's abandoned because it's an unmanaged file so Drupal doesn't know about it it no longer has that name so even if I delete my global that's CSS because I finally wised up and I'm going to pull it into my theme repo like I should do in the first place it's it's still going to be living there until I uninstall and delete and that's just not good we got to do some garbage collection so what we're going to do here is we're actually going to create a method called dee Duke file and what this is going to do is we're going to look at the old name and the new name and if they are different then we'll delete the old one so the old name we're getting from whatever's currently saved in the database and the new name is the one that we just generate based off of the whatever the current name is relatively simple not too bad but again that's why we were storing that in the database so we can come back and clean this up so let's put in our deed OOP make sure we see we're on the Joetta remember where you live in okay so this is in place and we actually need to go through and make sure that this is going to put in a place that makes sense so we want to make sure that we're deduping at a time in the process where we haven't saved the other file yet and we actually haven't written to the database yet because we have to make sure we have an old value and a new value to compare and so the best place to do that is going to be in decrease saved so we've got our asset we've changed the title we change the CSS we click Save and before it writes it to the database it's going to run the priest say as part of that it's going to run the D dupe it's going to say oh the name of this is now global ah CSS but I'm noticing that in the database it's actually called my awesome CSS my awesome CSS CSS well those are different we run dee doop we can delete the old one now we save it now it writes the new one everybody's happy makes sense and again this is simply the the process of going through and I'm just going to add this to the end here at the process of going through and just iterating and going through and playing with it turn it on turn it off see what happens what doesn't happen figuring out how to solve that problem though neatly tightly being at where that goes and then you move on to the next issue it's just solving one problem at a time okay so at this point if I've written everything correctly I've saved everything correctly we should be good to go so now we should be able to enable this it should work or I miss something in a blow-up so this is kind of that fingers cross moment okay we want to enable it let's go well let's what up yet and looks like it worked so step one is good right don't we still got to test it but so far so good I got to tell you though when you're writing a module and you're going through this process and it blows up all the time like that there gets a moment where you really do like have a moment of panic Lizzy forward but it's a really good feeling when it does okay so let's let's refresh our structure page because you'll recall this is where it lives now although I'm not too pleased about that and there it is my list of assets great so let's go add one and see if this works call it my awesome CSS CSS file and like what was it I remember I remember now Bach Bartok is weird I was trying to come up with something that I could change that would be visible I did the body but Bartok overrides that in all these different places so um content maybe yeah main that'll be good man so we just want to make sure that we can test it make sure works well so we'll just do that should be visible right you'll see if the background changes red and you're noticing it that we can do revisions here now I'm not I'm not I don't have the infrastructure in place to go through and look at my revisions watch I guess I did yeah Drupal is even cooler than I thought yes asset one revisions and asset one revisions lovely that's okay though because it works okay so let's refresh the homepage and just make sure and that's where I said that my I don't have my flash drive I should fix that pretty confident I think I think this might work actually if we look down here we do have an asset folder with the CSS folder within my awesome CSS see so that should work fresh and bingo look at that isn't that beautiful thank you all right because I am NOT a designer folks just a code Mikey so let's let's double check and make sure all the other pieces work we'll change this to global we'll leave that create a new revision just we can see just in the D dupe save it when we should probably go ahead just saved side and if we look you'll notice that global dot CSS is now there and my awesome CSS CSS is gone so my D dupe works lovely how that happens and if we look at one of the revision tabs you get an error that's fantastic okay so that's the next thing on my list right so now I get to go through and figure out what that is it's the gift that keeps giving awesome that's good that it worked right because otherwise I've been really embarrassing okay so this is a question that that comes up all the time after my entities 101 talked people were asking me my webinar after the Drupal con session even though I said this had three people come up and ask me about it when does it make sense to create a custom entity I'm sure everybody has different ideas about things I have my own so one of the first ones I think about is the schema itself so I was talking to someone the other day and they were talking about they have an integration with some back-end system they're pulling information in to do stuff and it's like a there's like 200 fields or something per item and there's a couple hundred items so I said yeah you should use a custom entity that because it's going to be a bit of a nightmare to put you know 200 fields in your your entity but it's a heck of a lot better than having 200 or even more if you have revision turned on feel tables in your database for every single one of those fields that you need to create I mean that's a nightmare the other good thing is here and actually we can take a look this is actually putting it all in the same table so we look at assets let's just browse you can see that all of the information that I've got the ID the log message the actual content which should probably be stored as a blob that's fine all of this stuff is in one single table which is pretty quick and pretty efficient so if you're talking about the need to have a whole bunch of different fields custom scheme it starts to make more and more sense the the more crazy and the more complex it becomes if you need additional methods so in Drupal 8 everything is an entity but there are different types so notes or content entities have different stuff that happens when you save or you pre save or you do whatever you're going to do taxonomy terms have different things comments do different things those are entities users do different things so different entities have different things that need to happen in my case I need to write files delete files d-do check things all this other stuff that you never do with a node so I could have probably created a content type I could have stored stuff there and then I could have written some monkey code to go through and do stuff using some super hooks that would have been an old-school way this is much simpler and this is much more elegant and the other thing to think about is sometimes stuff happens and you don't necessarily want all the stuff that goes with it but like you might say I want to add notes to different pieces of content well that could be a comment field right but I don't want other things that do stuff on my site with comments to effect that or I want to do that but I want to do something else with it like I also want to push it out to this other system or have it send an email or do whatever it's going to do those are times when I start thinking about does a custom entity makes sense again if you have additional workflow steps things that you have to do as part of this that are on top of what's already happening you might want your own or as we said before if you if you just want to extend the default methods you're like you know a node or a comment would be absolutely perfect here except every single time on the post say I want it to send something out to HipChat or whatever well great I'll just create a custom entity I'll extend comment and maybe the only thing I'm really doing is I'm adding something into post save to do whatever that can also be cool if you don't want to have that live in a hook which is everywhere or you only want to load the code that calls HipChat or whatever when you need it as opposed to more often etc so those are the kind of things to think about luckily it's a lot easier now to create custom entities than it used to be hopefully you got that sense final notes here as we were talking about earlier with object-oriented programming no I honestly believe the best thing to do is just get your hands dirty so my slides are up there actually if you go to Drupal con Baltimore this is the session up there my slides are there the codes up there if you want to pull it down and play with it but I would just highly recommend you just make something and just monkey about when you got a couple of free hours um just get something done get off the fence and as I've been saying you know start simple uh you guys anybody here know you know who Tim Plunkett is right so Tim's a he's a pretty heavy hitter in Drupal these days Tim is actually the guys that got views in core and he's just ridiculously smart and he knows Drupal um as well as anybody but I was talking about it and the way that he did it was was very gratifying because it's probably the way I would have done it but I would have felt like a fraud is he went in and he took the views module and he basically added an info dot yeah mol file so da could see it and then he turned it on and then something broke and so he fixed whatever broke and he turned it on again and something else broke and so he basically just kept doing that he just kept going through and cycling turning it on seeing what broke fixing that until eventually he could turn it on a wouldn't break and then he'd go trying to use it in something would break and what he ended up at the end of that process was he ended up with a modified version that worked and did what it needed to in da and I think at that point he eventually ended up refactoring the whole thing anyway um but the point is he took a very simple approach even for something ridiculously complex like views so if you've got something cool that you want to create and I would suggest that you just created and just know that the complexity will come over time did he had you to testing you know by chance I'm guessing like that would be very important that month is if it's not is now not breaking but Jenna won three robot I would imagine so I don't know if he did it at that point or later but great at some point but the approach was hella great I was like wow that's that's why what I would have done it's lovely so homework I always give homework that's why people never show up to my sessions so the first thing to do is make sure you have Drupal console and go spin up a module and create a thingy entity and go play with it and see what that looks like see how it works seriously it'll take you like five minutes to create it and ten minutes of monkeying around with it and then you can throw it away and never play with it again so if you did nothing else but that it really does help to get your hands dirty um go find a module that needs to be ported maybe honor you or find one that is almost there needs some help or has some issues or find someone to work with maybe it's like the Drupal dojo or something like that um your house you know if you have something that you're working on um you can let me know and I will help you if I can and I will say that now and that's pretty ridiculous I say that all the time in meetings because I know most people won't take me up on it but I kind of feel like it's dangerous to stay here because somebody might yeah so and it's gonna be on you and it's yeah the entire world is gonna be calling you go party at Ron's house thanks guys thanks guys but hey yeah I mean we could do a sprint and go through and work stuff out you already know my process make a change see what breaks figure how to fix it go to the next thing that breaks that's that's how I work lots of other resources out there probably much better than this but to go check it out hopefully this gets a start and look look for an opportunity right look for a place that makes sense to use a custom entity even if it's simple and you know if someone can pay you to learn that's great so follow best practices it'll be good you're not shortchanging you wanna because you don't do anything crazy but every single time you do it you'll get better and faster any questions where's the code the code if you go to the Baltimore Drupal con site it's on my session there which is custom creating custom entities right there oh that's a really good call catch you um if I can do this there it is Drupal con custom entities and there's a video that's not going to do a whole lot of good because it has the audio but the video is stuck on one screen and doesn't change so if you ever want on sessions like that yeah so if you ever want to like listen to me drone on like I'm having trouble sleeping seriously it's you know you could do that I don't mind um and then on this page there's a link at the bottom for the slides and there's a link to download the exact one we just created which will be exactly well it won't be exactly the same some of the methods might be different place I don't know you guys can can figure that out any other questions I'll make sense was this helpful yeah it really kind of go through that process a little bit I was pretty cool to listen to very well trying to pop is that usually you try to look at a module that is how finish and polished and things are so complicated because so many variants I would I've been Cheerilee thinking about creating a podcast or something without module creators and try to make them take you through the process like how the hell is module started where is this simple first function that they created and how it evolved because uh that way that you get to our earn yeah otherwise it's so complicated that you don't go where time well and that's that's the thing I think so many people just get discouraged because they look at something and it's like oh man I could never write something like that because if they thought about everything yeah it's like a cheese it's like well no actually some of them did some of them are geniuses and they did think about everything and they probably wrote that that would take me a month in like a day but I think a lot of people are probably a very similar boat where you do something and it's relatively simple and then you add a little more and a little more and eventually you turn around and you look and you've got any you've got all this these files and all this crazy stuff that's going on and somebody else is asking you as I call man how did you figure all that out it's like oh just it one thing at a time you're gonna go make a custom instant oh I'm all sure man I'll treat it maybe is anybody gonna create a custom entity now oh yeah okay good I love the streamlined that you everything is to sink the database and we met at and there's no no extra stuff that you're making like you say right I mean now you can extend stuff on core very easily yeah exactly which is the idea if you have a question um good I mean preparing the answer but get few want to say that configuration and configuration rather than in the database oh is that hard to do how much well so I could have become a weird to do with this but yeah I mean config entities are different I haven't played with them too much to be honest with you I'm because they're kind of their own little thing is renewable household scaffold for that do can be as opposed to I think there is let's look samples module oh that's a there you go I think this will but yeah I mean that's the thing right you go find someone who's done it and you copy their code so it looks like yes generate entity config so you can create a new birthing entity really I thought that was going on here yeah well and then there's all the other stuff you can do with config so that's the kind of thing that you know at work I wish sometimes they would do that just like you know two hours of playtime on Friday go mess around like okay I'm going to see what these commands do we go break my dev site and fix it um yeah you can do that on Thursdays at the triple toe joke there you go always selling yes sir Jack we shan't stop here please mentioned the Drupal console necessary like installed is there like a fairly lengthy process no you can use composer actually um we're going to do it again this is over last time I tried excuse you command the run oh yeah it does but I didn't try to run that Highway yeah you can noisy I can drag it around the first thing oh I've jumped into my route here I'm no longer in a Drupal on site and so you'll see I'm not getting that full list I'm only getting some things because I have installed in my system but yep and saw like per site which kind of sucks but it says you know you need to run this against the Drupal order a giant issue in Google is so you have to do is validate your site and globally I don't know anything the recommended method is to install it first sight what's your blame the composer stuff yeah you have your now supposed to install everything Russian composer so to use the Drupal project drupal composer start organizations then it will actually give you your triple size plus Google console plus crush and it's all included once in your one anyways a little things ever they don't do this relation trouble composer or tuple projects well so that installs entire ah yeah then if you need to install it on an existing site thank you most constructions yeah yeah basically couple to require Drupal comfortable I think at the very least that will work so I'm gonna find it my vendor directory yeah yep there you go change execute composer required yes basically it probably that's basically it well I mean you know yeah they're excellent accessories and when it doesn't you have a new problem to solve right great win either way basically yeah but I don't I don't use Drupal console like for everything like most of my dev sites I've got quite a few on here don't have it I usually just have it one or two because I really only use it for stuff like this I used rush most but in my case it keeps on working even if I haven't globally I've never install it I probably did install it one side was used to try things out but I just used a global console so far been working yeah that's what I was I did that before once where I had it set up globally and I didn't have to do it for sight but I thought I did the same thing when I reloaded my system two months ago and now I still have to do it per site so I think I don't know just in our recent releases when it were they added that with water when she just fell it was per site so you might have an older version oh yeah I installed it I may have updated it but I installed it okay cool so there might be a way to do globally we've figured out then probably did the wrong way I've done the wrong way about 12 times thinking around Google yeah that's the secret to my success okay awesome and that's right total imposter shame do awesome well thanks everybody
Info
Channel: Austin Drupal Users Group
Views: 3,151
Rating: 4.8620691 out of 5
Keywords: Drupal, Drupal 8, Entities
Id: _blyY7em5Ag
Channel Id: undefined
Length: 84min 1sec (5041 seconds)
Published: Wed May 17 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.