Вебдев, заметки на полях

  • Archive
  • RSS
  • задать мне вопрос

Git: изменение авторства коммитов

В продолжение предыдущей заметки о миграции из SVN.

Имеющийся репозиторий крутился под управлением Visual SVN Server и всем сотрудникам почему-то были выданы уродские логины вида Ivan_Petrov, не учитывавшие, к тому же, e-mail автора.

При переносе истории изменений в Git с той же командой можно немного схитрить, изменив авторство коммитов при помощи вот такого шелл-скрипта:

#!/bin/sh

git filter-branch --force --env-filter '

an="$GIT_AUTHOR_NAME" # автор коммита
am="$GIT_AUTHOR_EMAIL" # e-mail автора коммита
cn="$GIT_COMMITTER_NAME" # коммитер
cm="$GIT_COMMITTER_EMAIL" # e-mail коммитера

if [ "$GIT_AUTHOR_NAME" = "Ivan_Petrov" ]
then
    cn="Ivan Petrov"
    cm="ivan@petrov.com"
    an="Ivan Petrov"
    am="ivan@petrov.com"
fi

export GIT_AUTHOR_NAME="$an"
export GIT_AUTHOR_EMAIL="$am"
export GIT_COMMITTER_NAME="$cn"
export GIT_COMMITTER_EMAIL="$cm"
'

На что нужно обратить внимание:

  • ключ --force, который может потребоваться, если историю репозитория уже переписывали (см. пост про смену корневой папки)
  • переменные cn, cm, an, am. В небольших коллективах автор коммита и коммитер может являться одним и тем же человеком, в больших проектах коммитить может специалист с определенными полномочиями, в то время как авторство кода может принадлежать другому программисту.
  • if-then-блоков может быть неограниченное количество, хватит на всех членов команды
  • для проверки авторства доступна переменная $GIT_AUTHOR_EMAIL
Источник: GitHub
    • #git
  • 3 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Git: Сделать подкаталог репозитория корневым

Ситуация — жил-был SVN-репозиторий, в котором одновременно велась история двух частей проекта, условно клиентской и серверной. То есть — две папки, client и server.

При переходе к Git SVN-репозиторий, несмотря на попытку чекаута отдельной папки, выдергивает весь проект целиком, включая историю изменений.

В то же время, нам, по уму, теперь хочется иметь два отдельных репозитория на клиент и на серверную часть. Что делать?

Решение в лоб — сделать две копии Git-репозитория, и в каждой:

$ rm -rf server
$ git add .
$ git commit

Решение правильное:

$ git filter-branch --subdirectory-filter client HEAD
Rewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (199/199)
Ref 'refs/heads/master' was rewritten

Результатом работы станет переписанная история, из которой будут удалены все ссылки на папку server и объекты в ней.

Аналогично из истории можно удалить упоминания отдельного файла (например, кто-то по ошибке закоммитил огромный бинарник или выложил файл с паролями):
$ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD

Однако пользоваться этой командой, предназначенной для крайних случаев, следует с осторожностью и по возможности в отдельной ветке.

Источник: ProGit

По теме

  • git filter-branch
  • git-svn
    • #git
    • #svn
    • #git-svn
  • 3 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Yii + Bitrix

Нашел хороший, но неполный рецепт по склейке Yii и 1С-Битрикс. На этот раз захотелось мне из Yii-приложения лазить в базу через Bitrix API, однако вылезает фундаментальная проблема — конфликт имен классов (пространства имен не используются). Решение: в PhpStorm прогоняем по папке с фреймворком Yii функцию Replace in path (case sensitive, whole words only) для следующих пар слов:

CComponent → YiiComponent
CEvent → YiiEvent
CModule → YiiModule
CApplication → YiiApplication
CMenu → YiiMenu
После этого меняем имена файлов:
// в папке base
CComponent.php → YiiComponent.php
CModule.php → YiiModule.php
CApplication.php → YiiApplication.php
// в папке zii/widgets
CMenu.php → YiiMenu.php
Соответственно, если в приложении есть вызовы компонентов по старым именам ($this->widget('zii.widget.CMenu')) — нужно все переименовать. Дописываем в index.php:
// ..
require_once($yii);
// наш код
function __autoload($className)
{
    // подключаем файлы битрикса через автозагрузку
    include_once('../bitrix/modules/main/include/prolog_before.php');
    CModule::RequireAutoloadClass($className);
}

define("NO_BITRIX_AUTOLOAD", FALSE);

// сначала отключим автозагрузчик Yii, потом, после Битрикса, включим обратно
spl_autoload_unregister(array('YiiBase','autoload'));
spl_autoload_register('__autoload');
spl_autoload_register(array('YiiBase','autoload'));
// закончили
Yii::createWebApplication($config)->run();
Как пользоваться:
public function actionFoobar()
{
    if(CModule::IncludeModule('iblock'))
    {
    // если подключился модуль информационных блоков, можно работать...
    }
}

TODO: Разобраться, возможно, получится повесить prolog_before.php и prolog_after.php на события onBeginRequest и onEndRequest.

    • #yii
    • #bitrix
  • 5 months ago
  • Comments
  • Permalink
  • Share
    Tweet

Yii: хитрые ячейки в CGridView

Понадобилось мне компоновать значения некоторых полей модели при выводе в гридвью. Решение достаточно элегантное:

<?php

