 I feel like it's close enough to 215 for me to start. And I'm also gonna put my phone way over there so that it doesn't distract me while I'm presenting because it has a tendency to do that. This presentation is going to be about the form API in Drupal. Specifically, the Drupal 8 form API, though there are a lot of tangents to the Drupal 7 form API as well. So a lot of the things that I'll talk about are true for both Drupal 7 and 8. Actually, six in a lot of cases too. The syntax is different, but the concepts are mostly the same. It's Thursday afternoon at DrupalCon, and this is the last session of the day. And if you somehow mistakenly wander it into the wrong room, or you get bored, or you don't feel like listening to things about to form API because your brain is melting, I will not be offended at all if you get up and go find something else to listen to you, so feel free to do so at any point. A little bit about me. First, my name is Joe. I currently work at Lullabot, and at Lullabot I'm part of the DrupalizeMe team. I spend a lot of time creating training videos for Drupal and doing things like talking about the form API and teaching people how to use it. I've been doing Drupal development for about 10 years now. I was thinking about it this morning actually, and the first Drupal sites I built were with Drupal 4.5, which actually predates even having the form API in Drupal, which is kind of crazy. In addition to doing the Drupal development, I'm also very active in, or working at Lullabot, I'm also very active in writing documentation and contributing there for Drupal. So that's a little bit about me. What I'm gonna be talking about today are forms and how they work and how specifically how they work in Drupal. It's gonna be a pretty high-level overview. I'm gonna, there's gonna be some code examples, so I'm not going to get into real depth on anything. What I'm hoping is that people will come away with a better understanding of the whole system of how forms, like the existence of forms in Drupal, and have some of the terminology you need to be able to go and look these things up on your own. There's way too much complication in the form API to explain it in one 50-minute session. So I will appoint you at some documentation references that will hopefully help some of the trickier bits. Before we can talk about the form API though, I think it makes sense to define what forms are. So when I'm talking about building forms, this is what I'm talking about. That's not actually what I'm talking about. That would be a sweet form. Forms are the tool that we provide users of our website to come and give us data. It allows us to display a widget, like a button that they can click on or a text field that they can enter information into. They're one of the fundamental ways in which people interact with websites. And this is especially true for content management systems. And if you think about it, like our ability to create a view in Drupal would be, well, you could do it, but it'd be really difficult to do without a form where you could click things together, give the view a title and that kind of thing. We wouldn't be able to log into our Drupal sites without forms. Forms are like one of the most important things in a content management system. Without them, it really wouldn't be all of that useful for end users or us as administrators. The standard HTML form looks something like this. This is getting crazy. Wow. So standard HTML form, what your browser sees and interprets into the thing that users are seeing. This is a really simple example. You've got opening and closing HTML form tags, some labels that label the field and saying, this field has a label of hero and this one has a label of other. And then HTML provides some very like sort of primitive data types for forms, if you will. Select list, check box, a text field that you can enter things into. Your browser sees that HTML and turns it into a set of widgets that your users can interact with. They can type text into that box, they can select something from the list and then they can hit a submit button. And the browser takes the data from the form and submits it back to the server or to Drupal in our case so that we can take the data we've collected from someone and do something with it. So that's kind of like the premise of forms, right? They're a tool that allow us to get information from the users of our site and then do something with that information. HTML forms on their own, though, are pretty complicated. And I think that they're really prone to us as developers making mistakes when we're creating them. This is kind of the context. This is why the form API exists. The form API exists because forms on their own are really hard to make secure. There's a lot of things that you have to take into account when you're letting people type something into a text field and then submit it to your server. Who knows the XKCD little Bobby tables, right? Somebody types in drop tables and then oops, they deleted everything in their SQL database. Because without proper sanitization, that kind of thing can happen. That's the extreme though. There's all kinds of other things that we don't think about. If we're writing forms on our own, we have to think about those things or we're compromising our application and our user's data. HTML forms, because they're just HTML that's displayed in the browser, are vulnerable to the concept of local modification. Meaning someone can edit that form and make it their own form and then submit it and that new form will send whatever you put in that form to your server, which is maybe not a good thing. What if they added some new fields or what if they removed some fields? Most of the things, like that security stuff is fairly boilerplate. So it's really easy to like, once you know how to do it, you can do it. But boilerplate also means prone to mistake. If we're just copying and pasting things or reusing the same code over and over again, it's really easy to just go, oh yeah, yeah, I got that part and leave something out and forget it. So a big part of why the form API exists is to make it easy for us to have that security without having to really spend a lot of time thinking about it. There's tons and tons of other reasons, but we'll get into more in depth into each of those throughout the presentation. I like to give this example of the problem with standard forms and one of the things that Drupal allows us to not have to think about. So if you go to the Amazon website, I thought I'm gonna buy a Kindle for everybody at DrupalCon, right? So I went to the Amazon website and my video's not playing, is it? Oh, oh, fail. It's like not playing in my preview. Here we go. Yeah, okay, here we go. So I went to the Amazon website and I said I'm gonna order a Kindle for everybody that's gonna be at DrupalCon and I go to the form and the maximum number of Kindles that you can buy from Amazon at one given time is 999 and I was like, well, I think there's gonna be more people than that at DrupalCon. So I opened up the Web Inspector in Chrome. I saw the form and I went, oh, this is cool. I can start making changes to this form. So I found the select list element and I changed the HTML for that element and I changed it to like, I don't know, a really large number. Actually, I changed it to a pile tone because I'm just gonna get a pile of Kindles and bring them. So I make some changes to the form and this is true of like any HTML form. People can see the HTML on your page. They can make changes to it. So after I make the changes, I, this is really hard because I can't see what's going, I'm trying to narrate this thing but I don't see the preview. It allows me to change the select list, select the value that I just said, and hit submit and I've just added a pile tone of Kindles to my cart. Granted, Amazon would actually probably not care that much. They'd be like, okay, I guess. But this is, I think, a really good example of the types of things that we totally forget to deal with in our forms but are really, really important. The church is prime. Yeah, so I did this and then I went, I like, this is cool, I recorded the video, I added everything to my cart and then I like closed the website and go away and I come back like a week later because I'm like, I need to order some toilet paper. And so I go into Amazon Prime and I put some toilet paper in my cart and I'm going through the checkout process and it's like, you know, buy with one click. At the last minute I'm like, why is there like a million dollars in my cart? Yeah, so I almost hacked myself, I guess. So that's kind of the stage here, right? Forms allow people to interact with our site. However, forms are inherently pretty insecure and there's a lot of complex things that we need to do in order to make them more secure. I'm gonna talk about the Drupal Form API and how it allows us to not have to think about those things quite as much. The Drupal Form API was in its sort of current form was introduced during Drupal 4.7 and has been iterated on since then. Prior to Drupal 4.7 there was still a Form API but it was drastically different than what we've got now. What we've got now is a sort of continued evolvement of that. Drupal's Form API is sort of a PHP abstraction around the HTML forms. It allows us to do things like create that standard HTML form through PHP functions, method calls, defining arrays, allowing Drupal to handle the actual HTML for us. So which we'll talk about why that's really beneficial. And I'm gonna talk a lot about sort of the life cycle that a form goes through in Drupal. So how do forms get created? When somebody presses the submit button on a form, what happens? What's the code that Drupal calls and what's the sequence that it calls it in and why? And I'm also gonna talk about some of the additional helpers that Drupal's Form API provides that you just can't really do easily with standard HTML forms. Somebody comes to your website and they go and they view a URL, like they go to say slash contact. And on the slash contact page, there's a form that they need to fill out. This is true of any page in Drupal that provides a form. They go to the URL, there's some form there, and they have to fill it out. When your browser requests that URL from Drupal, part of what Drupal does during the whole figuring out what its response should be is it determines that this is a request for a page which contains a form. And so it instantiates Drupal's Form API. It goes through the whole process of asking your module what the form should look like. It turns it into the HTML that is necessary and returns that to the browser. The browser then just sees an HTML form, just like the one that we had on the Amazon.com site, but this one was created by Drupal. Once your browser has that form, users can fill out the form, put whatever data they want into it, and then click the submit button or the save button or hit enter, whatever it is they do to submit that form. When a browser submits a form, it takes all of the user's entered data and encapsulate it into either a post or a get variable in most cases with Drupal forms. We're dealing with data that's posted to the server. Really, it's just, the browser takes care of taking all of those user input and putting it into a little package and sending it to the server. Or in our case, to Drupal. When it does that, your browser posts back to the exact same URL that you retrieved the form from in the first place. A lot of times, if you've written your own form, one of the things that you have to do is you define an action attribute for the form tag and you say, when somebody submits the button, this is the URL that it should go to. In Drupal's case, it always goes back to the same URL that the user is at when they're viewing the form. But this time, when it's processing that request for, you know, this is a page that contains a form, Drupal recognizes that there's incoming post data in the submitted request. And so it says, okay, the user must be submitting the form because there's additional data here. So it takes that additional data that was submitted and it starts to validate it. Drupal does some of its own validation routines. That local modification thing that we saw with amazon.com, Drupal provides a way to prevent against that by actually taking what it does is when the form is first built and sent to your browser, Drupal actually stored a copy of that form. And then when you submit the form, Drupal's taking the form that just got submitted and it stored copy and it's comparing the two. And if anything's different about them, it throws an error immediately. The error says something like, an error occurred, please contact the site administrator and you're like, I am the site administrator. This is not helpful at all. But in a lot of cases, that's what's causing that error in Drupal is that something has changed about the form that was submitted from the browser between the time that it was built by Drupal and the time that it was submitted. Once Drupal has done its own sort of really basic validation of the submitted data, Drupal will call out to the module that originally declared the form and ask that module, would you like to perform any additional validation on this data before I continue processing it? And your module then has the opportunity to say, I actually wanted a phone number in that field. I'm gonna go ahead and raise an error on this data or on what was submitted for this form. And it decides, I can't continue processing this form because there was one or more error detected. As soon as an error is detected, Drupal will take care of actually rebuilding the entire form and marking the fields in the form that have an error. So it usually highlights the form with a, I think by default it adds some red borders around the text field and it adds a list of errors up at the top of the page so you can see what fields have an error. One of the things that's really awesome about the Drupal form API is that it'll actually perform all validation routines before displaying the form again to get errors corrected versus ones that do the thing where it's like, how often have you filled out one of those forms where you're halfway through the form or you fill the whole form out, you hit submit and it's like email address is required. You're like, okay, so you fill out your email address, you hit submit and it's like phone number is required. You're like, huh, so you fill out your phone number and you hit submit and it's like phone number is invalid, you're like, oh my God. So you fill out your phone number at the right when you hit submit. Drupal will actually perform all of those validation steps at the same time and it'll just display one big list of errors and ask you to correct all of them. It then builds a copy of the form again just like it did the first time around, turns it into HTML and sends it to your browser. Your browser now has that version of the form with the errors displayed and your users can go ahead and correct whatever is causing that error. Hit the submit button, your browser sends the post data back to Drupal again. Drupal goes, check it out, somebody's posting data. They must be submitting the form instead of trying to view it. I'm gonna go ahead and run the validation routines. Does the same thing. It compares it against the cached version of the form. It calls all of your modules validation routines. If everything passes validation, Drupal's like sweet. I know what to do. I'm gonna go ahead and call the submission routine. In this case, it's gonna call out to your module and say, here's all the data that was submitted in the form. It's already passed validation so I know that it's ready for you to use or at least it meets the standards that you set up here. The required fields are filled in. The phone number field looks like a phone number, that kind of thing. And then your module can take care of, in that submission routine, take care of just the things that it needs to do with the submitted data. So save it to the database or send an email or whatever the case may be. So that's kind of the high level overview of how Drupal handles form submissions. What I wanna do now is kind of get a little bit more in depth into each one of those steps of the process. So how are forms built? How are forms validated? And then how do we handle the data that's submitted with a form? There's also the, just kind of talking through that a little bit. There's like, this is some of the stuff that makes Drupal forms way better than just standard HTML forms. We get that type of automatic workflow. Like we get the part where Drupal took care of just calling my validation function. I said, nope it's not valid. And then Drupal took care of rebuilding the form, displaying all of the errors, posting it to the user so they can see it, letting them submit it back. And I didn't really have to do anything other than mark the field as that doesn't look like an email address. Drupal also provides some automatic security for us. That thing like the fix for the local modification where it compared the form that the user submitted to the form that was stored in the cache. We also get some really big benefits like because Drupal's form API is a abstraction around HTML forms and we're letting the form API sort of create the HTML for us, we're gonna get much more consistent HTML output than we would if we were just having to type that entire form by ourselves. And this is really nice because we can ensure that like all of our forms have label fields and the label has the correct attributes and they're in the right order and linked together that actually the form API will help deal with a lot of accessibility stuff by adding the appropriate attributes to text fields and that kind of stuff. This is really awesome. It means that I don't have to think about that stuff for the most part. The form API also has the ability for us to, because their forms are defined in PHP and not as just a string of static HTML, we can manipulate other people's forms. So for example, I can manipulate the node form from my module. And this is one of the things that makes Drupal really, really powerful, right? Is my ability as a developer to say, well, on the node form, I wanna add in an extra checkbox that when somebody submits that form and that checkbox is checked, my module can take care of doing whatever super special custom business logic I have to do for my application. But I don't have to rewrite the entire node form. I can just add a little bit in as needed. If this was like, if you had to do that in an HTML form, you would have to like write a regular expression to parse the HTML form and inject your checkbox in there somewhere and it would not be fun. So this is that workflow again, but kind of illustrated more from the code perspective and less from the browser and Drupal talking to one another perspective. What I'm gonna do through the rest of this presentation is basically go into more detail on each one of these points. But the basics is this. Drupal has a form builder class with the get form method. Get form is kind of our doorway to the form API. We call get form and say, I would like you to return a form by doing so, Drupal now knows, okay, this is a request that requires me to do all of this workflow and processing for a form. In our modules, when we wanna provide a form, we do so by implementing the form builder interface. This provides a couple of methods that we need to implement in our PHP that are basically so Drupal knows when I'm going to build the form, where should I go to get a definition of the form? When I wanna validate the form, where should I go to validate the form? If there's post data, we validate it. If there are errors, we raise them so that Drupal can highlight them and display them in the form. If there are no errors, because we're implementing the form builder interface, Drupal knows I should call the submit method on your form class. And then in our code, we can deal with saving it to the database or sending an email or whatever we need to do. All right, so building forms is the first part. You need to put something together that someone can see when they come to your page. I've got a lot of code samples throughout the rest of this, excuse me, that I'm gonna use to talk about how some of these things work. I will warn you that they may be a little bit inaccurate because this stuff is still changing somewhat for Drupal 8. And most of these slides were put together a month or two ago. I tried to edit them all this morning to make sure that they were still accurate but they might not be 100% perfect. But I will again point out the documentation, which should be kind of at this point considered the canonical source for how this stuff works. So the first step to building a form is calling the get form method and giving it the namespace of a class that defines our form. So in this case, the my form class is an implementation of the form builder interface. By calling get form, Drupal just, at this point is basically saying, okay, this is a form API workflow and I need to be prepared to do things like render the HTML for a form or deal with submitted data and so forth. This replaces the Drupal 7 function, Drupal get form, but otherwise does essentially the same thing. You're calling a piece of code that says, right here, start the form API for this specific form. We can either call this directly in our module if we want to, so if I wanted to just say, right here in my code, start the form API up and render a form, or what is more common is actually defining a route. So in your routing.yaml file, you would say, when someone goes to this URL, instead of loading a page controller, I'm gonna load a form controller, which would be the same thing, an implementation of the form builder interface. And in that case, all Drupal is doing is just calling this code for us automatically. A really basic implementation of the form builder interface looks something like this. You've got four methods that are, I would say, not required, but you will most likely implement. And I also generally recommend starting by actually extending the base form class in Drupal 8 instead of just, you could say, my class is just a vanilla implementation of the form builder interface, but by extending base form, you're actually gonna get some benefits, which we'll talk about, but things like being able to more easily access the database abstraction layer, things like adding submit buttons and such are a little bit easier. The form builder interface has these three methods, build form, validate form, and submit form, which do pretty much exactly that. The first one allows us to define our form and what all of the fields in the form are going to be, what that form should look like. We're essentially saying, this is the data that I would like to collect. The validate form method gets called after somebody submits the form, and Drupal said, there's post data here, I'm gonna go ahead and call the validate method from your form class in order to allow you the opportunity to perform whatever validation it is you need, and if it passes validation, it'll call the submit form method. In Drupal 7, this is basically the same workflow, it was just instead of implementing methods on a class, you just had to make sure you named your functions the right way. So you would have my underscore form, and then my underscore form underscore validate, and if that function existed, Drupal would automatically call it. This is basically that same principle. If the method exists on your class that builds the form, it'll call it, Drupal will take care of calling it for you automatically. Inside of your build form method, you're gonna start to write some code that looks something like this. This is a pretty standard form API array. We see these a lot in Drupal. Sometimes you'll see the words form API array and renderable array used interchangeably. They basically mean the same thing. These are arrays of properties and elements that Drupal will use, each of these is the definition of a field on your form that Drupal will use to figure out what HTML to put in that place. Form API arrays, I said, are made up of properties and elements. Properties are always anything that starts with a hash sign, or is, so here you can see I've got the second one on the list, property two. Properties do exactly that. They describe the properties of an element in this form array. So if an element is something like, this is the name field, that's an element. This is a checkbox field, that's an element. Properties define a name field as of the type text field. So Drupal goes, okay, you must want the HTML for a text input field. I know how to create that. You say, I wanna add a title of name next to my field. So Drupal goes, okay, now I need to create an HTML input tag with a label that says title. So these properties are how Drupal translates sort of what you've defined in your form API array into the HTML that's ultimately displayed for the browser. Kind of like this. Well, not kind of like this, exactly like this. So this is that defined, or forms are defined by really giant nested arrays that are rendered into HTML for us. It seems a little bit weird at first, because you're like, why wouldn't I just write the HTML? I know how to write the HTML for a form. But defining forms as arrays like this allows for a lot more flexibility for both our module and other modules inside of Drupal. It's a lot easier for PHP to deal with an array and to just move elements around in an array, to change things about an array than it is to deal with one really long string of already rendered HTML. There are about a million different properties that you can use in the form API. And one of the really challenging things about it is knowing what those are and how to use them and when to use them. The best place to get that documentation right now is if you go to api.drupal.org, you go to the Drupal 8 tab, you click on forms here in the list. This will take you to a page that kind of has an explanation of this overview of how the form workflow works, and it'll link you to this page. Actually this is only like maybe like one 100th of the page. It's this giant table that says on the left hand side you can see a list of all of the different possible properties that an element could use, and across the top you'll see all the different element types. Anytime we're defining an element in a form API array, the most important aspect of that is we have to tell Drupal what type of element this is. So that might be a text field or you might have a check box or you might have a select list or you might have some that are a little bit more complicated than that like a password field or a file upload field for example. When you're on this page and you're looking through it on both the left hand column where we've got the properties and the top across the top where you can see the element types, if you click on any of those it'll jump you down in the page, this page is huge, but it'll jump you down in the page to the definition of that particular property and it'll also almost always show you some examples of it being used. I find this is really helpful so that I can in a lot of cases just kind of copy and paste this into my form and start modifying it and getting it to do what I need. I encourage you to take a look at this, the documentation for the form API arrays is a good starting point for just kind of understanding what all of the available elements are. Unfortunately they're not all documented though because there is an opportunity for any new module that we install to add additional elements to this list so it gets a little bit confusing but the majority of them are documented on that page and it's a great place to start. Most of the properties that you define on a form API array are just doing simple like strings of text that are kind of metadata telling Drupal this thing is of the type text field this thing has a title of name and so forth but some properties are actually special and they're not just a single or simple string of metadata in cases like this element validate property this one is one that takes any sort of PHP callable so a function or a namespace and a method name any code that could be called in PHP and it'll do things like say when this particular property is being accessed by the form API I'm actually gonna call out to this function and then do whatever that function says so be aware of that as you're reading through the documentation I found that to be really confusing at first I'd be like I don't quite understand how this is working in a lot of cases what it is it was just saying right here I'm defining when this particular element when this form is submitted and this particular element is encountered I'm gonna validate that element or perform some additional validation on it by calling this callback function it's really not as hard as it looks and since forms make up all of our interaction with Drupal almost every module ever including all of the modules in core implement forms and they provide a really great place to go and look at how Drupal core does this and use that as a learning opportunity for saying okay on the node form I can see that there's like three stacked check boxes I wanna figure out how to do that in open source you know how you do that you copy it and you paste it and then you change a little bit and now it's yours so form API is some really simple properties like text you know this thing has a title of name it also has some that are a little bit more complicated but can allow us to do some really cool things the form API in a lot of cases tries to make the user interface patterns that we present to users reusable in Drupal so that they're consistent so that whenever you know somebody does that thing where you click on a check box and now new elements appear on the page that that experience is consistent across all of our forms this is called the state system and this works this is kind of just a quick example of basically what this does is like in my form API definition of my form by telling it a little bit about using the state system Drupal will when it's rendering the HTML for this form actually render some JavaScript as well and it'll allow me to do things like change the visibility of a field based on the value of some other field without having to write any JavaScript to do it granted the JavaScript to do it is probably pretty easy this is another one of those like kind of prone to failure things because we go oh yeah yeah I know how to do that click click click I'm done but maybe you forgot a step or if you copy and pasted it it's not quite right every time I find this to be a little bit easier you can actually see how this is kind of working too in the state's definition I'm saying I'd like to affect the visibility for this element here's the jQuery selector for that element and I would like to change it based on the value of some other field so in this case I'm saying based on the value of the select list I would like to make this visible so if someone chose unicorns in the select list the field would be visible Drupal's form API also makes it a lot easier to do Ajax same thing it's just defining a couple of properties in our form API array and Drupal will take care of kind of essentially writing that JavaScript for you so you don't have to think about it this example is really like almost all you would have to do to a form in order to say instead of having this be a complete HTTP post and refresh cycle just submit this via Ajax and what it's gonna do is it's gonna say when somebody clicks this button instead of refreshing the page just let Drupal take care of everything that it needs to do and call this PHP function for me so I don't have to write all of the jQuery, post, error checking, wait to make sure something was returned Drupal will take care of that for us and then this is probably my favorite part about the fact that we use he's really complicated arrays to define form elements if you think about it, HTML forms have some really primitive elements that we can use like a text field and a checkbox and a simple file upload widget but Drupal's form API allows us to define much more complex patterns and reuse them things like think about a five star rating widget in most cases a five star rating widget is like a set of radio buttons you've got five radio buttons but you've got some CSS and some JavaScript that replaces the radio buttons with stars and then when you click on them the JavaScript says check the box for that one and so forth and that's really cool but that's a lot of additional code to write in Drupal with the form API we can do things like define a new element type that encapsulates all of that complex user experience into just a reusable thing so here I've got Drupal 8 and Drupal 7 both have this concept of a managed file element and when you create a new form element and you say type managed file and you define like two other properties what you get is not just the widget for uploading a file but a widget for uploading a file that's Ajax enabled that can show a progress bar that once somebody clicks submit instead of just getting the path to the file it actually uploads the file and it inserts it into Drupal's files table and it gives you the unique ID of the file entity and it's just done all of that for you just because you said this is a pound type managed file we also get Drupal allows us to sort of define forms as an array and then just kind of clone that piece of the array and have multiple sets of fields without having to write those same fields over and over this is really awesome because if you've ever had to like put two address fields on it like HTML form you're like billing address and shipping address you have to write basically all of your code twice you have to write the shipping address field and you have to be like address street shipping address street billing address street or address zip code shipping address zip code billing you have to like duplicate all of that because HTML expects each one of those form elements to have a unique name Drupal can allow us to deal with that by using the form API arrays and then of course because our forms are defined as arrays and so are everyone else's forms it means that Drupal gives us the ability to manipulate other people's forms. This is the hook form alter or hook form form ID alter functions that you can implement in a module at their core what these functions allow you to do is say after the form that the node module is building has been all that form API array is assembled go ahead and let any other module that wants to make changes to that array before it's turned to HTML and displayed on the page and this is how things like the whole field system in Drupal works. The field module implements hook form alter on anything in Drupal that has a that you can attach fields to and at that point it says okay I'm just gonna start starting the field definitions here as necessary this is what allows modules to say I'm gonna customize the way that the user login form works by instead of rewriting the entire user login form I'm just gonna add one additional step of validation to it so I can say for my particular site users have to write their passwords in all uppercase I guess I don't know that's a silly use case but it allows you to kind of modify other people's forms so that's the this is how a form gets built when somebody views the URL on your page like slash contact and Drupal knows that there's a form there it calls the form builders get form method which delegates to your classes build form method that build form method returns one of these giant nested arrays that defines the structure of your form Drupal turns it into HTML sends it to your browser your browser renders it and presents it to the user when somebody clicks this submit button that form is sent back to your back to Drupal from your browser and this time around Drupal says there's post data so instead of building the form I'm actually gonna call the validate form method followed by the submit form method if everything passes validation so in my class I've defined a validate form in a submit form method the nice thing about this is that Drupal has already taken care of the taking the information in the HTTP post request and turning it into just a simple array that's this form state array which will now contain all of the values that were submitted by the form and it's pretty easy for me to start accessing them I can also know at this point when it gets to the validate form method that Drupal's done things like check to make sure that the form that was submitted is the same as the form that I sent to the user to prevent things like local modification in this example I'm raising a simple error so I'm just checking to see if the value of the name field on our form is equal to Joe I'm gonna throw an error by calling the set form error which in this case this is one of the reasons that I find it's nice to extend the base form class rather than just implementing the form builder interface yourself is base form provides methods like this one set form error which I can just say here's the name of a something an element in my form API array here's the message that I would like you to display I've now raised an error that's all I have to do if this validation doesn't pass Drupal will halt processing of the form and make sure that that error gets fixed by the user before they submit it again and once it does pass validation then the submit form method gets called you guys still with me? It's complicated it's also Thursday afternoon the end of DrupalCon we're getting there so forms are when a form is submitted our module gets the opportunity to validate it with a validation method or handle the submitted data I do things like save it to the database and so forth in the build form method I think the most important element there is the dollar sign form array because that's the one that we're kind of giving Drupal the definition of what our form looks like in the validate and submit methods we focus more on the dollar sign form underscore state array that's passed in the form state array is actually available to us at any of these stages in this life cycle of a form when it's being built when it's being validated when it's being submitted and it contains state information about this form it contains information like hey this form is being submitted right now it contains when the form is submitted the values that Drupal parsed out of the HTTP request and placed into the form state array so that we can just deal with those values right there it can also be really useful if you're dealing with things like Ajax or multi-page forms because the form state array is persistent throughout the entire life of a form because forms are cached when they're built and so this form state is as well I use this a lot to just kind of when somebody submits the form and you wanna save some data until the next step of the form you can just kind of tack it on inside of the form state array and since that form state array continues to exist throughout the process it'll always be there for you and then finally the form state array is kind of our checklist for controlling the workflow of this form it contains things like there's a validate property in there that when it's set to true Drupal's going to work on the validation routines for this form when it's set to it has been validated we can see all that information there it also allows us to do things like say set the redirect property so after the form has been submitted redirect to the thank you page by default when you submit a form Drupal does all that work it calls your validation handler it calls your submit handler and then it actually just takes you right back to the same page that you were just on but if we modify the form state array and say redirect somewhere else it allows Drupal to say okay I've processed this form I'm gonna redirect somewhere else this is important because in this scenario where we allow other people or other modules to potentially modify the way that our form works we don't wanna just call like redirect inside of our submit handler because there may be some other module that added some custom functionality that needs to have its submit handler called as well so we use form state to control the workflow of our forms rather than doing things like raising an error and stopping processing of the form right here or redirecting by calling Drupal go to we allow the form state array to kind of dictate that for us so Drupal's form API when you want Drupal to build a form for you you get it to do so by calling the get form method for the form builder class you pass in the name space of the class that contains the form that you would like to build in Drupal 7 this was a little different you'd call Drupal get form and you would give it this form ID which would really be the name of a function that it should call in order to build the form in Drupal 8 you give it the name of the class that contains the build form method the validate form method and the submit form method or that implementation of the form builder interface once you've done that Drupal will take care of automating a lot of the workflow for you it takes care of saying okay I'm gonna call the build form method and figure out what this form should look like render it as HTML and display it on the page it takes care of dealing with somebody raised an error or I need to re-display the form all of that is taken care of for us automatically which is really nice our module during this process simply needs to return a dollar sign form array that is that definition of the form that we want to display to people it contains the elements and properties that Drupal uses to render the HTML form our module performs validation Drupal does some really basic validation like that making sure that the form that was submitted is the same one as the one that was displayed but it makes sure that the values are safe to be used inside of PHP but beyond that it doesn't really do any additional validation so if you're going to do things like say take that data and put it into an email or take the data that was submitted and enter it into the database you do need to make sure that you're validating the data that people are submitting because Drupal only does some really basic validation for us so in your validation method that's where you have the opportunity to do that and then finally your module is responsible for dealing with the submitted data so Drupal deals with the workflow but you have to tell it what form to build how to validate the form and then what to do with the data once it's been validated because of course Drupal can't assume oh Joe made a form I know what to do with the data finally I think important to remember in one of the best aspects of Drupal's form API is this ability for us to modify other people's forms without having to touch their code this kind of goes really well with Drupal's core as whole like don't hack core thing the form API hook form alter functions give us the ability to modify any form in Drupal core without actually hacking core at all which means we can change any functionality in Drupal without hacking Drupal core at all because all of our interactions or the user's interactions with our site are through those forms so you get a lot of power by understanding how the form API works that's it, that's my summary of Drupal's form API we've got time for questions so I'm happy to answer questions there's a mic in the middle of the room if anyone's got a question or you can just raise your hand and I'll repeat the question that's fine as well yeah sure, sure so the question is when would you use a module like web form to build your form versus when would you use something like form API to build your form and I think you would use form API to build your form if you were trying to build the web form module because you would need to be able to provide forms that someone can fill out in order to configure what the web form looks like for something like a simple contact form yes I would absolutely recommend using the web form module to construct that form the form API is more of the developer level I'm trying to create the interface that someone would use in order to have a module like web form or like the field UI right, same kind of thing should I write a custom module that adds a field to the node content type or should I use the field API to do it kind of depends on your use case but you would use the form API if you're the person that's building the field UI or building web form does that answer the question yep, yep, absolutely if you're just trying to build a form to collect people's information and store it in the database or send an email web form is a really great use case for that if your five-star module and your objective is to prevent a way for people to rate things on the site then you would use the form API if your if your module is integration with Salesforce you can't just create a web form and then say, post this to Salesforce it'll be fine, right? You actually have to you could potentially, yep, yep other questions? Yeah, let's do whoa, excuse me was wondering if you could speak to whether or not you know much about hook forms for Drupal 8 I have a Drupal 7 site where I'm presenting a lot of the same form and I think five-star uses this to to be able to rate multiple things in one shot using the same form what does that look like in D8? I honestly haven't looked into that much in D8 my, I assume that that functionality still exists but what the actual syntax for it is I don't know yet Okay, thanks I'd be, if you wanna stick around after we can totally look at it together and figure it out Okay, cool, thanks Yeah I think this is a different question I actually have two questions but is hook form alter deprecated in D8 or are we subscribing to events and then doing that? Currently, hook form alter is not deprecated it still exists in functions essentially the same way that it does for Drupal 7 there's potential for that to change I would be surprised if it does this late in the game but for Drupal 8 I think we'll continue to see the hook form alter where you're given a form ID and you just have to say if this is the form that I'm interested in here's the array make my changes to it the form ID now is defined by your implementation of the form builder interface one of the methods is form ID and so whatever string is there is what you would look for in hook form alter Okay, and then in Drupal 8 I do a lot of work with commerce in Drupal 7 and one of the things commerce kind of has to do is like if you're providing a payment method you provide sort of a self-contained form you don't do a form alter you just provide a form array and then commerce kind of grabs all of the different forms that you want to show in that checkout pane and it kind of has to build its it has to run its own router kind of around that just to run this form and display its errors and then run this form is there something more native in Drupal 8 for that or is that still a special case? I believe that that's still a special case like it, I mean essentially what it's doing is it's another layer of abstraction on the collection of that form API array commerce is saying I'm gonna call all of these different functions and let them aggregate together what the form API array is gonna look like as far as I'm aware that continues to be the same thing commerce will have to do that on its own Thank you. Hey, so how would be to theme a form in Drupal 8? Because for example, I found myself in the past for example, if I want to add a piece of markup before the form or just whatever I end up adding this markup elements in the form I don't know if that's the best way to do it it always seemed like Sure, so like if you wanted to modify the HTML that was output for some reason or another how would you go about doing that in Drupal 8? Mostly the same ways that you would in Drupal 7 and it depends a little bit on what you're trying to modify if you just wanted to let's say inject some additional HTML into the form using something like a element of type markup is probably still the best bet if what you want to do is say like modify the HTML that Drupal is outputting already and this is true of any renderable array in Drupal so form API arrays included you can define this is the template to use when rendering this array and then you could just copy the default I guess it would be a twig template now and make modifications to that. Okay, thank you. Does that answer your question? Yeah, sure. Cool. Okay, so the question is I've created a form, somebody submits the form and I need a table in the database to have that information wherever I'm gonna store that information how does that get built? Yeah, so that is actually you would that's not handled automatically it's sort of in some sense not really part of the form API but what you would need to do is in your module define what that table structure looks like using Drupal's schema definition once the table exists you could use the database abstraction layer to say insert first name, last name, phone number into the table that I defined so your module would have to do all of those things that has to define the table where things are stored it has to define the form that collects the element and it also actually has to say do that submission step of taking the data that was submitted by the form and saving it into the table. Absolutely. Yeah, so I'm gonna maybe reframe the question a little bit the question is kind of like I've got a form that's defined in some way or another and there are fields on it that I want to make some of them visible to everyone and some of them that I only want to be visible to an authenticated user. Using the form API the best way to handle that would be there's a pound access property if it's set to true that form element is visible if it sets a false is not visible it's also that's a really secure way of doing it too because if pound access is set to false Drupal will do things like make sure that someone doesn't perform local modification of the HTML add that form widget that they know is supposed to be there so that it's included with the posted data Drupal will be like an error has occurred please contact the site administrator like I am the site administrator yeah cool. Yeah so like Drupal 8 has a lot of the functionalities from the display suite module in terms of being able to reorder the way that forms are displayed or the fields on a content form are displayed and how they're grouped together and so forth and one of the things that it lets you do is basically be like show this form field or not and my guess, I don't know for sure but my guess is under the hood when you check that check box that says don't display it all it's doing is sending pound access to false thank you guys for coming that's all we got thank you guys sorry I wanted to ask oh did you, sorry did you have another what's that? did you have a question or do you want to just come up well if you're done that's all right I'm happy to answer it I just, I just noticed one of the frustrating things when you're working with forms if you have a, if you're trying to do a form alter on an element and another custom module is doing a form alter on the same element how do you control the order of alters so that your alter will override? the order that those hook form alter functions are called by Drupal is based on the weight of the module in the system table and so by default whenever you install a module it's given a weight of zero and it calls all of those basically it's like globs things together that are of the same weight and then within that it calls them alphabetically so if you want to make sure that your alter function is called after the field UI for example you just have to make sure that your module has a higher weight than the field UI you can also do things like there are, there's hook form alter but then there's hook form, form ID alter and those are called in a specific order too so the generic one is called first and then the more specific one is called second and so if you know that the other module is using the generic hook form alter you can call the more specific hook form, form ID alter and yours will be called after the more generic one right I, I, I totally get the setting the weights in the system table I, I was just wondering if the eight had an easier way to do it than that not that I'm aware of okay I guess you could like there's an alter function that you can use to modify the execution order of hooks but that seems dirty to me I would probably stick with the weight in the system table you're welcome I'll put a link up I'll upload the slides and I'll put a link to it on the algorithm page for this session yep yep you're welcome hey how's it going good um