Monday, December 10, 2012

Reload Cached CSS / JS Files in Symfony

An elegant way to force browsers to reload cached CSS / JS files in Symfony 1.4

settings.yml
Add Asset, CSSCache, JSCache to the standard_helpers row:
standard_helpers: [ Partial, Cache, I18N, Date, Asset, CSSCache, JSCache ]
lib/helper/CSSCacheHelper.php
function include_versioned_stylesheets()
{
  $response = sfContext::getInstance()->getResponse();
  sfConfig::set('symfony.asset.stylesheets_included', true);
  $html = '';
  foreach ($response->getStylesheets() as $file => $options) {
    $filepath = sfConfig::get('sf_web_dir') . '/' .  stylesheet_path($file);
    if(file_exists($filepath)) {
      $file .= '?v=' . filectime($filepath);
    }
    $html .= stylesheet_tag($file, $options);
  }
  echo $html;
}
lib/helper/JSCacheHelper.php
function include_versioned_javascripts()
{
  $response = sfContext::getInstance()->getResponse();
  sfConfig::set('symfony.asset.javascripts_included', true);
  $html = '';
  foreach ($response->getJavascripts() as $file => $options) {
    $filepath = sfConfig::get('sf_web_dir') . '/' .  javascript_path($file);
    if(file_exists($filepath)) {
      $file .= '?v=' . filectime($filepath);
    }
    $html .= javascript_include_tag($file, $options);
  }
  echo $html;
}
apps/xxx/templates/layout.php
Use the include_versioned_stylesheets() and include_versioned_javascripts() functions to load css and js files, instead of the default include_stylesheets() and include_javascripts() functions.

Tuesday, December 4, 2012

Display Image with Original Size in TCPDF

$pdf->setImageScale(1.53); makes an ability to display pictures in original dimensions, with no blur. Also beware to call setImageScale() before AddPage:
$pdf->setImageScale(1.53);
$pdf->AddPage();
Source: http://sourceforge.net/p/tcpdf/discussion/435311/thread/404343d4

Monday, December 3, 2012

Enable CKFinder in CKEditor

     

Wednesday, November 28, 2012

Format Date in Admin Generator in Symfony

For example, on the index/list page...
    config:
      actions: ~
      fields:  ~
      list:    
        display: [_id, Partner, name, valid_from, valid_to]
        fields: 
          valid_from: { date_format: yyyy-MM-dd }
          valid_to: { date_format: yyyy-MM-dd }

Friday, November 16, 2012

Add AJAX Request to Google Analytics

If you use jQuery you can bind to the global AjaxComplete event to fire a Pageview everytime an Ajax call completes:
jQuery(document).ajaxComplete(function(e, xhr, settings){
  var d = document.location.pathname + document.location.search + document.location.hash;
  _gaq.push(['_trackPageview', d]);
});
Source: http://stackoverflow.com/questions/7737549/google-analytics-and-loading-a-page-using-ajax-get-request

Sunday, October 28, 2012

FreeTDS Output Parameter Not Return to PHP

I had a stored procedure that returned with the output parameter (I found it in the FreeTDS log file) but the variable of the output parameter was blank in PHP. I checked the stored procedure and I found a stupid 'select @foo' selection in the procedure, before the initialization of the output parameter (set @output='bar'). I commented the selection (--select @foo) and now it works like a charm, the value of ouput parameter is available in the output PHP variable. I hope this helps you.

Tuesday, October 16, 2012

Native SQL Query in Doctrine

Examples...
// get Doctrine_Connection object
$con = Doctrine_Manager::getInstance()->connection();
// execute SQL query, receive Doctrine_Connection_Statement
$st = $con->execute("...............");
// fetch query result
$result = $st->fetchAll();
Or with parameter...
$db = Doctrine_Manager::getInstance()->connection();
$query = $db->prepare("INSERT INTO search_term (term, counter) VALUES (:term, '1') ON DUPLICATE KEY UPDATE counter=counter+1;");
$query->execute(array('term' => $search));

mb_ucfirst

function mb_ucfirst($string, $encoding)
{
    $strlen = mb_strlen($string, $encoding);
    $firstChar = mb_substr($string, 0, 1, $encoding);
    $then = mb_substr($string, 1, $strlen - 1, $encoding);
    return mb_strtoupper($firstChar, $encoding) . $then;
}

Tuesday, September 25, 2012

Do Not Save Null Values in Embedded Form in Symfony

Think there is a Product object with many ProductPrice objects. The Product form contains some ProductPrice forms as embed forms. Prices are not mandatory fields. Now if you save the form, there will be null price rows in the ProductPrice table. Do the following in the ProductPrice model(!) class!
  public function save(Doctrine_Connection $conn = null)
  {
    if($this->price > 0)
    {
      return parent::save();
    }
    else
    {
      $this->delete();
      return null;
    }
  }
This will check the price (there is a price field in the ProductPrice table) is greater than 0 or not. If greater, it will save to the database. If not, it will delete the row in the table (if presents) and stop the saving process for this price object.

Doctrine: SQLSTATE[23000]: Integrity constraint violation duplicate entry

If you are using a table where some fields are I18N and ex. the title field is sluggable, you will realize that you cannot update(!) the object with the same title. See an example:

The page is multilingual (Hungarian and English). You create a product with TEFAL XY Hungarian and TEFAL XY English tilte (the same title used in each language). You can saved the form / object, it created successfully. Now you change the Hungarian title to TEFAL X. Save. Then change the English title to TEFAL X, too. You will get an error:

Doctrine: SQLSTATE[23000]: Integrity constraint violation duplicate entry

This is a bug in doctrine 1.2.x.

Solution
  1. Copy lib / vendor / symfony / lib / plugins / sfDoctrinePlugin / lib / vendor / doctrine / Doctrine / Template / Listener / Sluggable.php inside your own lib directory.
  2. In the getUniqueSlug method, change this line:
    $whereString .= ' AND r.' . implode(' != ? AND r.', $table->getIdentifierColumnNames()) . ' != ?';
    to this:
    $whereString .= ' AND (r.' . implode(' != ? OR r.', $table->getIdentifierColumnNames()) . ' != ?)';
  3. Save. Clear cache. Be happy.

Monday, September 24, 2012

Hide Errors at Top of the Embed Form in Symfony

If you use embed forms, you will realise that the validatation errors appear twice, once near the input fields (in the embed form) and once at top of the embed form. To solve this....

I'm using the jroller plugin to generate auto admin:

plugins / sfAdminThemejRoller / data / generator / sfDoctrineModule / jroller / template / templates / _form_field.php

Use this (my solution):


    [?php if ($form[$name]->hasError() && get_class($form[$name]) != 'sfFormFieldSchema'): ?]
        [?php echo $form[$name]->renderError() ?]
    [?php endif; ?]

Thursday, September 20, 2012

MySQL Tuning

  1. Optimize tables (to correct overheads)
  2. Set query cache size bigger if Qcache_lowmem_prunes (on the runtime information page) is red.
Useful commands:

  • Show all query cache settings:
    SHOW VARIABLES LIKE  '%query_cache%';
  • Set a bigger query cache size (256 MB) ON RUNTIME:
    SET GLOBAL query_cache_size = 256000000;
  • Set a bigger query cache size in config (will work after mysql restart):
    /etc/mysql/my.cnf
    Search for "query_cache_size" then change...
    query_cache_size = 256M

Saturday, September 15, 2012

Install Symfony 2 on Debian

  1. Download the Standard version and put the Symfony folder to the root.
  2. Open /Symfony/web/config.php with browser to check the configuration. If needed, remove the ip address check from the begining of the file. I had to install things and do some changes:

    apt-get update
    apt-get install php-pear php5-dev apache2-threaded-dev build-essential libicu-dev
    pecl install apc
    pecl install intl

    php.ini:
    short_open_tag = Off
    date.timezone = Europe/Budapest (for me)
    extension = apc.so
    extension = intl.so


    Save then restart apache.

Friday, September 14, 2012

Filter Data On Frontend with Symfony Form Filter

Source: http://stackoverflow.com/questions/3765495/symfony-how-to-filter-data-on-the-frontend-like-in-the-backend

If you want to do it exactly like it is done on the backend, you can use the admin generator on frontend applications. A more general and customizable way would be to simply create list and filter actions and use Symfony's form filters. Here's a basic example for a model class "Article":

In an actions class:
class articleActions extends sfActions
{
  public function executeList(sfWebRequest $request)
  {
    $this->form = new ArticleFormFilter();
    $this->pager = new sfDoctrinePager('Article');
  }

