Paul M. JonesControllers and Domain Exceptions (23.5.2017, 12:00 UTC)

A few months ago I had a great email conversation with a correspondent about how to handle business logic exceptions in his controller code. His message follows, lightly edited for brevity and clarity:

I think controller has single responsibility – to mediate communication between caller’s context and actual business logic services. (I believe business logic services should be unaware of caller’s context, be it HTTP request or CLI.)

Given that services should be unaware of who called them, they should not throw HTTP-specific exceptions. So instead of throwing a Symfony HttpNotFound Exception, the service would throw ObjectNotFound (which is HTTP agnostic) in cases where DB record could not be found.

Yet at the same time the logic that converts exceptions to HTTP responses expects HTTP-specific Symfony exceptions. This means that the exception thrown by service needs to be transformed into Symfony exception.

One of solutions I see to this is that the controller could take that responsibility. It would catch domain exceptions thrown by service and wrap them into appropriate HTTP exceptions.

class FooController
{
    public function fooAction()
    {
        try {
            $this->service->doSomething('foo');
        } catch (ObjectNotFound $e) {
            throw new NotFoundHttpException('Not Found', $e);
        } catch (InvalidDataException $e) {
            throw new BadRequestHttpException('Invalid value', $e);
        } // ...
    }
}

The downside I see with this approach is that if I have many controllers I will have code duplication. This also could lead to big amount of catch blocks, because of many possible exceptions that could be thrown.

Another approach would be to not have try/catch blocks in controller and let the exceptions thrown by service bubble up the stack, leaving the exception handling to exception handler. This approach would solve the code duplication issue and many try/catch block issue. However, because the response builder only accepts Symfony exceptions, they would need to be mapped somewhere.

It also feels to me that this way the controller is made cleaner, but part of controllers responsibility is delegated to something else, thus breaking encapsulation. I feel like it’s controllers job to decide what status code should be retuned in each case, yet at the same time, cases usually are the same.

I truly hope you will be able to share your thoughts on this and the ways you would tackle this.

If you find yourself in this situation, the first question to ask yourself is, “Why am I handling domain exceptions in my user interface code?” (Remember: Model-View-Controller and Action-Domain-Responder are user interface patterns; in this case, the user interface is composed of an HTTP request and response.) Domain exceptions should be handled by the domain logic in a domain-appropriate fashion.

My correspondent’s first intuition (using domain-level exceptions, not HTTP-specific ones) has the right spirit. However, instead of having the domain service throw exceptions for the user interface controller to catch and handle, I suggest that the service return a Domain Payload with domain-specific status reporting. Then the user interface can inspect the Domain Payload to determine how to respond. I expand on that approach in this post.

By way of example, instead of this in your controller …

class FooController
{
    public function fooAction()
    {
        try {
            $this->service->doSomething('foo');
        } catch (ObjectNotFound $e) {
            throw new NotFoundHttpException('Not Found', $e);
        } catch (InvalidDataException $e) {
            throw new BadRequestHttpException('Invalid value', $e);
        } // ...
    }
}

… try something more like this:

class FooController
{
    public function fooAction()
    {
        $payload = $this->service->doSomething('foo');
        switch ($payload->getStatus()) {
            case $payload::OBJECT_NOT_FOUND:
                throw new NotFoundHttpException($payload->getMessage());
            case $payload::INVALID_DATA:
                throw new BadRequestHttpException($payload->getMessage());
            // ...
        }
    }
}

(I am not a fan of using exceptions to manage flow control; I’d rather return a new Response object. However, I am trying to stick as closely to the original example as possible so that the differences are more easily examined.)

The idea here is to keep domain logic in the domain layer (in this case, a service). The service should validate the input, and if it fails, return a “not-valid&r

Truncated by Planet PHP, read more at the original (another 2328 bytes)

Link
Rob AllenInserting binary data into SQL Server with ZF1 & PHP 7 (22.5.2017, 10:45 UTC)

If you want to insert binary data into SQL Server in Zend Framework 1 then you probably used the trick of setting an array as the parameter's value with the info required by the sqlsrv driver as noted in Some notes on SQL Server blobs with sqlsrv.

Essentially you do this;

$data['filename'] = 'test.gif';
$data["file_contents"] = array(
    $binaryData,
    SQLSRV_PARAM_IN,
    SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY),
    SQLSRV_SQLTYPE_VARBINARY('max')
);
$db->insert($data);

