簡體   English   中英

PHP。創建對象的最佳實踐

[英]PHP. The best practices of creating objects

假設我有一個實體(一塊石頭),我有一些更具體的實體,它們擴展了基本的實體 - 例如,一個有說服力的石頭,它有一些不同的屬性和方法。 石頭的所有屬性都存儲在同一個表中的數據庫中。 特定對象的所有特定屬性都序列化存儲在表的“specific_options”字段中。 我有“石頭”課程和“Talking_Stone”課程,它擴展了基本的石頭課程。 我需要根據從數據庫中獲取的數據創建一個石頭對象。

實現這樣的事情的最佳做法是什么?

到目前為止我得到了什么:

class Stone_Data {
    ...
    public static function get_item( $id ) {
            $sql = 'SELECT * FROM `' . self::$table . '` WHERE `id`=' . ( int ) $id;
            $item = self::$db->get_row( $sql );
            return $item;
    }
    ...
}

class Stone_Factory {
    ...
    public static function create( $id = null ) {
            // if the stone's type is set
            if ( !is_null( $id ) && !is_null( $data = Stone_Data::get_item( $id ) ) && !empty( $data['type'] ) ) {
                    // create a stone of this type
                    $class_name = ucfirst( $data['type'] ) . '_Stone';
                    return new $class_name( $data );
            }
            // otherwise create a basic stone
            return new Stone;
    }
    ...
}

class Stone {
    private $data = array(
        ...
            'specific_options'  => '',
        ...
    );
    ...
    public function __construct( $data = array() ) {
            $this->set( $data );
    }
    ...
    public function __set( $name, $value ) {
            if ( array_key_exists( $name, $this->data ) ) {
                    // serialize if the value is an array or an object
                    if ( is_array( $value ) || is_object( $value ) ) {
                        $value = serialize( $value );
                    }
                    $this->data[$name] = $value;
            }
    }
    public function set( $data = array() ) {
            foreach ( $data as $key => $value ) {
                    // serialize if the value is an array or an object
                    if ( is_array( $value ) || is_object( $value ) ) {
                        $data[$key] = serialize( $value );
                    }
            }
            $this->data = array_merge( $this->data, $data );
            return $this;
    }
    ...
}
class Talking_Stone extends Stone {
    ...
    public function __construct( $data = array() ) {
        parent::__construct( $data );
        // $this->type = 'talking'
        $this->specific_options->language = 'French';
        ...
    }
    ...
}

但不知何故,它感覺不太對..

您想為此使用存儲庫類:

class StoneRepository
{
    private $stoneFactory;

    public function __construct(StoneFactory $factory) {
        $this->stoneFactory = $factory;
    }

    /**
     * @param integer $id
     * @return Stone
     */
    public function findStoneById($id) {
        // Fetch your data from the database
        $row = ...;

        // Use the factory to create a new stone from the data
        // that has already been fetched
        $stone = $this->stoneFactory->create($row);

        // Return the new stone
        return $stone;
    }
}

這里最大的優點是您可以從模型中分離數據庫邏輯。 這很好,因為你得到一個沒有數據庫意識的干凈模型。 而且你可以隨心所欲地進行查詢,也可以保持清潔和分離。

然后你可以使用它來獲取具有給定id的石頭,例如你的控制器:

$factory = new StoneFactory();
$repository = new StoneRepository($factory);

$stone = $repository->findStoneById($id);

獲取集合

獲取集合同樣簡單:

class StoneRepository
{
    ...

    public function findAllStones() {
        // Again, fetch the data
        $rows = ...;

       // Transform each row into a Stone object
        $collection = array_map(function ($row) {
            return $this->stoneFactory->create($row);
        }, $rows);

        return $collection;
    }
}

用關系返回對象

遲早你可能想要獲取一些相關的對象。 您可以在這里采取一些方法。 最簡單的方法是實際上單獨獲取每種類型的對象並在控制器中構建您的模型。 例如,如果您想要一個包含相關Stone對象的Bag對象:

$bag = $bagRepository->findBagById($bagId);
$stones = $stoneRepository->findStonesByBagId($bagId);

$bag->addStones($stones);

另一種方法是使用join並在BagRepository實際構建BagStones 因為它有點復雜,我不打算在這里寫下來。

CRUD

您還應該使用存儲庫根據您的模型插入/更新/刪除數據庫中的數據。 同樣,它就像添加一個接受Stone對象並將其數據保存在數據庫中的insertupdatedelete方法一樣簡單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM