Окт 22

Очень часто разработчик встречается с проблемой неверного отображения символов на странице (всегда используйте только UTF-8!). Причин тому может быть несколько. В общем случае на это влияют следующие факторы:

Проблемы с базой данных

1) База должна быть создана с такими параметрами:

charset - utf8

collation - utf8_general_ci

2) Текстовые поля в таблицах также должны иметь charset  utf8 и collation  utf8_general_ci

Проблемы с кодировкой файлов

Каждый файл сохраняйте в UTF-8 кодировке (ну и с Unix переносами строк, естественно :-)

Кодировка в Symfony

В symfony все просто - в файле databases.yml указываем кодировку, например:

all:
  propel:
    class:      sfPropelDatabase
    param:
      phptype:  mysql
      host:     localhost
      database: the
      username: root
      password: 123
      encoding: utf8
Окт 6

4 октября 2008 года прошел очередной конкурс “Программания” от компании (экс Validio) Global Logic. Это был 13 по счету конкурс, проходил он в здании Харьковского театра оперы и балета - народу было очень много. Стоит отметить, что в этом году конкурс проходил не только в Харькове, а еще в Киеве и Львове. Призы были стандартные (много было мониторов), главный приз - MacBook Pro :)
В этом году вопросы мне понравились - отвечал на темы PHP, Dynamic HTML, AJAX, XML, Основы SQL, English ну и совсем чуть чуть .NET.
Количество граблей было достаточным. Каждый второй вопрос, естественно, был с подвохом. Поделюсь с вами этими каверзными вопросами.

Dynamic HTML

1. Как будет выглядеть блок? (какой будет вид bordera?)

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<html>
<head>
<style>
 .red     { border:1px solid red;      }
 .blue    { border:1px solid blue;     }
 .yellow { border:1px solid yellow; }
</style>
</head>
<body>

<div class=red yellow blue>
  Block with border
</div>

</body>
</html>

И как вы думаете?
Ответ: на самом деле блок будет иметь ЖЕЛТУЮ рамку, т.к. CSS класс “yellow” был определен последним в секции style (а порядок задания классов в элементе не имеет значения).

2. Вопрос по поводу приведения типов в javascript:

Каким будет значение переменной a?

var a = 1 + 2 + “3″;

Ответ: 33
Javascript изначально выполнит сложение целых чисел, а потом произведет конкатенацию со строкой.

3. Подвох при работе со строками в javascript (replace)

Каким будет значение переменной s?

var s = “000,777,000,777″;
s = s.replace(“000″, “111″);

На первый взгляд, хочется сказать, что результирующая строка будет выглядеть так: “111,777,111,777″.
Но в действительности метод replace предназначен для работы с регулярными выражениями. В данном случае первый параметр - строка “000″ рассматривается как регулярное выражение и результатом будет строка “111,777,000,777″ (перестановка выполнится при первом нахождении подстроки “000″).
Если же вам нужно заменить подстроку в строке javascript, то следует добавить в регулярное выражение модификатор g (global):

var s = “000,777,000,777″;
s = s.replace(/000/g, “111″);

Здесь уже выполнится замена всех вхождений подстроки и результатом будет “111,777,111,777″.

4. Добавление комментария в div средствами DOM.

В принципе, ничего сложного. Просто никогда не пользовался - да и вообще не пойму кому такое нужно?
Например, есть div:

<div id=“block”>
 Нуждаюсь в комментарии
</div>

Добавление комментария:

document.getElementById(“block”).appendChild(document.createComment(“русский коммент”));

ИМХО, этот вопрос был включен с мыслью о том, что никто не использует это на практике. document.createComment встречается гораздо реже чем document.createElement :)

По PHP граблей было куда меньше, так что эти вопросы рассматривать не буду. Пожалуй, единственное, что было новым для меня - один момент относительно обработки исключительных ситуаций. Информацию эту узнал в тот же день, когда пошел на очередную пару по JAVA (я теперь каждую субботу еще и на JAVA хожу :).
Момент заключается в следующем: если у нас есть наследники класса Exception (например, MyException) и если в блоке try возможен выброс исключений родительского класса и класса наследника, то отлавливать их нужно в порядке от наследника до родителя. Следующий пример показывает корректный вариант следования блоков catch:

<?php
class MyException extends Exception
{
    public function __construct($msg, $code)
    {
        parent::__construct($msg, $code);
    }
}

try {
    throw new MyException(‘Some message’);    
}
catch (MyException $e) {
    echo “MyException”;
}
catch (Exception $e) {
    echo “Exception (base)”;
}
?>

Данный пример выводит строку “MyException” - попытка обработать исключение типа MyException удалась.
Но если поменять порядок блоков catch:

<?php
try {
    throw new MyException(‘Some message’);    
}
catch (Exception $e) {
    echo “Exception (base)”;
}
catch (MyException $e) {
    echo “MyException”;
}
?>

В этом случае сработает первый блок catch и результатом будет строка “Exception (base)”

Вот еще вспомнил вопрос, подвох в котором был касательно ссылок в PHP.

<?php
$a = 1;
$b = &$a;

unset($a);
echo $b;
?>

Значение переменной $b будет равно 1. Ссылка дает возможность переменным указывать на одно и то же содержание. Это не значит, что $b указывает на $a, поэтому значение $b по прежнему 1.

Пожалуй это все что хотел написать по данной теме.

Сен 30
PHP и XML
icon1 Snowcore | icon2 XML, php | icon4 09 30th, 2008| icon38 Comments »

Продолжаю свою подготовку к Zend exam. Zend Certification Study Guide (могу поделиться, кому нужно :), текущая тема - XML and Web Services.

PHP 5 предоставляет отличные средства для работы с XML документами. Одной из этих библиотек является SimpleXML.
Все объекты, созданные SimpleXML, являются экземплярами класса SimpleXMLElement. Рассмотрим на примере загрузку XML документа. У нас есть XML файл с информацией о продуктах в магазине следующего содержания (store.xml):

<?xml version=”1.0″ encoding=“UTF-8″ ?>
<store>
    <sku id=7705>
        <name>iPod classic</name>
        <price>330</price>
        <ean>0002520190555</ean>
    </sku>
    <sku id=1139>
        <name>ASUS A626</name>
        <price>310</price>
        <ean>0502770290391</ean>
    </sku>
    <sku id=783>
        <name>Sony iBook</name>
        <price>300</price>
        <ean>4506790441392</ean>
    </sku>
</store>

Загрузить XML документ можно несколькими способами. Первый способ предполагает использование функций simplexml_load_string и simplexml_load_file, которые возвращают объект SimpleXMLElement.

<?php
$xmlstr = file_get_contents(’store.xml’);
$store = simplexml_load_string($xmlstr);
?>
<?php
$store = simplexml_load_file(’store.xml’);
?>

Второй способ - использование конструктора объекта SimpleXMLElement.

<?php
$xmlstr = file_get_contents(’store.xml’);
$store = new SimpleXMLElement($xmlstr);
?>
<?php
$store = new SimpleXMLElement(’store.xml’, NULL, true);
?>

Пожалуй, самым интересным является последний способ. Загрузка XML через конструктор позволяет задать некоторые опции (второй параметр конструктора): все эти флаги начинаются на “LIBXML_”. При их помощи можно убрать пустые элементы (LIBXML_NOBLANKS), заменить entities (LIBXML_NOENT), отключить вывод ошибок и предупреждений (LIBXML_NOERROR), проверить загружаемый документ на валидность, используя DTD схему (LIBXML_DTDVALID) - подробное описание можно найти в мануале - глава “LXXVI. libxml Functions”.

После загрузки XML документа мы можем получить доступ к его элементам. Все элементы конвертируются в свойства объекта SimpleXMLElement, все атрибуты - в ассоциативный массив (имена элементов и атрибутов регистрозависимые):

<?php
foreach($store->sku as $sku)
{
 echo $sku[‘id’]  .‘<br />’;
 echo $sku->name  .‘<br />’;
 echo $sku->price .‘<br />’;
 echo $sku->EAN   .‘<br />’;
}
?>

Кроме этого SimpleXML предоставляет средства, при помощи которых можно узнать список всех элементов и атрибутов (и их имена).

SimpleXMLElement::children()
SimpleXMLElement::attributes()
SimpleXMLElement::getName()

Таким образом можно вывести XML, не зная имен элементов и атрибутов.

SimpleXML также позволяет выполнять запросы XPath (метод SimpleXMLElement::xpath(xpath_expression)). Данный метод возвращает массив элементов SimpleXMLElement. Например, мы можем получить названия всех товаров:

<?php
$productNames = $store->xpath(‘/store/sku/name’);
?>

или массив id всех товаров:

<?php
$productIDs = $store->xpath(‘/store/sku/@id’);
?>

Следует отметить, что XPath всегда возвращает массив объектов SimpleXMLElement (даже если результатом запроса является один элемент).

Изменение XML документа

В ранних версиях php (до 5.1.3), у SimpleXML не было возможности добавлять элементы и атрибуты в XML документы. Можно было только изменять существующие значения, но единственным способом добавления новых элементов и атрибутов было экспортирование SimpleXML объекта в DOM (используя функцию dom_import_simplexml). Добавление производится при помощи DOM (методы объекта DomDocument->create_element, DomDocument->create_attribute и др.). После этого DOM документ экспортируют обратно в SimpleXML (simplexml_import_dom). Согласитесь, не очень удобно.
С версией php 5.1.3 у SimpleXML появилось два новых метода SimpleXMLElement::addChild() и SimpleXMLElement::addAttribute().
Эти методы принимают 3 параметра - имя элемента (атрибута), его значение и пространство имен (опционально).
Рассмотрим на примере добавление нового продукта в наш документ store.xml:

