CakePHP中的非公共可访问函数

CakePHP中的非公共可访问函数,php,cakephp,Php,Cakephp,我已经在我的Cake应用程序中构建了一个简单的通知系统,我希望有一个功能,在我调用某个方法时创建一个新的通知。因为这不是用户实际直接访问的内容,而是唯一的数据库逻辑,所以我将其放在通知模型中,如下所示: class Notification extends AppModel { public $name = 'Notification'; public function createNotification($userId, $content, $url) {

我已经在我的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添加方法中考虑了

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

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

}
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;
    }
}
但是由于受到保护,我将无法从NotificationsController外部访问该方法。此外,我使用的语法与从模型调用函数的语法相同,因此再次感觉它不正确


希望有人能帮助我走出困境,让我回到正轨,因为这对我来说是一个新领域。

控制器应该将所有数据传递给模型

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

因此,这通常不是简单的方法。

根据定义,模型中的方法不是“可公开访问的”。用户不能调用或调用模型中的方法。用户只能启动控制器操作,而不能启动模型中的任何操作。如果没有从任何控制器调用模型方法,则永远不会调用它。所以,忘掉问题的“非公开”部分吧


您的问题是,您在模型中工作,就像在控制器中一样。模型中没有
请求
对象。您只需将数据数组传递到model方法并保存该数组。不需要
$this->request
。只需制作一个常规的
数组()
,将控制器传递的数据放入其中并保存。

整个方法在MVC上下文中是完全错误的,需要使用CakePHP事件系统。因为你想要的实际上是触发某种事件。阅读

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


如果你为你的应用程序做了一个合适的MVC堆栈,那么大多数(如果不是全部的话)事件(又称通知)都应该从一个模型中触发,例如,当一篇文章成功保存时。

这就是我最后要做的。当然,它并不迷人。它符合我的要求,是一个很好的快速成功,因为通知只在少数几个方法中使用,所以我不会创建大量将来需要改进的代码

首先,要创建通知,请执行以下操作:

$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);
这将使用传递的内容在表中创建一条新记录,并将其状态设置为0(表示未读)和创建日期。然后,当用户访问通知页面时,通知被设置为已读

同样,这很可能不是解决这个问题的理想方案但是它可以工作并且很容易使用,并且对于学习CakePHP的其他人来说可能很有用,因为他们在构建原型应用程序时希望从模型中运行函数


记住,没有什么能阻止你在未来改进

首先,您可以通过以下方式改进上一个解决方案以执行一次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)时,我也遇到了这个问题。 (我想在任何其他控制器中使用控制器的功能。) 因为我不知道/研究这样的代码应该放在哪里,我在一个非常大的项目中犯了一年多的错误。因为这个项目实在太大了,我决定不做了我就是这么做的:

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);
        }
    }
我向app\u controller.php添加了一个函数(没有视图,带下划线):

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

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

}
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;
    }
}
这样,您可以通过以下方式从通知控制器和Posts控制器访问该功能:

$this->_doSomething();
我使用这种函数来做与数据提交或读取无关的事情,所以我决定将它们保存在app_控制器中。在我的项目中,这些功能用于向用户提交电子邮件,例如。。或者从不同的控制器向facebook发布用户操作


希望我能让别人满意;)但是,如果您计划制作大量这些函数,那么最好将它们放在模型中

很好,你删除了这个问题,只是为了在10分钟后重新提交,而没有对这个主题的研究提出你应得的所有评论。我甚至没有因此否决你的问题——只是为了澄清一下。@mark这些评论是居高临下的,没有任何帮助。并不是每个人都像你一样了解CakePHP,当人们问别人觉得简单但对提问者来说可能不明显的问题时,寻求帮助和建议的人不应该觉得自己受到了欺负和庇护。