技術情報
- 2021年03月26日
- 技術情報
Laravel Service-Repository Pattern
In this article, you’ll learn about:
• Main benefits of using Repository Pattern
• How to implement a PHP Repository Pattern in Laravel?
• We will show you how to start code and implement it in the Laravel based App.
What Important – Why we need a design pattern?
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.
The main idea to use Repository Pattern in a Laravel application is to create a bridge between models and controllers. In other words, to decouple the hard dependencies of models from the controllers.
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’s logic.
Based on experience, it’s really conducive to separate the logic and the wrapper of the model especially when you’re working on team or big projects.
The use of Repository Pattern has many benefits, below is a list of the most important ones:
• It centralizes data logic or business logic and service logic.
• It gives a substitution point for the unit tests.
• Provides a flexible architecture.
• Reduces duplication of code
• A lower chance for making programming errors.
Let’s start with code and implement it in your Laravel app!
Now you know the benefits of the repository pattern in Laravel, so let’s implement them in your application!
Repository
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:
-- app
---- Repositories
--------PostRepository.php
We call the Post model in the constructor of our class. So the PostRepository class will look like this:
<?php
namespace App\Repositories;
use App\Models\Post;
class PostRepository
{
/**
* @var Post
*/
protected $post;
/**
* PostRepository constructor.
*
* @param Post $post
*/
public function __construct(Post $post)
{
$this->post = $post;
}
/**
* Get all posts.
*
* @return Post $post
*/
public function getAll()
{
return $this->post
->get();
}
/**
* Get post by id
*
* @param $id
* @return mixed
*/
public function getById($id)
{
return $this->post
->where('id', $id)
->get();
}
/**
* Save Post
*
* @param $data
* @return Post
*/
public function save($data)
{
$post = new $this->post;
$post->title = $data['title'];
$post->description = $data['description'];
$post->save();
return $post->fresh();
}
/**
* Update Post
*
* @param $data
* @return Post
*/
public function update($data, $id)
{
$post = $this->post->find($id);
$post->title = $data['title'];
$post->description = $data['description'];
$post->update();
return $post;
}
/**
* Update Post
*
* @param $data
* @return Post
*/
public function delete($id)
{
$post = $this->post->find($id);
$post->delete();
return $post;
}
}
Service
Like repository, laravel doesn’t 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:
-- app
---- Services
--------PostService.php
<?php
namespace App\Services;
use App\Models\Post;
use App\Repositories\PostRepository;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use InvalidArgumentException;
class PostService
{
/**
* @var $postRepository
*/
protected $postRepository;
/**
* PostService constructor.
*
* @param PostRepository $postRepository
*/
public function __construct(PostRepository $postRepository)
{
$this->postRepository = $postRepository;
}
/**
* Delete post by id.
*
* @param $id
* @return String
*/
public function deleteById($id)
{
DB::beginTransaction();
try {
$post = $this->postRepository->delete($id);
} catch (Exception $e) {
DB::rollBack();
Log::info($e->getMessage());
throw new InvalidArgumentException('Unable to delete post data');
}
DB::commit();
return $post;
}
/**
* Get all post.
*
* @return String
*/
public function getAll()
{
return $this->postRepository->getAll();
}
/**
* Get post by id.
*
* @param $id
* @return String
*/
public function getById($id)
{
return $this->postRepository->getById($id);
}
/**
* Update post data
* Store to DB if there are no errors.
*
* @param array $data
* @return String
*/
public function updatePost($data, $id)
{
$validator = Validator::make($data, [
'title' => 'bail|min:2',
'description' => 'bail|max:255'
]);
if ($validator->fails()) {
throw new InvalidArgumentException($validator->errors()->first());
}
DB::beginTransaction();
try {
$post = $this->postRepository->update($data, $id);
} catch (Exception $e) {
DB::rollBack();
Log::info($e->getMessage());
throw new InvalidArgumentException('Unable to update post data');
}
DB::commit();
return $post;
}
/**
* Validate post data.
* Store to DB if there are no errors.
*
* @param array $data
* @return String
*/
public function savePostData($data)
{
$validator = Validator::make($data, [
'title' => 'required',
'description' => 'required'
]);
if ($validator->fails()) {
throw new InvalidArgumentException($validator->errors()->first());
}
$result = $this->postRepository->save($data);
return $result;
}
}
We inject the PostRepository dependency into the constructor of our PostService class. Now that we are done with the repository-service setup.
PostController -> PostService -> PostRepository
So we can use makinglogic like this in the controller:
<?php
namespace App\Http\Controllers;
use App\Services\PostService;
use Exception;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* @var postService
*/
protected $postService;
/**
* PostController Constructor
*
* @param PostService $postService
*
*/
public function __construct(PostService $postService)
{
$this->postService = $postService;
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$result = ['status' => 200];
try {
$result['data'] = $this->postService->getAll();
} catch (Exception $e) {
$result = [
'status' => 500,
'error' => $e->getMessage()
];
}
return response()->json($result, $result['status']);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$data = $request->only([
'title',
'description',
]);
$result = ['status' => 200];
try {
$result['data'] = $this->postService->savePostData($data);
} catch (Exception $e) {
$result = [
'status' => 500,
'error' => $e->getMessage()
];
}
return response()->json($result, $result['status']);
}
/**
* Display the specified resource.
*
* @param id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$result = ['status' => 200];
try {
$result['data'] = $this->postService->getById($id);
} catch (Exception $e) {
$result = [
'status' => 500,
'error' => $e->getMessage()
];
}
return response()->json($result, $result['status']);
}
/**
* Show the form for editing the specified resource.
*
* @param Post $post
* @return \Illuminate\Http\Response
*/
public function edit(Post $post)
{
//
}
/**
* Update post.
*
* @param Request $request
* @param id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$data = $request->only([
'title',
'description'
]);
$result = ['status' => 200];
try {
$result['data'] = $this->postService->updatePost($data, $id);
} catch (Exception $e) {
$result = [
'status' => 500,
'error' => $e->getMessage()
];
}
return response()->json($result, $result['status']);
}
/**
* Remove the specified resource from storage.
*
* @param $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$result = ['status' => 200];
try {
$result['data'] = $this->postService->deleteById($id);
} catch (Exception $e) {
$result = [
'status' => 500,
'error' => $e->getMessage()
];
}
return response()->json($result, $result['status']);
}
}
That’s 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.
By Ami
asahi at 2021年03月26日 10:00:23
- 2021年03月22日
- 技術情報
Magic methods in PHP – Part 2
I will continue to talk about magic methods article I wrote last week. For the part 1, you can read here.
ToString
The magic __toString () method allows you to define what you would like to display when an object of the class is treated as a string. If you use echo or print on your object, and you haven’t defined the __toString () method, it will give an error.
<?php
class Student {
private $name;
public function __construct($name)
{
$this->name = $name;
$this->email = $email;
}
public function __toString()
{
return 'Name: '.$this->name;
}
}
$student = new Student('Yuuma');
echo $student;
?>
Call
If the __get () and __set () methods are called for non-existent properties, the __call () method is called when trying to invoke inaccessible methods, the methods that have not been defined in your class.
<?php
class Student {
public function __call($methodName, $arg)
{
// $methodName = getName
// $arg = array('1')
}
}
$student = new Student();
$student->getName(1);
?>
Isset
The magic __isset () method is called when you call the isset () method on inaccessible or non-existent object properties. Let’s see how it works with an example.
<?php
class Student {
private $data = array();
public function __isset($name)
{
return isset($this->data[$name]);
}
}
$student = new Student();
echo isset($student->email);
?>
Invoke
The magic __invoke () method is a special method that is called when you try to call an object as if it were a function. the $student object is treated as if it were a function, and since we have defined the __invoke () method, it will be called instead of giving you an error. The main purpose of the __invoke () method is that if you want to treat your objects as callable, you can implement this method.
<?php
class Student {
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function __invoke()
{
echo 'Invoke function';
}
}
$student = new Student('John');
$student();
?>
There are still some magic methods in PHP but let me stop here as I had written most used methods in article part 1 and part 2. If you are interest for more, you can check it out in PHP official documentation.
Yuuma
yuuma at 2021年03月22日 11:00:59
- 2021年03月19日
- 技術情報
Tips to Speed up your database queries in Laravel
Here is some tips based on my experience to speed up database queries.
Table Indexing
Indexes are important part in database. Indexes are used to quickly retrieve data without having to search every row in a database table is accessed. The users cannot see the indexes, they are just used to speed up searches/queries.
How to use? For example, you have thousands of rows of users and you want to get an email.
Select * from users where email = “me@gmail.com”
Without index, this process will be from top to bottom until it the email is found.
Using with index, in Laravel, the easy way is to create a migration file.
public function up()
{
Schema::table(‘users’, function(Blueprint $table)
{
$table->index(‘email’);
});
}
Or if you currently on fresh project just add index to column you want to
public function up()
{
Schema::create(‘users, function(Blueprint $table) {
…
$table->index(‘email’);
…
});
}
Index is not only for single column. You can use multiple column like this $table->index([‘email’, ‘ phone_no’]); Let’s us look at a query that could use two different indexes on the table based on the WHERE clause restrictions. Multi column indexes are called compound indexes.
Eloquent Eager Loading
At its core Eager Loading, is telling Eloquent that you want to grab a model with specific relationships that way the framework produces a more performant query to grab all the data you will need. By eager loading, you can take many queries down to just one or two. Wrong implementation cause N+1. Here is where common developer do which cause N+1.
For example:
Class Post extends Model
{
public function author()
{
return $this->belongsTo(Author::class);
}
}
Lets fetch author about 100 rows from the table and what happen
Mistake 1
$post = Post::all();
foreach($posts as $post)
{
$total_user = $post->author;
}
The query runs once to get all the author and for each loop it query another query for author for 100 times. 100 + 1 = N+1 problem. Imagine if you want to fetch thousand to data. If one query cost 100ms * 100 = 10,000ms it takes to complete process.
Solution
It can be solve by using with method in Eager loading. For example
$post = App\Post::with(‘author’)->get();
If you had multiple related associations, you can eager load them with an array:
$post = App\Post::with([‘author’, ‘comments’])->get();
$post =App\Post::with(‘author.profile’)->get();
With this, instead of hitting database N+1, with will single query by joining those table and transform it into collection. So you can freely access the collection object without hitting the database.
By Ami
asahi at 2021年03月19日 10:00:36
Magic methods in PHP – Part 1
When we are developing web systems using PHP, we might encounter to use magic methods in PHP a lot. Today I would like to talk about some important magic methods provided by PHP.
Actually there are lots of magic methods in PHP. For example,
- __construct()
- __destruct()
- __call($fun, $arg)
- __callStatic($fun, $arg)
- __get($property)
- __set($property, $value)
- __isset($content)
- __unset($content)
- __sleep()
- __wakeup()
- __toString()
- etc..
But we don’t use all of the things unless it’s necessary. I will only write about a few methods which are mostly used in my experience.
Construct
If you define this method in your class, it will be called automatically when an object is instantiated. The purpose of this method is to assign some default values to the properties of the object. This method is also called a constructor.
<?php
class Student {
private $name;
public function __construct($name)
{
$this->name = $name;
}
}
$student = new Student('yuuma');
?>
Destruct
The __destruct () method is called destructor and is called when the object is destroyed. Generally also called when script stops or exits. The purpose of this method is to provide an opportunity to save the state of the object or any other cleaning you want to do.
<?php
class Student {
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function __destruct()
{
echo 'This will be called when the class has been closed';
// file close, removing session etc.
}
}
$student = new Student('yuuma');
?>
Set
The magic __set () method is called when you try to set data on properties of inaccessible or non-existent objects. The purpose of this method is to set additional object data for which you have not explicitly defined object properties.
<?php
class Student {
protected $data = array();
public function __set($name, $value)
{
$this->data[$name] = $value;
}
}
$student = new Student();
// __set() called
$student->name = 'yuuma';
As you can see from the example above, we are trying to set the property of the name, which does not exist. And so the __set () method is called. The first argument to the __set () method is the name of the property that is being accessed, and the second argument is the value we are trying to set.
Get
In the case of the __set () method example in the previous section, we discussed how to set values for non-existent properties. The __get () method is the exact opposite. The magic __get () method is called when you try to read data from properties of inaccessible or non-existent objects. The purpose of this method is to provide values for these properties.
<?php
class Student {
private $data = array();
public function __set($name, $value)
{
$this->data[$name] = $value;
}
public function __get($name)
{
If (isset($this->data[$name])) {
return $this->data[$name];
}
}
}
$student = new Student();
// __set() called
$student->name = 'yuuma';
// __get() called
echo $student->name;
?>
I would like to write more but I think the article is a little bit long for now. So I will write a part 2 in next week relating with this week article. So see you next week.
By Yuuma
yuuma at 2021年03月15日 11:00:22
- 2021年03月08日
- 技術情報
Laravel QR code generator
I am using a laravel library called `simple-qr-code` in my previous project. It is pretty easy to use and configurable and I would like to share with you today.
Firstly download the package via composer
composer require simplesoftwareio/simple-qrcode "~4"
That is all for the configuration. And you can now generate in controller like this.
use SimpleSoftwareIO\QrCode\Facades\QrCode;
QrCode::generate('Make me into a QrCode!');
This will make a QrCode that says “Make me into a QrCode!”

If you want to generate directly on the view, it is fine too.
{!! QrCode::size(300)->generate('generate Qr code'); !!}
If we want to generate a URL after reading the Qr code, we just have to pass a url string in generate function like this.
{!! QrCode::size(300)->generate('www.google.com'); !!}
You can vary the Qr code designs as well. You can see more detail here. Make sure to use when you have to deal with qr code as it is pretty easy to use.
By Yuuma
yuuma at 2021年03月08日 11:00:01