Piotr Gabryjeluk blog

Doctrine PHP

1225396135|%e %B %Y

A few days ago, I found Doctrine Project which is an object-relational mapping (ORM) solution for PHP. It seems really powerful and actually very similar to Wikidot DB Layer (especially one in Wikidot 2).

Doctrine is a really cool project and has features of:

  • Wikidot DB
  • Zend Framework DB
  • Hibernate (ORM for Java)
  • Ruby on Rails DB

Let's start from the beginning of the list.

Doctrine is most similar to Wikidot DB, because both:

  • are ORM implementations for PHP
  • use abstract (non-PHP, non-SQL) data definition language
    • for Wikidot it's XML-based format
    • for Doctrine it's YAML-based one

It's similar to Zend Framework DB, because of:

  • using magic PHP methods for accessing objects properties

Hibernate and Doctrine shares:

  • completeness of the DB layer
  • higher abstraction than other DB layers

Ruby On Rails concepts in Doctrine:

  • using YAML as a model definition language
  • independence of database engine

Example of model definition:

User:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    login:
      type: string(64)
      unique: true
      notnull: true
    realname:
      type: string
    password:
      type: string(64)
      notnull: true
    im:
      type: string(64)
    token_active:
      type: string
    token_created:
      type: timestamp

Bet:
  columns:
    id:
      type: integer
      primary: true
      autoincrement: true
    brand:
      type: string(100)
      notnull: true
    qty:
      type: integer
      default: 1
      notnull: true
    unit:
      type: string(100)
      notnull: true

BetUser:
  columns:
    bet_id:
      type: integer
      primary: true
    user_id:
      type: integer
      primary: true
    wins_if:
      type: string
      notnull: true
  detect_relations: true

Doctrine comes with a CLI tool, that offers the following things:

Doctrine Command Line Interface

./doctrine.php create-tables
./doctrine.php rebuild-db
./doctrine.php generate-models-db
./doctrine.php generate-models-yaml
./doctrine.php generate-yaml-db
./doctrine.php load-data
./doctrine.php build-all-load
./doctrine.php generate-migrations-models
./doctrine.php build-all
./doctrine.php create-db
./doctrine.php migrate
./doctrine.php generate-yaml-models
./doctrine.php dump-data
./doctrine.php dql
./doctrine.php generate-migrations-db
./doctrine.php compile
./doctrine.php generate-sql
./doctrine.php drop-db
./doctrine.php generate-migration
./doctrine.php build-all-reload

The tool can be used to generate PHP files from YAML files, generate SQL files (for given DB engine), drop and create the database and more.

The dql seems to be an interesting option. Doctrine supplies its own backend-independent SQL-like language for querying and updating the DB. These operations can be done with the dql option. Although I haven't tested it yet, it seems perfect for some cronjobs or other automatic tasks that don't need to be coded in PHP.

<OFF-TOPIC>
Now, I'm converting my nuclear project — opiwo.com (bet a beer in Polish) to Doctrine ORM (from Zend Framework's one) to see how it works in reality. The project uses also other nice technologies like JSON-RPC.

I'm willing to minimize the work needed to launch it soon, by using bleeding edge technologies and web service programming concepts. The whole user interface part is programmed in JavaScript, jQuery (with many plugins) and static HTML files. Only pure data is fetched from server (with JSON-RPC). This gives more power to the server and user more responsive interface to the user. On the other side, the website may be more CPU-intensive (I hope not too much).
</OFF-TOPIC>

Please forgive me I'm now quite excited about the Doctrine. It's just how I react to some really cool (well-designed) things. I hope it's really that cool :).

Comments: 2, Rating: 1

Django-like routing in PHP

1215273992|%e %B %Y

As I've recently work with Django, the way it does the URL-based routing seemed really cool for me. I missed that in PHP, so I decided to code something like this.

Here is a class that uses (extends) my Controller class that does the routing:

<?php
 
class Controller_Ajax_Auth extends Controller_Ajax {
    protected $routes = Array(
        ':^info$:'                => 'info',
        ':^challenge$:'            => 'challenge',
        ':^login$:'                => 'login',
        ':^logout$:'            => 'logout',
    );
 
    protected function info($url) {
        $r = Array();
        /* something */
        $this->ajaxResponse($r);
    }
 
    protected function challenge($url) {
        /* $q = something */
        $this->ajaxResponse($q);
    }
 
    protected function login($url) {
        /* set $auth to true if logged */
        $this->ajaxResponse($auth);
    }
 
    protected function logout($url) {
        /* logout */
        $this->ajaxResponse(null);
    }
}

This mainly routes URLs info, challenge, login and logout to corresponding methods in the same object.

But you can route out of the object to other Controller subclass instance:

    protected $routes = Array(
        ':^auth/(.*)$:'            => 'Controller_Ajax_Auth',
    );

This gets URL and passes what's after auth/ to the new object of class Controller_Ajax_Auth (see the code above). Generally the first ()s in the left side of each line define what's passed to the method/object on the right side.

The controller has abstract errorHandler and defaultAction methods that need to be overridden. The first is called when a exception is thrown in a performed action. The latter is called, when routing comes to some object and then no routing line matches.

Comments: 1, Rating: 0

Mirror Server

1214312135|%e %B %Y

Today I've (almost) managed to create a mirror server for wikidot.com service.

Features:

  • CentOS distribution
  • almost live Wikidot read only mirror
  • database is replicated from the original service in real time to this server
  • user uploaded files are replicated in real time to this server using FS mirror
  • avatars are to be mirrored with rsync every now and then
  • uses Portable IP address: 67.228.37.27
  • lighttpd serves ALL content with FastCGI PHP
  • database is read-only (as being replication slave)
  • CVS configured to use SSH keys (no password asking)
  • Wikidot PHP source mainly from the current production server
  • Improvements (from CVS): uploaded files served like in OpenSource version

Problems:

  • FS mirror is not 100% exact, it may not synchronize some (little fraction of) files every now and then, so we must rsync them additionally, to make sure nothing's lost
  • if you were logged in to Wikidot before, it'll complain about not being able to write to ozone_session (because it's read only)
  • Flickr Gallery not working and causing the whole page to display just nothing
  • magic file recognition not working (it may be a problem in PHP configuration or an extension):
PHP Warning:  finfo_open(): Failed to load magic database at '/usr/share/misc/magic'. in /var/www/www.wikidot.com/wikidot/php/utils/- on line 3
PHP Warning:  finfo_file(): supplied argument is not a valid file_info resource in /var/www/www.wikidot.com/wikidot/php/utils/- on line 4
PHP Warning:  finfo_close(): supplied argument is not a valid file_info resource in /var/www/www.wikidot.com/wikidot/php/utils/- on line 5

UPDATE: Flickr problem solution:

  1. yum install php-pear-HTTP-Request
  2. chgrp lighttpd /var/lib/php/session

Remember:

  • when switching to mirror, we must restart memcached (or force to invalidate every item in it)

Comments: 2, Rating: 0

page 3 of 3« previous123

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License