تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Planning Fake Product Cleanup0:00

We want to provide the user the ability to delete the fake products that were created by our app. Now you might be asking why can't the user just go to the products page and select all these products and then do delete products and delete them this way. The answer is yes they could do that but we could provide a more convenient way to mass delete all the fake products that were created by our app because they might have some other products in their development store that they may not want to delete. This way they don't have to do some filters on the products page to find the products that were created by our app and delete them manually. We can give them a button that they can click that will do the cleanup for them. Now to provide such functionality we need to track the product IDs so that we can make an API call to them to delete them. So let's open our code editor. Let's open the terminal. We need to create a new migration and a new model so we'll do

Creating FakeProduct Model0:46

track the product IDs so that we can make an API call to them to delete them. So let's open our code editor. Let's open the terminal. We need to create a new migration and a new model so we'll do vendor/bin/sail artisan make:model FakeProduct --migration hit enter. Let's open the migration and let's add a column here to store the ID that we get from Shopify. I think they're all integers so we could store it maybe as unsignedBigInteger or something like that. You could also store it as a string but I think they're all integers so we'll do $table->unsignedBigInteger('shopify_id') and we could call this shopify_product_id or just product_id but I like shopify_id more and we'll make this unique. Next we need to associate the FakeProducts with the User or the Shop that is creating them so that way when one shop creates FakeProducts it doesn't interfere with another shop's FakeProducts. So we need the user_id foreign key that references the users table.

the shop that is creating them so that way when one shop creates fake products it doesn't interfere with another shop's fake products. So we need the user_id foreign key that references the users table. As far as the timestamps goes we only really need the created_at timestamp. I don't think we need the updated_at so I'm going to change this to timestamp created_at and I think we're good for now. I don't think we need to store anything else. This should be good enough to get us started. So let's migrate the database. We'll do php artisan migrate. Let's now open the model and configure our model. So we'll open FakeProduct and here we can add the casts variable to cast the created_at to DateTime. We also need to disable the updated_at timestamp so we can do const updated_at equals to null and we also need to define the user relationship. So we'll do public function user() belongsTo and this will return belongsTo relationship with the User model. Let's also

Saving Shopify Product IDs2:36

to null and we also need to define the user relationship. So we'll do public function user() which belongs to and this will return belongsTo relationship with the User model. Let's also add the inverse relationship on the User model because User or the Shop has many Products so it will be a hasMany relationship on the User. So we'll do public function fakeProducts() and this will return hasMany. So we'll do return $this->hasMany(FakeProduct::class); Great. So now we need to save the Product IDs whenever the fakeProducts are created. So if we go to our ProductController we are creating the fakeProducts in here and we're storing the ID in this products array. So we essentially need to do something like $shop->user->fakeProducts()->createMany($products); this way. We're getting an underline here saying variable $shop is probably undefined well because we're defining it within the loop. I'm not sure why this is here this should have

the products this way. We're getting an underline here saying variable shop is probably undefined well because we're defining it within the loop. I'm not sure why this is here this should have been outside of the loop anyways. So let's move that there and we also need to adjust the products array because we need to prepare it to be compatible with the FakeProduct model. Since we're not really using products anywhere else this was just for debugging purposes so we can actually remove this from here and instead of returning JSON we'll just return no content and let's adjust the return type here and we can change the way we are structuring our product array. So instead of doing id title we can do something like shopifyId equals the id and we can get rid of the title because we don't need to store the title for now. If we need to store more information we can always add that later on but for now the most important thing is the id

can get rid of the title because we don't need to store the title for now. If we need to store more information we can always add that later on but for now the most important thing is the ID that's what we're going to use to then delete these fake products. In fact we can actually get rid of this extra variable and just put this directly in here. Next since we're creating many products this way with Shopify ID we need to add this to our fillable property so we go back to the fake product let's define fillable array and set Shopify ID in here. Great so let's test this out now to see if the products are being created in our local fake products table. So let's go back to the browser open our app let's click create it's going to take a couple of seconds then go to products and we see that the products were created in here. Now let's check the local table let's go back to the code open the database refresh and sure enough we see the five products

Adding Delete Button UI5:13

to products and we see that the products were created in here. Now let's check the local table let's go back to the code open the database refresh and sure enough we see the five products created in our fake products table. Now that we have these IDs stored in our local table let's add the delete button to allow the user to delete these products. So let's close these things out for now and we're going to open ProductCreator let's actually open the App component and in here where we're rendering the ProductCreator we're also rendering this Page component and the Page component can actually have the title as well as the primary action button. So we can do something like title equals generate fake data and then set the primary action button to something like delete fake data button. Let's actually move this component within the ProductCreator I feel like this is awkward having it outside of the ProductCreator I feel like this belongs inside. So let's

delete fakeDataButton. Let's actually move this component within the ProductCreator I feel like this is awkward having it outside of the ProductCreator I feel like this belongs inside. So let's put that in here we'll add it right here and let's close it out here let's format we need to import the Page component and we need to create this DeleteFakeDataButton. So let's open our project files scroll down to components we'll add a new component here called DeleteFakeDataButton.jsx let's create that functional component here which will return some jsx and we'll export default DeleteFakeDataButton. All right in here we can render the destructive button so we'll do something like Button from the Polaris component we'll set it to be destructive and for the text we can set it to something like Delete Fake Data and I think this is good enough for now we'll add the onClick handler in just a bit. Let's open the browser to see if this actually works we do need