  public function executeFilter(sfWebRequest $request)
  {
    $this->form = new ArticleFormFilter();
    $this->form->bind($request[$this->form->getName()]);
    if ($this->form->isValid())
    {
      $this->pager = new sfDoctrinePager('Article');
      $this->pager->setQuery($this->form->getQuery());
      $this->setTemplate('list');
    }
    //handle invalid form here
  }
}
In view, iterate throw pager like this:
foreach($pager->getResults() as $article)
Doctrine FormFilter's are fairly similar to Doctrine forms. Get started by configuring the form inside of FormFilter::configure();

ob_start: PHP Output To Variable / String

<?php ob_start(); ?>
Hello world, <?php echo "My Website"; ?>
<?php include('something.php') ?>
Thank you.
<?php $var = ob_get_clean(); ?>

Friday, September 7, 2012

The user specified as a definer ('root'@'%') does not exist

Solution:
mysql -u root -p
grant all privileges on *.* to `root`@`%` identified by 'password';
flush privileges;

Install Apache 2, PHP 5, MySQL 5 on Debian

apt-get update

apt-get install apache2
apt-get install php5
apt-get install libapache2-mod-php5
apt-get install mysql-server mysql-client mysql-common php5-mysql
apt-get install php5-xsl php5-gd php5-curl

Install the Latest APC on Debian
Install PHPMYADMIN on Debian

Install PHPMYADMIN on Debian

1. Download the latest PHPMYADMIN.
2. Put here: /usr/share/phpmyadmin
3. Create phpmyadmin.conf in /etc/apache2/conf.d :
Alias /phpmyadmin /usr/share/phpmyadmin


        Options Indexes FollowSymLinks
        DirectoryIndex index.php

4. /etc/init.d/apache2 restart

Thursday, September 6, 2012

How to Save Empty Form Fields as NULL in Symfony

If you leave a field empty in your form, Symfony will save it as a blank value. However sometimes you want to save it as NULL...

Create a method for the field in the form class:
  public function updateManufacturerColumn($value)
  {
    return (!$value) ? null : $value;
  }
Manufacturer is the name of the field now.

Post Validator in Symfony

  public function configure()
  {
    $this->getValidator('day')->setOption('required', 'true');
    
    $this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
      new sfValidatorCallback(array('callback' => array($this, 'checkFields'))),
    )));
  }
  
  public function checkFields($validator, $values)
  {
    if(empty($values['manufacturer']) && empty($values['category_apollo_kod']) && empty($values['product_apollo_kod']))
    {
      throw new sfValidatorErrorSchema($validator, array('manufacturer' => new sfValidatorError($validator, 'custom error')));
    }
     
    return $values;
  }

Wednesday, August 22, 2012

Debian: Install NTPD To Synchronism Clock With Internet Standard Time Servers

date
apt-get install ntp
(wait....)
date
(works like a charm)

Wednesday, July 11, 2012

Using Validators in Actions in Symfony

Check whether an email address is valid or not with sfValidatorEmail:
$v = new sfValidatorEmail();
try {
  $v->clean(trim($email));
} catch (sfValidatorError $e) {
  // not valid
}

Tuesday, July 10, 2012

phpMyAdmin: No activity within 1440 seconds

At the end of /etc/phpmyadmin/config.inc.php:
$cfg['LoginCookieValidity'] = 60 * 60 * 8;

/etc/php5/apache2/php.ini:
session.gc_maxlifetime = 30000

Thursday, July 5, 2012

Log to Custom Log File in Symfony

$logger = new sfFileLogger($this->getContext()->getEventDispatcher(), array('file' => sfConfig::get('sf_log_dir').'/CronSendOrderEmail.log'));

Wednesday, July 4, 2012

Symfony Email Validator Accepts Accents

Use this validator to ignore accents:

  1. Put this after sfCoreAutoload::register(); in config/ProjectConfiguration.class.php:
    require_once dirname(__FILE__).'/../lib/validator/sfValidatorEmail.class.php';
  2. Create lib/validator/sfValidatorEmail.class.php with this content:
class sfValidatorEmail extends sfValidatorRegex
{
   // const REGEX_EMAIL = '/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i';
  // const REGEX_EMAIL = '/^([^@öüóőúéáűíÖÜÓŐÚÉÁŰÍ\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i';
  
  const REGEX_EMAIL = '/^([A-Z0-9._%+-]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i';
  /**
   * @see sfValidatorRegex
   */
  protected function configure($options = array(), $messages = array())
  {
    parent::configure($options, $messages);
    $this->setOption('pattern', self::REGEX_EMAIL);
  }
}

Friday, June 29, 2012

Sign a JAR File That Never Expires

  1. Download Java JDK.
  2. Go to the JDK bin folder with command prompt with full administrator access/permission.
  3. Create a certificate that expires 50 years later: keytool -genkey -alias sakra -validity 18250
    Give a password and some information.
  4. Run: jarsigner jarname.jar sakra
    It prompts the password you gave for the certificate. It put my jar file to the bin folder! It is easier.
  5. That's all, it is signed.

Saturday, June 23, 2012

Symfony 1.4 Tweak Guide by Fabien

Source:  http://trac.symfony-project.org/browser/doc/branches/1.4/gentle-introduction/en/18-Performance.markdown?rev=28950

Chapter 18 - Performance
========================

If you expect your website will attract a crowd, performance and optimization issues should be a major factor during the development phase. Rest assured, performance has always been a chief concern among the core symfony developers.

