Laravel 6 Beginner - e19- Final Project Part 3 (Questionnaire/Survey App)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] let's continue working with our survey or questionnaire application at the end of the last episode we finally got some data in our database but now let's shift our focus a little bit start working on the view necessary to see this new questionnaire the first thing I have is a small bug here I'd redirect it back to questionnaire but it should have been questionnaires with an S so let's go ahead and make that change and I'll make that change right here and so now we are back to this alright so let's add a new question that way we get the entire flow what should we do next for example we'll say choice 1 let me copy this do the same thing and then we'll do 3 and finally we'll do 4 we'll add a question and sure enough we end up back here however we don't see our questions so this right here is hitting the questionnaires controller and close this up let's go to the questionnaires controller and that pertains to my show view the first thing I want to show you here though is the fact that we are using route model binding but now we are fetching a distant relationship so we don't have any relations the thing about it though is that if we don't lazy load our relationship then we're going to create an N plus 1 problem for ourselves whenever we start to display the questions inside the questionnaire because each questionnaire is going to have questions and each question will have 4 answers that's a ton of different things that it has to do we can fix that dope by doing something called lazy loading so during lazy loading we can take our questionnaire and say hey let's go ahead and load a relationship now you can use nested relationships in here so yes I want to load my questions and that is referencing my questionnaires a relationship this one right here the reason why I can use questions right here during the lazy loading process is because I have questions in here now if questions itself meaning this model has an additional relationship then I could use nested relationships on so what I want to grab is answers so to do that I could do questions dot answers so with that now we are lazy loading the questions and answers and to show you what that looks like let me down that questionnaire one more time we'll go back here I'll hit refresh and now I have a relation section here in my model when I open that up I've got questions and then I've got two questions right now and we see that right there but then each question itself has a relation right here which has my answers and we've got four of those let me show you the difference if we don't load the answers I'll go ahead and delete the answers part of it we'll hit refresh we do get our questions one more time like so but now there is no relations with the answers so we lazy loaded the questions but we didn't lazy load the answer so we still end up with an N plus 1 problem to fix both at the same time we'll go ahead and eager load the questions and the answers ok so now our question is that show has the appropriate data that it's going to need let's go in there now and let's go ahead and figure out how we're gonna do this all I'm thinking about is we could just add cards for each one of the questions available I will go ahead and copy my card and now let's add a new for each section we'll save for each questionnaire and then I could use that relationship questions so that is going to return a collection to me we'll call that question I'll go ahead and paste my card in right there and then end for each okay for the card title let's use the questions question loose a question arrow question there we go and then for my answers I will need a list I'll cut that out let me go back into bootstrap website let me do a quick search here for a list group and there it is just a simple list that's all I need I'll go ahead and copy that let's bring that in here I only need a single list item and what I'm going to do here is a nested for each that way I can get each of the answers inside this particular question so say inside our question I want the answers as answer I'll paste that in and then let's end the for each and now inside of here I can simply output out answer answer like that does that make sense let's go through it we've got a big for each loop which is basically grabbing each of the questions inside this questionnaire which remember we lazy loaded and that's why we could do this the correct way we are renaming that to a question variable so we're gonna have a card for each of my questions as the card header we are using the actual question then inside of a list group we are actually grabbing each of the answers and saving them to answer and then we're just using that as one of the items so we're gonna have four of these items per question now it just occurred to me right now that I accidentally deleted the card body this right here the card needs that let me go ahead and add that back in so card body will just wrap that like so okay let me fix my indentation there we go okay so we've got the card header we've got the card body that's more bootstrap stuff I just accidentally deleted that okay let's take a look in the browser let's see what we have fresh and sure enough we've got our first question here with the four answers and we've got the second question here with my four answers only thing missing here is obviously we need a little bit of margin let's do margin top of four let's try four yeah four looks good so now when we add a new question we'll say it yet another one three one two three one two three one two three we'll add that question and now that is down here yet another one one two three and all of my answers so that's great because now we can see all of the questions which is awesome but next we need the ability for somebody to actually take this questionnaire so let's start working on that let's add a button right here and ultimately what I would want is to have a public sharing address that someone could potentially give to somebody else and they don't need to have an account with our application or anything like that so we're going to want that to be in a totally separate view remember the view that we are currently on is protected by authentication you do have to be logged in you actually have to own this questionnaire to even see this so just keep that in mind let's add that button now simple enough to do let's go ahead and make another anchor tag and we'll talk about where it's gonna go in just a second but let's go ahead and change this to take survey I've decided that in our application a questionnaire is gonna be the set of questions and then the responses from somebody that is gonna be grouped into a survey and then each of the individual responses for each answer will be a survey response but I will explain every step of the way don't worry about that just now let's talk about the address stuff I think it makes sense for us to start with Slash surveys let's do that now and after that what we could do is maybe use our questionnaire ID okay put that in there but then I really want something else now one technique that I can teach you right here is a lot of times you'll see an address that has the slug abide version of the title of that page or of that blog post or whatever that is so I'm gonna show you how to do that right now let's add another - and after that less slug of Phi the title so what would that look like well let's start with the title and then we can use STR STR is a set of string tools that come with laravel that help us do things like slugs so we'll say STR colon colon and then we'll use the slug method on that then we'll go ahead and close the parentheses back here okay let's go ahead and give this a go and what I want to show you is what it actually outputs out I'll do it inspect on this and check that out so it's gonna be slash surveys slash one and then - cool - title our title is cool title so notice how nice of a slug it made for us automatically that's pretty cool right in future lessons we'll touch up on more on slug but just know that it's just a set of tools available to you and there's actually a ton of very cool things in there all right but now when we click on this of course we don't have a route how do we handle these routes obviously we're gonna have a little bit of a different route here so let's explore how that would happen let me go ahead and open a new route here we'll say route gets so we know it's gonna be slash surveys then slash well slash what well it's gonna be slash my questionnaire so let's start with that questionnaire and then there's gonna be a dash followed by what I will call a slug okay now this is a slightly different format than what we've been using up here right because we have this idea that there are two pieces of data within the same string now the only thing that is going to separate these two pieces of data is this - right here and if you take a look at the address up here we're gonna grab whatever is in the front right after Survey / up until the very first - and then we're gonna grab the rest of that string the slug itself we're truthfully not that interested in it we're going to ignore it altogether but I'll show you how to grab it anyway now this needs to hit a new controller which is going to be the survey controller and for method on this let's use the show because this will basically show that now technically you could use the create or the show it's entirely up to you the reason why I'm not using creates like I did up here is because I don't want to have that slash creates I just want this pure string I feel like the show is probably okay for this you could always use the create method here and not do the slash up - you just know that that's what I'm doing I am purposely not following restful controllers 100% but I saw her where I'm at the same time okay so now we have a route but we don't have that serve a controller easy enough let's add that PHP artisan make controller serve a controller okay now of course it's gonna say well you don't have a show view okay easy enough let's go ahead and open up the survey controller let's add the very first method here show okay now let me go back to my web routes I still have questionnaire so I can still use route model binding for this let's go ahead and do that now let's say app questionnaire questionnaire I'll go ahead and import that class at the top that way it's nice and clean like so we'll clean up any unused imports and now I told you I was gonna show you how to use this lug how to get this slug right here well as it turns out has a second argument here we can just accept it slug as easy as that as a matter of fact I can dime dump slug right here and now we can get that second piece of data whatever we type back here that is just gonna be passed through to us right here but like I said I'm not really interested in that that is mostly going to be just so that we have a nice address we don't actually need it so we're not gonna use it at all it's just gonna go unused but I do have my questionnaire which is what I'm interested in and there it is so now of course we're not gonna die end up we're gonna return a view let's return a new view and this is gonna be under survey that show and we need to pass through my questionnaire so let's compact the questionnaire as we've always done and now of course it's gonna say well I don't have that view let's go ahead and create that view now now the best thing that I could do here is just reuse one of my other abuse this one right here I'll go ahead and open it up and let's save as it's not gonna be create anymore it's gonna be called show now as that's what I'm using and this is gonna go into survey okay all right so we've copied that obviously the action for our form is gonna be something else we'll talk about that in just a second but let's start modifying this view to work for what we need ultimately I want this to be a nice form that someone can use to submit their version of the survey so let's start with a nice h1 tag up here for the title go out put out a questionnaire title and right after my title let's start a new form I'll tell you what we'll do it 100% from scratch like I said we'll go somewhere I'm not worried about that right now let's go ahead and leave that blank and let's go to method it's gonna be a post like so and inside of here the questionnaire has questions now we didn't really load them in my controller so let's go ahead and do that now as well let's say questionnaire go ahead and lazy load questions and my answers I need both of those and now I'm go to take survey here we go that's what we have so far we just have our cool title over the top let me close this up so that we clean it up a little bit alright so we are back in our form inside of this form we're going to need the CSRF token we can never forget that so let's add that up front and then after that we need to iterate through each of the questions now we already know how to do that so we'll do for each questionnaire questions asked question and we'll end for each so now inside of here we'll have each of the questions so what we could do here is go ahead and have a card for each other questions at this point let me go fetch one of those cards from my show view and here it is let me go ahead and grab this right here and let's come back to my survey and I'll pay study so we'll have a card at the top we'll add the question now one thing that would be nice is if I displayed maybe like a number like this is question number one this is question number two how can we do that well one thing we haven't talked about is for each in PHP in general has two versions this short version that we're using but there's also a version where you can actually grab the key and do a pair like that so now we would have a key but arrays are zero based index so this will technically start with question zero which is a little weird let's add a strong tag so what we could do is just add one to it so we'll have our key like I said it will start at zero these always look like that zero 1 2 that's a little weird for humans we start at 1 right so we'll say plus 1 and now we have 1 how cool is that now one thing here is we don't notice the bold we don't notice the strong but that's because laravel doesn't actually import the strong version of the font if we take a look at the app that blade right here right where we are bringing in our font this new need oh there's another version of it let me do a quick side note here for this because I think it's important that you understand how the google fonts work they're very very useful so we go into google fonts initially this will import only one weight so if you say select font and you take a look at customize you see that regular is the only thing that gets imported however if we clicked on bold and we go back to the embed notice that now we have this right here and this is really what we are looking for let me go back to phpstorm right after this we can add whoops I added that twice we'll get rid of that you can add whatever weights you need so we want to import the 400 weight and the 700 weights so now if we take a look at our application sure enough the 1 the 2 you see that it is bolded so that's just a quick little tip with using google fonts is that you can customize which weights you want to bring it and so that's how we get that to work awesome so that's good so far let's keep working through this let me close that off all right back to where we were so we've got a quite turn up here next I do need basically a list group but of radio buttons because ultimately each of these answers is going to be a radio button so inside of my Li instead of just displaying out the answer we need to add a new input it's gonna be an input of type radio for name as you know we're gonna have something special so for now let's leave it blank I'm not gonna put anything in there and now in terms of ID each one needs to have a specific ID so what we can use is maybe just the answer ID so we can say answer and then we can output out with PHP the answer ID this is just going to give us a unique ID and that's really what I'm after I want every single of these input radio buzzes to have a unique ID this is one easy way that we can make that happen and now let's go ahead and output out my actual answer right underneath alright let's check out a progress okay but that's looking good it's a little bit on top of each other we can fix that though let's add a class here a class of margin-left of two whoops and added it in the wrong place margin right up to there we go all right so now we have a little bit of space here's one thing that I hate and it's I can only click on the actual radio button instead of being able to click on the whole word this drives me insane whenever I see websites that just don't have a nice and big target it's really easy to fix to be honest with you the only thing we need to do is wrap the whole thing in a label right outside of my li I'm gonna cut it out altogether and let's just add a label that we can wrap it all the way around now the label we already have a unique ID remember the unique ID is answer and then the ID of the answer we can say answer ID okay now I'll paste that back in now with the simple fix whoops doesn't work did I miss something oh yeah oh yeah answers no it's answer to match answer right here okay all right with this simple click now I can actually click anywhere in this box doesn't matter where it is and it will still get selected of course I can still hit my radio button how cool is that this is one of those like public important informations that you need to know when you're developing things it's important to test things out most users are not gonna click on this most users are probably gonna click on the word to just know that just wrapping it with a label will fix that all together now in order for this label to work though you saw that you need the four which means you need a unique ID for every single input field and sometimes it's easier than you think to be able to just have a unique ID all you need to do is find some sort of unique ID in some column or something like that to make that work alright let's keep going with this let's talk about the name we've been talking about how to get these nested arrays to basically just do all of the work force and this episode is gonna be no different we're gonna take it to the next level though so let's go ahead and start out with what I think should be the final name like I said this is going to be called the responses for service so let's start with responses and then two responses I do need to have a key because I need to group them together let's use the key of the question okay so inside of here I'll go ahead and output out the key so this is gonna be responses 0 for example in the first one and then one on the second one and so on and so forth and then inside of here I can just have my answer ID because the value of this needs to be equal to my answer ID so let's add value now let's say value of each one of these is going to be my answer ID so again we are using the answer ID as a value in order for us to see this though and start to see how it's working out we do need to create the action for our form now I think that it would make the most sense is we continue to use this same exact URL that we've been using already so that would look something like surveys slash and then the ID of the questionnaire but let's recreate that so questionnaire ID a dash and then a slug so I basically need to have the same exact thing that I had in the other place so say STR slug and then we'll have my questionnaire title alright does that make sense again I am posting to the same place and it's the same exact address the only difference here is that it's gonna be a post request so now I can go back here and I can simply change this over to a post request and then let's go ahead and hit the store method it doesn't exist yet and I do want to create one now so let's create a store method inside my survey controller and for now let's dine dump all of my data Doce requests all that way we get everything all together and then if I go click on here this this is actually a different form hang on let's fix that real quick down here I've got a totally different form I'll go ahead and disable all of this let me go ahead and comment it out because I actually don't need it so at the end of my form here let me create a quick button that we can use this will be a button let's give it some classes there's through class BTN and BTN dark and this is going to be of type submit' and let's go ahead and say complete survey all right there we go let's give this another go and there we go all right I'll click on a couple of these answers and I'll hit complete survey so there we go in terms of our data we have a responses key and then inside of that I've got an array that has my answer ID and it matches exactly what I need okay so we're making good progress on this however I do need the answer but it's the answer to what question how could I possibly include the question ID as well and at first glance it may not be super obvious but we can add a hidden field why not write inside of this Li tag and that would look something like this let's add an input gonna be of type hidden in terms of name well let's start with this name right here we'll paste that in but instead of answer ID this is going to be my question ID I need to know what this answer actually belongs to so we use the question ID and then for value we know what that is because that is just my question ID let's output out question ID okay let's go back here I'll hit refresh I'll click on a couple of these complete survey now we've got three things and check that out I've got the question ID I've got the answer ID I basically have everything that I need to be able to create that record I've got the question and I've got the answer ID and it's all nice and nested inside that I can basically send it right on through so next let's work on a little bit of validation I think it's important on all these surveys if someone completes the survey it shouldn't go on it should say you know what you need to have an answer for every single one of these fields let's go back into the survey controller let's get validation in place we'll say data equals request validate and then in here we're going to have obviously some sort of nested validation we know that we've got a set of fields that are all nested under the responses and then inside of that we're gonna have any number of things the first thing is we're gonna have an answer ID and that is going to be required next I'm gonna have something very similar but I do know that it's not answer ID it's gonna be question ID and now we're gonna have some validation however whenever I click on this yeah it comes back but I don't have a way of displaying it I need a way of displaying that in my show view so let's add that right down here where the card body starts I can add that right here we'll say error and then let's do end and error in my error how am I gonna grab it well I'm going to grab it using the key because if you remember right down here we're using the key as the answer ID that's gonna take something very similar to this it's gonna be something like responses then we're gonna have dot then I will output out the key let's get rid of all of this and then I'll have another string here which will start with answer ID you know and in just a quote so it'll basically translate to responses dot 0 for example dot answer ID so if I do have one of those let's go ahead and output out some sort of error message will say small let's give this a class of text danger I will just out put out the message nothing new here we've been doing this all along alright so now I won't fill anything out I'll hit complete survey and now we've got nice validation for each one of these fields now if I click on one of them and I complete survey sure enough that goes away but now it's not selected obviously we need to make that happen we cannot do that to our users we need to use that old trick again so let's go into my input field let's add a new line and let's go ahead and output out selected or not selected based upon what comes back from old so like I said we'll use old we'll do this as a single inline if statement so we'll say if old and then I can use the exact same responses key that I used up here so if old of that so basically using the same exact key nothing new there if that is equal to my answer ID then that means that this is the checked input field so let's output out checked and if it's not then don't I'll put out anything all right let's give this a go I'll click on this first answer I'll click complete survey and sure enough notice that on refresh that is still selected I can select another one I also liked choice 2 and now it doesn't pass validation but my first two answers are already there the only one that's not there of course is answer 3 which if I do click then we do go through into our survey all right so we've got validation the last thing is very easy last thing we need to do is actually just go ahead and save this to the database it's gonna take two tables it's gonna take the survey table and it's going to take the survey response table so let's go ahead and create those at the same time PHP artisan make model survey with the migration and survey response and we will need a migration for that as well let me open up my survey model and the first thing I'll do is I'll turn guarded off go guarded an empty array and then I'll do the same exact thing for survey response guard it equals empty array now my survey this survey belongs to a questionnaire so let's add that now public function questionnaire return this belongs to a questionnaire class there we go so of course a questionnaire will have many surveys so let's add that relationship here say public function it will be surveys return this as many survey ok so now my survey response this is going to belong to a survey that a public function here for survey returned this belongs to a survey like so and in the inverse of that a survey will have many survey responses let's just call them responses public function responses return this as many survey responses class like so and then that's it we basically have all of the different things that can happen so a survey which is what stands in between a questionnaire and an actual response to an answer it belongs to a questionnaire and it has many responses a response it just simply belongs to a survey okay so with that out of the way let's go into my controller and figure out how to save this let's go into the survey controller and I've got the data here so very similar to what we did before we need to generate that survey first so say survey we need to go ahead and grab the questionnaire which we don't have yet but again we can use route model binding let me copy this in we'll put that in the store method like so so now we have a questionnaire and then let's use that new relationship that we just created for surveys then we'll go ahead and create a new one now in terms of what I'm going to send to this I really basically only need maybe a name and an email but I don't have any data to sent to it let's fix that right now let me add two more fields to my form so that at the end figure down here we'll say give us your name and give us your email address for example just two fields that I can use to identify the customer remember that at the end of the day whoever's taking the survey is not logged in this is going to be a public-facing part to our application so let's add another card to that show method and I actually have some data here let's bring this data back like so all right so I've got it card let's say your information like so this doesn't need a form let me get rid of this form it's gonna be part of the form that I already have we could do that and let's reinvent this I also will not need a button so let's give it all that together all right so we've got a title here and a purpose this needs to be a name and it needs to be an email so let's start with title we'll change this over to name and then let's change this to your name and then for placeholder enter your name and then for information let's say hello what's your name okay then let's change purpose over to email and then we'll say your email here and then enter your email maybe just enter email instead there we go and then for text let's just say your email please like so okay and then I'll have a message here now I can change the type here from text to just email and let's see what that looks like there we go now this complete survey they can move let's go ahead and move that button I'll cut it out of there let's put it down here I think it makes more sense wrap it in a div Doe and then let's go ahead and see what we have okay so that's looking pretty good now this is on top of each other so we need to give a little bit of room to this card lets say margin top before there we go all right so now we've got this at the end now in terms of the names of these two things I do want to group them together the way that I have been doing for everything else so let's change the name right now the name needs to be grouped in some sort of survey key so we'll say Survey and I'm changing both of them at the same time and then we'll use array notation again and that way we now have a nice formatted string let me show you what that looks like I'll actually just output out this again let me move this to the top like so all right let me give this a go I'll type something in here and when I try to complete it it doesn't work and that is because my form element ends here I need to cut this one out yeah we need to include the whole thing so let me move this one and then I'll end my form there instead looks like I'm missing one more div and there we go okay so all I did is we'll just extend my form so that it's all the way all right let's give this another go ah this is gonna complain because it's not an email that's okay all right so now we've got this survey sub key and then inside of that we've got a name and an email so this survey sub key is what I want to use for my controller so in my controller the data that I can pass through here is data survey so so now presumably I will have a survey at that point I can use that new responses relationship that I created on the survey to create many of those survey answers let's do that now survey responses create but remember I need to do create many because I have an array inside of here we'll simply pass through those responses responses remember those belong to this right here this response is what I'm passing through in this case it doesn't have any of the answer IDs but that's because it didn't pass validation that's okay don't worry about it we'll turn on validation again as soon as I get rid of this line so we'll have that in place and for now just to call it for now we'll just say return thank you can return a nice view at this point thinking the user for filling out our survey we're not worried about that right now I just want to wrap this up and see it working the last little bit though is I do want to make those two new fields that I added required as we did before let's add survey that name that will be required and survey that email will also be required for let's make sure that it's an email that's another little class that we can add they're using pipe so it's gonna be required and it needs to be of type email so at this point we've got all the logic but we are missing a big piece and that is my actual migrations I created them but I haven't filled them out and I haven't even migrated my database let's take care of those very quickly let's go into the create surveys table and in here we know we're gonna have a name and an email right I need to store that name and email of information inside my survey so we'll add strings for that for name as well as my email and then this needs to be associated to a questionnaire ID dos a table unsigned big integer for questionnaire underscore ID awesome let's jump into the create surveys responses and I will have another one of those unsigned big integers and this is going to be for question ID as well as answer ID remember that's what I'm passing through my form so we need to store both of those and a survey response it needs to belong to a survey so I will also need a survey ID okay let's go ahead and migrate the database PHP artisan migrate like so and now when we come back here we've got surveys it's empty and we've got survey responses let's get this a go let's see if we did everything correct I'll just click on a couple of random choices here my name here email at email comm let me complete the survey and it says thank you but let's see if it really worked for my surveys I've got a new survey here and it's associated with my questionnaire ID got the name it's got the email and then I've got all of my answers here for each of the questions don't notice how everything is filled out for us and through the magic of all that work that we did with naming our input fields and radio fields correctly everything just works and look how clean my controller ends up being because I could just pass through this data I can do proper validation and I continue to only have a handful lines inside of my controllers there's a little bit more work that I want to do but let's go ahead and leave that for part 4 so for part 4 we'll go ahead and try to wrap up the entire project and be done with final projects for level 6 beginner lessons great job on this lesson don't forget to subscribe hit the bell button that way when new lessons get posted you get notified immediately so with that my name is Victor and I'll see you in part 4
Info
Channel: Coder's Tape
Views: 18,326
Rating: undefined out of 5
Keywords: laravel, laravel 6 auth, laravel authorization, laravel 6 auth tutorial, laravel front end, laravel frontend template, laravel frontend scaffolding, twitter bootstrap, bootstrap laravel 6, laravel mix, laravel mix tutorial, laravel login, laravel beginner project, laravel survey, laravel project from scratch, laravel has many, laravel hasmany, laravel belongsto, laravel belongs to, laravel saving to multiple tables, laravel 6, laravel 6 full project
Id: vmashFZ0RcI
Channel Id: undefined
Length: 36min 15sec (2175 seconds)
Published: Fri Jan 03 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.