Matthias NobackBackwards compatible bundle releases (27.9.2014, 11:43 UTC)

The problem

With a new bundle release you may want to rename services or parameters, make a service private, change some constructor arguments, change the structure of the bundle configuration, etc. Some of these changes may acually be backwards incompatible changes for the users of that bundle. Luckily, the Symfony DependenyInjection component and Config component both provide you with some options to prevent such backwards compatibility (BC) breaks. If you want to know more about backwards compatibility and bundle versioning, please read my previous article on this subject.

This article gives you an overview of the things you can do to prevent BC breaks between releases of your bundles.

Renaming things

The bundle itself

You can't, without introducing a BC break.

// don't change the name
class MyOldBundle extends Bundle
{
}

The container extension alias

You can't, without introducing a BC break.

use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class MyBundleExtension extends Extension
{
    ...

    public function getAlias()
    {
        // don't do this
        return 'new_name';
    }
}

Parameters

If you want to change the name of a parameter, add another parameter with the desired name, which receives the value of the existing parameter by substitution:

parameters:
    old_parameter: same_value
    new_parameter: %old_parameter%

class MyBundleExtension extends Extension
{
    public function load(array $config, ContainerBuilder $container)
    {
        $container->setParameter('old_parameter', 'same_value');
        $container->setParameter('new_parameter', '%old_parameter%');
    }
}

Now existing bundles or the user may still change the value of old_parameter and that change will propagate to the new parameter too (thanks WouterJNL for suggesting this approach!).

Config keys

The container extension alias can not be changed without causing a BC break, but it is possible to rename config keys. Just make sure you fix the structure of any existing user configuration values before processing the configuration:

class Configuration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('my');

        $rootNode
            ->beforeNormalization()
                ->always(function(array $v) {
                    if (isset($v['old_name'])) {
                        // move existing values to the right key
                        $v['new_name'] = $v['old_name'];

                        // remove invalid key
                        unset($v['old_name']);
                    }

                    return $v;
                })
            ->end()
            ->children()
                ->scalarNode('new_name')->end()
            ->end()
        ;
    }
}

Service definitions

If you want to rename a service definition, add an alias with the name of the old service:

services:
    new_service_name:
        ...

    old_service_name:
        alias: new_service_name

This may cause a problem in user code, because during the container build phase they may call $container->getDefinition('old_service_name') which will cause an error if old_service_name is not an actual service definition, but an alias. This is why user code should always use $container->findDefintion($id), which resolves aliases to their actual service definitions.

Method names for setter injection

services:
    subject_service:
        calls:
            # we want to change the name of the method: addListener
            - [addListener, [@listener1]]
            - [addListener, [@listener2]]

This one is actually in the grey area between the bundle and the library. You can only change the method names used for setter injection if users aren't supposed to call those methods themselves. This should actually never be the case. You should just offer an extension point that takes away the need for users to call those methods. The best option is to create a compiler pass for that:

namespace MyBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

class InjectListenersPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $subjectDefinition = $container->findDefintion('subject');

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

Link
SitePoint PHPHow to Install Custom PHP Extensions on Heroku (26.9.2014, 16:00 UTC)

In this tutorial, we’ll learn how to install custom extensions on Heroku. Specifically, we’ll be installing Phalcon.

Sign-up and Set up

In order to use Heroku, you must sign up for a Heroku account. Heroku generally works with a command-line interface. To use that interface, you need to install the Heroku toolbelt package for your operating system. If you are using Linux, open up terminal and type the following command.

wget -qO- https://toolbelt.heroku.com/install.sh | sh

After installing the toolbelt, you’ll have access to the heroku command from your command shell. Authenticate using the email address and password you used when creating your Heroku account:

heroku login


Enter your Heroku credentials.
Email: fcopensuse@gmail.com
Password:
Could not find an existing public key.
Would you like to generate one? [Yn]
Generating new SSH public key.
Uploading ssh public key /home/duythien/.ssh/id_rsa.pub

Press enter at the prompt to upload your existing ssh key or create a new one, used for pushing code later on.

Phalcon is a third party extension, and thus not bundled with PHP. Phalcon requires the following components:

Continue reading %How to Install Custom PHP Extensions on Heroku%

Link
Michael KimsalDealing with an incorrect security report (26.9.2014, 06:53 UTC)

A colleague of mine has had his company’s code “security audited” by one of their clients; specifically, the client hired a firm to do security testing for many (all?) of that company’s services, and my colleague’s company was one of the services.

They’re told they’re in danger of losing the account unless all of the “security holes” are patched. The problem is, some of the things that are being reported don’t seem to be security holes, but their automated scanner is saying that they are, and people can’t understand the difference.

Here’s an example – you tell me if this is crazy or not.

For URL:
hostedapp.com/application/invite/?app_id="><script>alert(1407385165.6523)</script>&id=104

Output contains:
<input type="hidden" name="app_id" id="app_id" value=""><script>alert(1407385165.6523)</script>">

Report coming back is:
Cross-Site Scripting vulnerability found
Injected item: GET: app_id
Injection value: "><sCrIpT>alert(14073726.2017)</ScRiPt><input "
Detection value: 14073726.2017
This is a reflected XSS vulnerability, detected in an alert that was an immediate response
to the injection.

When you pass in a value, it is escaped; there is no alert box that pops up (in any browser at all). I’m *thinking* that the reporting tool is simply seeing that the number exists on the resulting page (“detection value”) and is flagging this as “bad”. That seems way too naive for a security tool, though.

Is there some other explanation for why a security tool would look at this and still report that this was ‘insecure’?


I'm currently working on a book for web freelancers, covering everything you need to know to get started or just get better. Want to stay updated? Sign up for my mailing list to get updates when the book is ready to be released!

Web Developer Freelancing Handbook

Link
Matthias NobackExposing resources: from Symfony bundles to packages (25.9.2014, 22:00 UTC)

Symfony bundles: providing services and exposing resources

When you look at the source code of the Symfony framework, it becomes clear that bundles play two distinct and very different roles: in the first place a bundle is a service container extension: it offers ways to add, modify or remove service definitions and parameters, optionally by means of bundle configuration. This role is represented by the following methods of BundleInterface:

namespace Symfony\Component\HttpKernel\Bundle;

interface BundleInterface extends ContainerAwareInterface
{
    /** Boots the Bundle. */
    public function boot();

    /** Shutdowns the Bundle. */
    public function shutdown();

    /** Builds the bundle. */
    public function build(ContainerBuilder $container);

    /** Returns the container extension that should be implicitly loaded. */
    public function getContainerExtension();

    ...
}

The second role of a bundle is that of a resource provider. When a bundle is registered in the application kernel, it automatically starts to expose all kinds of resources to the application. Think of routing files, controllers, entities, templates, translation files, etc.

The "resource-providing" role of bundles is represented by the following methods of BundleInterface:

interface BundleInterface extends ContainerAwareInterface
{
    ...

    /** Returns the bundle name that this bundle overrides. */
    public function getParent();

    /** Returns the bundle name (the class short name). */
    public function getName();

    /** Gets the Bundle namespace. */
    public function getNamespace();

    /** Gets the Bundle directory path. */
    public function getPath();
}

As far as I know, only getName() serves both purposes, since it is also used to calculate the configuration key that is used for the bundle's configuration (e.g. the configuration for the DoctrineBundle is to be found under the doctrine key in config.yml).

