{"id":9749,"date":"2021-03-26T10:00:23","date_gmt":"2021-03-26T01:00:23","guid":{"rendered":"https:\/\/www.gigas-jp.com\/appnews\/?p=9749"},"modified":"2021-03-26T10:23:28","modified_gmt":"2021-03-26T01:23:28","slug":"laravel-service-repository-pattern","status":"publish","type":"post","link":"https:\/\/www.gigas-jp.com\/appnews\/archives\/9749","title":{"rendered":"Laravel Service-Repository Pattern"},"content":{"rendered":"\n<p>In this article, you\u2019ll learn about:<br> \u2022    Main benefits of using Repository Pattern <br> \u2022    How to implement a PHP Repository Pattern in Laravel?<br> \u2022    We will show you how to start code and implement it in the Laravel    based App.<\/p>\n\n\n\n<p><strong>What Important \u2013 Why we need a design pattern?<\/strong><\/p>\n\n\n\n<p>Service-Repository design pattern is clean and sustainable. The concept of repositories and services ensures that you write reusable code and helps to keep your controller as simple as possible making them more readable. <\/p>\n\n\n\n<p>The main idea to use Repository Pattern in a Laravel application is to create a bridge between models and controllers.&nbsp;In other words, to decouple the hard dependencies of models from the controllers.<\/p>\n\n\n\n<p>Repositories are usually a common wrapper for your model and the place where you would write different queries in your database. A service on the other hand is a layer for handling all your application\u2019s logic. <\/p>\n\n\n\n<p>Based on experience, it\u2019s really conducive to separate the logic and the wrapper of the model especially when you\u2019re working on team or big projects.<\/p>\n\n\n\n<p>The use of Repository Pattern has many benefits, below is a list of the most important ones:<br>\u2022 It centralizes data logic or business logic and service logic. <br>\u2022 It gives a substitution point for the unit tests.   <br>\u2022 Provides a flexible architecture.  <br>\u2022 Reduces duplication of code  <br>\u2022 A lower chance for making programming errors. <\/p>\n\n\n\n<p><strong>Let\u2019s start with code and implement it in your Laravel app!<\/strong><\/p>\n\n\n\n<p>Now you know the benefits of the repository pattern in Laravel, so let\u2019s implement them in your application!&nbsp;<\/p>\n\n\n\n<p><strong>Repository<\/strong><\/p>\n\n\n\n<p>In the beginning, we will start with a folder structure. Laravel does not have a repository command. You have to do it manually. We should start by creating a Repositories folder into our app folder. Then add PostRepository file. So the final file structure should look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-- app\n---- Repositories\n--------PostRepository.php<\/code><\/pre>\n\n\n\n<p>We call the Post model in the constructor of our class. So the PostRepository class will look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace App\\Repositories;\n\nuse App\\Models\\Post;\n\nclass PostRepository\n{\n    \/**\n     * @var Post\n     *\/\n    protected $post;\n\n    \/**\n     * PostRepository constructor.\n     *\n     * @param Post $post\n     *\/\n    public function __construct(Post $post)\n    {\n        $this->post = $post;\n    }\n\n    \/**\n     * Get all posts.\n     *\n     * @return Post $post\n     *\/\n    public function getAll()\n    {\n        return $this->post\n            ->get();\n    }\n\n    \/**\n     * Get post by id\n     *\n     * @param $id\n     * @return mixed\n     *\/\n    public function getById($id)\n    {\n        return $this->post\n            ->where('id', $id)\n            ->get();\n    }\n\n    \/**\n     * Save Post\n     *\n     * @param $data\n     * @return Post\n     *\/\n    public function save($data)\n    {\n        $post = new $this->post;\n\n        $post->title = $data['title'];\n        $post->description = $data['description'];\n\n        $post->save();\n\n        return $post->fresh();\n    }\n\n    \/**\n     * Update Post\n     *\n     * @param $data\n     * @return Post\n     *\/\n    public function update($data, $id)\n    {\n        \n        $post = $this->post->find($id);\n\n        $post->title = $data['title'];\n        $post->description = $data['description'];\n\n        $post->update();\n\n        return $post;\n    }\n\n    \/**\n     * Update Post\n     *\n     * @param $data\n     * @return Post\n     *\/\n    public function delete($id)\n    {\n        \n        $post = $this->post->find($id);\n        $post->delete();\n\n        return $post;\n    }\n\n}<\/code><\/pre>\n\n\n\n<p><strong>Service<\/strong> <\/p>\n\n\n\n<p>Like repository, laravel doesn\u2019t have a service command. We should start by creating a Services folder into our app folder. Then add PostService file. So the final file structure should look like this: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-- app\n---- Services\n--------PostService.php<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace App\\Services;\n\nuse App\\Models\\Post;\nuse App\\Repositories\\PostRepository;\nuse Exception;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Facades\\Log;\nuse Illuminate\\Support\\Facades\\Validator;\nuse InvalidArgumentException;\n\nclass PostService\n{\n    \/**\n     * @var $postRepository\n     *\/\n    protected $postRepository;\n\n    \/**\n     * PostService constructor.\n     *\n     * @param PostRepository $postRepository\n     *\/\n    public function __construct(PostRepository $postRepository)\n    {\n        $this->postRepository = $postRepository;\n    }\n\n    \/**\n     * Delete post by id.\n     *\n     * @param $id\n     * @return String\n     *\/\n    public function deleteById($id)\n    {\n        DB::beginTransaction();\n\n        try {\n            $post = $this->postRepository->delete($id);\n\n        } catch (Exception $e) {\n            DB::rollBack();\n            Log::info($e->getMessage());\n\n            throw new InvalidArgumentException('Unable to delete post data');\n        }\n\n        DB::commit();\n\n        return $post;\n\n    }\n\n    \/**\n     * Get all post.\n     *\n     * @return String\n     *\/\n    public function getAll()\n    {\n        return $this->postRepository->getAll();\n    }\n\n    \/**\n     * Get post by id.\n     *\n     * @param $id\n     * @return String\n     *\/\n    public function getById($id)\n    {\n        return $this->postRepository->getById($id);\n    }\n\n    \/**\n     * Update post data\n     * Store to DB if there are no errors.\n     *\n     * @param array $data\n     * @return String\n     *\/\n    public function updatePost($data, $id)\n    {\n        $validator = Validator::make($data, [\n            'title' => 'bail|min:2',\n            'description' => 'bail|max:255'\n        ]);\n\n        if ($validator->fails()) {\n            throw new InvalidArgumentException($validator->errors()->first());\n        }\n\n        DB::beginTransaction();\n\n        try {\n            $post = $this->postRepository->update($data, $id);\n\n        } catch (Exception $e) {\n            DB::rollBack();\n            Log::info($e->getMessage());\n\n            throw new InvalidArgumentException('Unable to update post data');\n        }\n\n        DB::commit();\n\n        return $post;\n\n    }\n\n    \/**\n     * Validate post data.\n     * Store to DB if there are no errors.\n     *\n     * @param array $data\n     * @return String\n     *\/\n    public function savePostData($data)\n    {\n        $validator = Validator::make($data, [\n            'title' => 'required',\n            'description' => 'required'\n        ]);\n\n        if ($validator->fails()) {\n            throw new InvalidArgumentException($validator->errors()->first());\n        }\n\n        $result = $this->postRepository->save($data);\n\n        return $result;\n    }\n\n}<\/code><\/pre>\n\n\n\n<p>We inject the PostRepository dependency into the constructor of our PostService class.  Now that we are done with the repository-service setup.&nbsp; <\/p>\n\n\n\n<p>PostController -&gt; PostService\n-&gt; PostRepository<\/p>\n\n\n\n<p>So we can use makinglogic like this in the controller:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Services\\PostService;\nuse Exception;\nuse Illuminate\\Http\\Request;\n\nclass PostController extends Controller\n{\n    \/**\n     * @var postService\n     *\/\n    protected $postService;\n\n    \/**\n     * PostController Constructor\n     *\n     * @param PostService $postService\n     *\n     *\/\n    public function __construct(PostService $postService)\n    {\n        $this->postService = $postService;\n    }\n\n    \/**\n     * Display a listing of the resource.\n     *\n     * @return \\Illuminate\\Http\\Response\n     *\/\n    public function index()\n    {\n        $result = ['status' => 200];\n\n        try {\n            $result['data'] = $this->postService->getAll();\n        } catch (Exception $e) {\n            $result = [\n                'status' => 500,\n                'error' => $e->getMessage()\n            ];\n        }\n\n        return response()->json($result, $result['status']);\n    }\n\n    \/**\n     * Show the form for creating a new resource.\n     *\n     * @return \\Illuminate\\Http\\Response\n     *\/\n    public function create()\n    {\n        \/\/\n    }\n\n    \/**\n     * Store a newly created resource in storage.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @return \\Illuminate\\Http\\Response\n     *\/\n    public function store(Request $request)\n    {\n        $data = $request->only([\n            'title',\n            'description',\n        ]);\n\n        $result = ['status' => 200];\n\n        try {\n            $result['data'] = $this->postService->savePostData($data);\n        } catch (Exception $e) {\n            $result = [\n                'status' => 500,\n                'error' => $e->getMessage()\n            ];\n        }\n\n        return response()->json($result, $result['status']);\n    }\n\n    \/**\n     * Display the specified resource.\n     *\n     * @param  id\n     * @return \\Illuminate\\Http\\Response\n     *\/\n    public function show($id)\n    {\n        $result = ['status' => 200];\n\n        try {\n            $result['data'] = $this->postService->getById($id);\n        } catch (Exception $e) {\n            $result = [\n                'status' => 500,\n                'error' => $e->getMessage()\n            ];\n        }\n        return response()->json($result, $result['status']);\n    }\n\n    \/**\n     * Show the form for editing the specified resource.\n     *\n     * @param  Post $post\n     * @return \\Illuminate\\Http\\Response\n     *\/\n    public function edit(Post $post)\n    {\n        \/\/\n    }\n\n    \/**\n     * Update post.\n     *\n     * @param Request $request\n     * @param id\n     * @return \\Illuminate\\Http\\Response\n     *\/\n    public function update(Request $request, $id)\n    {\n        $data = $request->only([\n            'title',\n            'description'\n        ]);\n\n        $result = ['status' => 200];\n\n        try {\n            $result['data'] = $this->postService->updatePost($data, $id);\n\n        } catch (Exception $e) {\n            $result = [\n                'status' => 500,\n                'error' => $e->getMessage()\n            ];\n        }\n\n        return response()->json($result, $result['status']);\n\n    }\n\n    \/**\n     * Remove the specified resource from storage.\n     *\n     * @param $id\n     * @return \\Illuminate\\Http\\Response\n     *\/\n    public function destroy($id)\n    {\n        $result = ['status' => 200];\n\n        try {\n            $result['data'] = $this->postService->deleteById($id);\n        } catch (Exception $e) {\n            $result = [\n                'status' => 500,\n                'error' => $e->getMessage()\n            ];\n        }\n        return response()->json($result, $result['status']);\n    }\n}<\/code><\/pre>\n\n\n\n<p> That\u2019s it! You have implemented a repository pattern in your app. Now you can add new repositories for the other models you are using in your application. <\/p>\n\n\n\n<p>By Ami<\/p>\n<div class='wp_social_bookmarking_light'>\n            <div class=\"wsbl_google_plus_one\"><g:plusone size=\"medium\" annotation=\"none\" href=\"https:\/\/www.gigas-jp.com\/appnews\/archives\/9749\" ><\/g:plusone><\/div>\n            <div class=\"wsbl_hatena_button\"><a href=\"\/\/b.hatena.ne.jp\/entry\/https:\/\/www.gigas-jp.com\/appnews\/archives\/9749\" class=\"hatena-bookmark-button\" data-hatena-bookmark-title=\"Laravel Service-Repository Pattern\" data-hatena-bookmark-layout=\"standard\" title=\"\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0\"> <img src=\"\/\/b.hatena.ne.jp\/images\/entry-button\/button-only@2x.png\" alt=\"\u3053\u306e\u30a8\u30f3\u30c8\u30ea\u30fc\u3092\u306f\u3066\u306a\u30d6\u30c3\u30af\u30de\u30fc\u30af\u306b\u8ffd\u52a0\" width=\"20\" height=\"20\" style=\"border: none;\" \/><\/a><script type=\"text\/javascript\" src=\"\/\/b.hatena.ne.jp\/js\/bookmark_button.js\" charset=\"utf-8\" async=\"async\"><\/script><\/div>\n            <div class=\"wsbl_twitter\"><a href=\"https:\/\/twitter.com\/share\" class=\"twitter-share-button\" data-url=\"https:\/\/www.gigas-jp.com\/appnews\/archives\/9749\" data-text=\"Laravel Service-Repository Pattern\" data-via=\"GIGASJAPAN_APPS\" data-lang=\"ja\">Tweet<\/a><\/div>\n            <div class=\"wsbl_facebook_like\"><div id=\"fb-root\"><\/div><fb:like href=\"https:\/\/www.gigas-jp.com\/appnews\/archives\/9749\" layout=\"button_count\" action=\"like\" width=\"100\" share=\"false\" show_faces=\"false\" ><\/fb:like><\/div>\n            <div class=\"wsbl_facebook_send\"><div id=\"fb-root\"><\/div><fb:send href=\"https:\/\/www.gigas-jp.com\/appnews\/archives\/9749\" colorscheme=\"light\" ><\/fb:send><\/div>\n    <\/div>\n<br class='wp_social_bookmarking_light_clear' \/>\n","protected":false},"excerpt":{"rendered":"<p>In this article, you\u2019ll learn about: \u2022 Main benefits of using Repository Pattern \u2022 How to implement a PHP Repo [&hellip;]<\/p>\n","protected":false},"author":19,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[100],"tags":[],"acf":[],"_links":{"self":[{"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/posts\/9749"}],"collection":[{"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/comments?post=9749"}],"version-history":[{"count":5,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/posts\/9749\/revisions"}],"predecessor-version":[{"id":9756,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/posts\/9749\/revisions\/9756"}],"wp:attachment":[{"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/media?parent=9749"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/categories?post=9749"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gigas-jp.com\/appnews\/wp-json\/wp\/v2\/tags?post=9749"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}