Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [SF2][Symfony] dostęp do danych w twigu
Foxx
post 11.05.2013, 02:18:41
Post #1





Grupa: Zarejestrowani
Postów: 896
Pomógł: 76
Dołączył: 15.11.2003
Skąd: Sosnowiec/Kraków

Ostrzeżenie: (0%)
-----


Załóżmy, że mamy tablicę obiektów "Pytanie" przekazaną do szablonu twig. Wyświetlamy sobie te pytania:

  1. {% for pytanie in pytania %}
  2. {{ pytanie.nazwa }}
  3. {% endfor %}


I teraz załóżmy, że każde pytanie może mieć powiązany obiekt "Odpowiedź" w relacji OneToMany (jedno pytanie może mieć wiele odpowiedzi - od różnych userów).

Pytanie: w jaki sposób mogę wyświetlić przy każdym z pytań odpowiedź, która jest do niego przypięta i która ponadto należy do wybranego usera? Czyli nie po prostu odpowiedź należącą do tego pytania, ale dodatkowo, która ma parametr userId = np. 5.

Moje próby:

1. Najprościej byłoby w kontrolerze po prostu pobrać odpowiedzi do każdego z pytań skoro pobieram tam pytania. Problem w tym, że ja nie pobieram pytań w kontrolerze. W kontrolerze pobieram tylko "Karty", a w twigu pętlą pobieram wszystkie "Grupy" każdej z kart i kolejną pętlą pobieram dopiero wszystkie "Pytania" każdej grupy. Czyli nie bardzo mogę pobrać odpowiedzi bo nie dysponuję pytaniami w kontrolerze.

2. Próbowalem to zrobić przy pomocy renderowania kontrolera w twigu. Napisałem metodę, która zwraca mi odpowiedź, ale problemem jest to, że w ten sposób renderuję jakiś template w twigu i tyle. A ja potrzebuję uzyskać dostęp do tej zmiennej i móc ją użyć kilka razy w moim szablonie.

Inaczej moje pytanie można sformułować tak: jak mogę uzyskać w twigu dostęp do obiektu powiązanego z obiektem, który tam już mam, ale mogąc jednocześnie wykonać trochę bardziej złożone filtrowanie na tych powiązanych obiektach.

Dzięki za wszelkie rady.

EDIT:

Rozwiązałem problem, ale nie jestem zadowolony. W kontrolerze zrobiłem podwójnego foreacha, analogicznego do tego, który robię w twigu żeby wyświetlić pytania. I w tym foreachu tworzę tablicę z odpowedziami gdzie kluczami są identyfikatory pytań. Podaję tą tablicę do twiga no i mogę sobie jej użyć. Nie jestem zadowolony bo dwa razy robię tą samą pętlę. Nie bardzo mogę wyeliminować pętlę w twigu bo bardzo wygodnie wyświetla mi się w ten sposób pytania uporządkowane w grupach.

Ten post edytował Foxx 11.05.2013, 02:34:33
Go to the top of the page
+Quote Post
destroyerr
post 11.05.2013, 11:00:27
Post #2





Grupa: Zarejestrowani
Postów: 879
Pomógł: 189
Dołączył: 14.06.2006
Skąd: Bytom

Ostrzeżenie: (0%)
-----


O ile dobrze zrozumiałem to moja propozycja jest taka:

  1. class Answer
  2. {
  3. public function getUser();
  4. }
  5.  
  6. class Question
  7. {
  8. private $answers;
  9.  
  10. public function getAnswers()
  11. {
  12. return $this->answers;
  13. }
  14.  
  15. public function getAnswersForUser(User $user)
  16. {
  17. return $this->getAnswers()->filter(function (Answer $a) { return $answer->getUser() == $user });
  18. }
  19. }


Kod
{% for question in questions %}

  {{ question.name }}
  
  {% for answer in question.getAnwersForUser(user) %}
  {% endfor %}

{% endfor %}
Go to the top of the page
+Quote Post
Foxx
post 11.05.2013, 11:07:25
Post #3





Grupa: Zarejestrowani
Postów: 896
Pomógł: 76
Dołączył: 15.11.2003
Skąd: Sosnowiec/Kraków

Ostrzeżenie: (0%)
-----


Rozumiem, to by rozwiązało problem, ale czy takie metody nie powinny znaleźć się w repozytorium encji zamiast w samej encji? Jak ocenić czy metoda może znaleźć się w encji czy już powinna iść do repozytorium?
Go to the top of the page
+Quote Post
Crozin
post 11.05.2013, 11:15:42
Post #4





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


W tym przypadku najprawdopodobniej pobranie odpowiedzi dla danego użytkownika powinno być przerzucone do repozytorium, chociażby ze względu na potencjalnie ogromną ilość danych do pobrania i przetworzenia w przykładzie podanym przez @destroyerr. Czyli:
  1. $questionsRepository = ...;
  2.  
  3. $questions = $questionsRepository->findAllAnsweredBy($user);
Go to the top of the page
+Quote Post
destroyerr
post 11.05.2013, 13:33:20
Post #5





Grupa: Zarejestrowani
Postów: 879
Pomógł: 189
Dołączył: 14.06.2006
Skąd: Bytom

Ostrzeżenie: (0%)
-----


Cytat
Rozumiem, to by rozwiązało problem, ale czy takie metody nie powinny znaleźć się w repozytorium encji zamiast w samej encji? Jak ocenić czy metoda może znaleźć się w encji czy już powinna iść do repozytorium?

Podstawowym kryterium jest to czy encja operuje na danych które posiada, tzn. znajdują się w jej grafie. Tak jest w tym przypadku, inaczej byłoby dla relacji Answer ManyToOne Question. Jeśli problem dotyczyłby innego pytania lub odpowiedzi nie powiązanych z tym pytaniem to wtedy faktycznie pozostaje repozytorium. Reszta to optymalizacja.

Cytat
ogromną ilość danych do pobrania


Tego nie wiemy. Skoro tak gdybamy to być może w Twoim przykładzie powinieneś jeszcze uwzględnić pobieranie pytań tylko dla konkretnych odpowiedzi. Dodatkowo znowu trzeba by indeksować tablicę kluczem głównym pytania. Dla mnie to jest podejście którego staram się unikać na rzecz jasno zdefiniowanych struktur. Dopiero teraz zauważyłem, że Twój kod pobiera pytania na które odpowiedział użytkownik a nie odpowiedzi. Chyba nie zrozumiałem Twojej koncepcji.
Wracając do optymalizacji to żeby nie pobierać zbyt wielu danych możemy skorzystać z filtrowania kolekcji bez pobierania jej całej.
Go to the top of the page
+Quote Post
Foxx
post 11.05.2013, 13:43:19
Post #6





Grupa: Zarejestrowani
Postów: 896
Pomógł: 76
Dołączył: 15.11.2003
Skąd: Sosnowiec/Kraków

Ostrzeżenie: (0%)
-----


Dzięki za odpowiedzi.

Jeszcze pojawiło mi się takie pytanie: jeżeli chciałbym pobrać dane, które nie znajdują się w grafie encji to czy mogę stworzyć metodę w repozytorium, która te dane pobierze, a następnie metodę w encji, która wywoła sobie tą metodę z repozytorium i następnie użyć jej w twigu? Czy to już może jest zniszczenie całej tej idei?

Go to the top of the page
+Quote Post
destroyerr
post 11.05.2013, 14:23:23
Post #7





Grupa: Zarejestrowani
Postów: 879
Pomógł: 189
Dołączył: 14.06.2006
Skąd: Bytom

Ostrzeżenie: (0%)
-----


Encja nie wie o istnieniu repozytorium więc takie rozwiązanie odpada.
Go to the top of the page
+Quote Post
Crozin
post 11.05.2013, 15:06:57
Post #8





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


@destroyerr: Założyłem po prostu, że najprawdopodobniej autora interesuje jedynie mały fragment potencjalnie dużej kolekcji odpowiedzi na dane pytanie (filtrowanie wg użytkownika). Innymi słowy, dokładnie to co podlinkowałeś z dokumentacji Doctrine.

@Foxx: Encja powinna ograniczyć się do względnie prostych metod operujących wyłącznie w obrębie grafu relacji encji. Powinieneś raczej utworzyć metodę w repozytorium, która jako argument przyjmuje encję i zwraca jakieś wyniki - absolutnie nic nie stoi na przeszkodzie byś w Twigu korzystał z obiektu repozytorium. Ba! Jest to prawidłowe rozwiązanie z punktu widzenia MVC! smile.gif
Go to the top of the page
+Quote Post
Foxx
post 11.05.2013, 15:39:17
Post #9





Grupa: Zarejestrowani
Postów: 896
Pomógł: 76
Dołączył: 15.11.2003
Skąd: Sosnowiec/Kraków

Ostrzeżenie: (0%)
-----


@Crozin: jak mogę w takim razie skorzystać z metody z repozytorium w twigu? W book znalazłem tylko sposób na renderowanie kontrolera, a użycie metody z repozytorium byłoby dla mnie idealne, ale gdy tego szukałem to trafiałem tylko na wypowiedzi takie jak tu
http://stackoverflow.com/questions/1175407...ate-in-symfony2
czyli "you shouldn't do this".
Go to the top of the page
+Quote Post
Crozin
post 11.05.2013, 16:16:49
Post #10





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Przekaż repozytorium jako zmienną dla szablonu:
  1. // kontroler:
  2. return $this->render(..., array('answersRepository' => $this->get('....'));
  3.  
  4. // TWIG:
  5. {% for answer in answersRepository.findBy...(user) %}
  6. ...
  7. {% endfor %}
Z tym you sholdn't nie zgodziłbym się. Logika biznesowa jest ukryta wewnątrz repozytorium. Istotne jest tylko to, by metoda findBy...() zwracała już "czyste" dane gotowe do bezpośedniego wyświetlenia.

Ten post edytował Crozin 11.05.2013, 16:17:35
Go to the top of the page
+Quote Post
Foxx
post 12.05.2013, 12:48:44
Post #11





Grupa: Zarejestrowani
Postów: 896
Pomógł: 76
Dołączył: 15.11.2003
Skąd: Sosnowiec/Kraków

Ostrzeżenie: (0%)
-----


Dzięki wam obojgu za pomoc.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 28.03.2024 - 12:12