Php traits

С выходом PHP версии 5.3 язык ожил и заиграл новыми красками. Пафосно звучит конечно, но это факт. Следущие две версии, 5.4 и 5.5, соответственно, принесли тоже не мало вкусных плюшек, использование которых реально доставляет немалое удовольствие. Сегодня не столько делюсь опытом, сколько делюсь впечатлениями, так как впервые нашлось и время и возможность попробовать и применить эти самые плюшки.

Continue reading «Php traits»

Php traits

Symfony. sfDoctrineGuardPlugin и data-load

sfDoctrineGuardPlugin позволяет без лишних телодвижений настроить авторизацию пользователей и групп для проекта на Symfony. Есть у него один неприятный «изъян». При использовании doctrine:data-dump и doctrine:data-load напрочь слетают пароли пользователей, по причине того, что при заливке данных из fixtures пароли по новой шифруются. Что бы избежать это неприятности нужно слегка подпатчить один из методов класса PluginsfGuardUser, а именно setPassword

1. Открываем файл plugins/sfDoctrineGuardPlugin/lib/model/doctrine/PluginsfGuardUser.class.php
2. Находим метод setPassword()
3. Изменяем код следующим образом:

public function setPassword($password)
{
  if (!$password && 0 == strlen($password))
  {
    return;
  }

  $fromdump = false;
  if($this->isNew() && $this->getSalt()){
    $fromdump=true;
  }

  if (!$salt = $this->getSalt())
  {
    $salt = md5(rand(100000, 999999).$this->getUsername());
    $this->setSalt($salt);
  }
  $modified = $this->getModified();
  if ((!$algorithm = $this->getAlgorithm()) || (isset($modified['algorithm']) && $modified['algorithm'] == $this->getTable()->getDefaultValueOf('algorithm')))
  {
    $algorithm = sfConfig::get('app_sf_guard_plugin_algorithm_callable', 'sha1');
  }
  $algorithmAsStr = is_array($algorithm) ? $algorithm[0].'::'.$algorithm[1] : $algorithm;
  if (!is_callable($algorithm))
  {
    throw new sfException(sprintf('The algorithm callable "%s" is not callable.', $algorithmAsStr));
  }
  $this->setAlgorithm($algorithmAsStr);

  if($fromdump)
  {
    parent::_set('password',$password);
  } else {
    parent::_set('password', call_user_func_array($algorithm, array($salt.$password)));
  }
}

После этого можно спокойно работать с fixtures, не поправляя с помощью guard:change-password пароли после каждой заливки дампа.

Symfony. sfDoctrineGuardPlugin и data-load

Symfony. Как заменить backend.php на /admin

Мне в посленднее время что-то лениво писать большие посты, поэтому опять мини how-to. Итак, меняем в нашем проекте на Symfony путь к админке:

1. Добавлем RewriteRule в .htaccess:


RewriteCond %{REQUEST_URI} ^/admin/?
RewriteRule ^(.*)$ backend.php [QSA,L]

2. Открываем /app/backend/config/settings.yml и влючаем no_script_name:


prod:
  .settings:
    no_script_name: on

3. Открываем app/backend/config/routing.yml и меняем prefix_path у всех routes:


news:
...
  prefix_path:  admin/news
...

4. Если используем sfDoctrineGuardPlugin, то не забываем поправить и его routings, добавляем в файле plugins/sfDoctrineGuardPlugin/lib/routing/sfGuardRouting.class.php префикс admin/ в следующие методы:
— addRouteForUser
— addRouteForGroup
— addRouteForPermission
— addRouteForRegister

5. Выполняем:


php symfony cc.

6. Profit!

Symfony. Как заменить backend.php на /admin

Ссылка на другое приложение в Symfony

Подсмотрено на просторах сети, после небольших правок стало готово к использованию:

<?php
    public static function cross_app_link_to($app, $route, $args=null)
    {
      /* get the host to build the absolute paths
         needed because this menu lets switch between sf apps
      */ 
      $host = sfContext::getInstance()->getRequest()->getHost() ;
      /* get the current environment. Needed to switch between the apps preserving
         the environment
      */
      $env = sfConfig::get('sf_environment');
      /* get the routing file 
      */
      $appRoutingFile = sfConfig::get('sf_root_dir').
            DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.
            $app.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.
            'routing.yml' ;
      $routeUrl = "";
      if (file_exists($appRoutingFile))
      {
        $yml = sfYaml::load($appRoutingFile) ;
        $routeUrl = $yml[$route]['url'] ;
        if ($args)
        {
          foreach ($args as $k => $v)
          {
            $routeUrl = str_replace(':'.$k, $v, $routeUrl) ;
          }
        }
        if (strrpos($routeUrl, '*') == strlen($routeUrl)-1)
        {
          $routeUrl = substr($routeUrl, 0, strlen($routeUrl)-2) ;
        }
      }
      if ($env == 'dev')
      {
          $path = 'http://' . $host . '/' . $app . '_dev.php' . '/' . $routeUrl ;
      }
      else 
      {
        $path = 'http://' . $host . '/' . $app . '.php' . '/' . $routeUrl ;
      }
      return $path ;
    }
?>

Можно положить во frontendConfiguration.class.php, или оформить в виде helper’а. После чего просто вызываем:

<?php
frontendConfiguration::cross_app_link_to('backend', 'module_name')
?>
Ссылка на другое приложение в Symfony