Extend mysqli with query logging, but don't lose insert_id
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.
精彩评论