Google+

SEO для сайта на AngularJS своими руками

Одностраничные приложения на AngularJS всем хорошои, кроме того, что поисковые системы пока что не могут (или не хотят) нормально индексировать их страницы. Часть ботов не умеет яваскрипт полностью, другие - в очень ограниченном объёме.

В наличии имеется AJAX сайт за nginx на CentOS 6, хочется обойтись минимальными телодвижениями для обеспечения его индексации. Основная идея - исполнять приложение в каком-нибудь headless браузере и отдавать результат поисковику.

Подготовка к сканированию

В секцию head главной страницы вставляем <meta name=”fragment” content=”!” />. Увидев такое, поисковики понимают, что на этой странице есть содержимое, которое генерируется яваскриптом, но при этом доступное по запросу, сформированному специальным образом. Подробности и полная спецификация есть у гугла и яндекса.

Вкратце, происходит вот что:

Программное добавление HTTPS-привязки к сайту IIS

В рабочем проекте на ASP.NET MVC понадобилось дать пользователям сайта возможность самим добавлять доменные имена для существующего сайта.

Для управления IIS 7+ существует библиотека Microsoft.Web.Administration. Добавляем её в проект через NuGet

Install-Package Microsoft.Web.Administration

CakePHP — MongoDB session storage

Для того, чтобы сохранять сессии в MongoDB нам понадобятся:

1. сам MongoDB

2. php-драйвер монго

3. источник данных для CakePHP MongoDB Datasource

скачиваем плагин и кладем его в my/app/plugins/mongodb или забираем гитом

cd my/app/plugins
git clone git://github.com/ichikaway/cakephp-mongodb.git mongodb

дальше в database.php описываем новое подключение

public $mongo = array( 
    'driver' => 'mongodb.mongodbSource', 
    'database' => 'sessions', 
    'host' => 'localhost',
    'port' => 27017,
);

создаем модель Session, в ней описываем схему данных (хотя монго и schemaless, но кэйк сохраняет только те поля, которые описаны в схеме)

class Session extends AppModel {
    public $mongoSchema = array(
        'id' => array('type' => 'string'),
        'data' => array('type' => 'string'),
        'expires' => array('type' => 'integer'),
    );
}

в core.php задаем новые параметры хранения сессий

Configure::write('Session.save', 'database');
Configure::write('Session.model', 'Session');
Configure::write('Session.database', 'mongo');

все получилось:

session

Autocomplete in views — Netbeans 6.9 + CakePHP 1.3

Старый трюк с хелперами в отдельном файле для вьюх в Netbeans 6.9 работать перестал, да и в грядущем CakePHP 2.0 хелперов отдельными переменными во вьюхах не будет. Поэтому вот как надо поступить, чтобы наслаждаться правильным автокомплитом:

  1. Добавляем в проект файл autocomplete.php c таким вот содержимым
/**
* @property HtmlHelper $Html
* @property FormHelper $Form
* @property JsHelper $Js
* @property NumberHelper $Number
* @property PaginatorHelper $Paginator
* @property RssHelper $Rss
* @property SessionHelper $Session
* @property TextHelper $Text
* @property TimeHelper $Time
*/
class AutocompleteView extends View {
}

2. В каждой вьюхе пишем в самом начале (да, не очень изящно, но зато работает):

<?php/* @var $this AutocompleteView */?>

3. Готово

IDE screenshot

UPD. для массовой вставки строчки в начало шаблонов можно воспользоваться следующей командой (linux/cygwin)

find -name "*.ctp" -print0 | xargs -0 sed -i "1i <?php /** @var \$this AutocompleteView */ ?>"

Scope Behavior

У меня возникла такая ситуация, что несколько сайтов с одинаковым движком используют одни и те же таблицы в одной базе данных. Для различения принадлежности записей в бд к сайтам используется поле site_id. Добавлять его к каждому запросу в условия довольно утомительно, поэтому я сделал специальный behavior для этой цели — Scope.

в модели (например, User) добавляем behavior и передаем ему настройки

var $actsAs = array(
    'Scope.Scope' => array(
        'field' => 'site_id',
        'value' => SITE_ID,
    )
);

теперь при вызове функций модели find или save условие будет добавляться автоматически, то есть

$this->User->find('all');

будет эквивалентно

