THELIA Forum

Welcome to the THELIA support and discusssion forum

Announcement

Rejoignez la communauté sur le Discord Thelia : https://discord.gg/YgwpYEE3y3

Offline


Bonjour,

J'essaie actuellement d'automatiser l'un de nos traitements en fournissant un fichier JSON rempli avec des infos sur quelques-uns de nos produits, et de l'utiliser pour alimenter une table avec.

Mon problème se situe au niveau de la récupération après upload. J'ai essayé de copier un peu le fonctionnement du module carousel et de son upload d'image.

<form name="dimensionsUpload" method="post" action="{url path="/admin/module/dimension/upload"}" class="clearfix">
    <div class="form-group">
        <label for="dimensions" class="control-label">Chargez le fichier <i>"dimension.json"</i></label>
        <div class="input-group">
            <input type="file" id="dimensions" required="required" name="dimensions" class="form-control">
            <span class="input-group-btn">
                <input type="submit" class="form-submit-button btn btn-sm btn-success" value="Mettre à jour les dimensions" >
            </span>
        </div>
    </div>
</form>

Au début j'ai tenté de créer vraiment un Form, de le déclarer, de le valider dans le contrôleur... Ce qui me génère une foule d'erreur donc je suis reparti sur une récupération du formulaire plus simple :

public function uploadDimensions() {        

        $request = $this->getRequest();
        $form = $request->request->get('dimensionUpload');

        $fileBeingUploaded = $request->files->get(sprintf('%s[file]', $form->get('dimensions')), null, true);

        $dimensions = json_decode($fileBeingUploaded, true);
        var_dump($dimensions);
        exit();
}

Lorsque j'ajoute mon fichier via ce form, j'obtiens cette erreur :

Fatal error: Call to a member function get() on null in BackOfficeController.php on line 117

//La ligne ne question :
$fileBeingUploaded = $request->files->get(sprintf('%s[file]', $form->get('dimensions')), null, true);

C'est évidemment l'objet $form qui est null. J'obtiens aussi un résultat null si j'essaie "$request->request->get('dimensions')".
J'ai beau essayer plein de petites choses, il n'est jamais rempli et je ne suis plus assez lucide pour voir ce qui ne va pas yikes

À tout hasard, il existerait pas un autre moyen d'ouvrir un fichier uploadé pour en parcourir le contenu ? Les méthodes de PHP de type $_FILES ne me conviennent pas non plus. hmm

Last edited by HeishPi (04-07-2019 08:30:18)


Développeur web Junior

Offline


Bonjour,
Ton objet $form n'en est pas un au sens du Framework Symfony. Donc ton code ne peut pas fonctionner en l'état. Il te faut passer par les méthode PHP pures mais pour une obscure raison tu ne souhaites pas les utiliser roll

Il est préférable de passer par la "méthode" Thelia (une version allégée des Formulaires Symfony) tel que présenté dans la documentation.

Pour référence un formulaire utilisé dans un projet récent

1 déclarer le formulaire dans le fichier Config/config.xml du module

    <forms>
        <form name="booking.vehicle" class="Booking\Form\VehicleForm"/>
    </forms>

2 Définir le formulaire dans un dossier Form/BookingForm.php

<?php

namespace Booking\Form;

use Booking\Booking;
use Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\ExecutionContextInterface;
use Thelia\Model\ConfigQuery;
use Thelia\Model\BrandQuery;
use Thelia\Form\BaseForm;
use Thelia\Core\Translation\Translator;

class VehicleForm extends BaseForm
{

    protected function buildForm()
    {

        $brands = BrandQuery::create()->find();
        $brandChoices = [];
        foreach ($brands as $brand) {
            $brand->getTranslation('fr_FR');
            $brandChoices[$brand->getId()] = $brand->getTitle();
        }

        $this->formBuilder

            ->add("model", "text", array(
                "constraints" => array(
                    new Constraints\NotBlank()
                ),
                "label" => "Modèle de véhicule"
            ))
            ->add("brand_id", "choice", array(
                'choices' => $brandChoices,
                'label' => Translator::getInstance()->trans("Marque", [], Booking::MODULE_DOMAIN)
            ))
        ;
        // parent::buildForm();
    }

    public function getName()
    {
        return "booking_vehicle_form";
    }
}

3 Afficher le formulaire dans un template

                                <div class="">
                                  {form name="booking.vehicle"}
                                    <form id="add-vehicle" action="{url path='/admin/booking_vehicle/add'}" method="post">
                                      {form_hidden_fields}
                                      {form_field field="model" form=$form }
                                          <div class="form-group group-firstname {if $error}has-error{elseif !$error && $value != ""}has-success{/if}">
                                              <label for="{$label_attr.for}">{$label}{if $required} <span class="required">*</span>{/if}</label>
                                              <div class="control-input">
                                                  <input type="text" name="{$name}" id="" value="{$smarty.get.firstname}" class="form-control" maxlength="255" {if $required} aria-required="true" required{/if} autofocus>
                                                  {if $error}
                                                      <span class="help-block">{$message}</span>
                                                  {elseif !$error && $value != ""}
                                                      <span class="help-block"><span class="fa fa-check"></span> {intl l="Thanks for signing up! We'll keep you posted whenever we have any new updates."}</span>
                                                  {/if}
                                              </div>
                                          </div>
                                      {/form_field}
                                      {form_field field="brand_id" form=$form }
                                          <div class="form-group group-firstname {if $error}has-error{elseif !$error && $value != ""}has-success{/if}">
                                              <label for="{$label_attr.for}">{$label}{if $required} <span class="required">*</span>{/if}</label>
                                              <div class="control-input">
                                                  <select type="text" name="{$name}" id="{$field}" value="{$smarty.get.brand_id}" class="form-control" maxlength="255" {if $required} aria-required="true" required{/if} autofocus>
                                                      {foreach $choices as $brand}
                                                          <option value="{$brand->value}">{$brand->label}</option>
                                                      {/foreach}
                                                  </select>
                                                  {if $error}
                                                      <span class="help-block">{$message}</span>
                                                  {elseif !$error && $value != ""}
                                                      <span class="help-block"><span class="fa fa-check"></span> {intl l="Thanks for signing up! We'll keep you posted whenever we have any new updates."}</span>
                                                  {/if}
                                              </div>
                                          </div>
                                      {/form_field}
                                      <div class="">
                                          <div class="form-group group-btn">
                                              <div class="control-btn">
                                                  <button type="submit" class="btn btn-primary"><i class="fa fa-chevron-right"></i>Ajouter un modèle</button>
                                              </div>
                                          </div><!--/.form-group-->
                                      </div>
                                    </form>
                                  {/form}
                                </div>

4 Traiter le formulaire dans un controller

<?php

namespace Booking\Controller;

use Booking\Booking;
use Booking\Form\VehicleForm;
use Booking\Model\BookingVehicles;
use Booking\Model\BookingVehiclesQuery;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Thelia\Controller\Admin\BaseAdminController;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;

use Thelia\Form\Exception\FormValidationException;
use Thelia\Tools\URL;

/**
 * Class VehicleController
 * @package Booking\Controller
 * @author Nicolas Léon <nicolas@omnitic.com>
 */
class VehicleAdminController extends BaseAdminController
{
    public function addAction()
    {
        $vehicle_form = new VehicleForm($this->getRequest());
        $vehicleForm = $this->validateForm($vehicle_form, "POST");

        $vehicle = new BookingVehicles();

        $vehicle->setModel($vehicleForm->get('model')->getData());
        $vehicle->setBrandId($vehicleForm->get('brand_id')->getData());
        $vehicle->save();
        
       // Redirection vers page de confirmation
        return RedirectResponse::create(URL::getInstance()->absoluteUrl('/admin/module/' . Booking::MODULE_NAME . '?current_tab=vehicles_pane'));
        // return $this->redirect('/admin/module/' . Booking::MODULE_NAME . '?current_tab=vehicles_pane');
    }
}

Pour la partie upload de fichier c'est très bien explique dans la doc Symfony, notamment ici  (en anglais): How to upload file.

Passer par les forms te permet  de disposer d'un ensemble de méthode bien pratiques sans avoir à réinventer la roue tongue

Offline


Pff, les méthodes PHP ne me convenaient pas tout simplement parce que je ne les comprenais pas... Ce matin avec une cafetière dans le cornet, ça va beaucoup mieux roll

Du coup j'accède à mes données de cette façon :

$dimensions = json_decode(file_get_contents($_FILES['dimensions']['tmp_name']), true);
        echo "Dimensions : <br>";
        foreach ($dimensions as $dimension){
            foreach ($dimension as $key => $value){
                echo $key." : ".$value.'<br>';
            }
            echo "<br><br>";
        }
        exit();

Merci tout de même du temps que t'as pris pour ça, ça m'a redonner courage pour m'attaquer à la doc php.net et ses 16 ans d'ancienneté cool
Et puis ton exemple est pas perdu du tout puisqu'il est bien fait, complet, et que je reviendrais sûrement dessus à un moment ou un autre puisque les forms me posent souvent problème.

Bonne journée et merci encore !


Développeur web Junior

Offline


Il est vrai que le café du matin fait souvent des miracles.

Je suis sût que mon example pourra aider d'autres personnes. Pour ma part j'ai souvent appris pas mal de choses à partir des posts d'autres utilisateurs cool

Last edited by Nog (04-07-2019 09:34:01)