2012-03-30 2 views
-1

Давайте рассмотрим, что у нас есть два отдельных класса, каждый из которых имеет объект mysqli для использования в операциях с базой данных.Обработка транзакций PHP с несколькими объектами mysqli

class A{ 
    protected $mysqliObject; 
    public function __constructor(){ 
    $this->mysqliObject=new mysqli(...) 
    } 
    public function doSomething(){ 
    $this->mysqliObject->query(...); 
    } 
} 
class B{ 
    protected $mysqliObject; 
    public function __constructor(){ 
    $this->mysqliObject=new mysqli(...) 
    } 
    public function doSomething(){ 
    $this->mysqliObject->query(...); 
    } 
} 

В doSomething() методы используют $mysqliObject для запроса к базе данных (SELECT, UPDATE, DELETE, и т.д ...). Я хочу сделать следующее снаружи:

// Start point 
$aObject=new A(); 
$bObject=new B(); 
$aObject->doSomething(); 
$bObject->doSomething(); 
// End point 

... но я хочу откатить оба запроса, если какой-либо из них не сработает. Как я могу это сделать?

  • Могу ли я создать новый mysqli объект в «Начальная точка», и использовать его для фиксации или отката на «Конечная точка» базы данных запроса class A и class B?
  • Должен ли я создать снаружи и передать те же $mysqliObject в __constructor() из class A и class B и использовать их для откат или фиксации (снаружи).

Хотелось бы увидеть больше приемов с проконсонами.

ответ

2

Каждый объект подключения к базе данных, который у вас есть, представляет собой другое соединение с базой данных, даже если соединение относится к одному серверу базы данных. Каждое соединение полностью независимо друг от друга, поэтому транзакция, запущенная в одном соединении, будет невидима для другого соединения.

Если весь доступ к базе данных находится на том же сервере, просто создайте одно соединение и передайте его на все, что требует доступа к соединению. Затем транзакция будет применяться по всей программе.

class ClassThatNeedsDbAccess 
{ 
    protected $connection = NULL; 

    protected function doQuery ($query) 
    { 
     return ($this -> connection -> execute ($query)); 
    } 

    public function __construct (PDO $connection) 
    { 
     $this -> connection = $connection; 
    } 
} 

class OtherClassThatNeedsDbAccess extends ClassThatNeedsDbAccess 
{ 
} 

$myDb = new PDO ('dsn_goes_here'); 

$obj1 = new ClassThatNeedsDbAccess ($myDb); 
$obj2 = new OtherClassThatNeedsDbAccess ($myDb); 

Если вы разговариваете с различными серверами баз данных, то вы, вероятно, следует обернуть все соединения в объекте, который может координировать деятельность базы данных. Обязанностью этого объекта является отслеживание того, какое соединение с базой данных имеет транзакцию в полете.

+0

В основном, мой вопрос состоял в том, чтобы спросить/настроить другой подход, чем это. Возможно, я просто хотел немного обмануть и выбросить ООП из окна. Я продолжу, как вы упомянули. – Dyin

+0

Удачи вам в этом. Это может работать в воображаемых программах, но на практике вы столкнетесь с [командами не синхронизированы] (http://dev.mysql.com/doc/refman/5.0/en/commands-out-of-sync.html) , В этом вопросе четко указано использование mysqli. – doug65536

0

Используйте один объект MySQL - соединение для всей вашей бизнес-логики ... взгляните на одноэлементный шаблон. Вы можете передать его конструктору или использовать метод статического класса для получения объекта mysql.

Тогда это вопрос вас, когда вы начинаете конечную транзакцию, соединение должно быть одинаковым. Лучше всего было бы абстрагировать его на некоторый общий уровень доступа к базе данных.

+0

Не используйте синглтоны. http://gooh.posterous.com/singletons-in-php – GordonM

+0

спасибо, интересная статья. Итак, предложение просто вставляет объект базы данных? –

+0

Да, инъекция зависимости - это путь. Включение одного и того же объекта во все иждивенцы будет иметь тот же эффект, что и Singleton, и если вы обнаружите в какой-то более поздней момент, что одному из зависимых требуется другое соединение, вам просто нужно дать ему другой объект базы данных. – GordonM

Смежные вопросы