Cross-application partial w symfony
Napisane przez wowo | Kategorie: Symfony, php, webdev
Ostatnio zetknąłem się z problemem wspólnych partiali dla wszystkich aplikacji w projekcie Symfony (dokładnie frontend i backend). Dokładniej, to te partiale były templatkami mailowymi, wysyłanymi zarówno przy zdarzeniach wygenerowanych w frontendzie jak i w panelu administracyjnym. Jako, że ponad wszystko cenię zasadę DRY (Don’t Repeat Yourself, czyli Nie Powtarzaj Się), chciałem, aby moje templatki były napisane raz, a używane z każdego miejsca w projekcie. Pewnym rozwiązaniem byłoby zrobienie symlinka: apps/frontend/modules/mails -> apps/backend/modules/mails i to działa, ale nie jest zbyt eleganckie. Z pomocą przyszła analiza kodu Symfony (dzięki Bogu, że jest Open Source:-)).
Projekt w skrócie wygląda następująco: w aplikacji frontend, mamy moduł default z akcją index, w której to używamy partiala _hello. Partial ten natomiast leży w aplikacji backend w module mails. Z poziomu backendu dostęp do tego partiala jest bezproblemowy.
Cały przykładowy, działający projekt jest dostępny na githubie: http://github.com/wowo/crossApp
Zaczynamy od tego, że w configu mamy możliwość zdefiniowania klasy, która będzie odpowiedzialna za renderowanie partiali w poszczególnych modułach. Jest za to odpowiedzialny wpis mod_NAZWA-MODUŁU_partial_view_class. Aby to skonfigurować na nasze potrzeby, wpisujemy do ogólnej konfiguracji config/ProjectConfiguration.class.php do metody setup() – będzie ona dostępna dla wszystkich aplikacji:
config/ProjectConfiguration.class.php
sfConfig::set('mod_mails_partial_view_class', 'CrossApp');
Aby uczynić nasze rozwiązanie uniwersalnym, możemy dla modułów, którym zmieniamy domyślną klasę partial_view utworzyć odpowiednie wpisy w konfiguracji, definiujące w której aplikacji leży moduł z partialami:
config/ProjectConfiguration.class.php
sfConfig::set('mod_mails_partials_app', 'backend');
Teraz pozostaje napisanie klasy dziedziczącej po sfPartialView, której nazwa jest połączeniem pierwszej wartości konfiguracyjnej oraz suffiksu PartialView oraz umieszczenie jej w głównym folderze lib:
lib/CrossAppPartialView.class.php
<?php
class CrossAppPartialView extends sfPartialView
{
public function setDirectory($directory)
{
if ($app = sfConfig::get(sprintf('mod_%s_partials_app', $this->getModuleName()))) {
$directory = sprintf('%s/apps/%s/modules/%s/templates', sfConfig::get('sf_root_dir'), $app, $this->getModuleName());
}
parent::setDirectory($directory);
}
}
W tej klasie nadpisujemy metodę setDirectory, uzyskując podmianę ścieżki, w sposób podany powyżej i cieszymy się partialami cross-aplikacyjnymi :-) Zaletą tego rozwiązania jest jego przeźroczystość, nie musimy nic zmieniać w wywołaniach partiali w obydwu aplikacjach – wyciągamy je standardowo.
Tagi: cross-app, partial, Symfony
Podobne wpisy
- Symfony admin generator – optymalizacja zapytań do bazy dla Doctrine
- Prefix w URLach Symfony
- Symfony Mixins – how to extend symfony core classes without inheritance
2 Responses to “Cross-application partial w symfony”
-
greg Says:
Kwiecień 2nd, 2010 at 14:44dzięki za pomoc bo akurat tego szukałem.
troche zmodyfikowałem dodatkowo setDirectory() bo ja pobierałem partiala nie dosc ze z innej aplikacji to jeszcze z zupełnie innego modułu (nie o tej samej nazwie). dzieki jeszcze raz, bo zaoszczędziłeś mi kilka godzin :) -
Bedger Says:
Czerwiec 26th, 2010 at 19:59Ten sam efekt można uzyskać poprzez tymczasową zmianę aplikacji przez metodę statyczną switchTo dostępną z poziomu sfContext. Np.
sfContext::switchTo(‘frontend’);
$mailMessage = $this->getPartial(‘module/partial’, array(‘object’ => $object));
sfContext::switchTo(‘backend’);Fakt, niektórzy nie lubią stosować sfContext, szczególnie że nie zawsze jest dostępny (głównie jeśli chodzi o taski z poziomu konsoli) ale imo do np. pobrania treści meila z poziomu akcji nadaje się w sam raz :)



