Getting go-ing

Posted on 29th March 2017 | View comments


I had a bit of a play around with Go today. Didn't get much further than a basic hello world but using the net/http component to serve it in the browser. This post really serves as me reminding myself what I did to set everything up and get going.

First up, installing go is easy because I'm on Ubuntu:

$ sudo apt-get install golang

Then, as I'm used to PhpStorm, I went ahead and installed JetBrains's EAP Go IDE, Gogland which was minimal fuss.

Following the documentation and a helpful screencast I managed to figure out something that jarred me to start with. I fired up Gogland, and it kept complaining about GOPATH being missing. It's not immediately clear what this is, but it turns out that Go mandates a specific folder structure, for example if you chose your GOPATH to be in ~/go:

~/go
 - bin
   - project1
   - project2
 - pkg/linux_amd64/github.com/othervendor
   - libfoo.a
 - src/github.com
   - asgrim
     - project1 [...]
     - project2 [...]
   - othervendor
     - libfoo [...]

This was a bit frustrating at first, because I have have all other projects in ~/workspace/<project-name>. So, after throwing my toys out the pram and screaming at a wall, I got over it and understood the folder structure. A good thing to do once you've also done the screaming thing is to set up paths, by adding this into ~/.profile:

export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$PATH

Once set up, I whizzed through the tutorial in the screencast above and got the "hello world" app running, along with the "string" library to reverse the string. I then went a little further and used the net/http library to serve up the string reversing tool as a web page, which was pretty easy to do.

Of course, not that it's much use to anyone, but the repo I set up is in https://github.com/asgrim/go-playground. Just a useful closer, it may help to visualise that folder structure:

~/go
 - bin
   - hello
 - pkg/linux_amd64/github.com/asgrim/go-playground
   - string.a
 - src/github.com
   - asgrim
     - go-playground
       - hello [...]
       - string [...]

Another useful resource I found, though I haven't worked my way through it all is Evert Pot's slides from his talk Go for PHP programmers.

Better Reflection 1.1.0 released

Posted on 25th July 2016 | View comments


After a bit more hacking away, tinkering and violating all good programming practices, I'm pleased to announce the release of Better Reflection 1.1.0, with shiny new features including the highly anticipated monkey patching abilities I've promised at my talk at the Dutch PHP Conference this year. Here's a taster of the main things we've added:

  • Ability to modify function, method and class structure (basic monkey patching)
  • Ability to replace the body of a function or method
  • Updated documentation
  • PHP 7 compatibility
  • Some PHP 7.1 compatibility (more features will come in a future version!)
  • Implemented ::class constant resolution
  • FindReflectionOnLine helper (look up code unit by filename and line number)
  • Various other improvements and bugfixes

The future...

We'd really like to see some feedback on how you folks are using the library, what you find useful, what you think would be a great addition and so on. Right now, the 1.2.0 release is planned to have:

  • PHP 7.1 compatibility (will require PhpParser 3.0 which is currently in beta)
  • Possibly some dynamic autoload handling for easier monkey patching
  • More bug fixes and reflection compatibility
  • Other stuff you request!

Thank you...

Thank you to the contributors for this release!

Go forth and enjoy the new Roave offering of Better Reflection!

Better Reflection - The Lowdown

Posted on 24th June 2016 | View comments


You may have heard me mention Better Reflection a few times already. In fact, I've just done a talk this morning at Dutch PHP Conference 2016 (the slides are on Joind.in now!). If you missed my talk, or weren't able to make the conference... what's the big deal, you might ask. Let me summarise what this is all about, and why this library can help you.

Reflection is part of the core of PHP, and is a built-in set of classes that allow you to introspect your code, and put it under the magnifying glass, so to speak. Surprisingly, there's some limitations as to what you can do; primarily the reflection API is a read-only API, and will give you information only about what is written in code. Additionally, you can only reflect on code that is already loaded - because the way reflection works is to examine the class "blueprint" to get the metadata about methods, properties, parameters, functions, and with PHP 7 also types.

Many of us will have seen, or used, reflection in unit tests. Regardless of your views on testing private properties and methods, there is code out there that does, and these would be tested using reflection. It'd look a little like this:

public function testSomething()
{
    $myObj = new Thing();

    $propReflection = new \ReflectionProperty($myObj, 'foo');
    $propReflection->setAccessible(true);
    $propReflection->setValue($myObj, 'whatever');

    // ... whatever ... 
}

But there's much more to just this simple use case than you think, and it can prove very powerful. This is where Better Reflection comes into play. Better Reflection is a userland library, and therefore doesn't have access (without using PHP's built-in reflection) to everything going on under the hood. Therefore, we've taken a different approach. In Better Reflection, we use the AST generated by Nikita Popov's PHP-Parser library, and use the metadata and more surrounding this to create a mostly-compatible reflection library with some extra bonus features. Let's have a look at a few of these key features...

Reflect without loading code

Because we use the PHP-Parser technique to load the code into AST and analyse like this, we can examine and reflect on code that has not actually been loaded into PHP yet. We can do this a number of different ways, by using these things we called Source Locators. The concept is quite simple; the Source Locators contain the information on how to find the code, and will load the AST. You can use the simple external API, which uses some default Source Locators (which are opinionated and make assumptions about your code), or you can explicitly define the instructions on how to find the code for Better Reflection to load.

This is what it might look like using the defaults:

use BetterReflection\Reflection\ReflectionClass;

$reflection = ReflectionClass::createFromName(\My\ExampleClass::class);

Very simple, right? And if your code doesn't conform to the assumptions we make (i.e. we assume that your autoloader, loads classes from a file - for example if you use Composer to autoload classes, the defaults will work fine):

use BetterReflection\Reflector\ClassReflector;
use BetterReflection\SourceLocator\Type\StringSourceLocator;

$source = <<<EOF
<?php
class MyClassInString {}
EOF;

$reflector = new ClassReflector(new StringSourceLocator($source));

$classInfo = $reflector->reflect(MyClassInString::class);

Yes indeed, this code example shows reflecting code contained in just an arbitrary string!

Monkey patching - modifying code before it runs

One of our planned features in Better Reflection 1.1.0 will be monkey patching, or the ability to modify code before it runs. There are some cases where this will be useful - for example you're using a library which doesn't quite do something, or you'd like to hook into certain places, or modify behaviour arbitrarily.

It's a little long-winded at the moment, and you should use this with caution! Let's say we want to reflect on, and modify the behaviour of this class:

class MyClass
{
    public function foo()
    {
        return 5;
    }
}

By using this code, we can modify the behaviour of the above function to make foo() return 4 instead of 5...

use BetterReflection\Reflection\ReflectionClass;
use PhpParser\PrettyPrinter\Standard as CodePrinter;

// Create the reflections in the normal way
$classInfo = ReflectionClass::createFromName('MyClass');
$methodInfo = $classInfo->getMethod('foo');

// Override the method body with a closure
$methodInfo->setBodyFromClosure(function () {
    return 4;
});

// Bring the class into PHP space
$printer = new CodePrinter();
$classCode = $printer->prettyPrint([
    $classInfo->getAst(),
]);
eval($classCode);

// Instantiate, and execute the resulting class
$c = new MyClass();
var_dump($c->foo()); // will be 4!!!

Essentially, you're replacing the whole body of the function here, but it's also possible to grab the AST from the method, perform your own modifications accordingly, and then call setBodyFromAst() to override the body. You'll also probably notice the rather inelegant method of loading the code; essentially using eval() here, but we still haven't come up with a better, safer, cleaner, and nicer way of doing this (suggestions or ideas are welcome!!).

Better type introspection

As well as using the type information now present in PHP 7, we also read the docblocks and expose methods that allow us to see what these types are for parameters and return types. Naturally, this relies on your docblocks being correct... But, it makes this kind of type introspection possible, even in PHP 5.6 and below code.

More stuff...!

There's plenty of other features already written, as well as planned to be written in future versions of Better Reflection. I'd love to get your feedback on using this library. Does it not do something that you'd like? Would you like to help? Let me know!

PHPSC16 - Scholarship Programme Review

Posted on 15th June 2016 | View comments


This year at PHP South Coast 2016, we decided to run a ticket scholarship programme with fundraising. Someone asked me to blog about how it went, so this is that blog post. I'm presenting my findings here only in note form really, but should give you an idea of how it went:

  • We had a total of 8 contributions to the fund, giving us a total of £543.29 (including VAT). Out of those contributors, five of them preferred to stay anonymous with only three (including me) being happy to have their name published.
  • The "value" of the scholarship award is a £70 (excluding VAT) ticket, so we added wording to the ticketing page to encourage contributions in multiples of £70 (excluding VAT).
  • The largest contribution was £140 (excluding VAT), and the smallest was £1 (excluding VAT). Note that the amount is not important as it goes into a "pot" anyway.
  • Out of the fund, we were able to award five scholarship tickets. We did not have a means to test eligability, we based the system on trust, asking only a handful of questions:
    • Where are you from? (this is important as we needed to advise those applying travelling from afar that we cannot cover travel and accomodation)
    • What is your occupation / are you a student?
    • Where did you hear about us?
  • We had six applicants for tickets. One person never claimed their ticket. Out of the five that did claim, three actually attended the conference.
  • This leaves us with a surplus of £123.29 (including VAT). If we decide to run the scholarship programme next year, this surplus will be used to seed the next programme. If not, we will find a worthy cause to donate the amount to (some ideas are Sustain, Code Club, Bletchley Park).
  • An interesting question was raised about charging VAT, which we investigated with our accountant. We discovered that contributors cannot reclaim VAT on the contributions because the supply is being made to the awardee rather than the contributor. We added this important wording to the Scholarship page on the website.
  • As the conference is not run by a charity (it is run by a not-for-profit social enterprise, PHP Hampshire CIC), unfortunately there are no tax benefits or gift aid available on any of the scheme. The overhead of running a charity is, in our opinion, not worth the additional effort at this stage.

I'm not sure how this measures up to other scholarship programmes, but I feel we operated this with moderate success on a small scale. We're quite a small conference relatively speaking anyway, but I'm mostly happy with the results. I'd like to have been able to award more scholarships, and I'm also a little disappointed that two of the people we awarded tickets to did not attend (as it still costs us for catering etc.). I'm undecided about running the scheme again next year, and instead we may defect to let Sustain or similar external organisation handle this.

The other issue discussed and debated was the means-testing problem; in the end we went down the "trust" route, making an assumption that the applicant "deserved" the ticket. However, this could leave us open to abuse in the future, with tickets being applied for going to those who would otherwise be able to afford or acquire a ticket. It's an interesting problem, because the other method means needing to pry into potentially highly sensitive information about the applicant which they may not feel comfortable revealing to us.

Zend Expressive + Doctrine integration - now even easier!

Posted on 4th March 2016 | View comments


Introduction

Zend Expressive is the new framework on the block, and it's super easy to get up and running with it. On many applications, before long, you'll need to start integrating with a database. My go-to solution, because I'm very familiar with it, is Doctrine. I've already written a guide to set up Doctrine into a Zend Expressive application, but now there's an even easier way of doing this, courtesy of the efforts of Ben Scholzen.

I'd like to introduce you to his new binding library, dasprid/container-interop-doctrine, and show you how to get started with this very simple-to-use set of factories.

Set up a Zend Expressive application

First up, we're going to start from absolute scratch with this project, so we'll start out with a blank canvas using the Zend Expressive skeleton application. As per the Expressive instructions, we simply have to:

$ composer create-project zendframework/zend-expressive-skeleton doctrine-test

When I set up, I accepted all the default options, except I did not opt to install Whoops error handler:

  • Full skeleton
  • FastRoute
  • Zend ServiceManager
  • No template engine
  • No error handler

Now we're set up, don't forget to descend into your new project directory for the rest of the commands.

$ cd doctrine-test

Install container-interop-doctrine

Because Ben is a neat guy, he put his library on Packagist, which makes it super easy to install with Composer:

$ composer require dasprid/container-interop-doctrine

Let's also do a quick sanity check, to ensure everything is working as we'd expect. Fire up a temporary PHP server using the following:

$ php -S 0.0.0.0:8080 -t public/ public/index.php

If you now open up http://localhost:8080/ in your browser, you should see some JSON output indicating everything works:

{"welcome":"Congratulations! You have installed the zend-expressive skeleton application.","docsUrl":"zend-expressive.readthedocs.org"}

If you see this, we're looking good, and can go on to start configuring and using container-interop-doctrine.

Configure container-interop-doctrine

First up we need some configuration, and you'll need an existing MySQL server (or other type of DB that Doctrine supports... take your pick!). I used MySQL, because it was already installed on my machine, so easy to set up. Create your Doctrine configuration in a sensibly named file - to keep things neatly organised, I recommend creating a new file in config/autoload/doctrine.local.php specifically for this purpose.

<?php
return [
    'doctrine' => [
        'connection' => [
            'orm_default' => [
                'params' => [
                    'url' => 'mysql://username:[email protected]/database',
                ],
            ],
        ],
        'driver' => [
            'orm_default' => [
                'class' => \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain::class,
                'drivers' => [
                    'App\Entity' => 'my_entity',
                ],
            ],
            'my_entity' => [
                'class' => \Doctrine\ORM\Mapping\Driver\AnnotationDriver::class,
                'cache' => 'array',
                'paths' => __DIR__ . '/../../src/App/Entity',
            ],
        ],
    ],
];

For your project, you may wish to also create a doctrine.local.php.dist containing a template or example of configuration for other users of your project.

Ben's library container-interop-doctrine has made the set up of the rest of the Doctrine factories super simple by requiring you to only register one single little factory! Head into your dependencies.global.php and add a register for the following factory:

<?php
return [
    'dependencies' => [
        'factories' => [
            'doctrine.entity_manager.orm_default' => \ContainerInteropDoctrine\EntityManagerFactory::class,
        ],
    ],
];

That's actually all the configuration needed to get this thing up and running! Now we can go ahead and make a very basic example to prove everything works as expected.

Create an entity

As you might've noticed in the configuration above, we've pointed our entity driver at the src/App/Entity folder, where we're going to create a very basic entity - just two fields, id and name. This is what my src/App/Entity/Foo.php looks like:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="foo")
 */
class Foo implements \JsonSerializable
{
    /**
     * @ORM\Id
     * @ORM\Column(name="id", type="integer")
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @var int
     */
    private $id;

    /**
     * @ORM\Column(name="name", type="string", length=32)
     * @var string
     */
    private $name;

    /**
     * Application constructor.
     * @param $name
     */
    public function __construct($name)
    {
        $this->name = $name;
    }

    public function jsonSerialize()
    {
        return [
            'id' => $this->id,
            'name' => $this->name
        ];
    }
}

I'm not going to mess around too much with the ORM stuff, for now, you can run this script manually to create the appropriate database table.

CREATE TABLE `foo` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO `foo` (`id`, `name`) VALUES
  (1, 'Testing'),
  (2, 'Testing2');

Naturally, if you're using a different flavour, storage engine, ODM etc., you'll need to adapt this accordingly - this is left as an exercise for the reader.

Update the HomePageAction and Factory

I'm going to go ahead and hack up the src/App/Action/HomePageAction.php now so that it has the pre-configured EntityManager injected and ready to go:

<?php

namespace App\Action;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response\JsonResponse;
use Doctrine\ORM\EntityManager;
use App\Entity\Foo;

class HomePageAction
{
    private $entityManager;

    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
    {
        return new JsonResponse($this->entityManager->find(Foo::class, 1));
    }
}

And the factory, in src/App/Action/HomePageFactory.php needs updating to only inject the Entity Manager:

<?php

namespace App\Action;

use Interop\Container\ContainerInterface;

class HomePageFactory
{
    public function __invoke(ContainerInterface $container)
    {
        $em = $container->get('doctrine.entity_manager.orm_default');

        return new HomePageAction($em);
    }
}

Naturally, this is not something I'd do in production, but this is just a demo, and the quickest way to prove the concept. If you're interested, I'd wrap this fetch process into a service class to abstract the Doctrine logic away from your controller action, so that it can work with a consistent internal API, rather than external dependencies.

That's it! Check it and see it work...

Head back to the browser at http://localhost:8080/ and you should see your new updated JSON response:

{"id":1,"name":"Testing"}

Change the requested ID in the HomePageAction to 2 and you'll see the response change accordingly.

{"id":2,"name":"Testing2"}

As you can see, setting up and binding the Doctrine library to a new Zend Expressive application has been made trivially easy - and it probably takes about 10 minutes to set this all up. For a bare-bones, quick and easy, set up this is really ideal in my opinion, and I'd encourage you to look into this route. That said, there's still times when the functionality that the DoctrineORMModule is a necessity - for example the ObjectSelect and hydrators for binding to Zend\Form instances and so on. If that's something you think you may need, then you could use the above as a basis, but additionally include DoctrineORMModule for the functionality you require.

P.S., CLI tools?

One of the powerful features of Doctrine is the CLI tools that allow you to manage schema, create migrations and so on. For this, Ben provides instructions on setting up the CLI tools over on the README.md - which is something you'll probably want to set up too to take advantage.