<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>xlab &#187; symfony</title>
	<atom:link href="http://xlab.pl/tag/symfony/feed/" rel="self" type="application/rss+xml" />
	<link>http://xlab.pl</link>
	<description>XSolve laboratory - dzielimy się tym co wiemy...</description>
	<lastBuildDate>Mon, 30 Aug 2010 07:34:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>pl</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Symfony sfWidgetFormSelect z nieaktywnymi opcjami</title>
		<link>http://xlab.pl/2010/05/symfony-sfwidgetformselect-z-nieaktywnymi-opcjami/</link>
		<comments>http://xlab.pl/2010/05/symfony-sfwidgetformselect-z-nieaktywnymi-opcjami/#comments</comments>
		<pubDate>Tue, 25 May 2010 08:06:33 +0000</pubDate>
		<dc:creator>Wojtek Sznapka</dc:creator>
				<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sfWidgetFormSelect]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1157</guid>
		<description><![CDATA[sfWidgetFormSelect nie daje możliwości wyświetlania nieaktywnych opcji. Jest to rzadko wykorzystywana właściwość elementu select, ale czasami może się na prawdę przydać :-) Pomimo to, możemy uzyskać tą funkcjonalność poprzez stworzenie własnego widgetu, który dziedziczy z  sfWidgetFormSelect. Kod klasy znajduję się poniżej. W tym przypadku nieaktywne opcje, to te które mają ujemne value. Można oczywiście [...]]]></description>
			<content:encoded><![CDATA[<p><strong>sfWidgetFormSelect</strong> nie daje możliwości wyświetlania nieaktywnych opcji. Jest to rzadko wykorzystywana właściwość elementu select, ale czasami może się na prawdę przydać :-) Pomimo to, możemy uzyskać tą funkcjonalność poprzez stworzenie własnego widgetu, który dziedziczy z  <strong>sfWidgetFormSelect</strong>. Kod klasy znajduję się poniżej. W tym przypadku nieaktywne opcje, to te które mają ujemne <strong>value</strong>. Można oczywiście ustawiać inne opcje na nieaktywne, wystaczy odpowiednio zmodyfikować metodę <strong>disableCondition</strong>.<span id="more-1157"></span></p>
<pre class="php" name="code">
  class myWidgetFormSelect extends sfWidgetFormSelect
  {
    public function renderContentTag($tag, $content = null, $attributes = array())
    {
      if ($tag == 'option' &amp;&amp; isset($attributes['value'])
        &amp;&amp; $this-&gt;disableCondition($attributes['value'])
      ) {
        $attributes['disabled'] = 'disabled';
      }
      return parent::renderContentTag($tag, $content, $attributes);
    }   

    protected function disableCondition($value)
    {
      return (int)$value &lt; 0;
    }
  }
</pre>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/2010/05/symfony-sfwidgetformselect-z-nieaktywnymi-opcjami/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Wykrywanie przeglądarek na urządzenia mobilne</title>
		<link>http://xlab.pl/2010/05/wykrywanie-przegladarek-na-urzadzenia-mobilne/</link>
		<comments>http://xlab.pl/2010/05/wykrywanie-przegladarek-na-urzadzenia-mobilne/#comments</comments>
		<pubDate>Tue, 18 May 2010 07:09:21 +0000</pubDate>
		<dc:creator>Wojtek Sznapka</dc:creator>
				<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[przeglądarki mobilne]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://xlab.pl/?p=1096</guid>
		<description><![CDATA[Często bywa  tak, że chcemy utworzyć mobilną wersję naszego serwisu. Cechuje się ona przeważnie skromniejszą szatą graficzną oraz umiarem w wykorzystaniu JavaScriptu. Aby wykryć przeglądarkę mobilną (używaną w telefonach komórkowych, smartphone lub palmtopach) wystarczy użyć poniższej klasy. W zaprezentowanym rozwiązaniu detekcja przeglądarki oparta jest o nagłówek HTTP_USER_AGENT lub o dodatkowe nagłówki wysyłane przez niektóre przeglądarki.
class [...]]]></description>
			<content:encoded><![CDATA[<p>Często bywa  tak, że chcemy utworzyć mobilną wersję naszego serwisu. Cechuje się ona przeważnie skromniejszą szatą graficzną oraz umiarem w wykorzystaniu JavaScriptu. Aby wykryć przeglądarkę mobilną (używaną w telefonach komórkowych, smartphone lub palmtopach) wystarczy użyć poniższej klasy. W zaprezentowanym rozwiązaniu detekcja przeglądarki oparta jest o nagłówek HTTP_USER_AGENT lub o dodatkowe nagłówki wysyłane przez niektóre przeglądarki.<span id="more-1096"></span></p>
<pre class="php" name="code">class MobileBrowserDetector
{
  private static $mobileAgentPrefixes = array(
    'w3c ','acs-','alav','alca','amoi','audi','avan','benq','bird','blac',
    'blaz','brew','cell','cldc','cmd-','dang','doco','eric','hipt','inno',
    'ipaq','java','jigs','kddi','keji','leno','lg-c','lg-d','lg-g','lge-',
    'maui','maxo','midp','mits','mmef','mobi','mot-','moto','mwbp','nec-',
    'newt','noki','oper','palm','pana','pant','phil','play','port','prox',
    'qwap','sage','sams','sany','sch-','sec-','send','seri','sgh-','shar',
    'sie-','siem','smal','smar','sony','sph-','symb','t-mo','teli','tim-',
    'tosh','tsm-','upg1','upsi','vk-v','voda','wap-','wapa','wapi','wapp',
    'wapr','webc','winw','winw','xda','xda-'
  );

  private static $mobileAgentParts = array(
    'up.browser', 'up.link', 'mmp', 'symbian', 'mobile safari',
    'opera mobi', 'android', 'smartphone', 'midp', 'wap', 'phone'
  );

  public static function isMobile($userAgent = '')
  {
    if (!strlen($userAgent)) {
      $userAgent = $_SERVER['HTTP_USER_AGENT'];
    }
    $isMobile = false;
    $isMobile |= in_array(strtolower(substr($userAgent, 0, 4)), self::$mobileAgentPrefixes);
    $isMobile |= preg_match(sprintf('#(%s)#i', implode('|', self::$mobileAgentParts)), $userAgent);
    $isMobile |= strpos(strtolower($_SERVER['HTTP_ACCEPT']),'application/vnd.wap.xhtml+xml') !== false;
    $isMobile |= isset($_SERVER['HTTP_PROFILE']);
    $isMobile |= isset($_SERVER['HTTP_X_WAP_PROFILE']);
    $isMobile |= isset($_SERVER['ALL_HTTP']) &amp;&amp; strpos(strtolower($_SERVER['ALL_HTTP']),'OperaMini') !== false;
    return (bool)$isMobile;
  }
}</pre>
<p>Możemy łatwo użyć tej klasy na przykład w projekcie symfony, podmieniając główny layout na layout mobilny (apps/APLIKACJA/templates/layout_mobile.php) w filtrze, w poniższy sposób.<br />
Zawartość apps/APLIKACJA/config/filters.yml</p>
<pre class="php" name="code">rendering: ~
security:
  class: sfGuardBasicSecurityFilter
mobile:
  class: MobileFilter
cache:     ~
common:    ~
execution: ~</pre>
<p>Klasa filtra lib/MobileFilter.class.php:</p>
<pre class="php" name="code">class MobileFilter extends sfFilter
{
  public function execute($filterChain)
  {
    if (MobileBrowserDetector::isMobile()) {
      $this-&gt;getContext()-&gt;getActionStack()-&gt;getFirstEntry()-&gt;getActionInstance()-&gt;setLayout('layout_mobile');
    }
    $filterChain-&gt;execute();
  }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/2010/05/wykrywanie-przegladarek-na-urzadzenia-mobilne/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Piekło die();</title>
		<link>http://xlab.pl/2009/11/pieklo-die/</link>
		<comments>http://xlab.pl/2009/11/pieklo-die/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 23:40:50 +0000</pubDate>
		<dc:creator>Krzysztof Wawoczny</dc:creator>
				<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[debugowanie]]></category>
		<category><![CDATA[FirePHP]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.xlab.pl/?p=676</guid>
		<description><![CDATA[
Natchnęło mnie dziś do pomyślenia jak uchronić się przed niebezpieczeństwami związanymi z stosowaniem die()  w kodzie&#8230;tak wiem że była o tym parę razy mowa, że to zło w najczystszej postaci,  że najlepiej korzystać z xdebug, a najlepiej nigdy nie korzystać z die() w kodzie.
Wszystko ma jednak swoje wady i zalety – o ile w [...]]]></description>
			<content:encoded><![CDATA[<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } --></p>
<p style="margin-bottom: 0cm">Natchnęło mnie dziś do pomyślenia jak uchronić się przed niebezpieczeństwami związanymi z stosowaniem die()  w kodzie&#8230;tak wiem że była o tym parę razy mowa, że to zło w najczystszej postaci,  że najlepiej korzystać z xdebug, a najlepiej nigdy nie korzystać z die() w kodzie.</p>
<p style="margin-bottom: 0cm">Wszystko ma jednak swoje wady i zalety – o ile w pracy xdebuga mogę sobie skonfigurować pod netbeansa to w domu nie korzystam z tego IDE (połączenie przez OpenVPN i dość częste skanowanie projektu jest nader uciążliwe). Dlatego zaczerpnąłem nieco mocy googla i po kilku testach przedstawiam: <strong> FirePHP</strong>.</p>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } --></p>
<p style="margin-bottom: 0cm"><strong>FirePHP</strong> to całkiem zgrabny logger dla PHP wykorzystujący <strong>Firebuga</strong> – ku mojemu zdziwieniu jest to całkiem niezły plugin, do jego działania wystarczy mieć zainstalowaną wtyczkę Firebug z włączoną zakładką sieć i konsola. Instalując FirePHP trzeba jeszcze pamiętać o zaciągnięciu biblioteki FirePHPCore, którą rozpakowujemy do katalogu roota (w moim przypadku to katalog web w symfony).  FirePHP pokaże się jako niebieski robal (widoczny na poniższym zrzucie).</p>
<p style="margin-bottom: 0cm">Mając to wszystko jesteśmy niemal gotowi by bezpiecznie debugować skrypty. Do skryptu dołączamy:</p>
<pre class="php">require_once('FirePHPCore/FirePHP.class.php');</pre>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } --></p>
<p style="margin-bottom: 0cm">Teraz już poprzez wywołanie w postaci:</p>
<p style="margin-bottom: 0cm">
<pre class="php">$firephp = FirePHP::getInstance(true);
$firephp-&gt;log($var, 'nieobowiazkowy opis dla loga');</pre>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } --></p>
<p style="margin-bottom: 0cm">Zobaczymy w zakładce konsola Firebuga wartość zmiennej $var poprzedzoną opisem podanym jako drugi parametr funkcji log.<br />
Dla własnej wygody napisałem krótką funkcję ustawiającą podstawowe parametry debugowania:</p>
<p style="margin-bottom: 0cm">
<pre class="php">/**
* Function is used for debuging this scrypt, in prod environment change
* $firephp-&gt;setEnabled(true); to false.
*
* @param object $var
* @param string $desc[optional]
*/
public function keep($var, $desc = null)
{
  $options = array(
  'maxObjectDepth' =&gt; 10,
  'maxArrayDepth' =&gt; 20,
  'useNativeJsonEncode' =&gt; true,
  'includeLineNumbers' =&gt; true);

  $firephp = FirePHP::getInstance(true);
  $firephp-&gt;setEnabled(true);
  $firephp-&gt;setOptions($options);
  $firephp-&gt;log($var, $desc);
}</pre>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } --></p>
<p style="margin-bottom: 0cm">Ważne aby pamiętać iż dla własnego bezpieczeństwa należy w środowisku produkcyjnym ustawić setEnabled na false.</p>
<p style="margin-bottom: 0cm">Posłużę się Jobeetem, zatem moja funkcja index wygląda tak:</p>
<p style="margin-bottom: 0cm">
<pre class="php">public function executeIndex(sfWebRequest $request)
{
  $vars = 0;
  $this-&gt;categories = Doctrine::getTable('JobeetCategory')-&gt;getWithJobs();
  $this-&gt;keep($vars, "at line: ".__LINE__);
  $vars = 12;
  $this-&gt;keep($vars, "at line: ".__LINE__);
}</pre>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } --></p>
<p style="margin-bottom: 0cm">drugi parametr funkcji keep służy mi jako informacja pozwalająca szybko odnaleźć miejsce z wywołaniem logera. Wynik logowania prezentuje się następująco:</p>
<p style="margin-bottom: 0cm;text-align: center"><a rel="attachment wp-att-677" href="http://www.xlab.pl/2009/11/pieklo-die/attachment/1/"><img class="size-medium wp-image-677 aligncenter" src="http://www.xlab.pl/wp-content/uploads/2009/11/1-300x172.jpg" alt="Debugowanie z użyciem FirePHP" width="300" height="172" /></a></p>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } --></p>
<p style="margin-bottom: 0cm">Ciekawsze wyniki można uzyskać deklarując przykładową tablicę z danymi – najeżdżając kursorem myszy na wynik debugowania tablicy ukaże się okienko jak na poniższym zrzucie – możemy tutaj nieco dokładniej przyjrzeć się zwróconym wartościom.</p>
<p style="margin-bottom: 0cm;text-align: center"><a rel="attachment wp-att-688" href="http://www.xlab.pl/2009/11/pieklo-die/attachment/2/"><img class="size-medium wp-image-688 aligncenter" src="http://www.xlab.pl/wp-content/uploads/2009/11/2-300x172.jpg" alt="Debugowanie z FirePHP 2" width="300" height="172" /></a></p>
<p><!-- 		@page { size: 21cm 29.7cm; margin: 2cm } 		P { margin-bottom: 0.21cm } --></p>
<p style="margin-bottom: 0cm">Na koniec chciałbym zauważyć, że odświeżenie strony nie zawsze powoduje odświeżenie wyników debugowania, prowadzi to wręcz do ich utraty – należy wówczas kliknąć w Firebugu opcję Off a następnie On dzięki czemu zobaczymy aktualne dane.</p>
<p style="margin-bottom: 0cm">Zachęcam do korzystania z FirePHP i testowania jego pozostałych funkcjonalności.</p>
<p style="margin-bottom: 0cm"><a href="http://www.firephp.org/HQ/Use.htm">http://www.firephp.org/HQ/Use.htm</a></p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/2009/11/pieklo-die/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Połączenie sfGuardUser oraz sfGuardUserProfile</title>
		<link>http://xlab.pl/2009/08/polaczenie-sfguarduser-oraz-sfguarduserprofile/</link>
		<comments>http://xlab.pl/2009/08/polaczenie-sfguarduser-oraz-sfguarduserprofile/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 09:03:01 +0000</pubDate>
		<dc:creator>kibao</dc:creator>
				<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[admin generator]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sfGuardPlugin]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.xlab.pl/?p=162</guid>
		<description><![CDATA[Przy ostatnich pracach związanych z przeniesienie naszej aplikacji z symfony 1.0 na symfony 1.2 natknęliśmy się na kilka problemów z pluginem sfGuardPlugin, a dokładniej z połączeniem administracji sfGuardUser oraz sfGuardUserProfile.
Chcieliśmy aby podczas listowania użytkowników, poprzez moduł sfGuardUser, można było wyświetlać nie tylko pola znajdujące się w tabeli sf_guard_user ale także wybrane pola z profilu usera, [...]]]></description>
			<content:encoded><![CDATA[<p>Przy ostatnich pracach związanych z przeniesienie naszej aplikacji z symfony 1.0 na symfony 1.2 natknęliśmy się na kilka problemów z pluginem <a href="http://www.symfony-project.org/plugins/sfGuardPlugin" target="_blank">sfGuardPlugin</a>, a dokładniej z połączeniem administracji sfGuardUser oraz sfGuardUserProfile.<br />
Chcieliśmy aby podczas listowania użytkowników, poprzez moduł sfGuardUser, można było wyświetlać nie tylko pola znajdujące się w tabeli sf_guard_user ale także wybrane pola z profilu usera, a także mieć możliwość filtrowania po nich.</p>
<p>Na początek stworzymy sobie możliwość wyświetlania pól z profilu użytkownika podczas listowania. Otwieramy <em>generator.yml</em> z modułu sfGuardUser, który w oryginale wygląda tak:</p>
<pre name="code">generator:
  class: sfPropelGenerator
  param:
    model_class:           sfGuardUser
    theme:                 admin
    non_verbose_templates: true
    with_show:             false
    singular:              ~
    plural:                ~
    route_prefix:          sf_guard_user
    with_propel_route:     1

    config:
      fields:
        password_again: { label: "Password (again)" }

      list:
        title:   User list
        display: [=username, created_at, last_login]

      form:
        class: sfGuardUserAdminForm
        display:
          "NONE":                   [username, password, password_again]
          "Permissions and groups": [is_active, is_super_admin, sf_guard_user_group_list, sf_guard_user_permission_list]

      edit:
        title: Editing User "%%username%%"

      new:
        title: New User</pre>
<p>Interesuje nas dokładnie sekcja</p>
<pre name="code" class="YML">list:
  title:   User list
  display: [=username, created_at, last_login]</pre>
<p>Do wyświetlania informacji z pól z profilu użytkownika, będziemy korzystać z możliwości użycia własnych partiali.<br />
Nas interesuje np. imię, nazwisko, oraz adres e-mail użytkownika, dlatego wprowadzamy takie modyfikacje:</p>
<pre name="code" class="YML">list:
  title:   User list
  display: [=username, created_at, last_login, _first_name, _last_name, _email]</pre>
<p>Następnie tworzymy 3 pratiale w katalogu<em> sfGuardUser/templates/</em> :<br />
<em>_first_name.php</em></p>
<pre name="code"  class="php">&lt;?php echo $sf_guard_user-&gt;getProfile()-&gt;getFirstName(); ?&gt;</pre>
<p><em>_last_name.php</em></p>
<pre name="code"  class="php">&lt;?php echo $sf_guard_user-&gt;getProfile()-&gt;getLastName(); ?&gt;</pre>
<p><em>_email.php</em></p>
<pre name="code"  class="php">&lt;?php echo $sf_guard_user-&gt;getProfile()-&gt;getEmail(); ?&gt;</pre>
<p>Po tym</p>
<pre name="code"  class="bash">symfony cc</pre>
<p>I po odświeżeniu strony z listowaniem użytkowników będziemy mieli także informacje o imieniu, nazwisku oraz adresie email.<br />
Wszytko pięknie tylko po takich modyfikacjach nie można sortować po dodanych polach. A to dlatego, że generator podczas tworzenia kodu naszych template&#8217;ów sprawdza czy pole które ma być wyświetlone istnieje w modelu.<br />
Dlatego musimy obejść to sprawdzanie poprzez zmodyfikowanie informacji o polach w listowaniu (<em>generator.yml</em>):</p>
<pre name="code"  class="YML">list:
  title:   User list
  display: [=username, created_at, last_login, _first_name, _last_name, _email]
  fields:
    last_name:      { is_real: true }
    first_name:     { is_real: true }
    email:          { is_real: true }</pre>
<p>Teraz po wyczyszczeniu cache i odświeżeniu strony mamy już możliwość sortowania po polach z profilu.</p>
<p>Jeżeli przejdziecie teraz w środowisko dev zauważycie, że nagle zwiększyła się bardzo ilość zapytań do bazy.<br />
A to ze względu, że dla każdego użytkownika pobierany jest osobno jego profil.<br />
Należałoby to zoptymalizować, aby nie wywoływać niepotrzebnie tylu zapytań. Tutaj natknęliśmy się na kilka problemów, ponieważ klasa sfGuardUserPeer nie posiada metody doSelectJoinsfGuardUserProfile.<br />
Otwieramy plik <em>sfGuardUserPeer.php</em> i wprowadzamy pewne modfikacje:</p>
<pre name="code"  class="php">&lt;?php
class sfGuardUserPeer extends PluginsfGuardUserPeer
{
  public static function doSelectJoinsfGuardUserProfile(Criteria $c, $con = null, $join_behavior = Criteria::LEFT_JOIN)
  {

    foreach (sfMixer::getCallables('BasesfGuardUserPeer:doSelectJoin:doSelectJoin') as $callable)
    {
      call_user_func($callable, 'BasesfGuardUserPeer', $c, $con);
    }

    $c = clone $c;

    if ($c-&gt;getDbName() == Propel::getDefaultDB()) {
      $c-&gt;setDbName(self::DATABASE_NAME);
    }

    sfGuardUserPeer::addSelectColumns($c);
    $startcol = (sfGuardUserPeer::NUM_COLUMNS - sfGuardUserPeer::NUM_LAZY_LOAD_COLUMNS);
    sfGuardUserProfilePeer::addSelectColumns($c);

    $c-&gt;addJoin(array(sfGuardUserPeer::ID,), array(sfGuardUserProfilePeer::USER_ID,), $join_behavior);
    $stmt = BasePeer::doSelect($c, $con);
    $results = array();

    while ($row = $stmt-&gt;fetch(PDO::FETCH_NUM)) {
      $key1 = sfGuardUserPeer::getPrimaryKeyHashFromRow($row, 0);
      if (null !== ($obj1 = sfGuardUserPeer::getInstanceFromPool($key1))) {
      } else {

        $omClass = sfGuardUserPeer::getOMClass();

        $cls = substr('.'.$omClass, strrpos('.'.$omClass, '.') + 1);
        $obj1 = new $cls();
        $obj1-&gt;hydrate($row);
        sfGuardUserPeer::addInstanceToPool($obj1, $key1);
      }
      $key2 = sfGuardUserProfilePeer::getPrimaryKeyHashFromRow($row, $startcol);
      if ($key2 !== null) {
        $obj2 = sfGuardUserProfilePeer::getInstanceFromPool($key2);
        if (!$obj2) {

          $omClass = sfGuardUserProfilePeer::getOMClass();

          $cls = substr('.'.$omClass, strrpos('.'.$omClass, '.') + 1);
          $obj2 = new $cls();
          $obj2-&gt;hydrate($row, $startcol);
          sfGuardUserProfilePeer::addInstanceToPool($obj2, $key2);
        }
        $obj1-&gt;setProfile($obj2);

      }
      $results[] = $obj1;
    }
    $stmt-&gt;closeCursor();
    return $results;
  }
}</pre>
<p>A w pliku <em>sfGuardUser.php</em>, dodajemy funkcję setProfile :</p>
<pre name="code"  class="php">&lt;?php
class sfGuardUser extends PluginsfGuardUser
{
  public function setProfile( $profile )
  {
    $this-&gt;profile = $profile;
  }
}</pre>
<p>Na koniec musimy tylko zmienić peer_method wywoływaną przez generator do pobierania wyników.<br />
Otwieramy plik <em>sfGuardUser/lib/sfGuardUserGeneratorConfiguration.class.php</em> i dodajemy funkcję getPeerMethod:</p>
<pre name="code"  class="php">&lt;?php

/**
 * sfGuardUser module configuration.
 *
 * @package    sfGuardPlugin
 * @subpackage sfGuardUser
 */
class sfGuardUserGeneratorConfiguration extends BaseSfGuardUserGeneratorConfiguration
{
  public function getPeerMethod()
  {
    return 'doSelectJoinsfGuardUserProfile';
  }
}</pre>
<p>Teraz po wyczyszczeniu cache, odświeżeniu strony ilość zapytań do bazy powinna spaść.</p>
<p>Na dzisiaj to tyle. Zostało jeszcze opisanie jak filtrować po polach z profilu użytkownika ale to już innym razem.</p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/2009/08/polaczenie-sfguarduser-oraz-sfguarduserprofile/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Automatyczna inwigilacja kodu</title>
		<link>http://xlab.pl/2009/03/automatyczna-inwigilacja-kodu/</link>
		<comments>http://xlab.pl/2009/03/automatyczna-inwigilacja-kodu/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 19:08:33 +0000</pubDate>
		<dc:creator>Marcin Dryka</dc:creator>
				<category><![CDATA[Programowanie PHP]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[codesniffer]]></category>
		<category><![CDATA[format]]></category>
		<category><![CDATA[formatter]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php_codesniffer]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.xlab.pl/?p=27</guid>
		<description><![CDATA[Każdy (dobry) programista chciałby, aby jego kod był najlepszy. Najważniejszą i podstawową rzeczą podczas pisania kodu, to prawidłowe nazywanie zmiennych, funkcji oraz klas. Tego jednak program nie jest w stanie sprawdzać (przynajmniej jak na razie nikt nie napisał, tak zaawansowanego analizatora kodu źródłowego). Możemy jednak zatrudnić parę skryptów aby utrzymać poprawne formatowanie kodu (tak, niektórzy [...]]]></description>
			<content:encoded><![CDATA[<p>Każdy (dobry) programista chciałby, aby jego kod był najlepszy. Najważniejszą i podstawową rzeczą podczas pisania kodu, to prawidłowe nazywanie zmiennych, funkcji oraz klas. Tego jednak program nie jest w stanie sprawdzać (przynajmniej jak na razie nikt nie napisał, tak zaawansowanego analizatora kodu źródłowego). Możemy jednak zatrudnić parę skryptów aby utrzymać poprawne formatowanie kodu (tak, niektórzy z tym także mają problemy).<br />
<span id="more-27"></span></p>
<p>Na pierwszy ogień testów poszedł <a href="http://www.waterproof.fr/products/phpCodeBeautifier/">phpCodeBeautifier</a>. Szybko jednak okazało się, że klamra otwierająca zawartość klasy musi znajdować się w tej samej linii co jej deklaracja. Istnieje opcja:</p>
<p><code><strong>--space-before-start-angle-bracket</strong></code></p>
<p>która pozwala wymusić jeden znak spacji przed &#8220;{&#8220;. Czemu autorzy nie pomyśleli o</p>
<p><code><strong>--newline-before-start-angle-bracket</strong></code></p>
<p>? Cieżko powiedzieć. Kod jest zamknięty, więc się tego nie dopisze samemu.</p>
<p>Istnieje jednak <a href="http://pear.php.net/package/PHP_CodeSniffer">PHP_CodeSniffer</a> (phpcs), który połączony z odpowiednim standardem sprawdzi składnie pliku.</p>
<p>Zainstalujmy &#8220;to&#8221; wszystko&#8230; Na początek instalacja samego phpcs:</p>
<pre name="code" class="bash">apt-get install php-codesniffer</pre>
<p>Aby aplikacja mogła sprawdzać <a href="http://trac.symfony-project.org/wiki/HowToContributeToSymfony#CodingStandards">formatowanie zgodne z symfony</a> należy jeszcze doinstalować standard symfony. Można go znaleźć w repozytorium svn pod adresem http://subversion.assembla.com/svn/phpsymfony/Symfony%20Code%20sniffer%20standards/Symfony/.</p>
<pre name="code" class="bash"> cd /usr/share/php/PHP/CodeSniffer/Standards &amp;&amp; sudo svn co http://subversion.assembla.com/svn/phpsymfony/Symfony%20Code%20sniffer%20standards/ .</pre>
<p>Do przetestowania programu stwórzymy plik:</p>
<pre name="code" class="bash">vim ~/test.php</pre>
<p>z odpowiednią zawartością:</p>
<pre name="code" class="php">&lt;?php
class TestKlasa
{
  public function testFunction()
  {
  }
}</pre>
<p>Uf, nareszcie możemy sprawdzić czy nasz kod jest poprawny:</p>
<pre name="code" class="bash">phpcs --standard=Symfony ~/test.php</pre>
<p>W wyniku czego otrzymamy:</p>
<pre name="code" class="bash">FILE: ~/test.php
--------------------------------------------------------------------------------
FOUND 3 ERROR(S) AND 0 WARNING(S) AFFECTING 2 LINE(S)
--------------------------------------------------------------------------------
2 | ERROR | Missing file doc comment
2 | ERROR | Missing class doc comment
4 | ERROR | Missing function doc comment
--------------------------------------------------------------------------------</pre>
<p>Działa! To znaczy są błędy, ale o to właśnie nam chodziło &#8211; aby je wykrywać. Poprawmy więc zawartość pliku:</p>
<pre name="code" class="php">&lt;?php
/**
* Test file for PHP_CodeSniffer
*
* PHP versions 4 and 5
*
* @category Tests
* @package  XX
* @author   Marcin Dryka &lt;marcin.dryka@xsolve.pl&gt;
* @license  http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version  SVN: 1
* @filesource
*/

/**
* TestKlasa
*
* @package XX
* @author  Marcin Dryka &lt;marcin.dryka@xsolve.pl&gt;
* @version Release: 1
*/
class TestKlasa
{
  /**
  * testFunction
  *
  * @author Marcin Dryka &lt;marcin.dryka@xsolve.pl&gt;
  * @access public
  * @return void
  */
  public function testFunction()
  {
  }
}</pre>
<p>Przy tak wyglądającym pliku wynik działania phpcs jest pusty, brak błędów oznacza poprawnie sformatowany plik. Teraz potrzebna jest tylko silna wola, aby używać skryptu do sprawdzania wszystkich plików. Przy starszych aplikacjach będzie to dość kłopotliwe. Zdarzają się jednak pliki pisane od tak zwanego zera. Gdzie możemy w pełni stosować konwencje ustalone przez autorów symfony (i nie tylko).</p>
]]></content:encoded>
			<wfw:commentRss>http://xlab.pl/2009/03/automatyczna-inwigilacja-kodu/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
