Install your composer package somewhere outside vendor

And I don’t mean change the vendor folder name, that’s easy. I mean getting one package in a custom location, whereas the rest still go into vendor.

This will only work with packages that require composer/installers, so if it isn’t your own package and they don’t require that in, then you can stop reading.

Still here? Awesome. In your vendor package, you need to add the installer

composer require composer/installers

Now in your composer.json, change (or add) the type. The package we just required in is actually to help various CMS’es and frameworks, so you must supply a valid type. Thankfully, it doesn’t matter which we choose, as we override the install path anyway.

"type": "ppi-module",

Commit that, and then go to your main project. In the composer.json, add the following:

"extra": {
"installer-paths": {
"/some/custom/path": ["your/package"]
}
}

Now when you run composer install, you’ll see everything but your package in the vendor folder, and your custom package in its custom location! 😀

Advertisements

Setting up a multi user XDebug proxy

I absolutely love XDebug, it’s a tool that no PHP developer should go without! I constantly find myself in contracts where the workplace aren’t using it, and I end up installing and configuring it for them. However, using XDebug alone will only allow one connection at a time. This is fine when we are are developing in an isolated environment, but in many offices an entire team of developers could be working on a server at once! The solution to this is to add an XDebug proxy!

I will assume for this tutorial that you already have XDebug working and can connect with one user.

The first step is to download the debugger proxy itself to the machine running PHP. This can be found here http://code.activestate.com/komodo/remotedebugging/

Now, before you click on the PHP download, DON’T. You actually want the Python one. Download the package for your OS. If you use Linux or Mac, you’ll need python installed too. Windows comes with a binary .exe so Python isn’t required.

Depending whether you are using PHP-FPM or not will determine which port XDebug is currently listening on. PHP-FPM itself runs on port 9000, so if you are using that, your XDebug port will probably be 9001. If you are using PHP as an apache module or whatever, XDebug will probably be listening on port 9000. For the purposes of this article I will assume XDebug is listening on port 9000.

To start the proxy on Windows:

.\pydbgpproxy.exe -d 127.0.0.1:9000 -i 100.200.30.40:9001

To start the proxy on Linux:

export PYTHONPATH=<_Komodo install directory_>/lib/support/dbgp/pythonlib;$PYTHONPATH
cd <_Komodo install directory_>/lib/support/dbgp/bin
python pydbgpproxy -d 127.0.0.1:9000 -i 100.200.30.40:9001

To start the proxy on OS X:

export PYTHONPATH=<_Komodo install directory_>/Contents/SharedSupport/dbgp/pythonlib;$PYTHONPATH
cd <_Komodo install directory_>/Contents/SharedSupport/dbgp/bin
python pydbgpproxy -d 127.0.0.1:9000 -i 100.200.30.40:9001

The options;

-d is the debugger itself, listening on port 9000 on the same machine

-i is the IDE listener port. The IP itself is actually the external IP of this same machine.

If it’s running, you should see something like this:

proxy> .\pydbgpproxy.exe -d 127.0.0.1:9000 -i 10.227.148.40:9001
INFO: dbgp.proxy: starting proxy listeners. appid: 8080
INFO: dbgp.proxy: dbgp listener on 127.0.0.1:9000
INFO: dbgp.proxy: IDE listener on 10.227.148.40:9001

Now back in PHPStorm (or some inferior product) Goto the DBGp Proxy settings in the tools menu, and select configure. Put your name in the IDE key box, the IP of the PHP server, and port 9001.

Again in the tool DBGp proxy, and click Register IDE. If successful, you should be able to see lines like this:

INFO: dbgp.proxy: Server:onConnect ('10.227.148.38', 60748) [proxyinit -p 9000 -k DEREK -m 1 ]
INFO: dbgp.proxy: Server:onConnect ('10.227.148.38', 60996) [proxyinit -p 9000 -k KPATIL -m 1 ]

