Problemy z Symfony

Jeszze trochę o Symfony, tym razem o problemach jakie ostatnio napotkałem.

1. UTF-8 a BOM i nie BOM

Autorzy Symfony polecają kodowanie wszystkich plików .php w UTF-8. Ja również gorąco polecam UTF-8 ale trzeba uważać na BOM. Sposoby kodowania plików w UTF-8 są dwa. Z BOM i bez BOM (zobacz np. Notepad++). Ten pierwszy dodaje na początek pliku kilka znaków informujących o sposobie kodowania.  Niestety te dodatkowe kilka bajtów bardzo przeszkadza Symfony. Każdy plik php ładowany przez Symfony automatycznie (np. pliki z klasami, projectConfiguration.class.php) powoduje wysłanie do bufora wyjściowego tych właśnie znaków. Przeszkadza to zarówno przy wysyłaniu plików binarnych (np. w przykładzie poniżej) jak i przeszkadza również generatorowi admin’a, PHP zgłasza błąd typu “Parse error”.

Niedoposzczalne jest również stosowanie BOM dla plików .yml, parser Yaml z takimi plikami po prostu  sobie nie radzi.

2. Wysyłanie pliku

Sprawa wydaję się być oczywista, wystarczy zagooglować i znaleźć można kilka przykładów dobrego kodu jak w kontrolerze wytawić plik do przeglądarki. Z jakiś tajemniczych powodów u mnie żaden z wyszukanych snippetów nie zadziałał. Symfony uparcie wysyłało po raz kolejny nagłówki chociaż rezultat działania akcji był sfView::NONE.

Kod teoretycznie poprawny:

private function sendFile($filename, $name = null)
{
  $this->setLayout(false);
  sfConfig::set('sf_web_debug', false);
  $this->getResponse()->clearHttpHeaders();
  $this->getResponse()->setHeaderOnly(true);
  $this->getResponse()->setHttpHeader('Pragma: no-cache', true);
  $this->getResponse()->setContentType('application/octet-stream');
  $this->getResponse()->sendHttpHeaders();
  readfile($filename);
  return sfView::NONE;
}

Kod który zadziałał u mnie:

public function sendFile($filename, $name = null)
{
  $this->setLayout(false);
  sfConfig::set('sf_web_debug', false);
  ob_end_clean();
  //coś inicjuje wysylanie bufora
  //dodaje to niepotrzebne znaki na początku pliku
  header('Content-type: application/octet-stream', true);
  if ($name)
    header('Content-Disposition: attachment; filename="'.$name.'"');
  header('Pragma: no-cache', true);
  readfile($filename);
  die();
  //nic więcej nie potrzebuje
  //nie chcę pononwego wysyłania nagłówków HTTP
}

Niezbyt elegancko ale skutecznie.

3. sfContext a linia poleceń Symfony

Jeśli podczas wykonywania zadań z linii komend Symfony zdarzy się Wam błąd typu

Default context does not exist

oznacza to że wasz kod lub plugin który używacie używa:

sfContext::getInstance()

W trybie linii komend nie ma użytkownika i nie ma kontekstu. Szczególna pułapka tkwi w zainstalowanych pluginach, gdzie użyty jest powyższy kod w np. w metodzie configure(). Jeśli niezbędne jest użycie sfContext::getInstance() wówczas polecam:

    if(sfContext::hasInstance())
      $context=sfContext::getInstance();
    else
      //zrob cos innego

4 Komentarzy

Komentarze zostały wyłączone.