Skip to content

Instantly share code, notes, and snippets.

@AmyStephen
Last active December 13, 2018 15:26
Show Gist options
  • Save AmyStephen/4693855 to your computer and use it in GitHub Desktop.
Save AmyStephen/4693855 to your computer and use it in GitHub Desktop.
Example Proxy Pattern implementation in PHP. The example implements an HTTP Proxy using cURL. Try it out on a local server by downloading and opening the page in your browser.
<?php
/**
* @package Design Patterns
* @copyright 2013 Amy Stephen. All rights reserved.
* @license MIT
*
* Proxy Pattern
*
* A proxy pattern creates an entry point which interacts behind the scenes with other objects.
* Can be useful for implementing access control, to implement lazy loading of resource intensive
* objects, or to simply act as a wrapper to reduce the options available to another more complex object
*/
interface HttpInterface
{
public function get();
}
/**
* HttpProxy Usage Instructions:
*
* $proxy = new HttpProxy('http://rss.cnn.com/rss/cnn_world.rss');
* echo $proxy->get();
*
*/
class HttpProxy implements HttpInterface
{
protected $address;
protected $string;
/**
* Constructor
*
* @param $address
*/
public function __construct($address)
{
$this->address = filter_var($address, FILTER_SANITIZE_URL);
}
/**
* Method uses HTTP address to retrieve contents of the page
*
* @return mixed
* @throws Exception
*/
public function get()
{
$handle = curl_init();
curl_setopt($handle, CURLOPT_URL, $this->address);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($handle, CURLOPT_HEADER, 0);
try {
$data = curl_exec($handle);
$response = curl_getinfo($handle);
if ($response['http_code'] == 200) {
} else {
throw new Exception;
}
curl_close($handle);
} catch (Exception $e) {
throw new Exception ('Request for address: ' . $this->address . ' failed.');
}
$this->string = $data;
return $this->__toString();
}
/**
* Format output as a string
*
* @return string
*/
public function __toString()
{
return $this->string;
}
}
/**
* Try the Proxy Pattern Example:
*
* 1. Download and place file on your local server.
* 2. Open the file using your browser.
*/
$proxy = new HttpProxy('http://www.youtube.com/watch?v=oHg5SJYRHA0');
echo $proxy->get();
Agree - removed unnecessary comments from above.
@AmyStephen
Copy link
Author

Agree on the "overkill" for comments. I rarely use comments in the body of the code although I am diligent to provide a decent docblock comment. It's too easy to copy and paste, rarely updated, never tested, and the code should be simple enough to document itself.

In this example case, however, I wanted to leave learners links if they wanted to pick up more about cURL since my example was so basic.

As far as the NOT recommendation, I am of the camp who believe it's best to code "positive."

I don't buy into the "avoid the else" thinking or conserving space. I agree with those who believe the IF portion should represent the "nominal case" but I will think about how to express the normal case in a positive way.

The example we are talking about is simple either way but when the logic starts to get complex, it is very easy to create a bug combining NOT's with OR's and compound logic.

Thanks so much for your comments!

@douma
Copy link

douma commented Dec 13, 2018

This is not a Proxy. A proxy delegates to a subject just like a decorator, with the only difference that proxies are often connecting to a different boundary like a database or remote call or used for lazy loading.

Like:

class LazySoapClient extends SoapClient
{
    protected $constructor, $subject;

    public function __construct($wsdl, array $options = null)
    {
        $this->constructor = func_get_args();
    }

    protected function _getSubject()
    {
        if(!$this->subject) 
        {
            $this->subject = new SoapClient(...$this->constructor);
        }
        return $this->subject;
    }

    public function __call($function_name, $arguments)
    {
        return $this->_getSubject()->__call(...func_get_args());
    }

    public function __soapCall($function_name, array $arguments, array $options = null, $input_headers = null, array &$output_headers = null)
    {
        return $this->_getSubject()->__soapCall(...func_get_args());
    }

    //... other methods that forward to the subject, left out for example 
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment