Left join on addAttributeToFilter with EAV tables

When you want to filter a collection with custom attribute value it works but when you want to retrieve the non-corresponding entries (like with the neq, null, not null, …. statements) it doesn’t work.

Default join on collection is an inner join so if you are doing that :

$myCollection()->addAttributeToFilter('my_attribute', array('null' => true));

.. you will find no entries

If you want to change the default inner join to a left join you just have to add ‘left’ as the third parameter of the addAttributeToFilter method :

$myCollection()->addAttributeToFilter('my_attribute', array('null' => true), 'left');

and now it works…

Here is the prototype of the corresponding method in Mage_Catalog_Model_Resource_Product_Collection :

public function addAttributeToFilter($attribute, $condition = null, $joinType = 'inner')

We can see that inner parameter is used by default

phpMyAdmin change timeout & other customizations

Tired to login again and again on your phpMyAdmin interface ?
You can change the default timeout in your config.inc.php file.

Add or edit this variable

$cfg['LoginCookieValidity'] = 36000; //In seconds 

The config.inc.php file is in your /etc/phpmyadmin/ folder on debian.

Some other options:

$cfg['MaxRows'] = 100; //change the number of line displayed by default
$cfg['AjaxEnable'] = false;  //enable or disable ajax 
$cfg['NavigationBarIconic'] = true;   //enable or diasable navigation icons
$cfg['PropertiesIconic'] = true;      //enable or disable properties icons

Symfony 1.x propel-insert-sql [propel-sql-exec] SQLSTATE[42000]: Syntax error or access violation: 1064

You are using a old version of symfony 1.x on a new version of mysql and when you try to insert the model on your database you get this error :

[propel-sql-exec] SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘Type=InnoDB’ at line 6

The problem come from this query

CREATE TABLE `pret_externe_type`
 (
 `id_pret_externe_type` BIGINT(20)  NOT NULL AUTO_INCREMENT,
 `libelle` VARCHAR(100)  NOT NULL,
 PRIMARY KEY (`id_pret_externe_type`)
 )Type=InnoDB

Mysql do not use “Type=” option anymore, you have to replace it by “Engine=”

CREATE TABLE `pret_externe_type`
 (
 `id_pret_externe_type` BIGINT(20)  NOT NULL AUTO_INCREMENT,
 `libelle` VARCHAR(100)  NOT NULL,
 PRIMARY KEY (`id_pret_externe_type`)
 )Engine=InnoDB

To fix it the code, on symfony 1.2 go on this file /lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/sql/mysql/MysqlDDLBuilder.php and change the line 156
from

 $script .= "Type=$mysqlTableType";

to

 $script .= "Engine=$mysqlTableType";

On symfony 1.4, you have to change this file : lib/vendor/symfony/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/sql/mysql/MysqlDDLBuilder.php
Always on ligne 156

After code change, rebuild your SQL model and insert it to your databases

php symfony propel-build-sql
php symfony propel-insert-sql

Warning: ob_start(): function ” not found or invalid function name Symfony

If you are installing a symfony 1.x project on a PHP 5.4.1 (or later) version, you may encounter this warning message :
Warning: ob_start(): function ” not found or invalid function name in /var/www/lib/config/sfApplicationConfiguration.class.php on line 157 Notice: ob_start(): failed to create buffer in /var/www/lib/config/sfApplicationConfiguration.class.php on line 157

To fix it, go on your /lib/config/sfApplicationConfiguration.class.php file and change this

// compress output
    if (!self::$coreLoaded)
    {
      ob_start(sfConfig::get('sf_compressed') ? 'ob_gzhandler' : '');
    }

to this

// compress output
    if (!self::$coreLoaded)
    {
      ob_start(sfConfig::get('sf_compressed') ? 'ob_gzhandler' : null);
    }

ERROR: This RRD was created on another architecture

You are migrating cacti from a 32bits machine to a 64bits machine and you get this error message : “ERROR: This RRD was created on another architecture” ?

To fix it, you need to convert on your 32bits machine the .rrd file to xml files.

    for i in `ls *.rrd`; do rrdtool dump $i > $i.xml; done

And on your 64bits machine, transform your XML files to rrd files :

for i in `ls *.xml`; do rrdtool restore $i `echo $i |sed s/.xml//g`; done

PHP sort array by sub value

Here my array structure :

Array
(
    [33] => Array
        (
            [id_site] => 33
            [datas] => Array
                (
                    [id] => 2965
                    [site_id] => 33
                    [operation_id] => 20
                    [positionnement] => 1
                )
            [statut] => Validé DM
            [sort] => 0119
        )
    [32] => Array
        (
            [id_site] => 32
            [datas] => Array
                (
                    [id] => 1929
                    [site_id] => 32
                    [operation_id] => 20
                    [positionnement] => 1
                 )
            [statut] => Validé DM
            [sort] => 0114
        )
    [34] => Array
        (
            [id_site] => 34
            [datas] => Array
                (
                    [id] => 2230
                    [site_id] => 34
                    [operation_id] => 20
                    [positionnement] => 1
                )
            [statut] => Validé DM
            [sort] => 0128
        )
)

How to sort by the [sort] value inside my array ?

I have to use the usort() function :

function sortByCustom($a, $b) {
    return strcmp($a['sort'], $b['sort']);
}
...
usort($array, 'sortByCustom');

Here the result :

Array
(
    [0] => Array
        (
            [id_site] => 32
            [datas] => Array
                (
                    [id] => 1929
                    [site_id] => 32
                    [operation_id] => 20
                    [positionnement] => 1
                 )
            [statut] => Validé DM
            [sort] => 0114
        )

    [1] => Array
        (
            [id_site] => 33
            [datas] => Array
                (
                    [id] => 2965
                    [site_id] => 33
                    [operation_id] => 20
                    [positionnement] => 1
                )
            [statut] => Validé DM
            [sort] => 0119
        )
    [2] => Array
        (
            [id_site] => 34
            [datas] => Array
                (
                    [id] => 2230
                    [site_id] => 34
                    [operation_id] => 20
                    [positionnement] => 1
                )
            [statut] => Validé DM
            [sort] => 0128
        )
)

If you want to maintain the index value association, use the uasort() function

uasort($array, 'sortByCustom');

Here the result :

Array
(
    [32] => Array
        (
            [id_site] => 32
            [datas] => Array
                (
                    [id] => 1929
                    [site_id] => 32
                    [operation_id] => 20
                    [positionnement] => 1
                 )
            [statut] => Validé DM
            [sort] => 0114
        )

    [33] => Array
        (
            [id_site] => 33
            [datas] => Array
                (
                    [id] => 2965
                    [site_id] => 33
                    [operation_id] => 20
                    [positionnement] => 1
                )
            [statut] => Validé DM
            [sort] => 0119
        )

    [34] => Array
        (
            [id_site] => 34
            [datas] => Array
                (
                    [id] => 2230
                    [site_id] => 34
                    [operation_id] => 20
                    [positionnement] => 1
                )
            [statut] => Validé DM
            [sort] => 0128
        )
)

If you use this in a class, you have to define the sort function outside the class

<?php
function sortByCustom($a, $b)
{
        return strcmp($a['sort'], $b['sort']);
}
class positionnemen {
...

for strict number comparaison, you can also use this function

  function sortByCustom($a, $b)
  {
      if($a['nbr'] > $b['nbr'])
      {
          return 1;
      }
      return -1;
  }

sfWidgetFormDateJQueryUI date format

You want to use the sfWidgetFormDateJQueryUI widget but you cannot configure it to display the date in your culture ?

I had the same problem, and there is what I did to fix it.

I start to override the sfWidgetFormDateJQueryUI class to add a “format_date” option. Add a new class here lib/widget/adinWindgetFormDateJQueryUI.class.php and override the configure fonction to add the format_date option.

 protected function configure($options = array(), $attributes = array())
  {
    $this->addOption('format_date', null);
    parent::configure($options, $attributes);
  }

In the render function, format the value

