Feb 14

Мдя, заработался совсем… Писать нет времени абсолютно… Поэтому сегодня будут ссылки:

И напоследок: мне недавно нужен был перевод из русского UTF-8 на латиницу в PHP. Ддо этого я его делал так: считываем по символу (или по нескольку символов) из строки и строим новую строку транслитерированием. Из плюсов - быстро, из минусов - напрягает выбирать по нескольку букв. Потом мне предложили использовать str_replace. Из плюсов - быстро пишется. К сожалению, долго работает. :) Есть и еще один вариант:

function rus_to_translit($string)
{
  $converter = array(
    'а' => 'a',  'б' => 'b',  'в' => 'v',   'г' => 'g',  'д' => 'd', 'е' => 'e', 'ё' => 'e', 'ж' => 'zh',
    'з' => 'z',  'и' => 'i',  'й' => 'y',   'к' => 'k',  'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o',
    'п' => 'p',  'р' => 'r',  'с' => 's',   'т' => 't',  'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c',
    'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sch', 'ь' => '\'', 'ы' => 'y', 'ъ' => '',  'э' => 'e', 'ю' => 'yu',
    'я' => 'ya',
    'А' => 'A',  'Б' => 'B',  'В' => 'V',   'Г' => 'G',  'Д' => 'D', 'Е' => 'E', 'Ё' => 'E', 'Ж' => 'ZH',
    'З' => 'Z',  'И' => 'I',  'Й' => 'Y',   'К' => 'K',  'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O',
    'П' => 'P',  'Р' => 'R',  'С' => 'S',   'Т' => 'T',  'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C',
    'Ч' => 'CH', 'Ш' => 'SH', 'Щ' => 'SCH', 'Ь' => '\'', 'Ы' => 'Y', 'Ъ' => '',  'Э' => 'E', 'Ю' => 'YU',
    'Я' => 'YA',
  );

  return strtr($string, $converter);
}

При этом не забудьте файл, в который вы это пишете сохранить в кодировке UTF-8. ИМХО, оптимальный вариант.

PS. Не забудьте сегодня поздравить свои половинки с днем всех влюбленных!

written by FX Poster \\ tags: ,

Feb 11

Используете ли вы методологию TDD при разработке ПО?

PS. Я - нет, но надеюсь, что скоро начну. Посоветуйте, что почитать.

written by FX Poster

Feb 09

Блин, “всё гениальное - просто”. И решение моей проблемы оказалось до ужаса простым, причем думать даже не пришлось - просто как-то случайно подумалось…

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

Для тех, кто не читал предыдущий пост - советую всё же прочитать.

Так вот, как я уже сказал, решение оказывается очень простым - мы изменяем ту самую Product::fetchByParameters(), которую вызывают все остальные функции выбирающие записи из таблицы (т.е. где-то внутри себя они вызовут именно fetchByParameters() для именно выбора записей). В предыдущем посте я написал, что делать этого нельзя - т.к. мы теряем возможножность доступа к неодобренным записям, но я забыл одну маленькую деталь - а ведь можно сделать так:

class Product {
  public static $showUnapproved = false;

  private static function fetchByParameters($sql)
  {
    if(!self::$showUnapproved) {
      // добавляем "WHERE approved = '1'" в наш sql-запрос
    }
    ...
  }

   ...
}

Теперь у нас по умолчанию будут везде показываться только approved-записи, а для нужных модулей в каком-нибудь preExecute для контроллера нужно добавить Product::$showUnapproved = true.

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

written by FX Poster \\ tags:

Feb 09

Читаем тут.

PS. Пипец мы там с khim’ом нафлудили… 

written by FX Poster \\ tags:

Feb 06

В процессе написания сайта с использованием Symfony начали проявляться недостатки этой замечательной, на мой взгляд, библиотеки…

Первое, о чем хочется сказать - очень удобно реализованы связи one-to-many. Propel сама сгенерирует базовые классы, в которых такие связи будут учитываться изначально. Пользоваться очень удобно, своего кода в моделях приходится писать очень мало, а если быть более точным - почти весь код в данном случае получается именно product-specific. В случае со связями one-to-one проблемы появляются - как я этого ни добивался, Propel упрямо считает эти связи такими же, как и one-to-many и генерирует неправильный код. Исправляется обычно дописыванием правильных функций вручную, благо, обычно дописать только get<PrimaryKey>-функции. В моем случае я вообще перестроил БД так, что таких связей у меня не оказалось, так что конкретного ничего сказать не могу.

