Archive for the ‘web development’ Category

Create a custom dojo build

Sunday, July 25th, 2010

When you develop an application with dojo, you can pretty quickly end-up with tens of http calls to load all dojo.require() files on demand. In my case, for a simple script relying on dijit.Dialog & dijit.Tooltip, firebug reporting more than 25 http calls for individual files. In production, this is not optimal at all.

So we will try to use dojo utilities to create our custom dojo file containing all (and only) the required dojo code into a single file. Problem is that there is scarce help on this matter on the Internet and official documentation is not correct!

Here are the steps:

  1. download a dojo- SDK (or “source-release”) (http://dojotoolkit.org)  (the uncompressed code is not enough), it contains data required to create dojo builds
  2. ensure java 1.4.2 or later is set up on your computer
  3. unzip dojo sdk file and go to: cd <dojo_folder>/util/buildscripts
  4. now create a new file that you will save wherever you want and call it “myapp.profile.js
    In this file we will put the following content:

    dependencies = {
    layers:
    [
    //This layer is used to discard modules
    //from the dojo package.

    {
    name: "dojo.js",
    customBase: true,
    discard: true,
    dependencies:
    [
    "dojo._base"
    ]

    },

    //This layer is used to discard modules
    //from the dijit package.

    //Custom layer mydojo.js which
    // includes our custom Dojo artifacts
    {
    //place the file under dojoRootDir
    name: “../../mydojo.js”,
    layerDependencies:
    [
    "dojo.js",
    ],
    dependencies:
    [
    //modules to be included from the
    //custom project. You can probably
    //list a single module here which in
    //turn declares all the required
    //modules as opposed to listing all the
    //modules individually. Please take a
    //look at dojoRootDir/dojo/_base.js
    //file for an example.
    // "dojo._base"
    "dijit.Dialog",
    "dijit.Tooltip"

    ]
    }
    ],

    prefixes: [
    ["dijit", "../dijit"],
    ["dojox", "../dojox"]
    ]

    }

  5. customize this file as you wish, basically simply list all the module you need where I put dijit.Dialog & dijit.Tooltip. Do not worry about modules required by these two modules, they will be automatically inserted by the build script!
  6. now run the following command:
    ./build.sh profileFile=<path_to_myapp.profile.js> action=clean,release releaseName=cusomizedDojo
  7. wait a few minutes (maybe more!)
  8. when the script has finished running, go up to dojo-root folder, a new folder named ‘release’ has been created, your dojo code is in there! The file you’re interested into is at the root of this folder and is named ‘mydojo.js’ or whatever name you put in your profile file.
  9. That’s it!

One-step further

At this point, we have generated a mydojo.js file containing all shrinked code for our dojo modules. Problem is that it does not contain dojo.js itself! It tried to include ‘dojo._base’ as a required module but it did not work. What I did was simply to open dojo.js in a word editor, copy its content and paste it at the top of mydojo.js file.

Now you have all your dojo-related js code in a single file! Exactly what we wanted.
If we insert this file in our code, replacing regular dojo.js file, we can see in firebug that no-more http calls are made!

Important notice

In my case, a folder named ‘nls’ was generated. It seems that this folder content cannot be incorporated into the single js file by build-script => I left it on its own in my /js folder and a single http call is made to retrieve the content of appropriate language file. A single extra http-call seems acceptable to me so  I left it this way.

Illustration

Before:

After:

Woooow! this is far better.

sources

How to restore mysql databases using raw files?

Thursday, June 17th, 2010

My server was recently hacked (damn it!), I tried to restore mysql dbs using my regular backup procedure to find out that mysql-dump backup was not working properly => unique solution remaining, restore mysql db from raw files (located into /var/lib/mysql).

Copying & pasting /var/lib/mysql folder did not make it, neither a copy & paste of only my own db folders. What I had to do was the following:

  1. reinstall mysql as usual (apt-get install mysql) and changing root password (along with password for all user-apps as well) <= the server was hacked!
    note: update your app code to reflect new db credentials
  2. log into mysql and recreate through sql queries all my dbs (create database <db_name>;)
  3. create app-users as well
  4. exit mysql
  5. copy your raw db folders and replace those that mysql has just created
  6. restart mysql daemon (/etc/init.d/mysql restart)

That should work.

sources

How to retrieve list of mysql users?

Thursday, June 17th, 2010

Mysql users are stored into ‘mysql’ db and ‘user’ table, therefore to retrieve the list of all registered users, simply execute the following query:

select * from mysql.user;

or, for a less detailed list:

select User, Host, Password from mysql.user;

sources

set php include_path variable directly from apache

Monday, May 10th, 2010

This tip is useful when you have several projects on the same server.

To set a php ‘include_path’ customized to each project, in your <VirtualHost *:80> (or equivalent) definition, simply add:

php_value include_path ".:/path/to/site:/another/path"

save your changes, check your config (sudo apache2ctl configtest) and restart apache (sudo /etc/init.d/apache2 restart).
That’s it.

sources

How to use/write resource plugins with Zend_Application

Sunday, May 2nd, 2010

(apply to ZF v1.10)

You have two types of resources:

- class resources (those methods that you define in your Bootstrap class and that starts with ‘_init’)
- plugin resources (those that you define externally and can trigger via application.ini file)

How do you automatically load an external resource from application.ini file?
This is pretty simple indeed. You only have to declare your resource in your config file as follow: “resource.<resource_name> = true”
note: we added ” = true” because otherwise our line would have been ignored since no value was defined to our <resource_name> variable. In next section, we will add some parameters therefore making explicit use of ” = true” useless.

How do you provide options to  your own external plugin resource?
Anything that will come after ‘resources.<resource_name>’ in your application.ini file will be considered an option and provided to your external resource upon instanciation.
If I write

resources.myplugin.option1 = 1
resources.myplugin.option2 = 2

Then ‘myplugin’ is automatically registered and will be instanciated with following options array ['option1' => 1, 'option2' => 2, 'bootstrap' => Object]
note: ‘bootstrap’ entry is automatically created by ZF (Zend_Application_Bootstrap_BootstrapAbstract) and therefore available to all plugins. It contains an instance of the bootstrap object.

Example:

in my application.ini, I have:

resources.db.adapter = “PDO_MYSQL”
resources.db.params.host = “localhost”
resources.db.params.username = “user”
resources.db.params.password = “pwd”
resources.db.params.dbname = “mydb”

Then what’s going to happen is:

  • Zend_Application_Resource_Db plugin will automatically get registered and bootstrapped
  • Options passed to Db plugin upon instanciation is an array:
    [
    'adapter' => 'PDO_MYSQL',
    'params' => [
      'host' => 'localhost',
      'username' => 'user',
      'password' => 'pwd',
      'dbname' => 'mydb'],
    'bootstrap' => Object
    ]

    note: for bootstrap entry, see above comment

How do you use Router resource?

ZF online documentation still contains example for old routing (ie. as it was performed prior to introduction of Zend_Application and external resources). Now it’s better to call external resource plugin rather than configure your Zend_Controller_Front as done previously.

To do this, it’s pretty simple. You can rely on examples provided in online documentation (http://framework.zend.com/manual/en/zend.controller.router.html), the only change that you have to do is to prefix all ‘routes’ entry in your application.ini file with ‘resources.router.’.

Thus,

routes.login.type = “Zend_Controller_Router_Route_Static”
routes.login.route = “login”
routes.login.defaults.controller = auth
routes.login.defaults.action = login

becomes

resources.router.routes.login.type = “Zend_Controller_Router_Route_Static”
resources.router.routes.login.route = “login”
resources.router.routes.login.defaults.controller = auth
resources.router.routes.login.defaults.action = login

That’s it. You don’t have to worry about anything else, a router instance is automatically created and your routes should be active now.

How do you use Log resource via .ini configuration?

In my case, I defined it this way:
resources.log.stream.writerName = “Stream”
resources.log.stream.writerParams.stream = APPLICATION_PATH “/../logs/app.log”
resources.log.stream.filterName = “Priority”
resources.log.stream.filterParams.priority = Zend_Log::WARN

Where can you access all instances used by external resource plugins?
Db plugin instanciates a Zend_Db_Adapter object, Log plugin instanciates a Zend_Log object, and so on…
Everytime a ->init() method of a resource plugin returns a value, this value is store in a container currently being a Zend_Registry instance (but not singleton).
As a consequence, once Db resource has been bootstrapped, you can access create db adapter instance in $bootstrap->getResource(‘db’); (and $boostrap->getResource(‘log’) for Log instance!)

How do you write your own external plugins?

  1. create your class extending Zend_Application_Resource_ResourceAbstract
  2. ensure your class implement ->init() method, which should perform all your bootstrapping and might return an instance to a shared object
  3. declare your plugin prefix and plugin path into application.ini:
    pluginPaths.My_Plugin_Prefix = APPLICATION_PATH "/path/to/my/resource/plugin/directory"
  4. call your plugin resource from application.ini:
    resources.myResource = true

    note: you can add parameters to this call (as explained above) that will be available in your resource plugin class via ->getOptions() method

Warning

  • execution order: by default, class resources get executed first
  • name overlapping: if your class resource has the same name as your external plugin resources, only your class resource will get executed
    example: in my Boostrap class, I have a method name ::_initDb() and in my application.ini file I initialize external Db resource (via ‘resources.db.xxx’ call), only my _initDb() will get executed. External plugin will simply be ignored
    => make sure you do NOT use the same name for your class resources and external plugin resources

sources

Zend Framework: remove call to favicon.ico via .htaccess file

Sunday, May 2nd, 2010

Almost all browser makes a query for /favicon.ico file.
When you use ZF, all your queries that do not match an existing physical file are rerouted to your bootstrap file and therefore go through your entire app to end-up in a 404 error.

Well this is a waste of computing resources and above all can drives you crazy when you’re tracking errors. You might not understand why your query runs twice on a single page load…

A quick and easy way to fix this is simply to create an empty file, name it ‘favicon.ico’ and place it in your /public folder.
If you want to skip the request call via .htaccess instead, simply preprend the following line to your rewrite condition:

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/favicon.ico$ [OR]
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

That’s it.
Good luck.

sources

multiple sections in an .ini file

Sunday, May 2nd, 2010

When you define an .ini file, you can divide your content in sections so that you can load on some sections or you can even implement section inheritance so that you have customized values based on your given configuration.

Lets’ see a quick example:

$ini = <<<EOF
[base]
host=localhost
user=testuser
pass=testpass
database=default

[users:base]
database=users

[archive : base]
database=archive
EOF;

$opts = parse_ini_string($ini, true);
var_dump($opts);

//output
array(3) {
  ["base"]=>
  array(4) {
    ["host"]=>
    string(9) "localhost"
    ["user"]=>
    string(8) "testuser"
    ["pass"]=>
    string(8) "testpass"
    ["database"]=>
    string(7) "default"
  }
  ["users : base"]=>
  array(1) {
    ["database"]=>
    string(5) "users"
  }
  ["archive : base"]=>
  array(1) {
    ["database"]=>
    string(7) "archive"
  }
}

Inheritance mechanism is implemented in Zend Framework through Zend_Config_Ini class.

Splitting a section in multiple parts

Unfortunately splitting a section in multiple parts might not work as expected. Your entire section is overwritten and no simply merged.

Let’s have a quick look:

$ini = <<<EOF

[base]
host=localhost
user=testuser
pass=testpass
database=default

[users : base]
database=users

[archive : base]
database=archive

[base]
koko=kiki
EOF;

$opts = parse_ini_string($ini, true);
var_dump($opts);

//output
array(3) {
  ["base"]=>
  array(1) {
    ["koko"]=>
    string(4) "kiki"
  }
  ["users : base"]=>
  array(1) {
    ["database"]=>
    string(5) "users"
  }
  ["archive : base"]=>
  array(1) {
    ["database"]=>
    string(7) "archive"
  }
}

too bad…

sources

    control mysql & apache logging level

    Thursday, March 11th, 2010

    If you want to avoid ‘too many connections’ error due to a full-disk error, you should consider modifying your mysql/apache log settings.

    MySQL

    First we will check our running log settings, then we will see how to change them permanently.
    To do this, we will need the help of ‘mysqladmin’ available within mysql-client package

    1. sudo apt-get install mysql-client-5.1
      update this command to match your mysql version
    2. mysqladmin variables -u mysqlusername -p  | grep log
      then enter your mysql user password when requested
      In my case:

      | log | OFF |
      | log_bin | OFF |
      | log_bin_trust_function_creators | OFF |
      | log_bin_trust_routine_creators | OFF |
      | log_error | /var/lib/mysql/r12925.ovh.net.err |
      | log_output | FILE |
      | log_queries_not_using_indexes | OFF |
      | log_slave_updates | OFF |
      | log_slow_queries | OFF |
      | log_warnings | 1 |

      In my case, log_warnings is set to ’1′ which leads me to sporadic ‘disk-full’ errors => I will disable log_warnings.

    3. We can disable log_warnings by adding a new line with “log_warnings = 0″ into /etc/mysql/my.cnf under [mysqld] section
    4. Restart mysql deamon (sudo /etc/init.d/mysql restart)
    5. Check again your configuration variables as described in step2, my output now is:

      | log_warnings | 0 |

    That’s it.

    Apache

    For apache, simply do the following:

    1. add a new line with “LogLevel crit” into /etc/apache2/http.conf
      apache will log only critical errors (and above)
    2. ensure your configuration is ok, run:
      apache2ctl configtest
    3. if everyting is ok, restart apache:
      sudo /etc/init.d/apache2 restart

    That’s it

    sources

    unable to stop / start / restart mysql server

    Thursday, March 11th, 2010

    Each time I tried to stop / start /restart mysql server, it ended in a ‘failed!’ message: Starting MySQL

    database server: mysqld . . . . . . . . . . . . . . failed!

    I killed it through its pid, updated mysql package and it was unable to start again!!!!!

    After looking at /var/log/syslog, I had multiple error messages such as:

    error: ‘Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’

    mysql invoke-rc.d: initscript mysql, action “start” failed

    After a couple of hours, I tried quick and dirty fix advised here (http://www.debianhelp.org/node/1962), I simply remove my mysql config file:

    sudo mv /etc/mysql/my.cnf /etc/mysql/my.cnf.customBackup

    After this, I was able to restart mysql (safely restart mysql through ‘sudo mysqld_safe‘ command).

    note1: it seems source of the problem was that I kept my old mysql configuration file when upgrading from mysql5.0 to mysql5.1
    So far I have not found any mysql config file checker as it can exist for apache2 (“apache2ctl configtest”)

    note2: recommended step is now to use default my.cnf file (sudo cp /etc/mysql/my.cnf.dpkg-dist /etc/mysql/my.cnf) and configure it the way you want

    sources

    ZF: Zend_Rest_Client::restDelete() ‘Unexpected error: No Method Specified’

    Thursday, March 4th, 2010

    When using Zend_Rest_Client & Zend_Rest_Server with ZF v1.10.2, to quickly build a Rest webservice, performing simple restDelete() queries ended up with following error message:

    Unexpected error: No Method Specified

    In fact, current implementation of Zend_Rest_Client::restDelete() does not provide any request parameter to queried url.
    On server side, Zend_Rest_Server expects the ‘method’ argument to be provided => above error is generated.

    To avoid this problem, I had to update Zend_Rest_Client with following updated method:

    /**
    * Performs an HTTP DELETE request to $path.
    *
    * @param string $path
    * @param array $query Array of GET parameters
    * @throws Zend_Http_Client_Exception
    * @return Zend_Http_Response
    */
    final public function restDelete($path, $query = null)
    {
    $this->_prepareRest($path);
    $client = self::getHttpClient();
    $client->setParameterGet($query);
    return $client->request('DELETE');
    }

    note: subclassing the class was not an option since most of its methods are ‘final’! Grrrr…

    For more information, look at corresponding tickets (see links below)

    sources