   if($this->getOption('format_date') != null){
        $dateFormat = new sfDateFormat();
        $value = $dateFormat->format($value, $this->getOption('format_date'));
    }

(The complete class source is at the end of this post.)

In your formClass, configure the widget :

class DemandeForm extends BaseDemandeForm
{
    public function configure()
    {
       $this->widgetSchema['date_creation'] = new adinWidgetFormDateJQueryUI(
                array("change_month" => true, 
                      "change_year" => true, 
                      "culture" => 'fr', 
                      "show_button_panel" => true, 
                      "format_date" => 'dd/MM/y' //define here format
                      )
                 );

        $this->validatorSchema['date_creation'] = new sfValidatorDate(   
                array("date_format" => '~(?P<day>\d{2})/(?P<month>\d{2})/(?P<year>\d{4})~' , //regex,
                      "date_output" => "Y-m-d",  //format the value after validation to send to BDD
                      "required" => true
                      )
                 );
    }
}

Here the complete adinWidgetFormDateJQueryUI source code

<?php
class adinWidgetFormDateJQueryUI extends sfWidgetFormDateJQueryUI
{
 protected function configure($options = array(), $attributes = array())
  {
    $this->addOption('format_date', null);
    parent::configure($options, $attributes);
  }

  /**
   * @param  string $name        The element name
   * @param  string $value       The date displayed in this widget
   * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
   * @param  array  $errors      An array of errors for the field
   *
   * @return string An HTML tag string
   *
   * @see sfWidgetForm
   */
  public function render($name, $value = null, $attributes = array(), $errors = array())
  {
    $attributes = $this->getAttributes();

    $input = new sfWidgetFormInput(array(), $attributes);

   if($this->getOption('format_date') != null){
        $dateFormat = new sfDateFormat();
        $value = $dateFormat->format($value, $this->getOption('format_date'));
    }
    $html = $input->render($name, $value);

    $id = $input->generateId($name);
    $culture = $this->getOption('culture');
    $cm = $this->getOption("change_month") ? "true" : "false";
    $cy = $this->getOption("change_year") ? "true" : "false";
    $nom = $this->getOption("number_of_months");
    $sbp = $this->getOption("show_button_panel") ? "true" : "false";

    if ($culture!='en')
    {
    $html .= <<<EOHTML
<script type="text/javascript">
        $(function() {
    var params = $.datepicker.regional['$culture'];
    params.changeMonth = $cm;
    params.changeYear = $cy;
    params.numberOfMonths = $nom;
    params.showButtonPanel = $sbp;
    $("#$id").datepicker(params);
        });
</script>
EOHTML;
    }
    else
    {
    $html .= <<<EOHTML
<script type="text/javascript">
        $(function() {
    var params = {
    changeMonth : $cm,
    changeYear : $cy,
    numberOfMonths : $nom,
    showButtonPanel : $sbp };
    $("#$id").datepicker(params);
        });
</script>
EOHTML;
    }

    return $html;
  }
}

Don’t forget to run

php symfony cc

to clear your cache and enable this new class on prod environment.

Symfony The default context does not exist

You may have to use in your model class or somewhere else the “context instance” in your code but when this code is used by a task, a test or data fixture, you get a “The default contect does not exist” error.
To avoid that, you can use the sfContext::hasInstance() fonction. See below

class Demande extends BaseDemande
{
   public function save(Doctrine_Connection $con = null)
   {
       if(sfContext::hasInstance())
       {
          $id_service = sfContext::getInstance()->getUser()->getAttribute('id_service', false, 'sfMatchlib/user');        
          $this->setIdService($id_service);
        }
        parent::save($con);
    }
}

Save MySQL query results into a file

Sometimes, phpMyAdmin doesn’t export queries properly. To get your file, you can add options to you query to save the result into a file.

SELECT cotisation.date_creation
FROM cotisation
WHERE cotisation.code_suppression =0
INTO OUTFILE '/home/transfert/cotisations_201212.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY "'"
LINES TERMINATED BY '\n'