如何将Ajax查询与Silex一起使用


How to use Ajax queries with Silex?

为了构建我的新站点,我决定尝试Silex框架。我在医生那里读了很多书,所以直到现在我都没有遇到任何问题。

我正在制作一个投票系统,我想在Ajax中动态使用它。

所以,首先我宣布了路线:

routes.php

$app->match('/ajax/vote', mysite'Controller'HomeController::voteAction');

我注册了服务:

app.php

$app['dao.ajax'] = $app->share(function ($app) {
    return new mysite'DAO'AjaxDAO($app['db']);
});

然后,有一个相关的控制器:

HomeController.php

public function voteAction(Application $app, Request $request) {        
    $vote = new Vote();
    $vote->setVoteId($request->get('vote_id'));
    $vote->setBookId($request->get('book_id'));
    $vote->setVoterIp($request->get('IP'));
    $voteAction = $app['dao.ajax']->saveVote($vote);
    return $app['twig']->render('index.html.twig');
}

因此,当我点击投票按钮时,它应该(重新)呈现索引页面。

我的DAO类:

DAO.php

namespace mysite'DAO;
use Doctrine'DBAL'Connection;
abstract class DAO 
{
    private $db;
    public function __construct(Connection $db) {
        $this->db = $db;
    }
    protected function getDb() {
        return $this->db;
    }
    protected abstract function buildDomainObject($row);
}

然后,投票功能:

AjaxDAO.php

namespace mysite'DAO;
use mysite'Domain'Vote;
class AjaxDAO extends DAO 
{
    protected function buildDomainObject($row) {
        $vote = new Vote();
        $vote->setVoteId($row['vote_id']);
        $vote->setBookId($row['book_id']);
        $vote->setVoterIp($row['vt_ip']);
        return $vote;
    }
    public function saveVote(Vote $vote) {
        $voteData = array(
            'vote_id' => $vote->getVoteId(),
            'book_id' => $vote->getBookId(),
            'vt_ip' => $vote->getVoterIp()
        );
        $this->getDb()->insert('t_vote', $voteData);
    }
}

投票类:

Vote.php

namespace mysite'Domain;
class Vote
{
    private $id;
    private $vote_id;
    private $book_id;
    private $vt_ip;

    public function getId() {
        return $this->id;
    }
    public function setId($id) {
        $this->id = $id;
    }
    public function getVoteId() {
        return $this->vote_id;
    }
    public function setVoteId($vote_id) {
        $this->vote_id = $vote_id;
    }
    public function getBookId() {
        return $this->book_id;
    }
    public function setBookId($book_id) {
        $this->book_id = $book_id;
    }
    public function getVoterIp() {
        return $this->vt_ip;
    }
    public function setVoterIp($vt_ip) {
        $this->vt_ip = $vt_ip;
    }
}

现在,带有Ajax的jQuery:

vote.js

$('button').on('click', function like(e) {
    $(this).off('click');
    e.preventDefault();
    var vote_id = '{{ vote_id }}';
    var book_id = $(this).attr('data-book');
    var IP = '{{ getUserIp() }}';
    if ($(this).hasClass('active')) {
        $.ajax({
            type: 'POST',
            url: '/ajax/vote',
            data: {'POST_type': 'vote', 'book_id': book_id, 'IP': IP},
            success: function(html) {
                $('button').removeClass('active').addClass('disabled');
            },
            error: function() {
                alert('error');
            }
        });
    };
});

正如你可能已经理解的,当我点击"投票"按钮时,我会收到一个错误警报。当我访问链接mysite/ajax/pvote时,我会出现以下错误:

Notice: Undefined property: mysite'DAO'AjaxDAO::$request

我查看了官方文档和以前的StackOverflow问题,但我只发现了问题22011254,这对我没有帮助…

编辑:我刚刚读到Silex只支持Json与Ajax的数据交换。也许这就是问题所在?

值得检查ajax请求发送的头中有什么。在silex中,application/json请求不作为标准x-form来处理。你可以使用silex食谱中提到的解决方案来解决这个问题(这对2.*和1.3.*都有效)。

至于通知,我会开始看这里:

$vote->setVoteId($request->get('vote_id'));
$vote->setBookId($request->get('book_id'));
$vote->setVoterIp($request->get('IP'));

如果您正在进行一些非标准的post请求,那么这些$request->get方法调用可能会返回与您预期不同的东西(例如请求对象?)。由于您没有进行验证或消毒,您可能没有注意到。

你也可以改变这个:

$app->match('/ajax/vote', mysite'Controller'HomeController::voteAction');

至:

$app->post('/ajax/vote', mysite'Controller'HomeController::voteAction');

因为没有指定方法的CCD_ 4将匹配每种类型的请求。现在可能不重要,但以后会省去你的麻烦。

AjaxDAO.php方法saveVote中存在错误。您尝试使用此类中未定义的属性$this->request。更好地在控制器中设置投票字段,并将其传输到saveVote

HomeController.php

public function voteAction(Application $app, Request $request) {
    ...
    $vote = new Vote();
    $vote->setVoteId($request->get('vote_id'));
    $vote->setBookId($request->get('book_id'));
    $vote->setVoterIp($request->get('vt_ip'));
    $voteAction = $app['dao.ajax']->saveVote($vote);
    ...
}

AjaxDAO.php

public function saveVote(Vote $vote) {
    $voteData = array(
        'vote_id' => $vote->getVoteId(),
        ...
    );
    $this->getDb()->insert('t_vote', $voteData);
}

我没有使用过Silex,对它也不太熟悉,但我正在查看文档。

您可以为大多数HTTP方法创建控制器。只需在应用程序上调用以下方法之一:get、post、put、delete、patch

在HomeController.php中,您使用get(),这个HTTP方法不应该也用于ajax吗?

示例

$('button').on('click', function like(e) {
    $(this).off('click');
    e.preventDefault();
    var vote_id = 'Vote ID';
    var book_id = $(this).attr('data-book');
    var IP = getUserIp();
    if ($(this).hasClass('active')) {
        $.ajax({
            type: 'GET',
            url: '/ajax/vote?vote_id='+vote_id+'&book_id='+book_id+'vt_ip='+IP,
            success: function(html) {
                $('button').removeClass('active').addClass('disabled');
            },
            error: function() {
                alert('error');
            }
        });
    };
});