web-dev-qa-db-fra.com

OOP Plugin Development. Y compris objet externe

Je développe un plugin en utilisant des classes et une programmation orientée objet.

Dans mon plugin, j'ai inclus un autre objet car j'ai besoin d'utiliser les fonctionnalités de cet autre objet.

J'instancie l'objet inclus dans le constructeur de mon plugin.

require_once ('path/to/my/IncludedObject');

class MyPlugin
{
    private $IncludedObject;

    public function __construct()
    {
        $this->IncludedObject = new IncludedObject();
    }
}

class IncludedObject
{
    public $instanceVar = 'defaultValue';

    public function getInstanceVar()
    {
        return $this->instanceVar();
    }

    public function setInstanceVar($instanceVar)
    {
        $this->instanceVar = $instanceVar;
    }
}

Le $ instaceVar est mis à jour après une action ajax dans mon formulaire HTML commandé par mon plugin. Donc, depuis le gestionnaire de mon plugin, j'appelle setInstanceVar ($ _ REQUEST ['newValue']);

Le problème auquel je suis confronté est que $ instanceVar n'est jamais mis à jour et a toujours la 'defaultValue'.

Quelqu'un peut-il faire la lumière sur cette question?

Merci

1
ivantxo

La racine de votre problème n'est pas la programmation orientée objet, mais un malentendu fondamental sur la façon dont PHP gère les requêtes.

S'il s'agissait d'une application Java ou Node par exemple, vous démarriez l'application sur le serveur, elle recevait les demandes et répondait. C'est un programme actif continu. Par conséquent, vous pouvez stocker des éléments en mémoire et ils sont toujours là lorsque vous faites une autre demande car ils ne sont jamais partis.

Ce n'est pas ainsi que fonctionne PHP.

Les demandes PHP ont plus en commun avec AWS Lamda, chaque demande engendre un tout nouveau cycle de vie PHP. Vous pouvez définir des choses en mémoire mais elles disparaissent à la fin de la demande, tous vos objets, vos fonctions , vos variables, tout cela.

Chaque nouvelle demande charge l'intégralité de l'application PHP à partir de zéro. Tous vos plugins, WordPress, votre thème, sont rechargés à chaque fois, puis disparaissent de la mémoire à la fin de la demande.

Alors, comment persistez-vous?

La seule façon de persister est d'utiliser un stockage persistant, comme une base de données, des fichiers, des cookies, des caches d'objets, etc.

Les alternatives incluent:

  • Pour les données spécifiques à l'utilisateur connecté, utilisez la méta utilisateur
  • Pour les données spécifiques à l'utilisateur déconnecté, utilisez des cookies si le serveur a besoin d'accès et un stockage local basé sur JS pour tout le reste
  • Pour conserver les informations sur les formulaires de plusieurs pages, utilisez des entrées masquées, il n'est pas nécessaire de conserver quoi que ce soit côté serveur jusqu'à ce qu'il soit soumis
  • Pour des informations à l'échelle du site, utilisez les options et les transitoires
  • Pour les données post-spécifiques, utilisez les termes post-méta et taxonomie
  • Pour les données spécifiques au terme, utilisez le terme méta

Notez qu'il peut être tentant d'utiliser $_SESSION PHP variables de session, mais:

  • ceux-ci sont vulnérables au détournement de session
  • ne sont pas utilisés par WordPress (WP utilise des cookies)
  • doivent être configurés et nettoyés manuellement
  • ne fonctionne pas avec beaucoup d'hôtes
  • sont incompatibles avec de nombreux systèmes CDN et de mise en cache, par ex. Cloudflare
  • Ces données doivent être stockées quelque part en mémoire sur le serveur, ce qui pourrait entraîner des problèmes avec des situations de trafic élevé

Quelques notes de suivi sur OO

  1. Utilisez l'injection de dépendance! Votre objet n'a rien à faire en créant d'autres objets dans son constructeur. Passez-les comme arguments. Cela rendra vos objets plus flexibles, plus faciles à tester, plus faciles à déboguer et vous évitera beaucoup de maux de tête.
  2. 1 classe par fichier, ne pilotez pas vos fichiers PHP. Gardez-le agréable et simple
  3. Votre IncludedObject pourrait tout aussi bien avoir la variable publique, il n'y a aucun intérêt à avoir un getter et un setter si vous pouvez simplement y accéder directement. Soit rendre cette variable privée ou se débarrasser de ces getter/setters
  4. N'appelez pas les choses "-> setXYZ ()" etc. Appelez-le simplement ->xyz(), appelez-le tel qu'il est. Pourquoi écrire $person->getName() alors que vous pouvez avoir $person->name()? Beaucoup plus simple.
  5. Il en va de même pour les setters, pourquoi avoir $person->setName() alors que vous pouvez avoir $person->rename()?

Mais surtout, avez-vous vraiment besoin d'objets ici? Faire des choses OO ne signifie pas que vous écrivez un meilleur code, cela signifie simplement que vous essayez OO. Si vos objets n'ont pas d'état interne et n'implémentent pas d'interfaces abstraites, alors vous ne gagnez rien en utilisant des classes, et ce n'est pas OO.

Ne faites pas un énorme gâchis de fonctions et enveloppez-les dans une classe et prétendez que c'est OO, ce n'est pas le cas, c'est juste une frappe supplémentaire pour vous. Alors, évitez les tracas. Il est normal que le point d'entrée de votre plugin soit une fonction. Il est correct de mettre des filtres rapides en tant que fonctions simples, vous n'avez pas besoin de tout mettre dans une classe.

Vous apprenez peut-être, mais ne vous forcez pas à utiliser des cours sous le couvert de "OO", ce n'est pas OO, et vous apprendrez simplement de mauvaises habitudes.

6
Tom J Nowell

EDIT: Comme indiqué, ce n'est pas une solution préférée sur wordpress as wordpress est sans état).

Votre problème n'est pas les objets externes, c'est la persistance des données. Je suppose que vous voulez avoir une persistance des données via une session utilisateur, vous pouvez donc utiliser quelque chose comme $ _SESSION (si vous voulez une persistance via une session utilisateur)

Donc, votre plugin pourrait avoir quelque chose comme ça

add_action( 'init', 'instanciate_object' );

//Check if object already instanciated, if not, instanciate.
function instanciate_object()
{
  if ( !isset( $_SESSION['myObject']) {
    $_SESSION['myObject'] = new includedObject();
  }
}

puis votre gestionnaire ajax ferait cela:

function ajax_handler()
{
  if ( isset( $_SESSION['myObject'] ) {
      $object = $_SESSION['myObject'];
      $object->setInstanceVar( $_REQUEST['newValue']);
      $_SESSION['myObject'] = $object;
  }
}

Assurez-vous que le fichier avec ajax_handler a accès à la définition de classe.

0
Jess_Pinkman