Создаем библиотеку видео в PHPixie

от автора

image
После моего предыдущего поста о выборе легкого Фреймворка я погуглил и увидел что некоторых из них нет ни одного русскоязычного туториала. Так вот я решил написать серию туториалов дабы заполнить эту нишу. Я думаю стоит начать с тех на которых я в конце остановился, а так как для Silex написано уже достаточно много то этот пост будет посвящен PHPixie.

Для тех кто не читал моего сравнения фреймворков, PHPixie — маленький и по моим меркам очень быстрый фреймворк с модульной структурой, хорошо реализованным DI, отсутствием статиков и простой архитектурой.

На официальном сайте все туториалы написаны на примере фей, я же попробую быть оригинальным и мы создадим библиотеку видео из Youtube. То есть мы сможем добавлять, удалять и просматривать видео. А еще по дороге научимся использовать API самого ютуба для получения мета информации и тамбнейлов.

Создание проекта

PHPixie можно установить либо используя Composer, либо скачав снапшот готовой системы с сайта. Разницы почти нет, так как снапшот регулярно обновляется и являет собой базовой проект с проинсталлированными тремя библиотеками (core, db и orm). Для простоты будем использовать второй метод, ссылка на снапшот здесь phpixie.com/phpixie.zip. Сервер надо настроить на папку /web/ внутри проекта. Вот и все, теперь можем зайти на наш хост и увидеть маленькое приветствие.

Объект $pixie

Объект $pixie — это имплементация DI Контейнера и Сервис Локатора, нечто похожее на $app в Silex. Он доступен как проперти контроллера и передается практически в каждый конструктор, $pixie также содержит фактори методы для каждого класса фреймворка. Грамотное использование его позволяет полностью избежать связывания классов а следовательно упростить тестирование. В отличии от Silex добавление методов и проперти в $pixie происходит только путем расширения класса. В базовом проекте уже присутстует класс App\Pixie который наследует от PHPixie\Pixie, как раз в него мы можем добавлять свой код чтобы иметь к нему доступ повсюду. Следует обратить внимание на то что это не синглтон и передавать его между классами приходится явно, такой подход был избран для избежания какого-либо глобального состояния в коде, аналогично фреймворк никогда не использует статические методы. Каждый модуль, например db или orm поставляет свой класс с фактори методами, эти классы прописываются в нашем App\Pixie в $modules. Потом мы можем запрашивать их как проперти, например используя $pixie->db->query() и $pixie->orm->get(), что вносит дополнительную структурированность и позволяет избежать супа из методов. В нашем случае менять в App\Pixie нам ничего не нужно.

База данных

Мы будем использовать лишь одну простенькую табличку для хранение информации о видео, вот ее структура:

CREATE TABLE `videos` ( 	`id` INT(10) NOT NULL AUTO_INCREMENT, 	`video_id` VARCHAR(20) NOT NULL, 	`title` VARCHAR(255) NOT NULL, 	PRIMARY KEY (`id`) ); 

Теперь прописываем настройки соединения к базе в /assets/config/db.php, например:

return array( 	'default' => array( 		'user'=>'root', 		'password' => '', 		'driver' => 'PDO', 		'connection'=>'mysql:host=localhost;dbname=videos' 	) ); 

тут, думаю все достаточно тривиально.

Модель

Любая MVC структура начинается с модели, в нашем случае она только одна, Video. Кто знаком с Kohana сразу почувствует себя дома, для создания модели достаточно просто расширить класс \PHPixie\ORM\Model:

namespace App\Model; class Video extends \PHPixie\ORM\Model{} 

Привязка к таблице по умолчанию происходит следуя из имени класса. В нашем случае так оно и есть и менять ничего не нужно. Доступ к модели можно получить используя $pixie. Самые яркие примеры кода:

//Создание и сохранение $video = $pixie->get('video'); $video->title = 'Test'; $video->save();  //Поиск $video = $pixie->get('video')->where('title','Test')->find();  //Поиск всех $videos = $pixie->get('video')->find_all(); 

Базовая разметка

В базовом проекте который ми скачали есть в наличии подвид контролера, класс App\Pixie. Его работа сводится к тому чтоб рендерить шаблон main.php доступный как проперти $view. Наши контроллеры просто передают разные данные в этот шаблон, включая $subview — имя подшаблона который надо вставить. Мне как раз очень понравилось то, что логика того как работают мастер-страницы и подшаблоны не прописана в самом фреймворке а выносится в сам проект, что позволяет переделать ее по своему усмотрению. Наш main.php будет выглядеть примерно так:

