2013-12-23 4 views
0

Я пишу библиотеку, которая требует подключения к базе данных, поэтому она требует, чтобы пользователи передавали объект PDO в качестве параметра конструктора.Библиотека с использованием объекта PDO

Но, как многие из вас знают, PDO имеет 3 разных механизма сообщения об ошибках: режим молчания, режим предупреждения и режим исключения (http://www.php.net/manual/en/pdo.error-handling.php).

Проблема в том, что для каждого режима требуется другой тип кода обработки ошибок. Признание того, что я не могу заставить пользователь использовать мой предпочтительный режим, я думаю, что мои варианты:

  1. Установка моего предпочтительный режима на введенном объекте PDO, и беспокоиться ни о чем
  2. Клонирование введенного объекта PDO а затем установите мой предпочтительный режим
  3. Написание кода обработки ошибок для всех трех режимов, а затем обнаружение и использование соответствующего метода с помощью метода PDO :: getAttribute()
  4. Установка моего предпочтительного режима перед каждым вызовом метода и последующим отзывом после каждого из них

Так что 1 может сломать код пользователя, 2 выглядит как ненужное дублирование, 3 - ужасно неудобно, а 4 не очень-ужасно-неудобно, но все еще неудобно и все еще подвержено нарушению кода пользователя.

Так что я прошу библиотечных писателей, как вы справляетесь с этим?

+0

С помощью замыканий u может обеспечить механизм, при котором пользователь может зарегистрировать свою функцию обратного вызова при возникновении ошибки. Если ни один не указан, используйте обработку ошибок по умолчанию – DarkBee

+1

. Я думаю, что лучший выбор для пользователя, какой он хочет использовать, например: предварительно сконфигурированный PDO, прежде чем передать его вашему ctor. – CentaurWarchief

ответ

1

Хорошо, не уверен, что это подходящий сайт для такого рода вопросов, но прежде всего позвольте мне кратко рассказать о ваших вариантах и ​​рассказать вам, что IMO - лучший вариант. Тогда я объясню все это в будущих изменениях.

  1. Это не путь вперед. Пользователь передает экземпляр, который вы затем меняете, за спиной пользователей. Не изменяйте то, что не принадлежит вам
  2. Не клонируйте соединение DB. Просто не
  3. В библиотеке не должно быть ошибок, которые являются результатом кода пользователя. Это проблема пользователя/ошибка, они также должны иметь дело с этим. Ни в коем случае lib не может предвидеть при каждом возможном злоупотреблении
  4. Нет, действительно ... Это просто бесшумный способ сделать то, что вы делаете в пункте 1: изменение объекта, который вы никогда не имели.

Что бы я сделал? Простой: предоставить API для соединений БД, которые могут в своем сердце иметь экземпляр PDO, но, по крайней мере, у пользователя есть ясный API, и он знает, каков результат возможных ошибок (например, PDO + setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION) => ваш API будет всегда бросать исключения


Теперь, почему ваш первый вариант не является жизнеспособным подходом (опять же: все это мое мнение)?
Предположим, что я должен был использовать свой код, и что-то вроде этого:

//code 
$this->db = new PDO($dsn, $usr, $pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT)); 
$this->dependency = new Your\Lib\Stuff($this->db); 
//code 
$this->db->query('bad query'); 

Теперь, если вы установите PDO для исключения исключений, я не поймаю. Мой код не писал, чтобы иметь дело с PDOException экземплярами, поэтому это приведет к остановке всего приложения.Более того, кто должен сказать, что я не собираюсь, чтобы добавить эту строку, во время отладки, когда это произойдет:

$this->dependency = new Your\Lib\Stuff($this->db); 
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);//override your setting 

Это не безопасный путь, чтобы идти вниз, так что нет.


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

class BadIdea extends PDO 
{ 
    public function __clone() 
    {//disable clone 
     return false; 
    } 
} 

В этом случае $db = new BadIdea() все равно будет проходить как экземпляр PDO (тест function foo(PDO $arg){echo 'argument is instance of PDO';}, а затем вызвать foo(new BadIdea), он будет работа). Теперь вы не можете клонировать, и ваша библиотека не работает.


Lib или рамки должны быть написаны достаточно обобщенно, так что вы можете повторное это. Если вы пишете код, думая о конкретном случае использования, вы, вероятно, собираетесь редактировать код каждый раз, когда хотите его использовать.
Если вы не собираетесь создавать свою собственную библиотеку (в любом случае пользователю не нужно будет проходить самодельное соединение с БД), обработка ошибок не должна быть задачей вашей библиотеки.

Ваш код должен просто бросать исключения, когда что-то происходит, неожиданно. Вы не можете ожидать, чтобы написать код, который работает со всеми этими ситуациями:

$yourInstance->pass('Invalid query'); 
$yourInstance->select('INSERT ...');//valid query, wrong method 
$your instance->query(array('invalid', 'argument')); 

Или хуже:

try 
{ 
    $yourInstance->beginTransaction(); 
    $yourInstance->query($q1); 
    $q2 = $anotherObj->composeComplexQuery();//might be the cause of Exceptions, too 
    $yourInstance->query($q2); 
    $yourInstance->commit(); 
} catch(){} 

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

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