<?php
$filename = ’store.xml’;
$store = new SimpleXMLElement($filename, NULL, true);
   
$newSku = $store->addChild(’sku’);
$newSku->addChild(‘name’, ‘Macbook Pro’);
$newSku->addChild(‘price’, ‘2400′);
$newSku->addChild(‘ean’, ‘1103610290850′);
    
$store->asXML($filename);
?>

В последней сроке используется метод SimpleXMLElement->asXML([filename]). Данный метод возвращает XML строку на основе текущего SimpleXMLElement, если определен параметр filename - то XML строка сохраняется в файл.

С XML можно работать при помощи DOM, но это будет рассмотрено уже в следующей статье.

Май 13
Symfony
icon1 Snowcore | icon2 php | icon4 05 13th, 2008| icon35 Comments »

Первым делом хочу поблагодарить своего коллегу YS-PRO за то, что он поведал мне об этом замечательном фреймворке (и за книгу “Definitive guide to symfony”).

Symfony - отлично продуманный и легкий в изучении фреймворк. Написан исключительно на PHP5. Он создан для быстрого создания веб приложений (большинство работы symfony сделает за Вас ;-) Не полный список преимуществ:

- простая установка и стабильная работа в Windows и *nix системах
- независимость от базы данных (поддерживаются MySQL, PostgreSQL, MS-SQL, SQLite, Oracle) - используется ORM (Propel + Creole)
- представление состоит из шаблонов и layouts, которые могут быть созданы дизайнерами без знания symfony

- поддержка автоматизированной валидации форм
- автоматическая очистка пользовательского ввода (для избежания SQL инъекций и XSS аттак)
- ЧПУ (человеко понятные урлы)
- Работа с Ajax, средства для постраничного вывода списков, их фильтрации и сортировки
- автоматизация создания административной части

Что ж, попробуем symfony на своем локальном Apache.

Скачать symfony можно здесь: http://www.symfony-project.org/content/download
Затем распаковываем архив на свой локальный сервер.

Большинство действий выполняются из командной строки при помощи утилиты symfony (/data/bin/symfony.bat). Так что сразу добавим ее в путь поиска Windows (PATH). Идем в Система->Свойства->Дополнительно->Переменные среды и добавляем путь к symfony.bat в переменную PATH.

Теперь создадим проект. Для этого добавляем пустую директорию (например helloSymfony) в корень symfony. Из коммандной строки вызываем symfony init-project helloSymfony (все комманды нужно вызывать из корневого каталога вашего проекта). Symfony создаст следующее дерево каталогов:

apps/
batch/
cache/
config/
data/
doc/
lib/
log/
plugins/
test/
web/

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

symfony init-app helloSymfonyApp

Symfony создаст такую структуру директорий:

apps/
helloSymfonyApp/
config/
i18n/
lib/
modules/
templates/
web/
index.php
helloSymfonyApp_dev.php

Теперь нам нужно сконфигурировать сервер. Делаем доступной для пользователя папку web (это будет корнем нашего сайта) - добавляем VirtualHost hello.
Здесь index.php - точка входа (Front Controller), а helloSymfonyApp_dev.php - точка входа для разработчика (symfony предоставляет средства отладки).

Приложение состоит из модулей (страниц). Добавим страницу home в наше приложение helloSymfonyApp:

symfony init-module helloSymfonyApp home

В следствии чего добавляется еще несколько директорий для модуля ;-)
Самым интересным здесь является сгенерированный класс в actions/actions.class.php

class homeActions extends sfActions
{
  public function executeIndex()
  {
    $this->forward('default', 'module'); // использование стандартного шаблона
  }
}

Это - сердце нашей страницы home - контроллер. Он выполняет некоторые действия (определяет данные для представления) и передает управление шаблону (представлению).
В кратце: каждый метод, начинающийся с executeЧТО-ТО передает управление шаблону под именем ЧТО-ТОSuccess.php, который находится в папке templates данного модуля (о других типах методов и шаблонов расскажу позже).

Теперь попросим symfony поприветствовать нас. Добавим новый метод в homeActions:

public function executeSayHello()
{
  $this->name = 'Geek';
  $this->date('d/m/Y');
}

Чтобы отобразить приветствие создаем шаблон sayHelloSuccess.php (в папке templates):

Symfony says: Hello,

Today’s date is

(смотрим в браузере http://hello/helloSymfonyApp_dev.php/home/sayHello/ )

Как видите, все очень просто: в контроллере мы задаем переменную как $this->имя_переменной, а в представлении она доступна, как обычная переменная.

To be continued… ;-)

Next Entries »