Структуризація проекту в Wordpress, Laravel Blade і не тільки

Wordpress можна любити, можна не любити, але складно не погодитися з тим, що він вирішує проблеми. Останнім часом розробка під Wordpress пішла далеко від створення примітивних блогів з 4-5 інформаційними сторінками. Все більше і більше компаній використовують Wordpress як інструмент для створення повноцінних систем з великою кількістю внутрішньої логіки. Сумна правда в тому, що він абсолютно не пристосований для цього. Але на жаль, розуміння цього приходить лише з черговим запуском проекту production.

Витрати функціональності призводять до того, що проект стає дуже складно підтримувати. Вся логіка, яка була закладена в проект погано структурована, погано описана, в більшості випадків позбавлена тестів. Якщо проект розробляв один чоловік, то розуміння внутрішньої складової проекту йде разом з цією людиною. І в підсумку компанії дістається черговий legacy code.

Можливо, ситуація, описана мною вам знайома, можливо ні. Після 5 років розробки в екосистемі Wordpress я зрозумів, що потрібно щось змінювати. Потрібно переосмислити структуризацію проекту, ввести правила організації логіки і виведення, вирішити проблему повторюваності коду. Так і народилася ідея написати wordpress theme framework — Classy.

image

Якщо ви розробляли теми під Wordpress, ви знаєте, що кожен view, будь то уявлення того, як буде виглядати відкрита стаття (single-post.php), або сторінка зі списком всіх статей (archive-post.php), вимагає репрезентації в основний директорії теми. Подібне рішення можливо має сенс при нескладному проекті, але як тільки проект обростає логікою — це стає проблемою.

Приклад кількості файлів на середньої складності проекті:├── 404.php
├── README
├── archive-gallery.php
├── archive-inspiration.php
├── archive-rent.php
├── archive-vendor.php
├── attachment.php
├── category.php
├── comments.php
├── footer-rent.php
├── footer-vendor.php
├── footer.php
├── functions.php
├── gulpfile.js
├── header-rent.php
├── header-vendor.php
├── header.php
├── image.php
├── index.php
├── page-diy-ideas.php
├── page-edit-vendor-profile.php
├── page-local-blogs.php
├── page-login.php
├── page-my-favorites.php
├── page-my-listings.php
├── page-my-messages.php
├── page-my-profile.php
├── page-new-listing.php
├── page-password-reset.php
├── page-register.php
├── page-vendor-guide.php
├── page-vendors.php
├── page-wedding-ideas.php
├── page.php
├── screenshot.png
├── search.php
├── searchform.php
├── sidebar-home.php
├── sidebar-rent.php
├── sidebar-vendor.php
├── sidebar-filters.php
├── sidebar-general.php
├── sidebar-user.php
├── single-inspiration.php
├── single-rent.php
├── single-gallery.php
├── single-vendor.php
├── single.php
├── style.css
├── tag.php
├── taxonomy-location.php
├── template-about.php
├── template-activate-account.php
├── template-become-a-member.php
├── template-contact.php
├── template-default.php
├── template-faq.php
├── template-grab-a-badge.php
├── template-map.php
├── template-new-inspiration.php
├── template-new-rent.php
└── template-welcome.php

«Це все і ми знаємо, але що ти пропонуєш?» — запитаєте ви. А я пропоную просту річ, яка з недавнього апдейта Wordpress, а саме з версії 4.4 нарешті стала цілком доступна — винести всі view у відповідну папку, а в корені залишити просто index.php, який буде брати на себе весь render:

Classy::render();

і те, що раніше виглядало як:

├── archive-rent.php
├── single-rent.php
├── header-rent.php
├── footer-rent.php
└── sidebar-rent.php

тепер виглядає як:

├── views
│ ├── rent
│ │ ├──archive.blade.php
│ │ ├──single.blade.php
│ │ ├──layout.blade.php

Організованіше? Думаю, так.