Where $db is an instance of Zend_Db_Adapter_Sqlsrv.

If you use SQL Server with ZF1 and happen to have updated to PHP 7, then you may have found that you get this error:

An invalid PHP type for parameter 2 was specified

(At least, that's what happened to me!)

Working through the problem, I discovered that this is due to Zend_Db_Statement_Sqlsrv converting the $params array to references with this code:

// make all params passed by reference
$params_ = array();
$temp    = array();
$i       = 1;
foreach ($params as $param) {
    $temp[$i]  = $param;
    $params_[] = &$temp[$i];
    $i++;
}
$params = $params_;

The Sqlsrv driver (v4) for PHP 7 does not like this!

As Zend Framework 1 is EOL, we can't get a fix into upstream and update the new release, so we have to write our solution.

We want to override Zend_Db_Statement_Sqlsrv::_execute() with our own code. To do this we firstly need to override Zend_Db_Adapter_Sqlsrv. (Also, let's assume we already have a App directory registered with the autoloader)

Firstly our adapter:

App/Db/Adapter/Sqlsrv.php:

<?php

class App_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Sqlsrv
{
    protected $_defaultStmtClass = 'App_Db_Statement_Sqlsrv';
}

This class simply changes the default statement class to our new one. Now, we can write our Statement class:

App/Db/Statement/Sqlsrv.php:

<?php

class App_Db_Statement_Sqlsrv extends Zend_Db_Statement_Sqlsrv
{
    /**
     * Executes a prepared statement.
     *
     * @param array $params OPTIONAL Values to bind to parameter placeholders.
     * @return bool
     * @throws Zend_Db_Statement_Exception
     */
    public function _execute(array $params = null)
    {
        $connection = $this->_adapter->getConnection();
        if (!$this->_stmt) {
            return false;
        }

        if ($params !== null) {
            if (!is_array($params)) {
                $params = array($params);
            }

            // make all OUT or INOUT params passed by reference
            $params_ = array();
            $temp    = array();
            $i       = 1;
            foreach ($params as $param) {
                $temp[$i]  = $param;
                if (is_array($param) && in_array($param[1], [SQLSRV_PARAM_OUT, SQLSRV_PARAM_INOUT])) {
                    $params_[] = &$temp[$i];
                } else {
                    $params_[] = $temp[$i];
                }
                $i++;
            }
            $params = $params_;
        }

        $this->_stmt = sqlsrv_query($connection, $this->_originalSQL, $params);

        if (!$this->_stmt) {
            require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
            throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
        }

        $this->_executed = true;

        return (!$this->_stmt);
    }
}

This class, takes the _execute() method from Zend_Db_Statement_Sqlsrv and makes the necessary changes the section that creates parameter references. Specifically, we only create a reference if the parameter has a direction of SQLSRV_PARAM_OUT or SQLSRV_PARAM_INOUT:

// make all OUT or INOUT params passed by reference
$params_ = array();
$temp    = array();
$i       = 1;
foreach ($params as $param) {
    $temp[$i]  = $param;
    if (is_array($param) && in_array($param[1], [SQLSRV_PARAM_OUT, SQLSRV_PARAM_INOUT])) {
        $params_[] = &$temp[$i];
    } else {
        $params_[] = $temp[$i];
    }
    $i++;
}
$params = $params_;

Finally, we need to register our new adapter with Zend_Application's Database resource. This is done in the config file:

application/configs/application.ini:

resources.db.params.adapterNamespace = "App_Db_Adapter"

That's it.

We can now insert binary data into our SQL Server database from PHP 7 using the latest sqlsrv drivers.

Link
SitePoint PHPRe-Introducing Composer – the Cornerstone of Modern PHP Apps (21.5.2017, 16:00 UTC)

In this article, we will tackle the basics of Composer, and what makes it such a powerful and useful tool.

Before we go into detail, there are two things that we need to have in mind:

  • What Composer is:

    As we can see on their website: "Composer is a tool for dependency management in PHP. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you."

    • What Composer is not:

    Composer is not a package manager. It deals with packages but in a "per project" way. While it provides a global installation option, it does not install anything globally by default.

Essentially, Composer allows you to declare and manage every dependency of your PHP projects.

Let's now install Composer so we can see it in action.

Composer logo

Installation

There are two ways of installing Composer: locally and globally. Because Composer is such a useful and widespread tool, I always recommend installing it globally, as you'll probably be working on more than one project at once.

Note that if you use an environment like Homestead Improved, it's installed globally by default. If you're unfamiliar with Vagrant and Homestead, this post will clear things up, and if you'd like to dive deeper, this book will reveal some wild mysteries to you.

To install Composer, follow the instructions for your operating system.

If you're on a Unix system, after installing it you can run the command:

mv composer.phar /usr/local/bin/composer

This moves the composer.phar file to a directory that's on your path (the location of your filesystem where the OS looks for executable files by default). This way, you can use just the composer command instead of composer.phar.

Running the composer command shows the information page:

Composer main information

Some of Composer's more useful commands are:

  • composer help - will show the help page for a given command.
  • composer self update - Updates composer to the latest available version.
  • composer search - Searches for packages.
  • composer status - Shows a list of modified packages.
  • composer diagnose - Diagnoses the system for common errors.
  • composer status - Shows a list of dependencies that have been modified locally. If we install something from the source (using the --prefer-source option), we will end up with a clone of that package in the /vendor folder. If we make some changes to that package, the composer status command will show us a git status for those changes.
  • composer diagnose - Diagnoses the system for common errors. This is especially useful for debugging, as it checks for things like connectivity to Packagist, free disk space and git settings.

We will focus our attention on composer init, composer create-project and composer require.

Using Composer

To manage dependencies in a project, Composer uses a json file. This file describes all the dependencies, and holds some metadata as well.

In this example we will create a new PHP project in which we will need PHPUnit for our unit testing. There are several ways to use Composer to manage this dependency.

Continue reading %Re-Introducing Composer – the Cornerstone of Modern PHP Apps%

Link
Stefan KoopmanschapWhat is WeCamp all about? (21.5.2017, 08:01 UTC)

Recently I got an email from someone who was interested in coming to WeCamp, but needed some more information to help convince their manager. I wrote a big email trying to describe WeCamp and our ideas of what WeCamp is (or should be).

Since this may actually be useful to more people that want to come to WeCamp but need to convince their manager, I'm posting that email here as well.

The idea behind WeCamp is that attendees will go through the whole process of a software development project. When the attendees come to the island they will be assigned in teams with 4 other people that they most probably not know (we try to split up people who work for the same company or live in the same region). Every team of 5 people will be assigned one of the coaches, and this coach will support the team in finding their own way in the project. These coaches are specifically NOT teachers, but instead people who will support the team, because we want the team to find their own way most of the time.

Once a team is formed and assigned a coach, they find a working place on the island, and they'll have to think of a project to work on. The team will have to think of a project themselves and decide on what is realistic to build given the limited amount of time (usually about 3 days of development). Once they've decided on their MVP and created their initial planning, they start working on their project.

Each team is free to choose a methodology for development. While we've so far seen no waterfall-style development, we've had several different methodologies from full scrum to kanban and variations on both because the team decided that was the best approach. One thing all teams have though: A central stand-up right before lunch where each team can share their progress, the problems they've run into and their lessons learned. In that way we try to get everyone to learn from everyone else. During the fifth day, each team will present their project as well as their lessons learned while doing the project.

To balance out all the hard work, we have some social events during the week. We have a game night (with board- and card games, no electronic games!), we have a BBQ and we have a "pirate game", an activity where a pirate comes to the island with some friends to have everyone do some assignments. When there's no special events at night, there's always the option for a drink with fellow attendees around the camp fire. Everyone sleeps in tents with beds in 'em, on the island. The price for the ticket is all-in: It includes all drinks and meals so attendees don't have to worry about anything during the 5 days on the island.

When we first started WeCamp 4 years ago, we meant to start a technical event. We had a lot of experience with conferences as an inspiring place for new tech, but felt we never had time to actually play with that new tech. That's what we initially aimed for with WeCamp: A place to actually play around with new tech. It quickly turned out though that all the tech is cool, but WeCamp was about more than just tech. It was about personal development. About learning a lot of soft skills next to all the tech: communication, teamwork, planning, making decisions, presenting.

The coaches will have private conversations with all team members, and together they will create a personal development plan with attendees. Some time after WeCamp coaches follow up with their team members to see if the goals set in the personal development plan were reached, or at least are being pursued.

Link
SitePoint PHPJumping from PHP to Go: Blasphemy, Bravado or Common Sense? (19.5.2017, 16:00 UTC)

Earlier this year, I made an arguably bad business decision. I decided to rewrite the Laravel application powering Boxzilla in Go.

No regrets though.

Boxzilla platform page

Just a few weeks later I was deploying the Go application. Building it was the most fun I had in months, I learned a ton, and the end result is a huge improvement over the old application. Better performance, easier deployments and higher test coverage.

The application is a fairly straightforward database driven API & account area where users can log-in to download the product, view their invoices or update their payment method.

Continue reading %Jumping from PHP to Go: Blasphemy, Bravado or Common Sense?%

Link
Paul M. Jones“Action Injection” As A Code Smell (16.5.2017, 12:00 UTC)

Circumstance has conspired to put Action Injection discussions in front of me multiple times in the past few days. Having seen the approach several times before, I have come to think that if Action Injection is the answer, you might be asking the wrong question. I find it to be a code smell, one that indicates the system needs refactoring or reorganizing.

Action Injection …

As far as I can tell, the term “Action Injection” originates with Alex Meyer-Gleaves in a 2010 article on ASP.NET MVC development. He summarizes Action Injection in this way:

Your [controller class] constructor is provided the dependencies [by the DI container] that are shared by all actions in your controller, and each individual action [method] can request any additional dependencies that it needs.

To expand on that, let’s say you have a controller class with several action methods in it. You realize after a while that the different action methods have slightly different dependencies. For example, some of the methods need a logger, while others need a template system, or access to the router. But you don’t want to pollute the controller class constructor with these method-specific dependencies, since those dependencies will be used only if that particular action method gets invoked.

With Action Injection, when you pull the controller from your dependency injection container and call a particular action method, the DI container will automatically pass the right dependencies for the method call arguments. Voila: now you can define all the common dependencies as parameters on the controller constructor, and all the action-specific dependencies as parameters on the method definition.

You can see a PHP-specific description of the problem, with Action Injection as the solution, in this Symfony pull request:

https://github.com/symfony/symfony/pull/21771

You can also hear about it in this presentation from Beau Simensen, from around 32:21 to 34:31:

https://www.youtube.com/watch?v=JyrgwMagwEM&feature=youtu.be&t=1941

The Yii and Laravel containers appear to support this behavior as well, using the term “method injection.” (I think that’s a misnomer; the term appears overloaded at best, as sometimes it may mean “methods called by the DI container at object-creation time” instead of “resolving method arguments at call-time”.) Perhaps other DI containers support Action Injection as well.

… As A Code Smell

The explicit reason for using Action Injection is “to reduce dependencies or overhead” when constructing an object. You don’t want to have to pass in a dozen dependencies, when only three are used in every method, and the others are used only in specific methods.

But the fact that your controller has so many dependencies, used only in some cases and not in others, should be an indicator that the class is doing too much. Indeed, it’s doing so much that you cannot call its action methods directly; you have to use the dependency injection container not only to build the controller object but also to invoke its action methods.

Reorganizing To Avoid Action Injection

What approaches exist to help you avoid the Action Injection code smell? I assert that the better solution is to change how you organize your controller structures.

Instead of thinking in terms of “a controller class with action methods,” think in terms of “a controller namespace with action classes.” Actions are the targets for your routes anyway, not controller classes per se, so it makes sense to upgrade actions to “first-class” elements of the system. (Think of them as single-action controllers, if you like.)

Thus, instead of …

<?php
namespace App;

class BlogController {

Truncated by Planet PHP, read more at the original (another 3357 bytes)

Link
Voices of the ElePHPantInterview with Michelangelo van Dam (16.5.2017, 12:00 UTC) Link
Qafoo - PHPExtracting Value Objects (16.5.2017, 08:25 UTC)
Software systems usually get more complex over time. In the beginning a variable starts out to represent something very simple with very few rules and constraints that can are enforced in a single location of the code. We will show you how you can use value object extraction to avoid spreading logic everywhere.
Link
SitePoint PHPCan You Build a CLI Image Drawing Laravel App with These Packages? (15.5.2017, 16:02 UTC)

It's time for our monthly hunt for new open source libraries to use and contribute to!

If you're new to Sourcehunt, it's our monthly post for promoting open source projects that seem interesting or promising and could use help in terms of Github stars or pull requests.

It's our way of giving back - promoting projects that we use (or could use) so that they gain enough exposure to attract a wider audience, a powerful community and, possibly, new contributors or sponsors.

Sourcehunt logo


laracademy/interactive-make [216 ★]

Laravel Interactive Make is a plugin that lets you use Laravel's make command interactively, without being verbose about exactly what it is you want to generate, as the following gif demonstrates:

Gif of Laravel Interactive Make in action

The tool will ask you about commands and sub-commands until you reach a point at which you're happy with what got generated. No more looking up make commands!

There's some issues to take care of, so get to helping!


reibengu/laravel-auto-validation [45 ★]

This package will let you remove all manual validation from Laravel Controllers, and instead rely on automatic validation that kicks instantly into action as a given controller and method are called - all you need to do is use the package's trait in a controller, and set the service provider. Then, you define rules like so:

$rules = [
    'UserController' => [
        'register' => [
            'name'     => 'required|max:255',
            'email'    => ['required', 'email', 'max:255', Rule::unique('users')->where('status', 1)],
            'password' => 'required|min:6|confirmed',
            'gender'   => 'required|in:male,female',
            'birthday' => 'required|date_format:Y-n-j',
        ],
        'update' => function ($request) {
            return [
                'name'     => 'required|max:255',
                'email'    => 'required|email|max:255|unique:users,email,'.$request->user()->id,
                'gender'   => 'required|in:male,female',
                'birthday' => 'required|date_format:Y-n-j',
            ];
        },
    ],
];

return ['rules' => $rules];

The remainder of the process is automatic, and if validation fails, the request is automatically redirected back to the page from where it came, with error messages about validation flashed into session.

The project has no outstanding issues or pull requests, but why not add some? Here's an idea: make it dead easy to customize these error messages, and integrate them with Laravel's translator.

Continue reading %Can You Build a CLI Image Drawing Laravel App with These Packages?%

Link
Rob AllenAutocomplete Composer script names on the command line (15.5.2017, 10:03 UTC)

As I add more and more of my own script targets to my composer.json files, I find that it would be helpful to have tab autocomplete in bash. I asked on Twitter and didn't get an immediate solution and as I had already done something similar for Phing, I rolled up my sleeves and wrote my own.

Start by creating a new bash completion file called composer in the bash_completion.d directory. This file needs executable permission. This directory can usually be found at /etc/bash_completion.d/, but on OS X using Homebrew, it's at /usr/local/etc/bash_completion.d/.

This is the file:

# Store this file in /etc/bash_completion.d/composer

_composer_scripts() {
    local cur prev
    _get_comp_words_by_ref -n : cur

    COMPREPLY=()
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    #
    #  Complete the arguments to some of the commands.
    #
    if [ "$prev" != "composer" ] ; then
        local opts=$(composer $prev -h --no-ansi | tr -cs '[=-=][:alpha:]_' '[\n*]' | grep '^-')
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi


    if [[ "$cur" == -* ]]; then
        COMPREPLY=( $( compgen -W '-h -q -v -V -n -d \
            --help --quiet --verbose --version --ansi --no-ansi \
            --no-interaction --profile --working-dir' -- "$cur" ) )
    else
        local scripts=$(composer --no-ansi 2> /dev/null |  awk '/^ +[a-z]+/ { print $1 }')
        COMPREPLY=( $(compgen -W "${scripts}" -- ${cur}) )
    fi

    __ltrim_colon_completions "$cur"
    return 0
}

complete -F _composer_scripts composer

(Note that __ltrim_colon_completions is only in recent versions of bash-completion, so you may need to remove this line.)

Reading from the bottom, to get the list of commands to composer, we create a list of words for the -W option to compgen by running composer --no-ansi and then manipulating the output to remove everything that isn't a command using awk. We also create a separate list of flag arguments when the user types a hyphen and then presses tab.

Finally, we also autocomplete flags for any subcommand by running composer {cmd} -h --no-ansi and using tr and grep to limit the list to just words starting with a hyphen.

That's it. Now composer {tab} will autocomplete both built-in composer commands and also custom scripts!

Composer autocomplete

As you can see, in this example, in addition to the built-in commands like dump-autoload and show, you can also see my custom scripts, including apiary-fetch and .

This is very helpful for when my memory fails me!

Link
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP