К основному контенту

Сообщения

Показаны сообщения с ярлыком "programming"

Частичный переезд

Я решил оживить домен handmadesite.net и переношу все посты про Shop-Script, Cake, ZendFramework, PHP и т.п. туда. А то мой “уютный дневничок” стал похож непойми на что. :-) Ну и еще там можно подписываться на каменты, да и вообще… Счас потихоньку все более менее свежие тематические посты дублирую туда, а здесь запрещаю их комментарии. Вот. Велкам всем, кому интересна эта тематика. :-)

Кэшируй, кэшируй, кэшируй запрос назло буржуазной Европе!

Обсуждение и дальнейшее развитие темы смотрите в блоге "WEB рукоделие" . Комментируйте там же. Простите за неудобства. Это опять пост про Shop-Script. Давно обещанная на форуме WebAssyst практика кэширования запросов многострадального ШопСкриптаПро. Предыстория этого вопроса такова: одно время магаз на ShopScript работал у меня на довольно хилом VDS и посещения поисковых ботов практически клали сервер на обе лопатки. Типичная, так сказать, DDOS атака :-) Поэтому я озаботился производительностью самого скрипта. Предпринял следующие логичные, как мне кажется, шаги: Добавил недостающие индексы в разные таблицы с товаром, параметрами товара, категории, валюты и т.д. Убрал подсчет запросов категорий и товаров . Во-первых это оказалась бесполезная фича, во-вторых это было просто. Закэшировал несколько запросов. Эти три пункта помогли решить проблему. Не знаю, какой оказал бОльшее влияние, но первого точно было недостаточно. Объяснять как установить PEAR, доба...

Болезни роста

Две таблицы в БД. Обе примерно по полмиллиона записей, а в рабочем виде будет и больше, миллиона 2-3. Таблицы не сами по себе, а связанные Один-ко-многим. При LEFT JOIN все это безбожно тормозит, невзирая на тип ключей, по которым идет связка, пробовал и INT вместо VARCHAR, который там изначально. Думаю над тремя вариантами. Обработку связей унести в код модели/контроллера Cake. т.е. SELECTить все по одельности. Попробовать InnoDB вместо MyISAM Перенести на PostgreSQL Пока обдумываю варианты, как буриданов осел, работа не движется. Буду пробовать на выходных сначала пункт 2, как наиболее простой в реализации, потом 3, потом 1-й как самый, на мой взгляд, идеологически неверный :-)

Неочевидное поведение метода updateAll

Как неожиданно выяснилось, методу Model::updateAll совершенно наплевать на указания contain, усли подключен ContainableBahavior , а также на значение свойства Model::recursive. Несмотря ни на что, при вызове Model::updateAll все равно подключались все зависимые модели. Вылечилось жесткой командой (дело было в методе модели): $this->unbindModel(array( 'belongsTo'=>array_keys($this->belongsTo), 'hasOne'=>array_keys($this->hasOne), 'hasMany'=>array_keys($this->hasMany) )); Но осадочек в душе остался. :-)

Если у вас нету капчи