While the advantages gained by accelerating the development process result in some overhead, the core symfony developers have always been cognizant of performance requirements. Accordingly, every class and every method have been closely inspected and optimized to be as fast as possible. The basic overhead, which you can measure by comparing the time to display a "hello, world" message with and without symfony, is minimal. As a result, the framework is scalable and reacts well to stress tests. And as the ultimate proof, some websites with [extremely](http://sf-to.org/answers) [high](http://sf-to.org/delicious) [traffic](http://sf-to.org/dailymotion)   (that is, websites with millions of active subscribers and a lot of server-pressuring Ajax interactions) use symfony and are very satisfied with its performance.

But, of course, high-traffic websites often have the means to expand the server farm and upgrade hardware as they see fit. If you don't have the resources to do this, or if you want to be sure the full power of the framework is always at your disposal, there are a few tweaks that you can use to further speed up your symfony application. This chapter lists some of the recommended performance optimizations at all levels of the framework and they are mostly for advanced users. Some of them were already mentioned throughout the previous chapters, but you will find it useful to have them all in one place.

Tweaking the Server
-------------------

A well-optimized application should rely on a well-optimized server. You should know the basics of server performance to make sure there is no bottleneck outside symfony. Here are a few things to check to make sure that your server isn't unnecessarily slow.

Having `magic_quotes_gpc` turned `true` in the `php.ini` slows down an application, because it tells PHP to escape all quotes in request parameters, but symfony will systematically unescape them afterwards, and the only consequence will be a loss of time--and quotes-escaping problems on some platforms. Therefore, turn this setting off if you have access to the PHP configuration.

The more recent PHP release you use, the better (PHP 5.3 is faster than PHP 5.2). So make sure you upgrade your PHP version to benefit from the latest performance improvements.

The use of a PHP accelerator (such as APC, XCache, or eAccelerator) is almost compulsory for a production server, because it can make PHP run an average 50% faster, with no tradeoff. Make sure you install one of the accelerator extensions to feel the real speed of PHP.

On the other hand, make sure you deactivate any debug utility, such as the Xdebug or APD extension, in your production server.

>**NOTE**
>You might be wondering about the overhead caused by the `mod_rewrite` extension: it is negligible. Of course, loading an image with rewriting rules is slower than loading an image without, but the slowdown is orders of magnitude below the execution of any PHP statement.

>**TIP**
>When one server is not enough, you can still add another and use load balancing. As long as the `uploads/` directory is shared and you use database storage for sessions, a symfony project will react seamlessly in a load-balanced architecture.

Tweaking the Model
------------------

In symfony, the model layer has the reputation of being the slowest part. If benchmarks show that you have to optimize this layer, here are a few possible improvements.

### Optimizing Propel Integration

Initializing the model layer (the core Propel classes) takes some time, because of the need to load a few classes and construct various objects. However, because of the way symfony integrates Propel, these initialization tasks occur only when an action actually needs the model--and as late as possible. The Propel classes will be initialized only when an object of your generated model is autoloaded. This means pages that don't use the model are not penalized by the model layer.

If your entire application doesn't require the use of the model layer, you can also save the initialization of the `sfDatabaseManager` by switching the whole layer off in your `settings.yml`:

    all:
      .settings:
        use_database: false

The generated model classes (in `lib/model/om/`) are already optimized--they don't contain comments, and they benefit from the autoloading system. Relying on autoloading instead of manually including files means that classes are loaded only if it is really necessary. So in case one model class is not needed, having classes autoloaded will save execution time, while the alternative method of using `include` statements won't. As for the comments, they document the use of the generated methods but lengthen the model files--resulting in a minor overhead on slow disks. As the generated method names are pretty explicit, the comments are turned off by default.

These two enhancements are symfony-specific, but you can revert to the Propel defaults by changing two settings in your `propel.ini` file, as follows:

    propel.builder.addIncludes = true   # Add include statements in generated classes
                                        # Instead of relying on the autoloading system
    propel.builder.addComments = true   # Add comments to generated classes

### Limiting the Number of Objects to Hydrate

When you use a method of a peer class to retrieve objects, your query goes through the hydrating process (creating and populating objects based on the rows of the result of the query). For instance, to retrieve all the rows of the `article` table with Propel, you usually do the following:

    [php]
    $articles = ArticlePeer::doSelect(new Criteria());

The resulting `$articles` variable is an array of objects of class `Article`. Each object has to be created and initialized, which takes time. This has one major consequence: Contrary to direct database queries, the speed of a Propel query is directly proportional to the number of results it returns. This means your model methods should be optimized to return only a given number of results. When you don't need all the results returned by a `Criteria`, you should limit it with the `setLimit()` and `setOffset()` methods. For instance, if you need only the rows 10 to 20 of a particular query, refine the `Criteria` as in Listing 18-1.

Listing 18-1 - Limiting the Number of Results Returned by a Criteria

    [php]
    $c = new Criteria();
    $c->setOffset(10);  // Offset of the first record returned
    $c->setLimit(10);   // Number of records returned
    $articles = ArticlePeer::doSelect($c);

This can be automated by the use of a pager. The `sfPropelPager` object automatically handles the offset and the limit of a Propel query to hydrate only the objects required for a given page.

### Minimizing the Number of Queries with Joins

During application development, you should keep an eye on the number of database queries issued by each request. The web debug toolbar shows the number of queries for each page, and clicking the little database icon reveals the SQL code of these queries. If you see the number of queries rising abnormally, it is time to consider using a Join.

Before explaining the Join methods, let's review what happens when you loop over an array of objects and use a Propel getter to retrieve details about a related class, as in Listing 18-2. This example supposes that your schema describes an `article` table with a foreign key to an `author` table.

Listing 18-2 - Retrieving Details About a Related Class in a Loop

    [php]
    // In the action
    $this->articles = ArticlePeer::doSelect(new Criteria());

    // Database query issued by doSelect()
    SELECT article.id, article.title, article.author_id, ...
    FROM   article

    // In the template
   
       
         
  • getTitle() ?>,
  •         written by getAuthor()->getName() ?>
       
       

    If the `$articles` array contains ten objects, the `getAuthor()` method will be called ten times, which in turn executes one database query each time it is called to hydrate one object of class `Author`, as in Listing 18-3.

    Listing 18-3 - Foreign Key Getters Issue One Database Query

        [php]
        // In the template
        $article->getAuthor()

        // Database query issued by getAuthor()
        SELECT author.id, author.name, ...
        FROM   author
        WHERE  author.id = ?                // ? is article.author_id

    So the page of Listing 18-2 will require a total of 11 queries: the one necessary to build the array of `Article` objects, plus the 10 queries to build one `Author` object at a time. This is a lot of queries to display only a list of articles and their author.

    If you were using plain SQL, you would know how to reduce the number of queries to only one by retrieving the columns of the `article` table and those of the `author` table in the same query. That's exactly what the `doSelectJoinAuthor()` method of the `ArticlePeer` class does. It issues a slightly more complex query than a simple `doSelect()` call, but the additional columns in the result set allow Propel to hydrate both `Article` objects and the related `Author` objects. The code of Listing 18-4 displays exactly the same result as Listing 18-2, but it requires only one database query to do so rather than 11 and therefore is faster.

    Listing 18-4 - Retrieving Details About Articles and Their Author in the Same Query

        [php]
        // In the action
        $this->articles = ArticlePeer::doSelectJoinAuthor(new Criteria());

        // Database query issued by doSelectJoinAuthor()
        SELECT article.id, article.title, article.author_id, ...
               author.id, author.name, ...
        FROM   article, author
        WHERE  article.author_id = author.id

        // In the template (unchanged)
       
         
           
    • getTitle() ?>,
    •         written by getAuthor()->getName() ?>
         
         

      There is no difference in the result returned by a `doSelect()` call and a `doSelectJoinXXX()` method; they both return the same array of objects (of class Article in the example). The difference appears when a foreign key getter is used on these objects afterwards. In the case of `doSelect()`, it issues a query, and one object is hydrated with the result; in the case of `doSelectJoinXXX()`, the foreign object already exists and no query is required, and the process is much faster. So if you know that you will need related objects, call a `doSelectJoinXXX()` method to reduce the number of database queries--and improve the page performance.

      The `doSelectJoinAuthor()` method is automatically generated when you call a `propel-build-model` because of the relationship between the `article` and `author` tables. If there were other foreign keys in the article table structure--for instance, to a category table--the generated `BaseArticlePeer` class would have other Join methods, as shown in Listing 18-5.

      Listing 18-5 - Example of Available `doSelect` Methods for an `ArticlePeer` Class

          [php]
          // Retrieve Article objects
          doSelect()

          // Retrieve Article objects and hydrate related Author objects
          doSelectJoinAuthor()

          // Retrieve Article objects and hydrate related Category objects
          doSelectJoinCategory()

          // Retrieve Article objects and hydrate related objects except Author
          doSelectJoinAllExceptAuthor()

          // Synonym of
          doSelectJoinAll()

      The peer classes also contain Join methods for `doCount()`. The classes with an i18n counterpart (see Chapter 13) provide a `doSelectWithI18n()` method, which behaves the same as Join methods but for i18n objects. To discover the available Join methods in your model classes, you should inspect the generated peer classes in `lib/model/om/`. If you don't find the Join method needed for your query (for instance, there is no automatically generated Join method for many-to-many relationships), you can build it yourself and extend your model.

      >**TIP**
      >Of course, a `doSelectJoinXXX()` call is a bit slower than a call to `doSelect()`, so it only improves the overall performance if you use the hydrated objects afterwards.

      ### Avoid Using Temporary Arrays

      When using Propel, objects are already hydrated, so there is no need to prepare a temporary array for the template. Developers not used to ORMs usually fall into this trap. They want to prepare an array of strings or integers, whereas the template can rely directly on an existing array of objects. For instance, imagine that a template displays the list of all the titles of the articles present in the database. A developer who doesn't use OOP would probably write code similar to what is shown in Listing 18-6.

      Listing 18-6 - Preparing an Array in the Action Is Useless If You Already Have One

          [php]
          // In the action
          $articles = ArticlePeer::doSelect(new Criteria());
          $titles = array();
          foreach ($articles as $article)
          {
            $titles[] = $article->getTitle();
          }
          $this->titles = $titles;

          // In the template
         
           
             
      •    
           

        The problem with this code is that the hydrating is already done by the `doSelect()` call (which takes time), making the `$titles` array superfluous, since you can write the same code as in Listing 18-7. So the time spent to build the `$titles` array could be gained to improve the application performance.

        Listing 18-7 - Using an Array of Objects Exempts You from Creating a Temporary Array

            [php]
            // In the action
            $this->articles = ArticlePeer::doSelect(new Criteria());

            // In the template
           
             
               
        • getTitle() ?>
        •    
             

          If you feel that you really need to prepare a temporary array because some processing is necessary on objects, the right way to do so is to create a new method in your model class that directly returns this array. For instance, if you need an array of article titles and the number of comments for each article, the action and the template should look like Listing 18-8.

          Listing 18-8 - Using a Custom Method to Prepare a Temporary Array

              [php]
              // In the action
              $this->articles = ArticlePeer::getArticleTitlesWithNbComments();

              // In the template
             
               
                 
          • ( comments)
          •    
               

            It's up to you to build a fast-processing `getArticleTitlesWithNbComments()` method in the model--for instance, by bypassing the whole object-relational mapping and database abstraction layers.

            ### Bypassing the ORM

            When you don't really need objects but only a few columns from various tables, as in the previous example, you can create specific methods in your model that bypass completely the ORM layer. You can directly call the database with PDO, for instance, and return a custom-built array. Listing 18-9 illustrates this idea.

            Listing 18-9 - Using Direct PDO Access for Optimized Model Methods, in `lib/model/ArticlePeer.php`

                [php]
                class ArticlePeer extends BaseArticlePeer
                {
                  public static function getArticleTitlesWithNbComments()
                  {
                    $connection = Propel::getConnection();
                    $query = 'SELECT %s as title, COUNT(%s) AS nb FROM %s LEFT JOIN %s ON %s = %sGROUP BY %s';
                    $query = sprintf($query,
                      ArticlePeer::TITLE, CommentPeer::ID,
                      ArticlePeer::TABLE_NAME, CommentPeer::TABLE_NAME,
                      ArticlePeer::ID, CommentPeer::ARTICLE_ID,
                      ArticlePeer::ID
                    );

                    $statement = $connection->prepare($query);
                    $statement->execute();

                    $results = array();
                    while ($resultset = $statement->fetch(PDO::FETCH_OBJ))
                    {
                      $results[] = array($resultset->title, $resultset->nb);
                    }

                    return $results;
                  }
                }

            When you start building these sorts of methods, you may end up writing one custom method for each action, and lose the benefit of the layer separation--not to mention the fact that you lose database-independence.

            ### Speeding Up the Database

            There are many database-specific optimization techniques that can be applied regardless of whether you're using symfony. This section briefly outlines the most common database optimization strategies, but a good knowledge of database engines and administration is required to get the most out of your model layer.

            >**TIP**
            >Remember that the web debug toolbar displays the time taken by each query in a page, and that every tweak should be monitored to determine whether it really improves performance.

            Table queries are often based on non-primary key columns. To improve the speed of such queries, you should define indexes in your database schema. To add a single column index, add the `index: true` property to the column definition, as in Listing 18-10.

            Listing 18-10 - Adding a Single Column Index, in `config/schema.yml`

                propel:
                  article:
                    id:
                    author_id:
                    title: { type: varchar(100), index: true }

            You can use the alternative `index: unique` syntax to define a unique index instead of a classic one. You can also define multiple column indices in `schema.yml` (refer to Chapter 8 for more details about the indexing syntax). You should strongly consider doing this, because it is often a good way to speed up a complex query.

            After adding an index to a schema, you should do the same in the database itself, either by issuing an `ADD INDEX` query directly in the database or by calling the `propel-build-all` command (which will not only rebuild the table structure, but also erase all the existing data).

            >**TIP**
            >Indexing tends to make `SELECT` queries faster, but `INSERT`, `UPDATE`, and `DELETE` queries are slower. Also, database engines use only one index per query, and they infer the index to be used for each query based on internal heuristics. Adding an index can sometimes be disappointing in terms of performance boost, so make sure you measure the improvements.

            Unless specified otherwise, each request uses a single database connection in symfony, and the connection is closed at the end of the request. You can enable persistent database connections to use a pool of database connections that remain open between queries, by setting `persistent: true` in the `databases.yml` file, as shown in Listing 18-11.

            Listing 18-11 - Enabling Persistent Database Connection Support, in `config/databases.yml`

                prod:
                  propel:
                    class:         sfPropelDatabase
                    param:
                      dsn:         mysql:dbname=example;host=localhost
                      username:    username
                      password:    password
                      persistent:  true      # Use persistent connections

            This may or may not improve the overall database performance, depending on numerous factors. The documentation on the subject is abundant on the Internet. Make sure you benchmark your application performance before and after changing this setting to validate its interest.

            >**SIDEBAR**
            >MySQL-specific tips
            >
            >Many settings of the MySQL configuration, found in the my.cnf file, may alter database performance. Make sure you read the online [documentation](http://dev.mysql.com/doc/refman/5.0/en/option-files.html) on this subject.
            >
            >One of the tools provided by MySQL is the slow queries log. All SQL statements that take more than `long_query_time` seconds to execute (this is a setting that can be changed in the `my.cnf`) are logged in a file that is quite difficult to construe by hand, but that the `mysqldumpslow` command summarizes usefully. This is a great tool to detect the queries that require optimizations.

            Tweaking the View
            -----------------

            According to how you design and implement the view layer, you may notice small slowdowns or speedups. This section describes the alternatives and their tradeoffs.

            ### Using the Fastest Code Fragment

            If you don't use the caching system, you have to be aware that an `include_component()` is slightly slower than an `include_partial()`, which itself is slightly slower than a simple PHP `include`. This is because symfony instantiates a view to include a partial and an object of class `sfComponent` to include a component, which collectively add some minor overhead beyond what's required to include the file.

            However, this overhead is insignificant, unless you include a lot of partials or components in a template. This may happen in lists or tables, and every time you call an `include_partial()` helper inside a `foreach` statement. When you notice that a large number of partial or component inclusions have a significant impact on your performance, you may consider caching (see Chapter 12), and if caching is not an option, then switch to simple `include` statements.

            As for slots, the difference in performance is perceptible. The process time necessary to set and include a slot is negligible--it is equivalent to a variable instantiation. Slots are always cached within the template that includes them.

            ### Speeding Up the Routing Process

            As explained in Chapter 9, every call to a link helper in a template asks the routing system to process an internal URI into an external URL. This is done by finding a match between the URI and the patterns of the `routing.yml` file. Symfony does it quite simply: It tries to match the first rule with the given URI, and if it doesn't work, it tries with the following, and so on. As every test involves regular expressions, this is quite time consuming.

            There is a simple workaround: Use the rule name instead of the module/action couple. This will tell symfony which rule to use, and the routing system won't lose time trying to match all previous rules.

            In concrete terms, consider the following routing rule, defined in your `routing.yml` file:

                article_by_id:
                  url:          /article/:id
                  param:        { module: article, action: read }

            Then instead of outputting a hyperlink this way:

                [php]
                getId()) ?>

            you should use the fastest version:

                [php]
                getId()) ?>

            The difference starts being noticeable when a page includes a few dozen routed hyperlinks.

            ### Skipping the Template

            Usually, a response is composed of a set of headers and content. But some responses don't need content. For instance, some Ajax interactions need only a few pieces of data from the server in order to feed a JavaScript program that will update different parts of the page. For this kind of short response, a set of headers alone is faster to transmit. As discussed in Chapter 11, an action can return only a JSON header. Listing 18-12 reproduces an example from Chapter 11.

            Listing 18-12 - Example Action Returning a JSON Header

                [php]
                public function executeRefresh()
                {
                  $output = '{"title":"My basic letter","name":"Mr Brown"}';
                  $this->getResponse()->setHttpHeader("X-JSON", '('.$output.')');

                  return sfView::HEADER_ONLY;
                }

            This skips the template and the layout, and the response can be sent at once. As it contains only headers, it is more lightweight and will take less time to transmit to the user.

            Chapter 6 explained another way to skip the template by returning content text directly from the action. This breaks the MVC separation, but it can increase the responsiveness of an action greatly. Check Listing 18-13 for an example.

            Listing 18-13 - Example Action Returning Content Text Directly

                [php]
                public function executeFastAction()
                {
                  return $this->renderText("Hello, World!");
                }

            Tweaking the Cache
            ------------------

            Chapter 12 already described how to cache parts of a response or all of it. The response cache results in a major performance improvement, and it should be one of your first optimization considerations. If you want to make the most out of the cache system, read further, for this section unveils a few tricks you might not have thought of.

            ### Clearing Selective Parts of the Cache

            During application development, you have to clear the cache in various situations:

              * When you create a new class: Adding a class to an autoloading directory (one of the project's `lib/` folders) is not enough to have symfony find it automatically in non-development environments. You must clear the autoloading configuration cache so that symfony browses again all the directories of the `autoload.yml` file and references the location of autoloadable classes--including the new ones.
              * When you change the configuration in production: The configuration is parsed only during the first request in production. Further requests use the cached version instead. So a change in the configuration in the production environment (or any environment where debug is turned off) doesn't take effect until you clear the cached version of the file.
              * When you modify a template in an environment where the template cache is enabled: The valid cached templates are always used instead of existing templates in production, so a template change is ignored until the template cache is cleared or outdated.
              * When you update an application with the `project:deploy` command: This case usually covers the three previous modifications.

            The problem with clearing the whole cache is that the next request will take quite long to process, because the configuration cache needs to be regenerated. Besides, the templates that were not modified will be cleared from the cache as well, losing the benefit of previous requests.

            That means it's a good idea to clear only the cache files that really need to be regenerated. Use the options of the `cache:clear` task to define a subset of cache files to clear, as demonstrated in Listing 18-14.

            Listing 18-14 - Clearing Only Selective Parts of the Cache

                // Clear only the cache of the frontend application
                $ php symfony cache:clear frontend

                // Clear only the HTML cache of the frontend application
                $ php symfony cache:clear frontend template

                // Clear only the configuration cache of the frontend application
                $ php symfony cache:clear frontend config

            You can also remove files by hand in the `cache/` directory, or clear template cache files selectively from the action with the `$cacheManager->remove()` method, as described in Chapter 12.

            All these techniques will minimize the negative performance impact of any of the changes listed previously.

            >**TIP**
            >When you upgrade symfony, the cache is automatically cleared, without manual intervention (if you set the `check_symfony_version` parameter to `true` in `settings.yml`).

            ### Generating Cached Pages

            When you deploy a new application to production, the template cache is empty. You must wait for users to visit a page once for this page to be put in the cache. In critical deployments, the overhead of page processing is not acceptable, and the benefits of caching must be available as soon as the first request is issued.

            The solution is to automatically browse the pages of your application in the staging environment (where the configuration is similar to the one in production) to have the template cache generated, then to transfer the application with the cache to production.

            To browse the pages automatically, one option is to create a shell script that looks through a list of external URLs with a browser (curl for instance). But there is a better and faster solution: a PHP script using the `sfBrowser` object, already discussed in Chapter 15. That's an internal browser written in PHP (and used by `sfTestFunctional` for functional tests). It takes an external URL and returns a response, but the interesting thing is that it triggers the template cache just like a regular browser. As it only initializes symfony once and doesn't pass by the HTTP transport layer, this method is a lot faster.

            Listing 18-15 shows an example script used to generate template cache files in a staging environment. Launch it by calling `php generate_cache.php`.

            Listing 18-15 - Generating the Template Cache, in `generate_cache.php`

                [php]
                require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
                $configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'staging', false);
                sfContext::createInstance($configuration);

                // Array of URLs to browse
                $uris = array(
                  '/foo/index',
                  '/foo/bar/id/1',
                  '/foo/bar/id/2',
                  ...
                );

                $b = new sfBrowser();
                foreach ($uris as $uri)
                {
                  $b->get($uri);
                }

            ### Using a Database Storage System for Caching

            The default storage system for the template cache in symfony is the file system: Fragments of HTML or serialized response objects are stored under the `cache/` directory of a project. Symfony proposes an alternative way to store cache: a SQLite database. Such a database is a simple file that PHP natively knows how to query very efficiently.

            To tell symfony to use SQLite storage instead of file system storage for the template cache, open the `factories.yml` file and edit the `view_cache` entry as follows:

                view_cache:
                  class: sfSQLiteCache
                  param:
                    database: %SF_TEMPLATE_CACHE_DIR%/cache.db

            The benefits of using SQLite storage for the template cache are faster read and write operations when the number of cache elements is important. If your application makes heavy use of caching, the template cache files end up scattered in a deep file structure; in this case, switching to SQLite storage will increase performance. In addition, clearing the cache on file system storage may require a lot of files to be removed from the disk; this operation may last a few seconds, during which your application is unavailable. With a SQLite storage system, the cache clearing process results in a single file operation: the deletion of the SQLite database file. Whatever the number of cache elements currently stored, the operation is instantaneous.

            ### Bypassing Symfony

            Perhaps the best way to speed symfony up is to bypass it completely... this is said only partly in jest. Some pages don't change and don't need to be reprocessed by the framework at each request. The template cache is already here to speed up the delivery of such pages, but it still relies on symfony.

            A couple of tricks described in Chapter 12 allow you to bypass symfony completely for some pages. The first one involves the use of HTTP 1.1 headers for asking the proxies and client browsers to cache the page themselves, so that they don't request it again the next time the page is needed. The second one is the super fast cache (automated by the `sfSuperCachePlugin` plug-in), which consists of storing a copy of the response in the `web/` directory and modifying the rewriting rules so that Apache first looks for a cached version before handing a request to symfony.

            Both these methods are very effective, and even if they only apply to static pages, they will take the burden of handling these pages off from symfony, and the server will then be fully available to deal with complex requests.

            ### Caching the Result of a Function Call

            If a function doesn't rely on context-sensitive values nor on randomness, calling it twice with the same parameters should return the same result. That means the second call could very well be avoided if the result had been stored the first time. That's exactly what the `sfFunctionCache` class does. This class has a `call()` method, which expects a callable and an array of parameters as its arguments. When called, this method creates an md5 hash with all its arguments and looks in the cache for a key named by this hash. If such a key is found, the function returns the result stored in the cache. If not, the `sfFunctionCache` executes the function, stores the result in the cache, and returns it. So the second execution of Listing 18-16 will be faster than the first one.

            Listing 18-16 - Caching the Result of a Function

                [php]
                $cache = new sfFileCache(array('cache_dir' => sfConfig::get('sf_cache_dir').'/function'));
                $fc = new sfFunctionCache($cache);
                $result1 = $fc->call('cos', array(M_PI));
                $result2 = $fc->call('preg_replace', array('/\s\s+/', ' ', $input));

            The `sfFunctionCache` constructor expects a cache object. The first argument of the `call()` method must be a callable, so it can be a function name, an array of a class name and static method name, or an array of an object name and public method name. As for the other argument of the `call()` method, it's an array of arguments that will be passed to the callable.

            >**CAUTION**
            >If you use a file based cache object as in the example, it's better to give a cache directory under the `cache/` directory, as it will be cleanup automatically by the `cache:clear` task. If you store the function cache somewhere else, it will not be cleared automatically when you clear the cache through the command line.

            ### Caching Data in the Server

            PHP accelerators provide special functions to store data in memory so that you can reuse it across requests. The problem is that they all have a different syntax, and each has its own specific way of performing this task. The symfony cache classes abstract all these differences and works with whatever accelerator you are using. See its syntax in Listing 18-17.

            Listing 18-17 - Using a PHP accelerator to cache data

                [php]
                $cache = new sfAPCCache();

                // Storing data in the cache
                $cache->set($name, $value, $lifetime);

                // Retrieving data
                $value = $cache->get($name);

                // Checking if a piece of data exists in the cache
                $value_exists = $cache->has($name);

                // Clear the cache
                $cache->clear();

            The `set()` method returns `false` if the caching didn't work. The cached value can be anything (a string, an array, an object); the `sfAPCCache` class will deal with the serialization. The `get()` method returns `null` if the required variable doesn't exist in the cache.

            >**TIP**
            >If you want to go further into memory caching, make sure you take a look at the `sfMemcacheCache` class. It provides the same interface as the other cache classes and it can help decrease the database load on load-balanced applications.

            Deactivating the Unused Features
            --------------------------------

            The default symfony configuration activates the most common features of a web application. However, if you happen to not need all of them, you should deactivate them to save the time their initialization takes on each request.

            For instance, if your application doesn't use the session mechanism, or if you want to start the session handling by hand, you should turn the `auto_start` setting to `false` in the `storage` key of the `factories.yml` file, as in Listing 18-18.

            Listing 18-18 - Turning Sessions Off, in `frontend/config/factories.yml`

                all:
                  storage:
                    class: sfSessionStorage
                    param:
                      auto_start: false

            The same applies for the database feature (as explained in the "Tweaking the Model" section earlier in this chapter). If your application makes no use of a database, deactivate it for a small performance gain, this time in the `settings.yml` file (see Listing 18-19).

            Listing 18-19 - Turning Database Features Off, in `frontend/config/settings.yml`

                all:
                  .settings:
                    use_database:      false    # Database and model features

            As for the security features (see Chapter 6), you can deactivate them in the `filters.yml` file, as shown in Listing 18-20.

            Listing 18-20 - Turning Features Off, in `frontend/config/filters.yml`

                rendering: ~
                security:
                  enabled: false

                # generally, you will want to insert your own filters here

                cache:     ~
                execution: ~

            Some features are useful only in development, so you should not activate them in production. This is already the case by default, since the production environment in symfony is really optimized for performance. Among the performance-impacting development features, the debug mode is the most severe. As for the symfony logs, the feature is also turned off in production by default.

            You may wonder how to get information about failed requests in production if logging is disabled, and argue that problems arise not only in development. Fortunately, symfony can use the `sfErrorLoggerPlugin` plug-in, which runs in the background in production and logs the details of 404 and 500 errors in a database. It is much faster than the file logging feature, because the plug-in methods are called only when a request fails, while the logging mechanism, once turned on, adds a non-negligible overhead whatever the level. Check the installation instructions and [manual](http://plugins.symfony-project.org/plugins/sfErrorLoggerPlugin).

            >**TIP**
            >Make sure you regularly check the server error logs--they also contain very valuable information about 404 and 500 errors.

            Optimizing Your Code
            --------------------

            It's also possible to speed up your application by optimizing the code itself. This section offers some insight regarding how to do that.

            ### Core Compilation

            Loading ten files requires more I/O operations than loading one long file, especially on slow disks. Loading a very long file requires more resources than loading a smaller file--especially if a large share of the file content is of no use for the PHP parser, which is the case for comments.

            So merging a large number of files and stripping out the comments they contain is an operation that improves performance. Symfony already does that optimization; it's called the core compilation. At the beginning of the first request (or after the cache is cleared), a symfony application concatenates all the core framework classes (`sfActions`, `sfRequest`, `sfView`, and so on) into one file, optimizes the file size by removing comments and double blanks, and saves it in the cache, in a file called `config_core_compile.yml.php`. Each subsequent request only loads this single optimized file instead of the 30 files that compose it.

            If your application has classes that must always be loaded, and especially if they are big classes with lots of comments, it may be beneficial to add them to the core compile file. To do so, just add a `core_compile.yml` file in your application `config/` directory, and list in it the classes that you want to add, as in Listing 18-21.

            Listing 18-21 - Adding Your Classes to the Core Compile File, in `frontend/config/core_compile.yml`

                - %SF_ROOT_DIR%/lib/myClass.class.php
                - %SF_ROOT_DIR%/apps/frontend/lib/myToolkit.class.php
                - %SF_ROOT_DIR%/plugins/myPlugin/lib/myPluginCore.class.php
                ...

            ### The `project:optimize` Task

            Symfony also offers another optimization tool, the `project:optimize` task. It applies various optimization strategies to the symfony and application code, which may further speed up the execution.

                $ php symfony project:optimize frontend prod

            If you want to see the optimization strategies implemented in the task, have a look at task source code.

            Summary
            -------

            Symfony is already a very optimized framework and is able to handle high-traffic websites without a problem. But if you really need to optimize your application's performance, tweaking the configuration (whether the server configuration, the PHP configuration, or the application settings) will gain you a small boost. You should also follow good practices to write efficient model methods; and since the database is often a bottleneck in web applications, this point should require all your attention. Templates can also benefit from a few tricks, but the best boost will always come from caching. Finally, don't hesitate to look at existing plug-ins, since some of them provide innovative techniques to further speed up the delivery of web pages (`sfSuperCache`, `project:optimize`).

            Friday, June 22, 2012

            sfPaypalPlugin - Paypal Payment Plugin for Symfony, PAYPAL PLUGIN SYMFONY

            If you need it, please send me a mail to sakramenta [AT] gmail [DOT] com
            Ha szükséged van rá, küldj egy levelet a sakramenta [KUKAC] gmail [PONT] com címre.

            sfQPAYPlugin - QPAY Wirecard Payment Plugin for Symfony, QPAY PLUGIN SYMFONY

            If you need it, please send me a mail to sakramenta [AT] gmail [DOT] com
            Ha szükséged van rá, küldj egy levelet a sakramenta [KUKAC] gmail [PONT] com címre.

            Get Texts or Values From HTML Select Code

            header('Content-type: text/html; charset=utf-8');
            echo $options = file_get_contents('options.txt');
            if(!file_exists('options.txt')) {
              echo "file not exists";
            }
            preg_match_all('/([^>]*)<\/option>/', $options, $matches);
            die('
            '.print_r($matches, true).'
            ');

            Compare MySQL Database Schema

            Use this FREE tool: http://www.quest.com/toad-for-mysql/ 

            Host xxx is not allowed to connect to this MySQL server

            1. Open PHPMYADMIN with root
            2. Go to Privileges
            3. Create a user or modify the user you want to connect with and set the host parameter to %, which means 'all hosts'.

            Open MySQL Port 3306

            1. check: netstat -lpn | grep 3306
            2. /etc/mysql/my.cnf
            3. bind-address -> 0.0.0.0
            4. /etc/init.d/mysql restart
            5. check: netstat -lpn | grep 3306
            6. open port with iptables...

            Monday, June 18, 2012

            jQuery ToolTip : qTip 2

            Download: http://craigsworks.com/projects/qtip2/download/

            My config in $(function () { });
              if($('.registration').length) {
                $('.registration input[type=text], .registration input[type=password], .registration select').qtip({
                  position: {
                    my: 'bottom center', 
                    at: 'top center'
                  },
                  show: {
                    event: 'focus'
                  },
                  hide: {
                    event: 'blur'
                  },
                  style: {
                    tip: true,
                    classes: 'ui-tooltip-dark'
                  }
                });
              }
            

            In the form class...
                // qtip2 i18n tooltips
                $widgetSchema = $this->getWidgetSchema();
                $formFormatter = $widgetSchema->getFormFormatter();
                $addToolTipsFor = array(
                    'email', 'email2', 'password', 'password2',
                    'billing' => array('name', 'country', 'zip', 'city', 'street', 'phone', 'vat_country', 'vat_number'),
                    'shipping' => array('name', 'country', 'zip', 'city', 'street'),
                    'contact' => array('name', 'phone')
                );
                foreach($addToolTipsFor as $key => $input) {
                  if(is_array($input)) {
                    foreach($input as $subinput) {
                      if(isset($widgetSchema[$key][$subinput])) {
                        $widgetSchema[$key][$subinput]->setAttribute('title', $formFormatter->translate($key.'_'.$subinput.'_tooltip'));
                      } else {
                        throw new sfException('No widget: '.$key.' '.$subinput);
                      }
                    }
                  } else {
                    if(isset($widgetSchema[$input])) {
                      $widgetSchema[$input]->setAttribute('title', $formFormatter->translate($input.'_tooltip'));
                    } else {
                      throw new sfException('No widget: '.$input);
                    }
                  }
                }
            
            My CSS:
            .ui-tooltip, .qtip { font-size: 13px !important; line-height: 20px !important; }
            

            Install APC for PHP in CentOS

            yum install pcre-devel gcc httpd-devel php-pear
            pecl install apc
            64bit: restorecon /usr/lib64/php/modules/apc.so
            32bit: restorecon /usr/lib/php/modules/apc.so
            echo "extension=apc.so" > /etc/php.d/apc.ini
            service httpd restart

            Solution: Fatal error: Cannot inherit previously-inherited or override constant LEVEL_TOP from interface Swift_Mime_Message in Symfony

            There is a bug in APC. You need install the latest version of APC to solve the problem between Swiftmailer and APC: Install the Latest APC on Debian

            Friday, June 15, 2012

            sfOTPPlugin - OTP Payment Plugin for Symfony, OTP PLUGIN SYMFONY

            OTP PLUGIN SYMFONY
            If you need it, please send me a mail to sakramenta [AT] gmail [DOT] com
            Ha szükséged van rá, küldj egy levelet a sakramenta [KUKAC] gmail [PONT] com címre.

            Thursday, June 14, 2012

            Default Permission In Linux (Debian)

            Set Default Permission to 777 for FTP:
            1.  /etc/vsftpd.conf
            2. local_umask=000
            3. /etc/init.d/vsftpd restart
            4. ftp clients have to reconnect.

            Monday, June 11, 2012

            List Form Errors in Symfony

            <?php if( $form->hasErrors() || $form->hasGlobalErrors() ) : ?>
              
              <?php foreach( $form->getGlobalErrors() as $name => $error ) : ?>
            • <?php echo $name ?> : <?php echo $error ?>
            • <?php endforeach; ?> <?php $errors = $form->getErrorSchema()->getErrors() ?> <?php if ( count($errors) > 0 ) : ?> <?php foreach( $errors as $name => $error ) : ?>
            • <?php echo $name ?> : <?php echo $error ?>
            • <?php endforeach; ?> <?php endif; ?>
            <?php endif; ?>

            Friday, June 8, 2012

            Doctrine Schema: float(18,4) ?

            Use decimal instead of float in this situation:

                sale_price_eur:
                  type: decimal(18)
                  scale: 4

            Monday, June 4, 2012

            Unzip with PHP

                 if(!class_exists('ZipArchive')) die('ZipArchive missing');
                 $zip = new ZipArchive;
                 $res = $zip->open('my_zip_file.zip');
                 if ($res === TRUE) {
                     $zip->extractTo('my_extract_to_dir/');
                     $zip->close();
                     echo 'ok';
                 } else {
                     echo 'failed';
                 }
            

            Thursday, May 31, 2012

            Install the Latest APC on Debian

            apt-get install php-pear php5-dev apache2-threaded-dev build-essential
            pecl install apc

            Thursday, May 24, 2012

            Calling the i18n Function __() in a Form in Symfony

            Do not use __() in forms! Use translate:

            $this->getWidgetSchema()->getFormFormatter()->translate('exampletext');

            Wednesday, May 23, 2012

            sfDependentSelectPlugin: Cannot set property 'onchange' of null

            From README:

                    // always the selects order has to be according to the dependency.
                    // ich means: country > state > city
                    $this->widgetSchema->moveField('city_id', 'after', 'state_id');


            If you not set the order, you will get a Uncaught TypeError: Cannot set property 'onchange' of null error.

            Wednesday, May 16, 2012

            Sync Datetime in CentOS

            service ntpd stop
            ntpdate time.kfki.hu
            service ntpd start

            ps: or ntpdate pool.ntp.org

            Tuesday, May 15, 2012

            Wednesday, May 9, 2012

            mssql_query Cause net::ERR_EMPTY_RESPONSE in Chrome

            If you get net::ERR_EMPTY_RESPONSE Chrome error message when you want to query some simple select with native mssql_query in PHP, you should set mssql.datetimeconvert = Off in php.ini or use ini_set("mssql.datetimeconvert", false); in the code.

            Tuesday, April 17, 2012

            Add Group to User Automatically when Creating a New User with Form

            Add this to the form...
            public function save($con = null)
              {
                //Do the main save to get an ID
                $user = parent::save($con);
              
                //Add the user to the relevant group, for permissions and authentication
                if (!$user->hasGroup('Dispatchers'))
                {
                  $user->addGroupByName('Dispatchers');
                  $user->save();
                }
              
                return $user;
              }
            

            Friday, April 13, 2012

            Format Datetime in Symfony

            $user->getDateTimeObject('created_at')->format('Y-m-d H:i');
            

            Tuesday, April 10, 2012

            Customize Zend Studio

            Disable AltGr + N to create a New Document
            Windows / Customize Perspective -> Command Groups Availability -> uncheck New PHP Document.

            To open a file by double-clicking in Zend Studio, not in external editor
             Add the file type to the list of file types which will automatically be opened in Zend Studio by doing the following:
            1. From Zend Studio 's Menu Bar, go to Window | Preferences | General | Content Types.
            2. The Content Types dialog will be displayed.
            3. Select Text | PHP Content Type from the list.
            4. A list of file types associated with Zend Studio will be displayed.
            5. Click Add to add your file's type to the list, Enter the file type (e.g. .php) and click OK.
            6. The file type will be added to the list.
            Encoding / character set + Line delimiter:
            Window / Preferences -> General -> Workspace -> Text file encoding -> UTF-8
            +
            New text file line delimiter

            Remove trailing whitespace:
            Window / Preferences -> PHP -> Editor -> Save Actions -> Remove trailing whitespace

            Ctrl + TAB to the next file
            Windows / Preferences -> General -> Keys
            Search for: Previous Editor, Next Editor...

            Default indentation for array initializers

            Window > Preferences > PHP > Code Style > Formatter > Edit... > Line Wrapping
            Set Default indentation for array initializers to 0.

            Mark Occurrences
            Windows / Preferences -> PHP -> Editor -> Mark Occurrences

            Friday, March 23, 2012

            Solved: Chrome Error 139 (net::ERR_TEMPORARILY_THROTTLED)

            1. Open: chrome://net-internals/#httpThrottling
            2. Uncheck the checkbox.
            3. Be happy ASAP.

            Thursday, March 22, 2012

            setValue() For Form Fields in Symfony

            If you want to overwrite the value of a field in an action, you have to a create a new method for the form. Usually  people think that setDefault method is good for that. No. setDefault set a default value to a field. However if the field contains a value, setDefault won't overwrite it. Let's see an example: You put a word to the "location" field then you save the form to the database. after that, you want to see another value in the "location" field:
            // add this method to the form class
            public function setValue($field, $value) {
              // set the value for this request
              $this->values[$field] = $value; 
              // override the value entered by the user
              $this->taintedValues[$field] = $value;
              // force a refresh on the field schema
              $this->resetFormFields();
            }
            
            
            // actions.class.php ... save method ...
            if ($this->form->isValid())
            {
              $this->form->save();
            
              // the magic
              $this->form->setValue('location', 'a new value');
            
              // you can set an empty value also
              $this->form->setValue('location', '');
            
              // if location is a checkbox, you have to set null to uncheck it
              $this->form->setValue('location', null);
            
            ...
            

            Wednesday, March 21, 2012

            Table border-radius With CSS3

            table tr:first-child td:first-child {
              border-top-left-radius: 5px;
            }
            
            table tr:first-child td:last-child {
              border-top-right-radius: 5px;
            }
            
            table tr:last-child td:first-child {
              border-bottom-left-radius: 5px;
            }
            
            table tr:last-child td:last-child {
              border-bottom-right-radius: 5px;
            }
            

            Tuesday, March 20, 2012

            Doctrine Not Save Boolean Value to Database in Symfony

            If you create a boolean field in the database and symfony renders it as a checkbox ( sfWidgetFormInputCheckbox ) in the form... AND DOCTRINE DOES NOT SAVE THE VALUE TO THE DATABASE, you have to a put the boolean validator on it and doctrine will save the value. That's the magic.
                $this->setValidators(array(
                    ...,
                    'enabled' => new sfValidatorBoolean(),
                    ...,
                ));
            

            Monday, March 19, 2012

            Disable Symfony CSRF Protection

            To the form...
            $this->disableLocalCSRFProtection();
            

            Friday, March 9, 2012

            Get Field Comments with Doctrine in Symfony

            In Action:
            $t = Doctrine::getTable('Product'); 
            foreach($t->getColumns() as $key => $column) {
               $comments[$key] = $column['comment'];     
            }
            

            Thursday, March 8, 2012

            Symfony sfConfig Variables

            This page was originally available here: Doggetto.com. However the page is unavailable now, thus I publish this copy.

            Reference to Config Variables

            • Be careful in referencing any app-specific variables in the model in a multi-app project.  If they are not available in the app you are using the model function in you will have problems.
            sfConfig::get('sf_config_variable', 'The default value'); // The default is optional.

            Symfony Framework

            sf_symfony_lib_dir
            The real path to the framework’s lib directory
            (/usr/share/php/symfony/symfony12/lib)

            Project Structure and Layout

            sf_root_dir
            The path to the project root
            (/var/www/project_name)
            sf_apps_dir
            The path to the project’s apps folder
            (/var/www/project_name/apps)
            sf_lib_dir
            The path to the project’s lib folder
            (/var/www/project_name/lib)
            sf_log_dir
            The path to the project’s log folder
            (/var/www/project_name/log)
            sf_data_dir
            The path to the project’s data folder
            (/var/www/project_name/data)
            sf_config_dir
            The path to the project’s config folder
            (/var/www/project_name/config)
            sf_test_dir
            The path to the project’s test folder
            (/var/www/project_name/test)
            sf_doc_dir
            The path to the project’s doc folder
            (/var/www/project_name/doc)
            sf_plugins_dir
            The path to the project’s plugins folder
            (/var/www/project_name/plugins)
            sf_cache_dir
            The path to the project’s plugins folder
            (/var/www/project_name/cache)
            sf_web_dir
            The path to the project’s plugins folder
            (/var/www/project_name/web)
            sf_upload_dir
            The path to the project’s upload folder
            (/var/www/project_name/web/uploads)

            Application Information

            sf_app
            The current application
            (backend)
            sf_environment
            The current environment
            (dev)
            sf_debug
            Whether debugging is enabled
            (1)

            Application Structure and Layout

            sf_app_dir
            The path to the current application
            (/var/www/project_name/apps/backend)
            sf_app_config_dir
            The path to the current application’s config directory
            (/var/www/project_name/apps/backend/config)
            sf_app_lib_dir
            The path to the current application’s lib directory
            (/var/www/project_name/apps/backend/lib)
            sf_app_module_dir
            The path to the current application’s module directory
            (/var/www/project_name/apps/backend/modules)
            sf_app_template_dir
            The path to the current application’s template directory
            (/var/www/project_name/apps/backend/templates)
            sf_app_i18n_dir
            The path to the current application’s i18n directory
            (/var/www/project_name/apps/backend/i18n)

            Cache Structure and Layout

            sf_app_base_cache_dir
            The path to the current application’s directory in the cache
            (/var/www/project_name/cache/backend)
            sf_app_cache_dir
            The path to the current application’s directory in the cache by current environment
            (/var/www/project_name/cache/backend/dev)
            sf_template_cache_dir
            The path to the current application’s templates directory in the cache by current environment
            (/var/www/project_name/cache/backend/dev/template)
            sf_i18n_cache_dir
            The path to the current application’s i18n directory in the cache by current environment
            (/var/www/project_name/cache/backend/dev/i18n)
            sf_config_cache_dir
            The path to the current application’s config directory in the cache by current environment
            (/var/www/project_name/cache/backend/dev/config)
            sf_test_cache_dir
            The path to the current application’s test directory in the cache by current environment
            (/var/www/project_name/cache/backend/dev/test)
            sf_module_cache_dir
            The path to the current application’s modules directory in the cache by current environment
            (/var/www/project_name/cache/backend/dev/modules)

            Application Settings

            You can access any value in settings.yml by prepending “sf_” to the value.
            sf_error_404_module
            The module that contains the 404 action (default)
            sf_error_404_action
            The action that displays the 404 error (error404)
            sf_logging_enabled
            Boolean for whether logging is currently enabled (1)
            sf_escaping_strategy
            Whether the sfView class is using the Escaping Strategy (1)
            sf_no_script_name
            Whether the application is requiring the script name. (1)
            sf_csrf_secret
            The CSRF secret (UniqueSecret)

            Also:

            You can grab some information from the current context (usually in templates, but should work well enough in actions – I’d be very cautious about using these in models):
            sfContext::getInstance()->getActionName();
            The name of the current action.  Can also be called by $this->getActionName() in templates.
            (my_awesome_action)
            sfContext::getInstance()->getModuleName();
            The name of the current module.  Can also be called by $this->getModuleName() in templates.
            (my_awesome_module)
            sfContext::getInstance()->getModuleDirectory();
            The path to the current module’s directory
            (/var/www/project_name/apps/backend/modules/my_awesome_module)

            Thursday, March 1, 2012

            Useful jQuery Tips

            Check if a checkbox is checked:
            if($('#checkbox').is(':checked')) ...

            Check if a select option is selected:
            if($('#select option:selected').length()) ...

            Get the selected radio value:
            $('.radio:checked').val()

            Get all inputs with a classname begins with rescheck:
              $("input[class^=rescheck-]").each(
                function() {
                  alert($(this).attr('class'));
                }
              );

            Jump to ( Scroll To ) an element:
            $('html, body').animate({ scrollTop: $("#some_element").offset().top }, 500);

            Checking to see if there is an attribute on an element:
            var attr = $(this).attr('name');
            if (typeof attr !== 'undefined' && attr !== false) {}

            Clear selection on select:
            $("#my_select option:selected").removeAttr("selected");

            Ajax request and putting the result array into a select:

              $.post("/url", function(data) {
                var selected = '';
                $.each(data, function(key, data) {
                  $('#foobar').append("");
                });
              });

            Thursday, February 23, 2012

            Symfony Build: Fatal error: Allowed memory size of x bytes exhausted

            If you run a symfony command, it is run by php cli, not apache.
            So increase the memory_limit to 128M in the /etc/php5/cli/php.ini file. Building will work fine.:)

            Create Plugin in Symfony

            1. Install: sfTaskExtraPlugin
            2. Generate a plugin (example): symfony generate:plugin sfPaypalPlugin
            3. Generate a module (paypal) in a plugin (sfPaypalPlugin): symfony generate:plugin-module sfPaypalPlugin paypal

            Wednesday, February 22, 2012

            Allow Website from Fix IPs in Apache

            Add this to the directory configuration in virtualhost:

            Order Deny, Allow
            Deny from All
            Allow from 110.70.55.154 10.0.0. 173.0.82.126 127.0.0.1

            Disable Apache Server Signature

            Add ServerSignature Off to virtualhost configuration. Restart Apache.

            Remove Accents in String with ICONV

            Don't forget: Iconv translit is locale sensitive. You must first set locale:
            // remove hungarian accents
            // magyar ékezetek eltávolítása
            setlocale(LC_ALL, 'hu_HU.UTF8');
            $text = iconv('UTF-8', 'ASCII//TRANSLIT', 'árvíztűrő tükörfúrógép');
            echo $text = str_replace(array('\'', '"', ':'), array(), $text);
            

            url_for Helper in Action in Symfony

            $this->getContext()->getConfiguration()->loadHelpers(array('Url'));
            // now you can use url_for()
            

            Tuesday, February 21, 2012

            Install Symfony Plugin: Warning: require_once(PEAR.php): failed to open stream

            1. If you try to install a plugin (ex. prestaPaypalPlugin) with symfony cli and get something like this...
              sakra:/var/www/sakra# ./symfony plugin:install prestaPaypalPlugin
              >> plugin    installing plugin "prestaPaypalPlugin"
              Warning: require_once(PEAR.php): failed to open stream: No such file or directory in mnt/vol1/vol1/www/sakra/lib/vendor/symfony/lib/plugin/sfPearEnvironment.class.php on line 15
              Fatal error: require_once(): Failed opening required 'PEAR.php' (include_path='.:/usr/share/php:/usr/share/pear') in /mnt/vol1/vol1/www/sakra/lib/vendor/symfony/lib/plugin/sfPearEnvironment.class.php on line 15
            2. Run: apt-get update
            3. Run: apt-get install php-pear
            4. Run again: ./symfony plugin:install prestaPaypalPlugin
            5. If you get an error like this...
              No release available for plugin "prestaPaypalPlugin" in state "stable"
            6. Run with -s parameter (to enable beta plugins): ./symfony plugin:install -s beta prestaPaypalPlugin

            Parse YML (Yaml) Files In Action in Symfony

            $myarray = sfYaml::load(sfConfig::get('sf_config_dir').'/myconf.yml');

            Monday, February 20, 2012

            Disable Symfony Application for Maintenance

            1. Put check_lock: true inside the (ex.) prod section of apps/frontend/config/settings.yml.
            2. Create an unavailable.php file in the root config dir (project folder/config).
            3. Clear the cache (symfony cc).
            4. Run symfony project:disable frontend prod to disable the prod environment of the frontend application. To enable, just change the disable word to enable.

            Wednesday, February 8, 2012

            Format Date Based On User Culture in Action in Symfony

            $user_culture = $this->getUser()->getCulture();
            $formatdate = new sfDateFormat($user_culture);
            echo $formatdate->format(strtotime('2012-02-08'), 'd'); // 'd' is a pattern
            

            Tuesday, January 31, 2012

            Layout Jumps Left If Vertical Scrollbar Appears - HOW TO FIX IN CSS

            Looks good in IE (5.5 <= 8 beta), FF (2,3), Chrome and Opera.
            html {
              overflow-y: scroll;
            }
            

            Thursday, January 19, 2012

            Moodle: Upload Big Files

            1. Set post_max_size to (ex.) 1000M in php.ini.
            2. Set upload_max_filesize to (ex.) 1000M in php.ini.
            3. Check the upload_tmp_dir value on the phpinfo page. If it's empty, php use the default tmp folder. On linux, it is /tmp. Sometimes it's a mapped partition/device and it has a size. If the size is lower than 1000MB, the upload won't work. Change the size of the tmp dir!
            4. If there is a LimitRequestBody row in httpd.conf (apache) or in a virtual host file, change the value to 0, it means unlimited.

            Monday, January 16, 2012

            Remove Yellow Border Hover from Input Boxes in Chrome

            input[type="text"], input[type="password"], textarea, select { 
              outline: none;
            }
            

            Tuesday, January 10, 2012

            Allow Only Numbers (0-9) in Input Fields with jQuery

              $(".numbersOnly").keydown(function(e){
                var key = e.charCode || e.keyCode || 0;
                // allow backspace, tab, delete, arrows, numbers and keypad numbers ONLY
                return (
                    key == 8 || 
                    key == 9 ||
                    key == 46 ||
                    (key >= 37 && key <= 40) ||
                    (key >= 48 && key <= 57) ||
                    (key >= 96 && key <= 105));
              });
            

            Get Data from an URL using cURL

            $url = 'http://www.domain.hu/user/getUsers';
             
            /* gets the data from a URL */
             
            function get_data($url)
            {
              $ch = curl_init();
              $timeout = 60;
              curl_setopt($ch,CURLOPT_URL,$url);
              curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
              curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
              $data = curl_exec($ch);
              curl_close($ch);
              return $data;
            }