ホームページ  >  記事  >  バックエンド開発  >  データ転送オブジェクト (DTO) の利点と、PHP 読み取り専用クラスが Laravel コードをどのように昇格できるかを探る

データ転送オブジェクト (DTO) の利点と、PHP 読み取り専用クラスが Laravel コードをどのように昇格できるかを探る

PHPz
PHPzオリジナル
2024-07-30 08:59:091159ブラウズ

Explore the Advantages of Data Transfer Objects (DTOs) and How PHP  Readonly Classes Can Elevate Your Laravel Code

現代の Web アプリケーション開発では、データを効率的かつ安全に管理および転送することが重要です。このプロセスを大幅に支援する設計パターンの 1 つは、データ転送オブジェクト (DTO) です。この投稿では、特に Laravel アプリケーションで DTO を使用する利点を詳しく掘り下げ、PHP 8.2 読み取り専用クラスがその利点をさらに高める方法を示します。

データ転送オブジェクト (DTO) とは何ですか?

データ転送オブジェクト (DTO) は、プロセスまたはシステム間でデータを転送するために設計された単純なオブジェクトです。一般的なモデルやエンティティとは異なり、DTO にはビジネス ロジックがありません。データをカプセル化し、アプリケーションの異なる層間またはさまざまなシステム間で情報を転送するための明確で構造化された方法を提供します。

DTO パターン

DTO パターンは、ソフトウェア アプリケーション内のさまざまなサブシステム間でデータを転送するために利用されます。 DTO を使用する主な目的は、メソッド呼び出しの数を最小限に抑え、必要なデータを集約し、データ変換と検証を管理するための構造化されたアプローチを提供することです。

DTO を使用する利点

  • 懸念事項の分離: DTO はビジネス ロジックをデータ表現から分離し、その結果、コードがよりクリーンで保守しやすく、理解しやすくなります。

  • データ検証: DTO により、他のアプリケーション層によって処理される前にデータを検証でき、有効なデータのみが使用されることが保証されます。

  • 一貫性: データ転送に一貫した構造を提供することで、DTO はさまざまなソースからのデータの管理と処理を簡素化します。

  • セキュリティ: DTO は、アクセスおよび変更可能なデータを制御することで、アプリケーションを不正なデータ操作から保護できます。

  • テスト: DTO はビジネス ロジックが組み込まれていない単純なオブジェクトであるため、モックとテストが簡単です。

  • 変換: DTO は、さまざまなアプリケーション層で必要な形式へのデータの変換を容易にします。

  • 不変性: DTO は多くの場合、不変性を促進します。これは、一度作成されると状態を変更できないことを意味します。この機能にはいくつかの利点があります:

    • 予測可能性: 不変オブジェクトは、作成後の状態が一定のままであるため、予測可能であり、推論が容易です。
    • スレッド セーフ: 不変性は本質的にスレッド セーフをサポートし、同時処理を簡素化します。
    • デバッグ: 不変オブジェクトを使用すると、その状態がライフサイクルを通じて変更されないことが保証されるため、デバッグが容易になります。

PHP 8.2 および読み取り専用クラス

PHP 8.2 では、読み取り専用クラスの導入により DTO の使用が強化されています。読み取り専用クラスを使用すると、プロパティを読み取り専用として明示的に定義する必要がなくなり、DTO の実装が簡素化されます。 PHP 8.2 の読み取り専用クラスが DTO を改善する方法は次のとおりです。

  • 簡略化されたコード: 読み取り専用クラスは自動的にプロパティを不変にし、定型コードを削減し、明確さを向上させます。
  • セキュリティの強化: 読み取り専用クラスは、プロパティを一度設定すると変更できないようにすることで、データの整合性とセキュリティを強化します。
  • 保守性の向上: 読み取り専用クラスを使用すると、データの不変性が言語自体によって強化されるため、コードがよりクリーンで保守しやすくなります。

例: プロパティ管理システムでの DTO の使用

API や CSV インポートなどのさまざまなソースからプロパティを取得できるプロパティ管理システムを考えてみましょう。 DTO を使用してプロパティ モデル、サブスクリプション、アセットなどを作成し、アプリケーション全体でデータの一貫性と検証を確保できます。

PropertyDTO の定義

まず、PropertyDTO クラスを定義しましょう:

app/DTO/PropertyDTO.php

namespace App\DTO;

/**
 * Class PropertyDTO
 *
 * Represents a Data Transfer Object for property data.
 */
