Reputation: 2645
I'm new to Laravel and am working on a collection of API endpoints that fetch data from a variety of database tables, transforms and processes that data, and then returns it as a JSON response. What I'm struggling to decide, from reading the documentation, is where my processing/transformation code should live.
I've setup my routes in routes/api.php, and have them point towards a Controller
subclass, but from here things get a little murky because I'm not currently looking to make use of Eloquent ORM. It seems like typically I'd generate Model
subclasses for each database table, and have a Repository
call into those and transform the returned data, like so:
Route => Controller => Repository => Model
But where should I be placing both the database query code, and the logic required to process/transform that data (the business logic), when not making use of Eloquent ORM or the Model
paradigm? Making the controller fat with DB queries and logic seems like a messy solution, but at the same time a lot of the Laravel DB example code does place logic in Controller subclasses.
Upvotes: 0
Views: 1136
Reputation: 1410
Here is an example of how you can setup your project without Eloquent
.
class OrderRecord
{
protected $id;
protected $createdAt;
public function __construct($id, $createdAt = null)
{
$this->id = $id;
$this->createdAt = $createdAt ?: date('d-m-Y H:i:s');
}
public function getID()
{
return $this->id;
}
...
}
class OrderRepository
{
public function find($id): OrderRecord
{
// Here goes your querying. StdClass will be returned in this case
// that will be used to create new record.
$row = DB::table('orders')->find($id);
if ($row) {
return (new OrderRecord($row->id, $row->created_at));
} else {
// If not found you can throw an exception or return null
// (return type should be ?OrderRecord then) depending on
// how you want to design your workflow with repositories.
...
}
}
...
}
Lastly your business logic can be in your controllers. Your controllers should use repositories to get your model objects, work with them and the use repositories to store result if needed.
Obviously, you will need to implement base classes/interfaces for all your entities. Use dependency injection and Laravel's service container to glue everything together.
You can also extend this design by separating querying and mapping in your repository - you will have Repository
classes that know only how to retrieve/store raw data and you will have Mapper
classes that know how to create/retrieve raw data to/from your records (and serve as factories that repository will use to generate record objects from query results). If business logic also need to be interchangeable then you can also take business logic out of your controllers and put it into separate classes that your controller can utilize.
Here is an excellent article about repository-based approach and how you can extend it.
Upvotes: 0
Reputation: 106
So I'll offer an approach that is I think accomplishes what you are asking. In the API I developed, I used the route/api.php
file to create the API endpoints. Each of these point to a Controller
where the authentication and request validation is performed. The Controller
then calls a Service
class that handles all the business logic of the application and these are the real heavy lifting parts. The Service
class makes calls to a Repository
, which actually performs Model
changes and saving.
I saw this used in another project several years ago and mimicked it for my projects. The code flow is shown below. Not sure if it will work for you, but I find it to be a very neat and keeps the code grouped together in logical ways.
Route => Controller => Service => Repository => Model
Upvotes: 1