1

I am developing a plugin by using classes and object oriented programming.

Within my plugin I have included another object as I need to use the functionality of this other object.

I am instantiating the included object within my plugin's constructor.

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;
    }
}

The $instaceVar is updated after an ajax action within my HTML form commanded by my plugin. So, from the handler within my plugin I call setInstanceVar($_REQUEST['newValue']);

The problem I am facing is that $instanceVar never gets updated and always have the 'defaultValue'.

Can anyone shed some light on this issue?

Thanks

  • Can you include the code that's actually giving you trouble? – Jacob Peattie Nov 8 at 0:05
6

The root of your problem is not object oriented programming, but a fundamental misunderstanding about how PHP handles requests.

If this were a Java or a Node application for example, you would start the application on the server, and it would recieve requests, and respond. It's a continuous active program. As a result, you can store things in memory and they're still there when you make another request as they never went away.

That's not how PHP works.

PHP requests have more in common with AWS Lamda, each request spawns a brand new PHP lifecycle. You can set things in memory but they dissapear at the end of the request, all your objects, your functions, your variables, all of it.

Every new request loads the entire PHP application from scratch. All your plugins, WordPress, your theme, get reloaded every time, then vanish from memory when the request finishes.

So How Do You Persist Things?

The only way to persist things is to use persistent storage, such as a database, files, cookies, object caches, etc

Alternatives include:

  • For logged in user specific data use user meta
  • For logged out user specific data, use cookies if the server needs access, and JS based local storage for everything else
  • For persisting information across multi-page forms, use hidden inputs, there's no need to persist anything server side until it's submitted
  • For site wide information, use options and transients
  • For post specific data use post meta and taxonomy terms
  • For term specific data, use term meta

Note that it might be tempting to make use of $_SESSION PHP session variables, but:

  • these are vulnerable to session hijacking
  • aren't used by WordPress ( WP uses cookies )
  • have to be manually set up and cleaned up
  • don't work with a lot of hosts
  • are incompatible with a lot of CDN and caching systems, e.g. Cloudflare
  • That data has to be stored somewhere in memory on the server, so this could cause problems with high traffic situations

Some Follow up Notes on OO

  1. Use dependency injection! Your object has no business creating other objects in its constructor. Pass them in as arguments. It'll make your objects more flexible, easier to test, easier to debug, and save a lot of headaches.
  2. 1 class per file, don't piledrive your PHP files. Keep it nice and simple
  3. Your IncludedObject might as well just have the public variable, there's no point in having a getter and a setter if you can just access it directly. Either make that variable private or get rid of those getter/setters
  4. Don't call things "->setXYZ()" etc. Just call it ->xyz(), call it what it is. Why write $person->getName() when you can have $person->name()? Much simpler.
  5. The same goes for setters, why have $person->setName() when you can have $person->rename()?

But most importantly, do you really need objects here? Making things OO doesn't mean that you're writing better code, it just means you're trying OO. If your objects have no internal state, and don't implement any abstract interfaces, then you gain nothing from using classes, and it's not OO.

Don't make a huge mess of functions and wrap them in a class and pretend it's OO, it isn't, it's just extra typing for you. So save yourself the hassle. It's ok for the entry point of your plugin to be a function. It's ok to put quick filters as plain functions, you don't have to put everything in a class.

You might be learning, but don't force yourself to use classes under the guise of "OO", it isn't OO, and you'll just be learning bad habits.

  • This makes sense and that is right I was thinking the Java way, I thought my PHP objects will persist. Well, thank you for your answer and I was trying to avoid database at all costs. Hopefully I find some elegant solution, otherwise database will be. Thanks. – ivantxo Nov 8 at 0:23
  • You've got APIs in WP that'll give you custom post types to store things, taxonomies to organiser them, and post meta for the fine detail. You don't need to write custom database tables and queries if you use the tools WP gives you – Tom J Nowell Nov 8 at 0:29
  • Thanks for the follow up notes. I will consider them. – ivantxo Nov 8 at 0:32
  • @Tom, he said he wants to avoid database, not custom database, so 'custom post types, taxonomies, and post meta', all those include database. On a side note, while I agree with your comments on OO, I'd like to nitpick a bit, it is considered a best practice in all OOP to start a method with a verb, even though this is not in PSR. – Jess_Pinkman Nov 8 at 1:38
  • I read in many places that's not the case, it's rare to find anything everybody agrees on in OO. I've noticed you either get people saying use getters and setters because of encapsulation, or, people who say they're bad when naively implemented, and to name them differently instead, and some people who say your objects shouldn't be dumb bags of data. – Tom J Nowell Nov 8 at 14:14
0

EDIT: As pointed, this is not a prefered solution on wordpress as wordpress is stateless.

Your problem is not external objects, it is about data persistency. I am presuming you want to have data persistency through a user session, so you could use something like $_SESSION ( if what you want is persistency through a user session )

So, your plugin could have something like that

add_action( 'init', 'instanciate_object' );

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

and then your ajax handler would do that:

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

Make sure that the file with the ajax_handler does have access to the class definition.

  • Yes, my issue is about data persistence. You shed another interesting solution which I will check later. Yours makes sense to me too. Thanks all for your inputs. I will check the more convenient to me. – ivantxo Nov 8 at 1:09
  • PHP session variables don't work on a lot of WordPress hosts, and are fundamentally incompatible with a lot of CDNs and caching mechanisms. You won't get PHP sessions working with hosts like WP Engine, systems like Cloudflare, or plugins like WP Supercache. I would also strongly advise against storing objects and other complex data types in PHP sessions, and stick to scalar types such as integers and strings. WP itself uses cookies for user sessions – Tom J Nowell Nov 8 at 14:15
  • Also see phpsec.org/projects/guide/4.html for the security implications of PHP sessions. I would also avoid using $_REQUEST as it's not just a synonym for POST and GET, it also handles COOKIES SESSION ENV and others, always be explicit about using POST or GET – Tom J Nowell Nov 8 at 14:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.