Развитие Shop-Script Pro и Premium остановлено, вместо них теперь WebAssyst Shop-Script. Спору нет, обновка хороша, но особых причин переводить уже работающие проекты на новый движок я не вижу. Раз нет поддержки, то дорабатывать старые версии придется самостоятельно. Спамеры, похоже, отлично умеют распознавать старый движок и спамить по формам описания и обсуждения товаров. Поэтому нужно к ним приделать капчу. Вся эта операция займет 10-15 минут. Первым делом, надо скачать отличный скрипт KCaptcha . Из архива надо извлечь полностью папку ‘fonts’ и файлы kcaptcha.php и kcaptcha_config.php. Сложить их в отдельную директорию на сервере, я, например, поместил их в ‘/kcaptcha’. После этого на основе примера надо написать маленький скрипт, который будет по запросу генерировать картинку и записывать код, отображенный на ней, в переменную сессии. Я сделал вот такой: <?php include('kcaptcha.php'); session_start(); $captcha = new KCAPTCHA(); $_SESSION['captcha_keystring...

Значение именованного параметра

Совсем крошечный метод, который можно поместить в AppController. Возвращает значение именованного параметра, или null , если такого параметра нет. Просто чтоб не повторять одинаковый код в разных методах. /************************************ * Returns a value of named parameter * or null if it isn't exists ************************************/ protected function named($paramName) { if (!array_key_exists($paramName, $this->params['named'])) { return null; } return $this->params['named'][$paramName]; }

Составные первичные индексы и CakePHP

Общеизвестный факт: CakePHP не поддерживает составные первичные индексы. Разработчики предлагают добавить в качестве первичного индекса поле id, а составной индекс из нескольких полей просто сделать уникальным. Это, в общем-то, разумно — первичный индекс используется в моделях для установления и проверки связей, поэтому добавление процедур для работы с составными индексами неплохо увеличит объем кода, что, в свою очередь, скажется на производительности. Более того, использование составных индексов в качестве первичных — редкое явление, хотя я сходу придумал пару ситуаций когда это оправданно. Схема с добавлением еще одного поля, предлагаемая разработчиками Cake неплохо функционирует, однако контроль за уникальностью составного индекса перекладывается на веб-разработчика. Для определения, вставляется-ли новая запись (INSERT…) или обновляется старая (UPDATE…) при вызове из метода save(), Cake поступает очень просто: продеряет наличие в элемента массива $this->data[‘Model’][‘id’]...

Sitemap для Shop-Script

С недавних пор наш национальный поисковик присоединился к славной компании поисковиков, умеющих обрабатывать файлы sitemap . Наверное, это связано с какими-то общеланетарными амбициями. Как бы то ни было, теперь есть возможность скормить Яндексу файл(ы) sitemap . Я решил, что обрабатывать сайт какой-нибудь сторонней приблудой много дольше, чем просто сгенерировать файлы sitemap с помощью скрипта. Тем более, что у shop-script в общем-то довольно простая структура. Новая версия Shop-Script с ЧПУ пока недоступна, получу — модифицирую скрипт. :-) Скрипт простенький, делает sitemap для aux-страниц — это у shop-script так называются обычные статические html страницы; страниц с категориями. Без разбивки на страницы 1, 2 и т.д. на мой взгляд эти страницы не слишком важны страниц с товарами и обсуждениями товаров Можно запускать из браузера, можно по cron’у. Корневую страницу сайта, страницу с новостями, страницу с формой обратной связи и т.п. надо записать в отдельный файл sitemap ...

У ZendFramework теперь есть полноценный layout

Модуль Zend_Layout перебрался из инкубатора в основную ветку. Ура! Непонятно почему создатели этого фреймворка не начали с создания именно удобной структуры самого паттерна MVC, а озаботились совершенно второстепенными вопросами. И только теперь дело дошло до правильных View. Шустрые пользователи ZendFramework уже настрочили неплохой пример использования: http://akrabat.com/2007/12/11/simple-zend_layout-example/

Построение деревьев

Небольшое введение . Весь пост написан с оглядкой на MySQL, из-за ее распространенности в web. Конечно, у Oracle возможностей больше, но хостинг с Oracle (или, например, с PostgreSQL) поискать еще надо. Нас же интересует практическое применение в веб-приложениях и обычных сайтах. Для построения сложных систем вообще надо сильно подумать над возможностью применения реляционной БД и рассмотреть другие варианты. Ведь не строчно-табличным видом все БД ограничиваются. Основным посылом к написанию этого поста послужили частые обсуждения темы хранения древовидных структур на различных форумах и комьюнити. Я с удивлением узнал, что многие люди просто не знают методов, отличных от первого, " родитель-дети ". Я точно помню, что в начале 90-х видел статью, посвященную этой проблеме, но уже не помню где. Может, вPC Magazine или в Компьютерпресс? Может даже это было в безруковской Софтпанораме. Так или иначе статья я не нашел, может, плохо гуглил. Родитель-дети Это самый распростране...

Pagination в CakePHP 1.2. Небольшая хитрость

Этот пост устарел! Читайте по ссылке исправленную и сильно переработанную версию ! This is totally outdated article! Follow the link to see a more complete version! Sorry. The newwer post in russian too. Как уже писал , Containable behaivior , который отлично справляется с задачей выборки только нужных для данного действия (action). И при небольшой модификации отлично работает с методом pagination . Однако есть одна неприятная вещь, опять же связанная с тем, что pagination вызывает последовательно 2 метода модели — сначала для подсчета количества записей, а потом для выборки. При попытке подсчитать количество записей у модели с большим количеством связей, paginator делает SQL запрос SELECT COUNT(*) со всеми положенными JOIN'ами, что при больших объемах данных существенно увеличивает время выполнения запроса. Особенно, если при этом еще и сортировку делать надо. Этот факт сильно раздражает, если в итоге нужно всего-лишь количество записей в основной модели. Выход есть. ...

