6

doctrine 2.1(およびzendフレームワーク1.11、この問題では重要ではありません)を使用して、dbへの再保存を含むpostpersistおよびpostupdateアクションを実行するにはどうすればよいですか?

たとえば、生成されたばかりの主キーのIDに基づいて一意のトークンを作成したり、アップロードされた画像のサムネイルを生成したりします(実際には、データベースに再保存する必要はありませんが、それでも)?


編集-説明しましょう、私たちはしませんか?

上記は実際には2つのシナリオに関する質問です。どちらのシナリオも、次の状態に関連しています。

User私が実体を持っているとしましょう。永続化のマークが付けられた後にオブジェクトがフラッシュされると、通常の自動生成されたmysqlのID(通常は1、2、3などで始まる実行番号を意味します)があります。
各ユーザーは画像をアップロードできます。彼はアプリケーションで使用できるようになります-データベースにもレコードがあります。だから私はという別のエンティティを持っていますImage。各Imageエンティティには、自動生成されたIDもあります。これはユーザーIDと同じ方法です。

さて、シナリオは次のとおりです。

  1. ユーザーが画像をアップロードするときに、データベースに保存された直後にその画像のサムネイルを生成したいと思います。これは、新しいイメージまたは更新されたイメージごとに発生するはずです。
    スマートを維持しようとしているので、サムネイルを生成するコードを次のように記述したくありません。

    $ image = new Image();
    ...
    $ entityManager-> persist($ image);
    $ entityManager-> flush();
    callToFunctionThatGeneratesThumbnailOnImage($ image);

    むしろ、prePersistまたはpreUpdateメソッドのように、オブジェクトの永続化(永続化されたオブジェクトのフラッシュ)で自動的に発生するようにしたいのです。

  2. ユーザーが画像をアップロードしたので、彼はその画像へのリンクを取得します。おそらく次のようになりますhttp://www.mysite.com/showImage?id=[IMAGEID]
    これにより、誰でもこのリンクのimageidを変更するだけで、他のユーザーの画像を見ることができます。
    そのため、このようなことを防ぐために、画像ごとに一意のトークンを生成したいと思います。それほど洗練されている必要はないので、画像IDのmd5値をソルトとともに使用することを考えました。
    ただし、そのためには、そのイメージのIDを取得する必要があります(永続化されたオブジェクトをフラッシュした後にのみ取得します)。次に、md5を生成し、それをデータベースに再度保存します。

画像へのリンクは一般公開されているはずなので、認証されたユーザーに何らかの許可ルールで画像を表示させることはできません。

4

2 に答える 2

7

あなたはおそらくDoctrineのイベントについてすでに知っているでしょう。あなたにできること:

postPersistイベントハンドラーを使用します。これはDB挿入後に発生するため、自動生成されたIDを使用できます。

EventManagerクラスはこれであなたを助けることができます:

class MyEventListener
{
    public function postPersist(LifecycleEventArgs $eventArgs)
    {
        // in a listener you have the entity instance and the 
        // EntityManager available via the event arguments
        $entity = $eventArgs->getEntity();
        $em = $eventArgs->getEntityManager();

        if ($entity instanceof User) {
            // do some stuff
        }

    }
}

$eventManager = $em->getEventManager():
$eventManager->addEventListener(Events::postPersist, new MyEventListener());

Userたとえば、がすでにあるかどうかを必ず確認してくださいImage。そうでない場合、イベントリスナーでflushを呼び出すと、無限ループに陥る可能性があります。

もちろんUser、インラインpostPersisteventHandlerを使用してその画像作成操作をクラスに認識@HasLifecycleCallbacksさせ、マッピングを追加して、リクエストの最後に、たとえばシャットダウン関数で常にフラッシュすることもできますが、私の意見では、この種のものは別のリスナー。YMMV。

フラッシュする前、オブジェクトを作成した直後にエンティティIDが必要な場合、別のアプローチは、たとえばuuidを使用して、アプリケーション内のエンティティのIDを生成することです。

今、あなたは次のようなことをすることができます:

class Entity {
    public function __construct()
    {
        $this->id = uuid_create();
    }
}

これで、次の操作を行うだけでIDがすでに設定されています。

$e = new Entity();

そして、リクエストの最後にEntityManager::flushを呼び出すだけです。

于 2011-09-12T19:34:25.770 に答える
2

最後に、質問にコメントした@Armsの話を聞きました。
私はそのようなことをするためにサービスレイヤーを使い始めました。
これで、Imageエンティティを作成するメソッドがサービスレイヤーにあります。永続化とフラッシュを呼び出した後、サムネイルを生成するメソッドを呼び出します。

サービスレイヤーパターンは、そのようなものに適したソリューションです。

于 2012-04-17T10:05:17.933 に答える