我在我的Cake应用程序中构建了一个简单的Notification系统,我想要一个函数,当我调用某个方法时会创建一个新的通知。因为这不是用户实际上直接访问的东西而且只是数据库逻辑,我把它放在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添加方法中想到了 :
if($this->save($this->request-data){
$this->Notification->_createNotification($userId,'Test','Test');
}
但是受到保护我将无法从NotificationsController外部访问该方法。我也使用相同的语法,就像我从一个模型调用一个函数,所以再次感觉不对。
希望有人可以帮助我,让我回到正轨,因为这对我来说是个新领域。
答案 0 :(得分: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);
}
所以这通常不是蛋糕的方式..
答案 1 :(得分:1)
根据定义,模型中的方法不是“可公开访问的”。用户无法调用或调用模型中的方法。用户只能启动控制器操作,而不能启动模型中的任何操作。如果不从任何控制器调用模型方法,则永远不会调用它。所以忘记问题的“非公开”部分。
您的问题是您在模型中工作,就像您在控制器中一样。模型中没有request
个对象。您只需将数据数组传递给模型方法并保存该数组。无需$this->request
。只需定期array()
,将控制器传递的数据放在那里并保存。
答案 2 :(得分:0)
整个方法在MVC上下文IMO中完全错误,并且对使用CakePHP事件系统感到尖叫。因为你想要的实际上是触发某种事件。阅读http://book.cakephp.org/2.0/en/core-libraries/events.html
触发事件并附加一个全局事件侦听器,它将侦听此类事件并在事件发生时执行它应该执行的任何操作(将某些内容保存到db)。它干净,灵活,可扩展。
如果你为你的应用程序做了一个适当的MVC堆栈,那么大多数(如果不是全部)事件也应该从模型中触发,就像成功保存帖子一样。
答案 3 :(得分: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是仅提供信息的通知,则该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的人有用在构建原型应用程序时从模型运行函数。
记住没有什么可以阻止你将来改进的事情!
答案 4 :(得分: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();
我使用这种函数来做与数据提交或阅读无关的事情,所以我决定将它们保存在app_controller中。在我的项目中,这些功能用于向用户提交电子邮件,例如..或者将用户操作从不同的控制器发布到Facebook。
希望我能让某人对此感到高兴;)但如果您计划制作很多这些功能,那么将它们放在模型中会好得多!