readonly class PropertyDTO extends AbstractDTO
{
    /**
     * The name of the property.
     *
     * @var string
     */
    public string $name;

    /**
     * The address of the property.
     *
     * @var string
     */
    public string $address;

    /**
     * The price of the property.
     *
     * @var float
     */
    public float $price;

    /**
     * The subscription status of the property, if applicable.
     *
     * @var string|null
     */
    public ?string $subscription;

    /**
     * The list of assets associated with the property.
     *
     * @var array|null
     */
    public ?array $assets;

    /**
     * Set the properties from a model instance.
     *
     * @param $model The model instance.
     * @return $this
     */
    public function setFromModel($model): self
    {
        $this->name = $model->name;
        $this->address = $model->address;
        $this->price = $model->price;
        $this->subscription = $model->subscription;
        $this->assets = $model->assets;

        return $this;
    }

    /**
     * Set the properties from API data.
     *
     * @param array $data The API data.
     * @return $this
     */
    public function setFromAPI(array $data): self
    {
        $this->name = $data['property_name'];
        $this->address = $data['property_address'];
        $this->price = $data['property_price'];
        $this->subscription = $data['subscription'] ?? null;
        $this->assets = $data['assets'] ?? null;

        return $this;
    }

    /**
     * Set the properties from CSV data.
     *
     * @param array $data The CSV data.
     * @return $this
     */
    public function setFromCSV(array $data): self
    {
        $this->name = $data[0];
        $this->address = $data[1];
        $this->price = (float) $data[2];
        $this->subscription = $data[3] ?? null;
        $this->assets = explode(',', $data[4] ?? '');

        return $this;
    }
}
PropertyDTO の使用

PropertyDTO を使用してさまざまなソースからのプロパティを処理する方法は次のとおりです。

// From a Model
$model = Property::find(1);
$propertyDTO = (new PropertyDTO([]))->setFromModel($model);

// From an API
$apiData = [
    'property_name' => 'Beautiful House',
    'property_address' => '1234 Elm Street',
    'property_price' => 450000,
    'subscription' => 'Premium',
    'assets' => ['pool', 'garden']
];
$propertyDTO = (new PropertyDTO([]))->setFromAPI($apiData);

// From a CSV
$csvData = ['Beautiful House', '1234 Elm Street', 450000, 'Premium', 'pool,garden'];
$propertyDTO = (new PropertyDTO([]))->setFromCSV($csvData);

// Convert to Array
$arrayData = $propertyDTO->toArray();

// Convert to JSON
$jsonData = $propertyDTO->toJson();

まとめ

データ転送オブジェクト (DTO) は、データの一貫性、検証、懸念事項の分離を保証することで、Laravel アプリケーションに多くの利点をもたらします。 DTO を実装すると、アプリケーションの保守性、安全性が向上し、テストが容易になります。プロパティ管理システムでは、DTO は API や CSV インポートなどのさまざまなソースからのデータを効率的に処理するのに役立ち、ビジネス ロジックがクリーンな状態に保たれ、検証済みデータの処理に集中できるようになります。

Moreover, embracing immutability within DTOs enhances predictability, thread-safety, and simplifies debugging.

Extending DTOs with Abstract Classes for Consistency

To streamline the creation of DTOs and promote code reuse, we can use an abstract class or base class. This approach allows us to define common methods and properties in the abstract class and extend it for specific data sources.

Defining the AbstractDTO

app/DTO/AbstractDTO.php

namespace App\DTO;

/**
 * AbstractDTO
 *
 * An abstract base class for Data Transfer Objects (DTOs).
 * Provides common methods and properties for DTO implementations.
 */
abstract class AbstractDTO
{
    /**
     * AbstractDTO constructor.
     *
     * Initialises the DTO with data from an associative array.
     *
     * @param array $data The data array to initialize the DTO.
     */
    public function __construct(array $data)
    {
        $this->setFromArray($data);
    }

    /**
     * Set the properties of the DTO from a model instance.
     *
     * @param $model The model instance from which to populate the DTO.
     * @return $this
     */
    abstract public function setFromModel($model): self;

    /**
     * Set the properties of the DTO from API data.
     *
     * @param array $data The data array from the API.
     * @return $this
     */
    abstract public function setFromAPI(array $data): self;

    /**
     * Set the properties of the DTO from CSV data.
     *
     * @param array $data The data array from the CSV.
     * @return $this
     */
    abstract public function setFromCSV(array $data): self;

    /**
     * Convert the DTO to an associative array.
     *
     * @return array The DTO data as an associative array.
     */
    public function toArray(): array
    {
        $properties = get_object_vars($this);
        return array_filter($properties, function ($property) {
            return $property !== null;
        });
    }

    /**
     * Convert the DTO to a JSON string.
     *
     * @return string The DTO data as a JSON string.
     */
    public function toJson(): string
    {
        return json_encode($this->toArray());
    }

    /**
     * Set the properties of the DTO from an associative array.
     *
     * @param array $data The data array to populate the DTO.
     */
    protected function setFromArray(array $data): void
    {
        foreach ($data as $key => $value) {
            if (property_exists($this, $key)) {
                $this->$key = $value;
            }
        }
    }
}

Final Thoughts

Using an abstract or base class for DTOs not only ensures consistency across different DTO implementations but also promotes code reuse and maintainability. By defining common methods and properties in an abstract class, you can create a structured and efficient way to manage data transfer within your application. This approach aligns well with the principles of clean code and helps in building scalable and robust applications.

Here’s a revised phrase that includes a call to action:

"By leveraging DTOs and abstract classes together, you can refine your Laravel application's design, improving how data is managed and ensuring a more organised and efficient data flow. If you want to further encapsulate and enhance your DTOs with traits and interfaces, explore our guide on Enhancing Object-Oriented Design with Traits, Interfaces, and Abstract Classes."

以上がデータ転送オブジェクト (DTO) の利点と、PHP 読み取り専用クラスが Laravel コードをどのように昇格できるかを探るの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。