• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Symfony w Windowsie (XAMPP) - kod PHP pojawia się w przeglądarce

Object Storage Arubacloud
0 głosów
110 wizyt
pytanie zadane 22 lutego w PHP przez Panelinio Gaduła (4,440 p.)
zamknięte 23 lutego przez Panelinio

Witam

Napotkałem się z problemem w Symfony. Otóż chciałbym aby w menu generowały się nazwy kategorii z bazy danych. 


Samo generowanie działa (sprawdzałem na surowym PHP i na innych ścieżkach). Myślę, że jest to wina bloku include (jest to w pliku html.twig):
 

<div class="topnav" id="myTopnav">
        <a href="/">Główna</a>
        {% if app.user %}
        <a href="{{ path('logout') }}">Wylogowanie</a>
        {% else %}
        <a href="{{ path('login') }}">Logowanie</a>
        {% endif %}
        <a href="{{ path('post') }}">Strona z postami</a>
        {% include 'kategorie.php' %}
    </div>
<?php
        $servername = "localhost";
        $username = "root";
        $password = "";
        $dbname = "bazka";
        $conn = new mysqli($servername, $username, $password, $dbname);
        $sql = "SELECT * FROM kategorie";
        $result = $conn -> query($sql);

        while($row = $result->fetch_assoc()) 
        {
          echo $row['nazwa'];
        }
?>


Próbowałem także drukować za pomocą controllera, ale wyskakiwał błąd, że zmienne nie istnieją (oczywiście na innych ścieżkach istnieją, podawałem dokładną ścieżkę, bo pliki są w innych folderach)

komentarz zamknięcia: Rozwiązanie problemu: wystarczyło zmienić include na render bez parametrów. Dziękuję za pomoc <3

1 odpowiedź

+2 głosów
odpowiedź 22 lutego przez Arkadiusz Waluk Ekspert (287,950 p.)
wybrane 23 lutego przez Panelinio
 
Najlepsza
Nie możesz w taki sposób wywołać kodu PHP z poziomu Twiga. Właśnie dokładnie po to on jest, aby zachować separację między rzeczami typu wyciąganie danych z bazy a generowaniem wynikowego kodu HTML. Najprościej w tej sytuacji po prostu przekazać zmienną z kontrolera, jak choćby w tym przykładzie: https://symfony.com/doc/current/page_creation.html#rendering-a-template ze zmienną $number. Jeśli wyskakiwał błąd, to pokaż kod jak to konkretnie zrobiłeś i jaki błąd. Jeśli potrzebujesz tego w wielu miejscach w wielu szablonach, to można też pomyśleć o stworzeniu rozszerzenia do Twiga, które doda własną funkcję: https://symfony.com/doc/current/templates.html#writing-a-twig-extension (to jest nieco bardziej skomplikowany sposób).

Natomiast to co próbujesz zrobić w drugim pliku, nie wygląda jak sensowne zastosowanie Symfony. Masz spory framework, który obsługuje m.in. trzymanie konfiguracji i ładowanie jej z .env, a dane do bazy chcesz trzymać w jednym konkretnym pliku, który wyciąga kategorie? To samo kwestia połączenia do bazy danych, Symfony bardzo fajnie integruje się z Doctrine, które jest co prawda dość duże jeśli trzeba wykonać tylko jedno zapytanie, więc kwestia rozważenia czy warto. Nawet jeśli nie, to też lepiej byłoby przygotować jakiś jeden serwis łączący się do bazy danych, do niego przekazać parametry z env i wtedy wstrzykiwać go do innych klas czy kontrolerów. Obecny sposób wygląda trochę jakbyś do Symfony próbował wprowadzić praktyki, których się powinno unikać i próbował rozwiązać rzeczy, które zostały tam już fajnie na gotowo rozwiązane.
komentarz 22 lutego przez Panelinio Gaduła (4,440 p.)

Rozumiem. Właśnie uczę się tak symfony bardziej na poważnie a wcześniej operowałem na takich książkowych sposobach.
Zatem wróćmy do sposobu z kontrolerem:
Kontroler:

#[Route('/kategorie')]
class KategorieController extends AbstractController
{
    #[Route('/', name: 'app_kategorie_index', methods: ['GET'])]
    public function showData(KategorieRepository $kategorieRepository): Response
    {
        return $this->render('kategorie/index.html.twig', [
            'kategories' => $kategorieRepository->findAll(),
        ]);
    }
}

index.html.twig:
 

{% for kategorie in kategories %}
    <a>{{ kategorie.nazwa }}</a>
{% endfor %}

topnav.html.twig (generowanie menu):
 

<body>
    <div class="topnav" id="myTopnav">
        <a href="/">Główna</a>
        {% if app.user %}
        <a href="{{ path('logout') }}">Wylogowanie</a>
        {% else %}
        <a href="{{ path('login') }}">Logowanie</a>
        {% endif %}
        <a href="{{ path('post') }}">Strona z postami</a>
        {% include 'kategorie/index.html.twig' %}
    </div>
    
</body>

I potem to jest zawarte w base.html.twig:
 

<body>
    {% include 'topnav.html.twig' %}
    
        {% block body %}
        
        {% endblock %}
    </body>

A tak wyglądają ścieżki:

Controller/KategorieController.php
templates/kategorie/index.html.php
templates/topnav.html.twig
templates/base.html.twig

I jeszcze routes.yaml:
 

kategorie:
    path: /kategorie
    controller: App\Controller\KategorieController::showData

 

komentarz 22 lutego przez Panelinio Gaduła (4,440 p.)
Zapomniałem dodać jaki błąd wyskakuje, sorka
Otóż takie coś dostaję:
Uncaught PHP Exception Twig\Error\RuntimeError: "Variable "kategories" does not exist." at index.html.twig line 1
komentarz 22 lutego przez Arkadiusz Waluk Ekspert (287,950 p.)
Wygląda ogólnie poprawnie, ale czy tutaj te widoki są w dobrych miejscach wstawiane? W kontrolerze renderujesz kategorie/index.html.twig, to jest jak rozumiem ten for, który generuje kolejne <a>. Następnie dalej masz topnav i w nim znów masz osadzenie tego samego pliku kategorie/index.html.twig? Czy to jakiś inny plik index?

Generalnie i tak zmienna powinna być widoczna niżej, nawet jeśli wywoływany szablon ma extends lub jeśli jest include. Ale dla pewności możesz też spróbować tymczasowo stworzyć jakiś inny szablon, który ma za zadanie jedynie wyświetlić kategorie, nie ma żadnego extends ani niczego innego i zobaczyć czy wtedy też będzie problem.
1
komentarz 22 lutego przez Panelinio Gaduła (4,440 p.)

Tak, to ten sam plik index. Mogę jutro przetestować Twój pomysł i dam znać wink

komentarz 23 lutego przez Panelinio Gaduła (4,440 p.)

@Arkadiusz Waluk, Sprawa wygląda tak, że gdy nie korzystam z Include w topnav'ie i przejdę do 127.0.0.1/kategorie/ to kategorie pięknie się drukują. Chyba mam coś pokręcone ze ścieżkami :/

komentarz 23 lutego przez Arkadiusz Waluk Ekspert (287,950 p.)
A kiedy jest problem? Gdy jesteś na innej podstronie na przykład? Wtedy kwestia tego, czy w kontrolerze dla tej innej podstrony masz też przekazania zmiennej kategories w kontrolerze. Jeśli nie, to w tym miejscu jest problem. Odpalany jest jeden konkretny kontroler pod dany adres, więc w uproszczeniu jeśli nie przejdzie to przez kontroler, który przekazuje tę zmienną, to nie będzie widoczne. Musisz dołożyć ustawienie tej zmiennej do każdego kontrolera, który wywołuje widok, który wymaga tej wartości, niezależnie czy to jest bezpośrednio w widoku przekazywanym do render() czy gdzieś niżej, do widoku bazowego.

Jeżeli potrzebujesz mieć te kategorie na każdej podstronie, a nie chcesz ręcznie przekazywać tej zmiennej w każdym kontrolerze, to wtedy możesz spróbować np. utworzyć własną funkcję Twiga, jak linkowałem wyżej, albo użyć czegoś takiego: https://symfony.com/doc/current/templates.html#embedding-controllers
komentarz 23 lutego przez Panelinio Gaduła (4,440 p.)
Problem pojawia się na każdej innej stronie, bo tak skonfigurowałem base.html, aby on bazowo zawierał te menu. Teraz grzebię właśnie w nowym kontrolerze Header. Tutaj będę generować górne menu i kategorie. Myślę, że to dobra ścieżka. Dam znać jak wyjdzie
komentarz 23 lutego przez Panelinio Gaduła (4,440 p.)

@Arkadiusz Waluk, Jednak zrezygnowałem z tego kontrolera Header. Wrzuciłem wszystko do twiga od kategorii i dalej wyskakuje błąd  Variable "kategories" does not exist.
Nie wiem jak zaimplementować do swojego kodu przykład, który podałeś. Chciałbym aby generowało tyle ile jest w bazie, dynamicznie, a nie stale tak jak jest w przykładzie

 

#[Route('/kategorie')]
class KategorieController extends AbstractController
{
    public function index(KategorieRepository $kategorieRepository): Response
    {
        return $this->render('kategorie/index.html.twig', [
            'kategories' => $kategorieRepository->findAll(),
        ]);
    }
}
    <div class="topnav" id="myTopnav">
        <a href="/">Główna</a>
        {% if app.user %}
        <a href="{{ path('logout') }}">Wylogowanie</a>
        {% else %}
        <a href="{{ path('login') }}">Logowanie</a>
        {% endif %}
        <a href="{{ path('post') }}">Strona z postami</a>
        {% for kategorie in kategories %}
        <a>{{ kategorie.nazwa }}</a>
        {% endfor %}
    </div>

Edit: błąd pojawia się wszędzie oprócz 127.0.0.1/kategorie. Tutaj jedynie się te menu renderuje

1
komentarz 23 lutego przez Arkadiusz Waluk Ekspert (287,950 p.)
Jak wspomniałem wyżej, kwestia tego, że w każdym widoku, gdzie jest odwołanie do tej zmiennej, musiałaby być ona przekazana z kontrolera. Nawet jeśli zmienna jest używana gdzieś w widoku bazowym, ale nadal wystąpi przy tym wywołaniu. Aby tego nie robić ręcznie dla każdej podstrony to można np. wywołać renderowanie innego kontrolera, jak zalinkowałem, gdzie wtedy tylko w nim będzie przekazana ta zmienna, co jak wnioskuje z zamknięcia pytania się udało :)
1
komentarz 26 lutego przez Panelinio Gaduła (4,440 p.)

Tak, udało się. Dziękuję laugh

Podobne pytania

0 głosów
0 odpowiedzi 97 wizyt
pytanie zadane 18 kwietnia 2020 w PHP przez michh123 Bywalec (2,790 p.)
+1 głos
1 odpowiedź 76 wizyt
pytanie zadane 2 kwietnia w PHP przez XiverKi Bywalec (2,050 p.)
+1 głos
1 odpowiedź 174 wizyt

92,579 zapytań

141,432 odpowiedzi

319,664 komentarzy

61,965 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...