Второе - “всё - обьекты”. Очень популярное в ООП высказывание подходит к Propel’у просто замечательно. :) Работа с Propel’ом заключается исключительно в работе с обьектами-записями и обьектами-таблицами. Никаких php’шных массивов (привет CI и CakePHP), одни классы и обьекты. Очень удобно. С эффективностью, правда, могут возникать огромные проблемы. Я, кстати, так до сих пор и не знаю, как эффективно выбрать (категория + количество продуктов в ней) за один запрос. Но беспокоиться об этом я буду уже потом. :)

Блин, вот сидишь на работе и думаешь - сколько всего можно написать, плохого и хорошего, а приходишь домой и нифига не вспоминается.

Третье - many-to-many. После того, как у меня появились такие связи, я начал очень сильно жалеть о том, что я не выбрал Doctrine… По сравнению с ней (она дополнительную many-to-many таблицу создает сама и сама же за ней следит) в Propel’е всё ужасно - приходится создавать вручную таблицы и дописывать в них целую кучу кода, который бы вполне могла дописать сама библиотека в базовых классах. Может в том же CI это вполне нормальным кажется (контраст другой), но здесь, когда строишь модель базы данных - мыслишь исключительно в обьектах, которые тебе будут нужны. И добавлять (а еще сопровождать) эту [непонятно откуда взявшуюся, в реале-то её нет] таблицу очень неудобно.

Четвертое - опять по сравнению с Doctrine’ой - нет возможности “опускаться” на уровень SQL не теряя ORM’а. Т.е. либо Propel ORM, либо Creole (PDO). В Doctrine’е есть для таких случаев DQL - достаточно удобная штучка, если поглядеть по мануалу. Вообще, Doctrine, на мой взгляд, гораздо более функциональная, мощная и удобная библиотека. Да и User Guide’ы у неё гораздо более полные и, как ни странно, user-friendly.

Но по сравнению со всем остальным, что я видел на PHP - Propel - это очень круто.

written by FX Poster \\ tags: , ,

Feb 06

Чем больше мы делаем какое-то приложение, тем меньше оно становиться похоже на то, что хотел от нас заказчик…

written by FX Poster

Feb 06

Ищется самодостаточный десктопный mail sender - указать ему список e-mail’ов и он на все разошлет письма, не требуя ни стороннего smtp, ни чего либо еще. Желательно бесплатный или крякнутый. :)  Либо подскажите хороший smtp-сервак, через который можно было бы разослать быстро ~1000 писем. Те, что знаю - либо столько не шлют (gmail - отсылает примерно 200-250, потом расконнекчивается), либо пишут, что всё отослано, а ничего не приходит.

PS. Мне для рассылки нужно, а не для спама! 

written by FX Poster

Feb 02

Столкнулся я вот тут с ситуацией и хочу попросить помощи у читателей.

Имеется:

Таблица в базе данных, содержащая некоторые записи. У записей есть “переключатель” - одобрена/неодобрена (для тех, кто в танке - булевое поле approved). Для этой таблицы (и всех остальных таблиц в бд) есть ORM.

Нужно:

Обеспечить для большей части частей системы удобный доступ только к записям с approved = true, при этом нужно учесть, что другие таблицы также могут быть связаны с данной и в ORM’е есть метода доступа к записям в данной таблице. Грубо говоря имеем нечто типа такого:

Table ProductType
Table Product
$someProductType->fetchAllProducts()
Product::fetchAll()

То есть, доступ к данной таблице есть во многих местах и все такие места менять ОЧЕНЬ не хотелось бы.

Но это половина проблемы, и в моем случае не самая страшная т.к. у таблицы есть ОДИН метод, к которому обращаются все остальные (пусть это будет Product::fetchByParameters()), и заменив только его я получу то, что мне нужно.

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

written by FX Poster \\ tags:

Feb 02

Ждем понедельника. Скорее всего, я её все же поставлю вместо XP.

written by FX Poster \\ tags:

Feb 01

Смотрим FAQ в wiki. Наконец-то в CI можно использовать нормальный ORM. :)

written by FX Poster \\ tags: