开发者

Extend mysqli with query logging, but don't lose insert_id

开发者 https://www.devze.com 2023-03-09 23:12 出处:网络
I have a class that extends mysqli so that queries are logged. Unfortunately, I can\'t figure out how not to lose the insert_id property.

I have a class that extends mysqli so that queries are logged.

Unfortunately, I can't figure out how not to lose the insert_id property.

I'd like to be able to do this

$sql = sprintf("
    INSERT INTO picture
    SET     nm_picture = '%s'

",
    Db::instance()->escape_string($_POST['nm_picture'])
);

$result = Db::instance()->queri($sql);
$id_inserted_pic = Db::instance()->insert_id;

but $id_inserted_pic is the activity_log ID.

I hoped I'd be able to override $this->insert_id but alas no.

Any help appreciated.

My code as it stands with a few bit removed for simplicity: (please note that some of it was written by other people and/or may not be ideal)

class Db extends \mysqli
{
    private static $instance;
    protected $_database;

    public $insert_id; /* doesn't error but doesn't work either */

    private function __construct(array $config)
    {
        if (
            is_array($config)
            && isset($config['host'])
            && isset($config['username'])
            && isset($config['password'])
            && isset($config['database'])
        )
        {
            $this->_database = $config['database'];
            parent::__construct(
                $config['host']
                , $config['username']
                , $config['password']
                , $config['database']
                , $config['port']
                , $config['socket']
            );
        }
    }

    /**
     * Singleton Pattern
     * @param array $config
     */
    public static function instance(array $config = null)
    {
        if (!isset(self::$instance)) {
                $c = __CLASS__;
                self::$instance = new $c($config);
            }
            return self::$instance;
    }

    /**
     * Save the passed string into the activity_log table
     *
     * @param string $query
     * @param bool $force default false
     */
    public function activity_log($query, $force = false)
    {
        $sql = sprintf('
            INSERT INTO sw_activity_log
            SET     tx_activity_log = "%s"
        ',
            $query
        );
        $result = $this->query($sql);

        if ($result !开发者_如何学运维== false)
        {
            return $result;
        }
        else
        {
            //...
        }
    }

    /**
     * Run a query and activity_log() it if matched and not told otherwise
     *
     * @param string $query
     * @param unknown_type $resultmode
     * @param bool|null $fl_log default null
     *
     * @return mysqli_result;
     */
    public function queri($query, $resultmode = null, $fl_log = null)
    {
        $result = parent::query($query, $resultmode);
        $tmp_insert_id = $this->insert_id;

        if ($result !== false)
        {
            if ($fl_log || ($fl_log !== false && preg_match('~^(\s+)?(REPLACE|INSERT|DELETE|UPDATE)~ims', $query) > 0))
            {
                self::activity_log($query);
            }
            $this->insert_id = $tmp_insert_id;
            return $result;
        }
        else
        {
            // ...
        }
    }
}


I'd suggest having your queri method save the insert ID somewhere in a class variable. Have the logging function set a flag variable telling the queri method to NOT store the insert ID when a log query is performed. That way you'd have your insert ID preserved from the last non-log insertion.


You have two possibilities:

  • Don't use an auto-increment in your activity log. There really is no need for it. There isn't even a need for a primary key in that table, cause what are you going to link it with?
  • Insert the activity log before the actual query, wrap everything in a transaction and rollback when the query is invalid.
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号