There are several framework classes that use the bundle name and its root directory (which is returned by the bundle's getPath() method) to locate resources in a bundle. For instance the ControllerResolver from the FrameworkBundle allows you to use the Bundle:Controller:action notation to point to methods of controller classes in the Controller directory of your bundle. And the TemplateNameParser from the FrameworkBundle resolves shorthand notation of templates (e.g. Bundle:Controller:action.html.twig) to their actual locations.

It's actually quite a clever idea to use the location of the bundle class as the root directory for the resources which a bundle exposes. By doing so, it doesn't matter anymore whether a bundle is part of a package that is installed in the vendor directory using Composer, or if it's part of your project's source code in the src directory; the actual location of resources is always derived based on the location of the bundle class itself.

Towards a better situation for resources

Let me first say, I think the BundleInterface ought to be separated in two different "role interfaces", based on the different roles they play. I was thinking of ProvidesServices and a ExposesResources interface. That would clearly communicate the two different things that a bundle can do for you.

Puli: uniform resource location

Much more important than splitting the BundleInterface is to have a better way of exposing resources located inside a library (or bundle, it wouldn't make a difference actually). This is something Bernhard Schüssek has been working on. He has created a nice library called Puli. It basically provides a way to locate and discover resources from all parts of the application, be it your own project or a package that you pulled in using Composer.

The core class of Puli is the ResourceRepository. It works like a registry of resource locations. For every resource or collection of resources that you want to expose, you call the add() method and provide as a first argument a prefix, and as a second argument an absolute path to a directory:

use Webmozart\Puli\Repository\ResourceRepository;

$repo = new ResourceRepository();
$repo->add('/matthias/package-name/templates', '/path/to/Resources/views');

Now if you ask the repository to get the absolute path of a particular resource, you can do it by using the prefix you just

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

Link
Matthias NobackSemantic versioning for bundles (25.9.2014, 22:00 UTC)

A short introduction to semantic versioning

Semantic versioning is an agreement between the user of a package and its maintainer. The maintainer should be able to fix bugs, add new features or completely change the API of the software they provide. At the same time, the user of the package should not be forced to make changes to their own project whenever a package maintainer decides to release a new version.

The most extreme solution to this problem is: the package should never change, the user should never need to upgrade. But this is totally useless, since the user wants new features too, they just shouldn't jeopardize their existing, functioning code. At the same time the package maintainer wants to release new features too, and they may even want to redo things completely every once in a while.

Semantic versioning assumes a package to have a version number that consists of three numbers, separated by dots, like 2.5.1. The first number is called the "major version", the second number is called the "minor version", the last number is called the "patch version". The semantic versioning agreement in short tells the package maintainer to increment the:

MAJOR version when you make incompatible API changes,

MINOR version when you add functionality in a backwards-compatible manner, and

PATCH version when you make backwards-compatible bug fixes.

You can read the full explanation of the concept and what you are agreeing upon if you say that your package "follows semantic versioning" on semver.org.

Symfony and semver

As of version 2.3 the Symfony framework officially uses semver. They also apply some extra rules for parts of the code (classes, interfaces, methods) which they label as being part of the official Symfony API by adding an @api annotation to the respective doc comments. Semantic versioning and public API labeling together this consistutes Symfony's backwards compatibility promise.

In short, Semantic Versioning means that only major releases (such as 2.0, 3.0 etc.) are allowed to break backwards compatibility. Minor releases (such as 2.5, 2.6 etc.) may introduce new features, but must do so without breaking the existing API of that release branch (2.x in the previous example).

Bundles and semver

I was asked by Paul Rogers from the Symfony Live London crew:

How should you version a bundle? Should it be related to the library version, like ElasticBundle does?

As a matter of fact, I had already spent some toughts on this issue. The answer to the first question is: apply semver, just like any package should do. And the answer to the second is: no. It should not per se be related to the library version for which the bundle provides a framework-specific integration layer. I think this second answer requires some more detailed reasoning from my side.

Bundles expose an API themselves

The code in a library package exposes an API. People are going to use that API in a particular way. They are going to instantiate some of the classes from the package with a particular set of constructor arguments. They are going to call some of its methods with a particular set of arguments. This is the reason why semantic versioning should be applied to such packages in the first place: the maintainer should not be allowed to change any of the things the user relies on, like class names, method names, required parameters, etc.

A bundle mostly doesn't expose an API consisting of classes and methods. The API of a bundle consists of *services, or service definitions, and parameters. These are different types of entities. Yet they share some characteristics: service definitions often provide constructor arguments in a particular order, they sometimes contain method calls used for setter injection, they are public or private, abstract or concrete, have a certain name, etc.

Some changes, like making a private service public won't make a difference for an existing user.

services:
    formerly_a_private_service:
        public: true

If a service was formerly a private service, the user could not have relied on it in any way that a public service doesn't support. So that kind of a change should not to be considered a backward compatibility (BC) break.

The other way around - making a public service private - on the contrary should be considered a BC break.

services:
    formerly_a_public_service:
        public: false

Some users may rely on it being public. For example they may call

$container->

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

Link
SitePoint PHPEssentials of LDAP with PHP (25.9.2014, 16:00 UTC)

Ever wanted a simple way to store address book style information and network information actually next to any kind of ordered information?

If so, then there’s a technology which has been around since 1993, one which despite not having the cool factor of such technologies as Node.js and Go, allows you to do exactly this. It’s called LDAP!

What is LDAP?

LDAP is short for Lightweight Directory Access Protocol and was developed at the University of Michigan around 1993, by Tim Howes, Steve Kille, Colin Robbins, and Wengyik Yeong.

In short, LDAP is an internet-ready version of an earlier protocol called X.500, which was developed back in the 80’s by the International Telecommunications Union (ITU) for managing telephone directories and directory services.

Whilst LDAP technically refers to the protocol, the name is often applied to the client and server as well. If it helps, you can think of it like SQL is for database servers; it’s the language used to interact with LDAP-enabled servers.

There are a number of LDAP-enabled servers around, the most common of which is Microsoft’s ActiveDirectory; which has been pervasive throughout their product lineup since the release of Windows 2000.

There’s an open source choice as well, one which we’ll be using throughout this article series, called OpenLDAP. It makes no assumptions as to the schema you’re using or the information you’re storing.

Here in part one of the series, I’m going to:

  1. Take you through the basics of setting up an OpenLDAP
  2. Show you how to load up a set of records
  3. Show you how to connect to it and perform some basic operations

Terminology

Before we do that, we need to look at a bit of the terminology. Continuing with the SQL analogy, there are a couple of terms which you’ll need to know, and which I’ll be using throughout the series, which you can find in the table below.

Continue reading %Essentials of LDAP with PHP%

Link
Lorna MitchellJoind.in at PHPNW's Hackathon (25.9.2014, 08:32 UTC)

With a week to go, everyone attending PHPNW is starting to get excited. One of my highlights of the weekend is always the hackathon; as an open source project lead it's fantastic to meet new contributors and get a chance to hack in person with them and the more established people from the project.

This year will be no exception: PHPNW's Hackathon is on the Friday evening - you need a conference ticket, and you need to tick the "hackathon ticket" box. Joind.in will be there and we've got a very big todo list so if you are looking for something to hack on, then look no further!

  • The original joind.in site is maintenance mode only. We'll accept bug fixes for that but new features should be added to http://m.joind.in instead.
  • The new http://m.joind.in is our main focus, there's plenty to do so just show up and we'll find something that's a good fit for your skill set.
  • The android app is under active development - if you have these skills (or want to acquire them!) then Rich will be hacking away on that. I suspect that there are some new features that might be available first on android, which would be fabulous :)
  • The iphone app has been somewhat abandoned but we have everything we need to help you to pick it back up again. If you're an iphone app user and you'd like to keep up with the new features added in the other platforms, then you probably want to hack on this for your own interests.
  • The API powers the new website, the android app, and countless other integrations with conference sites etc. This holds the business logic and database, so we'll be hacking on this whatever happens!
  • Also on our wishlist: more javascript widgets for speakers and events to use on their own sites, tool for importing talks, integration with OpenCfP ... really anything else you can dream up :)

How To Get Involved

Come and say "hello, I'd like to get involved" :) If you're super keen, then feel free to grab the development platform beforehand (it saves a lot of time on the night), by following the installation instructions here: https://github.com/joindin/joindin-vm. This will set up a virtual machine with all the various bits of database, API and website all configured correctly so you can start developing.

Are you coming along to the hackathon? Do you already know what you want to hack on? Leave a comment and we'll see you there!

Lorna is an independent web development consultant, author and trainer, available for work (interesting projects only). This post was originally published at LornaJane

Link
Hasin HayderHow to enqueue javascript files properly in the WordPress admin panel (24.9.2014, 21:04 UTC)
Link
thePHP.ccBrno PHP Conference (24.9.2014, 07:00 UTC)
Link
Nomad PHPHTTP with GuzzlePHP (23.9.2014, 21:06 UTC)

Presented by Jeremy Lindblom @jeremeamia Guzzle is both an HTTP client and a framework for building web service clients. It gives you all the power of cURL, but is really easy to use. With a sleek, event-driven request system and the ability to make requests in parallel, Guzzle should be a permanent part of your …

The post HTTP with GuzzlePHP appeared first on Nomad PHP.

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