Як це працює?
Якщо ви знайомі з ієрархією Wordpress, то знаєте, що при обробці запиту, він намагається знайти саме специфічне подання цього запиту і спускається вниз поки не дійде до index.php власне, того файлу, на який ми і поставили основною Classy::render().

image

В даному випадку Classy::render виконує дві функції, одну для пошуку view (ClassyTemplate::get_template()) і іншу для пошуку scope (ClassyScope::get_scope()). Ці 2 функції, повторюють алгоритм пошуку view який використовують wordpress, але роблять вони це окремо, двічі. Це дозволяє нам мати незалежну архітектуру представлення даних.

Навіщо, запитаєте ви? Дуже часто виникають ситуації при розробці, коли одні і ті ж дані необхідно відобразити по-різному. Приміром, у нас є безліч templates, які є не більше, ніж різновидом для дизайну page.php. Так чому ж не прописати один раз дані scope/page.php і просто розробити окремі view для templates: view/page/dark.php, view/page/light.php і т. д. Внаслідок цього, ми зменшуємо кількість повторюваного коду, так як scope у нас готується один раз.

Так що там з Wordpress 4.4?
Ах так, зовсім забув розповісти про це. В Wordpress 4.4 нарешті з'явилася можливість модифікувати список шаблонів, які відображаються користувачу в адміністративній панелі. Тепер, завдяки хуку "theme_page_templates", ми можемо цей список переписувати і додавати в нього наші зареєстровані за новим способом шаблони.

А реєструються вони дуже просто. Наприклад, ми хочемо створити шаблон about. Для цього ми створюємо уявлення view/page/about.blade.php і вгорі файлу вказуємо Template Name: About. Тобто, в кінцевому рахунку, наш view буде виглядати так:

{{-- Template Name: About --}}

@extends('base.default')

@section('content')
@if ($post)
<article class=“about">
<h1>{{ $post- > title() }}</h1>

<section class="body">
{{ $post->content() }}
</section>
</article>
@endif
@stop


Концепція моделей
На жаль, в Wordpress не використовуються за замовчуванням шари абстракції даних, але це необхідно.

Замість того, щоб писати чергову prefix_vendor_get_posts, чому б не використовувати клас Vendor як модель, а get_posts як звичайний її метод. Цей, здавалося б, простий спосіб заощадить вам купу сил під час підтримки проекту, а, головне, дозволить писати функціонал з меншою кількістю помилок.

У нашому випадку є модель — ClassyPost, яку може розширити будь-яка інша модель custom post type.

Laravel Blade
Використання template engine в розробці Wordpress — справа кожного, але досвід показав, що він допомагає зменшити час розробки проекту, роблячи його більш структурованим, а код приємним і легким для читання. До недавніх пір я використовував Timber, який є імплементацією template engine — Twig, але в ньому є ряд мінусів:

1) Виконання php функцій. Думаю тут можна обійтися без коментарів, тому що воно виглядає ось так:

{{function('edit_post_link', 'Edit', '<span class="edit-link">', '</span>')}}

В той час, як Laravel Blade дозволяє виконувати php код і та ж сама функція буде виглядати так:

{{ edit_post_link('Edit', '<span class="edit-link">', '</span>') }}

2) Швидкість. Timber не найшвидший фреймворк і його основною проблемою є перевантаженість функціоналом. На маленьких проектах це непомітно, але коли ви маєте справу з проектами з великою відвідуваністю — це стає больовою точкою. Моєї ж ідеєю було зберегти мінімалістичність фреймворку, щоб там було тільки те, що дійсно використовується в проекті.

Висновок
Проект Classy є повністю Open-Source. Моєю початковою ідеєю було допомогти вирішити проблему з організацією проекту в Wordpress, з якою я стикаюся і мої колеги і, сподіваюся, ця реалізація допоможе й іншим. У поточній реалізації можливі баги, але я буду активно працювати над їх усуненням. З нетерпінням чекаю ваших відгуків про виконану роботу.

Репозиторій GitHub.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.