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

В этой статье мы расскажем, как строим архитектуру наших приложений на WordPress

Любая CMS дает нам админку и ядро, а из ядра выделяется набор функций, которые мы можем использовать для разработки приложений. WordPress дает нам отличный движок на PHP (новые версии постоянно поддерживаются) с хорошей популярной админкой и неограниченным количеством расширений, а всю клиентскую часть мы пишем самостоятельно.

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

  • Первое — мы используем систему готовых блоков и компонентов. У WordPress есть редактор Gutenberg (рассказывали об этом в одной из статей), и практически все страницы формируются из блоков, как в Tilda. Этот же принцип переносим и в построение архитектуры: формируем готовые блоки, shared-компоненты, глобальные пейдж-темплейты, отдельно бизнес-фичи и т д.

  • Второе — мы не используем JQL, пишем все на чистом JS с использованием объектно-ориентированного подхода к построению логики. Для создания сложных интерфейсов можем на отдельных страницах прикрутить Vue или React (который на WP доступен из коробки). К тому же в WP доступен REST API, и если у нас нет каких-то методов или эндпоинтов, мы можем легко их добавить.

Структура папок и файлов внутри темы WordPress

Файлы в корне темы:

  • style.css - Обязательный файл, содержит информацию о теме

    В этом файле указываются такие данные, как:

    • название темы

    • версия темы

    • минимальная версия WordPress

    • версия PHP

    Подробнее тут

  • theme.json - Настройки темы (настройки типографики, цветовая палитра)

    Видео с демонстрацией настроек

    https://www.loom.com/share/9fc072486f7e4f4ca883e76a3ae0be6e

    Пример файла настроек theme.json

    {
        "version": 1,
        "settings": {
            "typography": {
                "customFontSize": false,
                "lineHeight": true,
                "fontSizes": [
                    {
                        "slug": "h1",
                        "size": "6rem",
                        "name": "H1"
                    },
                    {
                        "slug": "h2",
                        "size": "2.88rem",
                        "name": "H2"
                    },
                    {
                        "slug": "h3",
                        "size": "1.5rem",
                        "name": "H3"
                    },
                    {
                        "slug": "text_46",
                        "size": "2.88rem",
                        "name": "Text 46"
                    },
                    {
                        "slug": "text_24",
                        "size": "1.5rem",
                        "name": "Text 24"
                    },
                    {
                        "slug": "text_16",
                        "size": "1rem",
                        "name": "Text 16"
                    }
                ]
            },
            "spacing": {
                "spacingSizes": [
                    {
                        "size": "clamp(1.5rem, 5vw, 2rem)",
                        "slug": "30",
                        "name": "1"
                    },
                    {
                        "size": "clamp(1.8rem, 1.8rem + ((1vw - 0.48rem) * 2.885), 3rem)",
                        "slug": "40",
                        "name": "2"
                    },
                    {
                        "size": "clamp(2.5rem, 8vw, 6.5rem)",
                        "slug": "50",
                        "name": "3"
                    }
                ],
                "blockGap": true,
                "customPadding": true,
                "customMargin": true,
                "units": [
                    "px",
                    "rem",
                    "%"
                ]
            },
            "color": {
                "palette": [
                    {
                        "slug": "black",
                        "color": "#000000",
                        "name": "Black"
                    },
                    {
                        "slug": "pink",
                        "color": "#F2CFCE",
                        "name": "Pink"
                    },
                    {
                        "slug": "white",
                        "color": "#ffffff",
                        "name": "White"
                    },
                    {
                        "slug": "grey",
                        "color": "#A5A5A5",
                        "name": "Grey"
                    }
                ]
            }
        }
    }
    
  • functions.php - Входной файл для всех скриптов php

    Тут выполняем объявления глобальных констант, подключение load файла из папки includes (где лежат все основные php скрипты), подключения load файла из папки blocks и components

  • header.php - Шаблон шапки сайта

    Тут выполняется функция wp_head(), которая подключает ресурсы и выводит мета-теги

  • footer.php - Шаблон подвала сайта

    Тут выполняется функция wp_footer(), которая подключает js-скрипты темы и плагинов

  • page.php - Дефолтный шаблон страницы

    Как правило, тут выполняется подключение header.php и footer.php c помощью функций get_header() и get_footer() соответственно.

    get_header();
    
    if ( have_posts() ) {
        while ( have_posts() ) {
            the_post();
            the_content();
        }
    }
    
    get_footer();
  • package.json - Зависимости приложения

  • index.php - Пустой индексный файл

Папки:

  • acf-json - Папка для автосохранения конфигов полей и страниц с опциями, созданных плагином Advanced Custom Fields. Это необходимо если разработка ведется в команде, все изменения полей будут отслеживаться в гите

  • assets - Тут лежат все стили, скрипты, шрифты и прочие файлы, отвечающие за фронтенд

  • blocks - Кастомные gutenberg блоки

  • components - Переиспользуемые компоненты

  • includes - Папка со всеми скриптами php

  • page-templates - Шаблоны страниц

Theme_folder
├── acf-json
│   ├── group_64c25ae72741a.json
│   └── ...
├── assets
│   ├── css
│   ├── js
│   │   ├── config
│   │   ├── admin.js
│   │   ├── editor.js
│   │   └── index.js
│   └── resource
├── blocks
│   ├── block1
│   │   ├── block.json
│   │   ├── functions.php
│   │   ├── template.php
│   │   ├── _index.scss
│   │   └── _index.js
│   └── load.php
├── components
│   ├── component1
│   │   ├── [component-name].php
│   │   ├── functions.php
│   │   ├── _index.scss
│   │   └── _index.js
│   └── load.php
├── includes
│   ├── [module-name].php
│   └── load.php
├── page-templates
├── footer.php
├── functions.php
├── header.php
├── index.php
├── package.json
├── page.php
├── style.css
└── theme.json

Gutenberg blocks

Видео с демо

https://www.loom.com/share/2c19f771a64f4c69b10484972d5163b5

В этой папке хранятся сами блоки в подпапках и файл load.php, в котором находится функция регистрации всех блоков.

Блок представлен в виде папки со следующими файлами:

  • block.json - Данные для блока, такие как name, title, и тд

  • template.php - Файл с разметкой блока

  • functions.php - PHP функции используемые только в рамках этого блока

  • _index.scss - Стили для блока

  • _index.js - Скрипты для блока

{
  "name" : "mytheme/custom-block",
  "title" : "Custom Block",
  "icon": "admin-site",
  "description": "My awesome custom block.",
  "apiVersion": 3,
  "textdomain": "mytheme",
  "supports": {
    "align" : false,
    "mode"  : false,
    "jsx"   : true,
    "anchor": true
  },
  "acf": {
    "mode": "preview",
    "renderTemplate": "./template.php"
  }
}
add_action( 'init', 'mytheme_block_registration' );

function mytheme_block_registration() {
    foreach(glob(THEME_DIR . '/blocks/*', GLOB_ONLYDIR) as $dir){
        register_block_type( $dir );
        $dir_exploded = explode( '/', $dir );
	     $block = $dir_exploded[ count( $dir_exploded ) - 1 ];
        //Подключение файла functions.php для каждого блока
		if ( file_exists( get_template_directory() . '/blocks/' . $block . '/functions.php' ) ) {
            include_once get_template_directory() . '/blocks/' . $block . '/functions.php';
        }
    }
}

Components

Примерно такая же концепция, как с gutenberg-блоками, набор компонентов представлен в виде папок со следующими файлами:

  • [component-name].php

  • functions.php

  • _index.scss

  • _index.js

И файл load.php, который подключает все php скрипты всех компонентов:

foreach(glob(THEME_DIR . '/components/*/functions.php') as $file){
	require_once $file;
}

Используем компоненты с помощью встроенной функции get_template_part() , куда передаем параметром args входные данные:

get_template_part( 'components/checkbox/checkbox', args: [
	'label' => 'Сheckbox label',
	'name'  => 'checkbox-name',
] );

Внутри файла компонента мы обозначаем параметры по умолчанию, затем объединяем их с входными параметрами и распаковываем в переменные, на основе которых и строим разметку:

// Fix PhpStorm inspection on undefined variable.
if ( empty( $args ) ) {
	$args = [];
}

$defaults = [
	'label'         => '',
	'checked'       => false,
	'disabled'      => false,
	'custom_class'  => '',
    'id'            => '',
    'name'          => '',
    'value'         => '',
];

// Fill args with defaults to avoid errors.
$args = mytheme_parse_args( $args, $defaults );

// Unpack arguments to variables for better readability.
// Should be in the same order as the keys in `$defaults` array.
[
	'label'         => $label,
	'checked'       => $checked,
	'disabled'      => $disabled,
	'custom_class'  => $custom_class,
	'id'            => $id,
	'name'          => $name,
	'value'         => $value,
] = $args;

