@BezdomnyiBox
Студент программной инженерии

Почему не рендерится ответ fetch в виде DOM?

Я новичок в symfony и столкнулся с проблемой. С помощью curl я обращаюсь к внешнему API и достаю данные. В chrome если посмотреть на сеть есть результат запроса, где есть отображение таблицы. Однако я хочу чтобы страница с которой я произвожу запрос обновилась при нажатии кнопки "искать"
Скриншоты и код (но не относящийся к проблеме напрямую)
67214e9cc3777566773163.png

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\RedirectResponse;

class ProductController extends AbstractController
{
    // public function searchForm(Request $request):Response
    // {
    //     $error = null;
    //     $products = [];

    //     return $this->render('product/search.html.twig', [
    //         'error' => $error,
    //         'products' => $products,
    //         'last_article' => $request->request->get('Article', ''),
    //         'last_api_key' => $request->request->get('api_key', ''),
    //     ]);
    // }

    public function searchByArticle(Request $request):Response
    {
        $error = null;
        $products = [];

        if ($request->isMethod('POST')) {
            // Получение данных из формы
            $articleNumber = $request->request->get('Article');
            $apiKey = $request->request->get('api_key'); // Получаем api_key от пользователя

            if (!$articleNumber || !$apiKey) {
                $error = 'Параметры "Article" и "api_key" обязательны.';
            } else {
                // Инициализация cURL
                $ch1 = curl_init();

                // 1. Получить все возможные бренды для заданного номера
                $fields = array("JSONparameter" => json_encode(['Article' => $articleNumber]));
                $url = "http://api.tmparts.ru/api/ArticleBrandList?" . http_build_query($fields);

                curl_setopt($ch1, CURLOPT_URL, $url);
                curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
                $headers = [
                    'Authorization: Bearer ' . $apiKey,
                ];
                curl_setopt($ch1, CURLOPT_HTTPHEADER, $headers);

                $response = curl_exec($ch1);
                $artList = json_decode($response, true);

                curl_close($ch1);

                if (isset($artList['Message']) && $artList['Message'] != "") {
                    $error = $artList['Message'];
                } elseif ($artList['BrandList'] == null) {
                    $error = 'Номер не найден.';
                } else {
                    // 2. По каждому найденному бренду выполнить проценку
                    $products = [];
                    foreach ($artList['BrandList'] as $brand) {
                        // Инициализация cURL для второго запроса
                        $ch = curl_init();
                
                        $fields = array("JSONparameter" => json_encode([
                            'Brand' => $brand['BrandName'],
                            'Article' => $artList['Article'],
                            'is_main_warehouse' => 0,
                        ]));
                        $url = "http://api.tmparts.ru/api/StockByArticle?" . http_build_query($fields);
                
                        curl_setopt($ch, CURLOPT_URL, $url);
                        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                        $headers = [
                            'Authorization: Bearer ' . $apiKey,
                        ];
                        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
                
                        $response = curl_exec($ch);
                        
                        $artListWithPrices = json_decode($response, true);

                
                        curl_close($ch);
                
                        // Обработка и добавление результатов в $products
                        foreach ($artListWithPrices as $item) {
                            if (isset($item['warehouse_offers']) && is_array($item['warehouse_offers'])) {
                                foreach ($item['warehouse_offers'] as $offer) {
                                    $products[] = [
                                        'brand' => $item['brand'] ?? '',
                                        'article' => $item['article'] ?? '',
                                        'name' => $item['article_name'] ?? '',
                                        'quantity' => $offer['quantity'] ?? 0,
                                        'price' => $offer['price'] ?? 0,
                                        'delivery_duration' => $offer['delivery_period'] ?? 0,
                                        'vendorId' => $offer['id'] ?? '',
                                        'warehouseAlias' => $offer['warehouse_code'] ?? '',
                                        'warehouseName' => $offer['warehouse_name'] ?? '',
                                        'branchName' => $offer['branch_name'] ?? '',
                                    ];
                                }
                            }
                        }
                        // Рендеринг шаблона формы поиска с результатами (если есть)
                        return $this->render('product/search.html.twig', [
                            'error' => $error,
                            'products' => $products,
                            'last_article' => $request->request->get('Article', ''),
                            'last_api_key' => $request->request->get('api_key', ''),
                        ]);
                    }
                }
            }  
        }

        
           
        // Рендеринг шаблона формы поиска с результатами (если есть)
        return $this->render('product/search.html.twig', [
            'error' => $error,
            'products' => $products,
            'last_article' => $request->request->get('Article', ''),
            'last_api_key' => $request->request->get('api_key', ''),
        ]);
    }

}