And that’s it! Now two or more developers can simultaneously use XDebug at the same time. Have fun!

Debugging a Memcached server

Is your Memcached instance working correctly? Who the hell knows? Well, we will in a minute.

Open your terminal, and use the ancient telnet to connect to your server on the correct port (usually 11211):

$ telnet my.memcache.server.net 11211
Trying my.memcache.server.net...
Connected to my.memcache.server.net.
Escape character is '^]'.

Next we reset existing stats then turn on stats collection:

stats reset
RESET
stats detail on
OK

Now, make a request on your website that will call memcache.

Finally, turn stats collection off, then dump the stats collected. If you have output, your memcached server is successfully caching your keys!

stats detail off
OK
stats detail dump
PREFIX User get 3 hit 2 set 1 del 0
PREFIX Trade get 1 hit 0 set 1 del 0
PREFIX Currency get 1 hit 0 set 0 del 0
PREFIX Orders get 2 hit 0 set 2 del 0
PREFIX Prices get 2 hit 0 set 0 del 0
END

To get out of telnet, you type quit.

Codeception Acceptance tests with Javascript

I had an issue on this old legacy site in work where I was writing a basic acceptance test where it clicks all the links in the top section of the home page. The problem was that one of the links opened another window using JavaScript. So I had to reconfigure Codeception to get it running.

There are various different drivers that codeception uses, PhpBrowser which doesn’t do JS, Selenium WebDriver does, and you have several options; you could install Selenium, chrome headless browser, or phantomjs. I chose phantomjs, as it was easiest (for me) to get up and running on a non X Server.

First up, you’ll need phantomjs. Go download it, unpack the zip, move the folder somewhere, and then symlink the bin/phantomjs to /usr/bin/phantomjs.

Next, launch phantomjs like so:

phantomjs --webdriver=4444 --ignore-ssl-errors=true --ssl-protocol=any

Now, in your YAML:

# Codeception Test Suite Configuration

# suite for acceptance tests.
# Run the following command FIRST:
# phantomjs --webdriver=4444 --ignore-ssl-errors=true --ssl-protocol=any

# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.

class_name: WebGuy
modules:
     enabled:
         - WebDriver
         - WebHelper
     config:
         WebDriver:
             url: 'https://USER:PASS@YOUR_URL_HERE'
             browser: phantomjs
             capabilities:
                 acceptSslCerts: true

If you have a site using HTTP Basic Auth, put USER:PASSWORD@ in yopur URL, if not, remove it.

Now in your acceptance test, you can write:

$i->click('Nouvel abonnement');
$i->switchToWindow('webformswin');

Note that, in your Javascript, when you run the open window function, you specify a name. This is the name you use, and not the title from the HTML <head> section!

And there you have it! We can now test with javascript functionality!

Creating DOMElements from HTML strings

DOMDocuments are cool, and a really nice way of dealing with HTML in an OO fashion. However, sometimes, we have an HTML string element which we need to add to our Document. Here’s how you do it:

    function createNodesFromHTML(DOMDocument $doc,$str) 
    {
        $nodes = array();
        $d = new DOMDocument();
        $d->loadHTML("<html>{$str}</html>");
        $child = $d->documentElement->firstChild->firstChild;
        while($child) {
            $nodes[] = $doc->importNode($child,true);
            $child = $child->nextSibling;
        }
        return $nodes;
    }


        $dom = new DOMDocument();
        $icon = '<i class="fa fa-remove"></i>'; // This is our string

        $button = $dom->createElement('a');
        $button->setAttribute('href', '/whatever/delete/12345');
        $button->setAttribute('class', 'btn btn-sm btn-danger');
        
        // This is us turning the string(s) into nodes we can add
        $nodes = createNodesFromHTML($dom, $icon);
        $button->appendChild($nodes[0]);
        
        $dom->appendChild($button);
        echo $dom->saveHTML();