Assets

Все фронтенд-файлы, которые не попали ни в components ни в blocks.

  • css - Папка с общими стилями, глобальными лэйаутами, переменными и миксинами

  • js - Папка с утилитарными js функциями и настройками webpack

  • resource - Папка с прочими файлами, такими как картинки, шрифты, видео и тд

В js/config лежат настройки webpack, они могут отличаться от проекта к проекту, но основной принцип такой, что у нас есть 3 точки входа:

  • index.js - Основная точка входа, используемая во фронт-енд части приложения

  • admin.js - Специфические стили и скрипты для admin-части приложения

  • editor.js - Специфические стили и скрипты для области редактирования

После компиляции создается по 3 css и js файла, которые мы подключаем в соответсвующих хуках WordPress.

  • wp_enqueue_scripts - Стили и скрипты для фронтенда

  • enqueue_block_editor_assets - Стили и скрипты для редактора

  • admin_enqueue_scripts - Стили и скрипты для админ части сайта

В index.js нужно подключить все файлы блоков и компонентов, выглядит это примерно так:

import '../css/style.scss';

function importAll(r) {
  r.keys().forEach(r);
}

importAll(require.context('./../../assets/resource/fonts/', true, /\.(woff|woff2|eot|ttf|otf)$/));

// Импортируем все файлы js и scss из каждой подпапки 'components'
importAll(require.context('./../../components', true, /\.js$/));
importAll(require.context('./../../components', true, /\.scss$/));

// Импортируем все файлы js и scss из каждой подпапки 'blocks'
importAll(require.context('./../../blocks', true, /\.js$/));
importAll(require.context('./../../blocks', true, /\.scss$/));

Такой базовый сетап уже позволяет закрывать 90% задач в рамках разработки кастомной темы для WordPress.

Использование REST API
Для асинхронных запросов чаще всего мы используем WP REST API. Это не единственный способ создать кастомный эндпоинт, но, как показывает практика, самый удобный. Все что нам нужно сделать - это воспользоваться функцией register_rest_route в хуке rest_api_init и написать функцию-колбэк, которая будет обрабатывать этот маршрут

Пример создания эндпоинта для блока со списком новостей и фильтрацией по таксономиям, создание которого мы рассматривали в предыдущей статье:

add_action( 'rest_api_init', 'wwzrds_news_list_route' );

function wwzrds_news_list_route() {
    register_rest_route( 'wwzrds/v1', '/news-list', [
        'methods'             => 'GET',
        'callback'            => 'wwzrds_news_list_route_callback',
        'permission_callback' => '__return_true',
    ] );
}

function wwzrds_news_list_route_callback( WP_REST_Request $request ) {
	$json_params = ! empty( $request['json'] ) ? $request['json'] : null;

	if ( ! $json_params ) {
		return new WP_REST_Response( [
			'error' => 'Params are empty',
		], 400 );
	}

	$query_args = json_decode( $json_params, true );

	if ( ! $query_args ) {
		return new WP_REST_Response( [
			'error' => 'Params are empty',
		], 400 );
	}

	$term = ! empty( $request['term'] ) ? $request['term'] : null;
	$page = ! empty( $request['page'] ) ? $request['page'] : null;
	$tax  = ! empty( $request['taxonomy'] ) ? $request['taxonomy'] : 'technology';

	$query_args['tax_query'] = [
		'relation' => 'AND',
	];

	if ( $term && $term !== 'all' ) {
		$query_args['tax_query']['term'] = [
			'taxonomy' => $tax,
			'terms'    => [ $term ],
			'field'    => 'slug',
		];
	}

	if ( $page ) {
		$query_args['paged'] = $page;
	}

	if ( $query_args['post_type'] !== 'post' || $query_args['post_status'] !== 'publish' ) {
		return new WP_REST_Response( [
			'error' => 'Invalid data',
		], 400 );
	}

	$query     = new WP_Query( $query_args );
	$max_pages = $query->max_num_pages;
	$news      = $query->posts;
	wp_reset_query();
	
	$response = [];

if ( ! empty( $news ) ) {
		$response['posts'] = [];
		foreach ( $news as $new ) {
			$response['posts'][] = wwzrds_get_template_string( 'template-parts/components/post-item', [
				'post_id'      => $new->ID,
				'attrs'        => [
    				'style'      => 'opacity:1; transform: translateY(0)',
				],
				'taxonomy'     => $tax,
                'custom_class' => 'news-list__post',
			] );
		}
		$response['pagination'] = wwzrds_generate_pagination( $page, $max_pages, false );
	} else {
		$response['empty'] = wwzrds_get_template_string( 'template-parts/blocks/block-news-list/empty-results' );
	}
	
	return new WP_REST_Response( $response, 200 );
}

wwzrds_generate_pagination - Функция, которая формирует разметку пагинации на основе входных данных.

wwzrds_get_template_string - Функция-хелпер, которая возвращает шаблон как строку.

add_action( 'rest_api_init', 'db_user_bank_endpoints' );

/**
 * Get user's bank
 *
 * @param  WP_REST_Request $request Full details about the request.
 * @return array $args.
 **/
function db_user_bank_endpoints( $request ) {
	register_rest_route('wp/v2', 'users/bank', array(
		'methods'             => 'GET',
		'callback'            => 'db_rest_user_bank_handler',
		'permission_callback' => function() {
          return is_user_logged_in();
    },
	));
}

function db_rest_user_bank_handler( $request = null ) {
	$user     = wp_get_current_user();
	$error    = new WP_Error();

	if ( empty( $user ) ) {
		$error->add( 400, __( 'Invalid user.', 'wp-rest-run' ), ['status' => 400] );
		return $error;
	}

	return new WP_REST_Response( db_calculate_user_store( $user->ID ), 123 );
}

Пример интеграции React-приложения

Демо-видео: https://www.loom.com/share/a25318215847465c94a8af212f870ec6

Сначала в папке темы создаем отдельную папку для файлов виджета, и внутри этой папки инициализируем package.json командой:

npm init

После этого устанавливаем WP Scripts командой:

npm install @wordpress/scripts --save-dev

Открываем package.json и добавляем следующую секцию:

"scripts": {
	"test": "echo \\"Error: no test specified\\" && exit 1",
	"build": "wp-scripts build",
	"check-engines": "wp-scripts check-engines",
	"check-licenses": "wp-scripts check-licenses",
	"format": "wp-scripts format",
	"lint:css": "wp-scripts lint-style",
	"lint:js": "wp-scripts lint-js",
	"lint:md:docs": "wp-scripts lint-md-docs",
	"lint:md:js": "wp-scripts lint-md-js",
	"lint:pkg-json": "wp-scripts lint-pkg-json",
	"packages-update": "wp-scripts packages-update",
	"plugin-zip": "wp-scripts plugin-zip",
	"start": "wp-scripts start",
	"test:e2e": "wp-scripts test-e2e",
	"test:unit": "wp-scripts test-unit-js"
},

В той же папке добавляем webpack.config.js:

const defaults = require('@wordpress/scripts/config/webpack.config');

module.exports = {
	...defaults,
	externals: {
		react: 'React',
		'react-dom': 'ReactDOM',
	},
};

В index.js будем использовать метод render не из ReactDom, а из wp.element, в остальном это будет обычное react приложение:

const { render } = wp.element; // we are using wp.element here!
import App from './calculator/components/App';

// check if element exists before rendering
const appElement = document.getElementById('calculator-app');
if (appElement) { 
	render(<App />, appElement);
}

В App.js поместим основное react приложение. Если нам необходимо импортировать что-то из React или ReactDOM то импортируем это из wp.element, например:

const {useState, useEffect} = wp.element;

При подключении react приложения в WordPress указываем зависимость от 'wp-element':

add_action('wp_enqueue_scripts', 'calc_react_app');
function calc_react_app()
{
	$calc_script_url = THEME_URL . '/calculator/build/index.js';
	$calc_script_path = THEME_DIR . '/calculator/build/index.js';
	wp_enqueue_script(
		'my_react_app',
		$calc_script_url, // This refer to the built React app
		['wp-element'], //This dependency indicates that you need React at Frontend
		filemtime($calc_script_path) // This could be changed to the theme version for production
	);
}

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

Конечно, многие скажут, что надо писать фронт на Vue или React целиком, получать данные по REST API и т. д. — и мы частично согласны, но каждая задача требует индивидуального подхода, в том числе и в выборе наиболее подходящего инструмента для ее реализации. Подписывайтесь на соцсети We Wizards и читайте о том, как мы делаем Headless WordPress + Vue/React в следующих статьях.

Комментарии (46)


  1. opposit
    22.12.2023 11:10

    В css-файле информация о теме, в json-файле цвета, шрифты и прочее. Л - логика!


    1. pantsarny
      22.12.2023 11:10

      Информация о теме в style.css - старое наследие WordPress, этот файл является обязательным, из него берется информация о теме. Механизм не меняется годами для обратной совместимости, не вызывает трудностей. А вот json файл - это фича автора, которая никак не конфликтует с требованиями wp


      1. wwzrds Автор
        22.12.2023 11:10

        Да, всё верно, style.css это обязательное легаси, которое носит сугубо технический характер, а theme.json файл - это специальный инструмент для работы с внутренним редактором Gutenberg, который позволяет делает предустановки для базовых стилей: цвета, шрифты, отступы - это позволяет ограничить возможности контент-редактора к произвольному изменению дизайна, мы туда прописываем правила из UI kit


  1. pantsarny
    22.12.2023 11:10

    Почему acf храните в json а не php? Ведь так удобнее работать с данными, завезти константы, обернуть функциями и бизнес логикой.


    1. KonstantinAgafonov
      22.12.2023 11:10

      json для быстрой синхронизации созданных в админке в интерфейсе acf полей


  1. sergeytolkachyov
    22.12.2023 11:10

    Попробуйте Joomla, будет интересно)


    1. pantsarny
      22.12.2023 11:10

      WordPress далеко впереди Joomla


      1. b2z
        22.12.2023 11:10

        В чём?


        1. pantsarny
          22.12.2023 11:10

          Во всем


          1. b2z
            22.12.2023 11:10

            Чувствуется ответ профессионала :)


            1. pantsarny
              22.12.2023 11:10

              Репозиторий плагинов, тем, комьюнити , поддержка


              1. b2z
                22.12.2023 11:10

                У Joomla это тоже есть.. Но это точно нельзя отнести к "во всём".


                1. pantsarny
                  22.12.2023 11:10

                  Понятно что есть, но сравните обьемы


      1. siroccolis
        22.12.2023 11:10

        И чем же он дальше?


        1. init0
          22.12.2023 11:10

          Ну например по популярности в 25 с лишним раз


          1. siroccolis
            22.12.2023 11:10

            При чем тут популярность, когда речь идёт о разработке. Пыха она и в Африке пыха. J4 и j5 это чистый код, охрененное ядро, все современные подходы к разработке. Я вообще использую symfony, но joomla шикарна, у меня на ней очень много проектов. Ну а WordPress дыра сплошная если прям из коробки и только допиливать, да и код сплошные костыли. Хотя тот же битрикс взять если, то там вообще сплошное дно, но бизнес требует


            1. init0
              22.12.2023 11:10

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


      1. lipatovroman
        22.12.2023 11:10

        В чем именно? Вы вообще joomla 5 щупали?


      1. ha1duk
        22.12.2023 11:10

        Это был явно сарказм)


    1. mihdan
      22.12.2023 11:10

      Я попробовал в этому году - понравилось. Теперь часть проектов на Joomla, часть на WordPress. Joomla по части написания кода прям радует, но и WordPress знатно подтянулся!!!


  1. vickivanov
    22.12.2023 11:10

    для крупных клиентов

    А как Вордпресс будет скалироваться в условном кубе для сотен тысяч rps и далее?


    1. funny_falcon
      22.12.2023 11:10

      PHP сам по себе скалируется бесконечно.

      Вопрос, как организованы походы в базу? Когда база перестанет справляться?


      1. wwzrds Автор
        22.12.2023 11:10

        Вопрос правильный, именно база часто ахиллесова пята) Нам пока что удавалось справиться с любыми нагрузками, это делается довольно стандартным набором методов: правильное кеширование, правильное распределенное хранение (для некоторых сущностей мы создаем новые таблицы), оптимизированные запросы к базе (именно в них часто кроется проблема).


      1. init0
        22.12.2023 11:10

        Тот же самый принцип, например у нас в проекте используем Galera


      1. mihdan
        22.12.2023 11:10

        Есть решения для шардинга БД в WordPress, которые используются на самом wp.com


    1. Roger99887795
      22.12.2023 11:10

      Вертикально, а что?


  1. kostin
    22.12.2023 11:10

    Расскажите, ACF используете в большинстве проектов и в версии PRO? Для проектов приходится докупать лицензию?


    1. wwzrds Автор
      22.12.2023 11:10

      Добрый день! Да, мы покупаем ACF Pro для наших клиентов и используем именно PRO версию, включаем стоимость лицензии в стоимость сайта


    1. mihdan
      22.12.2023 11:10

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


  1. Nelman86
    22.12.2023 11:10

    Большие проекты на wordpress, поддерживать очень сложно. На каком то этапе решение задачи начинается с того, чтобы "выключить" доступный из коробки функционал wp, т.к. он начинает мешать. Работал со всяким на wp, даже с маркетплейсом, то еще извращение))


    1. wwzrds Автор
      22.12.2023 11:10

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

      Так же хочу обратить внимание, мы упомянули в статье, что к каждой задаче свой инструмент и использовать Wordpress в таких сервисах как "маркетплейс" уже нецелесообразно, ну просто потому что объем разработки будет на WP будет равен объему разработки на Laravel, а второй объективно поддерживать легче


  1. bjl
    22.12.2023 11:10

    Как с индексацией и ранжированием фронт-реактивного сайта на WordPress?


    1. wwzrds Автор
      22.12.2023 11:10

      Мы напишем об этом отдельную статью, но при использовании Vue или React мы, конечно, рассматриваем SSR решения для индексных страниц, но бывают и хитрости, у нас был опыт написания SPA на интерактивных страницах и рендер статики для индексных. Вы можете посмотреть пример на одном из наших проектов https://parking-strogino.ru/, статичные страницы получают контент из Gutenberg и хранятся в статике, а страница "объекты" работает в режиме SPA


  1. Andrei-Krautsou
    22.12.2023 11:10

    Почему ACF, а не carbon fields?


    1. wwzrds Автор
      22.12.2023 11:10

      Мы изначально использовали ACF, нам нравится как движется его развитие: регулярные обновления, новые фичи, совместимость с gutenberg и многое другое


    1. mihdan
      22.12.2023 11:10

      ACF - для пользователей, Carbon Fields - для девелоперов.


  1. IvanShishkin
    22.12.2023 11:10

    Пожалуй, худшее что случалось с PHP


    1. SeemsLegit
      22.12.2023 11:10

      Я согласен. Так сложилось, что после долгой работы с yii/laravel пришлось включиться в проект с вордпрессом. Это буквально руководство о том, как не надо писать код. Не удивительно, что PHP приобрел такую репутацию: огромное количество разработчиков на нем учились писать код начиная с вордпресса, впитывая дурные привычки.


      1. init0
        22.12.2023 11:10

        А аргументы у вас есть, с примерами?


        1. SeemsLegit
          22.12.2023 11:10

          Да конечно. Возьмем хотя бы их "wordpress coding standards" из Кодекса. То есть официальных рекомендаций, как писать код на php в вордпрессе.
          https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/

          Начнем с того, что рекомендации вордпресса идут вразрез с PSR. Можно сказать, что это вкусовщина, однако стандарты берутся и развиваются не просто так. Многие подходы к форматированию кода устарели и от них отказались, однако в вордпрессе они продолжают существовать. Например, выравнивание пробелами по оператору присваивания.
          $integer = 123;
          $str = 'aaa';


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


          Если идти глубже, то я бы вспомнил обилие глобальных переменных, хуков и процедурного кода. Это даже не спагетти.

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

          В этом весь вордпресс. Да, в нем легко работать контет-менеджеру. На нем легко сделать что-то простое. Но как начинающему разработчику научиться писать хороший код, если у него пред глазами сборник того, как делать не надо?




          1. init0
            22.12.2023 11:10

            Начнем с того, что рекомендации вордпресса идут вразрез с PSR.

            Начать надо с того, что PSR это не стандарт, а рекомендации и что WPCS обязателен только для ядра, для плагинов и тем это так-же рекомендация. То есть ничто не запрещает вам использование PSR в последних.

            Например, выравнивание пробелами по оператору присваивания.

            Так а что здесь плохого? Я наоборот вижу здесь только благо - это визуально намного проще читать код с таким выравниванием.

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

            Глобальные переменные есть и от них невозможно отказаться разом ввиду обратной совместимости, а во многом благодаря этому WP и стал таким популярным. В хуках не понятно что плохого то? Это еще одна фича WP благодаря которой он относительно прост и удобен для разработки. Что вы понимаете под "процедурным кодом". Функции в глобальном scope? Большее количество функций под капотом используют вызовы методов классов под капотом, что опять-же очень удобно.

            Это даже не спагетти.

            То есть лучше или хуже? Что в вашем понимание "спагетти" и приведите примеры такого в WP.

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

            Ну тут уже понятно, что познания в разработке под WP у вас практически отсутствуют. Для вывода метаполей вообще не стоит использовать какие-либо SQL запросы т.к. тогда не работаю все хуки для них и не работает Object Cache.

            Если суммировать все выше:

            WP как разработчик вы не знаете (ваш пример с "кастомными полями" это прям дичь)
            Я вижу одну валидную претензию - глобальные переменные, но не уверен, что это является критическим фактором
            Все остальные ваши пассажи я проигнорировал т.к. там или ваше оценочное суждение или нет примеров.


            1. SeemsLegit
              22.12.2023 11:10

              Начать надо с того, что PSR это не стандарт, а рекомендации и что WPCS обязателен только для ядра, для плагинов и тем это так-же рекомендация. То есть ничто не запрещает вам использование PSR в последних.

              PSR — php standards recommendations. То есть это да рекомендации, но все-таки буквально по СТАНДАРТАМ. Обязателены ли они к исполнению? Ну конечно нет — мир не рухнет, если каждый будет писать, как попало. Этакий рабочий бардак. Еще могут возникнуть сложности с некоторыми инструментами, например composer autoload, который ожидает соблюдения определенных стандартов в наименовании директорий, файлов, классов и неймпспейсов. Но это мелочи, да.

              Так а что здесь плохого? Я наоборот вижу здесь только благо - это визуально намного проще читать код с таким выравниванием.

              Эта тема давно рассосана и поднималась разными авторами. Навскидку, в книге «Совершенный код» Стива Макконнелла. Избыточные пробелы не несут в себе никакой пользы. Со стороны может казаться, что выравненный таким способом код выглядит аккуратно, но на деле, от того что название переменной отдаляется от ее значения, восприятие только ухудшается.

              Глобальные переменные есть и от них невозможно отказаться разом ввиду обратной совместимости, а во многом благодаря этому WP и стал таким популярным. В хуках не понятно что плохого то? Это еще одна фича WP благодаря которой он относительно прост и удобен для разработки. Что вы понимаете под "процедурным кодом". Функции в глобальном scope? Большее количество функций под капотом используют вызовы методов классов под капотом, что опять-же очень удобно.


              Да, благодаря всем этим "фичам" очень легко кодить по принципу х*як-х*як и в продакшн. Начинающим разработчикам очень легко нагуглить куски кода и впихнуть их себе. И да, это будет работать! В этом несомненный плюс вордпресса: можно быстро и без особых навыков накрутить что-то несложное. Проблемы всплывут позже, при поддержке или при росте проекта.

              Однако я именно про это и говорю: вордпресс буквально учит плохой разработке. С одной стороны может показаться удобным, что можно перехватить хуком какой-нибудь параметр и переписать его. Коварство этого подхода в том, что это может сделать кто угодно, где угодно и сколько угодно раз. И потом попробуй разобраться в результате. Это, кстати, также отвечает на вопрос про "спагетти".

              Для вывода метаполей вообще не стоит использовать какие-либо SQL запросы т.к. тогда не работаю все хуки для них и не работает Object Cache.

              А кто сказал, что кастомные поля - это только простые метаполя? Это раз. Ну а два, перехват и модификация запроса используется и в разных уважаемых плагинах (тот же ACF), и даже в ядре.

              Вот, например, пример из кодекса:

              add_filter( 'posts_where' , 'posts_where' );
              
              function posts_where( $where ) {
              
              if( is_admin() ) {
              global $wpdb;
              
              if ( isset( $_GET['author_restrict_posts'] ) && !empty( $_GET['author_restrict_posts'] ) && intval( $_GET['author_restrict_posts'] ) != 0 ) {
              $author = intval( $_GET['author_restrict_posts'] );
              
              $where .= " AND ID IN (SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id=$author )";
              }
              }
              return $where;
              }


              1. init0
                22.12.2023 11:10

                Эта тема давно рассосана и поднималась разными авторами. Навскидку, в книге «Совершенный код» Стива Макконнелла.

                Отлично, вы только забыли маленькую деталь, цитату/ссылку на это.

                Избыточные пробелы не несут в себе никакой пользы.

                Вред несут?

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

                Опять-же ваше оценочное суждение, я противоположного мнения.

                Да, благодаря всем этим "фичам" очень легко кодить по принципу хяк-хяк и в продакшн.

                А "эти фичи" во множественном числе это вы так увыжительно "на вы" называете глобальные переменные?

                Начинающим разработчикам очень легко нагуглить куски кода и впихнуть их себе.

                Это вообще относится к любому языку программирования, при чем тут WP?

                В этом несомненный плюс вордпресса: можно быстро и без особых навыков накрутить что-то несложное. Проблемы всплывут позже, при поддержке или при росте проекта.

                Именно так, у кого нет познаний, опыта накрутит как придется - как вы, например, предлагали SQL запрос менять для получения метаполей. Я таких поделок под WP за свой опыт работы видал тысячи... и ничего страшного, для более-менее серьезного проекта выбирают имеено опытных разработчиков.

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

                Вы пишете, право, глупости. Это можно сделать в любом другой CMS (да той-же симофони) через рефлексию или даже тупо залезть в код ядра.

                И потом попробуй разобраться в результате.

                Довольно несложное занятие кстати, когда знаешь как и где искать.

                Это, кстати, также отвечает на вопрос про "спагетти".

                Не отвечает, т.к. тот подход, что вы описали выше можно применить где угодно. Я спрашивал где "спагетти" в самом WP.

                А кто сказал, что кастомные поля - это только простые метаполя?

                Потому, что это так и есть. И не бывает "не простых" метаполей.

                Ну а два, перехват и модификация запроса используется и в разных уважаемых плагинах (тот же ACF), и даже в ядре.

                При чем здесь сторонние плагины и WP. Их пишут совершенно разные команды. Про ядро вы выдумываете, в WP объявлены только хуки и само ядро их не использует. Вам дан инструмент, хотите пользуйтесь, хотите - нет.


                1. SeemsLegit
                  22.12.2023 11:10

                  Отлично, вы только забыли маленькую деталь, цитату/ссылку на это.

                  Это платная книга, ее нет в открытом доступе, так что разумеется я не могу быстро указать ссылку на нужную цитату. Однако тема форматирования поднимается во многих подобных книгах. Или вы их не читали?

                  Вред несут?

                  Да. И я об этом написал.

                  Опять-же ваше оценочное суждение, я противоположного мнения.

                  Это не мое оценочное мнение, а один из аргументов, которые я привел из книг.

                  Вы пишете, право, глупости. Это можно сделать в любом другой CMS (да той-же симофони) через рефлексию или даже тупо залезть в код ядра.

                  Ну кто же спорит. Однако где-то для этого надо постараться, а где-то это лежит прямо в документации как вполне себе рекомендованный способ.

                  Потому, что это так и есть. И не бывает "не простых" метаполей.

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

                  При чем здесь сторонние плагины и WP. Их пишут совершенно разные команды. Про ядро вы выдумываете, в WP объявлены только хуки и само ядро их не использует. Вам дан инструмент, хотите пользуйтесь, хотите - нет.

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


                  1. init0
                    22.12.2023 11:10

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

                    То есть у вас нет никаких пруфов относительно выравнивания?

                    Да. И я об этом написал.

                    Я не увидел где вы написали какой вред наносит форматирование (конкретно выравнивание пробелами), укажите?

                    Это не мое оценочное мнение, а один из аргументов, которые я привел из книг.

                    Все еще жду цитаты.

                    Метаполя - это всего лишь таблица в бд.

                    Это не таблица, а сущность WP. Таблица (а точнее таблицы т.к. она не одна) это реализация.

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

                    Ну явно не того уровня, что вы, у меня в проектах получение метаполей SQL запросами не практикуется.

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

                    Это не код ядра, а пример использования хука.


      1. mihdan
        22.12.2023 11:10

        Вся проблема WordPress - в обратной совместимости вплоть до очень старых версий. Но это же являеься его сильной стороной. Ни одна CMS не может себе этого позволить, поэтому количество установок говорит само за себя. А что до стандартов, так WordPress появился задолго до PSR/PHP-FIG. С появлением в проекте Gutenberg WPCS (WordPress for CodeSniffer) стандарты стали обязательны для ядра, а теперь и для разработчиков плагинов. Откровенный говнокод более в репозиторий не попадает. Но это долгий процесс, так как плагинов тысячи и их часто пишут люди, далекие от программирования. У WordPress своя ниша и свой огромный (почти 50% мирового интернета) кусок, с этим приходится считаться и уважать труд разработчиков, кто тянет на себе этот проект многие годы. А стандарты подтянутся, недаром в РНР внесли правки, чтобы оно работало с WordPress более лучше ;-)