-4

我在我的 Cake 应用程序中构建了一个简单的通知系统,我希望有一个函数可以在我调用某个方法时创建一个新通知。因为这不是用户实际直接访问的东西,而只是数据库逻辑,所以我将它放在 Notification 模型中,如下所示:

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

整个方法在 MVC 上下文 IMO 中是完全错误的,并且为使用 CakePHP 事件系统而尖叫。因为你想要的实际上是触发某种事件。阅读http://book.cakephp.org/2.0/en/core-libraries/events.html

触发一个事件并附加一个全局事件侦听器,该侦听器将侦听此类事件并在事件发生时执行它应该执行的任何操作(将某些内容保存到数据库)。它干净、灵活且可扩展。

如果你为你的应用程序做了一个适当的 MVC 堆栈,如果不是全部的话,事件又名通知应该从模型中触发,例如当一个帖子成功保存时。

于 2012-12-17T18:58:58.683 回答
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

首先,您可以通过以下方式改进最后一个解决方案以执行一次 save() (而不是 5 次):

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);
}

当我一年多前开始编程 CakePHP(1.3) 时,我也遇到了这个问题。(我想在任何其他控制器中使用控制器的功能。)因为我不知道/研究在哪里放置这样的代码,所以我在一个非常大的项目中做错了一年多。因为这个项目真的很大,所以我决定就这样离开它。这就是我所做的:

我向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;
    }
}

通过这种方式,您可以从 Notification 控制器和 Posts 控制器访问该功能:

$this->_doSomething();

I use this kind of functions to do things that have nothing to do with data submittance or reading, so i decided to keep them in the app_controller. In my project these functions are used to submit e-mails to users for example.. or post user actions to facebook from different controllers.

Hope I could make someone happy with this ;) but if you're planning to make a lot of these functions, it would be much better to place them in the model!

于 2013-02-05T12:01:38.760 回答