使用 AJAX 和 CakePHP 保存数据

Posted

技术标签:

【中文标题】使用 AJAX 和 CakePHP 保存数据【英文标题】:Save data using AJAX and CakePHP 【发布时间】:2011-09-11 05:12:18 【问题描述】:

我今天花了很多时间研究如何在 cakephp 中使用 ajax 请求来保存数据,现在我知道了,cakephp 网站上的文档似乎有点缺乏这个特定主题。

我有几个可排序的列表,我需要在排序时保存每个列表项的位置。我有一个 ajax 请求设置如下,在移动项目时触发:

$.ajax(                    
        url: "/orders/save_column_order",
        type:"POST",                                        
        data:"data="+data
       );

控制器中引用的函数是:

function save_column_order()
    if($this->RequestHandler->isAjax())

             SAVE STUFF...

        
  

我已经设置了助手等:

var $helpers = array('html','Form','Js');
var $components = array('Session','Email','RequestHandler');

而且它不工作......

所以我的问题是:

1) 向控制器中的操作发送 ajax 请求的当前 url 是什么?是简单的 /controller/action 吗?

2) 我还需要对控制器做什么才能访问 ajax 数据?

奖金:

3) 有没有办法在 CakePHP 框架中包含一个引用数据库设置的自定义 php 文件,以便我可以手动更新我的 mysql 数据库?

【问题讨论】:

【参考方案1】:

你们很亲密。

1.) URL 就是 /controller/action。数据在 $this->data 中传递,并且神奇地在操作中可用。 **由于您在帮助程序中列出了“Js”而不是“javascript”,我假设您使用的是 Cake 1.3.x 和 jQuery,因为 jQuery 是 Cake 1.3 的默认值,而 Js 取代了 Javascript/Ajax。

-- 修复你的助手:

var $helpers = array('Html', 'Form', 'Js'=>array("Jquery"));

-- 修复你的 jQuery:

$.ajax(
    url:'/orders/save_column_order',
    type:'POST',
    data:data
);

2.) 使用 Cake 的魔法:

function save_column_order() 
    if ($this->data != null) 
        $this->Model->save($this->data);
    // whatever else needs doing...
    

-- 因为你在做 ajax,你可能不想要 Cake 的默认视图渲染行为(只是一个猜测。)如果你想渲染任何视图,它可能只是一个 ajax 回调的标记片段, 所以你可能想把它放在一个元素中而不是一个完整的视图中:

function save_column_order() 
    // ...
    /* arg 1 - you can specify any view or element you like. 
       arg 2 - enforces your preferred request handling and layout */
    $this->set(compact('vars', 'for', 'view'));
    $this->render('/elements/new_column_order', 'ajax'); 

-- 否则,只是抑制渲染:

function save_column_order() 
    ...     
    $this->autoRender = false;

-- 如果您的保存不起作用,请确保 $this->data 的结构对 Cake-save 友好。如果您需要查看 $this->data 的内容,Cake 的内置调试(从您应用程序的任何位置)将帮助您理顺:

debug($this->data);

3.) 等等,什么?

不确定我是否正确理解您的问题,所以如果这不能涵盖您的问题,请说明您要做什么?

如果您的意思是,Cake 是否允许您手动更新表中的记录,是吗?虽然我不确定你为什么想要。 Cake 极其强大的内置 ORM 是框架的一半,它极其全面的魔力是另一半。

您可以使用 Model::sql() 方法直接写出 SQL,尽管不鼓励这样做,因为它不是非常 OOP 或可重用。

当您在模型中定义关联时,您可以将外键设置为 false 并指定像 Cake 的自动连接中的嵌套选择一样工作的条件。

如果你需要强制 join/s,Cake 的 $options['joins'] 给你完全精细的控制;如果默认的 LEFT 不足以满足您的需要,您可以指定任何类型的 JOIN。

您可以使用 $this->Model->bind() / unbind() 即时创建和中断模型绑定。您可以指定递归级别、应用可包含行为、指定要选择的字段和所有条件。

如果您需要一个子查询,而 Cake 无法正确处理,则 $dbo->buildStatement() 将构建您的 SQL 语句,而 $dbo->expression() 将触发它:

function intricate() 
    $dbo = $this->Rate->Status->getDataSource();
    $subquery = $dbo->buildStatement(
        array(
            'fields' => array('`Status`.`id`'),
            'table' => $dbo->fullTableName($this->Rate->Status),
            'alias' => 'Status',
            'limit' => null,
            'offset' => null,
            'joins' => array(),
            'conditions' => $subqueryConditions,
            'order' => null,
            'group' => null
            ),
        $this->Rate->Status
        );
    $subquery = "Status.id = (".$subquery.")";
    $status = $dbo->expression($subquery);
    $options['fields']=
        array(
            "Rate.id", "Rate.plan_id", "Rate.status_id","Rate.rate", "Plan.id", 
            "Plan.company_id", "Plan.name", "Company.id", "Company.name"
        );
    $options['conditions']=
        array(
            $status, 
            "Geographical.name LIKE '%$this->zip%'"
        );
    $rates = $this->Rate->find('all', $options);
    $this->set(compact('rates'));
    

——如果你的意思是——Cake 是否允许你即时交换数据库配置,是的。但是,这样做可能会变得非常顽固,尤其是当 Cake 的魔法是其中的一部分时。

