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, что частично подтверждает ее работоспособность.