Jump to content
Калькуляторы

Консультация по PHP Есть ли в PHP механизм, аналогичный tie из perl

1. PHP я знаю плохо.

2. Учить PHP не хочу.

3. perl знаю хорошо.

4. Есть большое веб приложение на PHP, в котором имеется примерно следующий код в процессе инициализации:

 

 $speeds  = array ();
 $q='select id,name,speed from tk_tariff';
 $r=mysql_query($q,$db);
 while ($p=mysql_fetch_array($r)) {
$speeds[$p[0]]=$p[2];
 }

 

Далее по тексту используется $speeds

 

Проект отлажен (не мной) и работает.

 

5. Я не хочу делать ф-цию get_tariff_speed_by_id() и менять по объёмному тексту все вхождения $speeds на вызов get_tariff_speed_by_id()

6. В перле есть "связывание" tie. Я могу связать переменную с некоторой структурой навроде объекта, которая будет перехватывать чтение и запись переменной и, вместо чтения или записи, выполнять какие-то свои методы/функции. Например, в моём случае, делать селекты в базу по мере нужды а не выбирать всю таблицу разом.

 

Внимание вопрос: Есть ли аналогичный механизм в PHP?

Share this post


Link to post
Share on other sites

$a='Some Text<br />';
$b=$a;  //присваивание значения
$a='Bla Bla Bla<br />'; 
echo $b;   //значение: Some Text
$c=& $a;  //ссылка на переменную
$a='PHP Use<br />';
echo $c; //значение: PHP Use

 

Оно?

Share this post


Link to post
Share on other sites

Не оно.

 

Надо, чтобы при вызове $s = $speed[38]

происходит вызов некоей ф-ции, которая делала бы

 

select speed from tk_tariffs where id=38

return $s;

Share this post


Link to post
Share on other sites

Опять не то...

https://www.opennet....rl_tie.txt.html Вот то, что надо.

 

Для перла, мне надо описать методы

 

  1. TIEHASH classname, LIST
  2. FETCH this, key
  3. STORE this, key, value
  4. DELETE this, key
  5. CLEAR this
  6. EXISTS this, key
  7. FIRSTKEY this
  8. NEXTKEY this, lastkey
  9. SCALAR this
  10. DESTROY this
  11. UNTIE this

и "связать" этот класс (объект) с хешем (переменной типа "ассоциативный массив").

 

Все эти методы писать с нуля не надо, есть стандартный класс Tie::StdHash, от которого надо унаследовать новый класс и, в моём случае, написать методы №2 и №3 и, возможно №6.

Share this post


Link to post
Share on other sites

Могу ошибаться, но, боюсь, нет такого в функциональном php. Только в ООП из похожего есть магические __call(), которые могут перехватывать вызов любой переменной, но только в рамках класса.

Share this post


Link to post
Share on other sites

Если речь про БД, то есть mysqli_stmt::bind_param/mysqli_stmt::bind_result (для MySQLi) и PDOStatement::bindParam/PDOStatement::bindColumn (для PDO).

Но вообще это разные языки. Один и тот же подход получиться использовать не везде.

Share this post


Link to post
Share on other sites

Да нет -же!

 

Беда в том, что автор извлекает табличку в массив сразу и целиком. И в дальнейшем работает только с этим массивом. Во многих частях этого проекта выбирая из него по 1-2 значения.

 

При этом в начале не известно, нужны ли вообще будут данные из этой таблицы. Табличка не маленькая, народу в апликухе сидит много, табличку эту дёргают. При некоторых обстоятельствах разом запросов 80 висит. Мне это не нравится. Я хотел без существенного рефакторинга самого проекта сделать финт, который сделал бы не задумываясь на перле. Сделал бы "магическую" переменную, обращения к которой перехватывались бы функциями.

 

В перле это запросто. Я думал, что и в php не трудно. А оказалось - показалось...

Share this post


Link to post
Share on other sites

Гхм... Если запрос реально НАСТОЛЬКО простой:

$q='select id,name,speed from tk_tariff';

и если его результат неизменен, и если вас беспокоит скорость его выполнения и висящие запросы - просто используйте, например, memcached для кеширования. В месте, где этот запрос выполняется, сначала дёргайте кеш, и только если в кеше массива нет - дёргайте базу.

Share this post


Link to post
Share on other sites

Тогда переменную превратить в объект и использовать магические методы.
Где про это прочесть?
Гхм... Если запрос реально НАСТОЛЬКО простой:
Это копипаста из проекта...

 

и если его результат неизменен
Меняется, но очень редко. Одно изменение на 10-20к запросов. И это верхняя граница. В реальности, меняется реже.

 

 

memcached - это оверкилл.

Share this post


Link to post
Share on other sites

memcached - это оверкилл.

Однако он предназначен именно для кеширования часто запрашиваемых, но редко меняющихся данных. Как раз ваш случай, имхо. Пихать в кеш на 10-15 минут - и всё было бы замечательно.

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

 

Тогда переменную превратить в объект и использовать магические методы.

Где про это прочесть?

Да не получится ничего без изменения кода во всех местах вызова этого массива.

Share this post


Link to post
Share on other sites

Ну нет же!

 

Вместо того, чтобы почти контекстной заменой поменять $s = $speed[38] на $s = get_this_***ing_speed(38) предлагается городить целого демона и всё одно переписывать код.

Share this post


Link to post
Share on other sites

предлагается городить целого демона

Тут есть нюанс.

В исходном варианте в $speeds загружается вся таблица при каждом http-запросе.

Если ее заменить на функцию, то будет загружаться не вся таблица, а только отдельные строки. Но тоже при каждом http-запросе.

А memcached позволит сделать так, чтобы строки из таблицы загружались только при перезапуске сервера, между http-запросами обращения к БД не потребуются.

Так что совет про memcached в целом неплохой.

Share this post


Link to post
Share on other sites

Всё так, только чуть дополню:

- "строки из таблицы загружались только при перезапуске сервера" - класть в кеш лучше таки с таймаутом: минут на 10-15. Соответственно, и актуальность данных будет с лагом 10-15 минут.

- "и всё одно переписывать код." - При замене массива на вызов функции - код меняется в куче мест, при использовании кеша - только в одном.

 

А так - дело ваше, конечно :)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.