<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="/templates/default/atom.css" type="text/css" ?>

<feed 
   xmlns="http://www.w3.org/2005/Atom"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/">
    <link href="http://www.phponthebeach.net/feeds/atom10.xml" rel="self" title="PHP on the beach" type="application/atom+xml" />
    <link href="http://www.phponthebeach.net/"                        rel="alternate"    title="PHP on the beach" type="text/html" />
    <link href="http://www.phponthebeach.net/rss.php?version=2.0"     rel="alternate"    title="PHP on the beach" type="application/rss+xml" />
    <title type="html">PHP on the beach</title>
    <subtitle type="html">The place where PHP is sunnier, breezier, saltier and a little sandy...</subtitle>
    
    <id>http://www.phponthebeach.net/</id>
    <updated>2010-04-12T01:42:22Z</updated>
    <generator uri="http://www.s9y.org/" version="1.4.1">Serendipity 1.4.1 - http://www.s9y.org/</generator>
    <dc:language>en</dc:language>

    <entry>
        <link href="http://www.phponthebeach.net/archives/4-Caching-made-simple-with-Zend_Cache.html" rel="alternate" title="Caching made simple with Zend_Cache" />
        <author>
            <name>Jordi Roura</name>
                    </author>
    
        <published>2010-04-12T01:42:22Z</published>
        <updated>2010-04-12T01:42:22Z</updated>
        <wfw:comment>http://www.phponthebeach.net/wfwcomment.php?cid=4</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.phponthebeach.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=4</wfw:commentRss>
    
            <category scheme="http://www.phponthebeach.net/categories/6-cache" label="cache" term="cache" />
            <category scheme="http://www.phponthebeach.net/categories/1-framework" label="framework" term="framework" />
            <category scheme="http://www.phponthebeach.net/categories/4-PHP" label="PHP" term="PHP" />
            <category scheme="http://www.phponthebeach.net/categories/3-zend" label="zend" term="zend" />
    
        <id>http://www.phponthebeach.net/archives/4-guid.html</id>
        <title type="html">Caching made simple with Zend_Cache</title>
        <content type="xhtml" xml:base="http://www.phponthebeach.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>One of the nice things about the Zend Framework is that most of its libraries can be used either from within the framework or as stadalone bits of code which can be seamlessly integrated into non-Zend applications.&#160; Zend_Cache is no exception and can be used to quickly apply caching solutions to common performance problems.&#160; If you are new to caching, or wondering what caching is, it is simply a technique by which something is stored to avoid running the same code over and over again.&#160; For example, if you have a query that is going to be launched time and time again and the result is not going to vary, we can <em>cache</em> it and run it only once, retrieving the cached result until the cache expires thus saving the database a lot of stress.<br /></p> <br />
