0

I was viewing this question PHP - defining classes inside a function(How it has so many upvotes is beyond me)

In short it does not answer my question.

Specifically speaking following with wordpress plugin creation codex

A shortcode is something you can use in any plugin once created for example

//Create callback for shortcode
function DisplayNumberFive(){
  echo "5";
}

//create shortcode as [DNF]
add_shortcode('DNF','DisplayNumberFive');

Now anywhere that I wanted to display the number 5 I can simply do

do_shortcode("[DNF]");

and the output is 5

Now with this functionality in mind would it make sense to have a class for instance

//Create callback for shortcode
 function CreateFooClass(){
  class Foo{
    function Bar(){
      return "FooBar";
    }
  }
 }

 //Create shortcode as [include_Foo]
 add_shortcode('include_foo','CreateFooClass');

 //Use case
 do_shortcode("[include_foo]");

 $foo = new Foo();

 echo $foo->Bar();

 //Ouput
 "FooBar"

My question is if I am doing this wrong or if this introduces bugs that I do not see. Would Bar() even be accessible since it is within a function?

The goal is to eliminate the need for duplicate files within plugins on wordpress so if you create a class for example for logging events on one plugin but you would also like to log events for another plugin the files in one plugin are not accessible to one another so a duplicate file must be made in the other plugin so to eliminate that creating a shortcode would allow the class to be accessible everywhere within all plugins which is how I came to this solution I am just concerned that It may not be right considering I could not find any google results detailing anyone doing this and it made me question if nobody else has done it there must be a reason why.

So why does nobody do this?

CoderJoe
  • 447
  • 3
  • 25
  • After reading the question you have linked, it seems the jury is still out on whether or not it is indeed bad practice IMHO, hence the upvotes. – Russ J Feb 28 '19 at 18:52
  • 1
    The biggest issue is that if you call `CreateFooClass()` twice then you get a fatal error. I recommend putting the class into a dedicated file and have the `CreateFooClass()` function simply `require_once()` that class file. This allows for your class file to be importable without requiring the presence of `CreateFooClass()` – MonkeyZeus Feb 28 '19 at 18:55
  • after 8 years I would assume maybe someone would have an answer @RussJ or at least some new magical code is used in place – CoderJoe Feb 28 '19 at 18:56
  • @MonkeyZeus But that would mean you have to have multiple files because you can not require a file that is outside of your folder – CoderJoe Feb 28 '19 at 18:56
  • @JosephWilliamson Coke and Pepsi have each been around for 100+ years and people STILL get into fistfights over which is better :-P – Russ J Feb 28 '19 at 18:59
  • 2
    Where did you get the idea you can't require a file outside of a folder? I'd also question how this way of defining a class is useful, when there is autoloading or just plain old require_once inclusion. – gview Feb 28 '19 at 18:59
  • 1
    Unfortunately I am not familiar with WordPress's structure at all. However, I assume your dilemma is that your plug-in doesn't know about the users's installed classes? If this is the case then ship your class in a sub-folder of your plug-in. If my comment is pure non-sense then please elaborate what you mean by `you can not require a file that is outside of your folder`? – MonkeyZeus Feb 28 '19 at 19:01
  • It seems you just want a helper method to do your logging. As with the answer posted, I wouldn't go the shortcode route either - it may technically work, but definitely not the intended method when you can simply load the class without all the extra work. You might consider creating a plugin that creates the helper `Class` that you can access everywhere if you're concerned about duplicating content in each of your plugins. – disinfor Feb 28 '19 at 19:15
  • @disinfor that is exactly what I am trying to accomplish but I run into this dilema also for those who are not familiar with wordpress using an autoloader only makes that class available within the plugin directory it would not be available at any top level or other plugin directories – CoderJoe Feb 28 '19 at 20:13
  • The `Class` isn't only available in the plugin directory. It's available everywhere as soon as it instantiates. You need to make sure it loads before the other plugins. – disinfor Feb 28 '19 at 21:05

2 Answers2

1

I understand that Object Oriented Programming has been on the top for over a dozen years, but WP uses a completely different paradigm: Structural programming. So try to avoid mixing this.

And now for your case:

If you use autoloader, then files with classes will be automatically included on first class use.

In addition, you use class definitions straight from PHP4. In PHP5 the keywords public,private, protected has been introduced (to adjust the visibility of methods in classes).

It looks, that do_shortcode is created to return HTML, so next solution can't be used with it. (But try it, I'm not sure.)

function CreateFooClass(){
  if(!class_exists('Foo')) {
    class Foo{
      public function Bar(){
        return "FooBar";
      }
    }
  }
  return new Foo()
 }

$foo = CreateFooClass();
$foo->Bar();
bato3
  • 2,695
  • 1
  • 18
  • 26
  • It looks like this with solve what I have seen other people complain about a fatal error if the function is called more then once – CoderJoe Feb 28 '19 at 19:46
  • That's why there is added `if(!class_exists('Foo'))` – bato3 Feb 28 '19 at 19:48
  • OT your function should be named `DeclareFooClass` because for creation require `new` operator. – bato3 Feb 28 '19 at 19:53
  • good point @bato3 This does not describe why I should not mix the 2 just that i shouldnt – CoderJoe Feb 28 '19 at 20:12
  • Simply: some things not proper to do. Here you introduce confusion. For the PHP interpreter, the form of the code does not matter, but in other people such code will be annoying. – bato3 Feb 28 '19 at 20:20
0

WordPress shortcodes were never designed to be called in PHP context. They are meant to be used in content. Being able to call shortcode in PHP is more of an implementation detail than something you would normally do.

So, yeah, technically you could use this to call shortcode from PHP to use it as a kind of class load mechanism.

Or you could a real class autoload and $foo = new Foo(); would work without any extra code.

So no one is doing it (or anything like it) because autoload is a thing and works fine.

Rarst
  • 2,335
  • 16
  • 26