Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Moderniser son code WordPress - Meetup AFUP Nov...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Jeremy Desvaux de Marigny Jeremy Desvaux de Marigny
November 28, 2017
160

Moderniser son code WordPress - Meetup AFUP Novembre 2017

Présentation donnée dans le cadre d'un meetup de l'AFUP Montpellier en novembre 2017 à propos des opportunités d'industrialisation de son code WordPress.

Avatar for Jeremy Desvaux de Marigny

Jeremy Desvaux de Marigny

November 28, 2017
Tweet

Transcript

  1. - « Acheter un thème 30$ et changer 3 fichiers,

    tu me fais rire! » - « Mettre x plugins chopés à droite à gauche c’est du bricolage » - « On dirait du code spaghetti des années 90 » - « C’est pas fait pour faire du dev » - « J’y connais rien et en fait je n’ai pas réussi à faire ce que je voulais » « Mais Pourquoi? » 4
  2. - Peu de règles / Grande flexibilité. Faire bien =

    + d’efforts - Votre choix = votre responsabilité - Les tutos - Achat de thème - Choix de plugin D’où vient le bricolage alors? 8
  3. • Programmation objet • PSR • Gestion des dépendances •

    Autoloader / namespaces / PSR4 • Injection de dépendance • Des objets à responsabilité précise • Tests automatisés • Intégration continue "C’est du vieux code" / "C’est pas fait pour faire du dev" 10
  4. Et WordPress du coup? 11 • Programmation objet • PSR

    • Gestion des dépendances • Autoloader / namespaces / PSR4 • Injection de dépendance • Des objets à responsabilité précise • Tests automatisés • Intégration continue • OUCH
  5. - Archi composer - WordPress = vendor - Accès à

    packagist - wpackagist = accès à tous les plugins du repo WP - satis = packages privés + Autoloader et PSR4 Pour composer : On passe sur bedrock 13
  6. Cas 1 : Subir (Core objects, ex wpdb, variables globales)

    Cas 2 : Interfacer / Abstraire (Core concepts ex: routing, API) Cas 3 : Coder en full objet (code plugin ET thème) Pour l’objet : 3 cas de figure 14
  7. - Services! - Container d’injection de dépendance, - MVC (Controllers

    + vue, voire templating) Ce que l’on peut faire aussi 15
  8. - Full objet, namespaces / PSR4 autoloading - Pas de

    fichier à rallonge, on range - Une responsabilité = un objet - Main plugin file - Activator / Deactivator -Hook service, ShortCode service, Routing service, ListTable service… Maintenant la pratique : mon plugin 17
  9. - Penser le fonctionnement - Traduire ce fonctionnement en interface

    - Implémenter l’interface par x services - Injecter ces services Méthode possible 18
  10. « Et si jamais on veut changer ce morceau, quel

    impact ça a sur le code?. » = la question qui guide (et qui vous fait créer des services)
  11. US: En back, je veux administrer les actualités. En front,

    je veux afficher une liste d’actualités paginées, puis le détail d’une actu au clic. Exemple : actualités 20
  12. En back: - Requêter : un repository - Afficher :

    une ListTable - Form édition : un service pour ça - Soumission: un service pour ça Pourquoi tant de services ? - Implémentation WordPress ou autre (web service JSON, SOAP…) - Injection d’un override sur mesure Stratégie 21
  13. Utilisation de composer { "name": "agencewonderful/wwp-actu", "description": "Plugin wwp-actu", "type":

    "wordpress-plugin", "minimum-stability": "dev", "prefer-stable": true, "authors": [ { "name": "Jeremy Desvaux", "email": "[email protected]" } ], "require": { "agencewonderful/wonderwp-plugin-core": "^1.0.0@dev" }, "autoload": { "psr-4": { "WonderWp\\Plugin\\Actu\\": "includes" } }, "repositories": [ { "type": "composer", "url": "https://won.wonderful.fr/satis/packages-mirror" } ] } Gestion de dépendance De version Autoload
  14. Orchestration <?php namespace WonderWp\Plugin\Actu; use WonderWp\Framework\AbstractPlugin\AbstractManager; use WonderWp\Framework\AbstractPlugin\AbstractPluginManager; … class

    ActuManager extends AbstractPluginManager { public function register(Container $container) { parent::register($container); //Register Config $prefix = $this->getPluginName(); $this->setConfig('path.root', plugin_dir_path(dirname(__FILE__))); $this->setConfig('path.url', plugin_dir_url(dirname(__FILE__))); $this->setConfig('textDomain', WWP_ACTU_TEXTDOMAIN); //Register Controllers $this->addController(AbstractManager::ADMIN_CONTROLLER_TYPE, function () { return new ActuAdminController($this); }); $this->addController(AbstractManager::PUBLIC_CONTROLLER_TYPE, function () { return $plugin_public = new ActuPublicController($this); }); //Register Services $this->addService(ServiceInterface::ACTIVATOR_NAME, function () { //Activator return new ActuActivator(WWP_PLUGIN_ACTU_VERSION); }); $this->addService(ServiceInterface::HOOK_SERVICE_NAME, $container->factory(function () { //Hook service return new ActuHookService(); })); $this->addService(ServiceInterface::ASSETS_SERVICE_NAME, function () { //Asset service return new ActuAssetsService(); }); $container[$prefix . '.repository'] = function () { return new ActuRepository(); };
  15. Exemple de rangement Full objet Rangé Un objet par responsabilité

    Facilement overridable (le hook ou le service) <?php namespace WonderWp\Plugin\Core; use WonderWp\Framework\DependencyInjection\Container; use WonderWp\Framework\Hook\AbstractHookService; class WwpHookService extends AbstractHookService { /** @inheritdoc */ public function run(WwpAdminChangerService $adminChangerService) { //Admin Login add_action('login_head', [$adminChangerService, 'customize_login_screen']); add_action('admin_menu', [$adminChangerService, 'forceDashboard']); //Admin pages add_action('admin_head', [$adminChangerService, 'jsConfig']); add_action('admin_head', [$adminChangerService, 'customizeLogo']); add_action('admin_menu', [$adminChangerService, 'customizeMenus']); add_action('admin_init', [$adminChangerService, 'registerPanels']); add_action('save_post', [$panelService, 'savePanels']); add_action('manage_pages_custom_column', [$tableManagerService, 'modifiedColumnValue'], 10, 2); add_filter('manage_edit-page_columns', [$tableManagerService, 'addModifiedColumn']); add_filter('manage_edit-page_sortable_columns', [$tableManagerService, 'addModifiedSortableColumn']); add_action('manage_posts_custom_column', [$tableManagerService, 'modifiedColumnValue'], 10, 2); add_filter('manage_edit-post_columns', [$tableManagerService, 'addModifiedColumn']); add_filter('manage_edit-post_sortable_columns', [$adminChangerService, 'addModifiedSortableColumn']); } }
  16. Exemple d’interfaçage entre vous et WordPress <?php namespace WonderWp\Plugin\Core\Framework\Repository; class

    PostRepository implements RepositoryInterface { /** * @inheritDoc * @return \WP_Post */ public function find($id) { return get_post($id); } /** * @inheritDoc * @return \WP_Post[] */ public function findAll() { $criteria = [ 'numberpost' => -1, ]; return get_posts($criteria); } /** * @inheritDoc * @return \WP_Post[] */ public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) { if (!empty($limit)) { $criteria['numberposts'] = $limit; } else { $criteria['numberposts'] = -1; } if (!empty($offset)) { $criteria['offset'] = $offset; } return get_posts($criteria); } Full objet PSR4 use \WonderWp\PostRepository; $repo = new PostRepository(); $post = $repo->find(1);
  17. Transversaliser les plugins et capitaliser dessus : Créer des vendors

    composer privés ou public. Intégration continue Pour aller plus loin 27
  18. • Passer sur bedrock • Coder en full objet son

    thème et ses plugins • Réappliquer les concepts de code moderne dans vos devs • Middleware entre vous et le code WP qui ne vous plait pas En résumé