Monday, November 28, 2011

Creating utf-8 tables in symfony 1.4 /doctrine 1.2

Recently I had an issue on one of my work websites where the database schema was setup in Latin-1 encoding, this was fine till the encoding of the website was also set to iso-8859-1 and nothing fancy was going on. However later in the last few months, I had been doing some development which required me to change the encoding to utf-8 and that resulted in a lot of issues. Some I am still resolving. One of the two solutions that we came up was assign it a custom function for 'escaping_strategy', which however wasn't the silver bullet to fix as there was more crazy code that was getting raw value from the model and hence our function would get by passed. I am still looking for better ways of fixing it (seems very likely a case of massive re-factoring required) however, this one tip was handy.

If you want to create an individual table to be utf-8 then in the schema.yml you can add.

?

1

2

3

4

5

6

7

8

User:

  options:

    type: MyISAM

    collate: utf8_unicode_ci

    charset: utf8

  columns:

    username: string(255)

    password: string(255)

However this can be a painful repetitive task, especially if you have loads and loads of tables to work with. In case you are like me and prefer all your tables to be utf-8 by default, you can add this function to your ProjectConfiguration.class.php file.

?

1

2

3

4

5

public function configureDoctrine(Doctrine_Manager $manager)

{

  $manager->setCollate('utf8_unicode_ci');

  $manager->setCharset('utf8');

}

