dddshelf / last-wishes

Last Wishes is a PHP application written following Domain-Driven Design approach. It's one of the sample applications where you can check the concepts explained in the "Domain-Driven Design in PHP" book.
https://leanpub.com/ddd-in-php
659 stars 120 forks source link

How can I return with an array of users #27

Open TheGeekyM opened 4 years ago

TheGeekyM commented 4 years ago

In all of your examples in application services you illustrate how to return a DTO but with one user so I need to know how to return a collection of users

this is what you did with one user, or in another example, you return a user transformer:

class SignUpUserService
{
    public function execute(SignUpUserRequest $request)
    {
// ...
        $user = // ...
        return new UserDTO($user);
    }
}

and what should to be done in pagination?

gitmood[bot] commented 4 years ago

Thanks for opening this issue. Once closed, we will ask you and to all participants to provide open feedback about your experience. Thanks in advance!

ngmy commented 4 years ago

I want to know too. I am reading your wonderful book and repository.

I created a data transformer for a collection class in my project.

Application service:

public function execute($request = null)
{
    // ...
    $users = // ...
    return $this->usersDataTransformer->write($users)->read(); 
}

Data transformer for a collection class:

class UsersDtoDataTransformer implements UsersDataTransformer
{
    private $users;
    private $userDataTransformer;

    public function __construct(UserDtoDataTransformer $userDataTransformer)
    {
        $this->userDataTransformer = $userDataTransformer;
    }

    public function write(Users $users): self
    {
        $this->users = $users;
        return $this;
    }

    public function read()
    {
        // Should I wrap this with a DTO?
        return array_map(function (User $user): object {
            return $this->userDataTransformer->write($user)->read();
        }, $this->users->toArray());
    }
}

If pagination is needed, I created a data transformer in the infrastructure layer. This transformer translates into a paginator.

namespace MyApp\Infrastructure\Application\DataTransformer\User;

// uses...

class UsersLaravelLengthAwarePaginatorDataTransformer implements UsersDataTransformer
{
    private $users;
    private $usersDataTransformer;
    private $perPage = 10;
    private $currentPage;
    private $options;

    public function __construct(UsersDtoDataTransformer $usersDataTransformer)
    {
        $this->usersDataTransformer = $usersDataTransformer;
        $this->currentPage = LengthAwarePaginator::resolveCurrentPage();
        $this->options = [
            'path' => LengthAwarePaginator::resolveCurrentPath(),
        ];
    }

    public function setPerPage(int $perPage): self
    {
        $this->perPage = $perPage;
        return $this;
    }

    public function write(Users $users): self
    {
        $this->users = $users;
        return $this;
    }

    public function read()
    {
        $users = $this->usersDataTransformer->write($this->users)->read();
        // Should I wrap it with a DTO?
        return new LengthAwarePaginator(
            array_slice(
                $users,
                $this->perPage * ($this->currentPage - 1),
                $this->perPage
            ),
            count($users),
            $this->perPage,
            $this->currentPage,
            $this->options
        );
    }
}

I have following questions.

  1. Is the above code a good idea?
  2. Should I build a paginator outside of DDD? (For example, a controller or view model of a web application framework)
  3. Should an application service translate one aggregation (or collection) into a DTO? Or should an application service translate all data needed by a view (multiple aggregations) into a DTO?