controllers:
    resource:
        path: ../src/Controller/
        namespace: App\Controller
    type: attribute

product_search:
    path: /product/search
    controller: App\Controller\ProductController::searchByArticle
    methods: [GET, POST]


{% extends 'base.html.twig' %}

{% block title %}Поиск товара{% endblock %}

{% block body %}
    <h1>Поиск товара по артикулу</h1>

    {% if error %}
        <div style="color: red;">
            <p>{{ error }}</p>
        </div>
    {% endif %}

    <form method="post" action="{{ path('product_search') }}">
        <div>
            <label for="article">Артикул:</label>
            <input type="text" id="article" name="Article" value="{{ last_article }}" required>
        </div>
        <div>
            <label for="api_key">API Key:</label>
            <input type="text" id="api_key" name="api_key" value="{{ last_api_key }}" required>
        </div>
        <button type="submit">Искать</button>
    </form>

    {% if products is not empty %}
        <h2>Результаты поиска</h2>

        <table border="1" cellpadding="5" cellspacing="0">
            <thead>
                <tr>
                    <th>Бренд</th>
                    <th>Артикул</th>
                    <th>Название</th>
                    <th>Количество</th>
                    <th>Цена</th>
                    <th>Время доставки (дней)</th>
                    <th>Код товара</th>
                    <th>Код склада</th>
                    <th>Склад</th>
                    <th>Филиал</th>
                </tr>
            </thead>
            <tbody>
                {% for product in products %}
                    <tr>
                        <td>{{ product.brand }}</td>
                        <td>{{ product.article }}</td>
                        <td>{{ product.name }}</td>
                        <td>{{ product.quantity }}</td>
                        <td>{{ product.price }}</td>
                        <td>{{ product.delivery_duration }}</td>
                        <td>{{ product.vendorId }}</td>
                        <td>{{ product.warehouseAlias }}</td>
                        <td>{{ product.warehouseName }}</td>
                        <td>{{ product.branchName }}</td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    {% elseif products is empty %}
        <p>Товары не найдены.</p>
    {% endif %}
{% endblock %}
  • Вопрос задан
  • 103 просмотра
Решения вопроса 1
 Если вам нужно динамическое обновление частей страницы, и вы не можете это сделать сами, то вам не стоит изобретать велосипед, а воспользоваться готовыми библиотеками для этого.

1. Вы можете вообще взять под контроль весь рендеринг DOM при помощи React, Vue и т.д. Но это вам надо будет серьёзно погрузиться в изучение этих фреймворков, и в классическом варианте вы потеряете поисковую оптимизацию.

2. Воспользоваться библиотеками, которые как раз для этого предназначены.

- Для Symfony есть прекраснейший компонент Live Components. Вы пишете всё в Twig, вставляя там особые атрибуты, и компонент возьмёт на себя всю работу по замене частей страницы нужными компонентами.

- Либо, если вам не понравится почему-то Live Components, можете воспользоваться Htmx

В результате вам даже не нужно будет особо знать JavaScript, всё будет автоматом работать

P.S. Если вы уже пользуетесь фреймворком, то пользуйтесь его плюшками, сильно упрощающими жизнь. Я имею ввиду, что не стоит использовать голый curl с простынёй настроек, когда в наличии имеется превосходный HTTP Client https://symfony.com/doc/current/http_client.html
А для сериализации/десериализации из JSON в PHP и обратно, лучше всего использовать Serializer component https://symfony.com/doc/current/components/seriali...
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы