Использование register_activation_hook в классах

Я пытаюсь разработать плагин для основных целей SEO, так как многие из моих знакомых не любят использовать Yoast. Я буквально только что запустил плагин и создаю сообщение об активации, отображаемое пользователю, когда он активирует плагин. У меня возникли проблемы с сочетанием ООП и встроенных функций Wordpress, и я не уверен, в чем я ошибаюсь.

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

Я не уверен, что то, что я делаю, это потому, что я не понимаю технику ООП на 100%, или я неправильно использую Wordpress API , Я включил три примера кода в следующем порядке:

  1. Основной файл плагина
  2. Файл класса, отвечающий моим требованиям к активации
  3. На что я действительно надеялся может быть сделано.

seo.php (основной файл плагина)

<?php/*... generic plugin info*/require_once(dirname(__FILE__) . '/admin/class-plugin-activation.php');class SEO {  function __construct() {    $activate = new SEO_Plugin_Activation();    $activate->activatePlugin();  }}new SEO();?>

class-plugin-активации.php

<?phpclass SEO_Plugin_Activation {  function __construct() {    register_activation_hook(__FILE__ . '../seo.php', array($this, 'activatePlugin'));    add_action('admin_notices', array($this, 'showSitemapInfo'));  }  function activatePlugin() {    set_transient('show_sitemap_info', true, 5);  }  function showSitemapInfo() {    if(get_transient('show_sitemap_info')) {      echo '<div class="updated notice is-dismissible">' .              'Your sitemap files can be found at these following links: ' .            '</div>';      delete_transient('show_sitemap_info');    }  }}?>

seo.php (то, на что я надеялся)