Модели в CakePHP

Беда какая-то с реализацией моделей в Cake. Не то, чтобы совсем уж плохо, или не то, чтобы их совсем нет, как в Zend Framework , но реализация пока хромает. Особенно с рекурсией туго. Т.е. если 1 уровень рекурсии, то все хорошо, но если нужно 2 уровня, то уже плохо. Например, есть у нас модель "Лекарство", связанная с моделями "Производитель" и "Цена", а "Цена" связана с моделью "Валюта". Связи примерно такие: Лекарство belongsTo Производитель Производитель hasMany Лекарство Лекарство hasOne Цена Цена belongsTo Валюта Обратная связь от Производителя — чтоб можно было получить все продукты, ему принадлежащие. Однако при попытке получить данные о лекарстве получается полная фигня — либо, при recursive=1 не получаем Валюту, либо при recursive=2 получаем на втором уровне все продукты от Производитель. Для этого есть несколько решений. как для версии 1.1, так и 1.2. Чаще всего предлагается сде...

Программистские приколы

Наткнулся на цитату, говорят, из книги "Deep C Secrets". Гуглить первоисточник лень, но история понравилась. When the ANSI C standard was under development, the pragma directive was introduced. Borrowed from Ada, #pragma is used to convey hints to the compiler, such as the desire to expand a particular function as in-line or suppress some range checks. #pragma met with some initial resistancee from a gcc implementor, who took the "implementation-defined" effect very literally. In gcc version 1.34, the use of pragma caused the compiler to stop compiling and launch a computer game instead. The gcc version 1.34 manual said: "The #pragma command is specified in the ANSI standard to have an arbitrary implementation-defined effect. In GNU C preprocessor, #pragma first attempts to run the game "rogue"; if that fails, it tries to run the game "hack"; if that fails, it tries to run GNU Emacs displaying Tower Of Hanoi; if that fails, it reports a fat...

На всякого мудреца...

Некоторое время назад при заполнении всяких регистрационных форм стало модно вводить циферки-буковки со специально сгенерированной картинки. Дескать, для проверки, что регистрируется человек, а не злобная спаммерская программа. Считается, что прикрутить распозновалку графических изображений довольно сложно, проще найти форум (почтовую службу и т.д.) которая не требует такой регистрации. Но есть метод проще . Я просто в восторге от простоты и изящества решения :)

Немного программизма: PHP и файлы CSV

Пришлось тут решать одну небольшую задачу, переносить номенклатуру товаров в несколько баз данных, а именно добавлять сразу много (порядка 100 тыс. позиций) в магазин, построенный на Bitrix и в магазин, построенный на Script-Shop . Для начала, чтоб не делать одну работу дважды, организовал некую базу, из которой решил сделать экспорт в форматы для каждой из систем. Ну, про ограничение в 65535 строк в одном листе Microsoft Excel я заранее был в курсе, неожиданностью для меня это не стало. Максимально увеличил в php параметр выполнения скрипта, чтобы браузер не отваливался по таймауту и, совершенно неожиданно, наступил на интересные детские грабли. Каждый раз при выполнении функции fgetcsv запрашивается новый кусок памяти, причем использовать предыдущий совершенно невозможно. Т.е. в зависимости от настроек сервера и PHP, скрипт по импорту падает из-за нехватки памяти после обработки 10 или 20 тыс. строк. Дальнейший тюнинг параметров PHP в плане увеличения доступной скрипту памяти ок...

Немецкий взгляд на жизнь

В очередной раз получил подтверждение тому, что немцы мыслят совршенно иначе, чем все остальные нации. Впервые с этим столкнулся, пытаясь настроить видеомагнитофон Grundig. Было это лет 15 назад. В отличие от двух других, бывших у меня в то время (соня и панас), без инструкции не справился. Не потому, что меню на немецком, его-то я быстро на инглиш переключил, а вот расположение пунктов настройки и последовательность действий... Второй звоночек прозвенел при попытке разобраться с инженерной программой CADdy продаваемой фирмой Ziegler. Ну, встроенный макроязык с немецкоязычными операторами это полбеды. Но опять же, алгоритм взаимодействия с пользователем, четкая последовательность операций, рассчитаные, видимо, на педантичных немцев, выводили из себя конкретно. Юзер мануал поверхности моего стола не покидал. Хотя в пиратской версии автокада все получалось и без мануалов. Немцы мыслят по-другому, наверное. Про имевшие место у меня немецкие автомобили -- отдельный разговор. В очередной...