使用AJAX和CakePHP保存数据

时间:2022-04-16 13:42:35

I've spent today researching how to save data using an ajax request in cakephp and have got now where, the documentation on the cakephp website seems a bit lacking for this particular topic.

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

I have several sortable lists and I need to save the position of each list item when one is sorted. I have an ajax request set up as follows that is triggered when an item is moved:

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

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

and the referenced function in the controller is:

并且控制器中引用的函数是:

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

             SAVE STUFF...

        }
  }

I have the helpers etc. set up:

我有帮助等设置:

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

And its not working...

它不起作用......

So my questions are:

所以我的问题是:

1) What is the current url for sending an ajax request to an action in a controller? Is it simply /controller/action?

1)将ajax请求发送到控制器中的动作的当前URL是什么?它只是/控制器/行动?

2) What else do I need to do to the controller to access the ajax data?

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

BONUS:

奖金:

3) Is there a way to include a custom php file in the CakePHP framework that references the database settings so I can manually update my mysql database?

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

3 个解决方案

#1


24  

You were very close.

你非常接近。

1.) URL is simply /controller/action. Data is passed in $this->data and is magically available in the action. **Since you list 'Js' in your helpers instead of 'Javascript', I'm presuming you're using Cake 1.3.x and jQuery, because jQuery is the default with Cake 1.3 and Js replaced Javascript / Ajax.

1.)URL只是/ controller / action。数据在$ this-> data中传递,并且在操作中神奇地可用。 **因为你在助手中列出'Js'而不是'Javascript',我假设你正在使用Cake 1.3.x和jQuery,因为jQuery是Cake 1.3的默认值,而Js取代了Javascript / Ajax。

-- Fix your helpers:

- 修复你的助手:

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

-- Fix your jQuery:

- 修复你的jQuery:

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

2.) Use Cake's magic:

2.)使用Cake的魔力:

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

-- Since you're doing ajax, you probably do NOT want Cake's default view-rendering behavior (just a guess.) If you want to render any view at all, it's probably just a snip of markup for an ajax callback, so you probably want to place it in an element rather than a full-blown view:

- 因为你正在做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'); 
}

-- Otherwise, just suppress rendering:

- 否则,只是抑制渲染:

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

-- If your save isn't working, make sure the structure of $this->data is Cake-save-friendly. If you need to view the contents of $this->data, Cake's built-in debugging (from anywhere in your app) will help you get straightened out:

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

debug($this->data);

3.) Wait, what?

3.)等等,什么?

Not sure I understand what you're asking correctly, so if this does not cover your question, please clarify what you're trying to do?

我不确定我理解你的问题是正确的,所以如果这不能解决你的问题,请澄清你想要做什么?

If you mean, will Cake allow you to manually update records in a table/s, yes? Although I'm not sure why you would want to. Cake's extremely powerful built-in ORM is half the point of the framework, and its extremely comprehensive magic is the other half.

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

You can scribble off straight SQL with the Model::sql() method, although this is discouraged it's not very OOP or reusable.

你可以使用Model :: sql()方法来划掉直接的SQL,虽然不鼓励它不是非常OOP或可重用。

When you define associations in your model, you can set the foreign key to false and specify conditions that work like a nested select in Cake's auto joins.

在模型中定义关联时,可以将外键设置为false,并指定与Cake的自动连接中的嵌套选择类似的条件。

If you need to force join/s, Cake's $options['joins'] give you completely granular control; you can designate any type of JOIN if the default LEFT isn't good enough for what you need to do.

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

You can make and break model bindings on the fly with $this->Model->bind() / unbind(). You can specify the level of recursion, apply Containable behavior, specify the fields to select and all conditions.

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

If you need a subquery and Cake just can't get it right, $dbo->buildStatement() will construct your SQL statement and $dbo->expression() will fire it:

如果你需要一个子查询而且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'));
    }

-- If you mean - will Cake allow you to swap out database configurations on the fly, yes. However, doing so can get pretty hardcore, especially when Cake's magic is part of the situation.

- 如果你的意思是 - Cake会允许你动态交换数据库配置,是的。然而,这样做可能会变得非常核心,特别是当蛋糕的魔力成为这种情况的一部分时。

You can add multiple db configs in /app/config/database.php -

您可以在/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'
);
}

-- Switching between them in your controller / model is where things get a little intense, depending on the complexity of your situation:

- 在控制器/模型中切换它们是事情变得有点紧张的地方,具体取决于您的情况的复杂性:

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

-- If this is what you meant, I can paste a chunk of code I wrote a couple weeks ago requiring I save an ajax form submission (at 2 stages of form completion) to 3 tables in 2 databases (one serving my Cake application, the other serving a legacy CodeIgniter application) showing all this fancy footwork in action along with some good old-fashioned Cake magic join-through save/update shortcuts. (I also had to generate selective emails and finally, fire off a REST request passing the id/s of the newly inserted records to the CI application to trigger it's processing. Whew!)

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

Anyway, HTH. :)

无论如何,HTH。 :)

#2


0  

  1. Yes, it's simple as that.
    1. To access the data like you sent it you can access the data with $this->data as usual
    2. 要像访问它一样访问数据,您可以像往常一样使用$ this-> data访问数据
    3. Why don't you use tools like phpmyadmin?
    4. 你为什么不使用像phpmyadmin这样的工具?
  2. 是的,就这么简单。要像访问它一样访问数据,您可以像往常一样使用$ this-> data访问数据为什么不使用像phpmyadmin这样的工具?

#3


0  

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

#1


24  

You were very close.

你非常接近。

1.) URL is simply /controller/action. Data is passed in $this->data and is magically available in the action. **Since you list 'Js' in your helpers instead of 'Javascript', I'm presuming you're using Cake 1.3.x and jQuery, because jQuery is the default with Cake 1.3 and Js replaced Javascript / Ajax.

1.)URL只是/ controller / action。数据在$ this-> data中传递,并且在操作中神奇地可用。 **因为你在助手中列出'Js'而不是'Javascript',我假设你正在使用Cake 1.3.x和jQuery,因为jQuery是Cake 1.3的默认值,而Js取代了Javascript / Ajax。

-- Fix your helpers:

- 修复你的助手:

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

-- Fix your jQuery:

- 修复你的jQuery:

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

2.) Use Cake's magic:

2.)使用Cake的魔力:

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

-- Since you're doing ajax, you probably do NOT want Cake's default view-rendering behavior (just a guess.) If you want to render any view at all, it's probably just a snip of markup for an ajax callback, so you probably want to place it in an element rather than a full-blown view:

- 因为你正在做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'); 
}

-- Otherwise, just suppress rendering:

- 否则,只是抑制渲染:

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

-- If your save isn't working, make sure the structure of $this->data is Cake-save-friendly. If you need to view the contents of $this->data, Cake's built-in debugging (from anywhere in your app) will help you get straightened out:

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

debug($this->data);

3.) Wait, what?

3.)等等,什么?

Not sure I understand what you're asking correctly, so if this does not cover your question, please clarify what you're trying to do?

我不确定我理解你的问题是正确的,所以如果这不能解决你的问题,请澄清你想要做什么?

If you mean, will Cake allow you to manually update records in a table/s, yes? Although I'm not sure why you would want to. Cake's extremely powerful built-in ORM is half the point of the framework, and its extremely comprehensive magic is the other half.

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

You can scribble off straight SQL with the Model::sql() method, although this is discouraged it's not very OOP or reusable.

你可以使用Model :: sql()方法来划掉直接的SQL,虽然不鼓励它不是非常OOP或可重用。

When you define associations in your model, you can set the foreign key to false and specify conditions that work like a nested select in Cake's auto joins.

在模型中定义关联时,可以将外键设置为false,并指定与Cake的自动连接中的嵌套选择类似的条件。

If you need to force join/s, Cake's $options['joins'] give you completely granular control; you can designate any type of JOIN if the default LEFT isn't good enough for what you need to do.

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

You can make and break model bindings on the fly with $this->Model->bind() / unbind(). You can specify the level of recursion, apply Containable behavior, specify the fields to select and all conditions.

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

If you need a subquery and Cake just can't get it right, $dbo->buildStatement() will construct your SQL statement and $dbo->expression() will fire it:

如果你需要一个子查询而且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'));
    }

-- If you mean - will Cake allow you to swap out database configurations on the fly, yes. However, doing so can get pretty hardcore, especially when Cake's magic is part of the situation.

- 如果你的意思是 - Cake会允许你动态交换数据库配置,是的。然而,这样做可能会变得非常核心,特别是当蛋糕的魔力成为这种情况的一部分时。

You can add multiple db configs in /app/config/database.php -

您可以在/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'
);
}

-- Switching between them in your controller / model is where things get a little intense, depending on the complexity of your situation:

- 在控制器/模型中切换它们是事情变得有点紧张的地方,具体取决于您的情况的复杂性:

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

-- If this is what you meant, I can paste a chunk of code I wrote a couple weeks ago requiring I save an ajax form submission (at 2 stages of form completion) to 3 tables in 2 databases (one serving my Cake application, the other serving a legacy CodeIgniter application) showing all this fancy footwork in action along with some good old-fashioned Cake magic join-through save/update shortcuts. (I also had to generate selective emails and finally, fire off a REST request passing the id/s of the newly inserted records to the CI application to trigger it's processing. Whew!)

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

Anyway, HTH. :)

无论如何,HTH。 :)

#2


0  

  1. Yes, it's simple as that.
    1. To access the data like you sent it you can access the data with $this->data as usual
    2. 要像访问它一样访问数据,您可以像往常一样使用$ this-> data访问数据
    3. Why don't you use tools like phpmyadmin?
    4. 你为什么不使用像phpmyadmin这样的工具?
  2. 是的,就这么简单。要像访问它一样访问数据,您可以像往常一样使用$ this-> data访问数据为什么不使用像phpmyadmin这样的工具?

#3


0  

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