您可以在 /app/config/database.php 中添加多个数据库配置 -

class DATABASE_CONFIG 
    var $default = array(
        'driver' => 'mysql',
        'persistent' => false,
        'host'=>'localhost',
        'login' => 'cake',
    'password' => 'icing',
        'database' => 'dev'
);
    var $offsite = array(
        'driver' => 'mysql',
        'persistent' => false,
        'host' => '11.22.33.44', // or whatever
        'login' => 'cake',
        'password' => 'frosting',
        'database' => 'live'
);

-- 根据您的情况的复杂性,在您的控制器/模型中切换它们会变得有点紧张:

// Model::getDataSource()->configKeyName holds whichever db config you're using
if ($this->Model->getDataSource()->configKeyName != 'default') 
    // do something, for example, change models, tables, reload schema, etc.
    $this->loadModel('Special')
    $this->Model->table = 'extras';
    $this->Model->schema(true);
 else 
    // predictably, Model::setDataSource($configKey) changes configs
    $this->Model->setDataSource('offsite');

-- 如果这是你的意思,我可以粘贴我几周前写的一段代码,要求我将 ajax 表单提交(在表单完成的 2 个阶段)保存到 2 个数据库中的 3 个表(一个为我的Cake 应用程序,另一个服务于旧版 CodeIgniter 应用程序)展示了所有这些花哨的步法以及一些很好的老式 Cake 魔术连接保存/更新快捷方式。 (我还必须生成选择性电子邮件,最后,触发一个 REST 请求,将新插入的记录的 id/s 传递给 CI 应用程序以触发它的处理。哇!)

无论如何,HTH。 :)

【讨论】:

非常感谢您的帮助!我已经进行了您所说的更改,但是我现在从 ajax 请求中收到了 404 错误。多亏了你,我离让它工作更近了,知道 404 可能是什么吗?回覆。 3)你绝对正确,它不是很蛋糕,我完全忘记了自定义 sql 语句 - 我认为自定义 sql 是我做错了什么的标志,现在我不需要使用它!还有你的权利,我正在使用 JQuery 和 cake 1.3。 Np。错误 404 通常表示某些东西已关闭 - 可能是权限,还是路由错误?否则 Cake 会抛出 Missing Controller / Action / View / 不管什么。每当 Cake 发出 404 错误时,我都会直接查看我的错误日志——首先是 Cake 的,然后是 Apache 的——看看它试图提取什么。检查所有权/权限,查找文件/类名中的拼写错误,所有这些小东西。如果您使用的是 Auth,请将您的 ajax 控制器操作添加到您的允许列表中。 Cake 的 debug() 是救命稻草,在调试 cake ajax 问题方面,没有什么比 FirePHP(与 Ca​​ke 集成)更好的了。 你是救生员和英雄!我有一个愚蠢的 url 问题,给了我 404。非常感谢。【参考方案2】:
    是的,就这么简单。
      要访问您发送的数据,您可以像往常一样使用$this->data 访问数据 为什么不使用phpmyadmin 之类的工具?

【讨论】:

phpMyAdmin 是一场安全噩梦。完全不适合生产服务器。 IME,团队开发服务器的最后选择/临时解决方案。 此外,直接访问 db manip 解决方案实际上只适合开发人员类型的用户。 在无限的现实场景中,应用程序必须解决复杂/奇异的数据库和数据源设置和操作的需求。我的项目-> 完美示例:当前的逐步淘汰/迁移阶段意味着同时处理 Cake 和 CI 的数据库。 2 个框架、2 个数据库/服务器(表略有不匹配!)、3 个模型、白名单、重新加载模式等......【参考方案3】:
 public function add_project() 
    $this->autoRender = false;
    $this->layout = 'ajax';
    if ($this->RequestHandler->isAjax()) 
        $this->Project->set($this->request->data);
        $this->request->data['Project']['user_id'] = $this->Session->read('Auth.User.id');
        $this->request->data['Project']['created_by'] = $this->Session->read('Auth.User.id');
        $this->request->data['Project']['updated_by'] = $this->Session->read('Auth.User.id');
        //$this->request->data['Skill']['accept_decline'] = 0;
        $this->User->set($this->request->data['Project']);
        Configure::write('debug', 0);
        if ($this->Project->validates(array('fieldList' => array('project_title', 'show_on', 'summary')))) 

            if ($this->Project->save($this->request->data, false)) 
                $response['status'] = 'succses';
                $response['message'] = 'data  sent';
                echo json_encode($response);
                exit();
             else 
                $response['status'] = 'error';
                $response['model'] = 'Project';
                $response['message'] = 'data not sent';
                echo json_encode($response);
                exit();
            
         else 
            $response['status'] = 'invalid';
            $response['model'] = 'Project';
            $errors = $this->Project->validationErrors;
            $response['errors'] = $errors;
            echo json_encode($response);
            exit();
        
    

【讨论】:

以上是关于使用 AJAX 和 CakePHP 保存数据的主要内容,如果未能解决你的问题,请参考以下文章

cakephp 在不使用视图的情况下保存 HABTM 关系的数据

使用 Cakephp model::save() 将数据保存到不同的数据库表

CakePHP patchEntity 不保存数据(“通过”关联)

CakePHP 在 HABTM 字段中保存数据

cakePHP 使用 hasMany 函数保存所有数据

将数据保存到 2 个表中 cakephp 3