Category: Uncategorized

  • Redirect all traffic to another domain with Laravel Forge

    Here’s something that I need to do every now and then, and always forget how.

    To set up a new redirect, first head over to the “Redirects” tab on your site in Forge.

    Then, create a new redirect rule with the following configuration:

    From
    /

    To
    {REDIRECT_DOMAIN}$request_uri

    Type
    Permanent

    You’re done!

  • Writing SOAP Web Service Consumers in PHP

    Recently I’ve had to interact with a number of SOAP web services, and I’ve come up with some techniques to help build good SOAP web service consumers.

    The two most important goals when building a SOAP consumer is for the code to be maintainable and testable.

    Dark Beginnings

    A natural first approach is to write one class that handles everything necessary to interact with the web service:

    <?php
    
    namespace App;
    
    use SoapClient;
    
    class Consumer
    {
        protected $client;
    
        public function __construct($wsdl, $username, $password)
        {
            $this->client = new SoapClient($wsdl, [
                'login' => $this->username,
                'password' => $this->password
            ]);
        }
    
        public function getBooks()
        {
            $response = $this->client->getBooks();
    
            // Transform the response as appropriate...
    
            return $response;
        }
    }

    What we’ve written above is difficult to test because we’re constructing the SoapClient ourselves. Testing any methods on the consumer would mean making a real call to the web service.

    We can do better:

    <?php
    
    namespace App;
    
    class Consumer
    {
        protected $client;
    
        public function __construct($client)
        {
            $this->client = $client
        }
    
        // ..
    }

    By having the consumer declare outright what it requires to work (an instance of a client) we’re now able to construct the consumer with mock instances of the SoapClient where we can fake real calls to the web service.

    Bonus: the consumer is no longer responsible for constructing a SoapClient object with the correct credentials. It’s always a good sign to reduce a class’s responsibilities.

    Writing a Test

    Now that we have a way to inject a client into our consumer, let’s use Mockery to fake a web service call:

    <?php
    
    namespace Tests\Unit\WebServices\Consumer\Methods;
    
    use App\Consumer;
    use Mockery as m;
    use Tests\TestCase;
    
    class GetBooksTest extends TestCase
    {
        /** @test */
        function it_gets_books()
        {
            // Mock the client to return our XML...
            $client = m::mock()
                ->shouldReceive('getBooks')
                ->once()
                ->andReturn(simplexml_load_string($this->getXml()))
                ->getMock();
    
            // Inject our mock SoapClient into the consumer
            // and make the call that we're testing...
            $response = (new Consumer($client))->getBooks();
    
            // Assert that the response is what we would expect...
            $this->assertEquals([
                [
                    'title' => 'The Alchemist',
                ], [
                    'title' => 'Veronica Decides To Die',
                ], [
                    'title' => 'The Second Machine Age',
                ],
            ], $response);
        }
    
        private function getXml()
        {
            return <<<XML
    <GetBooksResponse>
        <Books>
            <Book>
                <Title>The Alchemist</Title>
            </Book>
            <Book>
                <Title>Veronica Decides To Die</Title>
            </Book>
            <Book>
                <Title>The Second Machine Age</Title>
            </Book>
        </Books>
    <GetBooksResponse>
    XML;
        }
    }

    Since PHP’s SoapClient returns a SimpleXml  object from a web service method call, that’s what we’ll have our mock object return too – except we’ll use our predefined XML snippet in order to control our testing environment.

    We’re now free to test the response as we sit fit!

    Avoiding a 4000 Line Long Consumer Class

    As you write more and more code to consume the methods of the web service, your class will quickly grow long. This will happen especially quickly if there is any complex logic associated with formatting web service method requests and responses.

    The approach I use to keep classes short is to write one class per web service method. Here’s how:

    <?php
    
    namespace App;
    
    use Exception;
    
    class Consumer
    {
        protected $client;
    
        public function __construct($client)
        {
            $this->client = $client
        }
    
        public function __call($method, $parameters)
        {
            if (! class_exists($class = $this->getClassNameFromMethod($method))) {
                throw new Exception("Method {$method} does not exist");
            }
    
            $instance = new $class($this->client);
    
            // Delegate the handling of this method call to the appropriate class
            return call_user_func_array([$instance, 'execute'], $parameters);
        }
    
        /**
         * Get class name that handles execution of this method
         *
         * @param $method
         * @return string
         */
        private function getClassNameFromMethod($method)
        {
            return 'App\\Methods\\' . ucwords($method);
        }
    }

    The refactored consumer class now looks for a class in the App\Methods\* namespace with the same name as the method being called. If found, it will create an instance of the class, and delegate to it.

    In our example, a call to $consumer->getBooks() would internally be routed to another class called App\Methods\GetBooks .

    No matter how many methods we need to consume, our consumer class will never get any bigger!

    Bonus: our consumer class now conforms to the Open and Closed principle.

    Here’s what our App\Methods\GetBooks class looks like:

    <?php
    
    namespace App\Methods;
    
    class GetBooks
    {
        protected $client;
    
        public function __construct($client)
        {
            $this->client = $client;
        }
    
        public function execute()
        {
            $response = $this->client->getBooks();
    
            // Transform the response as appropriate...
    
            return $response;
        }
    }

     

    Caching Calls

    A common optimization technique is to cache web service calls. With a small tweak to our consumer, we can allow our method classes to be responsible for their own caching:

    <?php
    
    namespace App;
    
    use Exception;
    use App\Cacheable;
    
    class Consumer
    {
        protected $client;
    
        public function __construct(client)
        {
            $this->client = $client
        }
    
        public function __call($method, $parameters)
        {
            if (! class_exists($class = $this->getClassNameFromMethod($method))) {
                throw new Exception("Method {$method} does not exist");
            }
    
            $instance = new $class($this->client);
    
            if ($instance instanceof Cacheable) {
                return $instance->cache($parameters);
            }
    
            // Delegate the handling of this method call to the appropriate class
            return call_user_func_array([$instance, 'execute'], $parameters);
        }
    
        /**
         * Get class name that handles execution of this method
         *
         * @param $method
         * @return string
         */
        private function getClassNameFromMethod($method)
        {
            return 'App\\Methods\\' . ucwords($method);
        }
    }

    Whenever a method class implements the App\Cacheable interface, the cache method will be called instead. If using Laravel, this could look like the below:

    public function cache($parameters)
    {
        return app('cache')->remember('Ws.GetBooks', 10, function () use ($parameters) {
            return call_user_func_array([$this, 'execute'], $parameters);
        });
    }

     

    Logging Calls

    Debugging will be infinitely easier if all your web service calls are logged. Since we’re injecting the SoapClient into our consumer, we can write a simple decorator to log all web service calls:

    <?php
    
    namespace App;
    
    use SoapClient;
    use Psr\Log\LoggerInterface;
    
    class SoapClientLogger
    {
        protected $client;
        protected $logger;
    
        public function __construct(SoapClient $client, LoggerInterface $logger)
        {
            $this->client = $client;
            $this->logger = $logger;
        }
    
        public function __call($method, $parameters)
        {
            $response = call_user_func_array([$this->client, $method], $parameters);
    
            $this->logger->info("Request: {$method}. " . $this->client->__getLastRequest());
            $this->logger->info("Response:", (array) $response);
    
            return $response;
        }
    }

    For the request to be logged correctly, we’ll need to enable tracing when configuring our SoapClient:

    $consumer = new Consumer(new SoapClientLogger(new SoapClient(config('services.web_service.wsdl'), [
        'login' => config('services.web_service.login'),
        'password' => config('services.web_service.password'),
        'trace' => true,
    ]), $this->getLogger()));

    Of course, we can configure Laravel’s Container to correctly build our consumer class whenever we request it, by writing the following code in a service provider:

    $this->app->bind(Consumer::class, function ($app) {
        return new Consumer(new SoapClientLogger(new SoapClient(config('services.web_service.wsdl'), [
            'login' => config('services.web_service.login'),
            'password' => config('services.web_service.password'),
            'trace' => true,
        ]), $this->getLogger()));
    });

     

    End

    Dealing with SOAP web services can be a messy business. Use and improve upon the techniques written here to make the process a little bit more pleasant.

    Happy coding!

  • Copying Font Awesome Fonts with Laravel Elixir

    For some reason, I always have trouble setting up Font Awesome (quickly) with Laravel & Elixir.

    It’s three easy steps.

    Pull in font-awesome with npm or yarn

    # npm
    npm install font-awesome --save
    
    # yarn
    yarn add font-awesome

    Import Font Awesome’s stylesheets in your app.scss file

    @import "node_modules/font-awesome/scss/font-awesome.scss";

    Copy Font Awesome’s font files to your public directory

    Configure Elixir to do this automatically for you in your gulpfile:

    elixir((mix) => {
        mix.sass('app.scss')
           .webpack('app.js')
           .copy('node_modules/font-awesome/fonts/*.*', 'public/fonts/');
    });

    This last step is the one that I mix up, specifically the *.* .

    Hopefully this will help someone like me!

  • Stress Testing a Website with Throng

    I recently needed to stress test a website to ensure that it could hold up in the real world – after some searching I stumbled upon Throng – a simple app for Mac. It allowed me to hit my website with concurrent requests for a specified period of time.

    You can download the 7-day trial of Throng from this link.

    The app allows you to specify a URL you’d like to hit, a time limit in seconds, and the number of concurrent users to simulate. Hit Start and it will immediately begin hitting your website – charting the average response time.

    Alternatives

    Load Impact – An online tool service to stress test your website. I tried it until my credits ran out – but I found that for my (simple) needs Throng was a better choice.

  • Creating an Embeddable Javascript Widget

    One of the updates I’m working on for WhichBeach is the ability for other website owners to embed WhichBeach widgets that will display up-to-date beach data. This is very much a work in progress, but I’d like to share.

    I’ve never done anything like this before, so I thought I’d start by taking some inspiration from Facebook’s Like Button implementation:

    <!-- Load Facebook SDK for JavaScript -->
    	<div id="fb-root"></div>
    	<script>(function(d, s, id) {
    	  var js, fjs = d.getElementsByTagName(s)[0];
    	  if (d.getElementById(id)) return;
    	  js = d.createElement(s); js.id = id;
    	  js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1";
    	  fjs.parentNode.insertBefore(js, fjs);
    	}(document, 'script', 'facebook-jssdk'));</script>
    
    	<!-- Your like button code -->
    	<div class="fb-like" 
    		data-href="http://www.your-domain.com/your-page.html" 
    		data-layout="standard" 
    		data-action="like" 
    		data-show-faces="true">
    	</div>

    To break it down, Facebook’s script injects a new script tag that pulls in their Javascript SDK. They’re also ensuring that the script is only injected once into the page.

    I think I can make this work for me too:

    <!-- Load WhichBeach SDK for Javascript -->
    <div id="wb-root"></div>
    <script>(function(d, s, id) {
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) return;
      js = d.createElement(s); js.id = id;
      js.src = "//whichbeach.app/js/sdk.js";
      fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'whichbeach-jswidget'));</script>
    
    <div class="wb-widget" data-size="skyscraper"></div>

    Great. Now all that’s left is to write a Javascript SDK! I’ll need to expose that on /js/sdk.js and add all my widget logic in there.

    In due time… if anyone has any tips and resources that they think I should be using – let me know in the comments!

  • Applying Text Transform to Form Inputs

    I often find myself in the situation where a design calls for form inputs to transform the user’s text. It’s pretty easy to do nowadays:

    input[type="text"] {
        text-transform: uppercase;
    }

    This is what it looks like:

    But – I’ve always found these types of interactions frustrating whenever I come across them. The expectation of the user is jarred when the user’s input changes unexpectedly. I decided to do some research and found a couple of posts on the subject.

    Is text-transform uppercase frustrating when used in input form fields?

    Here’s a discussion on UX Stack Exchange that suggests transforming the text after the field loses focus. This javascript solution does seem slightly better than a simple CSS transform – but I still find it awkward when I come across these forms.

    The User Experience (UX) Of CSS Text-Transform On Form Input Fields

    Ben Nadal wrote an interesting commentary about how CSS transforms on form inputs causes frustration and confusion. I agree with him here.

    So what’s the best way to do it?

    I say – don’t ever transform a user’s input in a form field. User’s have come to expect forms to act in a certain way, and changing that (even for the better) gives your form an extra learning curve.

    If you really need to transform the user’s input somehow, I did come up with an elegant solution recently – by showing the user a summary of their form input (after or while they’re filling in the form) you can get the best of both worlds.

    The user can refer to the form where the text that they have input remains unchanged. At the same time, they can see the summary where they text that they’ve input has been modified in some way.

    I’d be interested to hear if anyone has any thoughts or findings on the topic in the comments!

  • Learning the Language

    I wrote an article about how learning the language of the business should effect your code over at BRND WGN.

    One way to alleviate the problem with ‘naming’ in programming is to write code using the jargon of your client’s business.

    With every new skill, comes a new bundle of terms that separate the complete novice from someone on their way to mastery.

    Read the rest of the article here.