Исключения в mysqli - есть ли надежда?

crocodile2u

http://vbolshov.org.ru
tony2001
Ну да, корректнее было бы сказать "только методами". А так - получается некий микс. Допустим, для объекта Mysqli появляется метод вроде setErrorHandler(), где есть возможность заставить его кидать исключения. В таком случае функции продолжат генерировать ошибки, а методы объекта - кидать исключения.. брр..
 

camka

не самка
Автор оригинала: tony2001
есть getTrace().
Ты неправильно понял.

PHP:
<?php
error_reporting(E_ALL);
set_error_handler('eh');

function eh($errno, $errstr, $errfile, $errline, $errcontext)
{
	// need to parse $errstr to find out
	// which class and method caused the exception
	
	/// .... $z = explode('::', $errstr, 2);
	
}
$m = new mysqli('localhost', '*****', '********', '*****');
$z = $m->query("select f");
?>
Вот где парсить надо. К тому же при неудаче в методе query (и ему подобным) никакая ошибка не генеруется. Только заполняются mysqli::errno i mysqli::error. Такие ошибки как раз и не перехватить.

а как ты предполагаешь сделать это, если эксепшены будут забиты в mysqli ?
Я во внутринностях не разбираюсь. А что разве класс не может выдавать исключения разного типа? Ну или хотя бы наследованные от одного предка?

>Кстати в концепцию ОО не вписываются mysqli_connect_err* функции.
"функции не вписываются в концепцию ОО" ?
я, пожалуй, это запишу..
.. краснею ..


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

tony2001

TeaM PHPClub
>// need to parse $errstr to find out
>// which class and method caused the exception

The problem is that I don't get why do you need to find out them at all.
And which class and method should be there if you use non-OO API ? Huh ?

>А что разве класс не может выдавать исключения разного типа?
>Ну или хотя бы наследованные от одного предка?
может.
но зачем?
я бы, например, так никогда не сделал.
поэтому я отталкиваюсь от того, что там был бы один класс эксепшенов с разными кодами ошибок, как это сделано в том же PDO.
 

camka

не самка
Автор оригинала: tony2001
The problem is that I don't get why do you need to find out them at all.
And which class and method should be there if you use non-OO API ? Huh ?
Ты же сам посоветовал использовать еррор_хэндлер для перехвата ошибок и преобразования их в исключения. Я привел пример, когда это не работает. Там закралась ошибка
"// which class and method caused the error "

Автор оригинала: tony2001
And which class and method should be there if you use non-OO API ? Huh ?
Это пример, который я, якобы, должен использовать в моем ОО подходе, чтобы выбросить соответствующий тип исключиния.
 

tony2001

TeaM PHPClub
>Ты же сам посоветовал использовать еррор_хэндлер для перехвата ошибок и
> преобразования их в исключения.
да.

>Я привел пример, когда это не работает.
я не понимаю почему.

PHP:
class test {
	function foo() {
		trigger_error("test error");
	}
}
	
class MyException extends Exception
{
    function __construct($errstr, $errno=0, $errfile='', $errline='')
    {
        parent::__construct($errstr, $errno);
        $this->file = $errfile;
        $this->line = $errline;
    }
}

function Error2Exception($errno, $errstr, $errfile, $errline)
{
    throw new MyException($errstr, $errno);//, $errfile, $errline);
}

$err_msg = 'no exception';
set_error_handler('Error2Exception');

try
{
	$t = new test;
	$t->foo();
}
catch (Exception $e)
{
	$t = $e->getTrace();
	var_dump($t[2]); // ----> см. результат
}
результат:
Код:
array(6) {
  ["file"]=>
  string(14) "/www/index.php"
  ["line"]=>
  int(30)
  ["function"]=>
  string(3) "foo"
  ["class"]=>
  string(4) "test"
  ["type"]=>
  string(2) "->"
  ["args"]=>
  array(0) {
  }
}
что еще надо-то ?
 

camka

не самка
Ок. Теперь ясно. Я бы сразу в хендлере и выкидывал исключение, перехватывал его там же и анализировал $t[2]. С этим ясно.
А что делать с mysqli::query, который не генерирует ошибки?
 

