From f437dc3ed9f48352ec0ec61e9c58d17c0262fb29 Mon Sep 17 00:00:00 2001 From: stephenjude Date: Sun, 12 Jan 2020 23:20:09 +0100 Subject: [PATCH] revert previous changes --- app/Http/Controllers/BlogController.php | 5 +- public/author.json | 1 - public/migerations.json | 1 - public/post_tags.json | 1 - public/posts.json | 203 ------------------------ public/tags.json | 1 - routes/web.php | 2 +- 7 files changed, 3 insertions(+), 211 deletions(-) delete mode 100644 public/author.json delete mode 100644 public/migerations.json delete mode 100644 public/post_tags.json delete mode 100644 public/posts.json delete mode 100644 public/tags.json diff --git a/app/Http/Controllers/BlogController.php b/app/Http/Controllers/BlogController.php index 2f8b93b..5c01cf5 100644 --- a/app/Http/Controllers/BlogController.php +++ b/app/Http/Controllers/BlogController.php @@ -117,15 +117,14 @@ public function seeder() $this->insertData('wink_tags', $tags); $this->insertData('wink_posts_tags', $post_tags); - dd('done'); } - public function insertData($table, $data) + private function insertData($table, $data) { return DB::table($table)->insert($data); } - public function extractJsonData($filename) + private function extractJsonData($filename) { $posts = file_get_contents(public_path($filename)); diff --git a/public/author.json b/public/author.json deleted file mode 100644 index 4b69345..0000000 --- a/public/author.json +++ /dev/null @@ -1 +0,0 @@ -{"title":"extract","values":[["aec24398-2e6b-4241-89ff-a4088c9259a9","stephen-jude","Stephen Jude","stephenjudesuccess@gmail.com","$2y$10$rl7P1QOI/9AdzDX/MFkg.OeC9cJ0L2XO85FspXLl4Utn8bGyj6gRu","\u003cp\u003eI build for the next billion users.\u003c/p\u003e",null,"nY4FxEUI8B4BFRDFkrhytqrlB5qJoMefI6mRHAtTwWaF45yinrQK5vHFUfK4","2019-10-05 06:21:29","2019-10-05 06:23:29","{\"meta_description\":null,\"opengraph_title\":null,\"opengraph_description\":null,\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":null,\"twitter_description\":null,\"twitter_image\":null,\"theme\":\"light\"}"]],"fields":["id","slug","name","email","password","bio","avatar","remember_token","created_at","updated_at","meta"],"types":[2950,1043,1043,1043,1043,25,1043,1043,1114,1114,25],"type_names":["uuid","text","text","text","text","text","text","text","timestamp(0) without time zone","timestamp(0) without time zone","text"],"started_at":"2020-01-12 12:50:06 +0000","finished_at":"2020-01-12 12:50:06 +0000","checksum":"58948fd6ef7e1279a27522607e956692"} diff --git a/public/migerations.json b/public/migerations.json deleted file mode 100644 index b614e8e..0000000 --- a/public/migerations.json +++ /dev/null @@ -1 +0,0 @@ -{"title":"extract","values":[[1,"2014_10_12_000000_create_users_table",1],[2,"2014_10_12_100000_create_password_resets_table",1],[3,"2018_10_12_000000_create_canvas_tables",1],[4,"2019_02_16_000000_create_canvas_topics_tables",1],[5,"2019_03_05_000000_add_indexes_to_canvas_views",1],[6,"2019_08_19_000000_create_failed_jobs_table",1],[7,"2018_10_30_000000_create_tables",2],[8,"2018_11_16_000000_add_meta_fields",2]],"fields":["id","migration","batch"],"types":[23,1043,23],"type_names":["integer","text","integer"],"started_at":"2020-01-12 12:47:58 +0000","finished_at":"2020-01-12 12:47:58 +0000","checksum":"18e6a37343c4bb1a283c5d6349f22b6f"} \ No newline at end of file diff --git a/public/post_tags.json b/public/post_tags.json deleted file mode 100644 index 7617d2b..0000000 --- a/public/post_tags.json +++ /dev/null @@ -1 +0,0 @@ -{"title":"extract","values":[["be6a404b-2974-49a2-83a0-792442ca5f11","fe5de373-a818-4faa-9411-5536a2112b73"],["be6a404b-2974-49a2-83a0-792442ca5f11","47b633f5-b0c7-4033-b9b8-ac4619f7a8d9"],["be6a404b-2974-49a2-83a0-792442ca5f11","05a1c5b1-8aaf-4d1e-94bf-2c7f67179601"],["be6a404b-2974-49a2-83a0-792442ca5f11","30372141-bdc2-4ee6-ac37-a3e851c9751d"],["8de5c7d4-31e2-4d51-a38f-be571307969f","fe5de373-a818-4faa-9411-5536a2112b73"],["8de5c7d4-31e2-4d51-a38f-be571307969f","47b633f5-b0c7-4033-b9b8-ac4619f7a8d9"],["8de5c7d4-31e2-4d51-a38f-be571307969f","05a1c5b1-8aaf-4d1e-94bf-2c7f67179601"],["8de5c7d4-31e2-4d51-a38f-be571307969f","30372141-bdc2-4ee6-ac37-a3e851c9751d"],["58de5bc4-4a8d-4434-a95b-f93a473329c0","30372141-bdc2-4ee6-ac37-a3e851c9751d"],["58de5bc4-4a8d-4434-a95b-f93a473329c0","05a1c5b1-8aaf-4d1e-94bf-2c7f67179601"],["58de5bc4-4a8d-4434-a95b-f93a473329c0","be25e91a-0675-43a2-8527-f47a345e3550"],["58de5bc4-4a8d-4434-a95b-f93a473329c0","b2fcdfd8-c0a3-4a32-b79b-6342b9f703a6"],["58de5bc4-4a8d-4434-a95b-f93a473329c0","00e22b8c-118a-43bd-8150-f0c1edcc913a"],["51b43e58-5bf0-4ed1-b9d9-9b68f215abdd","05a1c5b1-8aaf-4d1e-94bf-2c7f67179601"],["51b43e58-5bf0-4ed1-b9d9-9b68f215abdd","4898707b-210c-4808-9073-270df6f002db"],["51b43e58-5bf0-4ed1-b9d9-9b68f215abdd","44a9b58e-e8a0-47d7-83e6-4a7acb6b6d02"],["51b43e58-5bf0-4ed1-b9d9-9b68f215abdd","76a439df-f172-46b0-84b1-ffcb7c2fa00a"],["51b43e58-5bf0-4ed1-b9d9-9b68f215abdd","a781e343-1f42-4c90-ae0b-7efc89bc9c01"],["51b43e58-5bf0-4ed1-b9d9-9b68f215abdd","993ae98a-73b9-46ba-a916-a529df2466e7"],["c447fd84-8b91-465d-afe4-79b9ad2a3c78","29880afc-0071-4414-9336-2cf73ad5ca26"],["c447fd84-8b91-465d-afe4-79b9ad2a3c78","6ce8c6e6-add4-4316-bdb2-32d2767117aa"],["c447fd84-8b91-465d-afe4-79b9ad2a3c78","05a1c5b1-8aaf-4d1e-94bf-2c7f67179601"],["c447fd84-8b91-465d-afe4-79b9ad2a3c78","30372141-bdc2-4ee6-ac37-a3e851c9751d"],["c447fd84-8b91-465d-afe4-79b9ad2a3c78","996acbb0-75a1-4eb8-a4a7-402e1fa2c182"],["c447fd84-8b91-465d-afe4-79b9ad2a3c78","36e42cbb-a8bb-4469-9fbf-30b2a14cf681"],["5e07bf7f-3066-4d2a-a1fa-6ee2c32138b9","29880afc-0071-4414-9336-2cf73ad5ca26"],["5e07bf7f-3066-4d2a-a1fa-6ee2c32138b9","36e42cbb-a8bb-4469-9fbf-30b2a14cf681"],["5e07bf7f-3066-4d2a-a1fa-6ee2c32138b9","07844ed0-d615-4ffe-a57e-47575ed386ba"],["5e07bf7f-3066-4d2a-a1fa-6ee2c32138b9","6ce8c6e6-add4-4316-bdb2-32d2767117aa"],["5e07bf7f-3066-4d2a-a1fa-6ee2c32138b9","996acbb0-75a1-4eb8-a4a7-402e1fa2c182"],["5e07bf7f-3066-4d2a-a1fa-6ee2c32138b9","05a1c5b1-8aaf-4d1e-94bf-2c7f67179601"],["5e07bf7f-3066-4d2a-a1fa-6ee2c32138b9","30372141-bdc2-4ee6-ac37-a3e851c9751d"],["5e07bf7f-3066-4d2a-a1fa-6ee2c32138b9","65e9e8a7-bf37-4596-962d-d781659f9fce"],["8ab4de46-e4f2-498b-8142-e987cab9ca80","30372141-bdc2-4ee6-ac37-a3e851c9751d"],["8ab4de46-e4f2-498b-8142-e987cab9ca80","3b881881-752f-4894-a077-58a2ba7e13ea"],["8ab4de46-e4f2-498b-8142-e987cab9ca80","d40a451f-32bf-4e9e-b673-f4e9073cec57"],["8ab4de46-e4f2-498b-8142-e987cab9ca80","cf8157e8-c6ff-4362-9e6e-98be9ca26561"],["8ab4de46-e4f2-498b-8142-e987cab9ca80","b8ef60eb-e55b-4b0c-9a5c-7f497a469bf9"],["8ab4de46-e4f2-498b-8142-e987cab9ca80","024faf5c-a0bd-4ca4-a44e-37a672a976bd"],["8ab4de46-e4f2-498b-8142-e987cab9ca80","023f7c38-579c-45f7-a012-3003f612387a"],["8ab4de46-e4f2-498b-8142-e987cab9ca80","4898707b-210c-4808-9073-270df6f002db"],["b7f00203-bad7-43c3-9d58-bcf8c6882cc3","41e7072b-7322-41aa-b9cd-57abe6659d62"],["b7f00203-bad7-43c3-9d58-bcf8c6882cc3","9601ea85-b418-4fc1-bcec-e79b49c94f74"],["b7f00203-bad7-43c3-9d58-bcf8c6882cc3","1caea527-f51e-4940-bdc7-8654c1d100b7"],["8951abb4-f5f7-41e1-a97b-882990726c80","b2f6782a-c49f-4d50-8c3f-b05a5e86971d"],["8951abb4-f5f7-41e1-a97b-882990726c80","05a1c5b1-8aaf-4d1e-94bf-2c7f67179601"],["8951abb4-f5f7-41e1-a97b-882990726c80","30372141-bdc2-4ee6-ac37-a3e851c9751d"],["8951abb4-f5f7-41e1-a97b-882990726c80","f75b6f17-a227-4f07-9686-eb10a34b2485"],["8951abb4-f5f7-41e1-a97b-882990726c80","9f12199a-1f33-4d7d-9ecb-10b7db2872fa"],["8951abb4-f5f7-41e1-a97b-882990726c80","b5d7f1d8-521d-4677-afe2-ad2b7388e06d"]],"fields":["post_id","tag_id"],"types":[2950,2950],"type_names":["uuid","uuid"],"started_at":"2020-01-12 12:48:51 +0000","finished_at":"2020-01-12 12:48:51 +0000","checksum":"2e039289d7e868d2c6e8ed05e54a0dca"} \ No newline at end of file diff --git a/public/posts.json b/public/posts.json deleted file mode 100644 index 4553a2e..0000000 --- a/public/posts.json +++ /dev/null @@ -1,203 +0,0 @@ -{ - "title": "extract", - "values": [ - [ - "8951abb4-f5f7-41e1-a97b-882990726c80", - "how-to-redirect-to-https-using-laravel-middleware", - "How To Redirect To HTTPS Using Laravel Middleware", - "Laravel middleware provide a convenient mechanism for filtering HTTP requests entering your application. In this tutorial we are going to check if any HTTP request is entering our application and them force it to use HTTPS.", - "\u003cp\u003eI believe this is not your first time of hearing about HTTP \u0026amp; HTTPS. These two are transfer protocols for the web.\u003c/p\u003e\u003cp\u003eThere are lots of articles out there that explains why HTTPS is highly recommended but I will summarize it this way: \u003cstrong\u003eHTTPS is a secured version of HTTP. \u003c/strong\u003eSo if you care about the security of your web application you need to care about HTTPS.\u003c/p\u003e\u003ch2\u003eLaravel Middleware\u003c/h2\u003e\u003cp\u003eAccording to Laravel documentation, middleware provide a convenient mechanism for filtering HTTP requests entering your application.\u003c/p\u003e\u003cp\u003eSo there are lots of things that you can do with middleware but for this tutorial we are going to check if any HTTP request is entering our application and them force it to use HTTPS.\u003c/p\u003e\u003cp\u003eI am assuming you already have a Laravel app where you want to apply this.\u003cstrong\u003e\u003cbr\u003e\u003c/strong\u003e\u003c/p\u003e\u003cp\u003e\u003cstrong\u003eNote: You need to install SSL certificate (like \u003c/strong\u003e\u003ca href=\"https://letsencrypt.org/\" target=\"_blank\"\u003e\u003cstrong\u003eLetsEncrypt\u003c/strong\u003e\u003c/a\u003e\u003cstrong\u003e) on the server running your app before you continue with this tutorial!\u003c/strong\u003e\u003c/p\u003e\u003ch2\u003eLets Start!\u003c/h2\u003e\u003cp\u003e\u003cstrong\u003eDisclaimer: This is just a work around I use to avoid going through the inconvenience that .htaccess file can bring.\u003c/strong\u003e\u003c/p\u003e\u003cp\u003eCreate your \u003ccode\u003eSecuredHttp\u003c/code\u003e middleware class using this command:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003ephp artisan make:middleware SecuredHttp\n\u003c/pre\u003e\u003cp\u003eAll Laravel middleware can be found on this path: \u003ccode\u003eapp\\Http\\Middleware\u003c/code\u003e\u003c/p\u003e\u003cp\u003eNow lets add our redirection logic inside our middleware . All HTTP requests coming into Laravel middleware are handled inside the \u003ccode\u003ehandle()\u003c/code\u003e method.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-keyword\"\u003epublic\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003ehandle\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e($request,\u0026nbsp;Closure\u0026nbsp;$next)\u003c/span\u003e\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e\u0026nbsp;(!$request-\u0026gt;secure())\u0026nbsp;{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;redirect()-\u0026gt;secure($request-\u0026gt;path());\n\u0026nbsp;\u0026nbsp;}\n\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;$next($request);\n}\n\u003c/pre\u003e\u003cp\u003eOur logic is pretty simple. It checks for unsecured request and redirect it back to the same path that is secured (HTTPS). \u003c/p\u003e\u003cp\u003eNow we are going to register our \u003ccode\u003eSecuredHttp\u003c/code\u003e middleware class as a global middleware. This will allow it to run on every HTTP request coming into our application.\u003c/p\u003e\u003cp\u003eUpdate \u003ccode\u003e$middleware\u003c/code\u003e property of your \u003ccode\u003eapp/Http/Kernel.php\u003c/code\u003e class like this:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003eprotected\u0026nbsp;$middleware\u0026nbsp;=\u0026nbsp;[\n ....\n \\App\\Http\\Middleware\\SecuredHttp::\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e,\u003c/span\u003e\n ....\n];\n\u003c/pre\u003e\u003cp\u003eNow your \u003ccode\u003eSecuredHttp \u003c/code\u003emiddleware is actively waiting for HTTP requests that will near your app :)\u003c/p\u003e\u003ch2\u003eConclusion\u003c/h2\u003e\u003cp\u003eI just showed you one out of a million things you can do with Laravel middleware.\u003cstrong\u003e\u003cbr\u003e\u003c/strong\u003e\u003c/p\u003e\u003cp\u003eJoin my \u003ca href=\"http://stephenjude.tech/newsletter\" target=\"_blank\"\u003eweekly newsletter\u003c/a\u003e and never miss out on news, tutorials, tips and more.\u003c/p\u003e\u003cp\u003eYou can also follow me on twitter \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003e@stephenjudeso\u003c/a\u003e\u003c/p\u003e", - true, - "2019-12-11 19:09:00", - "https://images.unsplash.com/photo-1471958680802-1345a694ba6d?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@foxxmd\"\u003eMatt Duncan\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-12-11 19:10:41", - "2019-12-12 07:17:51", - "{\"meta_description\":\"Laravel middleware provide a convenient mechanism for filtering HTTP requests entering your application. In this tutorial we are going to check if any HTTP request is entering our application and them force it to use HTTPS.\",\"opengraph_title\":\"How To Redirect To HTTPS Using Laravel Middleware\",\"opengraph_description\":\"Laravel middleware provide a convenient mechanism for filtering HTTP requests entering your application. In this tutorial we are going to check if any HTTP request is entering our application and them force it to use HTTPS.\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"How To Redirect To HTTPS Using Laravel Middleware\",\"twitter_description\":\"Laravel middleware provide a convenient mechanism for filtering HTTP requests entering your application. In this tutorial we are going to check if any HTTP request is entering our application and them force it to use HTTPS.\",\"twitter_image\":null}" - ], - [ - "5e07bf7f-3066-4d2a-a1fa-6ee2c32138b9", - "paystacklite-getting-started-with-paystack-fluent-apis-in-your-laravel-application", - "PaystackLite: Getting Started With Paystack Fluent APIs In Your Laravel Application", - "In this article I will be walking you through how you can hit Paystack endpoints using PaystackLite.", - "\u003cp\u003eEarlier this week, I wrote an \u003ca href=\"http://stephenjude.tech/articles/paystacklite-fastest-way-to-setup-paystack-checkout-form-in-your-laravel-application\" target=\"_blank\"\u003earticle \u003c/a\u003eon how to setup Paystack checkout form. Yeah I did but that's not all PaystackLite can offer. \u003c/p\u003e\u003cp\u003eIn this article I will be walking you through how you can hit Paystack endpoints using \u003ca href=\"https://github.com/stephenjude/paystack-lite\" target=\"_blank\"\u003ePaystackLite\u003c/a\u003e. Let's get started.\u003c/p\u003e\u003ch2\u003eInstalling PaystackLite\u003c/h2\u003e\u003cp\u003eInstall the package with composer.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003ecomposer \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e stephenjude/paystack-lite\n\u003c/pre\u003e\u003cp\u003eIf you are using Laravel less than 5.4, add the line below to the\u003cstrong\u003e providers\u003c/strong\u003e array in your \u003cstrong\u003econfig/app.php \u003c/strong\u003efile\u003cstrong\u003e.\u003c/strong\u003e\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003eStephenjude\\PaystackLite\\PaystackLiteServiceProvider::\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e,\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eUpdate your \u003cstrong\u003e.env\u003c/strong\u003e file and add your public key, secret key, customer default email and payment url.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-attr\"\u003ePAYSTACK_PUBLIC_KEY\u003c/span\u003e=xxxxxxxxxxxxx\n\u003cspan class=\"hljs-attr\"\u003ePAYSTACK_SECRET_KEY\u003c/span\u003e=xxxxxxxxxxxxx\n\u003cspan class=\"hljs-attr\"\u003ePAYSTACK_PAYMENT_URL\u003c/span\u003e=https://api.paystack.co\n\u003cspan class=\"hljs-attr\"\u003ePAYSTACK_CUSTOMER_DEFAULT_EMAIL\u003c/span\u003e=general@email.com\n\u003c/pre\u003e\u003ch2\u003ePaystack Fluent APIs\u003c/h2\u003e\u003cp\u003ePaystackLite is wrapped around\u003ca href=\"https://paystack-client.herokuapp.com/#/laravel\" target=\"_blank\"\u003e Xeviant Paystack\u003c/a\u003e package. So you can use all \u003ca href=\"https://paystack-client.herokuapp.com/#/api/supported\" target=\"_blank\"\u003epaystack fluent APIs\u003c/a\u003e provided in the package. There are three different ways to make use of this package.\u003c/p\u003e\u003ch3\u003eInstantiate PaystackLite Class\u003c/h3\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;?php\u003c/span\u003e \n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eStephenjude\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003ePaystackLite\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003ePaystackLite\u003c/span\u003e\n\n$\u003cspan class=\"hljs-title\"\u003epaystack\u003c/span\u003e = \u003cspan class=\"hljs-title\"\u003enew\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003ePaystackLite\u003c/span\u003e;\n\n\u003cspan class=\"hljs-comment\"\u003e// Returns a list of your customers\u003c/span\u003e\n$data = $paystack-\u0026gt;api()-\u0026gt;customers()-\u0026gt;list();\n\u003c/pre\u003e\u003cp\u003eThis is basically accessing the fluent APIs through an instance of PaystackLite class.\u003c/p\u003e\u003ch3\u003ePaystackLite Facade\u003c/h3\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;?php\u003c/span\u003e \n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eStephenjude\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003ePaystackLite\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eFacades\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003ePaystackLite\u003c/span\u003e;\n\n\u003cspan class=\"hljs-comment\"\u003e// Returns a list of your transactions\u003c/span\u003e\n$data = PaystackLite::api()-\u0026gt;transactions()-\u0026gt;list();\n\u003c/pre\u003e\u003cp\u003eThis is Laravel Facades doing the magic for us.\u003c/p\u003e\u003ch3\u003eApp Service Container\u003c/h3\u003e\u003cp\u003eThis is my most preferred method of using Paystack fluent APIs provided in this package. You\u003c/p\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://res.cloudinary.com/hairconnect/image/upload/v1574398908/stephenjude/EJ0Ix32XUAI8R1t.jpg\"\u003e\u003c/div\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003eWith this method you don't need to import or instantiate any class to make use of the PaystackLite class. You only need to call \u003cstrong\u003eapp('paystack')\u003c/strong\u003e helper function followed by fluent methods as show above.\u003c/p\u003e\u003cp\u003eHere is an example on how to get a list of all the plans in your Paystack account.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;?php\u003c/span\u003e\n\n\u003cspan class=\"hljs-comment\"\u003e// returns a list of your paystack plans\u003c/span\u003e\napp(\u003cspan class=\"hljs-string\"\u003e'paystack'\u003c/span\u003e)-\u0026gt;api()-\u0026gt;plans()-\u0026gt;list();\n\u003c/pre\u003e\u003ch2\u003eSupported APIs \u003c/h2\u003e\u003cp\u003eHere is a list of endpoints supported in this package\u003c/p\u003e\u003cul\u003e\u003cli\u003e\u003cstrong\u003etransactions()\u003c/strong\u003e\u003c/li\u003e\u003cli\u003e\u003cstrong\u003ecustomers()\u003c/strong\u003e\u003c/li\u003e\u003cli\u003e\u003cstrong\u003eplans()\u003c/strong\u003e\u003c/li\u003e\u003cli\u003e\u003cstrong\u003esubscriptions()\u003c/strong\u003e\u003c/li\u003e\u003cli\u003e\u003cstrong\u003esubAccounts()\u003c/strong\u003e\u003c/li\u003e\u003cli\u003e\u003cstrong\u003epages()\u003c/strong\u003e\u003c/li\u003e\u003cli\u003e\u003cstrong\u003einvoices()\u003c/strong\u003e\u003c/li\u003e\u003cli\u003e\u003cstrong\u003etransfers()\u003c/strong\u003e\u003c/li\u003e\u003cli\u003e\u003cstrong\u003etransferRecipients()\u003c/strong\u003e\u003c/li\u003e\u003cli\u003e\u003cstrong\u003esettlements()\u003c/strong\u003e\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eAll supported endpoints are covered \u003ca href=\"https://paystack-client.herokuapp.com/#/api/supported\" target=\"_blank\"\u003ehere\u003c/a\u003e in details.\u003c/p\u003e\u003ch2\u003eConclusion\u003c/h2\u003e\u003cp\u003eI believe you now have an understanding of how PaystackLite works. You can go through the \u003ca href=\"https://github.com/stephenjude/paystack-lite/blob/master/README.md\" target=\"_blank\"\u003edocumentation \u003c/a\u003efor more details and don't forget to star \u003ca href=\"https://github.com/stephenjude/paystack-lite\" target=\"_blank\"\u003ePaystackLite \u003c/a\u003eon \u003ca href=\"https://github.com/stephenjude/paystack-lite\" target=\"_blank\"\u003eGithub\u003c/a\u003e. If you have any question drop it in the comment section below.\u003c/p\u003e\u003cp\u003eJoin my \u003ca href=\"http://stephenjude.tech/editor/posts/bit.ly/sj-tech-newsletter\" target=\"_blank\"\u003eweekly newsletter\u003c/a\u003e and never miss out on new tutorials, tips, and more.\u003c/p\u003e\u003cp\u003eYou can also follow me on twitter \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003e@stephenjudeso\u003c/a\u003e\u003c/p\u003e", - true, - "2019-11-25 11:00:00", - "https://images.unsplash.com/photo-1559526324-4b87b5e36e44?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@austindistel\"\u003eAustin Distel\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-11-22 04:09:29", - "2019-11-27 08:37:17", - "{\"meta_description\":\"In this article I will be walking you through how you can hit Paystack endpoints using PaystackLite.\",\"opengraph_title\":\"PaystackLite: Getting Started With Paystack Fluent APIs In Your Laravel Application\",\"opengraph_description\":\"In this article I will be walking you through how you can hit Paystack endpoints using PaystackLite.\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"PaystackLite: Getting Started With Paystack Fluent APIs In Your Laravel Application\",\"twitter_description\":\"In this article I will be walking you through how you can hit Paystack endpoints using PaystackLite.\",\"twitter_image\":null}" - ], - [ - "be6a404b-2974-49a2-83a0-792442ca5f11", - "building-my-personal-blog", - "How I Built My Personal Blog Using Lite Blog - A Laravel Blog Generator", - "I don't like the idea of duplicating codes so I decided to make my blog a reusable Laravel project so that anybody can use it.", - "\u003cp\u003eI am thrilled to write my first post here and I will start by going through the development process of building this blog and how it became a Laravel\u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003e\u0026nbsp;project\u003c/a\u003e.\u003c/p\u003e\u003ch2\u003eBuilding on Jigsaw\u003c/h2\u003e\u003cp\u003eI started building the first version of this blog with \u003ca href=\"https://jigsaw.tighten.co/\" target=\"_blank\"\u003eJigsaw\u003c/a\u003e. Jigsaw is a static site generator for Laravel developers. I used the Jigsaw blog template which helped me to get started. \u003c/p\u003e\u003cp\u003eBuilding my site on Jigsaw means that I will need an API that returns all my post. I like the idea of static sites because of their fast load time and ease of deployment especially on netlify. But I don't like the idea of my blog using APIs coupled with Jigsaw NPM errors that have been slowing down my progress. I decided to go monolithic which means that everything (frontend \u0026amp; backend) was going to be a single project. \u003c/p\u003e\u003ch2\u003eBuilding on Laravel\u003c/h2\u003e\u003cp\u003eI have been a Laravel developer for a while, so I choose to build on Laravel. To migrate to Laravel, I created a \u003ca href=\"https://laravel.com/docs/6.x/\" target=\"_blank\"\u003eLaravel 6\u003c/a\u003e project and copied all the frontend assets I have been using on Jigsaw to Laravel. Jigsaw made use of php, Laravel blades and Laravel mix. It was pretty easy since Jigsaw was built for Laravel developers. \u003c/p\u003e\u003ch3\u003eVuejs, Tailwindcss, Highlightjs \u0026amp; Fusejs.\u003c/h3\u003e\u003cp\u003eUsing NPM, I installed \u003ca href=\"https://tailwindcss.com/\" target=\"_blank\"\u003etailwindcss\u003c/a\u003e, \u003ca href=\"https://highlightjs.org/\" target=\"_blank\"\u003ehighlightjs \u003c/a\u003e\u0026amp; \u003ca href=\"https://fusejs.io/\" target=\"_blank\"\u003efusejs\u003c/a\u003e which are all part of Jigsaw blog template.\u003ca href=\"https://fusejs.io/\" target=\"_blank\"\u003e \u003c/a\u003eLaravel ships with \u003ca href=\"https://vuejs.org/\" target=\"_blank\"\u003evuejs\u003c/a\u003e so there is no need to install that again. Finally I have to recompile (\u003ccode\u003enpm run dev\u003c/code\u003e) the assets again and everything was working fine.\u003c/p\u003e\u003ch3\u003eWink - A Laravel-Based Publishing Platform\u003c/h3\u003e\u003cp\u003eI used \u003ca href=\"wink.themsaid.com\" target=\"_blank\"\u003ewink\u003c/a\u003e as my post editor. Wink is just like \u003ca href=\"https://medium.com/\" target=\"_blank\"\u003eMedium\u003c/a\u003e post editor. If you have been writing on Medium you already know what I mean. So I just plugged in the wink Laravel package to my Laravel application and boom I have a publishing platform where I can draft and publish posts. Awesome!\u003c/p\u003e\u003ch2\u003eLite Blog - A Laravel Blog Generator\u003c/h2\u003e\u003cp\u003eWhen I started building my blog, my boss was the first person to place an order for the same thing I was building. So when I was through with mine, I knew that I will have to duplicate everything on the project. \u003c/p\u003e\u003cp\u003eI don't like the idea of duplicating codes so I decided to make my blog a reusable Laravel project so that anybody can use it. The project is \u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003eLite Blog\u003c/a\u003e - a Laravel full (frontend \u0026amp; backend) blog generator. \u003c/p\u003e\u003cp\u003eAfter the pre-release version (0.4) of \u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003eLite Blog\u003c/a\u003e, I decided to delete my blog and rebuild it with \u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003eLite Blog\u003c/a\u003e. I can say that it was a seamless experience. If you are a Laravel developer, Lite Blog is worth giving a try. \u003c/p\u003e\u003cp\u003eYou can also contribute to the project on \u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003egithub\u003c/a\u003e, one pull request at a time :)\u003c/p\u003e\u003cp\u003eLet's continue the discussion on \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003etwitter\u003c/a\u003e.\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e", - true, - "2019-10-12 06:25:00", - "https://images.unsplash.com/photo-1517694712202-14dd9538aa97?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@clemhlrdt\"\u003eClément H\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-10-05 15:53:25", - "2019-10-12 09:08:46", - "{\"meta_description\":\"I don't like the idea of duplicating codes so I decided to make my blog a reusable Laravel project so that anybody can use it.\",\"opengraph_title\":\"How I Built My Personal Blog Using Lite Blog - A Laravel Blog Generator\",\"opengraph_description\":\"I don't like the idea of duplicating codes so I decided to make my blog a reusable Laravel project so that anybody can use it.\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"How I Built My Personal Blog Using Lite Blog - A Laravel Blog Generator\",\"twitter_description\":\"I don't like the idea of duplicating codes so I decided to make my blog a reusable Laravel project so that anybody can use it.\",\"twitter_image\":null}" - ], - [ - "8de5c7d4-31e2-4d51-a38f-be571307969f", - "lite-blog-a-laravel-blog-generator", - "Getting Started With Laravel Lite Blog", - "Lite Blog is a Laravel blog generator with minimal blog frontend, a publishing platform, SEO, social Links. In this post I will be detailing the interesting features and how to get started.", - "\u003cp\u003eIn my \u003ca href=\"http://stephenjude.tech/articles/building-my-personal-blog\" target=\"_blank\"\u003eprevious post\u003c/a\u003e, I mentioned how I built \u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003eLite Blog\u003c/a\u003e. In this post I will be detailing how to get started and some of the interesting features of \u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003eLite Blog\u003c/a\u003e.\u003c/p\u003e\u003ch2\u003eInstallation\u003c/h2\u003e\u003cp\u003eInstalling Lite Blog is pretty simple. Its just like installing a Laravel application using composer.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003ecomposer \u003cspan class=\"hljs-keyword\"\u003ecreate\u003c/span\u003e-\u003cspan class=\"hljs-keyword\"\u003eproject\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e--prefer-dist stephenjude/lite-blog myblog\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eAfter the installation, create your database and update \u003cstrong\u003e.env \u003c/strong\u003efile with your database credentials. After that run the setup command inside the project directory.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-attr\"\u003ecd\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003emyblog\u003c/span\u003e\n\u003cspan class=\"hljs-attr\"\u003ephp\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003eartisan setup:blog\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eThis will publish the public assets for the publishing platform (\u003ca href=\"https://github.com/writingink/wink\" target=\"_blank\"\u003ewink\u003c/a\u003e) and generate a login credentials for you. \u003c/p\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://res.cloudinary.com/hairconnect/image/upload/v1571303527/stephenjude/wink_installations.png\"\u003e\u003c/div\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003eVisit \u003ccode\u003emyblog.test\u003c/code\u003e on your local machine to see your homepage. \u003c/p\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://ucarecdn.com/a571a7d3-c4d5-400d-8805-c1b6e2e5afc0/homepage.PNG\"\u003e\u003c/div\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003eTo create post visit \u003ccode\u003emyblog.test/editor\u003c/code\u003e and login with the generated credentials.\u003c/p\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://ucarecdn.com/94f0f4d8-4cfd-42df-a5a5-565b43256884/editor.PNG\"\u003e\u003c/div\u003e\u003ch2\u003e\u003cbr\u003e\u003c/h2\u003e\u003ch2\u003eSite Configs\u003c/h2\u003e\u003cp\u003eHere we are going to set the site configuration for our blog. The site configs are inside the \u003ccode\u003econfig/services.php\u003c/code\u003e file. \u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-string\"\u003e'meta'\u003c/span\u003e =\u0026gt; [\n \u003cspan class=\"hljs-string\"\u003e'site_name'\u003c/span\u003e =\u0026gt; \u003cspan class=\"hljs-string\"\u003e'My Perosnal Blog'\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e'mantra'\u003c/span\u003e =\u0026gt; \u003cspan class=\"hljs-string\"\u003e'Web \u0026amp; Mobile Developer'\u003c/span\u003e, \n],\n\u003c/pre\u003e\u003cp\u003eThe \u003ccode\u003esite_name\u003c/code\u003e is the title of the blog while the \u003ccode\u003emantra\u003c/code\u003e is what the site stands for usually under the title of the blog. Update them to fit your taste.\u003c/p\u003e\u003ch3\u003eSocial Profile Links\u003c/h3\u003e\u003cp\u003eInside\u003ccode\u003e config/services.php\u003c/code\u003e add your social media profile links.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'social'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;[\n\u0026nbsp;\u0026nbsp;\u0026nbsp; \u003cspan class=\"hljs-string\"\u003e'linkedin'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'https://www.linkedin.com/in/username/'\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e'email'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'mailto:mail@gmail.com'\u003c/span\u003e,\n \u0026nbsp; \u003cspan class=\"hljs-string\"\u003e'medium'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'https://medium.com/@username'\u003c/span\u003e,\n \u0026nbsp; \u003cspan class=\"hljs-string\"\u003e'github'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'https://github.com/username'\u003c/span\u003e,\n \u0026nbsp; \u003cspan class=\"hljs-string\"\u003e'twitter'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'https://twitter.com/username'\u003c/span\u003e,\n \u0026nbsp; \u003cspan class=\"hljs-string\"\u003e'atom'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'#'\u003c/span\u003e,\n ],\n\u003c/pre\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://ucarecdn.com/2ea5aca3-1664-4c51-8f7f-689a9221011e/footer.PNG\"\u003e\u003c/div\u003e\u003ch3\u003e\u003cbr\u003e\u003c/h3\u003e\u003ch3\u003eUnsplash Integration\u003c/h3\u003e\u003cp\u003eWhen creating post you might like to make use of free professional photos. Wink comes with Unsplash integration out of the box so head over to \u003ca href=\"https://unsplash.com/oauth/applications\" target=\"_blank\"\u003eUnspash, \u003c/a\u003ecreate a new Unsplash app. Grab the 'Access Key' and add it to your \u003ccode\u003e.env\u003c/code\u003e file as \u003ccode\u003eUNSPLASH_ACCESS_KEY\u003c/code\u003e\u003c/p\u003e\u003ch3\u003eCompiling assets (Optional)\u003c/h3\u003e\u003cp\u003eIn case you want to recompile the javascript. You have to install the nodejs packages and then run dev, just like you do in your Laravel application.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-built_in\"\u003enpm\u003c/span\u003e install\n\u003cspan class=\"hljs-built_in\"\u003enpm\u003c/span\u003e run dev\n\u003c/pre\u003e\u003ch2\u003eSEO - Search Engine Optimizations\u003c/h2\u003e\u003cp\u003eThe Laravel publishing platform I used on this project (wink) made a very nice provision for SEO. It was designed that every post you publish has fields where you can add your post's SEO data. I have implemented this on the \u003ccode\u003eresources/views/post.blade.php.\u003c/code\u003e \u003c/p\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://res.cloudinary.com/hairconnect/image/upload/v1571309302/stephenjude/Screenshot_2019-10-17_Edit_Post_Wink_3.png\"\u003e\u003c/div\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003eFor the SEO image, I made use of post featured image. So automatically your featured image will appear as you share the post on twitter, facebook or any other social network sites.\u003c/p\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://res.cloudinary.com/hairconnect/image/upload/v1571309302/stephenjude/Screenshot_2019-10-17_Edit_Post_Wink_5.png\"\u003e\u003c/div\u003e\u003cp\u003eI also used post tags as SEO keywords so adding tags to your post is a plus.\n\u003c/p\u003e\u003ch2\u003eConclusion\u003c/h2\u003e\u003cp\u003e\u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003eLite Blog\u003c/a\u003e is a Laravel application and its highly flexible for modification. You can find the project on \u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003egithub \u003c/a\u003eand its open for contributions. \u003c/p\u003e\u003cp\u003eIf you have any question you can reach out to me on \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003etwitter\u003c/a\u003e.\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e", - true, - "2019-10-18 10:03:00", - "https://images.unsplash.com/photo-1489875347897-49f64b51c1f8?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@casparrubin\"\u003eCaspar Camille Rubin\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-10-10 10:06:29", - "2019-10-19 15:58:43", - "{\"meta_description\":null,\"opengraph_title\":\"Getting Started With Laravel Lite Blog\",\"opengraph_description\":\"Lite Blog is a Laravel blog generator with minimal blog frontend, a publishing platform, SEO, social Links. In this post I will be detailing the interesting features and how to get started.\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"Getting Started With Laravel Lite Blog\",\"twitter_description\":\"Lite Blog is a Laravel blog generator with minimal blog frontend, a publishing platform, SEO, social Links. In this post I will be detailing the interesting features and how to get started.\",\"twitter_image\":null}" - ], - [ - "90f5963c-634c-495d-a5c1-4b776a1603c0", - "a-recap-of-2019-code19", - "A Recap Of 2019 (CODE19)", - "I started the year with a list of things to focus on and I tagged it CODE19. C - Contents | O - Open Source | D - Devops | E - Engineering", - "\u003cp\u003eThis is my first time of writing a blog post on what I achieved for the year so let me go straight to the point.\u003c/p\u003e\u003cp\u003eI started the year with a list of things to focus on and I tagged it \u003cstrong\u003eCODE19. \u003c/strong\u003e\u003c/p\u003e\u003cp\u003e\u003cstrong\u003eC -\u003c/strong\u003e Contents |\u003cstrong\u003e O - \u003c/strong\u003eOpen Source | \u003cstrong\u003eD - \u003c/strong\u003eDevops |\u003cstrong\u003e E - \u003c/strong\u003eEngineering | \u003cstrong\u003e19\u003c/strong\u003e - 2019\u003c/p\u003e\u003ch2\u003eContent\u003c/h2\u003e\u003cp\u003eThis year I was able to publish more content than the previous year. I finished building \u003ca href=\"http://stephenjude.tech\" target=\"_blank\"\u003emy blog\u003c/a\u003e and published my \u003ca href=\"http://stephenjude.tech/articles/building-my-personal-blog\" target=\"_blank\"\u003efirst post \u003c/a\u003eon the 12th of October. I was able to publish \u003ca href=\"http://stephenjude.tech/articles\" target=\"_blank\"\u003e10 blog\u003c/a\u003e posts within 3 months (this inclusive) and the blog has attracted over \u003cstrong\u003e3.6k\u003c/strong\u003e readers with \u003cstrong\u003e5.7k \u003c/strong\u003epage views within this 3 months.\u003c/p\u003e\u003cp\u003eAfter I launched my blog I started sending out \u003ca href=\"http://stephenjude.tech/newsletter\" target=\"_blank\"\u003eweekly \u003c/a\u003enewsletter focused on \u003ca href=\"php.net\" target=\"_blank\"\u003ePHP\u003c/a\u003e \u0026amp; \u003ca href=\"https://laravel.com/\" target=\"_blank\"\u003eLaravel framework\u003c/a\u003e. I have sent out \u003ca href=\"https://us20.campaign-archive.com/home/?u=4e4ddd30dfc7de0c8a4bf6592\u0026amp;id=d3fe3975e4\" target=\"_blank\"\u003e#11 newsletters\u003c/a\u003e so far and my email list has grown to 40 subscribers. \u003c/p\u003e\u003ch2\u003eOpen Source\u003c/h2\u003e\u003cp\u003eI got involved with the open source community with one goal in mind - to give back to the community. \u003c/p\u003e\u003cp\u003eI participated in this year's \u003ca href=\"https://hacktoberfest.digitalocean.com/\" target=\"_blank\"\u003eHacktoberfest\u003c/a\u003e with 7 pull requests. I made a total of 18 pull requests to 8 repositories(some are private) this year. \u003c/p\u003e\u003cp\u003eI also published 3 Laravel \u003ca href=\"https://packagist.org/users/stephenjude/packages/\" target=\"_blank\"\u003epackages\u003c/a\u003e.\u003c/p\u003e\u003cul\u003e\u003cli\u003e\u003ca href=\"https://github.com/stephenjude/lite-blog\" target=\"_blank\"\u003eLite Blog\u003c/a\u003e - a minimal full (frontend \u0026amp; backend) blog generator.\u003c/li\u003e\u003cli\u003e\u003ca href=\"https://github.com/stephenjude/paystack-lite\" target=\"_blank\"\u003ePaystack Lite\u003c/a\u003e - Fastest Way To Setup Paystack Checkout Form In Your Laravel Application\u003c/li\u003e\u003cli\u003e\u003ca href=\"https://github.com/stephenjude/tertiary-institutes\" target=\"_blank\"\u003eTertiary Institutes\u003c/a\u003e - A database schema, models and controllers for list of Nigerian tertiary institutions.\u003c/li\u003e\u003c/ul\u003e\u003ch2\u003eDevops\u003c/h2\u003e\u003cp\u003eI don't really know much about devops but I got my hands on lots of servers this year. \u003c/p\u003e\u003cp\u003eI did lots of setups for repository pipelines and setup auto deploys. I also wrote an article about \u003ca href=\"http://stephenjude.tech/articles/zero-down-time-deployment-with-laravel-envoy-and-bitbucket\" target=\"_blank\"\u003e\"Zero Downtime Deployment With Bitbucket\"\u003c/a\u003e. \u003c/p\u003e\u003cp\u003eI got my hands on docker in one of our secret project in my workplace. Here is a sample \u003ca href=\"https://github.com/stephenjude/dockerized-laravel-app\" target=\"_blank\"\u003edockerized Laravel app\u003c/a\u003e I pushed to Github. You can fork it and follow the documentation on the \u003ca href=\"https://github.com/stephenjude/dockerized-laravel-app/blob/master/readme.md\" target=\"_blank\"\u003ereadme\u0026nbsp;\u003c/a\u003efile.\u003c/p\u003e\u003ch2\u003eEngineering\u003c/h2\u003e\u003cp\u003eI started this year with a goal not to write just code but a maintainable codebase. I read a lot of articles on software engineering and a few books with regards to PHP and Laravel.\u003c/p\u003e\u003cp\u003eTwo areas that have really improved in my coding life includes: \u003cstrong\u003enaming things\u003c/strong\u003e and \u003cstrong\u003ewriting tests\u003c/strong\u003e.\u003c/p\u003e\u003cp\u003eI also published a blog post on testing - \u003ca href=\"stephenjude.tech/articles/mocking-and-testing-php-traits-in-a-laravel-application\" target=\"_blank\"\u003eMocking And Testing PHP Traits In A Laravel Application\u003c/a\u003e\u003c/p\u003e\u003cp\u003eA few things I learnt this year I implemented them at \u003ca href=\"https://qwickpage.com/\" target=\"_blank\"\u003eQwickapge\u003c/a\u003e where I worked as the CTO for 1 year. Currently I am working onsite at Deacons Digital Solutions and also as a freelancer.\u003c/p\u003e\u003ch2\u003eMeetups, Conferences \u0026amp; Talks\u003c/h2\u003e\u003cp\u003eThis year I attended 8 developers events, spoke at 3 and was a core organizer of one of them (LaravelPHP Onitsha).\u003c/p\u003e\u003ch3\u003eHighlights\u003c/h3\u003e\u003cul\u003e\u003cli\u003e\u003ca href=\"https://www.meetup.com/GDG-Onitsha/events/259499384/\" target=\"_blank\"\u003eGoogle Cloud Study Jam\u003c/a\u003e - Attendee\u003c/li\u003e\u003cli\u003e\u003ca href=\"https://www.meetup.com/GDG-Onitsha/events/260876134/\" target=\"_blank\"\u003eGoogle I/O Extended 2019 \u003c/a\u003e- Attendee\u003c/li\u003e\u003cli\u003e\u003ca href=\"https://www.meetup.com/GDG-Onitsha/events/262383338/\" target=\"_blank\"\u003eFlutter Study Jam 2019 \u003c/a\u003e- \u003ca href=\"https://speakerdeck.com/stephenjude/what-is-flutter\" target=\"_blank\"\u003eSpeaker\u003c/a\u003e\u003c/li\u003e\u003cli\u003eFacebook Developers Circle Onitsha - Attendee\u003c/li\u003e\u003cli\u003e\u003ca href=\"https://www.meetup.com/GDG-Warri/events/263205974/\" target=\"_blank\"\u003eDevfest Warri 2019\u003c/a\u003e - Attendee\u003c/li\u003e\u003cli\u003e\u003ca href=\"https://www.meetup.com/GDG-Onitsha/events/265004092/\" target=\"_blank\"\u003eDevfest Onitsha 2019 \u003c/a\u003e- Speaker\u003c/li\u003e\u003cli\u003e\u003ca href=\"https://www.eventbrite.com/o/laravelnigeria-28165833301\" target=\"_blank\"\u003eLaravel Meetup Onitsha\u003c/a\u003e - Organizer \u0026amp; \u003ca href=\"https://speakerdeck.com/stephenjude/laravel-the-introduction\" target=\"_blank\"\u003eSpeaker\u003c/a\u003e\u003c/li\u003e\u003cli\u003e\u003ca href=\"https://www.meetup.com/GDG-Onitsha/events/266710333/\" target=\"_blank\"\u003eWomen Tech Makers Onitsha Meet \u0026amp; Greet\u003c/a\u003e - Attendee\u003c/li\u003e\u003c/ul\u003e\u003cp\u003eI have seen the importance of being part of a community and that's why I decided to be part of every community activities around me. By God's grace I will be more involved in it come 2020. \u003c/p\u003e\u003ch2\u003eSide Projects\u003c/h2\u003e\u003cp\u003eI started this year without having any project in mind but as time went on I got some inspiration turned them into side projects. \u003c/p\u003e\u003cp\u003eTwo side projects I worked were \u003ca href=\"http://stephenjude.tech/\" target=\"_blank\"\u003emy blog\u003c/a\u003e and \u003ca href=\"https://litehost.com.ng/\" target=\"_blank\"\u003eLitehost. \u003c/a\u003eYou already know about my blog so let me talk about \u003cstrong\u003eLitehost\u003c/strong\u003e. \u003c/p\u003e\u003ch3\u003eLitehost\u003c/h3\u003e\u003cp\u003e\u003ca href=\"https://litehost.com.ng/about-us.php\" target=\"_blank\"\u003eLitehost \u003c/a\u003eis basically a reseller platform that provides web hosting services to individuals, small businesses and organizations. We offer Linux shared hosting, WordPress hosting, domain name registration and transfer. \u003c/p\u003e\u003cp\u003eMy vision for Litehost is to make it easier for developers to deploy their Laravel application on shared host. Currently we have not achieved that but we have already made a lot of progress. \u003c/p\u003e\u003cp\u003eI will like to announce that Litehost will be ready to start accepting customers on the 24th of December 2019.\u003c/p\u003e\u003ch2\u003eConclusion\u003c/h2\u003e\u003cp\u003eSo that's all that happened this year. I am still putting down my plans for next year(2020) which will focus on building Litehost into a profitable company, publishing more contents on this blog, growing my local community and contributing to open source. \u003c/p\u003e\u003cp\u003eI know this is going to be hard because of my \u003cstrong\u003e8 to 5 job\u003c/strong\u003e and \u003cstrong\u003emy academic activities\u003c/strong\u003e as a student but I am ready to face 2019 by the grace of God.\u003c/p\u003e\u003cp\u003eDon't forget to join my \u003ca href=\"http://stephenjude.tech/newsletter\" target=\"_blank\"\u003eweekly newsletter\u003c/a\u003e and also follow me on \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003etwitter\u003c/a\u003e.\u003c/p\u003e", - true, - "2019-12-22 20:01:00", - "https://images.unsplash.com/photo-1553877522-43269d4ea984?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@charlesdeluvio\"\u003eCharles\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-12-20 13:02:24", - "2019-12-23 17:53:45", - "{\"meta_description\":\"I started the year with a list of things to focus on and I tagged it CODE19. C - Contents | O - Open Source | D - Devops | E - Engineering\",\"opengraph_title\":\"A Recap Of 2019 (CODE19)\",\"opengraph_description\":\"I started the year with a list of things to focus on and I tagged it CODE19. C - Contents | O - Open Source | D - Devops | E - Engineering\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"A Recap Of 2019 (CODE19)\",\"twitter_description\":\"I started the year with a list of things to focus on and I tagged it CODE19. C - Contents | O - Open Source | D - Devops | E - Engineering\",\"twitter_image\":null}" - ], - [ - "c447fd84-8b91-465d-afe4-79b9ad2a3c78", - "paystacklite-fastest-way-to-setup-paystack-checkout-form-in-your-laravel-application", - "PaystackLite: Fastest Way To Setup Paystack Checkout Form In Your Laravel Application", - "PaystackLite makes use of blade directives to abstract away all Javascript configurations for setting up Paystack checkout forms. This is the easiest way to integrate Paystack checkout form in Laravel applications.", - "\u003ch2\u003ePaystack\u003c/h2\u003e\u003cp\u003e\u003ca href=\"https://paystack.com/\" target=\"_blank\"\u003ePaystack \u003c/a\u003eis the modern online and offline payment for Africa. One thing that excites me about Paystack is that you don't need to be a registered company to make use of their payment gateway. Anybody can use it to start accepting payments.\u003c/p\u003e\u003ch2\u003ePaystackLite\u003c/h2\u003e\u003cp\u003eSetting up Paystack checkout form is pretty simple and easy but copying \u0026amp; pasting code over and over again in different client's and company's projects is quite irritating. So I decided to bundle those code into a \u003ca href=\"https://laravel.com/\" target=\"_blank\"\u003eLaravel \u003c/a\u003epackage. That's how \u003ca href=\"https://github.com/stephenjude/paystack-lite\" target=\"_blank\"\u003ePaystackLite\u003c/a\u003e came about.\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://github.com/stephenjude/paystack-lite\" target=\"_blank\"\u003ePaystackLite\u003c/a\u003e make use of blade directives to abstract away all Javascript configurations for setting up Paystack checkout forms. This is the easiest way to integrate Paystack checkout form in Laravel applications.\u003c/p\u003e\u003cp\u003eLets get our hand dirty with few lines of code. I will assume you already have your Laravel application \"up and running\".\u003c/p\u003e\u003ch2\u003eInstalling PaystackLite\u003c/h2\u003e\u003cp\u003eInstall the package with composer.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003ecomposer \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e stephenjude/paystack-lite\n\u003c/pre\u003e\u003cp\u003eIf you are using Laravel less than 5.4, add the line below to the\u003cstrong\u003e providers\u003c/strong\u003e array in your \u003cstrong\u003econfig/app.php \u003c/strong\u003efile\u003cstrong\u003e.\u003c/strong\u003e\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003eStephenjude\\PaystackLite\\PaystackLiteServiceProvider::\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e,\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eUpdate your .env file and add your public key, secret key, customer default email and payment url.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-attr\"\u003ePAYSTACK_PUBLIC_KEY\u003c/span\u003e=xxxxxxxxxxxxx\n\u003cspan class=\"hljs-attr\"\u003ePAYSTACK_SECRET_KEY\u003c/span\u003e=xxxxxxxxxxxxx\n\u003cspan class=\"hljs-attr\"\u003ePAYSTACK_PAYMENT_URL\u003c/span\u003e=https://api.paystack.co\n\u003cspan class=\"hljs-attr\"\u003ePAYSTACK_CUSTOMER_DEFAULT_EMAIL\u003c/span\u003e=general@email.com\n\u003c/pre\u003e\u003ch2\u003eSetting up Paystack Checkout Form\u003c/h2\u003e\u003cp\u003ePaystackLite makes use of \u003cstrong\u003e@paystack\u003c/strong\u003e blade directive. The \u003cstrong\u003e@paystack\u003c/strong\u003e blade directive creates a JavaScript helper method \u003cstrong\u003epayWithPaystack\u003c/strong\u003e which takes five parameters.\u003c/p\u003e\u003col\u003e\u003cli\u003eThe amount to be paid.\u003c/li\u003e\u003cli\u003eThe customer's email.\u003c/li\u003e\u003cli\u003eMeta data.\u003c/li\u003e\u003cli\u003eCallback function when payment is complete.\u003c/li\u003e\u003cli\u003eCallback function when checkout form is closed.\u003c/li\u003e\u003c/ol\u003e\u003cp\u003eSo whenever we want to display Paystack payment form we just call the \u003cstrong\u003epayWithPaystack \u003c/strong\u003emethod.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003escript\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.getElementById(\u003cspan class=\"hljs-string\"\u003e'paymentBtn'\u003c/span\u003e).onclick\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;()\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;payWithPaystack(amount,\u0026nbsp;email,\u0026nbsp;meta,\u0026nbsp;onPaymentCompleted,\u0026nbsp;onPaymentCancelled);\n}\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003escript\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eSo our blade file will look like this:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;!DOCTYPE\u0026nbsp;html\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ehtml\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003elang\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"en\"\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ehead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003emeta\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003echarset\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"UTF-8\"\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003emeta\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003ename\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"viewport\"\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003econtent\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"width=device-width,\u0026nbsp;initial-scale=1.0\"\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003emeta\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003ehttp-equiv\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"X-UA-Compatible\"\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003econtent\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"ie=edge\"\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003eDocument\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ehead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebody\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003eid\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"paymentBtn\"\u003c/span\u003e\u0026gt;\u003c/span\u003eMake\u0026nbsp;Payment\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e\u0026lt;!--\u0026nbsp;Include\u0026nbsp;paystack\u0026nbsp;blade\u0026nbsp;directive\u0026nbsp;--\u0026gt;\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;@paystack\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003escript\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.getElementById(\u003cspan class=\"hljs-string\"\u003e'paymentBtn'\u003c/span\u003e).onclick\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;()\u0026nbsp;\u003c/span\u003e{\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003evar\u003c/span\u003e\u0026nbsp;amount\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-number\"\u003e1000\u003c/span\u003e;\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003evar\u003c/span\u003e\u0026nbsp;email\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'customer@email.com'\u003c/span\u003e;\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003evar\u003c/span\u003e\u0026nbsp;meta\u0026nbsp;=\u0026nbsp;{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003ecustom_fields\u003c/span\u003e:\u0026nbsp;[\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003edisplay_name\u003c/span\u003e:\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e\"Name\"\u003c/span\u003e,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003evariable_name\u003c/span\u003e:\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e\"name\"\u003c/span\u003e,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-attr\"\u003evalue\u003c/span\u003e:\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e\"My\u0026nbsp;Customer\"\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;]\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;};\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e//display\u0026nbsp;checkout\u0026nbsp;form\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;payWithPaystack(amount,\u0026nbsp;email,\u0026nbsp;meta,\u0026nbsp;onPaymentCompleted,\u0026nbsp;onPaymentCancelled);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;};\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e//\u0026nbsp;Callback\u0026nbsp;when\u0026nbsp;payment\u0026nbsp;is\u0026nbsp;complete.\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eonPaymentCompleted\u003c/span\u003e(\u003cspan class=\"hljs-params\"\u003eresponse\u003c/span\u003e)\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;alert(\u003cspan class=\"hljs-string\"\u003e'payment\u0026nbsp;completed!'\u003c/span\u003e);\n \u003cspan class=\"hljs-comment\"\u003e// do what you like here with the response data returned\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp; }\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e//\u0026nbsp;Callback\u0026nbsp;when\u0026nbsp;checkout\u0026nbsp;form\u0026nbsp;is\u0026nbsp;closed.\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eonPaymentCancelled\u003c/span\u003e()\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;alert(\u003cspan class=\"hljs-string\"\u003e'payment\u0026nbsp;cancelled!'\u003c/span\u003e);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003escript\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebody\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\n\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ehtml\u003c/span\u003e\u0026gt;\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eYeah that's it. Now we have Paystack checkout form displayed whenever the \u003cstrong\u003eMake Payment\u003c/strong\u003e button is clicked. You can find the source code for this tutorial on \u003ca href=\"https://github.com/stephenjude/paystack-lite-demo\" target=\"_blank\"\u003eGithub\u003c/a\u003e.\u003c/p\u003e\u003ch2\u003eConclusion\u003c/h2\u003e\u003cp\u003e\u003ca href=\"https://github.com/stephenjude/paystack-lite\" target=\"_blank\"\u003ePaystackLite \u003c/a\u003eisn't just only about payment checkout form, it's also a Paystack API wrapper for Paystack endpoints. Check out the \u003ca href=\"https://github.com/stephenjude/paystack-lite/blob/master/README.md\" target=\"_blank\"\u003edocumentation \u003c/a\u003efor more details. Don't forget to star \u003ca href=\"https://github.com/stephenjude/paystack-lite\" target=\"_blank\"\u003ePaystackLite \u003c/a\u003eon \u003ca href=\"https://github.com/stephenjude/paystack-lite\" target=\"_blank\"\u003eGithub\u003c/a\u003e.\u003c/p\u003e\u003cp\u003eJoin my \u003ca href=\"http://stephenjude.tech/editor/posts/bit.ly/sj-tech-newsletter\" target=\"_blank\"\u003eweekly newsletter\u003c/a\u003e and never miss out on new, tutorials, tips, and more.\u003c/p\u003e\u003cp\u003eYou can also follow me on twitter \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003e@stephenjudeso\u003c/a\u003e\u003c/p\u003e", - true, - "2019-11-20 13:57:00", - "https://images.unsplash.com/photo-1563013544-824ae1b704d3?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@rupixen\"\u003erupixen.com\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-11-20 14:02:05", - "2019-11-20 22:29:46", - "{\"meta_description\":\"PaystackLite makes use of blade directives to abstract away all Javascript configurations for setting up Paystack checkout forms. This is the easiest way to integrate Paystack checkout form in Laravel applications.\",\"opengraph_title\":\"PaystackLite: Fastest Way To Setup Paystack Checkout Form In Your Laravel Application\",\"opengraph_description\":\"PaystackLite makes use of blade directives to abstract away all Javascript configurations for setting up Paystack checkout forms. This is the easiest way to integrate Paystack checkout form in Laravel applications.\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"PaystackLite: Fastest Way To Setup Paystack Checkout Form In Your Laravel Application\",\"twitter_description\":\"PaystackLite makes use of blade directives to abstract away all Javascript configurations for setting up Paystack checkout forms. This is the easiest way to integrate Paystack checkout form in Laravel applications.\",\"twitter_image\":null}" - ], - [ - "8ab4de46-e4f2-498b-8142-e987cab9ca80", - "upgrading-to-php-74", - "Upgrading To PHP 7.4 (Laragon)", - "PHP 7.4 is now available with lots of exciting new features. Here is how to migrate to PHP 7.4 on your local development server (Laragon)", - "\u003cp\u003eIts no longer news that \u003ca href=\"https://www.php.net/archive/2019.php#2019-11-28-1\" target=\"_blank\"\u003ePHP 7.4\u003c/a\u003e is now available with lots of exciting new features. \u003c/p\u003e\u003cp\u003ePHP 7.4 comes with numerous improvements and new features such as: Typed Properties, Arrow Functions, Null coalescing assignment operator, Unpacking Inside Arrays, Opcache Preloading etc. \u003c/p\u003e\u003cp\u003eYou can walk your self through this new features \u003ca href=\"https://www.php.net/manual/en/migration74.new-features.php\" target=\"_blank\"\u003ehere\u003c/a\u003e. Thanks to PHP development team. Bravo!\u003c/p\u003e\u003ch2\u003eLaragon\u003c/h2\u003e\u003cp\u003e\u003ca href=\"https://laragon.org/docs/\" target=\"_blank\"\u003eLaragon \u003c/a\u003eis a modern, maintained and rich-featured local development environment. Laragon comes pre-installed with many popular applications like Node.js, PHP, Apache, Nginx, Redis, Composer, and MariaDB/MySQL. It's currently available for only Windows OS. You can download it \u003ca href=\"https://laragon.org/download/\" target=\"_blank\"\u003ehere\u003c/a\u003e. \u003c/p\u003e\u003cblockquote\u003ePlease note that Laragon's latest release as at the time I wrote this article haven't shipped with PHP 7.4 and that's the essence of this article. \u003c/blockquote\u003e\u003ch2\u003eUpgrading to PHP 7.4\u003c/h2\u003e\u003cp\u003eFirst lets download PHP 7.4 for \u003ca href=\"https://windows.php.net/download#php-7.4\" target=\"_blank\"\u003eWindows\u003c/a\u003e. Here is a direct link for \u003ca href=\"https://windows.php.net/downloads/releases/php-7.4.0-nts-Win32-vc15-x64.zip\" target=\"_blank\"\u003e64 bits \u003c/a\u003eand \u003ca href=\"https://windows.php.net/downloads/releases/php-7.4.0-Win32-vc15-x86.zip\" target=\"_blank\"\u003e32 bits\u003c/a\u003e.\u003ca href=\"https://windows.php.net/downloads/releases/php-7.4.0-nts-Win32-vc15-x64.zip\" target=\"_blank\"\u003e\u0026nbsp;\u003c/a\u003e Extract the downloaded zip file to Laragon's PHP folder.\u003c/p\u003e\u003cp\u003eNote that Laragon's PHP folder can be found on this path:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-section\"\u003eC:\\laragon\\bin\\php\u003c/span\u003e\n\u003c/pre\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://res.cloudinary.com/hairconnect/image/upload/v1575312598/stephenjude/extract-php7.4.png\"\u003e\u003c/div\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003eNow open Laragon app on your system, click on Menu, navigate to the menu item, then change the PHP version to the latest one you have on your system.\u003c/p\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://res.cloudinary.com/hairconnect/image/upload/v1575312597/stephenjude/switch-to-php7.4.png\"\u003e\u003c/div\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003eNow you have your local development environment running PHP 7.4!\u003c/p\u003e\u003ch2\u003eCheers !\u003c/h2\u003e\u003cp\u003eJoin my \u003ca href=\"http://stephenjude.tech/newsletter\" target=\"_blank\"\u003eweekly newsletter\u003c/a\u003e and never miss out on news, tutorials, tips and more.\u003c/p\u003e\u003cp\u003eYou can also follow me on twitter \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003e@stephenjudeso\u003c/a\u003e\u003c/p\u003e", - true, - "2019-12-02 19:09:00", - "https://images.unsplash.com/photo-1563206767-5b18f218e8de?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@mbaumi\"\u003eMika Baumeister\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-12-02 17:09:54", - "2019-12-02 20:41:10", - "{\"meta_description\":\"PHP 7.4 is now available with lots of exciting new features. Here is how to migrate to PHP 7.4 on your local development server (Laragon)\",\"opengraph_title\":\"Upgrading To PHP 7.4 (Laragon)\",\"opengraph_description\":\"PHP 7.4 is now available with lots of exciting new features. Here is how to migrate to PHP 7.4 on your local development server (Laragon)\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"Upgrading To PHP 7.4 (Laragon)\",\"twitter_description\":\"PHP 7.4 is now available with lots of exciting new features. Here is how to migrate to PHP 7.4 on your local development server (Laragon)\",\"twitter_image\":null}" - ], - [ - "b7f00203-bad7-43c3-9d58-bcf8c6882cc3", - "why-you-might-need-multiple-instances-of-redis-for-your-laravel-application", - "Using Multiple Instances of Redis For Your Laravel Application", - "I worked as a Laravel backend developer at Qwickpage for a year. While at Qwickpage we have two instances of the core application that make use of Redis caching system and the end result was a conflict.", - "\u003cp\u003eI worked as a Laravel backend developer at\u003ca href=\"https://qwickpage.com\" target=\"_blank\"\u003e\u0026nbsp; Qwickpage\u003c/a\u003e for a year. Qwickpage has lots of products that are still in their development stage but its is primarily a social network for entrepreneurs. \u003c/p\u003e\u003cp\u003eWhile at Qwickpage we have two instances of the core application running on the server. One is for development while the other is served live (production). \u003c/p\u003e\u003cp\u003eWe make use of \u003ca href=\"https://redis.io/\" target=\"_blank\"\u003eRedis \u003c/a\u003eas our caching system for the two instances of the app and the end result was a conflict.\u003c/p\u003e\u003cp\u003eThe two applications (dev \u0026amp; live) were using the same instance of Redis on the server, each one keeps overriding the cached data of the other and returning wrong cached data.\u003c/p\u003e\u003ch2\u003eHow Did We Fix This\u003c/h2\u003e\u003cp\u003eWe fixed this by creating another instance of Redis that runs on port 6380. So the live app takes port 6379 while dev app takes 6380; We now have two instances of Redis running on our server.\u003c/p\u003e\u003cp\u003eIn this post, I will show you how you can create another instance of Redis on your Linux server. I will assume your already have Redis installed on your Linux server.\u003c/p\u003e\u003ch2\u003eNow Lets Go!\u003c/h2\u003e\u003cp\u003eTo create another instance of Redis we need to duplicate the existing Redis configuration file:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-attribute\"\u003ecp\u003c/span\u003e /etc/redis/redis_6379.conf /etc/redis/redis_6380.conf\n\u003c/pre\u003e\u003cp\u003eUpdate \u003cstrong\u003e\u003cem\u003eport 6380 \u003c/em\u003e\u003c/strong\u003econfig file (\u003cem\u003eetc/redis/redis_6380.conf\u003c/em\u003e)\u003cstrong\u003e\u003cem\u003e \u003c/em\u003e\u003c/strong\u003elike this:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-attr\"\u003epidfile\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e/var/run/redis_6380.pid\u003c/span\u003e\n\u003cspan class=\"hljs-attr\"\u003eport\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e6380\u003c/span\u003e\n\u003cspan class=\"hljs-attr\"\u003elogfile\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e/var/log/redis/redis_6380.log\u003c/span\u003e\n\u003cspan class=\"hljs-attr\"\u003edir\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e/var/lib/redis/6380\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eCreate a \u003cstrong\u003e\u003cem\u003eport 6380\u003c/em\u003e\u003c/strong\u003e working directory:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003emkdir /\u003cspan class=\"hljs-keyword\"\u003evar\u003c/span\u003e/lib/redis/\u003cspan class=\"hljs-number\"\u003e6380\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eUpdate \u003cstrong\u003e\u003cem\u003eport 6379\u003c/em\u003e\u003c/strong\u003e (\u003cem\u003e/etc/init.d/redis_6379\u003c/em\u003e) service script from this:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-attr\"\u003eEXEC\u003c/span\u003e=/usr/local/bin/redis-server\n\u003cspan class=\"hljs-attr\"\u003eCLIEXEC\u003c/span\u003e=/usr/local/bin/redis-cli\n\u003cspan class=\"hljs-attr\"\u003ePIDFILE\u003c/span\u003e=/var/run/redis_6379.pid\n\u003cspan class=\"hljs-attr\"\u003eCONF\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"/etc/redis/6379.conf\"\u003c/span\u003e\n\u003cspan class=\"hljs-attr\"\u003eREDISPORT\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"6379\"\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eto this:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-attr\"\u003eNAME\u003c/span\u003e=`basename \u003cspan class=\"hljs-variable\"\u003e${0}\u003c/span\u003e`\n\u003cspan class=\"hljs-attr\"\u003eEXEC\u003c/span\u003e=/usr/local/bin/redis-server\n\u003cspan class=\"hljs-attr\"\u003eCLIEXEC\u003c/span\u003e=/usr/local/bin/redis-cli\n\u003cspan class=\"hljs-attr\"\u003ePIDFILE\u003c/span\u003e=/var/run/\u003cspan class=\"hljs-variable\"\u003e${NAME}\u003c/span\u003e.pid\n\u003cspan class=\"hljs-attr\"\u003eCONF\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"/etc/redis/${NAME}.conf\"\u003c/span\u003e\n\u003cspan class=\"hljs-attr\"\u003eREDISPORT\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"${NAME#*_}\"\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eCreate a\u0026nbsp;symlink\u0026nbsp;script for port 6380 instance\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-attribute\"\u003eln\u003c/span\u003e -s /etc/init.d/redis_6379 /etc/init.d/redis_6380\n\u003c/pre\u003e\u003cp\u003eTo start the two Redis server instances run this:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e/etc/init.d/redis_6379 \u003cspan class=\"hljs-keyword\"\u003estart\u003c/span\u003e\n/etc/init.d/redis_6380 \u003cspan class=\"hljs-keyword\"\u003estart\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eYou can now update the dotenv files of your two applications and assign them different Redis port respectively.\u003c/p\u003e\u003ch2\u003eCheers!\u003c/h2\u003e\u003cp\u003eJoin my \u003ca href=\"http://stephenjude.tech/newsletter\" target=\"_blank\"\u003eweekly newsletter\u003c/a\u003e and never miss out on news, tutorials, tips and more.\u003c/p\u003e\u003cp\u003eYou can also follow me on twitter \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003e@stephenjudeso\u003c/a\u003e\u003c/p\u003e", - true, - "2019-12-11 01:54:00", - "https://images.unsplash.com/photo-1510519138101-570d1dca3d66?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@nkachanovskyyy\"\u003eNikita Kachanovsky\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-11-27 08:59:18", - "2019-12-11 08:58:28", - "{\"meta_description\":\"I worked as a Laravel backend developer at Qwickpage for a year. While at Qwickpage we have two instances of the core application that make use of Redis caching system and the end result was a conflict.\",\"opengraph_title\":\"Why You Might Need Multiple Instances of Redis For Your Laravel Application\",\"opengraph_description\":\"I worked as a Laravel backend developer at Qwickpage for a year. While at Qwickpage we have two instances of the core application that make use of Redis caching system and the end result was a conflict.\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"Why You Might Need Multiple Instances of Redis For Your Laravel Application\",\"twitter_description\":\"I worked as a Laravel backend developer at Qwickpage for a year. While at Qwickpage we have two instances of the core application that make use of Redis caching system and the end result was a conflict.\",\"twitter_image\":null}" - ], - [ - "51b43e58-5bf0-4ed1-b9d9-9b68f215abdd", - "zero-down-time-deployment-with-laravel-envoy-and-bitbucket", - "Zero Downtime Deployment With Laravel Envoy and BitBucket", - "Zero downtime deployment is a deployment method where your website or application is never down or in an unstable state during the deployment process.", - "\u003cp\u003eI learned about Zero downtime deployment while working on our server at \u003ca href=\"https://qwickpage.com/\" target=\"_blank\"\u003eQwickpage\u003c/a\u003e. That's where I first implemented zero down time deployment uisng \u003ca href=\"https://laravel.com/docs/6.x/envoy\" target=\"_blank\"\u003eLaravel Envoy\u003c/a\u003e and \u003ca href=\"https://gitlab.com/\" target=\"_blank\"\u003eGitLab\u003c/a\u003e. This week I did another setup, this time with BitBucket. It was quiet less stressful with \u003ca href=\"https://bitbucket.org\" target=\"_blank\"\u003eBitbucket\u003c/a\u003e. \u003c/p\u003e\u003ch2\u003eWhat is Zero downtime deployment\u003c/h2\u003e\u003cp\u003e\u003cstrong\u003eZero downtime deployment\u003c/strong\u003e is a \u003cstrong\u003edeployment\u003c/strong\u003e method where your website or application is never \u003cstrong\u003edown\u003c/strong\u003e or in an unstable state during the \u003cstrong\u003edeployment\u003c/strong\u003e process. To achieve this the web server doesn't start serving the changed code until the entire \u003cstrong\u003edeployment\u003c/strong\u003e process is \u003cstrong\u003ecomplete\u003c/strong\u003e.\u003c/p\u003e\u003cp\u003eNow you get the gist lets get started. \u003c/p\u003e\u003cp\u003eI am assuming you have a Laravel application you want to deploy, a VPS (virtual private server) and also a \u003ca href=\"https://bitbucket.org\" target=\"_blank\"\u003eBitbucket\u003c/a\u003e account.\u003c/p\u003e\u003ch2\u003eServer Setup\u003c/h2\u003e\u003cp\u003eDigital Ocean has a lot of server setup tutorials. So I will assume you have already done your VPS setup.\u003c/p\u003e\u003cp\u003eLogin to your VPS and create a base directory for our project deployment and cd into that directory. \u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003emkdir ~/betaApp \u0026amp;\u0026amp; \u003cspan class=\"hljs-built_in\"\u003ecd\u003c/span\u003e ~/betaApp\n\u003c/pre\u003e\u003cp\u003eFor this setup lets pull Laravel from \u003ca href=\"https://github.com/laravel/laravel\" target=\"_blank\"\u003eGithub \u003c/a\u003eso we can make a copy of the \u003ccode\u003estorage\u003c/code\u003e directory and \u003ccode\u003e.env.example\u003c/code\u003e file. We will make use of them in all our deployments. \u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003egit clone https:\u003cspan class=\"hljs-comment\"\u003e//github.com/laravel/laravel.git initial\u003c/span\u003e\ncp -a ~\u003cspan class=\"hljs-regexp\"\u003e/betaApp/i\u003c/span\u003enitial/storage ~\u003cspan class=\"hljs-regexp\"\u003e/betaApp/\u003c/span\u003estorage\ncp -a ~\u003cspan class=\"hljs-regexp\"\u003e/betaApp/i\u003c/span\u003enitial/.env.example ~\u003cspan class=\"hljs-regexp\"\u003e/betaApp/\u003c/span\u003e.env\n\u003c/pre\u003e\u003cp\u003eYou can now update your \u003ccode\u003e~/betaApp/.env\u003c/code\u003e file with all credentials your app will need to run.\u003c/p\u003e\u003cp\u003eWe are goin to create two more directories inside the \u003ccode\u003e~/betaApp\u003c/code\u003e directory. \u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003emkdir ~\u003cspan class=\"hljs-regexp\"\u003e/betaApp/\u003c/span\u003esources\nmkdir ~\u003cspan class=\"hljs-regexp\"\u003e/betaApp/\u003c/span\u003ecurrent\n\u003c/pre\u003e\u003cp\u003eThe \u003ccode\u003esource \u003c/code\u003edirectory will contain all the releases of our app that has been deployed to the server. The \u003ccode\u003ecurrent \u003c/code\u003edirectory will be a symbolic link (reference) to the last release that was deployed to the server. So make sure you point your server to this directory \u003ccode\u003e~/betaApp/current/public\u003c/code\u003e. \u003c/p\u003e\u003cp\u003eThat all for now, lets go setup our deployment script :)\u003c/p\u003e\u003ch2\u003eLaravel Envoy\u003c/h2\u003e\u003cp\u003e\u003ca href=\"https://github.com/laravel/envoy\" target=\"_blank\"\u003eLaravel Envoy\u003c/a\u003e provides a clean, minimal syntax for defining common tasks you run on your remote servers. Its pretty simple. \u003c/p\u003e\u003cp\u003eCreate a new file (Envoy.blade.php) inside your local project root directory. this file will contain all the task we want to run during deployment. Here is the one we are going to use. \u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e@servers([\u003cspan class=\"hljs-string\"\u003e'production'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'user@server_ip'\u003c/span\u003e])\n\n@setup\n \u003cspan class=\"hljs-comment\"\u003e/* Project repository url */\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp; $repo\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'repository_url'\u003c/span\u003e;\n\n \u003cspan class=\"hljs-comment\"\u003e/* Project base directory as setup on the server*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$appDir\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'~/betaApp'\u003c/span\u003e;\n\n \u003cspan class=\"hljs-comment\"\u003e/* repository branch we want to deploy*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$branch\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'master'\u003c/span\u003e;\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;date_default_timezone_set(\u003cspan class=\"hljs-string\"\u003e'UTC'\u003c/span\u003e);\n\n \u003cspan class=\"hljs-comment\"\u003e/* we will use timestamp as directory name of \n every release */\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$date\u0026nbsp;=\u0026nbsp;date(\u003cspan class=\"hljs-string\"\u003e'YmdHis'\u003c/span\u003e);\u0026nbsp;\n\n \u003cspan class=\"hljs-comment\"\u003e/* directory where our release will be saved */\u003c/span\u003e\n $builds\u0026nbsp;=\u0026nbsp;$appDir\u0026nbsp;.\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'/sources'\u003c/span\u003e;\n\n \u003cspan class=\"hljs-comment\"\u003e/* full path to the release we are deploying */\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$deployment\u0026nbsp;=\u0026nbsp;$builds\u0026nbsp;.\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'/'\u003c/span\u003e\u0026nbsp;.\u0026nbsp;$date;\n\n \u003cspan class=\"hljs-comment\"\u003e/* path to the symlink directory on the server */\u003c/span\u003e\n $serve\u0026nbsp;=\u0026nbsp;$appDir\u0026nbsp;.\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'/current'\u003c/span\u003e;\n\n \u003cspan class=\"hljs-comment\"\u003e/* path to our server .env file */\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$env\u0026nbsp;=\u0026nbsp;$appDir\u0026nbsp;.\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'/.env'\u003c/span\u003e;\n\n \u003cspan class=\"hljs-comment\"\u003e/* path to our storage directory */\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$storage\u0026nbsp;=\u0026nbsp;$appDir\u0026nbsp;.\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'/storage'\u003c/span\u003e;\n@endsetup\n\n@story(\u003cspan class=\"hljs-string\"\u003e'deploy'\u003c/span\u003e)\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eclone\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;install\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;live\n@endstory\n\n@task(\u003cspan class=\"hljs-string\"\u003e'clone'\u003c/span\u003e,\u0026nbsp;[\u003cspan class=\"hljs-string\"\u003e'on'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'production'\u003c/span\u003e])\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;git\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eclone\u003c/span\u003e\u0026nbsp;-b\u0026nbsp;{{\u0026nbsp;$branch\u0026nbsp;}}\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e\"{{\u0026nbsp;$repo\u0026nbsp;}}\"\u003c/span\u003e\u0026nbsp;{{\u0026nbsp;$deployment\u0026nbsp;}}\n@endtask\n\n@task(\u003cspan class=\"hljs-string\"\u003e'install'\u003c/span\u003e,\u0026nbsp;[\u003cspan class=\"hljs-string\"\u003e'on'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'production'\u003c/span\u003e])\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;cd\u0026nbsp;{{\u0026nbsp;$deployment\u0026nbsp;}}\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;rm\u0026nbsp;-rf\u0026nbsp;{{\u0026nbsp;$deployment\u0026nbsp;}}/storage\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;ln\u0026nbsp;-nfs\u0026nbsp;{{\u0026nbsp;$env\u0026nbsp;}}\u0026nbsp;{{\u0026nbsp;$deployment}}/.env\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;ln\u0026nbsp;-nfs\u0026nbsp;{{\u0026nbsp;$storage\u0026nbsp;}}\u0026nbsp;{{\u0026nbsp;$deployment\u0026nbsp;}}/storage\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;composer\u0026nbsp;install\u0026nbsp;--prefer-dist\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;php\u0026nbsp;artisan\u0026nbsp;migrate\n@endtask\n\n@task(\u003cspan class=\"hljs-string\"\u003e'live'\u003c/span\u003e,\u0026nbsp;[\u003cspan class=\"hljs-string\"\u003e'on'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'production'\u003c/span\u003e])\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;ln\u0026nbsp;-nfs\u0026nbsp;{{\u0026nbsp;$deployment\u0026nbsp;}}\u0026nbsp;{{\u0026nbsp;$serve\u0026nbsp;}}\n@endtask\n\u003c/pre\u003e\u003cp\u003eInside our \u003ccode\u003eEnvoy.blade.php\u003c/code\u003e file we have our \u003cstrong\u003e@server\u003c/strong\u003e section which contains the server we are deploying to. The\u003cstrong\u003e @setup\u003c/strong\u003e section is where we decleared all the variables we are going to be using during deployment. I believe those variable with those comments are self explanatory.\u003c/p\u003e\u003cp\u003eWe have three \u003cstrong\u003e@task\u003c/strong\u003e section which includes the \u003cstrong\u003eclone task\u003c/strong\u003e (clone from our repository), the \u003cstrong\u003einstall task \u003c/strong\u003e(removes the storage directory and the .env file, symlink our default storage directory and .env file, install all the php packages for the app and run migrations) and the \u003cstrong\u003elive task \u003c/strong\u003e(symlink this current release to the current directory).\u003c/p\u003e\u003cp\u003eThe \u003cstrong\u003e@story\u003c/strong\u003e section is where all the \u003cstrong\u003e@task\u003c/strong\u003e are called in the order we want it to run.\u003c/p\u003e\u003ch2\u003eBitBucket Pipeline\u003c/h2\u003e\u003cp\u003eI will assume you already have your app pushed to \u003ca href=\"https://bitbucket.org/\" target=\"_blank\"\u003eBitbucket\u003c/a\u003e. Create \u003ccode\u003ebitbucket-pipelines.yml\u003c/code\u003e file inside your project root folder on your local machine. \u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003eimage:\u0026nbsp;php:7.2-fpm\n\npipelines:\n\u0026nbsp;\u0026nbsp;default:\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;-\u0026nbsp;step:\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;script:\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;-\u0026nbsp;apt-get\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eupdate\u003c/span\u003e\u0026nbsp;\u0026amp;\u0026amp;\u0026nbsp;apt-\u003cspan class=\"hljs-keyword\"\u003eget\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003einstall\u003c/span\u003e\u0026nbsp;-qy\u0026nbsp;git\u0026nbsp;curl\u0026nbsp;libmcrypt-dev\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;-\u0026nbsp;apt-\u003cspan class=\"hljs-keyword\"\u003eget\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eupdate\u003c/span\u003e\u0026nbsp;\u0026amp;\u0026amp;\u0026nbsp;apt-\u003cspan class=\"hljs-keyword\"\u003eget\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003einstall\u003c/span\u003e\u0026nbsp;-y\u0026nbsp;unzip\u0026nbsp;openssh-\u003cspan class=\"hljs-keyword\"\u003eclient\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;-\u0026nbsp;yes\u0026nbsp;|\u0026nbsp;pecl\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003einstall\u003c/span\u003e\u0026nbsp;mcrypt\u003cspan class=\"hljs-number\"\u003e-1.0.1\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;-\u0026nbsp;curl\u0026nbsp;-sS\u0026nbsp;https://getcomposer.org/installer\u0026nbsp;|\u0026nbsp;php\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e--\u0026nbsp;--install-dir=/usr/local/bin\u0026nbsp;--filename=composer\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;-\u0026nbsp;composer\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003einstall\u003c/span\u003e\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;-\u0026nbsp;composer\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eglobal\u003c/span\u003e\u0026nbsp;require\u0026nbsp;laravel/envoy\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;-\u0026nbsp;~/.composer/vendor/\u003cspan class=\"hljs-keyword\"\u003ebin\u003c/span\u003e/envoy\u0026nbsp;run\u0026nbsp;deploy\n\u003c/pre\u003e\u003cp\u003eSo our Bitbucket pipeline will pull php7.2 docker image, install all necessary php extenstion, install composer, install Laravel Envoy and then execute our envoy script.\u003c/p\u003e\u003ch2\u003eDeployment Keys\u003c/h2\u003e\u003cp\u003eGitBucket is going to help us generate a public key for our deployment. Goto the settings of your project repository on BitBucket. Under Pipeline click \u003cem\u003esettings \u003c/em\u003eand enable pipeline for your project. You will be asked to configure your Pipeline but you don't have to, we have already done that. \u003c/p\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://res.cloudinary.com/hairconnect/image/upload/v1573168216/stephenjude/Screenshot_2019-11-08_StephenJude_test_Admin_Bitbucket_1.png\"\u003e\u003c/div\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003eNow lets generate a public key. Go back to the settings of your project repository on BitBucket. Under Pipeline click \u003cem\u003eSSH Keys, \u003c/em\u003ewhen the page is done loading click on generate key.\u003c/p\u003e\u003cdiv class=\"inline_html\" contenteditable=\"false\"\u003e\u003cimg src=\"https://res.cloudinary.com/hairconnect/image/upload/v1573168216/stephenjude/Screenshot_2019-11-08_StephenJude_test_Admin_Bitbucket.png\"\u003e\u003c/div\u003e\u003cp\u003e\u003cbr\u003e\u003c/p\u003e\u003cp\u003eNow copy the public key to your \u003ccode\u003e~/.ssh/authorized_keys\u003c/code\u003e file on your VPS. Go back to page where you generated the SSH key on BitBucket, add your VPS domain name or IP address and click the fetch button. If you added the public key successfully, BitBucket will be able to fetch your host's fingerprint and youe are good to go.\u003c/p\u003e\u003cp\u003eFinally go back to your project on your local machine, commit all these changes and push. Check your BitBucket pipleine to know when the deployment is complete. \u003c/p\u003e\u003ch2\u003eConclusion\u003c/h2\u003e\u003cp\u003eNow your have implemented a Zero downtime deployment you can revert back to any previous release by running this command on your VPS\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003eln\u0026nbsp;-nfs ~\u003cspan class=\"hljs-regexp\"\u003e/betaApp/\u003c/span\u003esources/prev_release_dir ~\u003cspan class=\"hljs-regexp\"\u003e/betaApp/\u003c/span\u003ecurrent\n\u003c/pre\u003e\u003cp\u003eIf you enjoyed my article why not signup for my \u003ca href=\"trim.ng/newsletter\" target=\"_blank\"\u003enewsletter\u003c/a\u003e to receive them directly in your inbox. I also send out hand picked resource links every week. \u003c/p\u003e\u003cp\u003eLets continue the discussion on \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003etwitter\u003c/a\u003e.\u003c/p\u003e", - true, - "2019-11-08 08:04:00", - "https://images.unsplash.com/photo-1506399309177-3b43e99fead2?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@imgix\"\u003eimgix\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-11-06 20:18:32", - "2019-11-10 08:47:43", - "{\"meta_description\":\"Zero downtime deployment is a deployment method where your website or application is never down or in an unstable state during the deployment process.\",\"opengraph_title\":\"Zero Downtime Deployment With Laravel Envoy and BitBucket\",\"opengraph_description\":\"Zero downtime deployment is a deployment method where your website or application is never down or in an unstable state during the deployment process.\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"Zero Downtime Deployment With Laravel Envoy and BitBucket\",\"twitter_description\":\"Zero downtime deployment is a deployment method where your website or application is never down or in an unstable state during the deployment process.\",\"twitter_image\":null}" - ], - [ - "58de5bc4-4a8d-4434-a95b-f93a473329c0", - "mocking-and-testing-php-traits-in-a-laravel-application", - "Mocking And Testing PHP Traits In A Laravel Application", - "Trait is the fastest way to create a reusable code. A Trait is intended to reduce some limitations of single inheritance. This means that you can use multiple traits in a PHP class.", - "\u003cp\u003eTrait is the fastest way to create a reusable code. A Trait is intended to reduce some limitations of single inheritance. This means that you can use multiple traits in a PHP class. \u003c/p\u003e\u003cp\u003eThe difference between a PHP Trait and a PHP class is that you cannot instantiate a Trait on its own.\u003c/p\u003e\u003cp\u003eHere is an example of a PHP trait.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;?php\u003c/span\u003e\n\u003cspan class=\"hljs-comment\"\u003e//\u0026nbsp;file\u0026nbsp;upload\u0026nbsp;trait\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003etrait\u003c/span\u003e\u0026nbsp;UploadFile{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eupload\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e($path)\u003c/span\u003e\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e//\u0026nbsp;performs\u0026nbsp;file\u0026nbsp;upload\u0026nbsp;and\u0026nbsp;return\u0026nbsp;the\u0026nbsp;new\u0026nbsp;file\u0026nbsp;path\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n}\n\n\n\u003cspan class=\"hljs-comment\"\u003e//\u0026nbsp;file\u0026nbsp;upload\u0026nbsp;controller\u003c/span\u003e\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eUploadController\u003c/span\u003e\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eUploadFile\u003c/span\u003e;\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003estore\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e($request)\u003c/span\u003e\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;upload($request-\u0026gt;file);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n}\n\u003c/pre\u003e\u003cp\u003eBecause we can't instantiate a PHP Trait, testing it can be a little challenging. I will be showing you how you can mock a PHP Trait and test it. We are going to build a web app for managing users via API. The focus will be on how we can use and test PHP Traits in this application.\u003c/p\u003e\u003cp\u003eLet's start by creating a new Laravel application.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003ecomposer \u003cspan class=\"hljs-keyword\"\u003ecreate\u003c/span\u003e-\u003cspan class=\"hljs-keyword\"\u003eproject\u003c/span\u003e \u003cspan class=\"hljs-comment\"\u003e--prefer-dist laravel/laravel UserApi\u003c/span\u003e\n\u003c/pre\u003e\u003cp\u003eCreate a database and update database credentials inside your \u003ccode\u003e.env\u003c/code\u003e file.\u003c/p\u003e\u003cp\u003eWe are going to make use of \u003ca href=\"https://github.com/spatie/laravel-fractal\" target=\"_blank\"\u003eSpatie fractal wrapper\u003c/a\u003e to transform our API data, so let's add it to our project.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003ecomposer \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e spatie/laravel-fractal\n\u003c/pre\u003e\u003cp\u003eThis project will only do 3 things: create user, list users and show a single user. We have only three API routes to deal with so let's add it to our \u003ccode\u003eroutes/api.php\u003c/code\u003e file.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003eRoute::group(['prefix'\u0026nbsp;=\u0026gt;\u0026nbsp;'v1'],\u0026nbsp;function\u0026nbsp;()\u0026nbsp;{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-attribute\"\u003eRoute\u003c/span\u003e::\u003cspan class=\"hljs-built_in\"\u003eget\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e'users'\u003c/span\u003e,\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'UserController@index'\u003c/span\u003e);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-attribute\"\u003eRoute\u003c/span\u003e::\u003cspan class=\"hljs-built_in\"\u003eget\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e'users/{id}'\u003c/span\u003e,\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'UserController@show'\u003c/span\u003e);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-attribute\"\u003eRoute\u003c/span\u003e::\u003cspan class=\"hljs-built_in\"\u003epost\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e'users'\u003c/span\u003e,\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'UserController@store'\u003c/span\u003e);\n});\n\u003c/pre\u003e\u003cp\u003eCreate a user transformer. \u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003ephp artisan make:transformer UserTransformer\n\u003c/pre\u003e\u003cp\u003eOur user transformer is going to be pretty simple, just returning user name, email, date of creation and modification.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;?php\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003enamespace\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eTransformers\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eUser\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eLeague\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eFractal\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eTransformerAbstract\u003c/span\u003e;\n\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eUserTransformer\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eTransformerAbstract\u003c/span\u003e\n\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003epublic\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003etransform\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e(User\u0026nbsp;$user)\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;[\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'name'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;$user-\u0026gt;name,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'email'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;$user-\u0026gt;email,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'created_at'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;$user-\u0026gt;created_at-\u0026gt;format(\u003cspan class=\"hljs-string\"\u003e'd-m-Y'\u003c/span\u003e),\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'updated_at'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;$user-\u0026gt;updated_at-\u0026gt;format(\u003cspan class=\"hljs-string\"\u003e'd-m-Y'\u003c/span\u003e),\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;];\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n}\n\n\u003c/pre\u003e\u003cp\u003eNext is to create our user controller.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003ephp artisan make:controller UserController --api\n\u003c/pre\u003e\u003cp\u003eThis command will scaffold the basic Laravel controller methods we will need. Our controller methods are all going to return JSON responses. \u003c/p\u003e\u003cp\u003eWe are going to create a custom response trait inside the \u003ccode\u003eapp\\Traits\u003c/code\u003e directory. This will take care of formatting our response status and data before its returned to the client using our API.\u003c/p\u003e\u003cblockquote\u003e\u003cstrong\u003eNote: \u003c/strong\u003eThe \u003ccode\u003eapp\\Traits\u003c/code\u003e directory does not come with Laravel by default, so you have to create it yourself.\u003c/blockquote\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;?php\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003enamespace\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eTraits\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003etrait\u003c/span\u003e\u0026nbsp;CustomResponse\n{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e/**\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@param\u003c/span\u003e\u0026nbsp;array\u0026nbsp;$data\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@param\u003c/span\u003e\u0026nbsp;string\u0026nbsp;$key\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@param\u003c/span\u003e\u0026nbsp;int\u0026nbsp;$status\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@param\u003c/span\u003e\u0026nbsp;string\u0026nbsp;$message\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@return\u003c/span\u003e\u0026nbsp;\\Illuminate\\Http\\JsonResponse\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003epublic\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003ecustomData\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e(\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;array\u0026nbsp;$data,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$key,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$status\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-number\"\u003e200\u003c/span\u003e,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$message\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e\"success\"\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;)\u003c/span\u003e\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$response\u0026nbsp;=\u0026nbsp;[\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e\"data\"\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;[\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e\"status\"\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;setStatus($status,\u0026nbsp;$message),\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e\"$key\"\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;$data[\u003cspan class=\"hljs-string\"\u003e'data'\u003c/span\u003e],\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;]\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;];\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;response()-\u0026gt;json($response,\u0026nbsp;$status);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e/**\u0026nbsp;\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@param\u003c/span\u003e\u0026nbsp;string\u0026nbsp;$message\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@return\u003c/span\u003e\u0026nbsp;\\Illuminate\\Http\\JsonResponse\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003epublic\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003enotFound\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e($message\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'Resource\u0026nbsp;not\u0026nbsp;found'\u003c/span\u003e)\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$response\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;formatStatusData(\u003cspan class=\"hljs-number\"\u003e404\u003c/span\u003e,\u0026nbsp;$message);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;response()-\u0026gt;json($response,\u0026nbsp;\u003cspan class=\"hljs-number\"\u003e404\u003c/span\u003e);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e/**\u0026nbsp;\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@param\u003c/span\u003e\u0026nbsp;int\u0026nbsp;$status\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@param\u003c/span\u003e\u0026nbsp;string\u0026nbsp;$message\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@return\u003c/span\u003e\u0026nbsp;\\Illuminate\\Http\\JsonResponse\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eprivate\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eformatStatusData\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e($status,\u0026nbsp;$message)\u003c/span\u003e:\u0026nbsp;\u003cspan class=\"hljs-title\"\u003earray\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;[\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'code'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;$status,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'message'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;$message,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;];\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n}\n\u003c/pre\u003e\u003cp\u003eCurrently we have only two public methods, the \u003ccode\u003enotFound\u003c/code\u003e and the \u003ccode\u003ecustomData\u003c/code\u003e method. I believe the methods are self explanatory. They format the data and return a JSON data. \u003c/p\u003e\u003cp\u003eNext we are going to update our \u003ccode\u003eUserController\u003c/code\u003e class to perform the basic CRUD operations that I mentioned earlier.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;?php\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003enamespace\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eHttp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eControllers\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eTraits\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eCustomResponse\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eTransformers\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eUserTransformer\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eUser\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eIlluminate\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eHttp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eRequest\u003c/span\u003e;\n\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eUserController\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eController\u003c/span\u003e\n\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eCustomResponse\u003c/span\u003e;\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e/**\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;Display\u0026nbsp;a\u0026nbsp;listing\u0026nbsp;of\u0026nbsp;the\u0026nbsp;resource.\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@return\u003c/span\u003e\u0026nbsp;\\Illuminate\\Http\\Response\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003epublic\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eindex\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$users\u0026nbsp;=\u0026nbsp;User::all();\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$data\u0026nbsp;=\u0026nbsp;fractal($users,\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e\u0026nbsp;UserTransformer())-\u0026gt;toArray();\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;customData($data,\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'users'\u003c/span\u003e);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e/**\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;Store\u0026nbsp;a\u0026nbsp;newly\u0026nbsp;created\u0026nbsp;resource\u0026nbsp;in\u0026nbsp;storage.\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@return\u003c/span\u003e\u0026nbsp;\\Illuminate\\Http\\Response\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003epublic\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003estore\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e//validate\u0026nbsp;request\u0026nbsp;\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$data\u0026nbsp;=\u0026nbsp;request()-\u0026gt;validate([\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'name'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'required|string'\u003c/span\u003e,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'email'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'required|email'\u003c/span\u003e,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'password'\u003c/span\u003e\u0026nbsp;=\u0026gt;\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'string|min:8'\u003c/span\u003e,\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;]);\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$user\u0026nbsp;=\u0026nbsp;User::create($data);\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$data\u0026nbsp;=\u0026nbsp;fractal($user,\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e\u0026nbsp;UserTransformer())-\u0026gt;toArray();\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;customData($data,\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'user'\u003c/span\u003e);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e/**\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;Display\u0026nbsp;the\u0026nbsp;specified\u0026nbsp;resource.\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@param\u003c/span\u003e\u0026nbsp;\u0026nbsp;int\u0026nbsp;\u0026nbsp;$id\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@return\u003c/span\u003e\u0026nbsp;\\Illuminate\\Http\\Response\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003epublic\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eshow\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e($id)\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e\u0026nbsp;(is_null($user\u0026nbsp;=\u0026nbsp;User::find($id)))\u0026nbsp;{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;notFound(\u003cspan class=\"hljs-string\"\u003e'user\u0026nbsp;not\u0026nbsp;found'\u003c/span\u003e);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$data\u0026nbsp;=\u0026nbsp;fractal($user,\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e\u0026nbsp;UserTransformer())-\u0026gt;toArray();\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;customData($data,\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'user'\u003c/span\u003e);\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n}\n\u003c/pre\u003e\u003cp\u003eSo inside our controller we do basically two things; return \u003ccode\u003enotFound\u003c/code\u003e response whenever we cant find a user or return \u003ccode\u003ecustomData\u003c/code\u003e response if we found the user.\u003cem\u003e \u003c/em\u003e\u003c/p\u003e\u003cp\u003e\u003cem\u003ePretty simple right? Cool.\u003c/em\u003e\u003c/p\u003e\u003ch2\u003eTesting our CustomResponse Trait\u003c/h2\u003e\u003cp\u003eIt's time to test our custom response trait. We will be testing two basic things, the response status code and a valid JSON string. Let's create our test class. \u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003ephp artisan make:\u003cspan class=\"hljs-built_in\"\u003etest\u003c/span\u003e CustomResponseTest --unit\n\u003c/pre\u003e\u003cblockquote\u003e\u003cstrong\u003eNote:\u003c/strong\u003e Unit tests can be found in the \u003ccode\u003e\u003cem\u003etest/Unit\u003c/em\u003e\u003c/code\u003e directory inside our Laravel project.\u003c/blockquote\u003e\u003cp\u003eAs we know traits cant be instantiated but we can mock it to be able to get an instance of it.\u003c/p\u003e\u003cp\u003eMocking our response trait will be very easy since Laravel ships with \u003ca href=\"https://github.com/mockery/mockery\" target=\"_blank\"\u003emockery\u003c/a\u003e. In unit tests, mock objects simulate the behavior of real objects. \u003c/p\u003e\u003cp\u003eWe will be using the \u003ccode\u003egetMockBuilder\u003c/code\u003e method to create an instance of our \u003ccode\u003eCustomResponse\u003c/code\u003e trait and then on each test method we call the response method we want to test.\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003e\u003cspan class=\"hljs-meta\"\u003e\u0026lt;?php\u003c/span\u003e\n\n\u003cspan class=\"hljs-keyword\"\u003enamespace\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eTests\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eUnit\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eTransformers\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eUserTransformer\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eUser\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eIlluminate\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eFoundation\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eTesting\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eRefreshDatabase\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eIlluminate\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eFoundation\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eTesting\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eWithFaker\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eTests\u003c/span\u003e\\\u003cspan class=\"hljs-title\"\u003eTestCase\u003c/span\u003e;\n\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eCustomResponseTest\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eTestCase\u003c/span\u003e\n\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003euse\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003eRefreshDatabase\u003c/span\u003e;\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eprotected\u003c/span\u003e\u0026nbsp;$customResponse;\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eprotected\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003esetUp\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e:\u0026nbsp;\u003cspan class=\"hljs-title\"\u003evoid\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003eparent\u003c/span\u003e::setUp();\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;customResponse\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;getMockBuilder(\u003cspan class=\"hljs-string\"\u003e'App\\Traits\\CustomResponse'\u003c/span\u003e)-\u0026gt;getMockForTrait();\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e/**\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@Test\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003epublic\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003etest_should_return_not_found_response\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$response\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;customResponse-\u0026gt;notFound();\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;assertEquals(\u003cspan class=\"hljs-number\"\u003e404\u003c/span\u003e,\u0026nbsp;$response-\u0026gt;getStatusCode());\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;assertJson($response-\u0026gt;getContent());\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-comment\"\u003e/**\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*\u0026nbsp;\u003cspan class=\"hljs-doctag\"\u003e@Test\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;*/\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003epublic\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-keyword\"\u003efunction\u003c/span\u003e\u0026nbsp;\u003cspan class=\"hljs-title\"\u003etest_should_return_custom_data_response\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003c/span\u003e{\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$user\u0026nbsp;=\u0026nbsp;factory(User::class)-\u0026gt;create();\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$data\u0026nbsp;=\u0026nbsp;fractal($user,\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e\u0026nbsp;UserTransformer())-\u0026gt;toArray();\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;$response\u0026nbsp;=\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;customResponse-\u0026gt;customData($data,\u0026nbsp;\u003cspan class=\"hljs-string\"\u003e'user'\u003c/span\u003e);\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;assertEquals(\u003cspan class=\"hljs-number\"\u003e200\u003c/span\u003e,\u0026nbsp;$response-\u0026gt;getStatusCode());\n\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u003cspan class=\"hljs-keyword\"\u003e$this\u003c/span\u003e-\u0026gt;assertJson($response-\u0026gt;getContent());\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;}\n}\n\u003c/pre\u003e\u003cp\u003eLet me explain the \u003ccode\u003etest_should_return_custom_data_response\u003c/code\u003e method.\u0026nbsp; First we have to seed the database with user data and then transform that data to an array so we can pass it to the \u003ccode\u003ecustomData\u003c/code\u003e method. Finally we have to assert that it returns 200 status code and a valid JSON response. Same assertions goes for \u003ccode\u003etest_should_return_not_found_response\u003c/code\u003e method.\u003c/p\u003e\u003cp\u003eYou can run the custom response test using this:\u003c/p\u003e\u003cpre class=\"ql-syntax\" spellcheck=\"false\"\u003evendor/bin/phpunit \u003cspan class=\"hljs-comment\"\u003e--filter=CustomResponseTest\u003c/span\u003e\n\u003c/pre\u003e\u003ch2\u003eConclusion\u003c/h2\u003e\u003cp\u003eTesting makes a confident developer. It's a discipline that I encourage every developer to imbibe. I will be writing more on the few things I have learned about testing.\u003ca href=\"http://eepurl.com/gGa_G1\" target=\"_blank\"\u003e \u003c/a\u003eJoin my \u003ca href=\"http://eepurl.com/gGa_G1\" target=\"_blank\"\u003emailing list \u003c/a\u003eto get more of my blog posts.\u003c/p\u003e\u003cp\u003eThe source code for this post is on \u003ca href=\"https://github.com/stephenjude/UserAPI\" target=\"_blank\"\u003egithub\u003c/a\u003e, feel free to fork it.\u003c/p\u003e\u003cp\u003eYou can follow me on \u003ca href=\"https://twitter.com/stephenjudeso\" target=\"_blank\"\u003etwitter\u003c/a\u003e, let's continue the discussion over there.\u003c/p\u003e", - true, - "2019-10-25 00:00:00", - "https://images.unsplash.com/photo-1563206767-5b18f218e8de?ixlib=rb-1.2.1\u0026q=80\u0026fm=jpg\u0026crop=entropy\u0026cs=tinysrgb\u0026w=1080\u0026fit=max\u0026ixid=eyJhcHBfaWQiOjg2OTE0fQ", - "Photo by \u003ca href=\"https://unsplash.com/@mbaumi\"\u003eMika Baumeister\u003c/a\u003e on \u003ca href=\"https://unsplash.com\"\u003eUnsplash\u003c/a\u003e", - "aec24398-2e6b-4241-89ff-a4088c9259a9", - "2019-10-19 15:52:39", - "2019-11-09 00:53:17", - "{\"meta_description\":\"Trait is the fastest way to create a reusable code. A Trait is intended to reduce some limitations of single inheritance. This means that you can use multiple traits in a PHP class.\",\"opengraph_title\":\"Mocking And Testing PHP Traits In A Laravel Application\",\"opengraph_description\":\"Trait is the fastest way to create a reusable code. A Trait is intended to reduce some limitations of single inheritance. This means that you can use multiple traits in a PHP class.\",\"opengraph_image\":null,\"opengraph_image_width\":null,\"opengraph_image_height\":null,\"twitter_title\":\"Mocking And Testing PHP Traits In A Laravel Application\",\"twitter_description\":\"Trait is the fastest way to create a reusable code. A Trait is intended to reduce some limitations of single inheritance. This means that you can use multiple traits in a PHP class.\",\"twitter_image\":null}" - ] - ], - "fields": [ - "id", - "slug", - "title", - "excerpt", - "body", - "published", - "publish_date", - "featured_image", - "featured_image_caption", - "author_id", - "created_at", - "updated_at", - "meta" - ], - "types": [ - 2950, - 1043, - 1043, - 25, - 25, - 16, - 1114, - 1043, - 1043, - 2950, - 1114, - 1114, - 25 - ], - "type_names": [ - "uuid", - "text", - "text", - "text", - "text", - "boolean", - "timestamp(0) without time zone", - "text", - "text", - "uuid", - "timestamp(0) without time zone", - "timestamp(0) without time zone", - "text" - ], - "started_at": "2020-01-12 12:49:37 +0000", - "finished_at": "2020-01-12 12:49:37 +0000", - "checksum": "a39807431fe5f9def7b49d78d3c52eae" -} diff --git a/public/tags.json b/public/tags.json deleted file mode 100644 index 03a32fa..0000000 --- a/public/tags.json +++ /dev/null @@ -1 +0,0 @@ -{"title":"extract","values":[["fe5de373-a818-4faa-9411-5536a2112b73","blog","blog","2019-10-10 09:32:19","2019-10-10 09:32:19",null],["47b633f5-b0c7-4033-b9b8-ac4619f7a8d9","project","project","2019-10-10 09:32:19","2019-10-10 09:32:19",null],["05a1c5b1-8aaf-4d1e-94bf-2c7f67179601","laravel","laravel","2019-10-10 09:32:19","2019-10-10 09:32:19",null],["30372141-bdc2-4ee6-ac37-a3e851c9751d","php","php","2019-10-10 09:32:19","2019-10-10 09:32:19",null],["be25e91a-0675-43a2-8527-f47a345e3550","traits","traits","2019-10-23 17:12:18","2019-10-23 17:12:18",null],["b2fcdfd8-c0a3-4a32-b79b-6342b9f703a6","testing","testing","2019-10-23 17:12:18","2019-10-23 17:12:18",null],["00e22b8c-118a-43bd-8150-f0c1edcc913a","mocking","mocking","2019-10-23 17:12:18","2019-10-23 17:12:18",null],["4898707b-210c-4808-9073-270df6f002db","server","server","2019-11-07 23:44:11","2019-11-07 23:44:11",null],["44a9b58e-e8a0-47d7-83e6-4a7acb6b6d02","deployment","deployment","2019-11-07 23:44:11","2019-11-07 23:44:11",null],["76a439df-f172-46b0-84b1-ffcb7c2fa00a","envoy","envoy","2019-11-07 23:44:11","2019-11-07 23:44:11",null],["a781e343-1f42-4c90-ae0b-7efc89bc9c01","bitbucket","bitbucket","2019-11-07 23:44:11","2019-11-07 23:44:11",null],["993ae98a-73b9-46ba-a916-a529df2466e7","vps","vps","2019-11-07 23:44:11","2019-11-07 23:44:11",null],["29880afc-0071-4414-9336-2cf73ad5ca26","paystack","paystack","2019-11-20 15:34:37","2019-11-20 15:34:37",null],["6ce8c6e6-add4-4316-bdb2-32d2767117aa","paystacklite","paystacklite","2019-11-20 15:34:37","2019-11-20 15:34:37",null],["996acbb0-75a1-4eb8-a4a7-402e1fa2c182","payment","payment","2019-11-20 15:34:37","2019-11-20 15:34:37",null],["36e42cbb-a8bb-4469-9fbf-30b2a14cf681","integration","integration","2019-11-20 15:34:37","2019-11-20 15:34:37",null],["07844ed0-d615-4ffe-a57e-47575ed386ba","fluent-api","fluent api","2019-11-24 09:44:50","2019-11-24 09:44:50",null],["65e9e8a7-bf37-4596-962d-d781659f9fce","api","api","2019-11-24 09:44:50","2019-11-24 09:44:50",null],["3b881881-752f-4894-a077-58a2ba7e13ea","php74","php7.4","2019-12-02 19:06:31","2019-12-02 19:06:31",null],["d40a451f-32bf-4e9e-b673-f4e9073cec57","74","7.4","2019-12-02 19:06:31","2019-12-02 19:06:31",null],["cf8157e8-c6ff-4362-9e6e-98be9ca26561","laragon","laragon","2019-12-02 19:06:31","2019-12-02 19:06:31",null],["b8ef60eb-e55b-4b0c-9a5c-7f497a469bf9","development-environment","development environment","2019-12-02 19:06:31","2019-12-02 19:06:31",null],["024faf5c-a0bd-4ca4-a44e-37a672a976bd","local-server","local server","2019-12-02 19:06:31","2019-12-02 19:06:31",null],["023f7c38-579c-45f7-a012-3003f612387a","local","local","2019-12-02 19:06:31","2019-12-02 19:06:31",null],["41e7072b-7322-41aa-b9cd-57abe6659d62","linux","linux","2019-12-11 01:46:32","2019-12-11 01:46:32",null],["9601ea85-b418-4fc1-bcec-e79b49c94f74","redis","redis","2019-12-11 01:46:32","2019-12-11 01:46:32",null],["1caea527-f51e-4940-bdc7-8654c1d100b7","redis-server","redis-server","2019-12-11 01:46:32","2019-12-11 01:46:32",null],["b2f6782a-c49f-4d50-8c3f-b05a5e86971d","middleware","middleware","2019-12-11 20:29:41","2019-12-11 20:29:41",null],["f75b6f17-a227-4f07-9686-eb10a34b2485","http","http","2019-12-11 20:29:41","2019-12-11 20:29:41",null],["9f12199a-1f33-4d7d-9ecb-10b7db2872fa","https","https","2019-12-11 20:29:41","2019-12-11 20:29:41",null],["b5d7f1d8-521d-4677-afe2-ad2b7388e06d","redirects","redirects","2019-12-11 20:29:41","2019-12-11 20:29:41",null]],"fields":["id","slug","name","created_at","updated_at","meta"],"types":[2950,1043,1043,1114,1114,25],"type_names":["uuid","text","text","timestamp(0) without time zone","timestamp(0) without time zone","text"],"started_at":"2020-01-12 12:48:29 +0000","finished_at":"2020-01-12 12:48:29 +0000","checksum":"bdb9dfc8b98a3840eb65e36dc6760eaf"} \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 643b344..25dd534 100644 --- a/routes/web.php +++ b/routes/web.php @@ -19,5 +19,5 @@ Route::get('/articles/{slug}', 'BlogController@findPostBySlug')->name('blog.post'); Route::get('/fresh', 'BlogController@updateIndexedArticles')->name('index.json'); Route::get('/newsletter', 'BlogController@newsletter')->name('newsletter'); -Route::get('seeder', 'BlogController@seeder'); +// Route::get('seeder', 'BlogController@seeder');