Comments (7)
Hi. Thank you for the feedback.
I don't think it's best practice to pass a Laravel's Request object to the Service Layer.
$request->file('image')
is not a Request object.
I don't like whereHas() example.
I always use Eloquent to keep the code maintainable. The tiny performance difference is not a problem for most of Laravel projects. Development and maintenance costs are more important.
If you have a couple of really slow queries that became a problem, you can always rewrite those into query builder queries or raw SQL queries, use cache etc.
I don't think mass assignment is a good practice, when your service is NOT TRIVIAL.
I always use the mass assignment feature. It's absolutely safe when you know how it works.
I think the document is leading people being tightly coupled to the framework.
Technically, that is correct but I still prefer to use the helpers because they make the code maintainable.
Overengineering is not good.
Donβt try to apply DDD for everything. Draw a context map and decide where you will make a push for DDD and where you will not (author of DDD)
Yes, the app will be tightly coupled with a couple of classes (not with the framework) but if you'll really want to transfer Laravel code to another PHP framework, this will be your smallest problem. By the way, it's super easy (cheap) to make all these helpers work in any PHP framework or in a vanilla PHP application.
Also, in the real world, a typical small business will keep using the existing app or rewrite the app using another programming language or framework from scratch rather than try to reuse old sloppy code in some new fancy PHP framework.
from laravel-best-practices.
If I'm not mistaken, what you're explaining is very similar to DDD. Here's is a recent blog post from Spatie people (I believe).
I have to say that I'm so happy I started working that way. Separating domain layers from the framework is so beneficial in terms of maintainability.
PD: Here's also a ValueObject library by Spatie.
from laravel-best-practices.
Of course, there's no silver bullet but this pattern worked for me for medium to large sized applications. Small applications can be coded whatever, though.
from laravel-best-practices.
@alexeymezenin Your answer is understandable, and totally I agree with you. I didn't mean to offend you (not a native speaker, so don't know write nicely), I just wanted to know how people think. Thanks.
from laravel-best-practices.
What you do is right ValueObject-wise, but Laravel is not ready for Value Objects. I used them the same way as you but it felt hacky. Every developer needs to know how to use them and since there is no object validation in Laravel you can assign any value to any attribute (existing or not in db) or create an empty object $user = new User
(which is not correct if you User must have an address) and nobody (Laravel) will complain.
There is a blog post about this: https://www.ntaso.com/why-i-dont-use-value-objects-in-laravel-anymore/
from laravel-best-practices.
@skyrpex I have looked through the Spatie's value object. Thanks for the link.
I do like and really respect the Spatie people and their packages though, but this time, I will not buy the concept of the Value Object(VO) from them. I think they mix up the concept of VO between Data Transfer Object(DTO).
My idea is based on Martin Fowler's book "Patterns of Enterprise Application Architecture", and definitions of VO from the Red Book by Eric Evans.
If you are interested, the following is the VO example in a Laravel project based on which I understood the concept. You may say, a lot of boilerplate code. But the decision is yours. Since I work for a growing Logistics sevice which currently handles more than 500k requests in a minutes, this style of code gave me a peace of mind.
class CreateUsersTable
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('zip_code', 5);
// ...
});
}
/**
* @property Address $address
*/
class User extends Model
{
public function getAddressAttribute()
{
return new Address(
$this->getAttributeValue('zip_code'),
// ...
);
}
public function setAddressAttribute(Address $address)
{
$this->attributes['zip_code'] = $address->getZipCode();
// ...
}
public function scopeWithAddress(Builder $query, $search)
{
// Assume value $search was sanitized
return $query->where('zip_code', 'like', "%{$search}%")
// ->orWhere(...)
;
}
}
class Address
{
private $zipCode;
public function __construct(
string $zipCode = null,
// ...
) {
$this->zipCode = $this->setZipCode($zipCode);
}
public function getZipCode()
{
return $this->zipCode;
}
private function setZipCode(string $zipCode = null)
{
if (is_numeric($zipCode) === false || mb_strlen($zipCode) !== 5) {
throw new InvalidArgumentException();
}
$this->zipCode = $zipCode;
}
// ...
public function isEqualTo(Address $other)
{
return $this->zipCode === $other->getZipCode()
// && ...
;
}
}
class SomeControllerOrCommandOrService
{
public function doSomethingWith(User $user)
{
$destAddress = $user->address;
// ...
}
}
class UserCreator(CreateUserDto $dto)
{
public function createUser()
{
$user = new User();
$user->address = $dto->getAddress();
// ...
return $user;
}
}
FYI, I got a lot of insights from these videos:
- "PHP UK Conference 2014" by Mathias Verraes - Unbreakable Domain Models
- "Hemoglobin & Hobgoblins" by Ross Tuck
PS. Sorry! The code was written without help of an IDE, so there were several times of corrections. I think there still are errors though, but I hope the readers get the point.
from laravel-best-practices.
@Konafets Thanks a million for the feedback and the link. I've read the link as soon as it was posted, and read them again thanks to you. This thread made me think a lot in terms of software design as well as myself.
While reading the article and navigating supporting links, I encountered inexperienced day's myself, and became red-faced with shame.
Of the discussion I've read on this article, the following sentence teached me that I am going too far...
Eloquent is Active Record, not modelling tool for describing your domain
- JarekTkaczyk
from laravel-best-practices.
Related Issues (20)
- What PHP to JS package is recommended? HOT 4
- How about throw exceptions? HOT 5
- Do not get data from the .env file directly, why? HOT 2
- What about laravel Resources? HOT 3
- Wrong return type? HOT 1
- PSR-12 HOT 3
- What about translation variables? HOT 2
- Best
- Interface best practice HOT 5
- Converting from and back to json HOT 1
- Validation FormRequest HOT 1
- Looking for the repo owner HOT 8
- Typo Issue in example (Don't repeat yourself (DRY)) HOT 2
- Store dates in the standard format. Use accessors and mutators to modify date format HOT 11
- Seeder in singular -> Good, Seeder in plural -> bad (naming-conventions) HOT 2
- Recommended route name conflict?
- A tool that enforces all these best practices HOT 1
- Change test case methods to snake_case HOT 1
- Query Parameter Validation HOT 1
- La
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from laravel-best-practices.