18

I read this entire post. It describes what a wrapper class is to other experienced programmers, but not to a newbie like me.

I understand PHP syntax, the object-oriented concept, but have not written my own application in object-oriented code yet. I am beyond confused when trying to figure out what exactly a wrapper class is. I don't understand the technical jargon.

I hope someone answers with a beautiful detailed child-like description that is easy to understand for someone that understands the basics of object oriented program and has read through pretty much the entire php.net language reference, but has no actual object oriented programming experience. No applications written yet.

Community
  • 1
  • 1
darga33
  • 401
  • 1
  • 4
  • 10

3 Answers3

24

Since the explanations on the question you linked to are quite extensive, I will not go an redefine it for you again. Instead, I will try to show you via an example of injection.

class Logger {

    private $__logger;

    public function __construct($logger) {
        $class = $logger . "Logger";
        $this->$__logger = new $class();
    }

    public function write($message) {
        $this->$__logger->write($message);
    }
}

So, above you have a class Logger that you may be using to log information somewhere. We don't really care how it does it, we just know it does.

Now, we have a couple of different logging possibilities...

class DBLogger {

    public function write($message) {
        // Connect to the database and 
        // INSERT $message
    }
}

class FileLogger {

    public function write($message) {
        // open a file and
        // fwrite $message
    }
}

class EMailLogger {

    public function write($message) {
        // open an smtp connection and 
        // send $message
    }
 }

Now, when we use our logger, we do it by doing any of the following:

$logger = new Logger("DB");
$logger = new Logger("EMail");
$logger = new Logger("File");

We always interact with $logger in the same way (ie. we call write($message)). The wrapper instance Logger wraps the actual logging class and calls its methods on our behalf.

A more common use of the above type of code would be when using configuration files to determine what your logger is. For example, consider the case where you want to have your logging sent to a file. You might have a config that looks like this:

$logging = array( 
               'type' => 'file',
               'types' => array(
                   'file' => array(
                       'path' => '/var/log'
                       'name' => 'app_errors.log'
                    ),
                    'email' => array(
                       'to' => 'webmaster@domain.com',
                       'from' => 'error_logger@domain.com',
                       'subject' => 'Major fail sauce'
                    ),
                    'db' => array(
                        'table' => 'errors',
                        'field' => 'error_message'
                    )
                )
);

And your adapted classes might look like:

class FileLogger {

    public function __construct() {
        // we assume the following line returns the config above.  
        $this->config = Config::get_config("logger");
    }

    public function write($message) {
        $fh = fopen($this->config->path . '/' . $this->config->file);
        fwrite($fh, $message . "\n");
        fclose($fh);
    }
}

We would do the same for the other adapted classes. Then, with a little modification to the main Wrapper Logger, we could create the correct wrapped instance by using the configuration data and base it on the type that is defined in the config. Once you have something like that in place, switching over to logging via email is as easy as changing the type in the config.

sberry
  • 128,281
  • 18
  • 138
  • 165
  • Thank you so much! Now I officially understand the concept. Although, don't get me wrong. The more examples I am able to look at the better my understanding will be. Thanks for taking the time to write out that example. It is much appreciated and I hope that others find their way to your response! – darga33 Feb 21 '12 at 05:22
  • @sberry Can wrapper class use inheritance? – user1448031 Oct 11 '13 at 12:04
5

Wrapper classes just make their child class easier to use for a particular circumstance. A lot of libraries are written to cover a wide variety of situations and therefore become cumbersome and complex to use. A lot of projects will create a wrappers for the library to make it easier to use.

Take this PDO class usage for example:

$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();

Don't worry too much about the particulars. Just know that these lines of code query a database. A wrapper class allows the same functionality above with something like:

Db::query('SELECT name, colour, calories
  FROM fruit
  WHERE calories < :calories AND colour = :colour',
  array($calories, $colour));

We've removed some of the cumbersome, but seldom-used, features of the child class into an easy to use interface. Internally, the wrapper class is constructing the same sort of calls to PDO, but that's hidden from the developer.

Disclaimer: The examples are just that.. examples. Not meant to show best-practices or even be practical.

Mike B
  • 31,886
  • 13
  • 87
  • 111
  • 1
    IE Sometimes "ease of use" never even occurred to original code authors, so sometimes someone else needs to come along and make a wrapper class to make that possible. Edit to be more fair: sometimes the original code authors didn't realize the additional platforms or purposes their code would be used on. – bob-the-destroyer Feb 21 '12 at 02:48
  • Mike! Same response to you as to sberry! Thanks so much! I can now understand a little bit about what it is used for. I wish there was some way to link this post to the link in the original post so others can benefit from it as well! – darga33 Feb 21 '12 at 05:23
0

I can share my experience.

Wrapper class follows proxy design pattern and this wrapper class can instantiate original class inside it or take an object of original class.

Wrapper class can implement original class method with exactly the same name. In this way, you can inject your own logic there.

I think Wrapper class constructor should not return the original class object.

kta
  • 19,412
  • 7
  • 65
  • 47