0

みなさんこんばんは、本題に入ります。モデルに次のコードがあります。

protected $_referenceMap = Array (
    "Imagens" => Array(
        "columns"       => Array (
            'paiId'
        ),
        "refTableClass" => "ModeloImagem",
        "refColumns"    => Array(
            "id"
        ),
        "onDelete" => self::CASCADE
    )
);

カスケードで呼び出されるテーブル上の画像を削除する必要があるため、次のようなものがあるかどうかを知りたいと思いました。

protected $_referenceMap = Array (
    "Imagens" => Array(
        "columns"       => Array (
            'paiId'
        ),
        "refTableClass" => "ModeloImagem",
        "refColumns"    => Array(
            "id"
        ),
        "onDelete" => function() {
            foreach($image as $i) {
                unlink($i);
            }
            return self::CASCADE
        }
    )
);
4

1 に答える 1

1

そのような事はありません。できることは、Zend_Db_Tableのメソッドを拡張_cascadeDelete($parentTableClassname, array $primaryKey)して関数を実行することです。

これを行う1つの方法がありますが、これはひどい量のコード重複です。コールバックに渡す独自のデータを指定するか、コールバックまたはクエリが失敗したかどうかに応じて動作を変更する必要がある場合があります。

class My_Db_Table extends Zend_Db_Table
{
    const ON_DELETE_CALLBACK = 'onDeleteCallback';

    /**
     * Called by parent table's class during delete() method.
     *
     * @param  string $parentTableClassname
     * @param  array  $primaryKey
     * @return int    Number of affected rows
     */
    public function _cascadeDelete($parentTableClassname, array $primaryKey)
    {
        $rowsAffected = 0;
        foreach ($this->_getReferenceMapNormalized() as $map) {
            if ($map[self::REF_TABLE_CLASS] == $parentTableClassname && isset($map[self::ON_DELETE])) {
                switch ($map[self::ON_DELETE]) {
                    case self::CASCADE:
                        for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
                            $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
                            $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
                            $type = $this->_metadata[$col]['DATA_TYPE'];
                            $where[] = $this->_db->quoteInto(
                                $this->_db->quoteIdentifier($col, true) . ' = ?',
                                $primaryKey[$refCol], $type);
                        }
                        $this->_executeCallback($map, $where);
                        $rowsAffected += $this->delete($where);
                        break;
                    default:
                        // no action
                        break;
                }
            }
        }
        return $rowsAffected;
    }

    private function _executeCallback($map, $where) {
        if (isset($map[self::ON_DELETE_CALLBACK]) && is_callable($map[self::ON_DELETE_CALLBACK])) {
            call_user_func($map[self::ON_DELETE_CALLBACK], $where);
        }
    }
}

次に、これを使用してコールバック関数を定義します。ただし、コールバック関数でカスケードを定義することはできません。そうしないと、Zend_Db_Tableが画像テーブルからエントリを削除するかどうかを判断しようとするたびに、すべての画像が削除されます。

protected $_referenceMap = Array (
    "Images" => Array(
        "columns"       => Array (
            'paiId'
        ),
        "refTableClass" => "ModeloImagem",
        "refColumns"    => Array(
            "id"
        ),
        "onDelete" => self::CASCADE,
        "onDeleteCallback" => function($where) {
            // Determine which image to unlink
            unlink($image);
        }
    )
);
于 2012-07-12T22:16:55.323 に答える