James Morris - JMOZ

I pretend I know PHP and internet stuff. Currently contracting at TimeOut London.

    • 7
      12 Dec 2011

      Symfony2 FOSUserBundle Role entities

      • Edit
      • Delete
      • Tags
      • Autopost

      I’ve been working with FOSUserBundle Roles recently, adding database persistence using a simple Doctrine array mapping. We needed a better implementation where the Roles could be managed from the database and dynamically added and removed to a User through an admin interface. I found quite a few posts on stackoverflow and the Symfony2 google group asking how best to implement Role entities but very few answers or solutions, and no documentation on the FOSUserBundle github page.

      Symfony2’s security system is one of the most complex parts of the framework. Couple this with FOSUserBundle’s weird AOP implementation and you’ve basically got a big massive ball ache when it comes to figuring out what’s going on. After staring through a lot of code and not really getting anywhere, I figured I’d write some tests to cover the existing functionality then refactor the User and Role classes until everything went green.

      Unit test to cover existing functionality

      For reference here is the unit test I was working with.

      Creating the Role entity

      FOSUserBundle provides no Role entity. Symfony2 provides a Role object but some class members are private so we just implement the Role interface, hoping it will ensure the new Role implementation works correctly with the security system.

      It’s a simple object, I’m implementing a __toString() method so we can loop in the template over User::getRoles() and echo the $role.

      Creating the User, Role relationship

      This is the User class with the Role relationship mapped. I tried to implement the same Role functionality as FOSUserBundle. You are restricted to certain method parameters due to the type hinting in the parent class, e.g. setRoles() must take an array. I found type hinting and return type expectations in some of the symfony2 security layer code, such as:

      UsernamePasswordToken::__construct($user, $credentials, $providerKey, array $roles = array())

      Because of this, I mixed up an ArrayCollection and array implementation. You can see I also provided the (set|get)RolesCollection() methods to make things easier when working with doctrine.

      Modify the schema

      Check the changes to the database:

      $ php app/console --env=test doctrine:schema:update --em=user --dump-sql
      CREATE TABLE security_roles (id INT AUTO_INCREMENT NOT NULL, role VARCHAR(70) NOT NULL, UNIQUE INDEX UNIQ_5A82CD6D57698A6A (role), PRIMARY KEY(id)) ENGINE = InnoDB;
      CREATE TABLE security_users_roles (user_id INT NOT NULL, role_id INT NOT NULL, INDEX IDX_71E6DDEFA76ED395 (user_id), INDEX IDX_71E6DDEFD60322AC (role_id), PRIMARY KEY(user_id, role_id)) ENGINE = InnoDB;
      ALTER TABLE security_users_roles ADD CONSTRAINT FK_71E6DDEFA76ED395 FOREIGN KEY (user_id) REFERENCES security_users(id) ON DELETE CASCADE;
      ALTER TABLE security_users_roles ADD CONSTRAINT FK_71E6DDEFD60322AC FOREIGN KEY (role_id) REFERENCES security_roles(id) ON DELETE CASCADE;
      ALTER TABLE security_users DROP roles

      Either run this using the --force parameter or create a migration.

      Issues

      This will break the FOSUserBundle promote and demote commands as they are hard coded to use addRole(string).

      Summary

      I managed to get all the tests to pass:

      $ phpunit --stop-on-error --stop-on-failure -c app src/JMOZ/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php
      PHPUnit 3.5.5 by Sebastian Bergmann.
      
      ...........
      
      Time: 30 seconds, Memory: 82.25Mb
      
      OK (11 tests, 35 assertions)

      I would rather have not mixed the array/ArrayCollection implementation but was forced to do so due to the existing functionality and interfaces. I’d have liked to have seen some other implementations or solutions but could not seem to find any. If anyone has seen anything better please let me know. I hope this helps someone out there!

      • views
      • Tweet
    • 0
      30 Nov 2011

      Symfony2 Warning: session_start(): The session id is too long or contains illegal characters...

      • Edit
      • Delete
      • Tags
      • Autopost

      Whilst trying to set up a new test environment I’ve run into another lovely Symfony2 bug/error. I have a functional test with a body as such:

      public function testFoo()
      {
          $client = self::createClient();
          $client->request('GET', '/foo/');
          $this->assertEquals( 403, $client->getResponse()->getStatusCode() );
      }

      FYI I’m trying to test access roles are working correctly so I should get a 403 forbidden.

      And my relevant config_test.yml:

      imports:
          - { resource: config_dev.yml }
          - { resource: parameters_test.ini }
      
      framework:
          router:   { resource: "%kernel.root_dir%/config/routing_test.yml" }
          test:     ~

      Upon running this test I get the lovely error:

      Warning: session_start(): The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in /home/james/foo/vendor/symfony/src/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php line 87 (500 Internal Server Error)

      After messing with the config and looking around, it turns out this is a known issue. For whatever reason, my config was missing some required session parameters for testing. Have a look at https://github.com/symfony/symfony/issues/1759 for more info. To fix it, I had to change the session storage method params in config_test.yml from native (inherited) to filesystem:

      framework:
          router:   { resource: "%kernel.root_dir%/config/routing_test.yml" }
          test:     ~
          session:
            storage_id: session.storage.filesystem

      Now, the exception is gone and the test runs:

      $ phpunit --stop-on-error --stop-on-failure -c app src/Foo/Bundle/SecurityBundle/
      PHPUnit 3.5.5 by Sebastian Bergmann.
      
      ..F
      
      Time: 1 second, Memory: 29.75Mb
      
      There was 1 failure:
      
      1) Foo\Bundle\FooBundle\Tests\Functional\SecurityTest::testFoo
      Failed asserting that  matches expected .
      
      /home/james/code/Foo/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php:59
      
      FAILURES!
      Tests: 3, Assertions: 4, Failures: 1.

      Great, next problem…

      • views
      • Tweet
    • 2
      23 Nov 2011

      Symfony2 FOSUserBundle Roles - a simple solution

      • Edit
      • Delete
      • Tags
      • Autopost

      Out of the box, FOSUserBundle does NOT support Doctrine ORM database persisted Roles. The base class they give you to extend has functionality for roles, i.e. setting, getting and checking them, but you will need to write your own code to persist to the database and thus fully equipping the User with role functionality.

      The quickest and easiest way to get roles up and running is to use the existing FOS functionality and create your user a new roles field, mapping it as an array type in Doctrine. This is quicker and easier to work with than using separate Role objects. So your user class will need to specify the $roles class member with the following mapping metadata:

      /**
       * @ORM\Column(type="array", name="roles")
       */
       protected $roles;

      This will tell doctrine to map a PHP array to a SQL CLOB using serialize() and unserialize(). Take a look at the Doctrine mapping documentation at http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html#...

      Schema changes

      So now the model has been sorted, the new column needs to be added to the database. Generate a migration for the changes to the users table:

      $ php app/console doctrine:migrations:diff
      Generated new migration class to "/home/james/fooapp/DoctrineMigrations/Version20111121145741.php" from schema differences.

      This will generate said file which will contain a call to a method to add the new column:

      $this->addSql("ALTER TABLE users ADD roles LONGTEXT NOT NULL COMMENT '(DC2Type:array)'");

      If you want to set up default roles for existing users, under the call to addSql() insert the following line:

      $this->addSql(sprintf("UPDATE users SET roles = '%s'", 'a:1:{i:0;s:8:"ROLE_FOO";}'));

      Then execute:

      $ php app/console doctrine:migrations:migrate
      ...
      Migrating up to 20111121145921 from 0
      
        ++ migrating 20111121145921
      
           -> ALTER TABLE users ADD roles LONGTEXT NOT NULL COMMENT '(DC2Type:array)'
           -> UPDATE users SET roles = 'a:1:{i:0;s:8:"ROLE_FOO";}'
      
        ++ migrated (0.69s)
      
        ------------------------
      
        ++ finished in 0.69
        ++ 1 migrations executed
        ++ 2 sql queries

      (More information on migrations can be found at http://symfony.com/doc/2.0/bundles/DoctrineMigrationsBundle/index.html and https://github.com/symfony/DoctrineMigrationsBundle)

      This will add the new column to your users table. You now need to create a new user which will save a serialized empty array in the roles column. From here you can add new roles to that user or you may need to sort out existing users which will have nothing in their roles field unless you followed the step above. Trying to update or work with existing users with empty roles fields will most likely give you a Doctrine ConversionException:

      [Doctrine\DBAL\Types\ConversionException]                   
      Could not convert database value "" to Doctrine Type array

      So I suggest setting up a new user with default roles for your system then copying the content of that user’s roles field into existing user’s roles fields.

      To test the roles functionality try the following:

      $ php app/console fos:user:create jamestest james@foo.co.uk mypassword
      Created user jamestest
      $ php app/console fos:user:promote jamestest --super
      User "jamestest" has been promoted as a super administrator.

      If you now check your db, the roles field for jamestest should look similar to:

      a:2:{i:0;s:8:"ROLE_FOO";i:1;s:16:"ROLE_SUPER_ADMIN";}

      Your User should now be set up to persist it’s roles to the database. You should be able to edit the security.yml file and restrict access to certain parts of your site by url pattern:

      access_control:
        - { path: ^/admin, roles: ROLE_FOO }

      For further information see http://symfony.com/doc/2.0/book/security.html#securing-specific-url-patterns

      UPDATE:

      See my following article if you need more powerful Role entity based solution http://blog.jmoz.co.uk/symfony2-fosuserbundle-role-entities

      • views
      • Tweet
    • 2
      7 Sep 2011

      PHP news

      • Edit
      • Delete
      • Tags
      • Autopost

      I've noticed recently a lack of PHP news/articles/blog posts coming to my attention.  I'm sure I used to see a constant stream of them but I can't remember my sources.  Maybe its my increasing reliance on Twitter as a source of everything - general news, local info, tech news and banter with friends.  I used to use Google Reader a lot, and sites such as Digg, Popurls, Mixx etc but they all seem to have dropped in quality or they get increasingly harder to manage (GReader rss feeds) whilst everywhere else seems to have a Twitter feed.  So this is more of a request for comments or tips on decent sources of PHP news.  You can reply by comment or tweet me at @jwm0z.  I'll list some of mine:

      Twitter

      Any tech site or person that tweets about PHP I tend to follow, I have a twitter tech list (which probably could do with being split into a php list) and I also watch a #php and #symfony2 search in my Tweetdeck.

      Web Sites

      One of my favourite sites to follow is PHP Developer, they reblog a lot PHP articles from developer blogs (including mine) and they have a busy twitter feed.

      Some others include Planet PHP, DZone PHP, Zend Developer Zone but I never seem to catch their updates as often as I do as PHP Developer's.

      Too many channels

      There's just too many channels of information available to be able to get a good overview of the PHP scene.  For me, Twitter is probably the easiest to manage but I need to follow more decent sources of technical articles and news.  If you've got any lists to share or think it's worthwhile me following you, please get in touch!

      • views
      • Tweet
    • 0
      5 Sep 2011

      A Symfony2 console Command and the Foursquare API venuehistory

      • Edit
      • Delete
      • Tags
      • Autopost

      I've been playing with the Foursquare API recently, I'm attempting to get a new homepage built and want to display a map of where I hang out. I use Foursquare quite a bit so wanted to get the locations from their API then plot them on Google maps.

      There's a venuehistory endpoint that gives you a massive list of all the venues you've checked into with details such as the venue name, location including lat and lng coordinates, and the count of times you've checked in.

      Here's a screenshot of their json response.

      Media_httpdldropboxco_gdpci

      I want to pull this into my own database so I have a local copy of it and can play around with it. I'm using Symfony2 so I've created a console command which I can run on a cron, or on demand. I decided to do it this way as mainly a learning exercise and also this is a bit better than a standard php script.

      The command hits the endpoint with my Oauth access token (outside of the scope of this article, but see the docs for details) and then simply loops over the response and creates a load of Checkin entities which the entity manager then persists.

      The command takes an optional argument for the access_token or otherwise defaults to a parameter. There's also an optional flag to disable the truncation of the checkins table. You can see how to set these up along with the help text in the configure() method. Output is handled by the call to $output->writeln() and you can see how highlighting works in the screenshot of the output.

      Media_httpdldropboxco_rkcdq

      I may write a future post showing how to push the Foursquare code into a service based implementation so look out.

      • views
      • Tweet
    • 2
      24 Aug 2011

      How to strip exif data using Imagick

      • Edit
      • Delete
      • Tags
      • Autopost

      Today I spent a good amount of time trying to figure out how to strip exif data from an image using Imagick.  The first port of call was the (pathetic) documentation at php.net.  I searched for 'exif' but found nothing.  Google isn't too helpful either.  There's a method Imagick::setImageProperty() but that didn't seem to save the data correctly.  There's also an exif extension but it only reads the exif data, not writes it.

      I was tipped off by a colleague to the method Imagick::stripImage() which apparently did what I wanted.  The only mention of exif is in a rather helpful comment at the bottom of the page.

      To remove the exif data you need to call Imagick::stripImage() on the populated Imagick object and then call Imagick::writeImage() to save your changes.  I've written a test script below that uses a sample image with exif data from the exif website.

      Media_httpwwwexiforgs_hijai

      Here's the script:

      And here's the output:

      moz on mz-904 in ~ 
       $ php imagick.php
      Array
      (   
          [exif:ApertureValue] => 262144/65536
          [exif:ColorSpace] => 1
          [exif:ComponentsConfiguration] => 1, 2, 3, 0
          [exif:CompressedBitsPerPixel] => 3/1
          [exif:Compression] => 6
          [exif:DateTime] => 2001:06:09 15:17:32
          [exif:DateTimeDigitized] => 2001:06:09 15:17:32
          [exif:DateTimeOriginal] => 2001:06:09 15:17:32
          [exif:ExifImageLength] => 480
          [exif:ExifImageWidth] => 640
          [exif:ExifOffset] => 184
          [exif:ExifVersion] => 48, 50, 49, 48
          [exif:ExposureBiasValue] => 0/3
          [exif:ExposureTime] => 1/350
          [exif:FileSource] => 3
          [exif:Flash] => 0
          [exif:FlashPixVersion] => 48, 49, 48, 48
          [exif:FNumber] => 40/10
          [exif:FocalLength] => 346/32
          [exif:FocalPlaneResolutionUnit] => 2
          [exif:FocalPlaneXResolution] => 640000/206
          [exif:FocalPlaneYResolution] => 480000/155
          [exif:InteroperabilityIndex] => R98
          [exif:InteroperabilityOffset] => 1088
          [exif:InteroperabilityVersion] => 48, 49, 48, 48
          [exif:JPEGInterchangeFormat] => 1524
          [exif:JPEGInterchangeFormatLength] => 5342
          [exif:Make] => Canon
          [exif:MakerNote] => 10, 0, 1, 0, 3, 0, 19, 0, 0, 0, 120, 3, 0, 0, 2, 0, 3, 0, 4, 0, 0, 0, 158, 3, 0, 0, 3, 0, 3, 0, 4, 0, 0, 0, 166, 3, 0, 0, 4, 0, 3, 0, 15, 0, 0, 0, 174, 3, 0, 0, 0, 0, 3, 0, 6, 0, 0, 0, 204, 3, 0, 0, 6, 0, 2, 0, 32, 0, 0, 0, 216, 3, 0, 0, 7, 0, 2, 0, 24, 0, 0, 0, 248, 3, 0, 0, 8, 0, 4, 0, 1, 0, 0, 0, 243, 105, 15, 0, 9, 0, 2, 0, 32, 0, 0, 0, 16, 4, 0, 0, 16, 0, 4, 0, 1, 0, 0, 0, 0, 0, 4, 6, 0, 0, 0, 0, 38, 0, 2, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 90, 1, 211, 0, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 140, 0, 2, 1, 128, 0, 14, 1, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 77, 71, 58, 74, 80, 69, 71, 32, 102, 105, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 105, 114, 109, 119, 97, 114, 101, 32, 86, 101, 114, 115, 105, 111, 110, 32, 49, 46, 48, 0, 0, 0, 0, 84, 111, 109, 32, 82, 111, 119, 97, 110, 32, 97, 110, 100, 32, 83, 97, 114, 97, 104, 32, 67, 108, 105, 102, 116, 111, 110, 0, 0, 0, 0, 0
          [exif:MaxApertureValue] => 194698/65536
          [exif:MeteringMode] => 2
          [exif:Model] => Canon DIGITAL IXUS
          [exif:Orientation] => 1
          [exif:RelatedImageLength] => 640
          [exif:RelatedImageWidth] => 480
          [exif:ResolutionUnit] => 2
          [exif:SensingMethod] => 2
          [exif:ShutterSpeedValue] => 553859/65536
          [exif:SubjectDistance] => 3750/1000
          [exif:UserComment] => 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
          [exif:XResolution] => 180/1
          [exif:YCbCrPositioning] => 1
          [exif:YResolution] => 180/1
      )
      *** stripImage()
      Array
      (
      )
      • views
      • Tweet
    • 1
      17 May 2011

      SplObserver, SplSubject - Removing dependencies with the Observer pattern

      • Edit
      • Delete
      • Tags
      • Autopost

      I work with symfony every day – I’m a backend developer who mainly enjoys designing and writing domain objects, core services and APIs.  I like to create loosely coupled objects where each object has a clear role and is composed of other objects.  Working on a symfony app, you usually have a mix of domain objects that are used by symfony actions, interspersed with symfony specific code such as logging and sfContext type stuff.  A common bad practice I see is symfony specific code peppered inside of domain objects that could be used elsewhere (such as inside of a Zend app or a script from the cli) but now can’t as they’re coupled to the symfony code.

      The Observer pattern

      One way you can remove an unwanted dependency is to use the Observer pattern – the dependency is pushed from inside the subject object to the client code that initialises the subject. The subject object exposes events in the code (such as before or after certain method calls) by calling a method notify(), this then notifies all observers that were set up at run time. The subject passes an instance of itself when each observer is notified so that whatever the implementation of the observer, it has full access to the context of when notify() was called. In (somewhat) simple terms, you pull out the line of code that is a dependancy, replace it with a call to notify(), then push the dependant code into an object that implements update() and attach this observer at runtime, we will use the interfaces provided by SPL – the Standard PHP Library, SplSubject and SplObserver.

      The Scenario

      Right, so I’ve tried to articulate this but as always a code example is best.  The scenario is as follows and is something I’ve seen numerous times: we have a symfony action that hits a web service and for this example just spits out the response.  There are Service classes (which I won’t show an implementation for as they’re simple) which basically contain some business logic, parameters, and endpoint details such as url and HTTP method.  The Client object takes a Service object and transport object (HTTP in this case) puts them both together and sends a HTTP request to the web service endpoint and returns the response.  Inside all of this is the need for logging so there is symfony specific code coupled to the cohesive and loosely coupled Client object. I’m going to show some example code and then refactor it till eventually the dependency is removed and the Observer pattern is implemented.  Obviously there are many ways to do this and many reasons for and against it.  Do not take this as dogma – it’s merely here to demonstrate an option you can take.  And none of this code is tested, just free styled.

      The Action

      The action simply chucks a Service and Http object into the client for it to use and calls it.

      The Client

      The ServiceClient takes an instance of a Service and a Http object which are injected at construction.  There’s an accessor and a mutator so the Service can be switched at runtime.  The main code is inside call() which sets up the Http request and returns the response.  You can also see we are logging the Service call details by getting the logger from sfContext - not nice.

      Refactoring out sfContext

      Nobody likes sfContext calls inside domain objects.  Fact.  So let’s make use of dependency injection and push it to the client code.  Here’s the new action and Client.

      That’s better than before but will still have the symfony dependency in the constructor and a call to a method named info(). This could be solved by using an adapter, but who said we wanted any logging inside this class in the first place? Services, Service Clients and Http objects are all fairly cohesive, logging is not.

      Implementing the Observer pattern

      Shit just got real. We’ll now modify the Client so it implements SplSubject, the interface so kindly provided by PHP’s SPL. We’ll create a new Observer object that implements SplObserver and push the logging to it, then all that’s left is to modify the action code. So first up is the Client.

      You can see we are implementing the SplSubject interface where we have to declare 3 methods, attach(), detach() and notify(). As we are a subject we need to maintain an array of Observers, we do this by using a hash of the object as a key to the array which allows us to easily detach() it. notify() is our event where we loop over each Observer calling update() and passing them the current instance so they have full access to the context of when notify() was called. We call notify at the last moment so the observer has more information and available to it (thanks dol).

      Next up the Observer.

      Here you can see the object has one clear role – to use symfony’s logger and the Subject that we passed in (our Client) to log details about the Service that was called. We could easily create another Observer that uses Zend’s logger or create something that has a function other than logging. The point is we pushed the symfony dependency from inside the Client object into a separate, decoupled object.

      And finally the action that brings it all together.

      You can see we construct our Client with 2 cohesive objects then attach an Observer directly after. We know that when notify() is called our logger will log details of the Service that was called. We’ve pushed the dependency out of the domain object and up into client code so that the domain object is no longer coupled to symfony, we could use it with Zend if we really wanted to (but probably don’t). As mentioned before, we could attach multiple Observers each with slightly different functionality. All we know is that each Observer wants to do something at the point that notify() was called. Nuff said.

      • views
      • Tweet
    • 0
      13 Apr 2011

      Shoreditch PHP?

      • Edit
      • Delete
      • Tags
      • Autopost

      If you've got a decent PHP contract in the Shoreditch area, hook a brother up.  I want to ride my fixie bike to work.

      20100129-old-street-map

      • views
      • Tweet
    • 0
      24 Apr 2010

      Make Symfony respond to a HTTP PUT or HTTP DELETE request

      • Edit
      • Delete
      • Tags
      • Autopost

      Whilst developing a RESTful API at work, I ran into a small ‘feature’ of Symfony 1.4 which required digging into the sourcecode.  I was trying to use the pecl_http HTTP class to make GET, POST, PUT and DELETE requests - the GET and POST worked fine with Symfony populating the request with the correct variables, but PUT and DELETE didn’t want to play ball leaving the request parameters empty.

      Turns out Symfony requires you to specifically set a Content-Type Header and have it’s value be set to application/x-www-form-urlencoded.

      So a route specified as such:

      foo_put:
        url:   /foo
        class: sfRequestRoute
        param: { module: foo, action: put } 
        requirements:     sf_method: [put]
      

      With an action that wants to access the content parameter:

      
      
      public function executePut(sfRequest $request) {
          echo $request->getParameter('content');
      }
      
      
      

      Will work correctly with the following pecl_http HTTP client code:

      $request = new HttpRequest('http://symfony/foo', HTTP_METH_PUT);
      $request->setHeaders(array('Content-Type' => 'application/x-www-form-urlencoded'));
      $request->setPutData('content=bar');
      $response = $request->send();
      

      The same also goes for a HTTP DELETE request (the client code will obviously be different but the Header needs to be set the same way).  GET and POST requests don’t need anything special.

      • views
      • Tweet
    • 0
      8 Mar 2010

      Install PHP 5.3 on Ubuntu Karmic Koala from dotdeb packages

      • Edit
      • Delete
      • Tags
      • Autopost

      First up, add the dotdeb repository.

      Fire up vim and add the following 2 lines to /etc/apt/sources.list:

      deb http://php53.dotdeb.org stable alldeb-src http://php53.dotdeb.org stable all

      Now do a sudo apt-get update to update your packages.  The next step may fail but give it a go anyway.

      Use Aptitude to install the PHP 5.3 packages.

      sudo aptitude install php5-cli php5-common php5-cgi php5-mysql php5-curl libapache2-mod-php5 php5-memcache php5-xdebug

      If this goes through ok, well done!  In my case I had dependency issues that could not be satisfied.  The package libicu38 was needed but could not be found in the repos in my sources.  I did a quick google and could see that libicu38 had been taken out of Karmic but was available in Jaunty security, so add that repo to the sources file:

      deb http://security.ubuntu.com/ubuntu jaunty-security main

      Now do a apt-get update and then:

      sudo aptitude install libicu38

      Now go back to the previous step and try to install the PHP 5.3 packages again, hopefully they should work now.

      You can now try and see if php 5.3 is working, issue php -v at the command line and see if it works correctly, once working you’ll get:

      PHP 5.3.1-0.dotdeb.1 with Suhosin-Patch (cli) (built: Dec  5 2009 20:08:29) Copyright (c) 1997-2009 The PHP GroupZend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies with Xdebug v2.0.5, Copyright (c) 2002-2008, by Derick Rethans with Suhosin v0.9.29, Copyright (c) 2007, by SektionEins GmbH

      In my case I had a couple of errors that needed fixing - PHP complained about a date setting and xdebug also shouted a bit.  They were easily fixed.

      Edit xdebug.ini.

      Fire up vim and edit /etc/php5/conf.d/xdebug.ini, you need to change the extension line so it’s a zend_extension and maybe also set the full path to the xdebug.so file (depending on if you set your include path in php.ini):

      zend_extension=/usr/lib/php5/20090626+lfs/xdebug.so

      Edit php.ini.

      vim /etc/php5/apache2/php.ini and find the line that starts with ;date.timezone and change it to:

      date.timezone = Europe/London

      To get xdebug to work correctly you need to enable html errors:

      html_errors = On

      Finally do a sudo apache2ctl restart and everything should be working!

      • views
      • Tweet
    • Search

    • My Sites

      • James Morris
      • Mixcloud Downloader
      • Shoreditch Vietnamese
      • I HEART Shoreditch
    • Tags

      • Symfony2
      • ubuntu
      • FOSUserBundle
      • clouddownload.co.uk
      • roles
      • shoreditch
      • symfony
      • 301
      • SplObserver
      • SplSubject
      • android
      • api
      • codename
      • command
      • console
      • contract
      • cucumber
      • delete
      • docky
      • dotdeb
      • errors
      • exif
      • firewatir
      • foursquare
      • http
      • imagick
      • iphone
      • mario
      • maverick
      • mixcloud
      • netbeans
      • news
      • nginx
      • observer
      • php 5.3
      • pidgin
      • poker planning
      • put
      • ruby
      • scrum
      • session
      • shit
      • shoreditchvietnamese.co.uk
      • skype
      • stripImage
      • sudo gem update --system
      • super hub
      • twitter
      • version
      • vietnamese
      • virgin media
      • watir
    • Archive

      • 2011 (22)
        • December (3)
        • November (4)
        • September (3)
        • August (3)
        • July (1)
        • May (2)
        • April (4)
        • March (1)
        • January (1)
      • 2010 (1)
        • April (1)
    • Contributors

      James Morris
    • Obox Design
  • James Morris - JMOZ


    30382 Views
  • Get Updates

    Subscribe via RSS
    TwitterFacebookLinkedIn