无脂肪框架; SQL Mapper插入两次

时间:2015-02-12 14:53:27

标签: php mysql fat-free-framework

当我尝试基于它构建自己的框架时,F3的SQL Mapper引发了奇怪的问题。

当我尝试将行插入MySQL数据库时,它会被插入两次。我通过将echo设置为beforeinsert方法进行了最简单的调试,该方法被触发一次。那么......我做错了什么导致行加倍?

控制器(特定代码):

$faq = new \FaqModel();
$faq->question = $params['q'];
$faq->answer = $params['a'];
$faq->save();
$id = $faq->get('_id');
if (isset($id))
    $this->status = 'success'; // this is shown
else
    $this->status = 'nope, not working';

FaqModel.php(是的,没有,这里)

class FaqModel extends \BaseModel
{
    public function __construct()
    {
        parent::__construct('faq');
    }
}

BaseModel.php(我想到这里,但beforeinsert()被调用一次):

abstract class BaseModel extends \DB\SQL\Mapper
{
    public function __construct($table)
    {
        $f3 = \Base::instance();
        $this->db=new \DB\SQL(
            'mysql:host='.$f3->get('db_host').';port='.$f3->get('db_port').';dbname='.$f3->get('db_name'),
            $f3->get('db_user'),$f3->get('db_pass'));
        parent::__construct($this->db,DB_PREFIX.$table);
        $this->table = DB_PREFIX.$table;
        $this->beforeinsert(function($me) {
            echo 'before insert <br/>';
            $me->createdAt = date('Y-m-d H:i:s');
        });
        echo 'construct <br/>';
    }
    // some loading methods here not related to problem
}

输出很简单:

construct
before insert
success 

并且没有webniffers中显示的重定向。但我仍然得到我的数据库重复行。


编辑:

好的,现在它比我们更奇怪了。我连续执行了两个添加请求。发生的事情是:

1)在第一次请求时,添加了两行:

41  testing         db_testing  2015-02-13 09:08:21     2015-02-13 09:08:21
42  testing         db_testing  2015-02-13 09:08:21     2015-02-13 09:08:21

2)在第二次请求时,添加了三个行:

43  testing         db_testing  2015-02-13 09:10:53     2015-02-13 09:10:53
44  another_test    db_why      2015-02-13 09:11:04     2015-02-13 09:11:04
45  another_test    db_why      2015-02-13 09:11:05     2015-02-13 09:11:05

我不知道发生了什么。

3 个答案:

答案 0 :(得分:1)

您到此特定控制器的路由怎么样?可能是你在GET请求上这样做了吗?有些浏览器会在实际的GET请求之前发送一个额外的HEAD请求。框架自动处理,调用您的GET控制器,插入行一次,并仅减少对标头的响应。然后是GET请求,它再次执行所有操作,从而产生第二行。这可以解释您的应用行为。

如果是这样,您可以添加一项检查,看看F3 VERB var是否包含GET来解决HEAD请求。

答案 1 :(得分:1)

这是一个老问题,但是,fwiw,我怀疑OP的问题是每次保存后都不会发出mapper reset()调用。从技术上讲,我认为映射器对象的行为,如果你没有重置它,是'未定义的',但是有一点意义,映射器会记住最后一条记录,并且有点理解它后面的新记录。

无论如何,F3映射器的最佳实践是实例化新的映射器或在db调用之间发出重置。我不能谈论性能权衡,除了假设reset()无论它做什么都必须比站起来一个全新的对象便宜。

答案 2 :(得分:0)

你应该做的就是在你实例化课程时立即致电reset()

最佳做法

  • 在模型外部实例化您的数据库,然后调用parent::__construct($db,'faq')
  • 在构造之外创建触发器 function addCreated() { echo 'before insert <br/>'; $this->createdAt = date('Y-m-d H:i:s'); }

  • 将您的触发器添加为$this->beforeinsert([$this,'addCreated']);

完整的基础现在是: abstract class BaseModel extends \DB\SQL\Mapper { public function __construct($table) { $f3 = \Base::instance(); $db = $f3->get('db') parent::__construct($db,DB_PREFIX.$table) $this->beforeinsert([$this,'addCreated']); echo 'construct <br/>'; } // some loading methods here not related to problem }