-4

Cakeアプリに簡単な通知システムを構築しました。特定のメソッドを呼び出すと、新しい通知を作成する関数が必要です。これはユーザーが実際に直接アクセスするものではなく、データベースロジックにすぎないため、次のように通知モデルに配置しました。

class Notification extends AppModel
{
    public $name = 'Notification';

    public function createNotification($userId, $content, $url)
    {
        $this->create();

        $this->request->data['Notification']['user_id'] = $userId;
        $this->request->data['Notification']['content'] = $content;
        $this->request->data['Notification']['url'] = $url;

        $result = $this->save($this->request->data);

        if ($result)
        {
            $this->saveField('datetime', date('Y-m-d H:i:s'));
            $this->saveField('status', 0);
        }
    }
}

そして、アプリ内で通知を作成したいときはいつでも、次のようにします。

$this->Notification->createNotification($userId,'Test','Test');

しかし、これは機能しません!コントローラーはモデルと正常に通信していますが、データベースに行が作成されません...理由はわかりません...しかし、コード内のすべてのコードを実行するだけで、これが間違っているように見えますモデルを作成し、アプリ全体で呼び出します。

編集:以下の回答とコメントに基づいて、通知コントローラーで保護されたメソッドを作成するために次のコードを試しました。

protected function _createNotification($userId, $content, $url)
    {
        $this->Notification->create();

        $this->request->data['Notification']['user_id'] = $userId;
        $this->request->data['Notification']['content'] = $content;
        $this->request->data['Notification']['url'] = $url;

        $result = $this->save($this->request->data);

        if ($result)
        {
            $this->saveField('datetime', date('Y-m-d H:i:s'));
            $this->saveField('status', 0);
        }
    }

今でも私を困惑させているのは(これが他の人にとって非常に単純である場合はお詫びしますが、以前にCakePHPで保護されたメソッドを使用したことがありません)、別のコントローラーからこれを呼び出すにはどうすればよいですか?たとえば、PostsControllerにメソッドがあり、保存が成功したときに通知を作成したい場合、これを行うにはどうすればよいですか?

PostsControllerのaddメソッドで考えました:

