This episode is for members only

Sign up to access "Building a Notification Preference System in Laravel" right now.

Get started
Already a member? Sign in to continue
Playing
07. Complex array validation

Transcript

00:00
Right now we're doing absolutely no validation here so what do we want to validate? Well we
00:05
want to validate when we send this data down and once again let's just dive up here on request and collect or just request get notifications. Let's take a look at what we want to validate. We'll implement validation and then we'll go ahead and write some tests for this. Let's hit save on here. Now the keys here, which can be a problem with validation but we can get around this, the keys
00:29
need to be valid notifications over in our database here. So we need to make sure that they exist within the database. The other thing that we need to make sure is that each of the channels exist within the database as well which is another benefit to having these values stored in the database. We can do a unique or a exists validation check within there and that's pretty
00:53
much all we need to do. So any users can set any notification so there's no authorization around this. It's basically just check that this key exists in the database and both of these values exist in the database as well. So let's go ahead and do that now. To do this we're going to create out a form request just to keep our controller nice and tidy. So let's make out a request here
01:16
called notification update request. We'll go ahead and swap our request over here so notification update request and let's head over to this and fill this in. So we can authorize this by default because we don't really need to authorize this. Now the question is how do we validate each of these pieces of data? Well let's start really simple. So let's say notifications. Well what does
01:43
that need to be? Well we know it needs to be an array. So let's make sure that's an array first of all. Each of the channel types, to validate each of the channel types, we just need to use a asterisk placeholder within our rules. So for this we would say notifications dot asterisk. Now asterisk there is going to represent the value, so the actual whole thing, so the whole array here.
02:11
But then we need to look on individually for each of these to make sure that they exist within the database. So again we look into that array for each of the items and what's the rule going to be here? Well let's go ahead and just type these out as pure text. I'm going to say notification channels so that exists within that database table under the type column. So remember
02:34
for each of our channels type is the sort of lowercase unique key for each of these and that should be enough to validate this for us. Now we have a slight problem here and that is that now when we run our tests this validation is obviously now applied to them routes that we're trying to post through to test. So let's go ahead and run our notification controller test again and you'll
02:56
see that now both of them tests that we added are now failing and that is because we don't actually have any notification channels in our database to start with. So before we even write a test for this we need to make sure that we can seed these. So I'm going to go ahead and create out a seeder in here. So let's make out a seeder called notification channel seeder. That's going to
03:19
seed the channels that we need specifically for our tests. Of course you can use them normally as well if you want to. Okay so let's open up the notification channel seeder and let's fill this in and we can see these then directly within our tests and we should be good. So we're going to say notification channel factory create and what do we want to add in here? We can just add the two
03:42
types that we've already been working with. So the email with the title of email and a slack type with a type or a title of slack and there we go. So now what we can do is within our tests so let's open up our notification controller test again within each of these tests we can go ahead and seed this data. So we can either do this directly in here like this so we could say this seed and
04:10
then say notification channel seeder like that and just give the fully qualified class name or we could take this and we could apply it to a before each like this and that would have exactly the same effect and it would just run it before each of our tests. Now we don't actually need this seeder before each of the tests that we're going to write in here so we're just going to go ahead and do this
04:33
individually inside of each of the tests just here. You can always change that up later if you need to. Okay let's make sure our tests are passing first and there we go. So now the validation is actually passing we know that our data is in there and that now has not broken our tests. Now we can actually write a specific test to make sure that this actually gets through. So let's go over to our
04:55
notification controller test and let's add a test in here for this. So we'll do this just at the bottom let's say it fails if channel type does not exist. So what do we want to do? Well we need a user because we need to obviously post this through as a user. Let's say factory and create so we just got a random user in there. Let's go and create out a notification type that we want to pass through
05:24
to actually modify or add to our notification preferences. So we're going to say notification factory we're going to create that out and let's set, no we don't actually need to do that do we because I think over in our notification factory we already added in some data so yeah that's fine we can just create that out. Now we can just go ahead and acting as that user go ahead and patch
05:50
down to the notifications update route and what data can we send down? Well we need to send this notification because eventually we're going to be testing that the notification id that we send down exists in the database and we're going to send this down as anything we want. So it could just be abc for example but because we've not seeded any of our channels here technically even
06:15
if we put email in here this would still fail. I'm going to put it as abc just so we know that this is a kind of fake channel that we're posting down to and then we are going to assert that the there's a couple of things that you can do here but I'm going to say assert session has errors and we're going to provide in the specific validation key here which is going to be
06:35
notifications dot asterix dot asterix. So basically create a notification because we need one to be able to actually send down in the first place but don't create any channels and pass through a fake channel and see if the validation fails. Let's go ahead and run our test and yeah this doesn't look good so let's just have a look here and notification group yeah so this needs to be
06:57
for a notification group. Pretty annoying and we could create a helper for this but it's not too much trouble to do this for now. Let's run our test and yeah we still get a failure. Let's have a look here attempt to read id on string and yeah we just need two notifications that needs to be wrapped under an array here okay and we should be good. Let's run that one
07:27
more time and it still fails and yeah so this needs to be notification factory. We'll get there in the end but hopefully all that makes sense so let's rerun that again and we get a pass. Great so we now know that the validation for the channel types is working. Let's go back over to our request and now what we need to do remember is validate the keys which are the notification
07:54
ids. How are we going to do that? Let's write a test for this first and then we'll fill this in. So let's go over to our tests again and let's say it fails if notification type does not exist. This is the actual notification itself now so we don't need to create a notification here because of course we don't need one to exist to be able to test the validation of it so we're just going
08:20
to say user factory create and we're going to say acting as that user we are going to patch down to the notifications update route and let's fill this in properly this time so let's say notifications and let's say one we want to update the email so we've already validated this it's this here that does not exist so we want to assert that we have some sort of validation error here so let's
08:52
say assert what are we going to say assert we normally have assert okay let's say assert invalid I think that should work so let's go ahead and run our tests and yeah we get four passed that's not right so let's say assert session has errors and maybe we could just get away with doing that okay yeah so the reason this is passing so this is a little bit of a
09:18
tricky situation is because the validation is not working because of the channel type not existing so what we want to do is we do want to see the channel type because that's going to give us the email type here so that will pass but then it's this that we don't want to pass so let's rerun this test again and yeah we now get a failure great so we know that this is failing now not
09:45
because of this because we've seeded that but because of this so what do we do here well we need to validate the keys of the array that we're passing in here how do we do that well we need to do a little bit more work to set this up first of all so what we need to do is we need a method in here called prepare for validation this is just a method that exists within the form objects within
10:14
Laravel that will be invoked before validation begins so with this what we can do is we can specifically merge in the keys of the data that we want to merge because what we can't do is we can't validate these keys if we were to do notifications dot asterisk that would validate the overall array here but we want to validate the keys so we need to pluck that data out
10:37
specifically to validate it so we're going to merge into the request the value keys you could call that notification keys whatever you want then we're going to use the native array keys function in php grab this notifications which is the data that's getting sent down if that doesn't exist we're just going to use an empty array now we have keys within our set of data
11:02
so as an example let's just die dump this keys inside of here and we can either run this in the browser or run a text and you can see now this gives us an array of two and one so they are the keys or the notification ids that we now want to validate because we've got them we can now say well for each of them integers within that array that we've plucked out we want to make sure these
11:28
exist within the notifications table under the id which is optional you don't actually need to pass that through okay now that we've done that let's go ahead and run our test and we get green so this is now working and we can even update our test now to specifically check for keys dot asterisks in the validation when we go ahead and run that okay there we go so we've now
11:53
looked at a pretty basic validation for the array based structures that we're passing through from our form but also more complex validation where we need to pluck some data out like these keys before we then go ahead and validate them and of course we've now got tests to back both of these scenarios up as well
10 episodes1 hr 23 mins

Overview

Need to store advanced notification preferences in your application?

In this course, we cover displaying a matrix of notification groups, types and channels with the ability to sync preferences cleanly and quickly.

Once you’re done, your users will be able to choose what notifications they receive, and how.

Oh, and we’ll write tests to back everything up, look at how to use notification preferences in Notification classes, and how to set defaults for when users register.

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Episode discussion

No comments, yet. Be the first!