<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>MV Associati Tech Gems</title>
	<atom:link href="http://www.mvassociati.it/en/gems/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mvassociati.it/en/gems</link>
	<description>Technical Article from MV Associati experience</description>
	<lastBuildDate>Fri, 04 Aug 2017 10:31:17 +0000</lastBuildDate>
	<language>en-EN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>Securing intranet applications with SSL</title>
		<link>http://www.mvassociati.it/en/gems/devops/https-on-private-intranet-applications-ssl-certificate?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=securing-intranet-applications-with-https</link>
		<comments>http://www.mvassociati.it/en/gems/devops/https-on-private-intranet-applications-ssl-certificate#comments</comments>
		<pubDate>Mon, 08 May 2017 07:02:39 +0000</pubDate>
		<dc:creator>whites11</dc:creator>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[intranet]]></category>
		<category><![CDATA[letsencrypt]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[ssl]]></category>

		<guid isPermaLink="false">http://www.mvassociati.it/en/gems/?p=848</guid>
		<description><![CDATA[We all know how important is HTTPS for securing data flowing between users&#8217; web browsers and the webserver. With the release of Chrome 56, Google decided to start marking websites not served using the HTTPS protocol as Insecure (source), so it is becoming even more important, if not critical, to use HTTPS for all web [...]]]></description>
			<content:encoded><![CDATA[<p>We all know how important is <strong>HTTPS</strong> for securing data flowing between users&#8217; web browsers and the webserver.<br />
With the release of Chrome 56, <strong>Google</strong> decided to start marking websites not served using the HTTPS protocol as <strong>Insecure</strong> (<a title="source" href="https://www.wordfence.com/blog/2017/01/chrome-56-ssl-https-wordpress/" target="_blank">source</a>), so it is becoming even more important, if not critical, to use HTTPS for all web applications.</p>
<p>This is obviously relevant for web applications and websites in general, which are available to the public. In such situations, the typical solution is to purchase an <strong>SSL certificate</strong> from a certification authority (such as RapidSSL or GoDaddy) and enable it within the webserver. This article is not about this. <img src='http://www.mvassociati.it/en/gems/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>What we&#8217;re going to talk about today is the <strong>security of Intranet web applications</strong>, such as a websites which are not publicly available, but somehow available to specific people having access to private networks.<br />
<span id="more-848"></span></p>
<h4></h4>
<h4><strong>Why is it important to secure intranet applications too?</strong></h4>
<p>Somebody might think that, since an application is not publicly available, it is not important to secure it with SSL. This is not true, and here&#8217;s why.</p>
<p>Think about a document storage web application that is running in the local area network (LAN) of your company. That application of course may contain many documents of different nature, such as customers&#8217; and suppliers&#8217; invoices and employees contracts and payment receipts.<br />
While some of this documents might be visible to all the users of such web application, many others have to be visible to specific users only.<br />
Let&#8217;s say that you implement a very secure ACL to ensure this security layer on your application and avoid unauthorized access to your sensitive data.<br />
If you don&#8217;t serve your project using the HTTPS protocol, than all your documents are traveling in the cables of your LAN unencrypted, and anybody connected to the same network can easily scan your network and read those documents. Plus, a malicious user could use the same technique to sniff user passwords and easily access your secure web app with other peoples&#8217; credentials (don&#8217;t you believe that? Check this <a title="tutorial" href="http://lifehacker.com/5853483/a-guide-to-sniffing-out-passwords-and-cookies-and-how-to-protect-yourself-against-it" target="_blank">tutorial</a>).</p>
<p><img class="alignnone size-large wp-image-929" title="firewall" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2017/02/firewall-400x332.jpg" alt="" width="400" height="322" /></p>
<p>That said, I hope you are all convinced now that SSL is important for every web application, even if it&#8217;s not public.</p>
<p>&nbsp;</p>
<h4><strong>How to secure an intranet application</strong></h4>
<p>There are a few options to secure private web applications.</p>
<ol>
<li>The dumbest option is to generate a self signed certificate. That does not solve the security problem though (read <a title="this link" href="https://www.globalsign.com/en/ssl-information-center/dangers-self-signed-certificates/" target="_blank">this</a> to understand why).</li>
<li>Buy a standard certificate. This is perfectly acceptable but requires spending some amount of money every year.</li>
<li>Generate a certificate using <a href="https://letsencrypt.org/" target="_lets">Letsencrypt</a></li>
</ol>
<p><img class="alignnone size-medium wp-image-852" title="letsencrypt-logo-horizontal.svg" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2017/02/letsencrypt-logo-horizontal.svg_-400x95.png" alt="" width="240" height="57" /></p>
<p>If you haven&#8217;t heard about <strong>Letsencrypt</strong> before, go have a look at their <a href="https://letsencrypt.org/about/" target="_blank">website</a> to learn more. In one sentence, it is an organization that aims at making the web more secure and gives you free SSL certificates for personal or professional use.<br />
This is in my opinion the perfect solution for intranet applications (which tipically have budget constraints).</p>
<p>&nbsp;</p>
<h4><strong>Generating SSL certificates with letsencrypt</strong></h4>
<p>Letsencrypt uses the <a href="https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment" target="_blank"><strong>ACME</strong></a> protocol to release SSL certificates in an automated manner.</p>
<p>That means you need an ACME client to get an SSL certificate. The official client is called <a href="https://certbot.eff.org/" target="_blank">certbot</a>, it&#8217;s free and open source and it is easily installable in many UNIX-based operating systems. We&#8217;re not going to cover the installation of certbot, though, because it is out of scope. You can find easy tutorials for your operating system on the <a href="https://certbot.eff.org/" target="_blank">officiale page</a>.</p>
<p>There are a few different ways to get a new certificate using certbot (such as apache, nginx, webroot, and so on. Read them <a href="https://certbot.eff.org/docs/using.html#getting-certificates-and-choosing-plugins" target="_blank">here</a>) but all of them have a very important common step to be performed which is domain ownership verification. This step is required by the certification authority to ensure that you are the owner, or at least you are allowed to manage, the DNS records for the internet domain you are requiring the certificate for. Skipping this step would mean that anybody could request a certificate for <em>google.com</em> or <em>paypal.com</em> and that of course would be a giant security problem.</p>
<p>&nbsp;</p>
<h4><strong>How does Letsencrypt check domain ownership?</strong></h4>
<p>There are basically 2 ways:</p>
<ul>
<li>HTTP challenge: an HTTP request is sent to the domain name you requested the domain for. The server must respond to a specific endpoint with a specific content in order for the domain ownership to be verified.</li>
<li>DNS challenge: letsencrypt servers will search on the DNS records of the requested domain for a specific TXT record, with a specific value.</li>
</ul>
<p>HTTP challenge is the most common and the easiest, because certbot (and other ACME clients) can do that for you automatically. Unluckily, it requires that the domain name resolves to a public IP address which is freely reachable on the internet. But, remember, our domain is in the intranet and so this approach simply would not work in our scenario. That means we need to choose the DNS challenge option.</p>
<p>&nbsp;</p>
<h4><strong>Generate a certificate using the DNS challenge</strong></h4>
<p>To do that, we need to use the <em>manual</em> strategy of certbot, by running a command similar to the following:</p><pre class="crayon-plain-tag">certbot -d private.mydomain.com --manual --preferred-challenges dns certonly</pre><p>Of course adjust <em>private.mydomain.com</em> with your domain.<br />
This command starts an interactive wizard:</p><pre class="crayon-plain-tag">Saving debug log to /var/log/letsencrypt/letsencrypt.log
Obtaining a new certificate
Performing the following challenges: dns-01 challenge for private.mydomain.com
------------------------------------------------------------------
NOTE: The IP of this machine will be publicly logged as having requested this certificate. If you're running certbot in manual mode on a machine that is not your server, please ensure you're okay with that.
Are you OK with your IP being logged?
------------------------------------------------------------------
(Y)es/(N)o: Y

------------------------------------------------------------------
Please deploy a DNS TXT record under the name _acme-challenge.private.mydomain.com with the following value:

LngHg_3lhXDJ_m3ArGTgtalz50uVCjXW5-zFVCulK8I

Once this is deployed,
------------------------------------------------------------------
Press Enter to Continue</pre><p>At this point, as clearly requested by the script, you need to create a new TXT record in your DNS administration panel for <em>_acme-challenge.private.mydomain.com</em> with value <em>LngHg_3lhXDJ_m3ArGTgtalz50uVCjXW5-zFVCulK8I</em></p>
<p>Once done, check that the DNS record propagated successfully (you can use <a href="https://www.whatsmydns.net/" target="_blank">this website</a> to do that) than press enter to continue executing the script.</p>
<p>If all went well, you should see a success message:</p><pre class="crayon-plain-tag">IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/private.mydomain.com/fullchain.pem.
Your cert will expire on 2017-05-16. To obtain a new or tweaked version of this certificate in the future, simply run certbot again.
To non-interactively renew *all* of your certificates, run &quot;certbot renew&quot;
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le</pre><p>Good, our certificates are ready! You can find everything you need under the folder: /etc/letsencrypt/live/mydomain.com/ (of course adjust the path to meet your domain name). In that folder you&#8217;ll find 4 files:</p>
<ul>
<li>cert.pem: the actual certificate</li>
<li>chain.pem: the certificate of the certification authority</li>
<li>fullchain.pem: basically the merge of the above 2 files</li>
<li>privkey.pem: your private key (never share this file with anybody)</li>
</ul>
<p>Now you only have to tell your webserver to use the HTTPS protocol and where to get the certificate files. Check the official documentation for <a href="http://nginx.org/en/docs/http/configuring_https_servers.html" target="_blank">Nginx</a> and <a href="https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html" target="_blank">apache</a> to get started.</p>
<p><img class="aligncenter size-large wp-image-929" title="https" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2017/02/https-576x288.jpg" alt="" width="576" height="288" /></p>
<h4><strong>Recap</strong></h4>
<p>In this article we discussed about the risks of having a plain HTTP web application hosted inside our company’s private network and the need of an SSL certificate to make traffic flow securely inside our ethernet wires.</p>
<p>We then learned how to generate a free SSL certificate using Letsencrypt even if our webservers are not public.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvassociati.it/en/gems/devops/https-on-private-intranet-applications-ssl-certificate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Token based authentication in Zend Expressive</title>
		<link>http://www.mvassociati.it/en/gems/software-development/token-based-authentication-with-zend-expressive/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=token-based-authentication-with-zend-expressive</link>
		<comments>http://www.mvassociati.it/en/gems/software-development/token-based-authentication-with-zend-expressive/#comments</comments>
		<pubDate>Wed, 01 Mar 2017 15:36:42 +0000</pubDate>
		<dc:creator>drigani</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[auth]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[expressive]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[routes]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://www.mvassociati.it/en/gems/?p=694</guid>
		<description><![CDATA[Authentication is one of the most important parts of any web application. As RESTful API designers we often deal with the need of authenticating our users in order to handle and display sensible information. In this post, we&#8217;ll focus in a specific authentication strategy called token based authentication using Zend Expressive micro framework. First of [...]]]></description>
			<content:encoded><![CDATA[<p>Authentication is one of the most important parts of any web application. As RESTful API designers we often deal with the need of authenticating our users in order to handle and display sensible information. In this post, we&#8217;ll focus in a specific authentication strategy called token based authentication using Zend Expressive micro framework.<span id="more-694"></span></p>
<p>First of all, if you still don&#8217;t know anything about Zend Expressive check it out:<a href=" https://zendframework.familiar.io/zend-expressive/" target="_blank"> http://zendframework.github.io/zend-expressive/</a></p>
<p>Prerequisites:</p>
<ul>
<li>A decent grasp of PHP</li>
<li>REST fundamentals</li>
<li>Basic Zend Expressive knowledge</li>
</ul>
<p>“Token based authentication works by ensuring that each request to a server is accompanied by a signed token which the server verifies for authenticity and only then responds to the request.”</p>
<p>So, we assume that we have a login page that will send the user credentials to our API endpoint (that will be http://api.mvlabs.it/api/v1/user/login in our example) and, if the given credentials are correct, then the API will respond with a token to the Front-End and the Front-End application will use the token to access the restricted resources in the following requests.</p>
<p><img title="api_token_auth1" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2017/01/api_token_auth1-576x384.jpg" alt="" width="576" height="384" /></p>
<h2>OK, so &#8230;how can I do that with Zend Expressive?</h2>
<p>In <strong>Zend Expressive</strong> we could use a Middleware plugged into our pipeline to verify the token validity. So, for this scope we’ll use the <a href="https://familiar.com/tuupola/slim-jwt-auth" target="_blank"><strong>tuupola/slim-jwt-auth</strong></a> middleware. It was originally developed for Slim but can be used with any framework that complies with the PSR-7 standard and of course, Zend Expressive is one of them! Yep, code reuse is a great thing enabled by Middleware! Ok, let’s take a look. First of all, we need to add to our <strong>Zend Expressive skeleton</strong> application the jwt auth middleware:</p><pre class="crayon-plain-tag">$ composer require tuupola/slim-jwt-auth</pre><p>Now we need to add some configurations parameters that will be used by the <strong>JwtAuthentication Middleware</strong>. In fact, the only mandatory parameter is <strong>&#8220;secret&#8221;</strong> which is used to verify the token signature, only the issuer application has to know it and should never be disclosed in any way. So:</p>
<p>config/autoload/jwt-authentication.global.php</p><pre class="crayon-plain-tag">return [
   'jwt-authentication' =&amp;gt; [
       &quot;secret&quot; =&amp;gt; getenv(&quot;JWT_SECRET&quot;),
       &quot;path&quot; =&amp;gt; [&quot;/&quot;],
       &quot;passthrough&quot; =&amp;gt; [&quot;/api/v1/user/login&quot;, &quot;/api/v1/ping&quot;],
       &quot;error&quot; =&amp;gt; function ($request, $response, &amp;amp;$arguments) {
           $data[&quot;status&quot;] = &quot;error&quot;;
           $data[&quot;message&quot;] = $arguments[&quot;message&quot;];

           return $response
               -&amp;gt;withHeader(&quot;Content-Type&quot;, &quot;application/json&quot;)
               -&amp;gt;write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
       }
   ]
];</pre><p>Some notes about the configuration above:</p>
<ul>
<li>The optional <strong>path</strong> parameter allows us to specify the protected part of your website.</li>
<li>With optional <strong>passthrough</strong> parameter we can make exceptions to <strong>path</strong> parameter.</li>
<li><strong>error</strong> is called when authentication fails. It receives last error message as argument.</li>
</ul>
<p>Now we can create our <strong>JwtAuthentication Middleware</strong> through a factory with our configuration defined above.</p>
<p>src/App/Factory/JwtAuthenticationFactory.php</p><pre class="crayon-plain-tag">namespace App\Factory;

use Interop\Container\ContainerInterface;
use Slim\Middleware\JwtAuthentication;

class JwtAuthenticationFactory
{
   public function __invoke(ContainerInterface $container)
   {
       $config = $container-&amp;gt;get('config');
       return new JwtAuthentication($config['jwt-authentication']);
   }
}</pre><p>Now is time to add the <strong>Jwt Authentication Middleware</strong> to the <strong>ZE middleware pipeline</strong>, then it will have the responsibility to determine if a token is valid for the protected endpoints.</p>
<p>config/autoload/middleware-pipeline.global.php</p><pre class="crayon-plain-tag">return [
   'dependencies' =&amp;gt; [
       'factories' =&amp;gt; [
	...
           Slim\Middleware\JwtAuthentication::class =&amp;gt; App\Factory\JwtAuthenticationFactory::class,
	...
       ],
   ],
   'middleware_pipeline' =&amp;gt; [
       'always' =&amp;gt; [
           'middleware' =&amp;gt; [
	       ...
               Slim\Middleware\JwtAuthentication::class,
               ...
           ],
           'priority' =&amp;gt; 10000,
    ],
    'routing' =&amp;gt; [
       'middleware' =&amp;gt; [
            ...
       ],
       'priority' =&amp;gt; 1,
    ],
       ...
   ],
];</pre><p>At this point we need to define some routes in our configuration file, so let&#8217;s add the following:</p>
<ul>
<li>/api/v1/ping unprotected example endpoint</li>
<li>/api/v1/user/login (unprotected) used for authentication and token generation</li>
<li>/api/v1/user/:id the protected endpoint example that returns user specific data</li>
</ul>
<p>config/autoload/routes.global.php</p><pre class="crayon-plain-tag">return [
   'dependencies' =&amp;gt; [
       'factories' =&amp;gt; [
           App\Action\AuthAction::class =&amp;gt; App\Action\AuthFactory::class,
       ],
   ],

   'routes' =&amp;gt; [
       [
           'name' =&amp;gt; 'api.ping',
           'path' =&amp;gt; '/api/v1/ping',
           'middleware' =&amp;gt; App\Action\PingAction::class,
           'allowed_methods' =&amp;gt; ['GET'],
       ],
       [
           'name' =&amp;gt; 'api.auth',
           'path' =&amp;gt; '/api/v1/user/login',
           'middleware' =&amp;gt; App\Action\AuthAction::class,
           'allowed_methods' =&amp;gt; ['POST'],
       ],
       [
           'name' =&amp;gt; 'api.user.get',
           'path' =&amp;gt; '/api/v1/user/:id',
           'middleware' =&amp;gt; App\Action\UsersAction::class,
           'allowed_methods' =&amp;gt; ['GET'],
       ],
   ],
];</pre><p>Now, we need to add the logic that will handles the data sent by the login form, validate it against a database, and after determining that the credentials are valid, will generate the token. So, we&#8217;ll define the <strong>AuthAction Middleware</strong> that will have those responsibilities:</p><pre class="crayon-plain-tag">namespace App\Action;
namespace App\Action;

use App\Entity\User;
use App\Service\UserService;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Diactoros\Response\JsonResponse;

class AuthAction
{
    private $userService;

    public function __construct(UserService $userService)
    {
        $this-&amp;gt;userService = $userService;
    }

    public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
    {
        $post = $request-&amp;gt;getParsedBody();
        $username = $post['username'];
        $password = $post['password'];

        $user = $this-&amp;gt;userService-&amp;gt;getUserByEmailPassword($username, $password);
        if ($user instanceof User) {
            $jwt = $this-&amp;gt;userService-&amp;gt;getAuthTokenForUser($user);

            return new JsonResponse([
                'time' =&amp;gt; time(),
                'jwt' =&amp;gt; $jwt,
            ]);
        }

        return new JsonResponse(['status' =&amp;gt; 'error'], 401);
    }
}</pre><p>Let&#8217;s take a detailed look to the token generation in the UserService:</p><pre class="crayon-plain-tag">namespace App\Service;

use App\Entity\User;
use Firebase\JWT\JWT;

class UserService
{

    ...

    public function geAuthTokenForUser(User $user)
    {
        $now = new \DateTime();
        $future = new \DateTime(&quot;now +2 hours&quot;);

        $random_number = openssl_random_pseudo_bytes(32); //generate using openssl_random_pseudo_bytes
        $jti = hash('sha256', $user-&amp;gt;getId() . $random_number);
        $serverName =  $this-&amp;gt;config['api']['endpoint'];
        /*
         * Create the token as an array
         */
        $data = [
            &quot;iat&quot; =&amp;gt; $now-&amp;gt;getTimeStamp(),  // Issued at: time when the token was generated
            'jti' =&amp;gt; $jti, // Json Token Id: an unique identifier for the token
            'iss' =&amp;gt; $serverName, // Issuer
            'nbf' =&amp;gt; $now-&amp;gt;getTimeStamp()+10, // Not before
            &quot;exp&quot; =&amp;gt; $future-&amp;gt;getTimeStamp(), // Expire
            'data' =&amp;gt; [ // Data related to the signer user
                'userId' =&amp;gt; $user-&amp;gt;getId(), // userid from the users table
                'username' =&amp;gt; $user-&amp;gt;getUsername(), // User name
            ]
        ];

        /*
         * Encode the array to a JWT string. Second parameter is the key to encode the token.             *
         * The output token $jwt can be validated at http://jwt.io/
         */
        $jwt = JWT::encode(
            $data,
            $this-&amp;gt;config['jwt-authentication']['secret'],
            &quot;HS512&quot;
        );

        return $jwt;
    }
}</pre><p>In order to check that everything is OK, let&#8217;s do a test call to our authentication endpoint with postman, passing our authentication credentials.</p>
<p><img class="alignnone size-large wp-image-697" title="auth_token" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2017/01/auth_token-576x236.png" alt="" width="576" height="236" /></p>
<p>Good, everything looks fine, so, at this point the client will have the token, and can store it using a storage mechanism like HTML5 Web Storage.</p>
<p>Now let’s retrieve a resource that is protected by our JWT mechanism. But first we need to set the Authorization header with the contents of the JWT in the format of Bearer [JWT]</p>
<p><img class="alignnone size-large wp-image-698" title="apicall_using_token" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2017/01/apicall_using_token-576x268.png" alt="" width="576" height="268" /></p>
<p>As we can see in the image above, we can access to the restricted resource once that we passed our authentication token.</p>
<h2>Summary</h2>
<p>This is a very reliable method to secure your information. From here on, you can try to implement a token based authentication using ZE in your next API. Feel free to share your constructive feedback or ask a question. Drop a note below, we&#8217;ll be happy to receive your comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvassociati.it/en/gems/software-development/token-based-authentication-with-zend-expressive/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP-Middleworld is Out!</title>
		<link>http://www.mvassociati.it/en/gems/php/middleware-php-middleworld-is-out?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=php-middleworld</link>
		<comments>http://www.mvassociati.it/en/gems/php/middleware-php-middleworld-is-out#comments</comments>
		<pubDate>Tue, 14 Feb 2017 09:39:02 +0000</pubDate>
		<dc:creator>marcoshuttle</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[middleware]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[psr-7]]></category>

		<guid isPermaLink="false">http://www.mvassociati.it/en/gems/?p=794</guid>
		<description><![CDATA[We just released php-middleworld.com, a repository for PSR-7 compliant middleware in PHP, and we would like to share our progress and what the future may bring. PSR-7 It all started with PSR-7, a set of common interfaces for representing HTTP messages in PHP, allowing application abstraction from the HTTP layer. The most important aspect of PSR-7 is that it [...]]]></description>
			<content:encoded><![CDATA[<p dir="ltr">We just released <a href="http://www.php-middleworld.com/">php-middleworld.com</a>, a repository for <a href="http://www.php-fig.org/psr/psr-7/">PSR-7</a> compliant middleware in PHP, and we would like to share our progress and what the future may bring.<span id="more-794"></span></p>
<h2>PSR-7</h2>
<p dir="ltr">It all started with <a href="http://www.php-fig.org/psr/psr-7/">PSR-7</a>, a set of common interfaces for representing HTTP messages in PHP, allowing application abstraction from the HTTP layer.</p>
<p dir="ltr">The most important aspect of PSR-7 is that it is framework independent and hence its interfaces can easily be used with multiple frameworks such as <a href="https://symfony.com">Symfony</a>, <a href="https://framework.zend.com">Zend Framework</a>, <a href="https://laravel.com">Laravel</a> or any other framework.</p>
<p dir="ltr">This capability allows developers to write framework agnostic code with a wider opportunity to be reused in other projects, relying on the PSR-7 interfaces only.</p>
<h2>PHP AND MIDDLEWARE</h2>
<p dir="ltr">The other important key-word is middleware: once the PHP ecosystem gained a nice abstraction over HTTP messages, it was time to think about the best way to write web applications on top of this abstraction.</p>
<p dir="ltr">Citing <a href="https://mwop.net/blog/2015-01-08-on-http-middleware-and-psr-7.html">Matthew Weier O&#8217;Phinney</a>, the concept of middleware can be summarized in a single method signature:</p>
<p></p><pre class="crayon-plain-tag">function (request, response) : response</pre><p></p>
<p dir="ltr">The idea is that objects representing the HTTP request and the HTTP response are passed to a callable, which does something with them to return an HTTP response.</p>
<p dir="ltr">This turns out to be a very easy and composable pattern, which had actually already been used with great success in several other programming languages.</p>
<p dir="ltr">The standard way to compose such middleware is to pass a third argument to the callable, so to allow for another layer of middleware to be invoked:</p>
<p></p><pre class="crayon-plain-tag">function (request, response, next) : response
{
    // do something on request

    response = next(request, response)

    // do something on response

    return response
}</pre><p></p>
<p dir="ltr">Several frameworks, as <a href="https://zendframework.github.io/zend-expressive/">Zend Expressive</a>, <a href="https://www.slimframework.com/">Slim</a>, <a href="https://github.com/radarphp/Radar.Project">Radar</a> or <a href="http://spiral-framework.com/">Spiral</a> rely nowadays upon the concept of middleware to create web applications.</p>
<h2>MIDDLEWARE REUSE</h2>
<p dir="ltr">Now that we have a highly composable pattern based upon a framework agnostic HTTP abstraction, we can actually start writing highly reusable components that would work on any PHP project. This definitely helps developers easing their daily job.</p>
<p dir="ltr">We can have middleware taking  care of logging all received requests, middleware to perform routing, middleware to manage authentication and some other to take care of user sessions. We use our framework to simply glue all this pieces together in the appropriate way.</p>
<p dir="ltr">The key question at this point should be: has anybody else already implemented the piece of middleware I need for the application I’m developing?</p>
<h2>PHP-MIDDLEWORLD IS HERE!</h2>
<p dir="ltr">Until now the answer to the previous question could only be gathered through <a href="https://packagist.org/">Packagist</a>, <a href="https://github.com/">Github</a>, or &#8211; in the worst case &#8211; google.</p>
<p dir="ltr"><a href="http://www.mvassociati.it/it/blog/?attachment_id=1404" rel="attachment wp-att-1404"><img class="aligncenter" title="Screenshot from 2017-02-07 08-43-55" src="http://www.mvassociati.it/it/blog/wp-content/uploads/2017/02/Screenshot-from-2017-02-07-08-43-55-400x126.png" alt="middleware repository request" width="400" height="126" /></a></p>
<p dir="ltr">Having received so much from the community over the years, we thought it was about time to give something back. That’s how <a href="http://www.php-middleworld.com/">php-middleworld.com</a> was born. With the aim to provide fellow PHP developers a means to quickly locate the middleware they need (often with multiple implementation choices).</p>
<h2>THE FUTURE</h2>
<p dir="ltr">We already have in mind several improvements for <a href="http://www.php-middleworld.com/">php-middleworld.com</a>.</p>
<p dir="ltr">First of all we would like to enable fellow developers to add their own middleware, so that our database could grow with a shared effort.</p>
<p dir="ltr">Then we would also like to add <a href="https://github.com/php-fig/fig-standards/tree/master/proposed/http-middleware">PSR-15</a> compatible middleware support also, so to be ready when that proposal will be approved.</p>
<p dir="ltr">No need to get any deeper here, to find out more just head to <a href="http://www.php-middleworld.com/">php-middleworld.com</a> and follow <a title="@phpmwd" href="https://twitter.com/phpmwd">@phpmwd</a> on Twitter!</p>
<p dir="ltr">Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvassociati.it/en/gems/php/middleware-php-middleworld-is-out/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Docker, PHP and E-Mail: getting things to work</title>
		<link>http://www.mvassociati.it/en/gems/devops/docker-email-php?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=docker-php-and-e-mail-getting-things-to-work</link>
		<comments>http://www.mvassociati.it/en/gems/devops/docker-email-php#comments</comments>
		<pubDate>Fri, 10 Feb 2017 16:21:16 +0000</pubDate>
		<dc:creator>whites11</dc:creator>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[mailhog]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sendmail]]></category>
		<category><![CDATA[ssmtp]]></category>

		<guid isPermaLink="false">http://www.mvassociati.it/en/gems/?p=668</guid>
		<description><![CDATA[It&#8217;s a common need for software nowadays to send notifications through e-mail: registration confirmations, password recovery requests, event notifications and so on. As my colleagues develop software, they often encounter problems while dealing with such e-mail exchange in their local (Docker) environment. The problem Let&#8217;s say you are also developing a PHP application and you [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s a common need for software nowadays to send notifications through <strong>e-mail</strong>: registration confirmations, password recovery requests, event notifications and so on. As my colleagues develop software, they often encounter problems while dealing with such e-mail exchange in their local (Docker) environment.<span id="more-668"></span></p>
<h2>The problem</h2>
<p>Let&#8217;s say you are also developing a <strong>PHP</strong> application and you want to use <strong>docker</strong> in your development machine. You will notice that &#8211; if you use the official PHP images from the docker hub &#8211; sending e-mail out of the box simply won&#8217;t work. Lets&#8217; see what I mean in practice, considering this simple index.php file, sending out an e-mail:</p><pre class="crayon-plain-tag">$result = mail(&quot;info@example.com&quot;, &quot;Subject&quot;, &quot;The very important email body&quot;);

if ($result) {
    echo &quot;Email sent correctly&quot;;
} else {
    echo &quot;Error sending the email&quot;;
}</pre><p><em>Please note: using the mail command to send an email is the simplest way, but there are many more powerful libraries out there that could make things easier. We have chosen to use the mail command just to keep the example as simple as possible.</em></p>
<p>If we run it using docker with the following command:</p><pre class="crayon-plain-tag">docker run -p &quot;80:80&quot; -v `pwd`:/var/www/html --rm php:7-apache</pre><p>and visit http://localhost with our browser, we&#8217;ll see that the mail command will fail, and we&#8217;ll get an &#8220;Error sending the email&#8221; message.</p>
<p>The reason why this happens is that the &#8220;mail&#8221; command relies on the &#8220;sendmail&#8221; system command inside the container, which is missing from the official PHP docker image.</p>
<p><a href="http://www.mvassociati.it/en/gems/wp-content/uploads/2017/02/docker-email.png" rel="lightbox[668]" title="docker-email"><img class="aligncenter" title="docker-email" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2017/02/docker-email.png" alt="" width="300" height="192" /></a></p>
<p>While you could simply create a new image extending the original one and adding the sendmail command, I suggest using a different strategy.</p>
<p>Here at MV Labs we do use a tool called <strong>Mailhog</strong> (<a title="MailHog" href="https://github.com/mailhog/MailHog" target="_blank">https://github.com/mailhog/MailHog</a>) which acts as an SMTP server listening on port 1025 but instead of sending real emails to your recipients, it simply displays them in a handy web interface (which is listening, by default, on port 8025). This way you avoid the risk of sending your testing e-mails to the customer (it happened at least once to everybody) and you don&#8217;t have to deal with spam filters or other annoyances in the e-mail chain.</p>
<p>So, how can we achieve this? To make things easier, we can take advantage of docker-compose. Let&#8217;s start by adding the mailhog container to our services:</p><pre class="crayon-plain-tag">version: '2'
services:
  php:
    image: php:7-apache
    volumes:
      - .:/var/www/html/
    ports:
      - 80:80
    networks:
      - base
  mailhog:
    image: mailhog/mailhog
    ports:
      - 8025:8025
    networks:
      - base
networks:
  base:</pre><p>Now, if we run <code>docker-compose up</code> and head our browsers to http://localhost:8025 we should see the mailhog simple but powerful web interface.</p>
<p>We&#8217;re not done yet, though, as we still need to tell the mail command to send emails through our new mailhog smtp server. Unluckily this requires the building of a custom docker image, since PHP doesn&#8217;t allow using the native mail command to connect to a SMTP server. For this reason, we need a tool called <strong>ssmtp</strong> (<a title="ssmtp" href="https://linux.die.net/man/8/ssmtp" target="_blank">https://linux.die.net/man/8/ssmtp</a>) which is basically a configurable sendmail command replacement, and which forwards the message to a SMTP server configured in its config file. We&#8217;ll need the following Dockerfile:</p><pre class="crayon-plain-tag">FROM php:7-apache

# install ssmtp
RUN apt-get update; apt-get install ssmtp -y

# tell php to use ssmtp's sendmail for email sending
RUN echo &quot;sendmail_path=/usr/sbin/sendmail -t -i&quot; &amp;gt;/usr/local/etc/php/conf.d/sendmail.ini

# tell ssmtp to use mailhog as the mail transport
RUN echo &quot;Mailhub=mailhog:1025&quot; &amp;gt; /etc/ssmtp/ssmtp.conf
RUN echo &quot;FromLineOverride=Yes&quot; &amp;gt;&amp;gt; /etc/ssmtp/ssmtp.conf</pre><p>Then we&#8217;ll need to tell docker-compose.yml to build the image from the Dockerfile for our PHP container:</p><pre class="crayon-plain-tag">version: '2'
services:
  php:
    build: .
    volumes:
      - .:/var/www/html/
    ports:
      - 80:80
    networks:
      - base
  mailhog:
    image: mailhog/mailhog
    ports:
      - 8025:8025
    networks:
      - base
networks:
  base:</pre><p>and build our containers again with:</p><pre class="crayon-plain-tag">docker-compose up -d --build</pre><p>Now we&#8217;re ready to send our first &#8220;virtual&#8221; email. Just head your browser to http://localhost and you&#8217;ll get the message &#8220;Email sent correctly&#8221;. If you check your mailhog at http://localhost:8025 you&#8217;ll see your email!</p>
<h2>Summary</h2>
<p>Using a simple example, we have demonstrated one possible solution for sending test e-mails out of our web applications under development in a secure and handy way, by using some nice open source tools such as SSmtp and Mailhog inside a docker dev environment.</p>
<p>Let us know what you think in the comments area below and happy developing!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvassociati.it/en/gems/devops/docker-email-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend Framework 2 Routing Basics</title>
		<link>http://www.mvassociati.it/en/gems/php/zf2-routing-basics?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=zend-framework-2-routing-basics</link>
		<comments>http://www.mvassociati.it/en/gems/php/zf2-routing-basics#comments</comments>
		<pubDate>Tue, 04 Jun 2013 13:47:45 +0000</pubDate>
		<dc:creator>drigani</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[routes]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[zend framework 2]]></category>
		<category><![CDATA[zf2]]></category>

		<guid isPermaLink="false">http://www.mvassociati.it/en/gems/?p=607</guid>
		<description><![CDATA[Earlier this year, I&#8217;ve had the opportunity to speak at the Italian Zfday in Milan, as well as at the Unconf of the PHPDay, the Italian conference on PHP, which is held every year in Verona. In both occasions, I introduced Zend Framework 2 Routing in a talk titled: “Full sail: easy routing with the [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this year, I&#8217;ve had the opportunity to speak at the Italian <a title="Zend Framework Day" href="http://www.zfday.it/">Zfday</a> in Milan, as well as at the Unconf of the <a title="PHPDay" href="http://2013.phpday.it/">PHPDay</a>, the Italian conference on PHP, which is held every year in Verona. In both occasions, I introduced Zend Framework 2 Routing in a talk titled: “Full sail: easy routing with the ZF2” (original title: &#8220;<a title="Zend Framework Routing Slides on Slideshare" href="http://www.slideshare.net/drigani/levate-lancora-rotte-senza-problemi-con-zf2">Levate l&#8217;ancora: Rotte senza problemi con ZF2</a>&#8220;). These conferences turned out to be interesting experiences, allowing me to get in touch with the Italian Zend Framework Community. From the positive feedback I have received, I&#8217;ve decided to write some blog posts about the topics that were introduced in my talks. So, here it comes this post, the first of a series about zf2 routing.<span id="more-607"></span></p>
<h2>For starters, what is routing?</h2>
<p>The fundamental principle of routing is to <strong>match incoming requests </strong>reaching an application and <strong>decide</strong> which fragment of<strong> code to execute</strong>. That could mean matching either an http request or a console requests (if you are interacting with a Command Line Interface application), and extracting the parameters that determine which snippet of code (IE which controller and then which action) to execute. The other basic principle is to <strong>assemble</strong> URLs and commands back. That is, from a set of parameters, to build the path of the route. In terms of an example, this means coming up with the /products/view/some_product URL starting from the controller = products, action = view, slug = some_product parameters*.</p>
<p>*I am aware this might not be the best possible example URL, but I hope it gets the message across in simple terms.</p>
<h2>Why should we care about routing?</h2>
<p>There are different reasons why routing is important. The simplest and most important one is that without routing your application won&#8217;t work <img src='http://www.mvassociati.it/en/gems/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Even in a working application, though, properly handling routing is important. That&#8217;s for different reasons, which can be summarized as follows:</p>
<p>- good URLs are easier to remember, type and share through word of mouth<br />
- they also make it easier for search engines to properly index websites and web applications<br />
- they allow for clean RESTful interfaces to be build<br />
- they improve web application security, because they make it easier for parameters to be properly handled</p>
<h2></h2>
<p><a href="http://www.mvassociati.it/en/gems/php/zf2-routing-basics/attachment/pirate-smoking-a-cigar" rel="attachment wp-att-611"><img class="aligncenter size-full wp-image-611" title="Pirate smoking a cigar." src="http://www.mvassociati.it/en/gems/wp-content/uploads/2013/05/zf2_routes.jpg" alt="" width="512" height="341" /></a></p>
<p>&nbsp;</p>
<h2>Routing within the Zend Framework 2</h2>
<h3>Under the Hood</h3>
<p>The basic unit of routing is a so called route, which is nothing but a PHP class implementing the following interface:</p><pre class="crayon-plain-tag">namespace Zend\Mvc\Router;

use zend\Stdlib\RequestInterface as Request;

interface RouteInterface
{
  public static function factory(array $options = array());
  public function match(Request $request);
  public function assemble(array $params = array(), array $options = array());
}</pre><p>The RouteInterface includes the  static method <strong>factory</strong>, which is used to create new routes. Every route is constructed with arguments (usually fetched from specific project/module configuration file). The <strong>match</strong> method, in turn, accepts a new Request, and determines if the request matches current route. If true, it then returns a RouteMatch object, which is a container object, that includes the route name and most likely all route parameters and values. Last, we also have the <strong>assemble</strong> method, which takes options and parameters and builds the path of a route (usually an URL).</p>
<p>We will rarely need to worry about implementation details of these methods, though, because the framework will take care of passing the configuration and creating our routes according to our definitions in each module configuration directives (as we&#8217;ll shortly see).</p>
<h3>Defining new routes</h3>
<p>Routes for each module shall be defined within the module configuration file, which can be found in every module&#8217;s root folder. The default Zend Framework Skeleton app also has its own Module.php file in <strong><em>/config/modules.config.php:</em></strong></p>
<p><a href="http://www.mvassociati.it/en/gems/php/zf2-routing-basics/attachment/modulepic-2" rel="attachment wp-att-608"><img class="size-full wp-image-608 alignnone" title="Module Filesystem Layout" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2013/05/modulepic1.jpg" alt="ZF2 Module Filesystem Layout" width="291" height="164" /></a></p>
<p>&nbsp;</p>
<p>The section dealing with routing is the one which goes under the <strong>router</strong> key; <strong>routes</strong> contains a list of our routes in array form:</p><pre class="crayon-plain-tag">return array(
  'router' =&gt; array(
    'routes' =&gt; array(
      'contact' =&gt; array(
        'type' =&gt; 'Literal',
        'options' =&gt; array(
          'route' &nbsp;&nbsp;&nbsp;=&gt; '/contact',
          'defaults' =&gt; array(
            'controller' =&gt; 'Application\Controller\Contact',
            'action' &nbsp;&nbsp;&nbsp;&nbsp;=&gt; 'index',
          ),
        ),
      ),
    ),
  ),
),</pre><p>In the basic example above, we defined a route named “contact”, of type Literal (all different Route types will be covered in a forthcoming post). Basically we just told the framework to dispatch users requesting the ‘/contact’ URL to the Contact controller, and to have the IndexAction method to be executed.</p>
<h3>What about route stacks</h3>
<p>The ZF2 router is a collection of routes, based on a priority stack. As it was happening in Zend Framework 1, routes can be added to a route list; the last added route is the one tested first. The same now happens in ZF2; we can now also take advantage of the new <strong>priority</strong> attribute, though. This means that every route will have a priority value, and highest priorty route will be tested first. I&#8217;m sure this will make it easier to keep things organized without needing to worry much about route position within configuration files. This will also make it easier for custom configurations to be used to override third party default configurations.</p>
<p>Every router (there are different types, which we&#8217;ll take a look at shortly) implements this interface:</p><pre class="crayon-plain-tag">namespace Zend\Mvc\Router;

interface RouteStackInterface extends RouteInterface
{
  public function addRoute($name, $route, $priority = null);
  public function addRoutes(array $routes);
  public function removeRoute($name);
  public function setRoutes(array $routes);
}</pre><p>All methods are self-explanatory, so I won&#8217;t go in further detail here. This is with the exception of the <strong>setRoutes</strong> method, which probably deserves some explanation. This method in fact replaces current routes in the stack with the new ones provided as an argument. So, it first removes current routes, then adding the new ones.</p>
<h3>Router types</h3>
<p>There are different implementations of the aforementioned Router base class:</p>
<ul>
<li><strong>SimpleRouteStack:</strong> the most basic implementation, which we can use and extend to make our own router stack class.</li>
<li><strong>Http\TreeRouteStack</strong>: the most common kind of router, it is used to create a tree of routes to deal with http requests, using a B-tree algorithm to match routes (this ensures that evaluation is efficiently made, as we&#8217;ll shortly see).</li>
<li><strong>Console\SimpleRouteStack</strong>: used in the realm of CLI applications and use to take care of command line arguments. This kind of router will be processed when our application is run from a console terminal window.</li>
</ul>
<h3></h3>
<h3>Tree Routing</h3>
<p>Zend Framework 2 introduces the Tree Routing concept as a big innovation. In fact, it&#8217;s very easy to use and its <strong>performance</strong> is great also: it&#8217;s much faster than its ZF1 counterpart. This is for multiple reasons: first off is the fact that the framework doesn&#8217;t try to match incoming requests with every single route anymore. This happens because every route can now have an unlimited number of <strong>children routes</strong>, which aren&#8217;t evaluated if parent route didn&#8217;t match the request first. Children routes are in fact only instantiated when the router matches or assembles their respective parent routes.</p>
<p>A Tree Route will consist of the following configuration:</p>
<ul>
<li>A <strong>base route</strong>, known as root route, which describes the base path (first part of an URL, for example);</li>
<li>The <strong>may_terminate</strong> key, which is set to false by default, telling the router whether the route may terminate or not.</li>
<li>The <strong>child_routes</strong> key, an array containing additional routes that stem from the base “route”. Each child route can itself be a Tree Route</li>
</ul>
<p>Example:</p><pre class="crayon-plain-tag">return array(
  'router' =&gt; array(
    'routes' =&gt; array(
      'zf' =&gt; array(
      'type' =&gt; 'Literal',
      'options' =&gt; array(
        'route' =&gt; '/zf',
        'defaults' =&gt; array(
        '__NAMESPACE__' =&gt; 'Application\Controller',
        'controller' &nbsp;&nbsp;&nbsp;=&gt; 'Article',
        'action' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=&gt; 'index',
      ),
    ),
    'may_terminate' =&gt; true,
    'child_routes' =&gt; array(
    'default' =&gt; array(
      'type' &nbsp;&nbsp;&nbsp;=&gt; 'Segment',
      'options' =&gt; array(
        'route' &nbsp;&nbsp;&nbsp;=&gt; '/:action',
        'constraints' =&gt; array(
          'action' &nbsp;&nbsp;&nbsp;&nbsp;=&gt; '[a-zA-Z][a-zA-Z0-9_-]*',
        ),
      ),
    ),
  ),</pre><p></p>
<h2>Summary</h2>
<p>In this first post about the Zend Framework 2 routing, I&#8217;ve introduced what&#8217;s a route, what&#8217;s routing, how the routing system works in the Zend Framework 2, and how it differs (especially from a performance point of view) from the ZF1 implementation. In my next post, I will be covering different HTTP route types we have at hand. Is there anything else you&#8217;d like to know? Just let me know with a comment below.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvassociati.it/en/gems/php/zf2-routing-basics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Asset management in Zend Framework 2</title>
		<link>http://www.mvassociati.it/en/gems/php/asset-management-zend-framework-2?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=asset-management-in-zend-framework-2</link>
		<comments>http://www.mvassociati.it/en/gems/php/asset-management-zend-framework-2#comments</comments>
		<pubDate>Fri, 08 Mar 2013 10:47:42 +0000</pubDate>
		<dc:creator>stefanovalle</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[assetmanager]]></category>
		<category><![CDATA[assets]]></category>
		<category><![CDATA[modules]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend framework 2]]></category>
		<category><![CDATA[zf2]]></category>

		<guid isPermaLink="false">http://www.mvassociati.it/en/gems/?p=554</guid>
		<description><![CDATA[During the last February I’ve had the chance to be a speaker at Zend Framework Day in Italy where I made a talk about zf2 modules. I think the topics covered deserve more time and space, so this blog post is the first of a series about how to take advantage of new ZF2 modular [...]]]></description>
			<content:encoded><![CDATA[<p>During the last February I’ve had the chance to be a speaker at Zend Framework Day in Italy where I made a talk about zf2 modules. I think the topics covered deserve more time and space, so this blog post is the first of a series about how to take advantage of new ZF2 modular structure.<br />
One of the first issues a developer runs into when dealing with ZF2 modules is how to <strong>arrange assets between modules</strong>. A Web asset is simply any css file, js library, image (and generally all static files) a module needs to work properly.<br />
<span id="more-554"></span></p>
<p><img class="size-full wp-image-561 aligncenter" style="font-size: 13px; font-weight: normal;" title="ZF2 modules" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2013/03/8322509672_27a30ccff1.jpg" alt="ZF2 modules" width="500" height="375" /></p>
<h3>The problem: where assets should be placed?</h3>
<p>The first problem to solve is: where my module’s assets should be placed to let me (the developer) forget about them? Because I should not care about assets provisioning, I would spend my time working on module itself! To simplify the problem, let me break it into two (not so) different use cases.</p>
<h4>Shared assets</h4>
<p>A module probably has many shared assets with other modules: javascript libraries, images, css files, etc. A common practice is to place all of them inside the project /public folder. Despite this is the simplest solution, it’s not the best. Copy/paste manually is never a good practice, besides copying all files inside the same folder will contribute to lose the explicit dependencies the module has with its assets.</p>
<h4>Single module’s assets</h4>
<p>In many cases a module has also some assets being used only by itself. We know that a module should focus on a single project functionality, so it should contain all the things that functionality needs to work well. The simplest answer now is probably the best: we should place all assets inside the module.</p>
<h3>Some naive solutions</h3>
<p><strong>How should we make the web server aware that out modules have some assets that need to be visible inside our view scripts?</strong></p>
<p>We could copy all assets (also those needed by a single module) inside public folder, every time one of them is added or updated. This is a bad practice, trust me!</p>
<p>We could use symlinks to let files be viewed inside another folder. Or we could do some apache htaccess tuning to let web server search files through all module folders. Luckily, there is a better way to handle things…</p>
<h3>Welcome AssetManager module</h3>
<p>AssetManager is a ZF2 module (<a href="https://github.com/RWOverdijk/AssetManager">https://github.com/RWOverdijk/AssetManager</a>) aimed at managing assets, that resolve exactly our problem. It’s based on the Assetic asset management framework for PHP (<a href="https://github.com/kriswallsmith/assetic">https://github.com/kriswallsmith/assetic</a>).</p>
<p>I don’t cover module provisioning and installation phases here because online there are straightforward and well organized articles about this (take a look on module’s wiki: <a href="https://github.com/RWOverdijk/AssetManager/wiki">https://github.com/RWOverdijk/AssetManager/wiki</a>).</p>
<p>Instead, here I would like to explain how this module can be a real time (and headache) saver for all ZF2 developers.</p>
<p>After completing the install process, the module can take care of your assets through two simple steps:</p>
<ol>
<li><strong>Create a folder where assets should be placed.</strong> I typically suggest to use the /assets folder inside your module. Obviously you’re free to use whatever name you prefer. Sometimes you find assets inside a folder named /public, but this could be confused with the folder where the web server points to. So I suggest to choose a different name to make things clear. Use the folder you prefer, but keep in mind the rule of thumb: use always the same location inside all your modules, to make them more clear and readable.</li>
<li><strong>Add</strong> the following <strong>rule to your module’s configuration file</strong> (/config/module.config.php – “assets” refers to the folder where your assets are placed):</li>
</ol>
<p></p><pre class="crayon-plain-tag">'asset_manager' =&gt; array(
    'resolver_configs' =&gt; array(
&nbsp;&nbsp;&nbsp;&nbsp;    'paths' =&gt; array(
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;    __DIR__ . '/../assets',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;),
&nbsp;&nbsp;&nbsp; ),
),</pre><p>With this two simple steps we are telling the AssetManager where the assets of our module are placed.</p>
<p><strong>That’s it!</strong> Now when an asset is not found inside project /public folder, the AssetManager module’ll look inside our module /assets folder to find the requested file. From now you could link assets inside your views simply as follows:</p><pre class="crayon-plain-tag">&lt;?php &nbsp;echo $this-&gt;headLink()-&gt;prependStylesheet($this-&gt;basePath() .&nbsp;
                                                '/css/aCssFile.css');&nbsp;?&gt;</pre><p>&nbsp;</p>
<p>In this way, <strong>we don’t need to worry about where our css is physically located</strong>, just link it as if it was placed inside /public folder. So simple and so amazing! In this way you can <strong>place all module assets (both shared and exclusive) inside the module. So that module is now really reusable</strong> inside other projects, without hidden dependencies.</p>
<p>Pay only attention to avoid colliding file rules. It’s not uncommon to have modules containing files with the same name. In this case prefixing the asset path with the module’s name (or slug) could solve the issue (this can be done through the ‘map’ key inside configuration file; take a look on the code in the following paragraphs for an example).</p>
<p>This is the simplest use of AssetManager we could make, but<strong> this module has many more features that are worth an extra look</strong>. Let me define some terms the module uses (each of this maps to a key of module’s config file):</p>
<ul>
<li><strong>Resolvers</strong> (resolver_configs key) allow to define where assets should be searched and how they are named / arranged. Many resolver types are available: MapResolver, CollectionResolver, PrioritizedPathsResolver and PathStackResolver (detailed infos and examples available here: <a href="https://github.com/RWOverdijk/AssetManager/wiki/Resolvers">https://github.com/RWOverdijk/AssetManager/wiki/Resolvers</a>)</li>
<li><strong>Filters</strong> (filters key) allow make some processing on assets before serving them (eg. Minify minification, compiling of css files)</li>
<li><strong>Cache</strong> (caching key), as the name suggest, allows to choose which caching policy use to speed up assets serving time</li>
</ul>
<h3>An example</h3>
<p>It’s a common practice to merge css files in order to limit the number of http requests (improving page serving speed). The AssetModule could help us to merge files automatically. Supposing our module has two css files (main.css and custom1.css), we could merge them together simply updating module’s config file as follows:</p><pre class="crayon-plain-tag">'asset_manager' =&gt; array(
    'resolver_configs' =&gt; array(
        'map' =&gt; array(
            'css/main.css' =&gt; __DIR__ . '/../assets/css/main.css',
            'css/custom1.css' =&gt; __DIR__ . '/../assets/css/custom1.css',
        ),
        'collections' =&gt; array(
            'css/merge.css' =&gt; array(
                'css/main.css',
                'css/custom1.css',
            ),
        ),
    ),
),</pre><p>&nbsp;</p>
<p>And the resulting view script is:</p><pre class="crayon-plain-tag">&lt;?php echo $this-&gt;headLink()-&gt;prependStylesheet($this-&gt;basePath() . 
                                                '/css/merge.css'); ?&gt;</pre><p>More code samples can be found on official module wiki (<a href="https://github.com/RWOverdijk/AssetManager/wiki">https://github.com/RWOverdijk/AssetManager/wiki</a>), that’s really well written and full of useful examples.</p>
<h3>Conclusion</h3>
<p>There are other ZF2 modules that provide asset management features. I personally like AssetManager because it’s really effective and simple to use. However is not important which module you decide to use, the important thing is that you should stop right now to manage assets manually. It’s a real boring and time wasting task, especially in the long run.</p>
<p>So now you’ve no excuses, <strong>this module requires no more than a few minutes to be installed and configured</strong>. Go and give it a try! And… after having configured your assets, don’t forget to <strong>enable AssetModule’s cache</strong>. That’s really a must to offer decent website performance and hence a good user experience.</p>
<p>For those who prefer a <strong>talk-like explanation</strong>, the extract of my Zend Framework Day presentation about this topic can be found <a href="http://www.slideshare.net/stefanovalle/zf2-asset-management">here</a>.</p>
<p>Image credit: http://www.flickr.com/photos/tracyleephoto/8322509672</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvassociati.it/en/gems/php/asset-management-zend-framework-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP error: file size limit exceeded</title>
		<link>http://www.mvassociati.it/en/gems/devops/php-error-file-size-limit-exceeded/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=php-error-file-size-limit-exceeded</link>
		<comments>http://www.mvassociati.it/en/gems/devops/php-error-file-size-limit-exceeded/#comments</comments>
		<pubDate>Fri, 04 Jan 2013 14:12:26 +0000</pubDate>
		<dc:creator>maraspin</dc:creator>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[file size]]></category>
		<category><![CDATA[include]]></category>
		<category><![CDATA[issue]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php.ini]]></category>
		<category><![CDATA[settings]]></category>
		<category><![CDATA[timezone]]></category>

		<guid isPermaLink="false">http://www.mvassociati.it/en/gems/?p=454</guid>
		<description><![CDATA[Troubleshooting PHP interpreter issues can be tricky. A few days ago a client reported that one of his cron job scripts wasn&#8217;t being executed on his x86_64 CentOS 5.8 server, running Zend Server CE PHP 5.3.14. Troubleshooting such situations is usually straightforward, but this time PHP error messages I got were so ambiguous, and issues [...]]]></description>
			<content:encoded><![CDATA[<p>Troubleshooting PHP interpreter issues can be tricky. A few days ago a client reported that one of his cron job scripts wasn&#8217;t being executed on his x86_64 CentOS 5.8 server, running Zend Server CE PHP 5.3.14. Troubleshooting such situations is usually straightforward, but this time PHP error messages I got were so ambiguous, and issues were so many at the same time, that I decided to write a blog post, hoping that it can be of some help for someone else.<span id="more-454"></span></p>
<h3>The Problem</h3>
<p>Script wasn&#8217;t outputting nor logging anything, so in order to find out more about the problem, I thought about logging last script execution datetime myself. I wanted to find out whether the problem was related to cron execution, or rather to some issue within the script itself. So I added following two lines (on top to the script):</p><pre class="crayon-plain-tag">$s_content = 'Script last run: '. date(&quot;d/m/Y h:i:s&quot; . &quot;\n&quot;);
file_put_contents('/tmp/cert_import.log', $s_content);</pre><p>And executed it:</p><pre class="crayon-plain-tag">php ./importa_certificati.php</pre><p>All I got was a nasty error message:</p><pre class="crayon-plain-tag">File size limit exceeded</pre><p>At first I thought the problem might&#8217;ve been related to the specific file name I had picked (IE /tmp/cert_import.log). Did it exist already and was it already too big? I was sure I had checked things out. And actually, file wasn&#8217;t there upon a second check. So what was PHP ranting about? Could have it been a permission issue? Nope, script was being executed by root and was executable. So, where did the problem lie? I started to search for the problem by reverting the script to its original form, commenting out my additions:</p><pre class="crayon-plain-tag">// $s_content = 'Script last run: '. date(&quot;d/m/Y h:i:s&quot; . &quot;\n&quot;);
// file_put_contents('/tmp/cert_import.log', $s_content);</pre><p>Problem magically disappeared. Weird, I thought. &#8220;Let&#8217;s see what happens if I prepare my string, but don&#8217;t it write to the file, I said to myself. I&#8217;m sure the problem lies there. Let&#8217;s check&#8221;:</p><pre class="crayon-plain-tag">$s_content = 'Script last run: '. date(&quot;d/m/Y h:i:s&quot; . &quot;\n&quot;);
// file_put_contents('/tmp/cert_import.log', $s_content);</pre><p></p><pre class="crayon-plain-tag">File size limit exceeded</pre><p>Whaat?!? Problem still there, despite no attempt to write to a file is even made. Things start to look awkward.</p>
<h3>The Cause</h3>
<p>What I had just discovered was that problem didn&#8217;t have anything to do with the file I was trying to write, but was related instead to the PHP process itself. In fact, wondering what other file size limit might&#8217;ve been reached, I came to think about logging. So, I opened php.ini and checked things out. Logging was configured indeed, pointing at /usr/local/zend/var/log/php.log through following directives:</p><pre class="crayon-plain-tag">; http://php.net/log-errors
log_errors = On

; Set maximum length of log_errors. [...]
log_errors_max_len = 1024

; Log errors to specified file. PHPs default behavior is to leave this value
; empty.
error_log = &quot;/usr/local/zend/var/log/php.log&quot;</pre><p>I changed my working directory to /usr/local/zend/var/log/ and checked things out with ls:</p><pre class="crayon-plain-tag">[root@XXX ~]# cd /usr/local/zend/var/log/
[root@XXX log]# ls -alh
-rw-rw---- 1 apache zend 2.0G Dec 27 17:30 php.log</pre><p>That exact 2Gb size looked suspicious, to say the least. Especially because the php.ini log_errors_max_len directive above had a 1024 value, not a 2048 one. So, I moved the log file out of its way, and gzipped it (so to save some space, without losing anything).</p><pre class="crayon-plain-tag">mv php.log
gzip php.log</pre><p>I then run the script again. All went well this time, with no error being reported. Problem was caused by log file size indeed. Most likely no one cared about rotating it, believing that log_errors_max_len would do the job. As it&#8217;s explained on <a title="PHP log_errors_max_len" href="http://stackoverflow.com/questions/1966540/log-errors-max-len-1024-in-php-ini-but-php-log-keeps-growing">stackoverflow</a> though, despite its possibly ambiguous name, log_errors_max_len only deals with the size of a single log message, not with the size of the log file itself.</p>
<p><img class="aligncenter size-large wp-image-512" title="php-logs" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2012/12/php-logs-576x455.jpg" alt="PHP Logs" width="576" height="455" /></p>
<p>Newly introduced problem was solved. But I was still wondering what might&#8217;ve caused the problem from the lines I had added in first place. Luckily I now had logs to check.</p>
<h3>The timezone not set and include underlying issues</h3>
<p>I opened the new php.log file and found a few entries like the following:</p><pre class="crayon-plain-tag">[05-Dec-2012 23:00:04 UTC] PHP Warning:  strtotime(): It is not safe to rely on the system's timezone settings. 
You are *required* to use the date.timezone setting or the date_default_timezone_set() function. 
In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. 
We selected 'Europe/Berlin' for 'CET/1.0/no DST' instead in /[...]/importa_certificati.php on line 14</pre><p>Easy problem to fix. And also found the reason why log file filled up so quickly. Such message was written for every run of another script where the date function was used.</p>
<p><img class="aligncenter size-large wp-image-530" title="Timezones" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2013/01/timezone-576x430.jpg" alt="" width="576" height="430" /></p>
<p>Still, I hadn&#8217;t solved my problem yet. Script would run from console, but wouldn&#8217;t from cron. Again, logs proved to be my friends, with entries like the following:</p><pre class="crayon-plain-tag">[27-Dec-2012 23:09:02 UTC] PHP Warning:  include_once(../classi/dbconnect.php): failed to open stream: No such file or directory in /[...]/importa_certificati.php on line 3
[27-Dec-2012 23:09:02 UTC] PHP Warning:  include_once(): Failed opening '../classi/dbconnect.php' for inclusion (include_path='.:/[...]') in /[...]/importa_certificati.php on line 3
[27-Dec-2012 23:09:02 UTC] PHP Warning:  include_once(../classi/utils.php): failed to open stream: No such file or directory in /[...]/importa_certificati.php on line 4
[27-Dec-2012 23:09:02 UTC] PHP Warning:  include_once(): Failed opening '../classi/utils.php' for inclusion (include_path='.:[...]') in /[...]/importa_certificati.php on line 4
[27-Dec-2012 23:09:02 UTC] PHP Fatal error:  Class 'utils' not found in /[...]/importa_certificati.php on line 10</pre><p>I had just found out that problem was due to the script having relative includes in the following form:</p><pre class="crayon-plain-tag">&lt;!--?php

include_once('../classes/dbconnect.php');
include_once('../classes/utils.php');

$s_pathCerts = __DIR__ . '/../rsync/data';

&lt;/pre--&gt;</pre><p>So everything worked when the script was tested by customer from local directory:</p><pre class="crayon-plain-tag">php ./importa_certificati.php</pre><p>But once it was invoked by cron, it stopped working, since path wasn&#8217;t quite the same.<br />
And, because no error messages related to the issue were collected in php.log, no one ever discovered about the problem with the script, and blamed cron settings instead.<br />
Changing lines above tothe following solved the problem:</p><pre class="crayon-plain-tag">&lt;!--?php

include_once(__DIR__ . '/../classes/dbconnect.php');
include_once(__DIR__ . '/../classes/utils.php');

$s_pathCerts = __DIR__ . '/../rsync/data';

&lt;/pre--&gt;</pre><p>&nbsp;</p>
<h3>Things to take home from this experience</h3>
<ol>
<li>If php can not write to its log file it will stop script execution, without giving a clear explanation of what&#8217;s going on</li>
<li>The log_errors_max_len directive is a bit ambiguous. It deals with each log record, not with the whole file size</li>
<li>You always need to set your timezone, if you don&#8217;t want to have your logs filled with crap</li>
<li>When including stuff, it&#8217;s wise to rely on the php __DIR__ or dirname(__FILE__) constructs rather than on relative paths. You can&#8217;t be sure the scritpt will be invoked from where you expect.</li>
<li>When troubleshooting it&#8217;s important to think &#8220;outside&#8221; the box. In this case the problem was related to the script itself, as much as it was related to its environment.</li>
<li>If you do write to logs, you need to check&#8217;em out every once in a while. Having their content e-mailed to you periodically is also a good idea</li>
</ol>
<p>Elephant picture courtesy of http://www.flickr.com/photos/laughingsquid/2218075860/</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvassociati.it/en/gems/devops/php-error-file-size-limit-exceeded/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enhancing user stories with personas</title>
		<link>http://www.mvassociati.it/en/gems/user-stories-with-personas?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=enhancing-user-stories-with-personas</link>
		<comments>http://www.mvassociati.it/en/gems/user-stories-with-personas#comments</comments>
		<pubDate>Wed, 12 Dec 2012 10:54:25 +0000</pubDate>
		<dc:creator>maraspin</dc:creator>
				<category><![CDATA[User Experience Design]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[efficiency]]></category>
		<category><![CDATA[personas]]></category>
		<category><![CDATA[requirements]]></category>
		<category><![CDATA[user stories]]></category>
		<category><![CDATA[value]]></category>

		<guid isPermaLink="false">http://www.mvassociati.it/en/gems/?p=156</guid>
		<description><![CDATA[Since the adoption of user stories, we have noticed huge benefits in our development workflow. We don&#8217;t expect to plan everything upfront anymore, don&#8217;t waste time analyzing things which will never turn into software, and can deliver value to our customers much quicker and more efficiently. Many other companies have experienced the same benefits and [...]]]></description>
			<content:encoded><![CDATA[<p>Since the adoption of user stories, we have noticed huge benefits in our development workflow. We don&#8217;t expect to plan everything upfront anymore, don&#8217;t waste time analyzing things which will never turn into software, and can deliver value to our customers much quicker and more efficiently.</p>
<p>Many other companies have experienced the same benefits and it&#8217;s for this reason that user stories are becoming a standard way to collect software requirements. <span id="more-156"></span>If you&#8217;re not familiar with them, you can learn more reading <a title="User Story" href="http://en.wikipedia.org/wiki/User_story">here</a> or getting <a title="User Stories Applied" href="http://www.amazon.com/User-Stories-Applied-Software-Development/dp/0321205685">this book</a>. For now let&#8217;s just think of them as simple sketches on Post It notes, in the following form:</p>
<p><img class="aligncenter size-full wp-image-271" title="User Story Example" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2012/12/user-story-example.jpg" alt="User Story Example" width="260" height="260" /></p>
<h3>The good about User Stories</h3>
<p>User stories don&#8217;t mention software features, focusing on user interactions and user benefits instead. Since they need to fit on a Post It sheet, they need to be short. Therefore, rather than being a list of detailed requirements, they end up being simple &#8220;reminders&#8221; of what will need to be discussed later on in the project life-cycle. <strong>Maybe</strong>. Yes maybe, because after having developed several stories, you might realize that several others do not need to be implemented at all. They are scratched from the project road-map altogether, before requiring significant design and development effort.</p>
<p>Stories are developed and delivered incrementally, in order of business priority. At each iteration (development phase) a batch of stories is selected, analyzed and turned into working software. Value is delivered to customers at regular intervals, much earlier than with traditional development processes.</p>
<p>&nbsp;</p>
<h3>Are User Stories a Silver Bullet?</h3>
<p><img class="alignright" title="Silver Bullet" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2012/12/silver-bullet-400x282.jpg" alt="Silver Bullet" width="240" height="169" />I&#8217;m sure the above sounds great. And indeed it is. But let me tell you a story: several years ago I got to work with some folks from an Italian company, which is famous for its adoption of agile methodologies. I&#8217;ve learned a lot from that experience. They quickly explained everyone involved in the project what user stories were, then assigned each of the developers and customer representatives (around 15 people) a set of post it sheets, and finally said: &#8220;ok everybody, let&#8217;s now start writing user stories together&#8221;. Everyone started to think about some stories and gave his contribution. By the end of the day, we had collected several dozen Post It sheets.</p>
<p>All good, right? Well, not really. Sure we had put together a lot of stories. Problem is that later on, <strong>after</strong> we had developed them, we found out that many provided little or no value towards the project goals. And I&#8217;m sure we had missed out several others which would have. Don&#8217;t get me wrong. I&#8217;m not saying that stories are not the way to go, and that you shouldn&#8217;t measure things in retrospective. But development has a cost. And if you can avoid developing the wrong things from principle, well, I think that&#8217;s even better.</p>
<h3>A problem of perspective</h3>
<p>I&#8217;m now confident the problem we faced is a perspective one. Let&#8217;s consider user stories in the form we have seen above again. By starting our statements in the form</p>
<p><img class="aligncenter size-full wp-image-345" title="User Story Myself Issue" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2012/12/user-story-myself-issue.jpg" alt="User Story Myself Issue" width="260" height="260" /></p>
<p>we are focusing on ourselves. And, in this example, if I think about myself shopping for some gifts, I think about as many filtering options as I can. And so &#8211; I&#8217;m sure &#8211; will do many other geeks, who just love to evaluate all possible available options. The problem is that intended system users will probably be different. They won&#8217;t know or care about Pareto optimals or multidimensional optimization. They&#8217;d probably just pick the best looking item, for the peace of their mind. System users more often than not have a different background, different expectations, and most likely different needs from ours. Which we need to take into account, and which we did not in the situation I&#8217;ve mentioned above.</p>
<h3>Introducing Personas</h3>
<p>In order to avoid this kind of issues, we introduced personas (for a good quick introduction see this <a href="http://www.amazon.com/Information-Architecture-Blueprints-Web-2nd/dp/0321600800">book</a>) into our requirements gathering process. We wanted to make sure we delivered software which satisfied intended users needs, not just our customers or ourselves. So, we started to create stereotyped characters of our intended users (whose characteristics were gathered either through interviews, observation or both) and then writing stories in the following form:</p>
<p><img class="aligncenter size-full wp-image-272" title="Impersonated User Story" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2012/12/josie-black-story.jpg" alt="Impersonated User Story" width="260" height="260" /></p>
<p>Now imaging implementing, or just estimating this story. At this point, you might be wondering who the heck Josie Black is. And that&#8217;s a good question. Let&#8217;s describe her as follows:</p>
<blockquote><p><img class="alignleft size-full wp-image-325" title="josie-1" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2012/12/josie-1.jpg" alt="" width="112" height="146" /> &#8221;Josie&#8217;s a 28 years old busy lawyer from Los Angeles, California. She&#8217;s always in a hurry, obsessed by her job and tends to forget about her friends&#8217; birthdays. Therefore she looks for presents on the Internet, always at the very last moment. She has a budget in mind and doesn&#8217;t care much about making the perfect gift. A good one will be enough. She just wants to get the purchase job done as quickly as possible, so to get back to work. She&#8217;s annoyed by systems who do make a lot of questions and offer too many options.&#8221;</p></blockquote>
<p>Now, what if Jodie&#8217;s profile was more similar to the following:</p>
<blockquote><p> <img class="alignleft size-full wp-image-324" title="josie-2" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2012/12/josie-2.jpg" alt="" width="112" height="146" />&#8220;Josie&#8217;s a 68 years old retired business woman, who now lives in a small town in New England. When she was living in New York city, she loved to go shopping in malls and spending a lot of time looking for the perfect present for her friends and family members. Nowadays she enjoys the countryside, but misses shopping a lot. Luckily there&#8217;s the Internet, and that&#8217;s where she still does spend a lot of time searching for the best gifts. Before making a purchase she literally compares dozens or even hundreds of items.&#8221;</p></blockquote>
<p>Now try to read the same user story above again. Do you feel the same way? If you need to make an estimate on development effort, do you think it&#8217;s going to take the same amount of time? Do you still think the story above is the best you could write? From our experience, the answer to these questions is almost always no. And that&#8217;s a good thing already, since the use of personas helps us being more accurate when writing stories and making initial estimates. What&#8217;s even more important, though, is the fact that when you properly consider the people who&#8217;ll use the system, you can easily ditch those stories which do not make sense at all. The process is no different from the traditional one, and everyone in the team can suggest a story. The point is that suggestions do not start from our perspective, but rather from that of our personas. And we&#8217;ve found this to be a significant switch. After all stories are collected, moreover, we review them and ask ourselves: &#8220;would this guy/gal, or anyone else of these folks here find this story useful&#8221;? If the answer is no, we simple drop the story.</p>
<p><img title="User Stories and Personas" src="http://www.mvassociati.it/en/gems/wp-content/uploads/2012/12/personae-stories.jpg" alt="User Stories and Personas" width="576" height="408" /></p>
<h3>Conclusion</h3>
<p>The majority of our customers come to us with a set of requirements that they expect us to transform into software. When they accept to follow the process introduced above, interesting things emerge. The most significant one is surely the 50% of features they were requesting being cut off.  With personas it&#8217;s immediate for eveyone to find out about features which would be of no use for anyone. This is a fundamental point, which much improved our process and efficiency. But that&#8217;s only part of the game. As JJ Garrett <a title="The Elements of User Experience Book" href="http://www.amazon.com/The-Elements-User-Experience-User-Centered/dp/0321683684/ref=cm_cr-mr-title">points out</a>, there are 2 things you need to address for an application to be successfull: user needs and business goals. The technique described above proved to be much helpful for better understanding user needs. A forthcoming post on this blog will talk about other techniques we do use in order to make sure business goals are also met.</p>
<p>Photo Credits: flickr.com/photos/eschipul/4160817135,<br />
flickr.com/photos/coalitionforicc/6521548779, flickr.com/photos/judybaxter/4272568538</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mvassociati.it/en/gems/user-stories-with-personas/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