and then rebuild all the models (and possibly load your fixtures if you have any.

?

1

# symfony doctrine:build --all --and-load --env=dev --no-confirmation

Obviously bare in mind that this will drop your database and re-create the tables with utf-8 encoding.

If anyone has any suggestions for my problem, do leave a comment.

How to Enable Local SMTP (Postfix) on OS-X Leopard

OS-X Leopard comes pre-installed with a Postfix version. No need to install it via darwin ports or other such mess (actually uninstall it if you have previously manually installed it via ports or something similar). Postfix just needs to be enabled and following sequence of several easy steps explains how to do it:

 sudo vi /System/Library/LaunchDaemons/org.postfix.master.plist 

add following line before the closing </dict> tag:

<key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> 

Start service with

$ sudo launchctl launchd% start org.postfix.master 

You can also start simply with "sudo postfix start" but the above command will start via launch sequence and test the configuration you edited in the previous step.

Check that SMPT is running:

telnet localhost 25 

For more information, see: Mac OS X Manual Page For launchd.plist

Symfony : Radio Widgets with formatting, radio_list formatter

symfony provides concept of widget. it's just like a sub-framework that provide classes to output HTML fields like input, textarea, select, radio etc...

Suppose you want to create widgets for the set of radio buttons with the option of html formatting of the radio button. creating a form class in module lib directory say Itinerary.Form.class.php
// Itinerary.Form.class.php
class ItineraryForm extends sfForm
{

  public static function radioFormatter($widgets, $inputs)
  {
    $rows = array();
    foreach ($inputs as $input)
    {
      $rows[] = $input['input'].$input['label'];
    }
    return "".implode("", $rows)."";
  }

  public function configure()
  {
      $tourTipChoice    =    array(
                                                         'tourItinerary'                => 'Itinerary',
                                                         'InclusionsExclusions'=> 'Inclusions/ Exclusions',
                                                         'sightSeeing'                 => 'Sightseeing'
                             );

    $this->setWidgets(array( 'tourTip'   => new sfWidgetFormSelectRadio(array(
'choices'                => $tourTipChoice,
                                                                              'formatter'            => array($this, 'radioFormatter')
                                                                             ))
                      ));

    $this->validatorSchema->setOption('allow_extra_fields', true);       
    $this->validatorSchema->setOption('filter_extra_fields', false);
    $this->setDefault('tourTip', 'Itinerary');
  }
}

after that just creating the object this class in action.class.php.
suppose you want to render the widget in your index file. so just create object inside the index funciton like as :
public function executeIndex(sfWebRequest $request)
  {
      $this->form = new ItineraryTourForm();  //Used to call form widgets
  } 

now you have to call only the function inside template i.e. in indexSuccess.php

echo $form['tourTip']->render(); 

It will render the  radio button list in the vertical format as we set in formatter. If we want to add other event on the radio button like onclick(), onsubmit() etc... i.e.

echo $form['tourTip']->render( array('onclick'=> 'showtourTip(this.value);'));

Tuesday, November 22, 2011

Using Subversion without a Subversion server

For a while now I've been using Subversion locally for version control on some of my small projects, but recently realized that I've been using it in a way that many people may not know is possible.  I use Subversion without actually having a Subversion server anywhere in sight.  How is this possible?  Simple!

A Subversion repository is merely a set of files that hold all the information about the files, changes, and even users.  The Subversion server is merely a gateway between the client and the repository files.  If you take out the server and point the client directly the repository files, it will be right at home!

Some of the advantages of using Subversion this way are:

  • No software to install, configure, eat resources, or open any ports!
  • Flat file based.  Want to move your repositories elsewhere?  Just move the files!
  • Can place your repositories on a NAS device, USB drive, even USB memory stick.  Since there is no software, the NAS device doesn't have to have a built-in Subversion server or any junk like that.
  • Wanted them internet accessible.  I have my repositories placed on my NAS device, so if I am out and about and need to get an update, I can just VPN into my home router, and then access it on the NAS device as if I was at home on the network.

So how can you configure Subversion to work this way?  Follow these steps:

  1. Install TortoiseSVN.  It rocks.
  2. Go to a place where you want the repositories to reside.  These will not be your live usable files, these will be the files that are a part of the repository file structure.
  3. Create a new empty folder and use the name of the repository you want to create.
  4. Go into the folder, right click, and go to TortoiseSVN -> Create repository here.  Choose the Native filesystem.
  5. Go to where you want your live, usable files to be and create a new folder for them.
  6.  Go into the new folder, right click and go to SVN Checkout.  The URL of the repository will follow the "file://" pattern.  Your base URL is "file:///" (yes, three slashes).  From there, you will use your standard file path, leaving out any semi-colons (:) and changing "\" to "/".  So if you created a repository at D:\repositories\test, you would use "file:///d/repositories/test".  If you created the repository on another system or on a NAS device, where your address would normally be "\nas-device\repositories\test", you would use "file://///nas-device/repositories/test" (yup, 5 slashes).

One important thing to note about using Subversion this way is that there is limited security when working this way.  Anyone who has access to the files will be able to get the files and make check-ins.  If you wish to limit access, the best way would be through filesystem permissions.  Additionally, on a network share or NAS box, you could require user logins to get access to the files.  Another thing is that user tracking uses the username of the user on the Windows machine.  You can still track who checked in what, but it gets the username automatically, without doing any user authentication on the repository.  It will ignore the repositories conf\svnserve.conf and conf\passwd settings.

The URLs you enter may not be the clearest, but this is by far the simplest way to get up and going with Subversion for your own personal use.  My own repositories are kept on my NAS box, accessible from both my desktop and my laptop, and can even get on it remotely by VPN.  All with zero install and configuration.

Friday, November 18, 2011

symfony mac xampp no database connection

if you installed xampp on mac then try to use cmd to build symfony project. you will find symfony can not connect to the database

the trick is to set host to 127.0.0.1 instead of localhost in databases.yml

sfAdminDashPlugin no menu item

when using sfAdminDashPlugin, after config, there's no menu item

make sure you setup sfDoctrineGuardUser properly for backend

and MAKE SURE you are logged in

then you'll be sweat

Tuesday, November 08, 2011

How to Write a symfony Plugin

One of the main things that makes symfony great is its thorough, clearly-written documentation. However, the documentation on how to write a plugin seems a trifle incomplete, so I will attempt to supplement it here by writing a comprehensive, step-by-step tutorial.

First let me point out what is already out there. The official documentation on how to write a symfony plugin is here. There is also a slideshow here (apparently authored by Fabien himself) that sheds some more light on the subject. Using these two sources I was able to piece together a plugin of my own but it took some head scratching. My goal here is to walk you through the plugin creation process with minimal cognitive strain.

The Plugin: jsHelloWorldPlugin

The plugin we will write today will be called jsHelloWorldPlugin. A quick note about the name: The "sf" prefix is reserved for symfony-ordained plugins. I chose "js" for my initials but the first two letters can, of course, be whatever you want them to be. The name of the plugin should end in "Plugin".

To keep things simple, we'll have this plugin perform one simple (and classic) task: print "Hello, world!" to the screen. We'll accomplish this by creating a symfony task.

Installing sfTaskExtraPlugin

The sfTaskExtraPlugin has a nifty task bundled with it that lets you kick off your plugin creation by running a simple command. Let's start by installing that:

$ php symfony plugin:install sfTaskExtraPlugin 

Generating the Task

We can now generate the plugin by running the following command:

$ php symfony generate:plugin jsHelloWorldPlugin 

Writing the Task

Next we'll create a task. As you can see in the symfony task documentation, you can create a task using generate:task. We'll call our task helloWorld, so we'll run this command:

$ php symfony generate:task helloWorld

This generates a task at lib/task/helloWorldTask.class.php. This isn't ultimately where we'll want it but we'll leave it there for now while we get the task working. Since all we need to do is print "Hello, world!", let's clear the contents of the execute() method and put our own code in:

 protected function execute($arguments = array(), $options = array()) {   echo 'Hello, world!'."\n"; }

Let's see what happens when we try to run the task:

 $ php symfony helloWorld Hello, world!

Success! Now that we have that task working, let's move it from our project and into our plugin. First we'll have to create a lib/task directory in our plugin folder:
$ mkdir plugins/jsHelloWorldPlugin/lib/task
Now let's move the task:
$ mv lib/task/helloWorldTask.class.php plugins/jsHelloWorldPlugin/lib/task/
If you try to run the task again, you'll notice that it won't work. That's okay. We have to install the plugin properly in order for the task to work again.

Getting the Plugin Ready For Installation

There are certain things that need to (or at least should) be in place in order for people to be able to install our plugin. First let's make a README file at jsHelloWorldPlugin/README

jsHelloWorldPlugin =================  This plugin prints "Hello, World!" to the screen.  Installation ------------    * Install the plugin          $ symfony plugin:install jsHelloWorldPlugin.tgz    * Clear the cache          $ symfony cache:clear  Documentation -------------  Once the plugin is installed, run the following command:    $ symfony helloWorld

Next we'll create a license file at plugins/jsHelloWorldPlugin/LICENSE:

Copyright (c) 2010 Jason Swett  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Now we'll take the important step of creating a package.xml file atplugins/jsHelloWorldPlugin/package.xml. You can see what a package file is supposed to look likehere. Ours can look like this:

 <?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.4.6" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">  <name>jsHelloWorldPlugin</name>  <channel>plugins.symfony-project.org</channel>  <summary>sample plugin</summary>  <description>Just a test plugin</description>  <lead>   <name>Jason Swett</name>   <user>jasonswett</user>   <email>jason.swett@gmail.com</email>   <active>yes</active>  </lead>  <date>2010-09-08</date>  <time>15:54:35</time>  <version>   <release>1.0.0</release>   <api>1.0.0</api>  </version>  <stability>   <release>stable</release>   <api>stable</api>  </stability>  <license uri="http://www.symfony-project.org/license">MIT license</license>  <notes>-</notes>  <contents>   <dir name="/">    <file role="data" name="README" />    <file role="data" name="LICENSE" />    <dir name="lib">     <dir name="task">      <!-- tasks -->      <file role="data" name="helloWorldTask.class.php" />     </dir>    </dir>   </dir>  </contents>  <dependencies>   <required>    <php>     <min>5.1.0</min>    </php>    <pearinstaller>     <min>1.4.1</min>    </pearinstaller>    <package>     <name>symfony</name>     <channel>pear.symfony-project.com</channel>     <min>1.4.0</min>    </package>   </required>  </dependencies>  <phprelease />  <changelog /> </package>

Now we're ready to wrap everything up into a nice package. Rename your plugin directory to include the version name:

 $ mv plugins/jsHelloWorldPlugin/ jsHelloWorldPlugin-1.0.0

Now compress the plugin folder into a .tgz file:

 $ tar cvzf jsHelloWorldPlugin-1.0.0.tgz jsHelloWorldPlugin-1.0.0/

Installing the Plugin

Now you can install the plugin like this:
$ php symfony plugin:install jsHelloWorldPlugin-1.0.0.tgz

Testing the Plugin

To test your plugin, simply run your helloWorld task like you did before:
$ php symfony helloWorld
Congratulations! You just wrote your first plugin.