<p>The hardest part to understand about Zend_Cache is its collection of <em>frontends</em> and <em>backends</em>.&#160; Since the aim of this article is to provide an introduction into quickly deploying a caching solution I will not cover all the options, but they are perfectly covered in the <a title="Zend_Cache documentation" target="_blank" href="http://framework.zend.com/manual/en/zend.cache.html">Zend_Cache framework documentation</a>.&#160; However, once we go past the tricky names we can see that a <em>frontend</em> is merely a way to specify <em><strong>what</strong></em> we want to store in cache, and a <em>backend</em> they to specify <strong><em>how</em></strong>.</p> <br />
<p>Zend_Cache can store virtually anything from php objects to pages or functions and, out of the box, supports storage &quot;mediums&quot; such as filesystem, Sqlite, Memcache or Apc among many others.&#160; Again, the documentation provides full reference, but for the purpose of this tutorial we will concentrate on the Core frontend (a generic container of text) and the File backend.&#160; Why?&#160; Because it is the most widely available solution and a good way to get started with Zend_Cache.&#160; If you are interested in other options please comment and I will address them.</p> <br />
<p>Now let's see a simple instantiation of a cache object:</p> <br />
<p><font face="courier new,courier,monospace">$frontendOptions = array(<br />&#160;&#160;&#160; 'lifetime' =&gt; 3600, // cache lifetime of 1 hour<br />&#160;&#160;&#160; 'automatic_serialization' =&gt; true<br />);<br />$backendOptions = array();<br /><br />$cache = Zend_Cache::factory('Core',<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 'File',<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $frontendOptions,<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; $backendOptions);</font></p> <br />
<p>Let's take a look at what we've done.&#160; First, we've defined the option values that will define the behavior of the frontend.&#160; In this case we've given the cached items a lifespan of one hour and we've set the automatic serialization option to true which guarantees the Core frontend becomes a pretty safe container of virtually anything.&#160; Secondly, we've defined the option values for the backend.&#160; In this case I've left it empty since default values are the most generic and work fairly well.&#160; Otherwise, we can change where the files containing the objects are stored, whether they should be locked, whether there should be read control etc...&#160; And finally we create the cache object using the Zend_Cache factory method.&#160; Voilà!&#160; Now let's take a peek on how it's used:</p> <br />
<p><font face="courier new,courier,monospace">if (!$obj = $cache-&gt;load('Object_Expensive_To_Generate')) {<br />&#160;&#160;&#160; $obj = new ObjectThatIsExpensiveToGenerate();<br />&#160;&#160;&#160; $obj-&gt;overloadDatabaseWithExpensiveQueries();<br />&#160;&#160;&#160; $obj-&gt;hogTheCpu();<br /><br />&#160;&#160;&#160; $cache-&gt;save($obj, 'Object_Expensive_To_Generate');<br />}</font></p> <br />
<p>Woohoo!&#160; Now we only get to go through the painful process of generating an ObjectThatIsExpensiveToGenerate once an hour.&#160; Now let's take a peek at what we've done...&#160; If the object has not yet been cached, or it has expired, the condition in the if clause will return true, and hence start generating and instance of the object.&#160; However, if it has been cached it will skip the if altogether and leave us with a perfectly functional $obj at the other side without going through all the hassle and thus saving valuable resources.&#160; If we do enter the conditional though, the last thing we do is to put the object in cache so we can safely retrieve it for the next hour.</p> <br />
<p>And now that we've finished this brief introduction into Zend_Cache and caching in general, it's time to apply it or to delve deeper and explore what this powerful class has to offer!<br /></p> 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.phponthebeach.net/archives/3-How-to-log-into-a-Google-Analytics-account-with-PHP.html" rel="alternate" title="How to log into a Google Analytics account with PHP" />
        <author>
            <name>Jordi Roura</name>
                    </author>
    
        <published>2010-01-22T21:11:28Z</published>
        <updated>2010-01-22T21:39:46Z</updated>
        <wfw:comment>http://www.phponthebeach.net/wfwcomment.php?cid=3</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.phponthebeach.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=3</wfw:commentRss>
    
            <category scheme="http://www.phponthebeach.net/categories/1-framework" label="framework" term="framework" />
            <category scheme="http://www.phponthebeach.net/categories/4-PHP" label="PHP" term="PHP" />
            <category scheme="http://www.phponthebeach.net/categories/3-zend" label="zend" term="zend" />
    
        <id>http://www.phponthebeach.net/archives/3-guid.html</id>
        <title type="html">How to log into a Google Analytics account with PHP</title>
        <content type="xhtml" xml:base="http://www.phponthebeach.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>The first step in using the Google Analytics API to retrieve insightful data into your PHP application is logging in.&#160; To this end we will use <a title="The Zend Framework" target="_blank" href="http://framework.zend.com">Zend Framework</a>'s Gdata libraries which get rid of much of the hassle by providing a comprehensive set of classes and functions that cover most of the GA API needs. The mechanism is simple: you boot up a connection client, use it to open a feed and use that feed to retrieve the necessary reports from GA.</p> <br />
<p><font face="courier new,courier,monospace">$email = 'some@email.com';&#160;&#160;&#160; // The email that identifies the Google Analytics Account<br />$password = 'xXxXxXxXx';&#160;&#160;&#160;&#160;&#160; // The Google Analytics account's password<br /><br />$client = Zend_Gdata_ClientLogin::getHttpClient($email,$password, 'analytics', null, 'curl-accountFeed-v2', null, null, 'https://www.google.com/accounts/ClientLogin', 'GOOGLE');<br />$feed = new Zend_Gdata_Gapps($client);<br />$response = $feed-&gt;get('https://www.google.com/analytics/feeds/data?ids=ga:13962678&amp;dimensions=ga:browser&amp;metrics=ga:pageviews&amp;filters=ga:browser%3D~%5EFirefox&amp;start-date=2009-01-01&amp;end-date=2009-12-31');<br />$xml = $response-&gt;getBody();</font></p> <br />
<p>And now, in the <font face="courier new,courier,monospace">$xml</font> variable holds the raw XML with the data from the report so you can collect it and use it in your app!<br /></p> 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.phponthebeach.net/archives/2-Handling-errors-the-sweet-way.html" rel="alternate" title="Handling errors the sweet way" />
        <author>
            <name>Jordi Roura</name>
                    </author>
    
        <published>2009-12-17T03:39:52Z</published>
        <updated>2009-12-17T03:39:52Z</updated>
        <wfw:comment>http://www.phponthebeach.net/wfwcomment.php?cid=2</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.phponthebeach.net/rss.php?version=atom1.0&amp;type=comments&amp;cid=2</wfw:commentRss>
    
            <category scheme="http://www.phponthebeach.net/categories/5-exceptions" label="exceptions" term="exceptions" />
            <category scheme="http://www.phponthebeach.net/categories/4-PHP" label="PHP" term="PHP" />
    
        <id>http://www.phponthebeach.net/archives/2-guid.html</id>
        <title type="html">Handling errors the sweet way</title>
        <content type="xhtml" xml:base="http://www.phponthebeach.net/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <p>If we were to argue about what are the most useful things that have come into modern PHP, Exceptions would be one of the first things that would come to mind, and it's still one of the features that most amateur developers tend to leave aside.&#160; However, adequately used, Exceptions give total control on what happens within your application, and most specifically when things go wrong which is when it is most important to try and keep things in check.&#160; Out of the box, Exceptions provide limited but useful information, mainly a message, an error code and some background information on what was being run at the time... but with some skillful plumbing we can get a lot more juice our of them.&#160; Enter the Custom Exceptions!</p> <br />
<p>In fact, Exceptions are meant to be simple in their simplest form.&#160; This way they can provide a clean and reliable set of tools with which we can construct some pretty mean guards to keep our applications in check.&#160; Only we know what's going to go on in our application, and only we know what it's going to take to keep everything in shape!&#160; Most of the time, we know when things can go wrong and how they can go wrong and hence it is easy to protect and correct, but it's when things go <em>unexpectedly</em> wrong that custom exceptions come in very useful as they can give very precise information on exactly where the issue is, and its nature.&#160; To this end, it is important that each possible source of conflict be uniquely labeled and identified in a way that will take us directly to the source of the problem.&#160; An excellent way to achieve this is to relate each class to a unique exception class, and give every single possible problem a unique ID.&#160; Take a simple example:</p> <br />
<p><font face="courier new,courier,monospace">try {<br />&#160;&#160;&#160; Database::connect();<br />&#160;&#160;&#160; $user = new User($id);<br />&#160;&#160;&#160; $valid = $user-&gt;login($password);<br />}<br />catch (DatabaseException $e) {<br />&#160;&#160;&#160; $errorMsg = 'There was a database problem';<br />}<br />catch (UserException $e) {<br />&#160;&#160;&#160; if ($e-&gt;getCode()==1) $errorMsg = 'The user doesn't exist';<br />&#160;&#160;&#160; elseif ($e-&gt;getCode()==2) $errorMsg = 'User and password don't match';<br />&#160;&#160;&#160; else $errorMsg = 'An error has occurred, our devlopment team has been notified';<br />}</font></p> <br />
<p>In this case, the error codes are very simple and provide little information, but they can be tailored to be a little more detailed, even if they can only be numerical strings.&#160; A quick example of this would be to imagine an application being run in different environments, and in which different exceptions can be assigned a &quot;criticality factor&quot; which would decide how bad he exception is and wether the application can continue.&#160; In this case we can divide the numerical error into three parts which would provide necessary information: the first three would indicate the environment, the next three would specify how bad the error is and the last three the ID of the actual exception being thrown.&#160; Therefore an exception with code 003001028 would tell us that Exception 28 has been thrown in environment 3 with a '1' criticality factor.&#160; Hence we can decide if we want to continue executing the script or jump to the 'site down' page, and which server's logs we have to fetch to see what was going on at the time.</p> <br />
<p> </p> 
            </div>
        </content>
        
    </entry>

</feed>