모두 관리화면에 들어가서 제작·갱신 처리, 방대한 신체 파라미터는 아무 일도 일어나지 않을 거야...

안녕하세요.타마호리입니다.
PHP 엔지니어로서 평소 Laavel을 활용한 네트워크 응용프로그램 개발.
참, 지난번 기사 읽었어요?
https://zenn.dev/tyamahori/articles/98e2c11f64ad48
여러분!
어떻게 모든 입관 화면을 마주합니까?
지난번에 나는 DTO를 어떻게 사용하는지에 관한 기사를 썼다.이번에는 전체 관리 화면에 들어가 데이터를 제작·업데이트할 때의 기술 노하우를 공유하고자 한다.

일반적인 구현


제작자의 처리가 있어서 그 코드 샘플을 만들어 봤어요.
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Contracts\Hashing\Hasher;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Response;
use Illuminate\Http\Request;

/**
 * 雰囲気コードです。
 */
class HogeController extends Controller
{
    /**
     * @param Request $request
     * @param Hasher $hasher
     * @param ResponseFactory $response
     * @param User $user
     */
    public function __construct(
        private readonly Request $request,
        private readonly Hasher $hasher,
        private readonly ResponseFactory $response,
        private readonly User $user
    ) {
        $request->validate([
            'email' => ['required', 'string'],
            'password' => ['required', 'string'],
        ]);
    }

    /**
     * @return Response
     */
    public function __invoke(): Response
    {
        $this->user
            ->save([
                'email' => $this->request->input('email'),
                'password' => $this->hasher->make($this->request->input('password')),
            ]);

        return $this->response->noContent();
    }
}
invoke 방법을 사용하는 단동작 컨트롤러.나는 construct 내부에서 진행하는 것이 가장 좋다고 생각한다.이렇게 하면 invoke 방법 내부에서 검증된 값을 전제로 처리할 수 있다.이 정도면 충분하다고 생각해요. 의문점을 높이면
  • 디렉터가 DB 열을 알고 있음
  • validation 처리를 다른 클래스로 잘라낼 수 있음(
  • 그렇겠지...사실 저도 용례반을 만들고 싶은데 이번에는 타협하지 않기로 했어요.

    FormRequest와 거리를 두세요!


    FormRequest의 존재를 부정하지 않았습니다.매우 편리합니다.하지만 고민하지 않고 Form Request를 사용하는 것은 좋지 않다고 생각합니다...!(이때 다트가 자신을 찔렀다)そのFormRequest、 Requestクラスでも良くないですか? 키워드로 복구해 보세요.
    따라서 이번에는 입력 값을 얻을 수 있는 DTO 레벨을 만들 것입니다.Interface를 사용합니다.
    <?php
    
    namespace App\Package;
    
    interface CreateUserInputInterface
    {
        /**
         * @return string
         */
        public function email(): string;
    
        /**
         * @return string
         */
        public function password(): string;
    }
    
    우리가 원하는 것은Form Request가 아니라 발리 데이트 가격입니다...!그리고 구상 레벨을 만든다.
    <?php
    
    namespace App\Package;
    
    use Illuminate\Contracts\Hashing\Hasher;
    use Illuminate\Http\Request;
    
    class CreateUserInputRequest implements CreateUserInputInterface
    {
        /**
         * @param Request $request
         * @param Hasher $hasher
         */
        public function __construct(
            private readonly Request $request,
            private readonly Hasher $hasher,
        ) {
            $request->validate([
                'email' => ['required', 'string', 'email'],
                'password' => ['required', 'string', 'min:8'],
            ]);
        }
    
        /**
         * @return string
         */
        public function email(): string
        {
            return $this->request->input('email');
        }
    
        /**
         * @return string
         */
        public function password(): string
        {
            // Hash対応を忘れない!本当は命名やどこでハッシュ対応するかは考えるべき
            return $this->hasher->make($this->request->input('password'));
        }
    }
    
    DI Laavel의 Request 클래스를 파리화합니다.

    부작용이 발생하는 처리용 리포츠리!


    그리고 우리의 User Repostiory를 만듭니다.
    <?php
    
    namespace App\Package;
    
    interface UserRepositoryInterface
    {
        /**
         * @param CreateUserInputInterface $input
         * @return void
         */
        public function createByInput(CreateUserInputInterface $input): void;
    }
    
    에서 온 구상류.
    <?php
    
    namespace App\Package;
    
    use App\Models\User;
    
    class UserRepositoryEloquent implements UserRepositoryInterface
    {
        /**
         * @param User $user
         */
        public function __construct(
            private readonly User $user
        ) {
        }
    
        /**
         * @param CreateUserInputInterface $input
         * @return void
         */
        public function createByInput(CreateUserInputInterface $input): void
        {
            $this->user->save([
                'email' => $input->email(),
                'password' => $input->password(),
            ]);
        }
    }
    
    외부에서 User Eloquent를 사용하는 것이 중요합니다.Eloquent 내부에도 정의할 수 있지만 다른 장소에서 사용하면 번거로움이 많아요...!
    주의해야 할 것은 인터페이스를 만들었기 때문에 앱 서비스 Provider 좌우에서 bind의 대응을 하세요!이번 할애는

    개선된 코드 예시


    <?php
    
    namespace App\Http\Controllers;
    
    use App\Package\CreateUserInputInterface;
    use App\Package\UserRepositoryInterface;
    use Illuminate\Contracts\Routing\ResponseFactory;
    use Illuminate\Http\Response;
    
    /**
     * 雰囲気コードです。
     */
    class HogeController extends Controller
    {
        /**
         * @param CreateUserInputInterface $userInput
         * @param UserRepositoryInterface $userRepository
         * @param ResponseFactory $response
         */
        public function __construct(
            private readonly CreateUserInputInterface $userInput,
            private readonly UserRepositoryInterface $userRepository,
            private readonly ResponseFactory $response
        ) {
        }
    
        /**
         * @return Response
         */
        public function __invoke(): Response
        {
            $this->userRepository->createByInput($this->userInput);
    
            return $this->response->noContent();
        }
    }
    

    총결산


    책임과 임무의 역할이 명확해졌고 코드도 보기 쉬워졌어요. 어때요?
  • CreateUserInputInterface->입력값을 검증하여 DTO
  • 로 변환
  • User Repository Interface->DTO를 수락하여 지속화
  • 클라이언트에 대한 응답 생성
  • 앞으로 입력 값의 증감과 관련해서는 CreateUserInputInterface를 통해 Getter 방법을 추가한다.UserRepository Interface에서CreateUserInputInterface에 추가된 Getter 방법을 이용하여 데이터를 생성하고 업데이트할 수 있다고 생각합니다.
    아마도 많은 나무랄 데가 있을 것이다.상황에 따라 관리화면 데이터 제작에 모두 들어가 컨트롤러가 모두 채워진 것을 업데이트 처리하고 싶습니다.
    그럼 Laavel 개발자의 삶을 즐겨주세요!

    좋은 웹페이지 즐겨찾기