$this->User->find('all', array(
    'conditions' => array(
        'User.site_id' => SITE_ID,
    )
);

Пользоваться, конечно, следует с осторожностью, так как некоторые операции, например updateAll и deleteAll c $cascade=false работают напрямую с источником данных и behavior остается не у дел (deleteAll c $cascade=true будет работать как и ожидается, с подстановкой параметров).

Исходный код лежит на гитхабе - http://github.com/evilbloodydemon/cakephp-scope

Замечания и предложения приветствуются.

Произвольная хэш функция для аутентификации в CakePHP

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

sha1(md5(‘SeCrEt’ . $password . ‘KeY’)).

Как с этим жить?

CakePHP хранит пароли следующим образом: поле пароля в БД = самый стойкий из доступных хэшей(открытый пароль + секретная соль)

Но на наш случай у компонента Auth припасено свойство authenticate (см. http://api.cakephp.org/class/auth-component) — ссылка на объект, который реализует функцию hashPassword.

И, собственно говоря, пример:

в файле app_controller.php помещаем класс для нашей хэш функции

class MyHash {
    public function hashPasswords($data) {
        if (is_array($data) && isset($data[‘User’])) {
            if (isset($data[‘User’][‘username’]) && isset($data[‘User’][‘password’])) {
                $data[‘User’][‘password’] = sha1( md5 (‘SeCrEt’ . $data[‘User’][‘password’] . ‘KeY’) );
            }
        }
        return $data;
    }
}

а в функции AppController::beforeFilter пишем строчку

$this->Auth->authenticate = new MyHash();

Готово!

Ускорение Netbeans

Netbeans — самая лучшая IDE для разработки на php, но иногда несколько задумчивая. Этот недостаток исправляется некоторыми настройками для java-машины.

В /etc/netbeans.conf или в ярлык для запуска IDE нужно добавить следующие опции

-J-client -J-Xms32m -J-Xmx384m -J-XX:PermSize=32m -J-XX:MaxPermSize=200m -J-Xverify:none -J-XX:CompileThreshold=100 -XX:+CompressedOOPS -XX:+AggressiveOpts -XX:+TieredCompilation -XX:+DoEscapeAnalysis -XX:+UseConcMarkSweepGC -J-XX:+CMSClassUnloadingEnabled -J-XX:+CMSPermGenSweepingEnabled

Таким образом мы разрешаем использовать до 384 мб памяти, компилировать в машинный код большинство функций и оптимизировать их.

Результат вас приятно удивит.

Netbeans CakePHP Bundle

Смастерил набор сниппетов для Netbeans, облегчающих разработку на фреймворке CakePHP. 50 для шаблонов отображения и 26 для php-кода. Источником вдохновения послужил оригинальный бандл для маковского редактора TextMate, в котором на скринкастах так ловко набирают километры исходных кодов для торта. Возможности у сниппетов в нетбинс не такие широкие, как у текстмэйта, но я постарался максимально сохранить оргинальное поведение.

Дистрибутив и репозиторий лежат на гитхабе

Установка очень проста:

  1. Cкачать последний релиз отсюда
  2. Запустить нетбинс
  3. Импортировать сниппеты (Tools -> Options -> Import)
  4. Перезапустить нетбинс
  5. Делать сайты в десять раз быстрее

Еще раз о Cake3

Введение

Да, да, я знаю. Такое уже было раньше. Что я могу сказать — у меня были вопросы, а у Nate были ответы. Это первая часть, в ней рассматриваются общие вопросы о CakePHP и Cake3.

Общие вопросы

Похоже что у CakePHP будут сразу три версии, это несомненно может запутать новых разработчиков. Я не видел официальных заявлений на этот счет, так что поправьте меня, если я не прав: — ветка 1.3 — для всех, кто пишет под PHP4 — ветка 2.0 — для тех, кто разрабатывает новые проекты под PHP5-5.2 или для тех, кто использует PHP 5.3 и хочет проапгрейдить приложения, написанные под CakePHP 1.2 — ветка 3.0 — для приложений на PHP 5.3

Почти верно. Как только ветка 1.3 станет стабильной, разработка версии 1.x прекратится, будут только исправляться ошибки и проблемы безопасности. Мы еще не определились с возможностью обратного портирования фич из 2.x, но это будет зависить от спроса на такую деятельность, чего не предвидится. и да, 2.0 позволит просто переносить приложения с 1.3 (его API практически не отличается от 1.2). 3.0, в свою очередь, находится в ранних стадиях разработки и не рекомендуется ни для чего, кроме экспериментов.

Cakephp 3.0

Сейчас очень мало информации о CakePHP 2.0 и особенно о суперновом 3.0, так что я решил провести небольшое интервью с Nate Abele, ведущим разработчиком CakePHP.

Привет, Nate, CakeFest завершился и слух об анонсе CakePHP 2.0 и Cake 3 постепенно распространяется. Можешь рассказать в общих чертах, что будет в новых версиях?

CakePHP 2.0 — это обновление текущей версии 1.x с переходом на строгую совместимость с PHP5, что означает, помимо выгоды от избавления от излишнего кода для поддержки PHP4, повышение производительности примерно на 25%.

Cake 3, с другой стороны, значительно отличается от текущей версии по ряду параметров. В основном тем, что с нуля переписан на PHP 5.3.

CakePHP 2.0 будет совместим с 1.x? Мы уже пережили значительный апгрейд с 1.1 на 1.2, апгрейд на 2.0 видимо будет еще более тяжелым?

Вообще-то, нет. CakePHP 2.0 будет практически 100% совместим на уровне API с грядущим CakePHP 1.3, который, в свою очередь, будет совместим с 1.2, за исключением некоторых устаревших (но еще работающих) методов.

Также, на случай миграции с 1.2 на 1.3/2.0, у нас есть инструкция, в которой будет сказано, какие небольшие изменения нужно будет внести в код существующих приложений.

Круто, то есть будет халявный прирост производительности для всех существующих 1.2 приложений?

Именно что.

Хорошо, вернемся к 3.0. Расскажи-ка немного о фундаментальных изменениях в PHP как языке и о том, как они повлияли на новое ядро CakePHP.