if($this->save($this->request-data){

    $this->Notification->_createNotification($userId,'Test','Test');

}

しかし、保護されているため、NotificationsControllerの外部からメソッドにアクセスすることはできません。また、モデルから関数を呼び出す場合と同じ構文を使用しているため、これも正しくありません。

これは私にとって新しい分野なので、誰かが私を助けて、私を軌道に戻すことができれば幸いです。

4

5 に答える 5

3

コントローラーはすべてのデータをモデルに渡す必要があります

$this->createNotification($this->request->data);

モデルはデータを使用できます。

public function createNotification(array $data) {
    $key = $data[$this->alias]['key'];
    $data[...] = ...;

    $this->create();
    return $this->save($data);
}

モデル内からコントローラー (および/またはその要求オブジェクト) にアクセスしようとすることは決してありません。

もちろん、他のモデルからメソッドを呼び出すこともできます。

public function otherModelsMethod() {
    $this->Notification = ClassRegistry::init('Notification');

    $data = array(
         'Notification' => array(...)
    );
    $this->Notification->createNotification($data);
}

また、メソッドを冗長にすることもできますが、通常、引数が増えると、読み取り/理解/維持が難しくなります。

public function createNotification($userId, $content, $url) {
    $data = array();
    // assign the vars to $data
    $data['user_id'] = $userId;
    ...

    $this->create();
    return $this->save($data);
}

だから、これはしばしばケーキの方法ではありません..

于 2012-12-17T13:44:15.620 に答える
1

モデル内のメソッドは、定義上、「パブリックにアクセス可能」ではありません。ユーザーは、モデル内のメソッドを呼び出したり呼び出したりすることはできません。ユーザーはコントローラーのアクションのみを開始できます。モデル内の何も開始することはできません。どのコントローラーからもモデル メソッドを呼び出さない場合、呼び出されることはありません。したがって、質問の「非公開」の部分は忘れてください。

あなたの問題は、コントローラーにいるかのようにモデルで作業していることです。requestモデルにオブジェクトはありません。モデル メソッドにデータ配列を渡して、その配列を保存するだけです。の必要はありません$this->request。通常の を作成array()し、そこにコントローラーから渡されたデータを入れて保存します。

于 2012-12-17T15:38:34.137 に答える
0

これが私がやったことです。それは確かに魅力的ではありませんが。それは私がやりたいことのために機能し、通知はいくつかの方法でしか使用されないため、将来的に改善が必要な大量のコードを作成していないため、素早い勝利です.

最初に通知を作成するには、次のことを行います。

$notificationContent = '<strong>'.$user['User']['username'].'</strong> has requested to be friends with you.';
$notificationUrl = Router::url(array('controller'=>'friends','action'=>'requests'));
$this->Notification->createNotification($friendId,$notificationContent,$notificationUrl);

ここで、必要なコンテンツと、ユーザーが何かを実行できる URL を渡します。この場合は、通知されたフレンド リクエストを確認します。情報のみの通知の場合、URL は null になる可能性があります。

createNotification 関数はモデルのみにあり、次のようになります。

public function createNotification($userId, $content, $url = null)
{
    $this->saveField('user_id',$userId);
    $this->saveField('content',$content);
    $this->saveField('url',$url);
    $this->saveField('datetime', date('Y-m-d H:i:s'));
    $this->saveField('status', 0);
}

これにより、渡されたコンテンツでテーブルに新しいレコードが作成され、そのステータスが 0 (未読を意味する) に設定され、作成された日付が設定されます。ユーザーが通知ページにアクセスすると、通知は既読として設定されます。

繰り返しになりますが、これはおそらくこの質問で概説されている問題の理想的な解決策ではありません...しかし、それは機能し、操作が簡単であり、プロトタイプアプリを構築するときにモデルから関数を実行したいCakePHPを学んでいる他の人に役立つかもしれません.

今後の改善を妨げるものは何もないことを忘れないでください。

于 2012-12-17T19:37:58.113 に答える
0

全体のアプローチは、MVC コンテキスト IMO では完全に間違っており、CakePHP イベント システムの使用について悲鳴を上げています。あなたが望むのは、実際には何らかのイベントをトリガーすることだからです。http://book.cakephp.org/2.0/en/core-libraries/events.htmlを読む

イベントをトリガーし、この種のイベントをリッスンし、イベントが発生したときに必要なことを実行する (データベースに何かを保存する) グローバル イベント リスナーをアタッチします。クリーンで柔軟性があり、拡張可能です。

アプリに対して適切な MVC スタックを実行した場合、すべてではないにしても、ほとんどのイベント (通知) は、たとえば投稿が正常に保存されたときのように、モデル内から発生するはずです。

于 2012-12-17T18:58:58.683 に答える
0

まず、次の方法で、(5 ではなく) 1 つの save() を実行するように最後のソリューションを改善できます。

public function createNotification($userId, $content, $url = null){

    $data = array(
        'user_id' => $userId,
        'content' => $content,
        'url' => $url,
        'datetime' => date('Y-m-d H:i:s'),
        'status' => 0
    );

    $this->create();
    $this->save($data);
}

1 年以上前に CakePHP(1.3) のプログラミングを始めたときも、この問題がありました。(コントローラーの機能を他のコントローラーで使用したかったのです。) このようなコードを配置する場所がわからなかったため、非常に大きなプロジェクトで1年以上間違っていました。このプロジェクトは本当に大きなものなので、そのままにしておくことにしました。これが私がすることです:

app_controller.phpに関数 (ビューなし、下線付き)を追加します。

class AppController extends Controller {
    //........begin of controller..... skipped here

    function _doSomething(){
        //don't forget to load the used model
        $this->loadModel('Notification');
        //do ur magic (save or delete or find ;) )
        $tadaaa = $this->Notification->find('first');
        //return something
        return $tadaaa;
    }
}

このようにして、通知コントローラーと投稿コントローラーから関数にアクセスできます。

$this->_doSomething();

私はこの種の関数を使用して、データの送信や読み取りとは関係のないことを行うので、それらを app_controller に保持することにしました。私のプロジェクトでは、これらの関数を使用して、たとえばユーザーに電子メールを送信したり、さまざまなコントローラーから Facebook にユーザー アクションを投稿したりします。

これで誰かを幸せにすることができれば幸いです;)しかし、これらの関数をたくさん作ることを計画している場合は、それらをモデルに配置する方がはるかに良いでしょう!

于 2013-02-05T12:01:38.760 に答える