<?php/* ... blah blah blah*/require_once(dirname(__FILE__) . '/admin/class-plugin-activation.php');class SEO {  function __construct() {    register_activation_hook(__FILE__, array($this, 'wp_install'));  }  function wp_install() {    $activate = new SEO_Plugin_Activation();    //Execute some method(s) here that would take care     //of all of my plugin activation bootstrapping  }}new SEO();?>

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

Ответы и комментарии:

Вы ищете заверение или правильный способ сделать OO в WordPress? Боюсь, что здесь нет канонического пути, которым я могу поделиться, единственные вещи, которыми я могу поделиться, - это общие ОО вещи. Например. не создавайте SEO_Plugin_Activation внутри вашего класса SEO, используйте внедрение зависимостей и передайте его в качестве аргумента вместо этого, и не определяйте и не используйте класс в том же файле, загрузка файла, описывающего класс, также не должна запускать его, иначе невозможно написать модульные тесты
Создан 10-08-2017 01:12 Tom J Nowell♦

Спасибо за ответ. Я, честно говоря, не слишком беспокоюсь о том, чтобы придерживаться «100% Wordpress Way». Судя по вашему комментарию, похоже, мне явно не хватает понимания принципов ООП. У меня сложилось впечатление, что мне нужно создать новый класс внутри класса для вызова его методов.
Создан 10-08-2017 01:59 Dan Zuzevich

Вы можете сделать это, но это не так гибко, например, Если вы хотите протестировать класс SEO, как бы вы заменили класс SEO_Plugin_Activation на фиктивный объект, не изменяя его? В любом случае кажется, что этот вопрос о недопонимании того, как работает register_activation_hook
Создан 10-08-2017 02:04 Tom J Nowell♦

Понятно, спасибо большое. Я, честно говоря, не думаю, что буду проводить тесты на чем-либо, так как это немного над моей головой в данный момент.
Создан 10-08-2017 02:13 Dan Zuzevich

Спасибо за подробный ответ. Из вашего объяснения, по крайней мере, что я получаю от этого, это то, что мне нужно найти способ, чтобы мой основной плагин знал обо всех классах, которые я написал? Например, я, вероятно, буду иметь файлы классов в папке «inc», а другие файлы классов - в папке «admin». У меня сложилось впечатление, что всякий раз, когда я хотел где-нибудь использовать класс, мне нужно было выполнить «$ var = new ClassName ();» чтобы иметь доступ к этим методам. Вот почему вы видите, как я создаю класс внутри основного класса.
Создан 10-08-2017 02:21 Dan Zuzevich

вам не нужно создавать объект внутри класса, просто передайте ему переменную $ var, конструкторы также могут принимать параметры, а объекты можно передавать, как и любую другую переменную. Вы можете сделать это так, как вы это сделали, но есть и недостатки. Проблема с доступом к __FILE__ является одной из них, это значение должно исходить из основного файла плагина, или оно не будет правильным, поэтому его нужно передать другим частям плагина
Создан 10-08-2017 02:59 Tom J Nowell♦

Alrighty. Благодарю. Этого ответа точно хватит. Я знаю, что мне нужно освежить.
Создан 10-08-2017 02:15 Dan Zuzevich

ОО сторона этого вопроса несколько оффтопична для этого сайта, я оставил вопрос открытым под предлогом правильного использования register_activation_hook. С другой стороны, посмотрите на tomjn.com/2015/06/24/root-composition-in-wordpress-plugins, но есть и другие способы сделать это. Нет правильного способа сделать это, все они имеют свои преимущества и недостатки, вы можете написать свой плагин, используя чисто функциональные программные конструкции в стиле haskell
Создан 10-08-2017 02:41 Tom J Nowell♦

Стоит ли переформулировать вопрос каким-либо образом, или это нормально?
Создан 10-08-2017 02:19 Dan Zuzevich

Это было полезно, и я ценю ответ.
Создан 10-08-2017 02:23 Dan Zuzevich

Я проголосовал за ответ как за определенный полезный ресурс.
Создан 11-08-2017 01:44 Dan Zuzevich

Это очень хорошая идея. Я полностью забыл про шаблонный плагин. Я проверил это некоторое время назад, и был сбит с толку тем, что это довольно запутанно. Но я определенно собираюсь скачать его снова и использовать в качестве справочного материала. Большое спасибо за предложение.
Создан 11-08-2017 01:47 Dan Zuzevich

Перечитав ваш вопрос, я думаю, что вижу проблему, и это связано с неправильным пониманием того, как работает register_activation_hook, в сочетании с некоторой путаницей по поводу того, как вы загружаете свой код и что это значит для начальной загрузки
Часть 1: register_activation_hook
Эта функция принимает 2 параметра:

register_activation_hook (строка $ file, вызываемая функция $)

Первый параметр, $ file, является основным файлом плагина, а не файлом, содержащим то, что вы хотите запустить. Он используется так же, как и plugins_url, поэтому вам нужно значение __FILE__, в частности его значение в корневом файле плагина с заголовком вашего плагина.
Второй параметр является вызываемым и работает как вы ожидаете, но на самом деле он просто использует add_action для внутреннего использования.

Когда плагин активирован, вызывается действие «activ_PLUGINNAME». В имени этого хука PLUGINNAME заменяется именем плагина, включая необязательный подкаталог. Например, когда плагин находится в wp-content / plugins / sampleplugin / sample.php, тогда имя этого хука станет «activ_sampleplugin / sample.php».

Часть 2. Начальная загрузка и __FILE__
Основная проблема здесь заключается в том, что __FILE__ будет иметь разные значения в разных местах, и вам нужно конкретное значение.
У вас также есть проблема, что при начальной загрузке должен собираться граф объектов, но вы этого не делаете. Все ваши объекты создаются сразу же после их определения или внутри друг друга, что затрудняет или делает невозможным передачу им значений.
Как пример, я мог бы написать плагин как это:
plugin.php:
<? PHP
/ **
 * Имя плагина: Мой плагин
 * Версия: 0.1
 * /

// шаг загрузки
require_once ('php / app.php');

// шаг начальной загрузки
$ app = новое приложение (__FILE__);

// шаг выполнения
$ App-> Run ();

Я определил все мои классы в подпапке php и загрузил их в одном месте. Теперь PHP знает, что такое мои классы, их имена и т. Д., Но пока ничего не произошло.
Затем я создаю все свои объекты, передавая им то, что им нужно, в этом случае приложению требуется значение __FILE__, поэтому я передаю его. Обратите внимание, что это создает объекты в памяти, но не выполняет никакой работы. Приложение плагинов готово к работе, чтобы начать работу, но оно находится на стадии подготовки.
Следующим шагом может быть передача этих объектов в набор юнит-тестов, но сейчас я собираюсь их запустить. Я завершил процесс начальной загрузки, и приложение готово к запуску, поэтому я запускаю метод run. Мне не нужно ничего передавать для запуска, так как все необходимое было передано конструкторам. Во время выполнения метода я добавляю все свои фильтры и хуки. Именно во время этих хуков запускаются все остальные части плагина.
Важной частью является то, что у меня есть определенная структура, и что я передаю то, что необходимо на этапе строительства / начальной загрузки, с определенным жизненным циклом.
Создан 10-08-2017 02:24 Tom J Nowell♦31.9k44694

Вы действительно должны зарегистрировать свои хуки активации / деактивации / деинсталляции вне вашего класса плагинов согласно ответу kaiser здесь, который обеспечивает намного лучшее изложение на предмете, чем я мог бы написать.
Это должно охватить вас, если вы хотите написать этот плагин в качестве учебного упражнения. Если все, что вам нужно, это плагин SEO, который работает хорошо и не увязан с липкой рекламой, такой как Yoast, я очень рекомендую SEO Framework.
Создан 10-08-2017 01:45

Том Макфарлин создал очень обширный шаблон плагинов (в настоящее время поддерживаемый Девином Винсоном), все написанные на ООП, которые вы можете использовать, чтобы создать новый плагин или просто изучить поток приложения, чтобы ответить на ваш вопрос. Я использовал его для нескольких пользовательских плагинов, и должен сказать, что он действительно открыл мне глаза на некоторые тайны ООП.
Создан 10-08-2017 02:29 Gary D1008