we can set it to something like deleteFakeData and I think this is good enough for now we'll add the onclick handler in just a bit. Let's open the browser to see if this actually works we do need to import this so let's import let's close that out let's open the browser let's open our app and sure enough we have the deleteFakeData and we also have this nice title in here. Let's now add the onclick handler on the deleteFakeData button so let's go back to the code let's add onclick handler here this will call some deleteFakeData function let's create that function deleteFakeData and in here we're going to make a DELETE request to some endpoint like /products so we'll do axios.delete('/products') and maybe let's set some loading state so we'll set some loading in here setLoading to true this means that we need the loading state so let's add it here const loading = setLoading this will be set to false by default and we can set it to false

set some loading in here set loading to true this means that we need the loading state so let's add it here const loading set loading this will be set to false by default and we can set it to false if the request was successful and we can also set it to false if request failed so we'll set loading to false here as well next let's add the loading to our button and this button actually has the loading prop so we'll do loading loading and we just need the axios instance so we can use our custom hook for that we'll do const axios equals useAxios and i think this is good enough now this will of course not work yet because we haven't created this route so let's duplicate this route it will be on the same /products but it will be a delete request and we'll change the method to destroy let's create this method on the ProductController so let's scroll down we'll do public function destroy and this will again return no content because i don't think

Implementing Delete Endpoint8:54

method to destroy let's create this method on the ProductController so let's scroll down we'll do public function destroy and this will again return no content because i don't think we need to return anything here so we'll do response()->noContent() let's add that return type and we need to fill this in to actually delete the products from the API now to implement this functionality we need to loop through all the fake products that we have stored in our local table so we can do something like $shop = $request->user(); and we need to inject $request in here so we'll do $request = request(); and then we can do $shop->fakeProducts and loop through each fake product and then do the API call for each product so we can do a function fakeProduct $fakeProduct and in here we'll make the API call now the API call here is pretty similar to this except that instead of POST it's a DELETE request to this same endpoint so let's copy this put it

fakeProduct and in here we'll make the API call now the API call here is pretty similar to this except that instead of post it's a delete request to this same endpoint so let's copy this put it in here this will be delete and the other difference is that we need to add the productId as part of the url so instead of the payload here we need to put it within the url so we'll do fakeProductShopifyId.json because remember the shopifyId we're storing it on our fakeProduct model let's make sure that shop variable is available within this closure then we can check if the response was successful or not the same way in here so if we have the errors instead of throwing the exception we'll simply report the exception for now responseException and otherwise if the response was successful then we can delete the local product record as well so we can do fakeProduct::delete let's open dev tools click delete fake data and seems like that worked

if the response was successful then we can delete the local product record as well so we can do fake product delete let's open dev tools click delete fake data and seems like that worked let's go to products and products haven't been deleted probably because i have some kind of error and the exception was reported instead of throwing it to the user that's probably not the best user experience we should probably do something about that but for now let's look into the code to see what i may have made a mistake on oh that's right we're missing the slash in here so it was doing productShopifyId which is invalid so we were probably getting something like 405 or some kind of error so let's add slash in here and let's try it again let's click delete that worked let's check the product and sure enough this time the products are gone let's check the local table open fakeProducts table and sure enough that table is empty

let's click delete that worked let's check the products and sure enough this time the products are gone let's check the local table open fake_products table and sure enough that table is empty as well now we should also probably add handling for cases where the API responds with 404 status because remember if we get some kind of error here and the status is 404 that means that the product has been probably deleted manually by the user from within the products page and if that's the case then we should probably just delete the local record we don't need to report it or anything like that so what we can do is that in here we can check if the errors are empty or the response status is 404 then we can delete the local record otherwise we can report so let's test this out i'm going to create five new fake_products let's check it that worked let's delete two of these manually so i'm going to delete it from the products page so now we have three products left

Adding Toast User Feedback12:29

i'm going to create five new fake Product instances let's check it that worked let's delete two of these manually so i'm going to delete it from the products page so now we have three Product instances left let's go back to our app click deleteFakeData check the products products are empty let's check our local table refresh and our fake products is empty all right so let's actually add some sort of feedback message to the user to improve the user experience to let them know that we have deleted the data or at least we have started deleting the data Polaris has a Toast component that we can use for that case so let's go to our deleteFakeData button component we'll need the state to manage the toastMessage so let's add that in here we'll do toastMessage, setToastMessage and by default this will be set to empty string and then we can set this message in here we can do setToastMessage to something like deleted fake data and then we need to render

message and by default this will be set to empty string and then we can set this message in here we can do setToastMessage to something like deleted fake data and then we need to render this toast message and we can do that in here if we have the toast message then we can render the toast component and the content of this message will be toast message and we also need to add the dismiss handler so what happens when the toast is dismissed so we'll do onDismiss we'll simply clear out the toast message so setToastMessage to empty for toast components to work it needs to be wrapped within the Frame component so let's wrap the whole thing from the ProductCreator component into a Frame component so we'll do Frame and close the Frame in here let's test this out now let's open the browser create five products and now let's delete the fake products and sure enough we see this toast message pop up right here now let's do the same

let's test this out now let's open the browser create five Products and now let's delete the fake Products and sure enough we see this toast message pop up right here now let's do the same thing when creating the Product so let's go back to the code i'm going to copy this and paste it into the Product creator under the button right here and we'll manage the state the same way for Product creation so let's scroll up create the state in here and we'll set the toast message right here so we'll do setToastMessage to something like generated fake data and we can get rid of the console.log because we're not returning anything in the response let's test this out now let's go back to the browser create five Products again and sure enough we see the generated fake data toast message let's delete and that works as well notice how it's taking a couple of seconds to create and delete the fake Products creating and deleting more Products like

generated fake data toast message let's delete and that works as well notice how it's taking a couple of seconds to create and delete the fake products creating and deleting more products like 100 products for example would take much longer so for better user experience we should maybe queue the jobs to create and delete products let's do that in the next lesson and talk a little bit about the API rate limits and versioning

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