$this->widget('zii.widgets.grid.CGridView', array(
  'dataProvider' => $dataProvider,
  'columns' => array(
    array(
      'header'=>'Хитрая колонка',
      'value'=>'$this->grid->getOwner()->renderPartial(\'cells/_myCustomCell\', array(\'data\'=>$data),true',
      'type'=>'raw',
    ),
  ), 

Как это работает

В папке с вьюшками контроллера, который выводит гридвью на экран создаем папку cells, а в ней по желанию файлы вьюшек (в нашем случае это _myCustomCell), где данные модели доступны через переменную $data (а не $model, что важно). После этого в коде объявления колонки мы указываем значение, и выводим «сырое» ('type'=>'raw') представление данных — то есть голый неэкранированный HTML из вьюшки.

По теме:

  • Хитрая группировка ячеек
  • Использование $data в массиве htmlOptions
    • #yii
    • #gridview
    • #cgridview
    • #datacolumn
    • #custom cells
  • 1 year ago
  • 1
  • Comments
  • Permalink
  • Share
    Tweet

Yii: MySQL bit и его проблемы

При разработке проекта столкнулся с проблемой — для поля типа bit в MySQL-базе данных не получалось вывести его реальное значение в Yii. Вместо нуля или единицы приходил нечитаемый символ, отображающийся квадратиком. Изначально я хотел использовать поле для чекбоксов, но естественно, с такой проблемой они не заработали.

Оказалось, проблема не столько в Yii, сколько в самом MySQL, где bit является плохо работающим костылем. Так что лучше по старинке, использовать tinyint(1)

    • #yii
    • #mysql
    • #bit
  • 1 year ago
  • Comments
  • Permalink
  • Share
    Tweet

Yii: сохраняем незаполненные поля формы как NULL

В модели прописываем правило:

protected function rules()
{
	return array(
		...
		array('yourField, yourField2', 'default', 'setOnEmpty' => true), 
		...
	);
}

Все!

    • #yii
    • #models
    • #forms
  • 1 year ago
  • Comments
  • Permalink
  • Share
    Tweet

Yii: забиваем данными dropDownList или radioButtonList

С формами редактирования простых полей типа varchar(25) нет ничего сложного — рендерим $form->textField($model->myField) и дело с концом.

Другой вопрос, если необходимо рендерить, скажем, <select>, да еще и забивать его значениями, которые периодически меняются. Менять этот набор значений во вьюшке не очень красиво, поэтому есть такое решение:

// вставляем в модель
public function getMyOptions()
{
	return array('value1'=>'label1', 'value2' => 'label2');
}

// вставляем во вьюшку
$form->dropDownList($model, 'myField', $model->myOptions);

Другой вариант, если список таких опций хранится в другой модели, или берется из базы данных, а не из «словаря»:

//во вьюшке пишем
$myOptionsModel = OptionsModel::model()->findAll(
	array('order' => 'id') // сортировка только для примера
);
$myOptions = CHtml::listData(
	$myOptionsModel,
	// поле модели $myOptionsModel, из которого будет взято value для <option>
	'someKeyField', 
	// поле модели $myOptionsModel, из которого будет взята подпись для <option>
	'someValueField' 
);
echo $form->dropDownList($model, 'myField', $model->myOptions);
    • #php
    • #yii
    • #models
    • #widgets
  • 1 year ago
  • Comments
  • Permalink
  • Share
    Tweet

Radio buttons

На днях в рассылке localize.drupal.org был задан вопрос о том, как переводить «radio button». Radio button, если что, это элемент пользовательского интерфейса, позволяющий сделать единственный выбор между несколькими заранее заданными опциями.

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

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

Old car radio

    • #ui
  • 1 year ago
  • Comments
  • Permalink
  • Share
    Tweet

Yii: как избавиться от index.php

Первое, что хочется изменить под себя, когда начинаешь разработку на Yii: отключить показ index.php в адресах.

Странно, что такое поведение включено в стандартную поставку.

Решение довольно простое.

Первое, что нужно сделать, это изменить в конфигурационном файле секцию urlManager:

'urlManager'=>array(
	'urlFormat'=>'path',
	// добавляем нижеследующую строчку
	'showScriptName'=>false,
	'rules'=>array(
		'post//'=>'post/view',
		'posts/'=>'post/index',
		'/'=>'/',
	),
),

Второй шаг — надо создать файл .htaccess (еще одна странность стандартной поставки):

RewriteEngine on

# если файл или директория существуют, отдать их напрямую
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# в противном случае вызвать index.php
RewriteRule . index.php

Готово!

Еще по теме:

  • Официальная документация на тему управления адресами
    • #yii
    • #webdev
    • #snippets
    • #SEF
    • #ЧПУ
  • 1 year ago
  • 12
  • Comments
  • Permalink
  • Share
    Tweet

Правильные кнопки

Неправильный контрол

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

Плохой пример: кнопка на картинке выше состоит из «спрайта» и вот такого кода:

<input type="submit" class="submit" onclick="App.interestsFormSubmit()" value="" id="submit" name="submit" style="background-position: 0px 0px; ">

Здесь две ошибки. Первая ошибка — не прописан value у инпута. Это значит, что кнопка как минимум без текста, как максимум браузер туда подставит свое дефолтное значение вроде «Отправить данные», если вдруг стили не подгрузятся, или их заменят на другие.

Вторая ошибка — опрометчивое использования текста-картинки в качества замены value фоном.

Третья, (не)ошибка, но не устраивающая меня вещь — в принципе неуниверсальное решение, которое начнет приносить проблемы, если размер текста на кнопке или его длина внезапно поменяются. Иначе говоря — кнопка не резиновая.

Наткнулся на такой дурной код я тогда, когда понадобилось сайт перевести один на английский язык. Если с текстами Zend Framework и $this->view->translate() еще справлялись, то вот с таким чудом техники придется расчехлять фотошоп и ковырять PSD.

Как бы там ни было, для решения проблем и просто по теме советую две статьи Сергея Чикуенка:

  • для широких и не очень кнопок
  • для любых кнопок вообще
  • 1 year ago
  • Comments
  • Permalink
  • Share
    Tweet

Создание региональных версий сайта, часть первая. Шаблоны

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

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

Ситуация несколько усложняется тем, что для этих регионов шаблоны сайта немного различаются, но в то же время, в большинстве своем похожи и используют одни и те же стили, скрипты, разметку.

Сейчас подсайтов два, а что, если завтра будет три, четыре, десять? Не копипастить же одно и то же.

После пары недель размышлений пришел к вот такому варианту. Подозреваю, что изобрел велосипед, и может быть в каком-нибудь приличном шаблонизаторе это уже придумано, но у нас Битрикс, детка, и в качестве шаблонизатора там собственно PHP, что, в принципе, очень ок. По крайней мере это дает известную свободу — имея на руках header.php и footer.php можно внутри них делать что душа пожелает.

Итак, сначала шаблон необходимо разбить на логические блоки. Шапка, тело, подвал, сайдбары, в сайдбарах отдельные блоки (поиск, обратная связь, и т.п).

Структура папок для всего этого такая:

|---includes
|       |---templates
|       |        |---blocks
|       |        |     |---rb
|       |        |     |---moscow

Таким образом, на каждый блок надо иметь как минимум один файл имяблока.php, который будет лежать в папке дефолтного региона, и будет общим для всех. Если блок для показа в другом регионе нужно изменить, надо иметь в подпапках соответствующие копии.

За показ блока в шаблоне отвечает другая функция:

function renderBlock($block, $region_specific = false) {
	$include_path = $_SERVER['DOCUMENT_ROOT'].'/includes/templates/blocks/';

	// если блок регионозависим — подключаем из другой папки
	if($region_specific == true)
	{
		$include_path .= detectRegion();
	}
	else
	{
		$include_path .= 'rb';
	}
	$include_path .= '/'.$block.'.php';
	
	// вставляем
	require_once($include_path);
}

В шаблоне блок вызывается вот так, например:

<?
	renderBlock('feedback');
?>

Если функцию вызвать со вторым параметром, установленным в true, будет подключен файл для конкретного региона.

Кстати о регионах. В моем случае определение региона посетителя происходит после ручного выбора города на сайте через <select>, поэтому примитивная функция считывает информацию из куков:

function detectRegion() {
	// в любой момент функцию можно усложнить по ситуации
	// но мне пока и так хватает :)
	if($_COOKIE['city'] == 'moscow')
	{
		return 'moscow';
	}
	else
	{
		return 'rb';
	}
}

Таким образом, каждый шаблон представляет собой последовательность подключенных файлов-блоков, где в любой момент можно включить «регионозависимость».

Пока вроде работает, посмотрим, как зарекомендует себя со временем.

P.S. При виде вышеописанного почему-то в памяти всплывают регионы и блоки Друпала, но какая теперь разница :)

    • #bitrix
    • #битрикс
    • #создание региональных версий сайта
    • #webdev
    • #php
    • #шаблонизатор
  • 1 year ago
  • 2
  • Comments
  • Permalink
  • Share
    Tweet

Подсветка синтаксиса в Tumblr

Сразу встала необходимость подсвечивать куски кода, которые я сюда собрался выкладывать, поэтому озадачился решением.

Решение оказалось простым и элегантным!

Идем в Customize appearance, в настройках темы включаем Custom HTML, тема предстает перед нами в виде исходника. Код из поста по ссылке советую разделить — скрипты вставить перед </body>, а стили подключить перед стилями темы в хедере, тогда можно их переопределить. Например я сразу прописал

pre.prettyprint {
	border:0;
	padding:1em;
}

и все стало довольно симпатично.

    • #syntax highlight
  • 1 year ago
  • Comments
  • Permalink
  • Share
    Tweet

Привет всем.

Тут, пожалуй, будет мой вебдев-бложик, вдали от уютной жежешки.

  • 1 year ago
  • Comments
  • Permalink
  • Share
    Tweet

About

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

Кратко о себе — бывший «только верстальщик», ныне, скорее, фронтенд-девелопер с редкими вынужденными углублениями в бэкенд-кодинг.

В силу обстоятельств поддерживаю IE6, что накладывает определенные ограничения на решения, которыми мне приходится пользоваться.

Twitter

loading tweets…

  • RSS
  • Random
  • Archive
  • задать мне вопрос
  • Mobile

Надеюсь, нагло тырить отсюда никто ничего не будет. Имейте совесть. Effector Theme by Carlo Franco.

Powered by Tumblr