简体   繁体   English

使用CodeIgniter DataMapper ORM保存一对一关系

[英]Saving one-to-one relationships using CodeIgniter DataMapper ORM

My database schema: 我的数据库架构:

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`)
);

Here's my controller code: 这是我的控制器代码:

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
    }
}

I'm new to CodeIgniter's DataMapper ORM and a bit lost in how I can assure to store a person ONLY when I successfully stored a related costumer. 我是CodeIgniter的DataMapper ORM的新手,在成功确保存储相关客户后如何确保仅存储一个人方面有些困惑。 For instance, if I validate a costumer status and it fails, to store that costumer I previously had to store its related person... How can I rollback the new person if I can't store the costumer? 例如,如果我验证了客户status并且失败了,那么我以前必须存储该客户的相关人员才能存储。如果我不能存储客户,如何回退新人员? (in the real scenario I've a persons , individuals , users and costumers tables, and I need to store them only if all succeeds) (在实际情况下,我有personsindividualsuserscostumers表,只有在一切成功后才需要存储它们)

How I can use transactions here? 我如何在这里使用交易? Yeah, I already have read the documentation about using transactions but I can't figure out and I'm stuck on that for a few hours by now. 是的,我已经阅读了有关使用事务的文档,但是我无法弄清楚,到目前为止我已经坚持了几个小时。 Thank you in advance! 先感谢您!

UPDATE UPDATE

I hacked my controller a bit and now it seems to work, is there any better way to achieve this? 我对控制器进行了一点修改,现在似乎可以正常工作了,是否有更好的方法来实现?

New controller: 新控制器:

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));
        }
    }
}
// Begin transaction
$p->trans_begin();

// Attempt to save person
$p->save();

// Check status of transaction
if ($p->trans_status() === FALSE)
{
// Transaction failed, rollback
$p->trans_rollback();

// Add error message
$u->error_message('transaction', 'The transaction failed to save (insert)');
}
else
{

//since the person has been saved, then we can now process the customer

// Begin transaction
$c->trans_begin();

// Attempt to save person
$c->save($p);

if( $c->trans_status === TRUE ){

 $p->commit(); 
 $c->commit();

}

}

/*
 * you can nest a lot of if statements depending on the number of objects you want to save
 * I followed whats exactly in the documentation for that. So give it a try, it should run.
 * dont forget to create $c and $p as datamapper objects.
 */

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM