IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Factorisation de mon code


Sujet :

Symfony PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 221
    Par défaut Factorisation de mon code
    Hello !
    J'ai écris un code pour insérer un csv dans ma bdd avec Synfony ! Le code marche bien et j'ai aussi géré les erreur qui pouvait être lié à l'insertion mais le souci c'est que mon code est un peu trop répétitif :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    /.../
            $originalFileName = pathinfo($csvFile->getClientOriginalName(), PATHINFO_FILENAME);                  
            $safeFileName = $slugger->slug($originalFileName);              
            $newFileName = $safeFileName.'-'.uniqid().'.'.$csvFile->guessExtension();        
            $csvFile->move($fileDirectory, $newFileName);                    
            $upload->setCsvFile($newFileName);                   
            $manager->persist($upload);
            $csv = Reader::createFromPath($fileDirectory.$newFileName);                    
            $csv->setHeaderOffset(0);
            $csv->setDelimiter(';');
            $csv->setEscape('');
            $records = $csv->getRecords();   
     
            foreach ($records as $record) {
                $numero = $record["Identifiant de la fiche"];
                $date = $record["Date d'emission de la fiche"];
                $origine = $record['Cas origine'];
                $cloture = $record['Cas cloture'];
                $commentaire = $record['Commentaire'];
                $epidemi = $record['Type de cas'];          
                $score = $record['Score'];   
     
                $infection = $manager->getRepository(Infection::class)->findOneBy(['infection' => mb_convert_encoding($record['Type infection'], 'UTF-8', 'Windows-1252')]);
                $structure = $manager->getRepository(Structure::class)->findOneBy(['nom' => mb_convert_encoding($record['Nom de la structure'], 'UTF-8', 'Windows-1252')]);
     
                $commentaire = mb_convert_encoding($commentaire, 'UTF-8', 'Windows-1252');
                $epidemi = mb_convert_encoding($epidemi, 'UTF-8', 'Windows-1252');
     
     
                //verification du numero de la fiche et utilisation pour empecher upload de doublon
                if(!(is_numeric($numero)) || (strlen($numero) !== 5)){
                    $this->addFlash('error','Problème de donnée dans le champs "Identifiant de la fiche"');
                    return $this->redirectToRoute('signalement.upload');  
                }
                $signal = $manager->getRepository(Signalement::class)->findOneBy(['numero' => $numero]);
                if(is_null($signal)){
                    $signal = (new Signalement())->setNumero($numero);
                    $manager->persist($signal);
                }
     
                //verification de la date
                [$d, $m, $y] = explode('/',$date);
                if(!checkdate($m, $d, $y)){
                    $this->addFlash('error','Problème de donnée dans le champ "date d\'émission"');
                    return $this->redirectToRoute('signalement.upload');  
                }
                $dbdate = \DateTimeImmutable::createFromFormat('d/m/Y', $date);
     
                //verification que les champs cas origine et cas cloture soient bien numeric
                if(!(is_numeric($origine)) ||  !(is_numeric($cloture))){
                    $this->addFlash('error','Problème de donnée dans un des champs "Cas origine" et/ou "Cas cloture"');
                    return $this->redirectToRoute('signalement.upload');  
                }        
                //si cas origine est supérieur à cas cloture
                if($origine > $cloture){
                    $this->addFlash('error','Problème de donnée dans un des champs "Cas origine / Cas cloture" le cas d\'origine ne peut pas être supérieur au cas cloture');
                    return $this->redirectToRoute('signalement.upload');  
                }
     
                //si le champ commentaire est vide
                if(empty($commentaire)){
                    $this->addFlash('error','Problème de donnée dans le champ "commentaire", celui-ci ne peut pas être vide');
                    return $this->redirectToRoute('signalement.upload');  
                }
     
                //si le champ Type de cas est valide avec verification type de cas/cas cloture
                if(($epidemi !== "Épidémie") && ($epidemi !== "Cas isolé")){
                    $this->addFlash('error','Problème de donnée dans le champ "Type de cas" en ligne(s) : '. $counter);
                    return $this->redirectToRoute('signalement.upload');  
                }else if(($epidemi !== "Épidémie") && ($cloture > 1)){
                    $this->addFlash('error','Le type de cas ne peut pas être "Cas Isolé" si le nombre de cas cloture est > 1');
                    return $this->redirectToRoute('signalement.upload');
                }else if(($epidemi !== "Cas isolé") && ($cloture == 1)){
                    $this->addFlash('error','Le type de cas ne peut pas être "Épidémie" si le nombre de cas cloture est = 1');
     
                //si le champ Score est valide 
                if(empty($score) || !is_numeric($score) || strlen($score) > 4 || $score > 212){
                    $this->addFlash('error','Problème de donnée dans le champ "Score"');
                    return $this->redirectToRoute('signalement.upload');  
                }
     
                //si le champ Type infection est valide
                if(!(ctype_alpha($infection)) && empty($infection)){
                    $this->addFlash('error','Problème de donnée dans le champ "Type infection"');
                    return $this->redirectToRoute('signalement.upload');  
                }
     
                //si le champ Structure est valide
                if(!(ctype_alpha($structure)) && empty($structure)){
                    $this->addFlash('error','Problème de donnée dans le champ "Structure"');
                    return $this->redirectToRoute('signalement.upload');  
                }  
     
                $signal              
                    ->setDate($dbdate)
                    ->setCasO($origine)
                    ->setCasC($cloture)
                    ->setCommentaire($commentaire)
                    ->setEpidemie($epidemi)
                    ->setCapacite($capacite)              
                    ->setScore($score)      
                    ->setInfection($infection) 
                    ->setStructure($structure)
                    ;
            }
    /.../
     
     
                    return $this->redirectToRoute('signalement.upload');
                }
    https://codeshare.io/5DpjRW
    Et encore il n'y a pas tout !

    Du coup je cherche à factoriser un peu tout ça... La méthode serait donc de créer une fonction en dehors du foreach et appeller la fonction dans le foreach !

    Etant encore debutant je fais d'abord des test mais mes test ne marche pas...

    Dans mon code , juste avant le foreach j'écris cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            function test(string $truc): string
            {
                return "le type est : $truc";
            }
    Et dans mon foreach j'insère cette ligne :
    echo test($commentaire);J’envoie donc le csv en upload, celui-ci est bien flush mais j'ai 0 message echo...

    J'ai essayé en mettant cette ligne ailleurs, en mettant volontairement une mauvaise valeur a un champs dans le CSV, et mettre mon echo dans la condition d'erreur lié à la mauvaise valeur... j'ai aussi essayé avec var_dump.... j'ai rien qui s'affiche !

    Comment je peux faire dans un premier temps pour que ca m'affiche correctement chaque valeur de chaque boucle du csv ? merci !

    Ensuite j'aimerais voir pour reduire mon code le plus possible ! Est ce que finalement l'idée de la fonction est la meilleurs selon vous ?

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 221
    Par défaut
    Voici une version complète de mon code à factoriser :

    https://codeshare.io/2WbQqM

    On voit très bien que ce code a besoin d'être réduit car beaucoup de conditions qui se répètent !!

    Depuis le post de mon message j'ai un peu essayé plein de chose surtout à base de fonction mais je tombe souvent sur un message d'erreur que j'essaye de contourner à chaque fois mais au final je me dis que je n'utilise pas les bonnes méthodes :

    https://codeshare.io/alJ0Rj

  3. #3
    Membre émérite
    Homme Profil pro
    Autre
    Inscrit en
    Juillet 2021
    Messages
    492
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Juillet 2021
    Messages : 492
    Par défaut
    Bonjour,

    Premier conseil : Il ne faut pas contourner les messages d'erreur, il faut les lires afin de comprendre les erreurs pour les corriger correctement.
    En cas d'erreur que tu ne comprends pas, utilise un moteur de recherche et/ou une IA pour comprendre l'erreur et comment la corriger, ou poste le message d'erreur complet avec le code correspondant sur le forum.


    Petit point vocabulaire : En POO, une fonction à l'intérieure d'une classe est appelée une méthode.


    Tu ne peux pas voir les echo qui sont dans la méthode upload() de ton contrôleur car celui-ci fait une redirection à la fin du traitement.
    La page affichée dans le navigateur est donc la page redirigée (signalement.index) qui est donc générée par la méthode/route 'index' de ton contrôleur.

    Une solution simple est de définir l'option intercept_redirects à true dans la configuration du Web Profiler.
    Fichier config/packages/web_profiler.yaml :
    Code yaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    when@dev:
        web_profiler:
            toolbar: true
            intercept_redirects: true
    Tu pourras ainsi voir les echo dans la méthode upload() avant que la page soit redirigé.


    Evite de créer des fonctions imbriquées (une fonction dans une fonction) ou utilise une fonction anonyme dans ce cas.
    Si besoin, crée simplement une méthode privée que tu peux appeler depuis les autres méthodes de la classe ;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    final class SignalementController extends AbstractController
    {
        #[Route('/signalement/upload', name: 'signalement.upload', methods:['GET', 'POST'])]
        public function upload(
            Request $request,
            SluggerInterface $slugger,
            EntityManagerInterface $manager,
            SignalementRepository $repository,       
            #[Autowire('%kernel.project_dir%/public/uploads/')] string $fileDirectory
        ) :Response {
            $upload = new Upload();
     
            // [...]	
            echo $this->uneAutreMethode();
     
            return $this->redirectToRoute('signalement.index');         
        }
     
        private function uneAutreMethode() :string
        {
            return 'exemple';
        }
    }

    Enfin pour la partie validation, au lieu de faire la validation manuellement, tu pourrais utiliser le composant Validator de Symfony.
    Il faut alors définir les contraintes de validation sur ton entité Signalement.
    Pour les contraintes simples (donnée non vide, type de la donnée, valeurs acceptées...) tu peux utiliser les attributs NotBlank, NotNull, Type, Date, Choice, etc. : https://symfony.com/doc/current/vali...ml#constraints
    Tu devras surement utiliser des contraintes personnalisées et/ou la contrainte Expression pour les contraintes plus avancées (cas date origine supérieur à la date clôture par exemple).
    https://symfony.com/doc/current/doct...dating-objects

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    221
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 221
    Par défaut
    Salut Pytet et merci d'avoir pris le temps de m'avoir répondu

    Du coup j'ai ajouté intercept_redirects: true dans le fichier web_profiler.yaml

    J'ai suivi ton conseil et créé une fonction juste après la fonction upload en ligne 244 et ajouter l’appelle de la fonction en ligne 236 !

    https://codeshare.io/2WbQqM

    mais cela m'affiche une erreur dans ma console : Error: Form responses must redirect to another locationPour la validation je connaissais les constraintes sur l'entity j'en ai déjà quelques une en place !

    Voici mon Entity Signalement : https://codeshare.io/am7p4X

    Ceci dit je me demandais si cela marchait bien dans mon cas de figure et l'import CSV !

    J'ai essayé du coup d'ajouter une contrainte Choice a $type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        #[ORM\Column(type : 'string', length: 10)]
        #[Assert\NotBlank()]
        #[Assert\Choice(choices: ['ESIN', 'Portail'])]
        private string $type;
    J'ai volontairement mis autre chose que ces choix dans le CSV mais celui-ci passe et est inséré qand même dans la BDD.

  5. #5
    Expert confirmé Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    2 550
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 2 550
    Par défaut
    Bonjour,

    La méthode upload(....):Response est censée retourner un résultat de type Response (une vue); cependant, l'utilisation de l'echo pour afficher le contenu de la méthode otherFunction():string qui est de type string (chaine de caractère) court-circuite ce processus.

    Cela génère une erreur d'affichage, ça plante (le echo envoie les en-têtes HTTP trop tôt), et donc PHP ne peut pas traiter simultanément l'envoi d'une chaîne de caractères brute et d'un objet Response, et ne sait pas quoi afficher, une vue? ou une chaine de caractère?.

    Pour résoudre ceci, stockez le message de la méthode otherFunction avec addFlash $this->addFlash('success',$this->otherFunction()); au lieu de l'écrire avec echo.

  6. #6
    Membre émérite
    Homme Profil pro
    Autre
    Inscrit en
    Juillet 2021
    Messages
    492
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Juillet 2021
    Messages : 492
    Par défaut
    Un echo dans une fonction n'équivaut pas à un return, l'erreur n'est pas en lien avec le type de retour ("Return value must be of type...").
    En effet l'affichage avant la redirection pourrait causer une erreur php "headers already send", mais on verrait les echo puique c'est la cause cette erreur.

    L'erreur Error: Form responses must redirect to another location qui se trouve dans la console du navigateur est une erreur javascript liée à Turbo UX qui gère notamment la soumission des formulaires en ajax (ce qui explique que tu ne ne vois pas les echo).
    Il applique le principe Post-Redirect-Get et attends donc un status code 3xx pour une redirection ou 422 en cas d'erreur de validation (ce que fait déjà Symfony en cas d'erreur de validation de ton formulaire).
    Dans l'onglet Réseau des outils de dev du navigateur, tu peux retrouver la dernière requête POST qui correspond à ton upload et tu peux y voir la sortie avec les echo dans le sous-onglet Réponse ou Aperçu selon le navigateur.
    https://symfonycasts.com/screencast/turbo/forms

    Si tu ne connais pas encore Turbo et/ou que tu ne veux pas l'utiliser tout de suite (il semble être installé de base dans les nouveux projets sf webapp), tu peux simplement désactiver son utilisation pour ce formulaire avec attribut data ({% form_start(form, {'attr': {'data-tubro': 'false'}}) %} pour ton formulaire twig).


    Tu peux aussi utiliser le logger du framework en ajoutant un paramètre LoggerInterface $logger à ton controleur ou tes services (avec un use Psr\Log\LoggerInterface;) et en appelant $logger->debug().
    Les logs sont dans ton_projet/var/log par défaut.

    Le mieux pour déboguer ton code serait d'utiliser Xdebug (commande php -v pour vérifier si celui-ci est déjà installé sur environnement de dev, sinon voir https://xdebug.org/docs/install
    Le plus compliqué est souvent de configurer correctement Xdebug avec ton ide la première fois, tu pourras ensuite déboguer ton code pas à pas, avec des points d'arrêts, et analyser les variables de ton code pendant l’exécution.


    Concernant ton contrôleur, je me souviens que tu t'étais inspiré de l'exemple de la doc pour l'upload.
    Si contrairement à l'exemple, les fichiers csv n'ont pas besoin d'être conservés, tu peux alors simplifier ton contrôleur en supprimant l'entité Upload et son utilisation (ajouter l'option 'mapped' => false dans le ImportType pour ne plus lier le fichier à une entité) et aussi simplifier le renommage du fichier uploadé.

    Toute la partie concernant l'import du csv pourrait être déplacé dans un ou plusieurs services.
    Ton contrôleur très simplifié pourrait ressembler à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <?php
     
    namespace App\Controller;
     
    use App\Form\ImportType;
    use App\Service\SignalementImporter;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Attribute\Route;
     
    final class SignalementController extends AbstractController
    {
        #[Route('/signalement/upload', name: 'signalement.upload', methods: ['GET', 'POST'])]
        public function upload(
            Request $request,
            SignalementImporter $signalementImporter
        ): Response {
            $form = $this->createForm(ImportType::class)->handleRequest($request);
     
            if ($form->isSubmitted() && $form->isValid()) {
                /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $uploadedFile*/
                $uploadedFile = $form->get('csvFile')->getData();
                $filename = uniqid() . '.' . $uploadedFile->guessExtension();
                $destination = $this->getParameter('kernel.project_dir') . '/var/upload/tmp';
     
                $uploadedFile->move($destination, $filename);
     
                $signalementImporter->importFromFile($destination . '/' . $filename);
     
                unlink($destination . '/' . $filename);
     
                $this->addFlash('success', 'Bien ajouté avec succès');
                return $this->redirectToRoute('signalement.index');
            }
     
            return $this->render('pages/signalement/upload.html.twig', [
                'form' => $form
            ]);
        }
    }
    Si tu veux afficher les résultats de l'import dans la vue après la redirection via une variable de session :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
        #[Route('/signalement/upload', name: 'signalement.upload', methods: ['GET', 'POST'])]
        public function upload(
            Request $request,
            SignalementImporter $signalementImporter
        ): Response {
            $session = $request->getSession();
            $form = $this->createForm(ImportType::class)->handleRequest($request);
     
            if ($form->isSubmitted() && $form->isValid()) {
                /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $uploadedFile*/
                $uploadedFile = $form->get('csvFile')->getData();
                $filename = uniqid() . '.' . $uploadedFile->guessExtension();
                $destination = $this->getParameter('kernel.project_dir') . '/var/upload/tmp';
     
                $uploadedFile->move($destination, $filename);
     
                $results = $signalementImporter->importFromFile($destination . '/' . $filename);
                $session->set('import-results', $results);
     
                unlink($destination . '/' . $filename);
     
                return $this->redirectToRoute('signalement.index');
            }
     
            $results = [];
     
            if ($session->has('import-results')) {
                $results = $session->get('import-results');
                $session->remove('import-results');
            }
     
            return $this->render('pages/signalement/upload.html.twig', [
                'form' => $form,
                'results' => $results
            ]);
        }
    Ne pas oublier l'option mapped dans la classe ImportType, tu peux d'ailleurs y mettre une contrainte pour le formulaire d'upload :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
        public function buildForm(FormBuilderInterface $builder, array $options): void
        {
            $builder
                ->add('csvFile', FileType::class, [
                    'label' => 'Fichier CSV des signalements',
                    'mapped' => false,
                    'required' => true,
                    'constraints' => [
                        new Assert\File(
                            maxSize: '2M',
                            extensions: ['csv'],
                        ),
                    ],
                ])
            ;
        }
    La classe App\Service\SignalementImporter serait une simple classe php qui peut utiliser d'autres services ou packages externes.
    Un exemple incomplet et non fonctionnel juste pour te montrer l'organisation du code (il faut notamment convertir les données du csv dans les bons types de l'entité avant d'hydrater l'entité) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <?php
     
    namespace App\Service;
     
    use App\Entity\Signalement;
    use Doctrine\ORM\EntityManagerInterface;
    use Psr\Log\LoggerInterface;
    use Symfony\Component\Validator\Validator\ValidatorInterface;
     
    class SignalementImporter
    {
        public function __construct(
            private CsvReader $csvReader,
            private ValidatorInterface $validator,
            private EntityManagerInterface $entityManager,
            private LoggerInterface $logger
        ) {}
     
        public function importFromFile(string $filepath): void
        {
            $this->logger->debug('Import du fichier ' . $filepath);
     
            foreach ($this->csvReader->getRows($filepath) as $index => $row) {
                // TODO normalize $row
     
                $signalement = new Signalement();
                $signalement
                    ->setNumero($row['numero'])
                    ->setType($row['ESiN ou Portail'])
                    // ->set[...]
                ;
     
                $errors = $this->validator->validate($signalement);
                if (0 === count($errors)) {
                    $this->entityManager->persist($signalement);
                }
            }
     
            $this->entityManager->flush();
        }
    }
    Les contraintes de ton entité ne sont validées que si tu vérifies l'entité avec le validator ($this->validator->validate($signalement)).

    Un autre exemple de service utilisé par le SignalementImporter en reprenant ton code pour la lecture du csv :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <?php
     
    namespace App\Service;
     
    use League\Csv\Reader;
     
    class CsvReader
    {
        public function getRows(string $filepath): \Generator
        {
            $csv = Reader::from($filepath)
                ->setHeaderOffset(0)
                ->setDelimiter(',');
     
            foreach ($csv->getRecords() as $record) {
                yield $record;
            }
        }
    }

Discussions similaires

  1. Mon code n'est pas interprété !
    Par korriganez dans le forum Langage
    Réponses: 3
    Dernier message: 31/05/2006, 15h46
  2. [Exécutable]puis je creer un executable a partir de mon code ?
    Par youpileouf dans le forum Général Java
    Réponses: 3
    Dernier message: 17/06/2005, 09h15
  3. Optimiser mon code ASP/HTML
    Par ahage4x4 dans le forum ASP
    Réponses: 7
    Dernier message: 30/05/2005, 10h29
  4. Réponses: 1
    Dernier message: 21/02/2005, 12h40
  5. [langage] algo de bissection dans mon code
    Par killy dans le forum Langage
    Réponses: 5
    Dernier message: 19/01/2004, 18h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo