Mailing list filter and import with Laravel | Sebastian Sulinski | Skillshare

Mailing list filter and import with Laravel

Sebastian Sulinski

Mailing list filter and import with Laravel

Sebastian Sulinski

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
7 Lessons (1h 46m)
    • 1. Set up

    • 2. Form view

    • 3. File type validation

    • 4. Uploading file

    • 5. Mailing list filter class

    • 6. Error bag

    • 7. Results view

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class

Learn how to code a component that filters uploaded csv file and removes any records with invalid or duplicate email address before importing it to the database using Laravel.

Meet Your Teacher

Hello, I'm Sebastian.

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
  • Yes
  • Somewhat
  • Not really
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Your creative journey starts here.

  • Unlimited access to every class
  • Supportive online creative community
  • Learn offline with Skillshare’s app

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.



1. Set up: What's up, guys? Today we're going to have a look at how we can build on this mailing, least fielder and import tool, and we're going to be using their a lot of all framework for this specific purpose. Now what this still will do is basically will take there. See is the farm when we upload it. If there are any involved email addresses, these will be field set and only the correct ones will be added to the database. Let's quickly have a look at one off the spread should one of the CIA's we finds that we've got here. For instance, we've got first Joan Dough, which has correct email address. Then we have this Jessie dough with this email address, which starts with these back takes. Then it's gonna back. Take for it slash. We will feel to this and remove all this invalid characters then. As you can see, this record doesn't have a correct email address. This one nighter and then the last one obviously is a duplicate off the previous one. The only difference is this one has this involved characters, so we will feel toe all these records and only 32 records from here will be added the one for this John Doe and Jesse Dough. Because this is a duplicates of this one will be ignored, and these two obviously invalid email addresses of this will be ignored as well. Let's just quickly have look at the data base structure, which will simply have column I. D name and email. You will be able to provide any other fields if you want to, but I will only work with these three fields I d be in the alto incremental number and then name and email address, which is what we going to be getting from this sea is very far. Let's quickly test. It's if we go to the browser, select the first file mailing least I've got two files, and for heat upload, you'll see that we get the confirmation you have important to records. Your fight contained two invalid email addresses, which, if we go back to ours season I see this one and this one is involved. Then one duplicate records. If we go back, obviously this one and this one is the same. Apart from the $5 that this one contains invalid characters and zero records existed already because I was database tables empty. There were no duplicates in the database. And then he tells us which records have actually been important. As you can see, it's also lowering their the older caps in the email address as well. Okay, if we try and import another spread should live. If we just go back here in and if I switch to the 2nd 1 you'll see it's exactly the same except for this more expensive here. We've got actually that correct email address. So now what we should get is this email address and this one are already in the database. If I just quickly check the database for a fresh there we go. You can see John Doe and Jesse Dough are here, so these will be duplicates in a database. This one will be. The new answer should be out of this one is still involved. And this one office is still a duplicate from within this Ah, see every farm. If you go back and try and import the 2nd 1 now and if we keep uploads and there we go, it tells us that important only one record one was invalid. email address, which is this domain here on. And then we have one duplicate record, which would be a this Jesse here. And then we have to already existing records, which were already in a database. Which was this John Doe and Jesse, though if we check our table, refresh the Patrik and see this Mark Spencer has been important. So let's no try and import the same fall again. So let's say this mailing leads to If we open and try to upload it, you will see that we have imported zero records because one was invalid. One was a duplicate within a spreadsheet, and three records which were valid were already in the database. And you can see important records. No records were imported. If we check our database, there are no duplicates. We just didn't out anything. Okay, so the first thing we need to do is to import installed the lad of l. And I'm within my cold directory. So I'm going to start with composer create Project a lotta vell for it slash lot of ill, and the directory I want to install it within is going to be mailing hyphen least and composer should know, installed them instance off the a lot of else. Oh, wait just a moment. Everything should be ready for us in just a few seconds. Now. A lot of all has been successfully installed so far. Just navigate. Navigate to a mailing least. And I'm going to open this project in my editor, which happened to be PHP Storm. I've got a project now open in PHP Storm. If we go back to the browser, I want to download the exercise files. So get hop dot com and ford slash s it the hyphen tutorials. And here, if we look for a lot of, ah, mailing list field to import chicken, just type in the search repositories field, or just if it's obviously a visible straight way, can just click on it. And what we want is to download death. Ah, their copy off this repository, which contains the exercise fast. Okay, if I know, opened my file browser and double click toe extracted. All what I need to do is to take this template view and copy it to our resource is views directory. So just copy it. And if we go back to our l itself and we go to the resource is of use, and here I'm just going to paste it. Template dot blades. We can remove this welcome, dulled blade. We're not going to be using it. So our templates copied. And for the tests, we can remove this example Test as we know, going to be using this one air from the test we're going to use this stops. So copy the entire directory and pasted within this ah test directory within our project. Okay. And that's everything. When it comes to the exercise files, we don't need anything else from here so we can remove these files now. The next thing we need to do is to update our E n v file and for the database name. Just put the name off the database that you're going to be using. My one will be called Mailing Underscore released and now to create it. Amusing homestead. Locally. So what I'm going to do is go Teoh sickle pro, and I'm going to create a new database and colleagues. It's call it a mailing least, and that's going to be utf eight audit and that's database ready. We're not going to be creating tables manually will use the migration s so we can now save and close their envy file. Their next thing we need to do is open our PHP. Ah, you need dot xml. I want to create two new environment variables and these will be 1st 1 will be for the DB connection, which is going to be sq light for testing. And then we're going to have DB database, which will be the one in memory. So Kahlan, memory and Colin save it and also stop on failure. I prefer to have its to set to true. If there's one failure, don't executing more tests. Just stop on this one. So save it end. Close it on DNA ext. Thing we're going to do is to install a few packages. So if we go back to the browser and if we navigates to park egy, start orc and hear what I'm going to do. I need to packages 1st 1 is the lot of all I D helper, which is going to be Bari the D h a lot of l that we go on this one. A lot of l I d. Help when I need to do is Just copy this. Go back to the terminal and land space to eat. Return to install this. I d help A few more seconds and should be Ah, done. There we go. Okay. If you go back to the browser, let's curl down and see what we should dio eso We've got it installed. Now we need to art this service provider to the conflict up dot PHP We go back to our project Conficker Abdel PHP and under their providers section. Let's just add it under this package, service providers save it thou If we go back, what else have we got here? We now can under speech beyond some i d help generate and I d help in meta within the scripts Post updates c m d We go back to our editor open our composer Jason. We scroll down, we have posed updates cmd After this post update composer scripts Let's paste these two lines. We can now save and close the composer and doubts everything. Nearly everything with them. This i d help. But we can also get this conflict are file published. Sophie, just go back to the terminal and pays this lines and that will basically copied of the far from within the package. This conflict I d. Help. It'll PHP if we open our editor again, you'll see we have this idea help. And you can change some options here should you needs to. Okay, I'm going to leave it the way it is because I won't be making any drastic changes here. Now, if you're not bothered with this, I d help. You don't have to install it. It's not essential for this exercise to work. It's just so that actually packages like the one we're going to be looking for now installing it eyes automatically showing, uh, not as highlighted within my i d basically so recognizes it. Okay, so the next package that I need is m a t website. Excel. There we go. That's the one. If we click on the Lincoln and Copies composer require command, If we go back to our terminal paste, it's and he returned to install it. While this is installing, let's go back and have a look at the documentation what we need to do. Ah, What we need to do is basically aren't this service provider here again to our conflict up dot PHP. So let's go back to our editor and do this straight where Come pick up the PHP backdoor providers. And right after the one, we've paste it for the I d help pellets based this one back on. And then we have this facade that we need to up as well. And again, you don't have to do it if you're not planning on using the facade. But I will be using for sounds within the exercise. So I'll based it here again with the same file conflict Abdel PHP. But under aliases and right to the bottom. Just Exxon, which would just copy it. Okay, One last thing. I'm going to publish this Ah conflict file for this package as well. So back to the terminal. Copy this line, paste it. And that will copy the this conflict from the from the package to the Conflict Director. If we go back to the editor, you'll see this Excel now has been out of here. I'm won't be changing anything. Everything stays is default by a few. I need to change anything. Obviously place feel free. Okay, so we're up. The PHP is now ready. One last thing I'm going to do is to set up a virtual host for this project. I will be here using home stats. If you prefer to use PHP artist unserved do that. But I will be using homes. The difficult everything separate from my local environments. So I'm going to navigates to my home directory. And from here I'm going to go to Homestead, which is where my homestead installation is located. And now Nano Homestead yum Oh, file. And I'm going to our new project here. Cold mailing least s O what I'm going to do. Space base mop mailing, least the death two and we pointing to home vague grant. Then we have codes and then we have mailing hyphen least and a public director, which is where we should be pointed. So mailings and in a public directors where our index of PHP start okay, back to terminal also control X. Why? To save it and then in far off, the file stays the same. Now I also need to add it the house file so pseudo because I needs administrative privileges to edit this file. Nano editor again an e t c hosts file and there we go for scrolled down and 19 to 168 10 10 under the main name Ace mailing a least built deaf control X Y and return that saves the changes. Now, if we navigate to the home directors, let's see the and here we going to see d homestead and here we're going to run vagrant pra vision, and that should provision the changes we've just applied. And in just a second, we should be able to access our project under this new, uh, fake domain like this virtual house so mailing least dot deaf return. And we are getting this error, which is related to his welcomed on the blade of PHP file which were removed so everything is fine. Let's move next video when you start actually programming our mainly lease filter 2. Form view: Okay, So the first thing I'm going to do is to create a new test, so we can either do it manually. Oh, by using the artist, son and I'm within the permite projects directory PW d, which is this mailing list, and what I'm going to do is simply wrong. PHP rt son a make test And the name of this test is going to be mailing least test. He returned and the test has been created. We check our test directory can see, maybe test has been added. What I'm going to be making use off is this database migrations trade. So use database migrations. And I don't need these other two, so I'm going to remove them now. We are going to remove this test as well and I'm going to start with a new test which is going to be, uh, cold displays upload for basket, going to determine whether the the upload fold from his displayed on the page. So test talk to make sure that it's obviously a test. We're going to start by visiting for its large, which is their route off our site and then our project, and then we're going to say that we should see element input with the following attributes Type should be file and name should also be filed. And then we should also see another element. And I'm just going to duplicate this line. It should also be over an input type and then type attributes should be submit, which will be the button that summons the form and name should be. What name? It's not gonna have a name. We're going to have a value instead, which is going to be their label for the baton. And I'm going to expect upload in capital if we save it around the task PHP you need. And obviously we have a problem here for scroll up. It tells us that we get 500 this is because we caused by view welcome not found in the same era that we saw in the browser. So what we need to do now is first of all, check our where routes If we go to the Web, which is responsible for the what we are trying to access this Web interface for its large . What I want to do is basically it. I want to redirect it to mailing least controller. And on this controller, I want to have an index method which were basically load this view for the former. And then I'm going to duplicate this methods change death methods to post the same controller, and this one will simply have a method store associated with it. So Index will display the page with the form store with process the form and displayed the results. And now it's all the words that we're going to have within this project so we can save and close this file now. We also need to create this control, obviously, because we don't have it. So if I just clear the screen Ph PRT son make controller and control The name was mailing a least controller. He returned. That should now be other tower http. Directory controllers and there we go. Mailing is controlled by the way you can remove this authentication directory for if you're not using the authentication within this project, I won't be creating any authentication here is just purely for up by sickly filtering and importing cuz. False. Okay, so within this mailing list control, what I'm going to have here is thes two methods. 1st 1 is the index of Public Function Index, and it will return the view. I'm going to be using this return type declarations here, available with pH. B seven and we're going to say display import form. And now, in my idea, because still highlighting I just need to go to PHP. And if we scroll down to language and frameworks, I want to make sure that wasn't 71 And that's the one that I've got. Stay interpreted. I've got installed on this machine. Apply in. OK, and now this highlight is gone. That's just in case if you are using PHP storm as well and have the same problem. Okay, so now this one, we returned the view which will be located within the mailing hyphen least directory Full stop. And the file name is going to be index dot PHP sort just in exile is going to be indexed, outplayed the PHP. So just index. And that's all within our index method than public functions store. And we are going for the time being I'm just going to leave it like this. I'm on Lee going to indicate that I also will return the view. It's just art dog block. And what I'm going to say here is upload file and store results and there will be a perimeter in just a moment. But for the time being, just to make sure that our roots aren't squeaking, we just out there the stub of this method. Okay, let's create this mailing list director within our resource is then views. Let's create a new directory called Mailing List Within these Director, I'm going to create this index index dot blade dot PHP and inside of this blade, find what I'm going to do to move this opening PHP talk. I'm going to extend our template, which we've copied with the exercise fans, this template built blade template and then section for the section content. And we're going to put our form here with Heading is all and an end section. So here, if we just opened this template, they'll blade. You'll see. It's a really simple file. I've just important some Google phones here from days deserved foundation from the Content Delivery Network and then some simple styling just to make it look a little bit, have decent basically, and then we have some raw and a column off a given with and so on. Okay, So for our wear index view, what we going to do is first of all, I'm going to drop everything within the robbers or thief class rapper and inside of this rap, I'm going to put H one saying something like mailing least and then on the new line, a filter and import. And then I'm going to do if statement and I'm going to check if there are any errors because we're going to be something that form. And again, I'm not using Ajax here. I'm not using require I'm no using view Angula anything. I'm just going to use straight PHP and functionality that comes with a lot of ill out of the box. So we're checking for errors, count if there are any areas, if there's mold and zero, then that means we have some errors and we're going to display them. And if here and for this one, I'm going to just go for for each errors. Oh, all of them s each one as error represented by the air via bond end for each Here. I'm going to put this spun with a class warning, So that's going to be just making the text read. And in between the curly brackets, just e era variable. So whatever message is associated with this So that's our errors right above the form and now form will have method Post. We'll have auction. It's not about action. We want to pulse to the root as well. So just the fourth slash and then inked type because we uploaded a file multi part form data. That's our form talk. And in between, first of all, winning to art CSR f token So C S r F S R F field so that it's going to art in put together with soak in for the values we should with value attribute and then import, which I just called up. This input will be off there type file. The name is going to be file and that's all I need for this one. And then input for their submit buttons. So type submit value up loads and class. I'm going apply here, expand it baton. So it's going to go all across okay for now, save it. And if we try and run the test again, hopes wrong once or PHP unit and there we go, we go. One test three Alsatians, all of which are passing. So now if we preview our page, the landing page There we go. That's our form. Heading form when we click on that. Obviously, this allows us to select the file and our expanded button with the upload A label going across the the entire layout. OK, so that's our form. Ready? We can now safe and close this for this index. It'll blade the PHP file. Our index view is completed to go back to our mailing least test. The next thing, what I'm going to test for is going to be actually the upload. So we're going to start with public function returns. Validation arrow. If sub meets it without the file, select it. Okay. And again, that's a test. So it's just out some test Sakia again. He I'm going to simply post to the roots and then assert response. Ah, status. I'm expecting to be response and we using illuminate http response and I want to get actually be found found because this one is returned returned when there is a validation error and it returned. Basically, redirects is back to the landing page with the errors then being available within the view where, as thesis airs for able. Okay, And after this, actually, let's just terminate he acid, which we are expecting to be redirected. Let's just import this response. He as well, right at the top to eliminate HDP response. And after this I'm also going to assert that this assert session has errors and years that I'm expecting to have file for the final field and what it should be. Now the message should be the same as if we go to the resource is language in and and then validation. And for the file, we're going to look for the file index. So we scroll down, file the our tribute Must be a files. That's what we should see within this session for Heiress. Now. Attributes is going to be replaced with their name attribute, So I'm just going to replace this column attribute with the file So the file must be a file . That's what we should get as a validation ist. Obviously, if we run the test now, we don't have any validation yet, So that's going to fail. Tells us the expected status bear three or two got 500. Now it doesn't tell us exactly what happened. It just tells us that obviously, rather than having this three or two status codes, we got five founders of this. Some internal server error, obviously being thrown back. Now, mailing these test online 26 26 line is the cessation assert response status. Obviously, we didn't get that one. If we get 500 air, then obviously, if we go back to storage locks in open our lot of elder lock, we can examine it for two. Fund to try and identify the problem. Now, as you can see, this is also contained the previous area that we had some just going to remove this file first and then going to run the test again. So delete it. There we go. And now I'm going to run this test again so that we get this era's the first item. Within this file theory, all the father has been regenerated and it tells me down type of return value off store must be an instance off view, non return. So if we go back to our controller, I indicated that returns view, but he doesn't return it so I'm just going to quickly return view, and it's going to be mailing hyphen least. And yet a phone is going to be cold. A result, and it's going to be result of blade PHP. So I'm just quickly going to create this file as well. Under this mailing list are a tree, so I knew. PHP file result dot blade dot PHP There we go. And here I'm going to the exactly same thing. So extend a template. There we go and then section content for content. We're going to display all these results and section for the time being that I'm going to leave it. I'm not going to do anything else. I just want to get rid of this arrow. We can remove this lot of l locked as well, so if there's any other one, it's going to be generated straight way. I'm just going to clear clear the screen here. Command K on the keyboard and Mark and and Ron PHP you need again, and now we get something different. Expected status. 30 to go to 200. So there's no problem, buddy, and this is because we don't have any validation and the way I want to do. The validation is by the use off the request form requests. So what I'm going to do is go back to the terminal and I'm going to clear everything again and use PHP artist son artists and make the request. And I'm going to call it upload, mailing, least request. Ah, and he returned. And that creates the request commands K to clear the screen again. Now, if we scroll up and under the the up http requests we see our upload mailing lee least request, and our first of all authorized, I'm going to set it to true. We're not doing any authorization here and fold the rules. What I'm going to do, I'm just going to actually provide the return statement. He as well, assuming that I'm going to be launching this on PHP seven server array from this one and here I'm going to put file, which is the name off the input. If we just go back to our view index of Play the blades, our import name is file. So that's the index that we're going to be using here for history. And we want to make sure that the file. The basic. This Thursfield isn't empty, so required then that it's often file type, and I want to make sure that we only allow CIA's V fires. And now foresee SV's where we need to use mimes. Colon see SV, But also t extra tried to adjust CIA's. We didn't work. You have to have txt as well. So these are the rules that we expecting. If I now run the test. Obviously nothing's gonna change because we still didn't apply this request to within art. This request is a dependency for our store method, So let's quickly do this as well. Upload mailing lease request as request and it's added to the dog block. Straight away, up the dog. Look, there we go. We save it and now run it. And there we go. That changes. Now we have felt a certain that in the ray contains defile. Must be a file. Now we must be getting something different here. And this is because if we go to upload mailing this request, first of all, we are checking if there's anything so required rather than file. So if we go back to our validation for the required message is required. There we go there. Thea, Our tribute field is required to copy this one. And actually, this is what we should be getting. So not their fire. Must be. If I was going to be the our tribute field is required. And obviously the name off this field is Field is file as well. So the file field is required. That's what we should be getting. Let's now cleared the screen, Run a test again. And there we go to tests. Six a session. So when we visit the page, we get the form with these fields. And then when we try and post without defile attached, then we are getting the're saying that obviously the fire field is required. So we didn't touch any fine with me to the form you need to select the file. Otherwise it's invite. Okay, so that's it for this video. Let's move to the next one when we going to be continuing with our tests and where I upload 3. File type validation: so continuing from where we've left, we know that we have the form for the upload ready when we visit the homepage, then that when we post without any field in the request, then obviously we get this. The file field is required air. Okay, The next thing, if we go back to our upload mailing this request, we also checked out the value associated with this file Index in the request is actually of their file type. So let's go back to our A Malian least test, and it's greet another test. This time we're going to call it returns validation error if sub meet it if submitted without their file file type, let's go like this. Okay? And let's make it it's s obviously scroll up and I'm going to create a few new lines yet. Okay. Hey, are we going to start again this post to the roots and then I'm going to put in the ray file for file. I'm just going to have tax rather than file some file. And then this assert response status should be response again, and it should also be found so they should be found. It's exactly same as before. because it should fail the validation. And then this assert session has errors and year that we should have is for the field file . And then there file must be a fun, because this is actually one we've used previously by mistake for the file type, if we expect in the following this is the measure. So the on tribute must be a file. An attribute is replaced with the name off the field so that the file must be a farm. That's what we expecting to get. So if you run it now, on we go. We've got three tests Niner stations, all of which are passing. So that's also validating correctly. Now, the next one I'm going to do is going to be the method actually that we're going to use in their following too. Test the method that will actually create the upload file for us, which would then can send with a request and that will validate as the actual fire being of touch to the Requip with the requests. Okay, It's going to be a private function and we call it upload file. It will take upload file their ago. It will take one argument off the string type, which is going to be a stop name and buy stuff Name I'm referring to If we just scroll down here to these stop files in which we've covered with the exercise fast. So the name of this file and it will return the uploaded its file and the one that we're interested in is this Illuminate? Http. Upload it fast. If I just use this one and import this class right here at the top, we have it important. Scroll down and we're going to start with a stop equals We point to the current directory, reconnected with stops and then filing. So stop name. So this D I. R Constant takes us to the director from within within which this mailing list testes, Which is this this Test one. And then we go to stops and select the fall by its name. So this is going to give us a full absolute path to this far. Then we're going to go for the file. We used the new SPE l file in, for instance and we passed this the path to this stop file and here we can now use to create the name off the file by using string on this cold random. Let's say eight heart er's concussion is with a full stop and then we want to obtain their The extension of the original files is going to be filed. Instance and then get extension method, which will give us the extension of this file and then path to the new file. I mean, to the new far, we, the file that would normally be uploaded to the temporal occasion. And we can get this temple location using the cysts get temp, the i r concatenation of the fourth slash and then name off this new faster. This is the file. The name this part basically would represent the file as if it was applauded with a new name to this temporary director directory. So now what we need to do is to copy this file, so copy the source file, which is the stop fall from our stops directory onto this path. So now it is available within this temporary directory and obviously, on the other hand, on the other side, When we make this skull, this fund will be available as if it was actually uploaded. So return new upload uploaded file, and we're looking at this element HDB uploaded file, and he and we need to provide a few arguments. 1st 1 is going to be a puff the fire, which is this temper path. Then we have a name of the file. Then we going to have a file size. Then we're going to use file size function on we paths path to it as an argument that will pretend that files us. And then we need to provide the mind types on mime underscore content type. And again, we part a past. That path through is an argument, then, no for their fifth arguments and true for the last 161 which indicates that we are actually testing. It's not the actual applaud. We click on this uploaded file, you'll see what all these arguments are, and this uploaded file extends This symphony applauded violence. If you click on this one and look at the constructor off this classical, see, 1st 1 is the path we look at that Doug blocks the full temperate path to the file second ones or regional name, which is the name of the file down. We have mind type then we have a file size. Sorry. The mime type. The type of the file, as provided by PHP defaults to. And if we just go back to our test, we've done it the other way around. So obviously that's wrong. We have mind time. Then we have sites. We need to swap these two. So, uh, mind type first den file size. And if we go buck, then we have the aero mess. Constance, to be uploaded by default is going to be a okay if it's no so that the upload has succeeded . And then the last one tells us whether the test mode is active. So we are obviously testings of that needs to be said to. True. So that's no quickly on the DOT books here. And let's say something like Get instance off the up low that file. Okay, so upload file method is now ready. We can write the first test, which makes use of it. So public function returns validation error if sub meets it. Submitted without the Val eat file. Four months and against the test. So it's just about the dog books here test, and I'm going to close the far browse on the left. How this name The name of this method actually goes on the one line and we are going to start by making a cold this cold methods and we want to submits. The request is imposed method. Then we go into send this request to our home page devices that this brute of our project and then we gonna put to empty a race and I'll show you exactly what these mean in just a moment and then is 1/5 argument. We provide the file, and this final will be off this upload, uploaded file instance and the name of the document will be document don't p d f in semi Qalandiya. Let's quickly look, have a look at this cool method commented takes that method we want to use with this call, which is that they get posed our ports or anything else. Then we have the u N I which we want to call. Then we have para meters. Any part of it is that Go with this goal Then we have cookies and then we have fun so far meters and Cokie sweet sets to empty race with him Want any but for files. We did our touch This file this applauded up uploaded file. Instance. So now with this goal, we obviously using this document A pdf and we only allow if you go back to mainland at least this request here, we only allow see, as we all txt. So obviously this should fail and telling us that obviously, this is a wrong file type. So we're going to do next is we run the assertion this assert response status should be response again. Illuminate HDP response found organization to be found, which is three old soon All these responses If we just click on this one, you'll see that this response symphony component actually be foundation comes with all this Constance with which represent different state of skills that you can get with your response when you making a call. That's why I use them rather than just type in the the number here straight in ob just prefer to use it this way. But obviously feel free if you prefer rather than this. If you prefer to just put three old to do it like this. It's entirely up to you. And then we have this assert session has errors this summer should have again for the file field. The message should say, Let's just quickly have a look at what we should have back to our upload mailing this request minds. Let's look for the minds within the validation file mimes the our tribute Mars Be off a file type and then the times that we expected So back to our test on Let's replace the attributes, which is the name off the field. So it's file Mosby off a file type Colin, and then colon values will replace with See SV Colon, a comma space. Txt. Because that's what we expecting to go back here and see his ville. Txt. The only difference is that there's obviously a space after the comma with the validation, that's it. So if we go back, you can see I've just added this space. Okay, let's save it, run the test and then we go full test with us oceans, all of which are passing. Okay, let's continue with this exercise in the next video 4. Uploading file: Okay, so we've written a test to validate all over the possible incorrect requests in sense that obviously, whether that the field file is empty, whether it's off anything different than file type and whether it's got different mime extension, mime typed in then CIA zl txt. So now the next test that we are going to write for just go back to our mailing least test is going to be actually checking. Now we can upload, field and import the record. So public function uploads and, uh, go directly fuel tres records, filters and imports records, perhaps, and imports records. And again, that's a test. And we're going to start again with the same thing. This coal and we are going to be using post request type. We are posting to the root and then to erase no cookies And no, no, Parliament is no cookies, and the last one is going to be in the file. We want to send this time this upload file and this time the name of the funds going to be mailing least dot C S V, which is one of these farms that we looked at in a bear. One of the phrase videos. Let's quickly have a look at this file. So this is the 2nd 1 and we have the 1st 1 So what do we have here? We have three violet email address. Apart from obviously this one, which will be field that we will remove this back slashes and for its lush zone, and it's going to validate as email eventually. But this is obviously the same. Email is this one, so we only should have two emails imported after the field filter has been applied. So if we go back to the editor, so if I'm submitting the correct file with C is V extension and then what I expect is to get the status code of 200 witches. Everything is fine. So we're going to start with this assert response. Okay, that's the methods that checks whether we get 200 response. And after this I should also see text on the page saying Import completed. And then we also should see text saying you have important two records because only two should be imported. Then this. We also should see text saying to invalids, email addresses. Let's just quickly have a look. It just have a look at our was pressured again. This one and this one is involved. We go, buck. So me calling here then we should also see the text. Ah, saying one duplicate record. And these duplicates are referring to the records within this the CIA's we found, which is this Jesse 12 Jesse 12. So these are duplicates. So one of them would be ignored. And then the last one see text. We should see zero already existing records because we are starting with the fresh database . Obviously, we don't have any records in a database yet, and obviously we don't even have a table structure yet, so that that's definitely going to fell. But let's just continue its Theus sessions. So this we also asserting that we should say have assert count should be to when we ran my mailing least again. Mother, we don't have yet all method, so that's going to definitely fail. We also are expecting to see these records in a database. So this see in database and database name is mailing least with grated database, but we don't have any tables. And within this database, we should see record with name John Door John Doe and email should be John lower case dot dot com Because we going to be a lower in this upper case letters as well without filter. If I go back to our C s V, John Doe email, John Doe full name and then we also should have Josi Jesse dough with this Jesse, 12 are dotted. Come. So if we go back, I'm going to duplicate this entire a session here. So see, in database this time, it's going to be just see dough wit jazz. See 12th art dough dot com and then we should not seen database this don't see in database . May ling Least we shouldn't see record with their name off. Mark Spencer, go back to our C is v. Mark Spence has invalid email address. Same for Greg Monty. So if we just go back and if we duplicate this last assertion here on changed their name and then if we duplicate this again, we also shouldn't see record if we just go back with the name Brian Smith and the same name as Jesse. So Brian Smith and email Jess C. 12 dull dot com. So we shouldn't see this record So that's the first colder when making that's a first of all. When making a call with the correct file, it's got some records we should get. Receive status 200 in response because everything should go. Okay, now we should see import. Complete it on the page within, within the view that's going to be displayed after the import and field. Certainly infiltration. Then we should see also the message saying that you have imported to records to invalid email addresses. Huang duplicate records zero already existing records. And then when we check the database, we check how many records we have associate with dismay Ning, this model that should return to and then we should see these two records in the database and not see these other three. That's what we have for this test. Let's quickly run. It's on. Did not surprisingly, test fails, telling us that filled, asserting dance. The page contains the text import completed, so let's quickly fix this back toe editor. I'm going to open the file browser if we, uh, we can just close some of these farms here as validation as well index blades and we can close this one as Well, because that's completed. If we go back to our resource is of use mailing list and open our result don't bladed PHP. And here we're going to start with the DIF class rapper on the side of this rapper. We're going to start with H one saying import completed. This is what we expecting in our test, but it's got to have competes A letter here in port completed. We now save it and ran the test again. Not should give us another error here, so we've got filter setting doubts. The page contains attacks you have to have imported to records police checking the counted about. Obviously we don't have it, and we're not going to have it for a while yet because we first of all, we need to create this mold on together with the migration. So open its terminal. We're going to start with PHP rt, son, make model and and name off the model, which is the mailing list Hyphen haIf it hyphen high Fitton migration hit return and decrees The model, together with the migration cake commands K to clear the screen. If we go back, open the database directory migrations and I'm going to remove this users and passwords because we know using authentication here. So we only have this create mainly stable, which you've just created together. Where if we go open up mailing least Modell, we're going to work with this model in just a moment. But let's quickly sort out this migration. And within this migration, I'm going to remove time stamps because I don't need them. If you want to keep them, it's up to you and basically, arts created at an updated at field. I don't need them for my import. So I just remove it than Table String, which is going to be the column name. And by dis fault, I'm going to set it to know liable because not all records might have a name associated with it that maybe just leased off email addresses. Table string again. Email on this one needs to be unique. Announce our migration completed, Sophie, save and close the file now mailing this model now mailing this model. First of all, I know we don't have to, but I like to strictly the declare. What table is this model associated with? So I'm going to go for protected table equals mailing on the skull. Least that's awesome. Third block string and then we're going to set protect it. Fallible so that we can out record using creates and an updated as well by just passing the array. I want to be to allow feel a ball name and email address. So email field that's our dogs in the last thing because I'm no using times, time, public times, times I need to set to false. And that's everything for our mailing least modern Now from within the test. Let's import this mailing this now because we have it available so we scroll up. You can see that's now being added here, going back down here. Obviously, nothing has changed yet because we haven't actually out of any records. If we now run a test, you'll see that we get exactly same thing as before. PHP unit was still Don't get this. You have imported to records, Even though we've sent everything, we've got a model ready. We have our migration ready as well, so the table will be created before the test is run. Eso If there waas there were any far and records to be added, they would have a table available, but obviously I would control it doesn't do anything yet. It only passes through, injects the the instance off this upload mailing these requests, but it doesn't do anything with this requested just returns. This result of you back to the users, obviously we don't get nothing is being really processed. So if we go back to our controller within the storm methods, we could put all the logic for actually moving the file on the uploaded file to the designated directory down here, Actually, within this store method. But what I'm thinking of doing this. Go to this, upload mating least request and do it from that. So what I'm going to do is go to http requests and open this up blood manning released requests, and I'm going to create a new method here which we call move fast a public function move far. So this method will return a string, which is going to be full absolute path to the uploaded file. So moved far to the import direct trip. Okay, so here were we going to do this first get the instance of the uploaded false. So final. Very able this file and the name off the input. It's file as well. And then we're gonna generate some name equals string random A top doctors, let's say and then contaminated with dot C S V extension and then file equals Sorry. Store s and we are going to store. It s it within the Doctor import and then with the name which was just generated. And then we're going to return storage path, storage path, and then up Import forward slash end and contaminated with the founding. So there we go. So this is the full absolute. This is going to give us the full absolute path to this file, which we've just stored, and it will be stored if we go to our studies directory up and here because we haven't created it, it will be generated automatically this import directory and then the name off the farm that we've just generated. Okay, So what's gonna happen now before we do anything I want to show you? Actually, how this whole upload is gonna work if you go to convict, and then we're gonna go to file system. The default is local. And if we have a look at the disc options. The local I used to drive a local, which means what is going to be on the same server s. They're running script. Then we have the roots and not will take us to storage path, which is this storage directory and then directory up. So this is where it's going to be uploaded. So when we are calling this, if we just go back to this request store s that will store it within this storage up and then within the import directory with the name we've generated And then obviously we returned the footpath so that this method later on can be associated with the variable here within this store methods. And we can obviously play with this file whichever way we want. So from within the storm ethics, we're going to start with a file variable. And we going to use this request that's been injected here and then called this move file methods, which is when the file will be copied from the temporary uploaded location to this storage Armand and import Director. It's another we've got to final. What we going to do next is create a collection equals new collection. You can also use collect helper function like collect. But I I prefer to use a classic speciation where possible. So, uh, here we are going to use this excel package Eyes is going to be a facade there were going to use here and then load. We going to load this file which will just copied, then get which will give us the entire content as a collection, actually, because it's going to return a collection as well. And then to every we want this as in the ray, because you want to create the new A collection. But this eliminates support collection, not the XO one, because it generates its own cult type of the collection. Okay, Now let's import this one. It is a fuss. Answer is not going to show here, so just use Excell. There we go. That's no important. Now we have a collection of all these records that where within this uploaded file, we have it as a collection element collection. So the next thing we need to do is to finally feel that these records to make sure we have on lee the correct ones, the ones that actually represent valid email address without any duplicates, and after that's we can add them to the database. So let's work on this in the following video. 5. Mailing list filter class: it's time to figure out how we're going to feel terrible. All these records. So what? I'm going to start with this air. The variable filter equals and new mailing least field. We don't have this field two yards about, Let's quickly have a look at what it will take. First of all, we're going to pass. It's a collection of records that we just extracted from the uploaded file. And second of all, I'm going to pass. It's a collection off all existing email addresses, which are currently in the database. Let's initialize this property, and it's not this all methods stop as well. We will work with this method in just a moment. Now, as you may remember, from within the control with passing two arguments Where ISS our collection fields. It only takes one argument for the constructor. So what I'm going to do is override this constructor. Ah, new constructor, this son, I will take collection as the 1st 1 and then the 2nd 1 is going to be also the collection time, even though it's eloquent, collection is going to be subscriber e mails and here what I'm going to do is basic run their parents construct the first, uh, construct. Passing this collection is the first argument. And then I'm going to initialize this, uh, subscriber e mails Property. Well, that's just added quickly as well on Let's make it private. No one needs access to it milder than us from within this class. Now it's about these two. They're Doug Block's. But the double look here for the constructor that's I would constructed now. And so we passing two arguments, then we call construct on the parent class, passing the collection as the only argument that the parent class constructed takes. And then we initialized the subscriber emails property, which is going to contain all of the emails that are currently in the database. Now, this way we will optimize this whole import a little bit, rather than rather than doing this all every time with each iteration. Basically, when were doing all the checks and everything like it, we're going to have all these emails that are already in the database available to us when we instance she ate this class. Okay, so what we going to do next? First of all, from within this all method, we need to start with Oh, variable this collection and we are going to, uh, run their mop method on it and for the cold back will refer to our internal method called purify. So the first thing we're going to do is to purify the record and by purifying what I mean is email field. I want to remove all unnecessary or invalid characters that shouldn't be within the email field. So let's create this new public method called purified. Now, why public? Because otherwise this mop method wouldn't have access to it. When you using Rehm up, the standard PHP functions Rehm up array filter. And so when you can use private visibility for the methods within the same class. However, when you are delegating calls to the mayor to the collection methods, you have to have them. Oh, public. Okay, so from within this purifying, this purify will take array, which is going to be so scribe er because obviously these ones are going to be passed in their former like this is going to be se email, email and then name will be something else. So basically, this is going to be what we going to receive here through as an argument, obviously, with each iteration of the smart method. Okay, so that's what we're getting is going to return. And the Rays? Well, eso here, we're going to go for subscriber email this purify email method, and we're going to pass subscriber email as an argument. So this purify email method will basically make sure that we only get what email field should have. And then we're going to return the subscriber, uh, array buck. So let's create this purifying email method as well. And before we do anything, let's our dog blocks to this purify methods and more. We're going to say he has purify record from and then dis purify email that's going to be office. Email is going to be of a string type, presumably, but it might be off any other types. I'm just going to actually remove this site. Pdf and we will expect string Buck so private this time because we refrain directly to the method within the same class return and we want to return string. So I'm going to just, uh, ah type casted here to a string string to lower. First of all, because I want to make sure email has old characters in lower case than preg replace. And what I want to replace is busted that, uh, the regular expression will be in between a square brackets we started with the card symbol needs to start with number. Oh, let's Ah, and symbol and full stop. That's all we allowing and, in its case, in Sensitives after the last for its lush letter, I shortly after recorded this video of realized that the Reggae X should be slightly different. We don't need back slash D because numbers automatically included with back slash W it, which basically returns off on the Miracle characters plus underscore. Then we should also include hyphen. That's why I've added a hyphen at the end, proceeded with a backslash. So if you copy this records instead of the one in the video, they should much all possible characters for a valid email address and then anything that doesn't much this Parton. We want to replace wit, an empty string and then the subject. This obviously any mail okay, lets out some dog block here, and let's say that this one will be a string. Actually, let's tie painted a string and let's typecast it when we pass into this beautiful email s string as well, just in case it probably will be imported A string anyway, from within the CIA's we filed. But that's just typecasting here, anyway. Okay. And then if we going to say purifying email, fault the summary. Okay, so now going back. As you can see, this collection here is highlighted. And this is because if I go back to this collection, feel that we have this property, but it's got private visibility, so any sub classes cannot access it. So let's just quickly change it to it. Protected saved this collection, field, abstract class. And now it should. This highlight should be gone, and it is Okay, so we have all of the records now purified on their email is purified, so they're Onley her actors that are allowed within the email. So now any of these back ticks for its large, it should be gone from within the email field. Next will be invalid e mails. So what I'm going to do issues this all collection which has already field it, and then I'm going to feel tear it using the fields a collection filter methods using this and the new methods, which is called Going to be called in volleyed Emails that so I'm going to call this method that's copy the name of the methods. And if we scroll down and let's create this public function involved emails and again, we passing every subscriber as an argument, it will return bullion. It basically checks if the email on the subscriber array is going to be off the valid email address. Okay and we have returned. We used a simple filter von disco var. If you want to use any other form off email validation police uses from within this email involving emails method make sure there it returns. True if it validates false if it doesn't subscriber email field and then filter undiscovered volley date email. That's what I'm trying to validate. The given item s the killer's out. Some dog block takes a rare returns bullion, Determine if email is volleyed. That's our invalids emails method. If we scroll back up s on now, after this involved emails, we're going to have a non unique e mails equals invalid emails. What we have left after this filtration and we run unique, not union. Nique. There we go. We want all records, don't have unique email. So if there are two records with the same value associate with the email index within the given array, then the 1st 1 will be kept, the other ones going to be removed. So now we have, and this is just a standard collection methods, so we don't have to create another method to run it through. Okay, so now we have known unique emails. We have valid emails, and we have the emails that are fielded already. So filter basically will make sure that we have all characters dots email field, except then filtering through is involved. Humans removes any valid records, the records that have involved email address. Then we ensuring that within this find of imported, we only get the record starts half unique email address. So on the one email address record with one email address is going to be on, Lee wants. If there are two of the records with the same amount Village email address, only the 1st 1 will be left. And then finally, when we going to do is do plea cat e mails and this one was used, its non unique emails what's left of it and then filter it through there. Internal method again, off this class duplicate emails. And if I know, copy the name off this method. And if we scroll down another public function, duplicate emails again, we take a race subscriber, and this one will also return bullion. And what we do here is bicycle check if return exclamation mark this subscriber subscriber emails. This collection that we passed through is an argument contains given subscriber email if it contains, that means that that would be a duplicate. So we don't want this record. That's where we go with the exclamation, the beginning, making sure it does not contain does it not contain this email address? And if it returns, should and obviously that's going to be kept because that means that's not going to be a duplicate. Otherwise, it would indicate that we already have record with this email in a database. Okay, so I'm just adding the dog book here. Determine if subscriber email is already in the data base, okay? And I'm going to stop here because we still have to do a little bit more work with in this class. But I'm going to leave it for the next video 6. Error bag: continuing from where we've left in the previous video, we can now return the's duplicate emails collection, which contains all of the emails that are valid with all the invalid character stripped on old records. Don't don't have a valid email address are now removed. Or if perhaps obviously they also have any Dupee cats already in the database. Now, all this is fine. But you might be asking the question. Why am I actually associating all these calls to these methods with separate Vari Ables? Because we could obviously change. We could just remove all this and just do it something like this, and then change this straight after and so on. But the reason why we doing this is because we want to actually get those messages which tell us how many emails were invalid. How many where known unique harmony were already in the database and so on. That's why have associated them with the separate valuables. Now, in order for us to be able to provide this feedback later on, we are going to create a an Arab back class filter Aero back class which will store all these details. So what? I'm going to start with peace this aero back and I'm going to create this property straightaway. So if we just go up to the top here on, we're going to make it public so that once we've run our fields, we can actually use the instance of this a robot class which will create in just a moment to get all these data out of it. And that's going to be let's just quickly create. This class is going to be called filter Aargh, Bach that we go that class created so that I can. There are tears of that's a filter of buck and I'm going to the new filter air back. And what we are going to be passing here is in a right. Let's just actually art it this way. So there we go. And now I'm going to, ah, use the same naming as the variables. So all key represents all collection the old collections than in volleyed emails represents involved emails. Then we have known unique e mails, known unique emails and lust, one which is going to represent this duplicate emails. There we go. So that's pretty much everything within our mating these fields so we can save and close this class. Now let's go back to our filter Arrow back and we're going to start with is by declaring three properties, all of them there will be private. 1st 1 will be collection and it's going to be a night. Um, that will receive three constructors, an argument and this one ISS alone minute support. And it's not contractors just saw port call election. There we go. Okay. Next one will also be private. It's going to be a simple array. Errors by default will set it to an empty array. Then we are going to have private ah, pry But currents, which will also be a collection. And again, same eliminate support collection. Okay, now, constructor and construct a will take collection and then initialize it that we go. It's all important. No. Okay, so we have a collection after this, we're going to set this current to the first item in this collection. So collection first and then we make coal to parse method which will create in just a second. So it's of the methods stop. There we go. And this method won't return anything. It's avoids time, so return void and we're going to say parts collection and what's going to happen here? Let me just scroll up a little bit. We are going to look through all these items in the collection. So this collection using each method and then just a closure with the collection which we're going to get with each item off this main collection and we call it item and end the key and within disclosure. What we're going to do is this Art ero and we are going to arrow key and then this current count. So whichever item is currently set as current, they all all these items within this collection also call it off the off the collection type. So whichever one is the current one, how many items are there and then miners the one that we're currently looking through? So item and also method counts to see how many items are there. So if we let's just go back to our mailing this field, as you may remember, here we first we get the full collection, we just purify email address. Then we will reduce number of items based on whether there are any invited emails. So from this one from Maine, one, depending. How many items are there? Then we deduct this and that and many involved email addresses. We did half within this original collection. And then from this one, we go into the duct. Ah, unique in emails. And then from this known, unique emails were going to feel to this one again, based on what we have in the database. So all these items will represent how many items were invited? Forgiven? A method. Okay, so here, out there. And then we change this current to the one we Just where? Iterating Officer item. So next time with Nick next iteration, this existing one the one we're currently Iterating through is going to be set its current . And from this current, we going to deduct the next item in this collection. Okay, let's have this out era method as well. And this art era will simply take key and, um, count rather than Param. Let's just call it count and then string. Sorry key is going to be of a string type and count is going to be an integer. And let's just do this errors. We aren't item by key equals count. Now it's just don't block and it returns nothing's avoid. And for this summary, we're going to say art, Pero and then the last methods which will be using outside of this the instance of this class in order to obtain the basically count off the items for the given item for the given error is going to be called, gets a public function, get and we will take string, which is going to represent the key, and it will return in the job. And let's just on some summary here, get count off errors for a given key. So here, what we going to do to return this errors and then we simply pass the key. Okay, and nuts, everything. I'm just going to remove this redundant space here, and one thing of just melt is obviously we are expecting collection, but our mailing lists filter is passing the year eight. So let's make sure that we passed the collection. So collection, There we go. So that's the one we need to rob this array with. Okay, So, ah, if we run a test, obviously, if I just go back to the terminal and if I run the test PHP you needs there, we go. We still haven't ever. But this time it's a different one. We get 500. Is there something wrong with the cold? Obviously, if we go to the storage because five hundreds, as you may remember, they saved their lock to them logs directory. And what it say's is that we have exception here. Class mailing at least control and not found in our mailing list. So, in mailing these fields in our mailing list controller OK, I'm going to remove this lock, and I'm going to open our controller mailing with controller there. Regards highlighted. Let's import this class first of all, so we actually have it here. There we go. I'm just going to organize them all. Application imports separate from the packages. So if we know save it. Rana, test again. We still have 500. Let's quickly check what this new lock is telling us this time. We have mailing least no such table mailing list in connection. So let's just remove this looks straightaway as well. So the new one is going to generate if they're sending out the air air obviously is going to generate a new lock file, and this is because Obviously, if we check our sequel Pro, you'll see that I have a database. Better not have any tables because we didn't run the migration yet. So because I'm using homesteads, what I need to do is first of all to ssh to the Helms. That and then they run migration from there. However, if you're using Wamp, mom or ZUMP, you can do it directly from within the root of your project, where you run all other comments like from here, for instance, where you would do is simply wrong. PHP artists on my great and he returned. But if I do this here, it won't work because of me. I don't have data base on this instance Off the system I only used the database from within the vagrant from with Hans Det. So what I need to do, I'm going to open a new top here in terminal commands t on the keyboard and what I'm going to do is navigate to my home directory with us. Just CD now navigates the homestead directory and from here I'm going to run vagrant ah province. No provisions ss age, and that should logmein to the homestead. And there we go Fight do l s. You can see we have their cold directory. So seedy coat and he half I do ls I should have all my projects and the one I'm currently working on is this mailing least one so city mailing least and here can run Ph b artisan, my great, And that should create all the tables that we need, which is only one. So if we know he refreshed There we go. Our mailing Mrs here plans the migration table, which basically keeps track of all the migrations in which we obviously create through a lot of Okay, so now our database is ready. If we go back, we can no exit from this homestead s age on. Let's go back to our project. And now, if Iran PHP unit, we still get five hundreds this time, it should be a different era. So if we just opened his lock and this time it tells me that we have no table mailing lease , let's quickly check our database. It's called mailing lists with s at the end, because by default, when we create ah migration together with them with the model it arts is basically makes it plural like, rather than singular for the table name. That's not I would prefer actually having us mailing this rather than mailing least if we open our mailing list model. That's how I stayed it here. But obviously table within the migration is called mailing least. So what I will do is actually rename this migration. So if I just first of all, I'm going to rename the migration itself to the file. So rather than mailing lists, I'm going to say create meaning least table and then open this migration. Angry name dissed, able to mailing list. Same for the down method. I don't want it to be improved. The plural. I want this single us A mailing list table. That class name is Well, we save it. Close it. Let's now go back to death. The sequel probably to remove everything So the elite tables and, yes, delete force delete so we can run this migration again again. I'm going to open new top, uh, navigates to the home directory homestead and vague Grant s s age. Now that I'm connected, I'm going to city coat mailing list and PHP rt son. My great. And that's created table. It's quickly. Have a look. Now the name is mailing me. So that's all five. OK, so that's exit. And, uh yeah, and we can close this man least class. Let's go back and run the test against or PHP units. And this time it tells me that we haven't got this You have imported to records. Okay, that's actually quite an easy fix. So let's go back to our controller. And after the field turn, let's create a new value pickled subscribers and on this instance off the filter called this all method So we only get the records with basic. This filter will filter all of them and return only the ones that are to be added to database and now mailing least model. On this model, we call insert methods and we pass this list of subscribers, Throw so that should are these records database. And lastly, let's remove The founders just been uploaded. So on link and then file Vari Able, which contains the full path to this uploaded file and then what we can do is fold this view. We are going to our touch a few variable so with subscribers and we passed the subscribers through so that the entire list is going to be passed through to the view and then a Robach with air back. And we passed this field error back so we can actually pull all these numbers through. So OK, so that's the controller end this storm methods completed. Let's now open. Our resource is and from within the views, if we go back to a mailing least and result and here we're going to start with a new paragraph saying you have import it and then between the brackets, count equals subscribers count. So we get number off subscribers and I'm associating this with the very because I'm gonna have to use it against the rather than calling the method again and trigger in discount method and wherever that method, as I have already resulting, is very before next for when I won't need to use it next within this view and after this space and against it of brackets, curly brackets And then I'm going to use helper functions, string underscore plural, and I'm passing the words that I want to make plural or singular out off, which is going to be record and then number off item which will determine what it's going to be record oil records. So this is where this count avoid was being passed, cause otherwise I would have to call this subscribers count again, which is obviously completely unnecessary. Five. Already cold. Hold it once I can, especially the value of the volume one. Just pass it through as an argument. Okay, so let's save it. Let's run our test. Last time you tell that they told us that you have imported to records message Wasn't a wasn't available within the view. Let's run again. As you can see now we have a different there again. 500. So let's check the lock and what it say, Stipe argument one past to build the insect mosby off the type array object given. Okay, let's go back to our controller. This is because we are passing collection rather than the array because filter all. If we click on this method, you can see it returns collection rather than Harry. So what we need to do is simply Onley subscribers Coal to array and not should work just fine if we go back turning off Rhonda test again and there we go. So the previous messages gone. So the previous messages now passing the procession is passing. Now we don't have this too involved email addresses. Okay, let's work on this in the next video. 7. Results view: continuing from a previous video. As you can see, our test is still failing. Now it can find this string, which to invalid email address. And if we go back to our tests, you can see this is where this assertion ISS place. So we successfully getting the response, okay, which is 200 status guilt. Then we get the import completed string. Then we can also see that were imported to records. But we now cannot see this to invalid email addresses. So what we going to do is go back to our result, Don't play doh PHP. And we are going to create another paragraph and he I'm going to start with a strong and I'm going to put the message you're file contained. Colon ended after all this new line, and we're going to start with a set of carried rockets in volleyed e mails, variable. And here we are going to use arrow bach and we called get involved e mails. As you can remember this a Robach get a method. If we just go back to components air back get will get us the number off the count. Basically, for the given index from within years property. So if we go back, eso This should tell us how many invalids images is where there. And we associated this with Avery before. Exactly Same purpose as here because we're going to use it again rather than kind is get method again. We're just going to use the variable. So here are we going to say so many involved email and now for the address or dresses to again, we're going to use this string chloral. We put a dress and then involved involved emails. So this will either return address or addresses, depending on how many there are. If I save it, run the test. Now we have this to invalid email addresses. The message should now change there, and we still should be failing on. We do, but obviously we get different one. Now it's one duplicate air duplicate record is what isn't showing. So after this one, we're going to do B R. And let me just close their far browse and left so things are aligned a little bit better. Okay, for this one, we're gonna go for non unique emails. If we just open our test, we have a duplicate records so This is actually the one that's associated with, uh, known unique emails so non unique e mails equals error back get. And it's going to be known unique e mails. And then we're going to say, Do pally cat string plural again and it's going to be a record. So, for instance, 10 duplicate records if there is more than one, obviously, and let's pass this non unique e mails very able through. So we know how many and then the string blood always going to figure out with its records or records. Okay, save it. Run a test again. It fails again about this son with a different message. It doesn't see zero records, all zero already existing records. It doesn't see this within our returned view. So again, new line. This I'm going to do. Do plea cat e mails equals error. Bach get do plea cat e mails and already existing and against drink brutal. A record occurred and we passed Do pally cat emails save it, run a test again and we go. Everything's passing. So we finally made our test passed. So up until now everything is okay on the next thing we need to do I want to upload another file? So what, I'm going to do this after I'm going to do is from within the same 10 test method. So what? I'm going to decide you're going to copy this coal method and pace it right after this. Don't seen database the last one. Only this time we're going to be important. This mailing least two if we open the file browser every open our test and stops directory have mailing list and mainly needs to. And the only difference between the two of this is if I just open them. So this is the 1st 1 And Mark Spencer here has an A. And if we switch to the other one, Mark Spencer here has actually valid email address. So this one should be imported that we should be the only record that's been out of the database after importing the previous one. And this will already be in a database. Obviously, this will be duplicate within this. See is V file and so on. Okay, lets go back. So after this, what? I'm going to do this first asser dot We get response. Okay, so this response assert response. OK, so we should get to hundreds status. Then we're gonna go for this, See dext and it's going to be import completed next association. I'm just going to duplicate this line and change the text here. We should have you have imported one record because the other one were duplicates or invalid. Then if I are duplicate this one, then we should have Ah, one invalid email address. Let me just actually you with low case 01 involved him address. If we just go back to our CIA's, we file this is the only invalid email address within the CSU file. So that's this one. Let's create another assertion here. Then we should have won do plea cat record. And here we are, referring to the duplicate within the CIA's V far, which is going to be this Jesse and Jesse after this one has been field it and then another one is going to say ah to already existing records. So if we save it because these two obviously are imported from the previous spread should if we save it, run the test and there we go, everything passes. So that's great. Now we need to put a few more sessions. We're going to start with this assert count, and it should be three records in the database. Now, when we wrong mailing least old method, save it, run it. And that passes a swell buck to the editor. After this, Assert count, We gonna say that that we gonna assert that we see record in the database? ISAF, See in database table mailing least and here we should see Name, uh, John Doe from the previous import and email should be joan dough dot com All lower case. Save it, run it. And we go 30 to all stations, all of which are passing. Let's duplicate this one. We should also see Jesse Doh that's going to jazz. See, 12th does that come? Run it. 33 associations, All guilt. Okay, We should also see this newly important record. Which waas mark spend, sir, And the email address walls. Mark spends sir dot com. Let's run it. 34 assertions, all of which are passing and then two records that we shouldn't see this don't see in database mailing. Least we shouldn't see the record with name Greg Monte. And also, if I just copy this one we shouldn't see the one with Brian Smith with email. Just see 12. Because this one obviously would be a duplicate within the CIA's very far. So don't Condo did come. Okay, let's run this and everything passes just fine. Now, if we go back to the editor and have a look that would result blades we only disprove displayed basic the information about how many records were imported, how many wins, any problems and so on. But we didn't actually display any off the imported records, which is what we want to have. The first thing we're gonna do is go back to our mailing list test, and I'm going to start right at the top for the first request. So we call the uploading this mailing list, See SV. And then I also want to see these records, which I have important because that's what should be displayed on this. So we should see John Dole text on the page with the email address. So john doe dot com and we should also see I'm just going to duplicate this one Jesse Dough with Jesse 12 off, though dot com. So that's what we should see here and then we also should see after this one, because here we only imported one record. I'm going to duplicate this last assertion. We should see this Mark Spencer then call on and his email address. So that's what we should see if I just based here. And if I ran the test now, obviously this wail failed. There we go. We doesn't see John Doe with his email address, Okay? I mean, I was going to clear the screen back to our editor and then back to our result plate. What I'm going to do here, it starts after this rapper I'm going to create another deal with the Robert Class. This is giving us this this great box wrapping the content. And here I'm going to start with you, l class least and rather than using for each, uhm I'm going to use each directive. I'm going to pass the view that I want to use, which is going to be mailing. At least it's going to be within the park shells directory, and it's going to be called road old blade dot PHP. So we only have to put raw here. So this is the one for each record for each iteration. Then we passed the collection, which is start within this variable subscribers. So scribe er's and then how each one is going to be referred to from within this have you here it's going to be simply subscriber variable. And then, if the subscribers collections empty, what should we display instead mailing least par shells and then raw hyphen empty. And it's going to be dulled. Blade dot PHP, and we can put all these on new line separately, so it's a little bit easier to read, and it's indented. And there we go. So open the fiber browser mailing needs. Then we go to resource is views mailing this? Let's create this directory partials. And let's create both of these files that the 1st 1 is going to be role. Don't blade ph beans. That's the 1st 1 And the 2nd 1 is going to be raw. Empty roll, empty adult blade dot PHP never go. Okay, so we have both of these files. If I now go back to row blades here, I'm going to use this l i as one of the arm two items. Then within the set of rockets subscriber name Ah, colon space and then subscriber email. So that's what we should see. Otherwise we should see if I just open this raw, empty blades again. Within between the ally tax is going to be no records. Where import it, save it. I'm going to close this file this one as well. This air back as well. And a div you is done so we can close it as well. Bucked our test. If we run it now and then we go. Everything passes now one are this scenario that I would like to do is to check them when I'm importing the same spreadsheet as I did before that none of the records is displayed, as are none off the records is important and that we actually see this message from within this. No records were imported view. So let's just carpet isn't I thinks I'm going to copy Old this and Goldbach go right to the bottom. Here, make another coal with the same file. And now import completed was will still see this. But we going to see you have imported zero records and we're going to see how Maney invited email addresses whether within this mailing list. There was only one. So one stays here. Duplicate records within the spreadsheet within this Fine if we just go back within this one, we only have this Jesse twice, so it's only one. And then already existing records. There will be three, because three after the two calls, we already have three records in the database, and we shouldn't see any off this. We should see whatever we put in here and this amputees. So I'm just going to copy this message and paste it here and let's let's run this test again. PHP unit. And there we go. Now we also want to make sure that we didn't are any records. I'm just going to copy all this again all the cessation we could actually extracted to a separate method. But it's just a quick test. So, yes, I'm just going to paste it. Nothing should change, so everything should stay the same if I run it again. And there we go. Five tests, 52 Alsatians, all of which are passing. So I think now it's a good time to test our project in the browser. So it's open a browser and then we go our landing page. First of all, I'm going to try and kids upload without selecting file. And there we go. Validation message displays. The fire field is required. I'm going to select the involved final form out. So if I navigate to my cold directory mailing list and within these test directories stops , we have this document, pdf, There we go. And if I hit upload that should tell media. Yeah, the file top is wrong. That's great. Now, if I sell it, dis mailing the CIA's V and click on Open before I heats Upload. Let's just checked out our tables. Clear. There's no records there. Hit uploads And there we go. We have to Records imported to involved email addresses. One duplicate records. Zero already existing a database and these other ones that were imported. OK, One other thing I just noticed we don't have this button, which I actually add it in the original project. So let's just open this result blade dot PHP file and what I'm going to art here right after this paragraph. Second paragraph here in his first proper, let's put a a treff for it slash just to go back to the form and class of Barton. Let's say import and other, for instance, Save it and close it buck to the browser. Now we just have to re reload the page. And now that we know we have to find, let's just check again within their database, their gold is to have being records. Thes two records have been imported. Now I'm going to try and import the same spreadsheet. If we hit, Upload was going to tell me that it imported zero records because to invalid to one duplicate and two were already in the database. And then we have this. No records were imported message and again. Another thing that I've forgotten to do is not up this heading. Let's just go back to this results. And before this least in the second Robert, I'm going to put age too age to imported bread. Kurds heavy Gil save it and close it now import. And now they're this summit. Select this 2nd 1 so we should be able to import just one record from them. Heaton upload, and then we go. One record uploaded 20 volley toe on duplicates to already in the database and record. That's been important this one. Let's try again. Same file uploads and no records important because we already have all three valid ones in a database. Okay, so that's it in this serious. I hope you enjoy this. Any questions? Suggestions? Use our common section.