<!DOCTYPE html> <html> 	<head> 		<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/css/bootstrap-combined.min.css" rel="stylesheet"/> 	</head> 	<body> 		<div class="container"> 			<div class="row"> 				<div class="offset3 span6"> 					<h2><a href="/">PHPixie Vids</a></h2>  					<!-- Форма добавления видео --> 					<form class="form-inline" method="post" action="/videos/add"> 						<input type="text" placeholder="Paste Link…" name="url"> 						<button type="submit" class="btn btn-primary">Add new</button> 					</form> 				</div> 			</div> 			<div class="row">  				<!-- Подключаем подшаблон --> 				<?php include($subview.'.php'); ?> 			</div> 		</div> 	</body> </html> 

Подшаблонов у нас всего два: list.php (для списка добавленных роликов) и view.php (для просмотра выбранного видео). Вот они:

<!-- /assets/views/list.php --> <div class="offset3 span6"> 	<ul class="thumbnails"> 		<?php foreach($videos as $video):?> 			<li class="span3"> 				<a class="thumbnail" href="/videos/view/<?php echo $video->id; ?>">  					<!-- Вот как легко получить тамбнейл видео по айдишке --> 					<img src="http://img.youtube.com/vi/<?php echo $video->video_id;?>/0.jpg"> 					<div class="caption"> 						<h3><?php echo $video->title;?></h3> 					</div> 				</a> 			</li> 		<?php endforeach;?> 	</ul> </div> 
<div class="offset3 span6">  	<!-- А вот как вставить видео и включить автопроигрывание--> 	<iframe width="420" height="345" src="http://www.youtube.com/embed/<?php echo $video->video_id; ?>?rel=0&autoplay=1"></iframe> </div> 

Роутинг

Я знаю что вы уже заждались самого кода, но перед тем как мы перейдем к контроллеру нам надо прописать его в /assets/config/routes.php. На самом деле в базовом проекте прописан только один роут и он выглядит как /контроллер/метод/id, что в принципе нас устраивает, но было б очень кстати по менять дефолтный контроллер из Hello на наш Videos.

return array( 	'default' => array('(/<controller>(/<action>(/<id>)))', array( 					// Дефолтные значения 					'controller' => 'Videos', 					'action' => 'index' 					) 				), ); 

Контроллер

Поскольку нам нужны 3 страницы в контроллере должно быть 3 метода. Вот с чего мы начнем:

namespace App\Controller;  class Videos extends \App\Page {  	public function action_index(){ 		$this->view->subview = 'list'; 		$this->view->videos  = $this->pixie->orm->get('video')->find_all(); 	} 	 	public function action_add(){ 		$this->redirect('/'); 		//Об этом чуть позже 	} 	 	public function action_view(){ 		$this->view->subview = 'view';  		//Берем id с URL: /video/view/3 		$id = $this->request->param('id'); 		$this->view->video = $this->pixie->orm->get('video') 												->where('id', $id) 												->find(); 	} } 

Задачи выбора всех и одного видео тривиальны.
Рассмотрим теперь добавление нового видео. Идентификатор видео в ссылке ютуба передается параметром ‘v’, например www.youtube.com/watch?v=75nBenOWul0, мы можем достать его множеством способов, но наиболее аккуратным мне показался с использованием parse_url(), вот так:

parse_str(parse_url( $url, PHP_URL_QUERY ), $vars ); $video_id = $vars['v'];  

Получить информацию о ролике, в нашем случае его имя, можно используя API по ссылке youtube.com/get_video_info?video_id=<id видео>. Используя эти знания мы теперь можем дописать недостающий action_add():

	public function action_add(){ 		if($url = $this->request->post('url')){ 			parse_str(parse_url( $url, PHP_URL_QUERY ), $vars ); 			$video_id = $vars['v'];  			$response = file_get_contents("http://youtube.com/get_video_info?video_id=".$video_id); 			parse_str($response, $data); 			$video = $this->pixie->orm->get('video'); 			$video->title = $data['title']; 			$video->video_id = $video_id; 			$video->save(); 		} 		$this->redirect('/'); 	} 

И вуаля! Вот кстати скриншот результата:
image

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

ссылка на оригинал статьи http://habrahabr.ru/post/178899/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *