Thursday, May 27, 2010

Symfony: Mailer

In action

$message = $this->getMailer()->compose(
    array('your@email.com'=>'Your Name'),
    'otheremail@email.com',
    'Subject',
    'Body'
);
$this->getMailer()->send($message);


factories.yml

dev:
  mailer:
     class: sfMailer
     param:
       logging:           %SF_LOGGING_ENABLED%
       charset:           %SF_CHARSET%
       delivery_strategy: realtime
       transport:
         class: Swift_SmtpTransport
         param:
           host:       localhost
           port:       25
           encryption: ~
           username:   ~
           password:   ~

Tuesday, May 25, 2010

YUI: Customize YUI

Building Your Own Widget Library with YUI
http://yuiblog.com/blog/2008/06/24/buildingwidgets/

Customizing Existing YUI Component

YAHOO.namespace static function to create an object space for our own library

YAHOO.namespace('SATYAM');  // create a property SATYAM under YAHOO


Define Constructor

YAHOO.SATYAM.LoadingPanel = function(id) {

  YAHOO.SATYAM.LoadingPanel.superclass.constructor.call(this,
    id || YAHOO.util.Dom.generateId() ,
    {
       width: "100px",
       fixedcenter: true,
       constraintoviewport: true,
       underlay: "shadow",
       close: false,
       visible: false,
       draggable: true
    }
  );

  this.setHeader("Loading ...");
  this.setBody('');
  YAHOO.util.Dom.setStyle(this.body, 'textAlign', 'center');
  this.render(document.body);
};


Use YAHOO.lang.extend
superclass is part of the inheritance mechanism provided by YUI’s extend method. After you declare the constructor for your new object, you call extend:

YAHOO.lang.extend(YAHOO.SATYAM.LoadingPanel, YAHOO.widget.Panel);

The constructor itself does not get executed immediately. The extend function does get executed immediately.

We use method call of JavaScript native Function object, which takes the first argument as the execution scope of the function called and passes it the rest of the arguments.

To Use the object we just created

if (!loadingPanel2) {
   loadingPanel2 = new YAHOO.SATYAM.LoadingPanel();
}
loadingPanel2.show();


Puts all the code within an anonymous function, which gets immediately executed (notice the empty parenthesis at the end)

YAHOO.namespace('SATYAM');
(function(){
    var Dom = YAHOO.util.Dom,
        Event = YAHOO.util.Event,
        Panel = YAHOO.widget.Panel;

 // here goes the library contents itself
 // constructor
 // extend component
})();
YAHOO.register('SATYAM.LoadingPanel', YAHOO.SATYAM.LoadingPanel, {version: "0.99", build: '11'});

After we declare the instance of the YUI Loader that we will use, we call method addModule providing the information about our library file

var loader = new YAHOO.util.YUILoader();

loader.addModule({
   name: 'SATYAM.LoadingPanel',
   type: 'js',
   requires: ['container'],
   fullpath: 'LoadingPanel.js'
});

loader.require('reset', 'grids', 'base', 'SATYAM.LoadingPanel');






Thursday, May 20, 2010

YUI: Drag & Drop

YUI 2: Drag & Drop
http://developer.yahoo.com/yui/dragdrop/

var dd1 = new YAHOO.util.DD("element1");
var dd2 = new YAHOO.util.DDProxy("element2"); //proxy element during movement
var dd3 = new YAHOO.util.DDTarget("element3"); //target for drag & drop interaction


Drag & Drop Manager
YAHOO.util.DragDropMgr (or alias YAHOO.util.DDM)

//sets the time delay between a mousedown and a
//drag event to 1200 milliseconds:
YAHOO.util.DragDropMgr.clickTimeThresh = 1200;


Interaction Groups
Each Drag and Drop object belongs to one or more interaction groups. Drag and Drop events fire only when the dragged element interacts with other objects that with which it shares a group membership. If no group is specified in the constructor, an object belongs to the "default" group

// No group specified so dd0 is assigned to the "default" group
var dd0 = new YAHOO.util.DD("elementid0");
// dd1 is a member of group1
var dd1 = new YAHOO.util.DD("elementid1", "group1");
// dd2 is a member of group2
var dd2 = new YAHOO.util.DD("elementid2", "group2");
// dd3 is a member of both group1 and group2
var dd3 = new YAHOO.util.DD("elementid3", "group1");
dd3.addToGroup("group2");
//groups can be removed via script as well:
dd1.removeFromGroup("group1");


Interesting Moments & Custom Events

var dd = new YAHOO.util.DD('demo');
dd.on('dragEvent', function(ev) {
YAHOO.log('Element is being dragged.');
}, dd, true);






Wednesday, May 19, 2010

Javascript Tips - Part2

1. Declare Function
http://www.permadi.com/tutorial/jsFunc/index.html
functionName([parameters]){functionBody};

function add(a, b)
{
    return a+b;
}

assign a variable to an unnamed function: consider the function as an object

var add = function(a, b)
{
    return a+b;
}
var add=function theAdd(a, b)
{
    return a+b;
}
alert(add(1,2)); // produces 3
alert(theAdd(1,2)); // also produces 3

Useful in object oriented program, we can have a function be a property of an object

var myObject=new Object();
myObject.add=function(a,b){return a+b};
// myObject now has a property/a method named "add"
// and I can use it like below
myObject.add(1, 2);


When we declare a function, JavaScript actually creates an object;
We can add properties to Objects, including function objects.

function Ball()     // it may seem odd, but declaration
{                   // creates an object named Ball, and you can
}                   // refer to it or add properties to it like below
Ball.callsign="The Ball"; // add property to Ball
alert(Ball.callsign); // produces "The Ball"

Since function is an object, we can assign a pointer to a function

function myFunction(message)
{
    alert(message);
}
var ptr=myFunction; // ptr points to myFunction
ptr("hello"); // executes myFunction which will prints "hello"


2. Function as Data Type and Function Constructor
http://www.permadi.com/tutorial/jsFunc/index2.html

By declaring a function, we have also created a new data type

function Ball(message)
{
    alert(message);
}
var ball0=new Ball("creating new Ball"); // creates object &
                                         // prints the message
ball0.name="ball-0"; // ball0 now has a "name" property
alert(ball0.name); // prints "ball-0"

The red portion as a shortcut for doing below

function Ball(message)
{
    alert(message);
}
var ball0=new Object();
ball0.construct=Ball;
ball0.construct("creating new ball"); // executes ball0.Ball("creating..");
ball0.name="ball-0";
alert(ball0.name);


Constructor function

function Ball(message, specifiedName)
{
    alert(message);
    this.name=specifiedName;
}
var ball0=new Ball("creating new Ball", "Soccer Ball");
alert(ball0.name); // prints "Soccer Ball"


The "new" keyword eventually causes the constructor function to be executed. In this case, it will executel Ball("creating new Ball", "Soccer Ball"); and the
keyword this will refer to ball0.
Therefore, the line: this.name=specifiedName becomes ball0.name="Soccer Ball".

Every constructor function has a property named prototype.
You do not need to explicitly declare a prototype property, because it exists on every constructor function.

function Test()
{
}
alert(Test.prototype); // prints "Object"


Prototype is an object
when an object is created, the constructor function assigns its prototype property to the internal __proto__ property of the new object.

function Fish(name, color)
{
this.name=name;
this.color=color;
}
Fish.prototype.livesIn="water";
Fish.prototype.price=20;


You can use prototype to assign functions that are common on all objects

function Employee(name, salary)
{
this.name=name;
this.salary=salary;
}
Employee.prototype.getSalary=function getSalaryFunction()
{
return this.salary;
}
Employee.prototype.addSalary=function addSalaryFunction(addition)
{
this.salary=this.salary+addition;
}



Symfony Tips

1. Add Timer (symfony 1.0)

/**** init timer *****/
$timer = sfTimerManager::getTimer('myTimer');
/**********/


/**** display timer *****/
$timer->addTime();
$elapsedTime = $timer->getElapsedTime();
echo $elapsedTime;
die();
/**********/


2. Unit Test (symfony 1.4)
http://www.symfony-project.org/jobeet/1_4/Doctrine/en/08
Create test.php file under ProjectName/test/unit/test

// test/unit/JobeetTest.php
require_once dirname(__FILE__).'/../bootstrap/unit.php';

$t = new lime_test(1);
$t->pass('This test always passes.');


To launch the test
$ php test/unit/test.php

Sample

require_once dirname(__FILE__).'/../bootstrap/unit.php';
$t = new lime_test(6); // display 1..6

$t->comment('::slugify()'); // display #::slugify()
$t->is(Jobeet::slugify('Sensio'), 'sensio', '::slugify() converts all characters to lower case'); // display ok 1 - ::slugify() converts all ...


3. User Flash (symfony 1.4)
http://www.symfony-project.org/jobeet/1_4/Doctrine/en/13
A flash is an ephemeral message stored in the user session that will be automatically deleted after the very next request. It is very useful when you need to display a message to the user after a redirect.

setFlash(): The first argument is the identifier of the flash and the second one is the message to display. You can define whatever flashes you want, but notice and error are two of the more common ones.
// apps/frontend/modules/job/actions/actions.class.php
public function executeExtend(sfWebRequest $request)
{
    $request->checkCSRFProtection();

    $job = $this->getRoute()->getObject();
    $this->forward404Unless($job->extend());

    $this->getUser()->setFlash('notice', sprintf('Your job validity has been extended until %s.', $job->getDateTimeObject('expires_at')->format('m/d/Y')));

    $this->redirect($this->generateUrl('job_show_user', $job));
}

Include the flash message in the templates
// apps/frontend/templates/layout.php
<?php if ($sf_user->hasFlash('notice')): ?>
  <div class="flash_notice"><?php echo $sf_user->getFlash('notice') ?></div>
<?php endif ?>
 
<?php if ($sf_user->hasFlash('error')): ?>
  <div class="flash_error"><?php echo $sf_user->getFlash('error') ?></div>
<?php endif ?>


4. User Attribute (symfony 1.4)
http://www.symfony-project.org/jobeet/1_4/Doctrine/en/13
getAttribute(), setAttribute()

// apps/frontend/modules/job/actions/actions.class.php
class jobActions extends sfActions
{
    public function executeShow(sfWebRequest $request)
    {
    $this->job = $this->getRoute()->getObject();

    // fetch jobs already stored in the job history
    $jobs = $this->getUser()->getAttribute('job_history', array());

    // add the current job at the beginning of the array
    array_unshift($jobs, $this->job->getId());

    // store the new job history back into the session
    $this->getUser()->setAttribute('job_history', $jobs);
    }
}

myUser class
The myUser class overrides the default symfony base sfUser class with application specific behaviors

// apps/frontend/modules/job/actions/actions.class.php
class jobActions extends sfActions
{
    public function executeShow(sfWebRequest $request)
    {
    $this->job = $this->getRoute()->getObject();

    $this->getUser()->addJobToHistory($this->job);
    }
}
// apps/frontend/lib/myUser.class.php
class myUser extends sfBasicSecurityUser
{
    public function addJobToHistory(JobeetJob $job)
    {
    $ids = $this->getAttribute('job_history', array());

    if (!in_array($job->getId(), $ids))
    {
        array_unshift($ids, $job->getId());
        $this->setAttribute('job_history', array_slice($ids, 0, 3));
    }
    }
}

remove attribute
User's attributes are managed by an object of class sfParameterHolder. The getAttribute() and setAttribute() methods are proxy methods for getParameterHolder()->get() and getParameterHolder()->set().

// apps/frontend/lib/myUser.class.php
class myUser extends sfBasicSecurityUser
{
    public function resetJobHistory()
    {
        $this->getAttributeHolder()->remove('job_history');
    }
}



5. i18n and l10n (symfony 1.4)
http://www.symfony-project.org/jobeet/1_4/Doctrine/en/19
User Culture
The language French is ‘fr’, English is ‘en’; the country Canada is ‘CA’, United States is ‘US’; the culture for a user speaking French from Canada is ‘fr_CA’
setCulture()and getCulture()

// in an action
$this->getUser()->setCulture('fr_BE');
echo $this->getUser()->getCulture();

The preferred user culture can be configured in the settings.yml configuration file

#apps/frontend/config/settings.yml
all:
    .settings:
       default_culture: en_CA

Internationalization
set i18n setting to true in settings.yml

# apps/frontend/config/settings.yml
all:
   .settings:
       charset: utf-8
       i18n: true

The I18N helper group is not loaded by default, you need to either manually add itin each template with use_helper(‘I18N’) or load it globally by adding to the standard_helpers setting

# apps/frontend/config/settings.yml
all:
   .settings:
      standard_helpers: [Partial, Cache, I18N]

Sample template of how to use the __() helper

    // apps/frontend/templates/layout.php

      <a href=""><?php echo __('About Jobeet') ?></a>

      <?php echo link_to(__('Full feed'), 'job', array('sf_format' => 'atom')) ?>

    Create catalogue using i18n:extract

    $ php symfony i18n:extract frontend fr --auto-save

    Each translation is managed by a trans-unit tag which has a unique id attribute. A lot of tools exist to ease the translation process. (check out Open Language Tools https://open-language-tools.dev.java.net/)

    <!-- apps/frontend/i18n/fr/messages.xml -->

    <xliff version="1.0">
      <file source-language="EN" target-language="fr" datatype="plaintext"
          original="messages" date="2008-12-14T12:11:22Z"
          product-name="messages">
        <header/>
        <body>
          <trans-unit id="1">
            <source>About Jobeet</source>
            <target>A propos de Jobeet</target>
          </trans-unit>
          <trans-unit id="2">
            <source>Feed</source>
            <target>Fil RSS</target>
          </trans-unit>
        </body>
      </file>
    </xliff>

    How to use format_date
    sfDateFormat::getPattern()
    http://fellipeeduardo.com/blog/symfony-helper-format_date-how-to-use/en/

    6. autoload.yml (symfony 1.4)
    http://www.symfony-project.org/reference/1_4/en/14-Other-Configuration-Files
    The autoload.yml configuration determines which directories need to be autoloaded by symfony

    7. Authentication (symfony 1.4)
    entire application require the user to be authenticated

    # apps/backend/config/security.yml
    default:
       is_secure: true

    when an un-authenticated user tries to access a secured action, symfony forwards the request to the login action

    # apps/backend/config/setting.yml
    all:

      .actions:
         login_module: default
         login_action: login


    By default, the myUser class extends sfBasicSecurityUser, and not sfUser. sfBasicSecurityUser provides additional methods to manage user authentication and authorization.

    To manage user authentication, use the isAuthenticated() and setAuthenticated() methods:

    if (!$this->getUser()->isAuthenticated())
    {
        $this->getUser()->setAuthenticated(true);
    }


    8. Basic File Structure (1.2)
    http://www.symfony-project.org/book/1_2/19-Mastering-Symfony-s-Configuration-Files

    sf_root_dir # myproject/
    sf_apps_dir # apps/
    sf_app_dir # frontend/
    sf_app_config_dir # config/
    sf_app_i18n_dir # i18n/
    sf_app_lib_dir # lib/
    sf_app_module_dir # modules/
    sf_app_template_dir # templates/
    sf_cache_dir # cache/
    sf_app_base_cache_dir # frontend/
    sf_app_cache_dir # prod/
    sf_template_cache_dir # templates/
    sf_i18n_cache_dir # i18n/
    sf_config_cache_dir # config/
    sf_test_cache_dir # test/
    sf_module_cache_dir # modules/
    sf_config_dir # config/
    sf_data_dir # data/
    sf_doc_dir # doc/
    sf_lib_dir # lib/
    sf_log_dir # log/
    sf_test_dir # test/
    sf_plugins_dir # plugins/
    sf_web_dir # web/
    sf_upload_dir # uploads/


    9. Use Helper in Action
    http://snippets.symfony-project.org/snippet/69
    In PrjectConfiguration file

    # ProjectName/config/ProjectConfiguration.class.php
    include_once('/opt/symfony/symfony14/lib/helper/DateHelper.php');

    In Action
    format_date(time(), 'D', 'fr');

    Format
    http://trac.symfony-project.org/wiki/formatDateHowTo

    JavaScript Tips - Part1

    1. Change ClassName

    document.getElementById(element).setAttribute('class', 'className');
    or document.getElementById(element).className = 'className';
    or using YUI
    YAHOO.util.Dom.getElementByClassName(className, tagName, rootNode);
    YAHOO.util.Dom.hasClass(element, className);
    YAHOO.util.Dom.addClass(element, className);
    YAHOO.util.Dom.replaceClass(element, oldClassName, newClassName);


    2. ParseAjaxResult

    function ajaxCall(id) {
        var displayResult = {
                success: function(o) {
                    var response = parseAJAXResult(o);
                    var elem = document.getElementById('div_id');
                    elem.innerHTML = response.result;
                },
                failure: generalAjaxFailure
            }   
            var params = 'id='+id;
            YAHOO.util.Connect.asyncRequest('POST', '<?php echo url_for('module/action')?>', displayResult , params);  
    }


    3. Ajax Form

    YAHOO.util.Connect.setForm(document.getElementById(form_id));
    document.search_transaction = YAHOO.util.Connect.asyncRequest('POST',
       '<?php echo url_for('module/action')?>',
       { success: successComplete, failure: generalAjaxFailure });

    Make sure the hidden field has name, otherwise setForm won't pick it up.
    <input type="hidden" id="selected_ids" name="selected_ids">

    4. String Functions
    http://www.w3schools.com/jsref/jsref_obj_string.asp

    if(resultVal.indexOf("keyword") != -1) { // contain keyword ... }
    function ucfirst(str) {   // capitalize first letter
        var firstLetter = str.substr(0, 1);
        return firstLetter.toUpperCase() + str.substr(1);
    }


    5. Check if variable exists
    if ( typeof (variableName) == "undefined" ) {
    } else {
    }


    6. Create Elements 
    var body = document.createElement('form');
    body.id = 'elem_id';
       var row1 = document.createElement('div');
       row1.className = 'formRow';
       row1.innerHTML = '<label for="cell_value">Enter a new value: </label>';
       // Input Text           
      var elTextbox = row1.appendChild(document.createElement("input"));
      elTextbox.id = "cell_value";
      elTextbox.name = "cell_value";
      elTextbox.type = "text";
      elTextbox.style.width = "130px";
      elTextbox.style.margin= "0 10px 0 0";           
      Event.addListener(elTextbox, "keydown", function(oArgs){ if(enterDown(oArgs)) { this.cellEditorAction(prod_id, column_key, 'newValue'); }}, this, true);
                   
      // Save button
     var elSaveBtn = row1.appendChild(document.createElement("button"));
     elSaveBtn.className = DT.CLASS_DEFAULT;
     elSaveBtn.innerHTML = this.LABEL_SAVE || DT.LABEL_SAVE;
      Event.addListener(elSaveBtn, "click", function(oArgs){ this.cellEditorAction(prod_id, column_key, 'newValue');}, this, true);


    body.appendChild(row1);
    panel.setBody(body);
    panel.render();
    panel.show();
                    


    7. Reload Page
    window.location.reload()

    8. Window onload
    YAHOO.util.Event.on(window, 'load', function () {
        if(window.parent.location.href != window.location.href) {
            window.parent.location.href = '<?php url_for('public/index') ?>';
        }
        document.getElementById('username').focus();
    });


    or

    window.onload = funcName;
    function funcName() {
    }

    Loading Sequence

    #js
    window.onload = getRight_onload; // IE doesn't take function() Error: Not implemented

    function getRight_onload() {
       getRight();
    }
    function getRight() {
       var displayData = {
          success: function(request) {
             document.getElementById('right_div').innerHTML = request.responseText;
          },
          failure: ajaxFailure
      }
       var params = 'column='+ column;
       YAHOO.util.Connect.asyncRequest('POST', url, displayData, params);
    }

    YUI Tips

    1. YUI Container
    http://developer.yahoo.com/yui/container/

    Seven Examples of YUI Panels
    http://icant.co.uk/sandbox/yuipanel/

    2. YUI Event
    http://developer.yahoo.com/yui/event/

    YAHOO.util.Event.addListener(el, sType, fn, obj, overrideContext)
    el:  id, or a collection of ids
    sType: the type of event to append (such as "click" http://www.quirksmode.org/dom/events/)
    fn: the method the event invokes
    obj: an arbitrary object that will be passed as a parameter to the handler
    overrideContect: if true, the obj passed in becomes the execution context of the listener; if an object, this object becomes the execution context

    YAHOO.util.Subscriber( fn , obj , overrideContext )
    fn: the function to execute
    obj: an object to be passed along when the event fires
    overrideContext: If true, the obj passed in becomes the execution context of the listener

    There are 2 main types of event subscriptions:

    //DragDrop
    var dd = new YAHOO.util.DD('dd');
    dd.on('dragEvent', function() { });

    //Panel
    var panel = new YAHOO.widget.Panel('panel');
    panel.renderEvent.subscribe(function() {});

    //Calendar
    var cal = new YAHOO.widget.Calendar('cal');
    cal.selectEvent.subscribe(function() {});

    //Editor
    var editor = new YAHOO.widget.Editor('editor', {});
    editor.on('afterRender', function() {});




    3. Define anonymous function 
    Defining an anonymous function in order to keep all variables out of the global scope. Inside the anonymous function, define some shortcuts to utils that will be used frequently (Dom and Event).

    (function () {
        var Event = YAHOO.util.Event,
        Dom = YAHOO.util.Dom;
    }());


    Inside the the anonymous function, use the onDOMReady method of the Event utility to instantiate an Overlay and a Button when the page's DOM is ready to be scripted.

    Event.onDOMReady(function () {
        var oCalendarMenu;

        // Create an Overlay instance to house the Calendar instance
        oCalendarMenu = new YAHOO.widget.Overlay("calendarmenu", { visible: false });

        // Create a Button instance of type "menu"

        var oButton = new YAHOO.widget.Button({
           type: "menu",
           id: "calendarpicker",
           label: "Choose A Date",
           menu: oCalendarMenu,
           container: "datefields" });
    });


    3. YUI Panel
    Click outside of a panel to close it
    var treePanel = new YAHOO.widget.Panel(...);

    function isInsideTreePanel(clicked_element) {
        var current_element = clicked_element;
        while(current_element && current_element != document.body) {
           if (current_element == treePanel.element) {
              return true;
           }
        current_element = current_element.parentNode;
        }
        return false;
    }

    function onDocumentMouseDown(e) {
        if (treePanel.cfg.getProperty('visible')) {
           if (!isInsideTreePanel(e.target)) {
              treePanel.hide();
              YAHOO.util.Event.removeListener(document, onDocumentMouseDown);
           }
        }
    }

    treePanel.show();
    YAHOO.util.Event.addListener(document, 'mousedown', onDocumentMouseDown, null);


    4. YUI namespace
    http://www.yuiblog.com/blog/2007/06/12/module-pattern/

    YAHOO.namespace("mySwitch");
    YAHOO.mySwitch.panelTable = new YAHOO.widget.Panel("panelTable");

    Error: missing ; before statement
    if trying to create a public method with “var” keyword

    YAHOO.namespace("mySwitch");
    var YAHOO.mySwitch.panelTable = new YAHOO.widget.Panel("panelTable");



    parentheses () at the end of function: cause anonymous function to execute immediately

    YAHOO.myProject.myModule = function () {
    } ();

    Javascript Syntax

    Javascript Tutorial
    http://www.tizag.com/javascriptT/javascriptsyntax.php

    document.write("something something");

    window.location = "http://...";

    function prompter() {
       var reply = prompt("what's your name?", "");
       alert("Nice to see you " +reply+"!");
    }

    window.print();

    function delayer() {
       window.location="../xxxx.php";
    }

    body onload="setTimeout('delayer()', 5000)"

    window.open("http://...", "name of window", "status =1, height=300, width=300, resizable = 0");

    if(elem.value.length ==0) {
       elem.focus();
    }

    var numericExpression = /^[0-9[+$/;
    if(elem.value.match(numericExpression)) {
    }

    javascript void 0
    News Flash
    because alert() returns null value


    Set myNum Please


    indexof
    var aURL = "http://www.tizag.com/";
    var aPosition = aURL.indexOf("www");
    document.write("The position of www = " + aPosition);


    Javascript Tutorial 2
    http://home.cogeco.ca/~ve3ll/jstutor0.htm

    Good Resource
    JavaFile.com
    http://www.javafile.com/

    JavaScript.net
    http://www.java-scripts.net/

    Thursday, May 13, 2010

    OOP with PHP 5.x

    OOP
    http://www.scribd.com/doc/38423/Object-Oriented-Programming-in-PHP-5
    • Abstraction
    • Modularization
    • Ecapsulation
    • Extensibility
    Basic

    class MyClass {
        public $data;
        private $private;
        static $static = 1;
        const constant = 'value';
        public function __construct() {
        }

        public function __destruct() {
        }

        protected function Action() {
        }

        private function Action() {
        }

        public function show() {
        }
    }

    Extending Class

    class MyClass {
       public $data;
       public function __construct() {
           $this->data = 'Hello World";
       }



    class Second extends MyClass {
       private $some;
       public function __construct() {
           $this->some = 'Second!';
           parent::__construct();
       }

    }

    Interface & implements
    keyword implements:
    • create class based on interface;
    • can be combined with extends

    interface Template {
       public function foo($var);
    }

    class MyClass implements Template {
       public function foo($var) {
           echo $var;
       }

    }
    class MyClass extends foobar implements Template {
       public function foo($var) {
           echo $var;
       }

    }

    Understanding PHP Object Model
    http://www.slideshare.net/sebastian_bergmann/understanding-the-php-object-model




    CSS Techniques

    1. CSS Drop Shadows
    http://www.alistapart.com/articles/cssdropshadows/



    2. Rounded Corner
    http://spiffybox.com/



    3. Free Graphics and Effects
    http://journalxtra.com/2009/08/snazz-up-your-website-with-free-graphics-and-sound-effects/

    Symfony: debugging (1.4)

    1. Unwanted &quot; in action

    # ProjectName/apps/appsName/config/settings.yml
    # Output escaping settings
        #escaping_strategy: true
        #escaping_method: ESC_SPECIALCHARS


    2. Call to undefined method dashboardActions::returnJsonResponse
    # ProjectName/lib/symfony/Actions.class.php

    class Actions extends sfActions {

    }









    Monday, May 10, 2010

    Symfony 1.4: Create New Project

    1. Create project directory under ~/workspace/
    [root/workspace]# mkdir ProjectName

    2. Create project
    [root/workspace/ProjectName]# symfony14 generate:project ProjectName

    in Eclipse
    File > New > PHP Project
    Project name: ProjectName

    3. Create application
    [root/workspace/ProjectName]# symfony14 generate:app appName

    4. Configuration
    [root/workspace/ProjectName]# chmod 777 cache/ log/

    create symfony softlink
    [root/workspace/ProjectName/web]# ln -s /opt/symfony/symfony14/data/web/sf

    create softlink
    [root]# cd /var/www/html
    [root/var/www/html]# ln -s ~/workspace/ProjectName

    under workspace/phplib
    [root/workspace/phplib]# ln -s ~/workspace/PHPLIB_***Adapter/***Service ***Service

    5. Create module
    under project directory ProjectName
    [root/workspace/ProjectName]# symfony14 generate:module appsName newModuleName

    6. Set routing
    /projectName/apps/appName/config/routing.yml
    homepage:
    url: /
    param: { module: public, action: index }


    7. Set view
    /projectName/apps/appName/config/view.yml

    default:
        http_metas:
           content-type: text/html
        metas:
           title:  Project Name
           robots: index, follow
           description: Project Description
           keywords: xxxx, xxxxx
           language: en
        stylesheets: [main]
        javascripts: []
        has_layout: on
        layout: layout



    customize the view for module

    # apps/frontend/modules/job/config/view.yml
    default:
    stylesheets: [public.css]

    resetSuccess:
    stylesheets: [main.css]


    8. Turn on/off debug toolbar
    Web Debug Toolbar Activation, in myapp/config/settings.yml

    dev:
        .settings:
           web_debug: true


    9. frontend_dev.php IP address check
    /projectName/web/frontend_dev.php

    // this check prevents access to debug front controllers that are deployed by accident to production servers.
    // feel free to remove this, extend it or make something more sophisticated.
    if (!in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', '::1')))
    {
    die('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
    }


    Error in Linux, but not on other machine
    Warning: session_start() [function.session-start]: Function spl_autoload_call() hasn't defined the class it was called for in /opt/symfony/symfony14/lib/storage/sfSessionStorage.class.php on line 93

    Catchable fatal error: Object of class __PHP_Incomplete_Class could not be converted to string in /opt/symfony/symfony14/lib/yaml/sfYamlInline.php on line 105

    Tried symfony14 cc, still have the error
    Tried symfony14 clear-cache, red box - Task "clear-cache" is not defined
    Closed browser without saving, worked (should just clear session/cookie);
    symfony clear-cache is changed to symfony cache:clear

    10. Forms
    1) FormHelper was removed from symfony 1.4, so input_tag(), checkbox_tag() and etc not working.
    http://www.symfony-project.org/forms/1_4/en/

    2) Notice: Undefined variable: sf_flash
    Use $sf_user->hasFlash()

    11. Auth
    Load AuthenticationService

    # ProjectName/config/ProjectConfiguration.class.php
    require_once('AuthenticationService/service/ASA_AuthSession.php');

    Add Auth.class.php

    # ProjectName/lib/symfony/Auth.class.php
    public function initialize(sfEventDispatcher $dispatcher, sfStorage $storage, $options = array()) { 

    }
    public function setAuthenticated($authenticated) {
        #throw new Exception('here');
        #sfContext::getLogger()->log('CSC_User::setAuthenticated is not implemented.');
    }

    public function addCredential($credential) {
        #sfContext::getLogger()->log('CSC_User::addCredential is not implemented.');
    }

    configure factories.yml

    # ProjectName/apps/appName/config/factories.yml
    all:
       user:
        class: Auth


    12. Login
    Create new component instance in CSC

    13. After move project / import other's project

    Warning: copy(/home/eshare/projects/sfproject2/cache/frontend/prod/config/config_config_handlers.yml.php) [function.copy]: failed to open stream: [B]Permission denied in /home/eshare/projects/sfproject2/lib/vendor/symfony/lib/config/sfConfigCache.class.php on line 359[/B]

    Warning: chmod() [function.chmod]: No such file or directory in /home/eshare/projects/sfproject2/lib/vendor/symfony/lib/config/sfConfigCache.class.php on line 365

    Warning: require(/home/eshare/projects/sfproject2/cache/frontend/prod/config/config_config_handlers.yml.php) [function.require]: failed to open stream: No such file or directory in /home/eshare/projects/sfproject2/lib/vendor/symfony/lib/config/sfConfigCache.class.php on line 279

    Fatal error: require() [function.require]: Failed opening required '/home/eshare/projects/sfproject2/cache/frontend/prod/config/config_config_handlers.yml.php' (include_path='.:/usr/share/php:/usr/share/pear') in /home/eshare/projects/sfproject2/lib/vendor/symfony/lib/config/sfConfigCache.class.php on line 279


    clear the cache completely. (remove the folders inside cache)
    Also run symfony project:permissions

    Friday, May 7, 2010

    Symfony: Multiple Version in same environment

    Your Complete Guide to Running Multiple
    Symfony Versions on the Same Environment
    http://symfonynerds.com/blog/?p=123

    Step 1 Uninstall any existing symfony installations
    [root]# pear uninstall symfony/symfony
    uninstall ok: channel://pear.symfony-project.com/symfony-1.0.20

    Step 2 Create a /opt/symfony directory
    Install symfony in /usr/share/php/symfony
    [root]# cd /opt/
    [root/opt]# mkdir symfony

    Step 3 Within the created /opt/symfony directory checkout the symfony 1.0 through 1.4 versions using SVN
    [root/opt]# cd symfony/
    [root/opt/symfony]# svn co http://svn.symfony-project.com/branches/1.0 symfony10
    ...
    [root/opt/symfony]# svn co http://svn.symfony-project.com/branches/1.1 symfony11
    ...
    [root/opt/symfony]# svn co http://svn.symfony-project.com/branches/1.2 symfony12
    ...
    [root/opt/symfony]# svn co http://svn.symfony-project.com/branches/1.3 symfony13
    ...
    [root/opt/symfony]# svn co http://svn.symfony-project.com/branches/1.4 symfony14
    ...
     


    Step 4 Create symbolic links to the symfony commands in the bin directory
    ln -s /opt/symfony/symfony10/data/bin/symfony /usr/bin/symfony10
    ln -s /opt/symfony/symfony11/data/bin/symfony /usr/bin/symfony11
    ln -s /opt/symfony/symfony12/data/bin/symfony /usr/bin/symfony12
    ln -s /opt/symfony/symfony12/data/bin/symfony /usr/bin/symfony13
    ln -s /opt/symfony/symfony12/data/bin/symfony /usr/bin/symfony14

    To test the links
    [root]# symfony10 -V
    symfony versoin 1.0.22-LAST
    [root]# symfony11 -V
    symfony versoin 1.1.10-DEV (/opt/symfony/symfony11/lib)

    Step 5 Update any existing symfony 1.0 projects to use the following include directories
    project/config/config.php
    $sf_symfony_lib_dir  = '/opt/symfony/symfony10/lib';
    $sf_symfony_data_dir = '/opt/symfony/symfony10/data';


    Step 6 New symfony 1.4 projects can use the following to create the projects
    symfony14 generate:project ProjectName