Profic

just Profic (PHP5 BetaTeam)
camka
Я вот написал свою обертку сверху mysqli, которая как раз таки кидает исключения, и не парюсь. Чего и тебе советую. Ну где ты найдешь еще такой метод query()? И потом захочешь, чтобы все php-функции *_query() вели себя анналогично?
PHP:
class DbConnection {
	private $link = NULL;
	private $queriesCount = 0;

	// ...

	public function query($sql, $fetchMode = dbResult::fetchBoth) {
		$res = $this->link->query($sql);
		if ($this->link->errno) {
			throw new dbException(
				$this->link->errno,
				$this->link->error,
				$this->link->sqlstate,
				$sql
			);
		}
		++$this->queriesCount;
		if ($res instanceof mysqli_result) {
			return new dbResult($res, $fetchMode);
		}
		if ($res) {
			if ($this->link->insert_id) {
				return $this->link->insert_id;
			}
			return $this->link->affected_rows;
		}
		return $res;
	}

	// ...

}
 

camka

не самка
Profic
Я тоже написал ее. Но не в этом проблема то. Например, чтобы обернуть mysqli::multi_query приходится обертывать еще и more_results, или next_result и store_result и use_result. Ну или уже по твоему усмотрению, можно в multi_query пробегаться по результатам, но это тоже нерезонно. Получается много кода, которого можно было бы избежать, предусмотри разработчики модуля механизм исключений.
 

Profic

just Profic (PHP5 BetaTeam)
camka
Не вижу в этом проблемы. По крайней мере я. Такая обертка пишется один раз и дальше юзается до посинения :). К тому же я люблю стиль studlyCase (или как он там называется), вместо применямого почти повсеместно в php стиля с подчеркиваниями. Т.е. такая обертка для меня убивает сразу три зайца: исключения, названия методов и расширения функциональности. Но, однако, повторюсь, это моя имха.
 

AnToXa

prodigy-одаренный ребенок
простите, не особо юзал 5 версию, но разве нельзя сделать врапперов через __call() ? получится очень просто и реюзабельно.
 

camka

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

AnToXa
а чем это будет отличаться от наследования? Или я что-то недопонимаю?
 

AnToXa

prodigy-одаренный ребенок
тем, что надо один раз написать только и все.
а потом на любой объект сверху навесить и буддут вам exceptions
 

si

Administrator
camka
сделай пачь для ext/mysqli который реализует нужные тебе фичи (exception). да так чтобы можно было их скрипа изменить поведение: по старому (BC mode) или с exception пошли его в php-dev с просьбой включить в основное дерево. т.к BC он не ломает глядишь и включать.
 

itprog

Cruftsman
Немного не по теме, а PHP когда-нибудь полностью перейдет на исключения ? Или так и придется использовать if(@...)?
 

tony2001

TeaM PHPClub
>Немного не по теме, а PHP когда-нибудь полностью перейдет на исключения ? Или так и придется использовать if(@...)?

я описал в топике два раза "как перейти полностью на эксепшены" и даже привел пример кода.
что неясно?
 

camka

не самка
Есть мнение, что раз уж, по мнению разработчиков, при ошибке в методе query не генерируется ошибка, а просто заполняются errno и error, то, возможно, и исключение будет здесь лишним. В чем суть подобного поведения? По какой причине не генерируется ворнинг или нотис, если произошла, скажем, ошибка синтаксиса запроса?
 

tony2001

TeaM PHPClub
camka
это вопрос к Georg Richter, он хозяин ext/mysqli и автор (почти) всего кода.
не могу сказать, что ext/mysqli мне очень нравится (в основном из-за кривого API и wrong_naming_style() instead of the goodOne()), но это вряд ли изменится в ближайшем будущем по причине BC.
 

si

Administrator
tony2001

а чем плох мой вариант при условии сохранения BC ?
 

tony2001

TeaM PHPClub
si
при условии сохранения BC не получится поменять поведение query().
 
Сверху