In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "how to understand the Laravel repository pattern". The content of the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "how to understand the Laravel repository pattern".
Activity record
By default, Laravel uses Active Record mode. Every Laravel programmer uses it intuitively because it is implemented in an abstract Model base class, and the model usually inherits from it. Let's look at an example:
Use Illuminate\ Database\ Eloquent\ Model;/** * @ property int $id * @ property string $first_name * @ property string $last_name * / class Person extends Model {} / /-use: $person = new Person (); $person- > first_name = 'Jack';$person- > last_name =' Smith';$person- > save ()
Of course, you can read and write the properties you created on Person. But to save the model, you can also call the method directly on the model. There is no need for another object-the model already provides all the methods to access the corresponding database tables.
This means that the domain model combines your custom properties and methods with all data access methods in the same class. The second part is implemented by inheriting Model.
Main points:
Active Record combines domain model with data access capabilities.
Laravel uses the Active Record pattern and implements it through the Model class.
Repository
Repository mode is an alternative to Active Record mode. It also provides abstractions for dealing with data access. But more broadly, it can be seen as a conceptual repository or collection of domain objects.
In contrast to the active record pattern, the storage pattern separates database access from the domain model. It provides an advanced interface where you can create, read, update, and delete domain models, regardless of the actual underlying data store.
The underlying repository can access the database by building and executing SQL queries, accessing remote systems through REST API, or simply managing in-memory data structures that contain all domain models. This is very useful for testing. The key part of the repository mode is the high-level interface it provides for the rest of the code.
Main points:
The repository represents a collection of concepts for domain objects.
It is only responsible for encapsulating data access with high-level interfaces.
Laravel does not provide a specific helper to implement the repository pattern
When implementing the Repository pattern in Laravel, I see two main variants.
Variant 1: specific method
In the first variant, the repository approach is focused and specific. The name explains what the caller gets, and the options for parameterizing the underlying query are limited.
Class InvoiceRepository {public function findAllOverdue (Carbon $since, int $limit = 10): Collection {return Invoice::where ('overdue_since',' > =', $since)-> limit ($limit)-> orderBy ('overdue_since')-> get () } public function findInvoicedToCompany (string $companyId): Collection {return Invoice::where ('company_id', $companyId)-> orderByDesc (' created_at')-> get ();}}
The advantage of this method lies in its expressiveness. When you read the code, you know exactly what to expect from the methods and how to call them. This will lead to fewer errors. The Repository method is easy to test because the parameters are limited.
One drawback of this approach is that it may end up using a large number of methods in the repository. Because methods cannot be easily reused, additional methods must be added for the new use case.
Main points:
Storage patterns can be implemented through classes that provide specific methods
Each method wraps a query and exposes only the necessary parameters
Advantages: readability and testability
Disadvantages: lack of flexibility and low reusability
Variant 2: general method
The other way is to provide a general method. This leads to a reduction in methods. But these methods have a large API surface because each method can be called with a different combination of parameters.
The key problem is parameter representation. This representation should guide the caller to understand the method signature and avoid invalid input. To do this, you can introduce a special class, such as using the Query Object pattern.
But what I often see in practice is a mix of scalar parameters and PHP arrays. The caller can pass input that is completely invalid, and the type data alone does not indicate what to pass. But if used properly, this lightweight approach can avoid more tedious abstractions.
Class InvoiceRepository {public function find (array $conditions, string $sortBy = 'id', string $sortOrder =' asc', int $limit = 10): Collection {return Invoice::where ($conditions)-> orderBy ($sortBy, $sortOrder)-> limit ($limit)-> get (); use: $repo = new InvoiceRepository () $repo- > find (['overdue_since',' > =', $since], 'overdue_since',' asc'); $repo- > find (['company_id',' =', $companyId], 'created_at',' asc',)
This approach alleviates the problem with the first approach: you can get fewer Repository methods, which are more flexible, and can be reused more frequently.
On the negative side, Repository becomes more difficult to test because there are more cases to cover. Method signatures are more difficult to understand, and because of this, callers may make more mistakes. In addition, some kind of query object representation will be introduced. Whether it is explicit or implicit (such as an array), your Repository implementation and its callers will be coupled to it.
Main points:
The repository pattern can be implemented through classes that provide common methods.
The difficulty lies in the representation of method parameters.
Advantages: greater flexibility and higher reusability.
Disadvantages: more difficult to test, poor readability, coupled with parameter representation.
Of course, these two methods can be combined. You may want some specific methods for complex queries and some general methods for simple where queries.
Realize
Now, let's talk about how to implement the method body.
In the above example, I used the methods of the Model class to gain access to the Eloquent query constructor. So the implementation of Repository actually uses the Active Record pattern as the implementation.
You don't have to do this. You can use DB facade to get a query builder while avoiding the Model class. Or you can write a SQL query directly:
Class InvoiceRepository {public function findAllOverdue (Carbon $since, int $limit = 10): Collection {return DB::table ('invoices')-> where (' overdue_since','> =', $since)-> limit ($limit)-> orderBy ('overdue_since')-> get () } public function findInvoicedToCompany (string $companyId): Collection {return DB::select ('SELECT * FROM invoices WHERE company_id =? ORDER BY created_at LIMIT 100mm, [$companyId]);}}
The advantage of the storage mode is that the implementation can be anything, as long as it satisfies the interface. You can also manage an API for objects or packages (and caches) in memory.
But the most common is that the underlying data store is an SQL database. To access it, you can choose the best implementation based on each method. For performance-critical or complex queries, you may want to use SQL statements directly. Simpler queries can use the Eloquent query builder.
When you do not use a model class to implement your Repository, you may consider not inheriting it in the model. But this method violates many of the built-in Laravel magic methods, and in my opinion is not a good one.
Main points:
The repository mode is flexible, allowing the use of a variety of implementation technologies.
In Laravel, the Eloquent query builder is a practical choice when accessing a database.
Interface
Your other option is whether or not to introduce an interface. The above example can be separated by an interface and one or more implementations:
/ /-Interface: public interface InvoiceRepositoryInterface {public function findAllOverdue (Carbon $since, int $limit = 10): Collection; public function findInvoicedToCompany (string $companyId): Collection;} / /-specific class, and implements the interface class InvoiceRepository implements InvoiceRepositoryInterface {public function findAllOverdue (Carbon $since, int $limit = 10): Collection {/ / implementation} public function findInvoicedToCompany (string $companyId): Collection {/ / implementation}}
Adding an interface is an additional indirect method, and it is not necessarily good. If your application is the only user of Repository and you don't want it to have multiple implementations, I don't think it makes sense to introduce interfaces. For testing, Repository can be simulated with PHPUnit, as long as it is not marked as final.
If you know that you will have multiple implementations, you should use an interface. If you are writing a package that will be used in multiple projects. Or if you want to test a particular Repository implementation, different implementations may occur.
In order to benefit from Laravel's dependency injection, you must bind the specific implementation to the interface. This must be done in the registration method of the service provider.
Use Illuminate\ Support\ ServiceProvider;class RepositoryServiceProvider extends ServiceProvider {public function register (): void {$this- > app- > bind (InvoiceRepositoryInterface::class, InvoiceRepository::class);}}
Main points:
An interface can be further decoupled to get the code base from the rest of the code.
Use the Repository interface when you expect multiple concrete classes to implement it.
In Laravel, bind the concrete class to the interface in the service provider.
Thank you for your reading, the above is the content of "how to understand the Laravel repository pattern". After the study of this article, I believe you have a deeper understanding of how to understand the Laravel repository schema, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.