我的数据库架构:
CREATE TABLE IF NOT EXISTS `costumers` (
  `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `person_id` smallint(5) unsigned NOT NULL,
  `status` tinyint(1) unsigned NOT NULL DEFAULT 1,
  PRIMARY KEY (`id`),
  KEY `fk_costumers_persons_idx` (`person_id`)
);
CREATE TABLE IF NOT EXISTS `persons` (
  `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  `phone` char(10) DEFAULT NULL,
  `mobile` char(10) DEFAULT NULL,
  `email` varchar(64) NOT NULL,
  `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `data_updated` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
);
这是我的控制器代码:
class Test extends CI_Controller {
    public function index()
    {
        // Faking POST values
        $_POST = array(
            // Person info
            'name' => 'Paulo Freitas',
            'phone' => 'xxxxxxxxxx',
            'email' => 'xx@xxxxxxxxxxxx.xx',
            // Costumer info
            'status' => 2
        );
        // Utility function
        function factory_from($class, $fields)
        {
            $CI =& get_instance();
            $input = array();
            foreach ($fields as $field) {
                $input[$field] = $CI->input->post($field) ?: null;
            }
            $obj = new $class;
            $obj->from_array($input);
            return $obj;
        }
        // Save person
        $person = factory_from('Person', array(
            'name',
            'phone',
            'mobile',
            'email'
        ));
        $person->save();
        // Save costumer
        $costumer = factory_from('Costumer', array(
            'status'
        ));
        $costumer->save($person);
        var_dump($costumer->id); // New costumer id
    }
}
我是 CodeIgniter 的 DataMapper ORM 的新手,我对如何确保仅在成功存储相关客户时才能确保存储一个人有点迷茫。例如,如果我验证一个客户status但它失败了,为了存储我以前必须存储其相关人员的客户......如果我不能存储客户,我该如何回滚新的人?(在实际场景中,我有一个persons、和表,只有在全部成功时才需要存储它们)individualsuserscostumers
我如何在这里使用交易?是的,我已经阅读了有关使用事务的文档,但我不知道,现在我已经坚持了几个小时。先感谢您!
更新
我稍微破解了我的控制器,现在它似乎可以工作了,有没有更好的方法来实现这一点?
新控制器:
class Test extends CI_Controller {
    public function index()
    {
        // Faking POST values
        $_POST = array(
            // Person info
            'name' => 'Paulo Freitas',
            'phone' => 'xxxxxxxxxx',
            'email' => 'xx@xxxxxxxxxxxx.xx',
            // Costumer info
            'status' => 2
        );
        // Utility functions
        function factory_from($class, $fields)
        {
            $CI =& get_instance();
            $input = array();
            foreach ($fields as $field) {
                $input[$field] = $CI->input->post($field) ?: null;
            }
            $obj = new $class;
            $obj->from_array($input);
            return $obj;
        }
        function get_errors()
        {
            $errors = array();
            foreach (func_get_args() as $obj) {
                $errors += $obj->error->all;
            }
            return $errors;
        }
        // Initialize person
        $person = factory_from('Person', array(
            'name',
            'phone',
            'mobile',
            'email'
        ));
        // Initialize costumer
        $costumer = factory_from('Costumer', array(
            'status'
        ));
        // Start transaction
        $person->trans_begin();
        if ($person->save()
                && $costumer->save($person)) {
            // If we can save all data, commit!
            $person->trans_commit();
            // Dump new costumer id
            var_dump($costumer->id);
        } else {
            // Otherwise, rollback all!
            $person->trans_rollback();
            // Dump all errors
            var_dump(get_errors($person, $costumer));
        }
    }
}