PHP библиотека для создания компонентов Twitter Bootstrap проще и быстрее.
Скачать Требования PHP 5.3 и Bootstrap 2.3
Работая над админкой своего проекта (админка делается на Bootstrap) обнаружил, что мне очень не хватает возможности прямо из php формировать содержание элементов Bootstap.
Например:
... и множество других вещей, также хотелось формировать прямо в php коде.
Кроме того на сайте уже были использованы хлебные крошки, навигация, pager и некоторые другие компоненты Bootstrap.
Чтобы иметь только один файл шаблон для каждого компонента, а не множество на каждый случай использования, я создавал классы конструкторы, которые позволяли наполнить и кастомизировать каждый компонент. Когда их стало значительно количество, решил выделить их в отдельный проект, а потом пришел к мысли, что это может быть полезно не только мне.
Так зачем библиотека вам? Прочитайте историю появления выше, и если у вас похожая ситуация, то рано или поздно вы придете к тому что вам потребуется что-то подобное.
Что делает эту библиотеку такой замечательной так это автодополнение. Используя
автодополнение и подсказки phpdocs, вам не придется обращаться к этой документации.
Смотрите сами:




Скачайте архив с библиотекой и распакуйте в любой директории.
Для того что бы не беспокоиться о подключении классов регистрируем функцию автозагрузки.
<?php use BootstrapPHP\BootstrapPHP; include 'BootstrapPHP/BootstrapPHP.php'; BootstrapPHP::register_autoload(); ?>
Все, библиотека готова к работе.
Любой компонент можно создать двумя способами. Посмотрим на примере компонента Button.
<?php
use BootstrapPHP\Button;
// Превый способ (не рекомундуется)
$button = new Button('Текст на кнопке');
// Второй способ (рекомендованный)
Button::create('Текст на кнопке');
?> Полное имя класса кнопки \BootstrapPHP\Button для более короткой записи используется
use BootstrapPHP\Button. В дальнейших примерах блок с use может быть
пропущен.
Почему рекомендован второй способ?
<?php
Button::create('Текст на кнопке')->setTag(Button::TAG_BUTTON);
// Вместо
$button = new Button('Текст на кнопке');
$button->setTag(Button::TAG_BUTTON);
?> Bootstrap.PHP включает в себя не все компоненты, которые есть в Bootstrap. Для включения в библиотеку были выбраны только те, которые скорее всего будут использовать как есть, то есть с внесением в их код минимальных изменений. Вряд ли вы будете что-то сильно менять в кнопках Bootstrap’а или в панели навигации, их функционала достаточно. Чего не скажешь, например, о таблицах или формах, конструкторы которых, могли бы быть отдельными большими проектами.
Но все же, минимальная гибкость нужна, например, для задания идентификатора, добавления классов или data атрибутов. Для этого у каждого объекта компонента есть свойство attributes.
<?=
Button::create('Кнопка с заданными атрибутами')
->attributes->setId('myButton')
->attributes->addClass('class_1')
->attributes->addClass(array('class_2', 'class_n'))
->attributes->addData('name-1', 'value 1')
->attributes->addData(array('name-2' => 'value 2', 'name-n' => 'value n'));
?> Результат:
<a id="myButton" class="btn class_1 class_2 class_n" data-name-1="value 1" data-name-2="value 2" data-name-n="value n" > Кнопка с заданными атрибутами </a>
Если вы используете цепочку вызовов как показано в примере, то использовать свойство attributes лучше не в одной цепочке с методом create, так как это сломает авто дополнение, при дальнейшем использовании. Используйте прием как показано ниже.
<?php
// Так будет сломано авто дополнение
$button = Button::create('Кнопка')
->setType(Button::TYPE_PRIMARY)
->attributes->addClass('class');
// Вот так правильно
$button = Button::create('Кнопка')
->setType(Button::TYPE_PRIMARY);
$button
->attributes->addClass('class');
?> И тот и другой работают одинаково, но второй способ позволит пользовать авто дополнением для
$button в дальнейшем.
У сложных объектов у которых есть методы добавляющие в них элементы, атрибуты можно добавлять элементам.
<?=
DropdownMenu::create()
->addLink(
'Пункт выпадающего меню', '/link/', false, false, false,
Attributes::create()->setId('myDropdownMenuLink')->addClass('class')
)
?> Результат:
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu"> <li> <a id="myDropdownMenuLink" tabindex="-1" href="/link/" class="class"> <i class="i"></i> Пункт выпадающего меню </a> </li> </ul>
Практика показала, что атрибуты нужно добавлять именно ссылке, а не элементу списка, так как Bootstap’ом data атрибуты проверяются у ссылок.
Нигде в проекте, где можно задать произвольный текст, не используется обработка введенного текста, текст вставляется как есть. Это значит, что везде можно использовать html и он будет вставлен как html. Это сделано для большей гибкости, так как моя собственная практика показала, что в реальном проекте без этого не обойтись. Хотя бы для того, чтобы добавить иконку рядом с текстом, в тех местах, где в проекте специально это не предусмотрено.
<?=
Label::create(Icon::create(I::TYPE_HAND_LEFT, true).' Метка с иконкой');
// или так если считаете что для создание иконки использовать php это перебор
Label::create('<i class="icon-hand-left icon-white"></i> Метка с иконкой');
?> Получить готовый html код объекта можно двумя способами. Выбирайте тот, что больше нравится.
<?php
// Первый способ (приведение объекта к строке приводит к вызову метода __toString())
echo Button::create('Текст на кнопке');
// Если хочется посмотреть получившийся html
var_dump((string) Button::create('Текст на кнопке'));
// Второй способ (вызов специального метода toHtml())
echo Button::create('Текст на кнопке')->toHtml();
?> <?=
Button::create('Обычная кнопка', '/link/')
?> <?=
Button::create('Заблокированная кнопка занимающая всю доступную ширину', '/link/', Icon::TYPE_DOWNLOAD)
->setType(Button::TYPE_PRIMARY)
->setWidth(Button::WIDTH_BLOCK)
->setEnable(false);
?> <?=
Button::create('Маленькая кнопка переключатель')
->setSize(Button::SIZE_SMALL)
->makeToggle()
?> <?php
echo Button::create('Тег по умолчанию')->setTag(Button::TAG_DEFAULT);
echo Button::create(htmlspecialchars('<a>'))->setTag(Button::TAG_A);
echo Button::create(htmlspecialchars('<button>'))->setTag(Button::TAG_BUTTON);
echo Button::create(htmlspecialchars('<input>'))->setTag(Button::TAG_INPUT);
?> <?=
Button::create('Нажми на меня')
->setLoadingText('Loading ...')
->attributes->setId('myLoadingButton');
?>
<script type="text/javascript">
$('#myLoadingButton').click(function(){
$(this).button('loading');
return false;
});
</script>
Иконку можно создать использую класс Icon или I которые являются синонимами.
<?= I::create(I::TYPE_USER); ?>
В большинстве случаев вам не придётся иметь дело с созданием иконки с помощью объекта, так как у тех компонентов, которые часто исползают совместно с иконками есть параметр функции для ее добавления. В нем вы можете использовать как просто константу иконки так и объект иконки. Объект иконки необходим если вы принудительно хотите сделать иконку белой или черной.
<?php
echo Button::create('Кнопка с иконкой', false, I::TYPE_USER)
->setType(Button::TYPE_SUCCESS);
echo '<br>';
// или так
echo Button::create('Кнопка с иконкой', false, I::create(I::TYPE_USER , false)) // делаем черной
->setType(Button::TYPE_SUCCESS);
?>
<?=
DropdownMenu::create()
->addLink('Действие')
->addLink('Другое действие (заблокировано)', '#', false, true)
->startSubmenu('Больше действий')
->addLink('Действие в подменю')
->addDivider()
->addLink('Еще одно')
->endSubmenu()
->attributes->addClass('show_dropdown_menu');
?> В функции добавления элемента списка есть аргумент «всегда снизу». Он необходим когда у вас есть например такой пункт как «Выход», который должен быть всегда внизу. Например, есть место где вы формируется основное содержание меню, в том числе «Выход», а при дальнейшей работе скрипта вам нужно добавить еще одну элемент.
<?php
$dm = DropdownMenu::create()
->addLink('Профайл', '/profile/', I::TYPE_USER)
// Ниже то что будет всегда внизу
->addDivider(true)
->addLink('Выход', '/logout/', I::TYPE_OFF, false, true)
->end(); // Метод для IDE для корректной работы авто дополнения в дальнейшем
$dm->attributes->addClass('show_dropdown_menu');
// много кода
$user = 'Admin';
if ($user === 'Admin')
{
$dm->addLink('Панель управления', '/dashboard/', I::TYPE_TASKS);
}
echo($dm);
?> Если с флагом «всегда снизу» было добавлено несколько пунктов они будут следовать внизу в том порядке в котором добавлены. Это видно в примере выше.
<?=
ButtonGroup::create()
->addButton(Button::create('', '#left', Icon::TYPE_ALIGN_LEFT))
->addButton(Button::create('', '#center', Icon::TYPE_ALIGN_CENTER))
->addButton(Button::create('', '#right', Icon::TYPE_ALIGN_RIGHT));
?> <?php
echo ButtonGroup::create()
->addButton(Button::create('CHECKBOX'))
->addButton(Button::create('CHECKBOX'))
->makeToggle(ButtonGroup::TYPE_TOGGLE_CHECKBOX);
echo ButtonGroup::create()
->addButton(Button::create('RADIO'))
->addButton(Button::create('RADIO'))
->makeToggle(ButtonGroup::TYPE_TOGGLE_RADIO);
?> <?=
ButtonGroup::create()
->addButton(Button::create('', '#', Icon::TYPE_ARROW_RIGHT))
->addButton(Button::create('', '#', Icon::TYPE_ARROW_DOWN))
->setAlign(ButtonGroup::ALIGN_RIGHT)
->setDirection(ButtonGroup::DIRECTION_VERTICAL)
?> <?=
ButtonToolbar::create()
->addButtonGroup
(
ButtonGroup::create()
->addButton(Button::create('<b>Ж</b>'))
->addButton(Button::create('<i>К</i>'))
)
->addButtonGroup
(
ButtonGroup::create()
->addButton(Button::create('', '#left', Icon::TYPE_ALIGN_LEFT))
->addButton(Button::create('', '#right', Icon::TYPE_ALIGN_RIGHT))
);
?> <?=
Button::create('Кнопка с меню')
->addDropdownMenu(
DropdownMenu::create()
->addLink('Ссылка 1')
->addDivider()
->addLink('Ссылка 2')
->end()
)
?> <?php
$dm = DropdownMenu::create()
->addLink('Ссылка 1')
->addDivider()
->addLink('Ссылка 2')
->end();
echo Button::create('С отдельной кнопкой')
->addDropdownMenu($dm, true);
echo Button::create('С выравниванием списка справа')
->addDropdownMenu($dm, true, true);
echo Button::create('С выпадением вверх')
->addDropdownMenu($dm, true, true, true);
?> <?php
/** @var Tabs $nav */
foreach(array(new Tabs(), new Pills()) as $nav)
{
echo $nav
->addItem('Ссылка 1 (активная)', '/1/', false, true)
->addItem('Ссылка 2', '/2/')
->addItem('Ссылка 3 (заблокирована)', '/3/', true)
->startDropdown('Выпадающее меню')
->addItem('Ссылка 4', '/4/')
->addDivider()
->addItem('Ссылка 5 (заблокировна)', '/5/', true)
->endDropdown()
->addItem('И еще одна ссылка', '/6/');
echo '<br>';
}
?> <?=
Pills::create()
->addItem('Ссылка 1 (активная)', '#', false, true)
->addItem('Ссылка 2', '#')
->addItem('Ссылка 3 (заблокировна)', '#', true)
->makeStacked();
?> <?=
Tabs::create()
->addContentItem('Раздел 1', 'section_1', 'Содержание раздела 1', false, true)
->addContentItem('Раздел 2', 'section_2', 'Содержание раздела 2')
->addContentItem('Раздел 3', 'section_3', 'Содержание раздела 3', true)
->makeFaded();
?> <?=
Tabs::create()
->setDirection(Tabs::DIRECTION_LEFT)
->addContentItem('Раздел А', 'section_a', 'Содержание раздела А', false, true)
->addContentItem('Раздел Б', 'section_b', 'Содержание раздела Б');
?> В выше приведенном примере важен порядок для корректной работы авто дополнения.
<?=
Breadcrumbs::create()
->addItems('Главная','/')
->addItems('Сатьи', '/articles/')
->addItems('О вреде курения');
?> <?=
Pagination::create()
->addItem(htmlspecialchars('<<'), '/first/', false, true) // передавать нужно иметь html
->addItem(htmlspecialchars('<'), '/back/', false, true) // об этом написано выше
->addItem('1', '/1/', true)
->addItem('2', '/2/')
->addItem('3', '/3/')
->addItem(htmlspecialchars('>'), '/next/')
->addItem(htmlspecialchars('>>'), '/last/')
->setSize(Pagination::SIZE_LARGE) // делаем большой
->setAlign(Pagination::ALIGN_CENTER); // выравниваем по центру
?> <?=
Pager::create()
->addItem('1', '/1/')
->addItem('2 <i>(заблокированный)</i>', '/2/', true)
->addItemPrevious('Предыдущий', '/back/')
->addItemNext('Следующий', '/next/', true);
?> Задать пользовательские стрелки можно следующих образом
<?php
echo Pager::create()
->addItemPrevious('Предыдущий', '/back/')
->addItemNext('Следующий', '/next/')
->setArrowLeft(htmlentities('<<'))
->setArrowRight(htmlentities('>>'));
echo Pager::create()
->addItemPrevious('Предыдущий', '/back/')
->addItemNext('Следующий', '/next/')
->setArrowLeft(I::create(I::TYPE_HAND_LEFT))
->setArrowRight(I::create(I::TYPE_HAND_RIGHT));
?> <ul>
<li><?= Label::create('TYPE_DEFAULT'); ?></li>
<li><?= Label::create('TYPE_INVERSE', Label::TYPE_INVERSE); ?></li>
<li><?= Label::create('TYPE_IMPORTANT', Label::TYPE_IMPORTANT); ?></li>
<li><?= Label::create('TYPE_INFO', Label::TYPE_INFO); ?></li>
<li><?= Label::create('TYPE_SUCCESS', Label::TYPE_SUCCESS); ?></li>
<li><?= Label::create('TYPE_WARNING', Label::TYPE_WARNING); ?></li>
</ul> <ul> <li><?= Badge::create(1); ?></li> <li><?= Badge::create(2, Label::TYPE_SUCCESS); ?></li> </ul>
<?php
echo Alert::create('<b>TYPE_DEFAULT</b> Cообщение для пользователя.');
echo Alert::create('<b>TYPE_SUCCESS</b> Cообщение для пользователя.', Alert::TYPE_SUCCESS);
echo Alert::create('<b>TYPE_INFO</b> Cообщение для пользователя.', Alert::TYPE_INFO);
echo Alert::create('<b>TYPE_ERROR</b> Cообщение для пользователя.', Alert::TYPE_ERROR);
?> <?=
// Для крупных сообщений используется 3ий параметр
Alert::create('<h4>TYPE_SUCCESS</h4> Cообщение для пользователя.', Alert::TYPE_SUCCESS, true);
?> <?php echo Progress::create(20, Progress::TYPE_INFO, '20% TYPE_INFO'); echo '<br>'; echo Progress::create(30, Progress::TYPE_SUCCESS, '30% TYPE_SUCCESS') ->makeStriped(); echo '<br>'; echo Progress::create(40, Progress::TYPE_DANGER, '40% TYPE_DANGER') ->makeStriped(true); echo '<br>'; echo ProgressStack::create() ->addBar(10, ProgressStack::TYPE_INFO, '10%') ->addBar(20, ProgressStack::TYPE_SUCCESS, '20%') ->addBar(30, ProgressStack::TYPE_DANGER, '30%'); ?>
<?php
echo Button::create('Максимально простое окно', '#simplestModal')
->attributes->addData('toggle', 'modal');
echo Modal::create('Заголовок', '<b>html тело</b>')
->attributes->setId('simplestModal');
?> <?php
echo Button::create('Плавно появляющееся окно с кнопкой закрыть', '#fadeModal')
->attributes->addData('toggle', 'modal');
echo Modal::create('Заголовок', 'Тело')
->makeFaded()
->addButtonClose()
->attributes->setId('fadeModal');
?> <?php
echo Button::create('Окно с пользовательскими кнопками', '#buttonsModal')
->attributes->addData('toggle', 'modal');
echo Modal::create('Заголовок', 'Тело')
->addButtonToFooter(Button::create('Да')->setType(Button::TYPE_PRIMARY))
->addButtonToFooter(Button::create('Нет')->setType(Button::TYPE_WARNING))
->addButtonClose('Отмена', true) // 2ой параметр перемещает кнопку левее остальных
->attributes->setId('buttonsModal');
?> <?php
$backdrops = array(
'BACKDROP_DEFAULT' => Modal::BACKDROP_DEFAULT,
'BACKDROP_ON' => Modal::BACKDROP_ON,
'BACKDROP_STATIC' => Modal::BACKDROP_STATIC,
'BACKDROP_OFF' => Modal::BACKDROP_OFF
);
$counter = 0;
foreach($backdrops as $backdrop_title => $backdrop_class)
{
$counter ++;
echo Button::create($backdrop_title, '#backdropModal'.$counter)
->attributes->addData('toggle', 'modal');
echo Modal::create($backdrop_title)
->setBackdrop($backdrop_class)
->attributes->setId('backdropModal'.$counter);
}
?> <?php
echo Button::create('По нажатию ESC окно не закрывается', '#keyboardModalNo')
->attributes->addData('toggle', 'modal');
echo Modal::create('Нажми Esc', 'окно не закрывается, а по умолчанию должно')
->setKeyboard(false)
->attributes->setId('keyboardModalNo');
?> <?php
echo Button::create('Окно с содержанием полученным по url\'у', '#bodyUrlModal')
->attributes->addData('toggle', 'modal');
echo Modal::create('В теле должно быть "Hello world"')
->setBodyUrl('modal_body.php')
->attributes->setId('bodyUrlModal');
?>
Для желающих убедиться в работоспособности библиотеки выкладываю тесты. Они покрывают полный функционал всех компонентов. В этом можно быстро убедиться - посмотреть тесты online, либо скачать исходный код.
Кстати эта страница с документацией сделана с помощью Bootstrap.PHP, что частично подтверждает ее работоспособность.