J'ai cherché partout, je ne vois nulle part /login_ckeck, j'ai vérifié dans les routes, dans d'autres fichiers, ... bref introuvable. Donc ma question est : à quoi correspond /login_check ?
Ensuite j'ai lu dans la documentation que login_check ne devait être accessible qu'avec les droits admin ou user enregistré, et non pas visible par tout le monde. Dans la documentation ils préconisent donc de préciser /admin/login_check. J'ai essayé et dans ce cas impossible d'accéder ne serait-ce qu'à la page de login, ce qui me laisse un peu perplexe : /login est accessible, alors pourquoi est-ce que ça ne fonctionne pas juste en changeant /admin/login_check pour la vérification ?
Ce qui amène à une 3ème question ... comment faire pour sécuriser login_check en laissant login accessible à tout le monde ?
Si vous avez quelques réponses à apporter, je suis preneur.
Désolé Vincent, je n'ai pas la réponse à ta question.
J'ai également une question à poser : comment « vider » le textarea après la soumission formulaire ? J'ai pensé le faire en jquery, soit on le fait immédiatement et le formulaire n'est pas soumis… soit on le fait avec un timeout et après la soumission dudit formulaire la page se réactualise donc cela ne fonctionne pas !
J'ai du mal à croire qu'il n'y a pas une solution ? En plus, je parie qu'elle est toute bête…
letengu : tu fais une redirection vers la page qui t'intéresse.
vincent48 : login est géré directemnt par silex, c'est pas toi qui t'en occupe et ce que tu as lu dans la doc :
The login_path path must always be defined outside the secured area (or if it is in the secured area, the anonymous authentication mechanism must be enabled -- see below);
The check_path path must always be defined inside the secured area.
La zone d'influence de ton firewall (la zone protégée) est '/' tout ton site car il doit matcher 'pattern' => '^/' . Pour login_path on est clairement dans le cas entre parenthèse et donc ton login_check l'est bien aussi.
dans la doc la zone protégé est /admin ('pattern' => '^/admin/') d'ou ta confusion et zone protégée ne veux pas dire zone interdite, on le voit bien dans notre cas, mais zone ou le firewall est définit.
il est possible de remplacer match par get ou post, si j'ai bien compris match laisse le choix d'utiliser la méthode get ou post, par contre si j'utilise get, post sera refusé et si j'utilise post, c'est get qui sera refusé, est-ce que c'est bien cela ?
ensuite, à la fin de la ligne, il y a bind et je n'ai pas bien compris ce qu'on mets entre parenthèses ... c'est un nom que je choisis au hasard, un peu comme une étiquette ? (ici admin_user_add) ou bien est-ce que ça doit correspondre à quelque chose de précis ?
Notre site internet CQMI utilise Joomla 3.7 mais nous avons une vieille version de PHP sur Ubuntu. Nous avons prévu de mettre à jour la version du système Ubuntu pour pouvoir mettre à niveau vers PHP version 7.
J'ai entendu sur une formation Joomla sur Elephorm que la version PHP 7 permettait d'avoir un site web 2 à 3 fois plus rapides. est-ce que c'est vrai ? Quels sont les avantages à mettre à niveau la version de PHP ?
quels sont les avantages et inconvénients ? merci de votre aide
Voilà ... je ne sais pas si mon post est bien placé ici, mais il parle directement de Silex. Donc je poste ici.
Afin de progresser davantage dans l'utilisation de Silex, je me suis lancé dans mon projet avec cette technologie. Voici le problème que je rencontre :
j'ai une base de données avec une table "specialities"
j'ai une page admin sur mon site avec accès par la route "/speciality"
la page des spécialités est divisée en 3 colonnes : 1 colonne avec le menu admin, 1 colonne avec la liste des spécialités, 1 colonne avec les détails d'une spécialité
lorsque je clique sur une spécialité dans la liste, je souhaite afficher les détails de cette spécialité dans la dernière colonne
Dans le cours nous avons appris à charger une page complète, mais là ce que je souhaite c'est charger seulement la colonne des détails avec AJAX sans toucher au reste de la page.
Or je ne vois pas comment je peux appeler speciality_form.twig.html et charger ce template via AJAX simplement dans ma div de la dernière colonne. Je précise que je sais utiliser AJAX et jQuery, mais je ne vois pas comment faire le lien avec le moteur de template twig.
RESOLU EN PARTIE => j'ai capturé un évènement sur un bouton pour charger le bout de code du template. Donc je reformule ICI => est-ce possible, en appelant simplement la route /speciality/{id}/edit, de ne charger qu'une partie de la page via AJAX ?
-----------------------------
NON RESOLU
Un second problème que je rencontre :
comment charger dynamiquement un template twig dans une fenêtre modale ? ce que j'ai vu c'est qu'il faut créer une div avec la classe "modal" (oui là c'est du css avec Bootstrap, ou plutôt j'utilise Bulma que je trouve moins usine à gaz)
y a-t-il une autre solution ou bien est-ce la seule qui soit correctement valable ?
Encore un problème :
j'aimerais beaucoup créer un bloc personnalité pour twig afin de pouvoir appeler dans mon code par exemple {% block mon_bloc_perso %}{% endblock %}
Et un dernier problème :
dans mon formulaire, j'ai une liste (par exemple pour ajouter une nouvelle ville, il faut la rattacher à un pays parmi ceux qui sont connus
comment faire charger un <select> via town_form.html.twig à partir de la liste des pays qui sont dans la base de données ? (j'ai essayé avec un champ de type EntityType, mais ça ne veut pas fonctionner)
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', TextType::class, array(
'required' => true,
'constraints' => array(
new Assert\NotBlank(),
new Assert\Length(array(
'min' => 1,'max' => 100,
))),
))
->add('postal_code', TextType::class, array(
'required' => true,
'constraints' => array(
new Assert\NotBlank(),
new Assert\Length(array(
'min' => 1,'max' => 10,
))),
))
->add('state_id', EntityType::class, array(
'class' => 'FreeProd\Domain\State',
'choice_label' => 'name',
));
}
J'ai cette erreur qui surgit :
Type error: Argument 1 passed to Symfony\Bridge\Doctrine\Form\Type\DoctrineType::__construct() must be an instance of Doctrine\Common\Persistence\ManagerRegistry, none given, called in /home/vincent/www/FreeProd/vendor/symfony/form/FormRegistry.php on line 85
Merci d'avance si vous avez quelques idées à me suggérer.
Je cherche toujours encore comment implémenter une liste déroulante dynamiquement à partir de la base de donnée en restant dans l'esprit de Silex. Disons que je sais faire dans un autre environnement sans aucun problème, mais pas dans un framework, encore moins dans Silex.
J'ai l'impression qu'il n'est pas possible d'utiliser EntityType avec Silex, je me trompe ?
Voilà où j'en suis avec un ChoiceType :
- j'ai créé dans StateDAO.php une fonction findAllIdName qui retourne un tableau avec l'ensemble des pays
- dans TownType.php je souhaite appeler cette fonction pour qu'elle me retourne le tableau en question, pour cela je voulais utiliser $app['dao.state']->findAllIdName(), mais $app n'est pas connu dans TownType.php.
Je cherche pourquoi et je ne trouve pas. J'ai pourtant mis use Silex\Application; en en-tête, mais ça ne marche pas.
Cela montre bien mon manque de maîtrise de cet outil, et j'espère vraiment que quelqu'un pourra me conseiller :
soit en restant avec un ChoiceType
soit en utilisant EntityType si c'est possible avec Silex
Voila bien une semaine maintenant que je me casse la tête sur ce cours (moultes problèmes avec composer etc)
et maintenant que j'en suis au premier exercice (après l'itération 7) j'ai un petit soucis de undefined index ...
voici la partie où l'erreur est localisée (AuthorDAO.php)
protected function buildDomainObject(array $row) {
$author = new Author();
$author->setAuthId($row['auth_id']);
$author->setAuthFirst($row['auth_first_name']);
$author->setAuthLast($row['auth_last_name']);
les champs de bdd sont identhiques, les variables sont bien déclarées dans la class Author, bref j'arrive pas à prendre du recul car je suis pressé dans le temps.
le soucis dans mon cas est que je suis actuellement en stage dans une entreprise sans équipe de dev (vive l'autonomie) et le projet que je dois améliorer est constitué de tout ce qui est dans ce cours... une chance de l'avoir trouvé, mais si je ne réussis pas ces tests et autres chapitres je ne pourrais rien produire durant mon stage.
J'ai essayé plusieurs méthodes pour m'en sortir mais apparemment je bloque toujours au même endroit (le moment où on doit cliquer sur le titre du livre).
J'ai déjà refais l'exercice 3 fois en une semaine...
Si seulement cette partie avait été vue en formation ...
Merci de m'indiquer une petite lumière qui m'aiderait à voir le bout du tunnel.
... me permet de créer le formulaire à partir du formulaire type TownType.
Et le code de TownType est le suivant :
public function buildForm(FormBuilderInterface $builder, array $options) {
$state_1 = new State(); // En attendant de récupérer les données dans la base
$state_1->setId(1);
$state_1->setName('France');
$state_2 = new State();
$state_2->setId(6);
$state_2->setName('Suisse');
$states = [];
$states[1] = $state_1;
$states[2] = $state_2;
//$app['dao.state']->findAllIdName();
//$stateDAO = new StateDAO();
//$states = $stateDAO->findAll();
$builder
->add('name', TextType::class, array(
'required' => true,
'constraints' => array(
new Assert\NotBlank(),
new Assert\Length(array(
'min' => 1,'max' => 100,
))),
))
->add('postal_code', TextType::class, array(
'required' => true,
'constraints' => array(
new Assert\NotBlank(),
new Assert\Length(array(
'min' => 1,'max' => 10,
))),
))
->add('state', ChoiceType::class, array(
'required' => true,
'choices' => $this->states,
'choice_value' => 'id',
'choice_label' => 'name',
));
}
Cette ligne :
'choices' => $this->states,
... ne fonctionne pas parce que $states n'est pas une propriété de TownType.
Donc j'ai ajouté cette propriété privée à la classe TownType, mais le problème est d'initialiser cette propriété avec la liste des états. Pour cela j'ai créé un constructeur __construct de TownType qui initialisera la propriété $states. Si toutefois c'est la bonne démarche, comment passer le tableau $states à TownType dans le code suivant :
Eh non je ne crois pas que cela ait été résolu. Il y a de nombreuses tentatives, des propositions, mais aucune ne fonctionne.
Et la solution que vous me proposez ne fonctionne pas parce que la fonction create n'accepte que 2 paramètres : le type de classe et les données. Le 3ème paramètre est refusé s'il ne contient pas dans le tableau passé en paramètre des options valides, j'avais déjà tenté cette possibilité.
Et j'ai également essayé (là ok, peut-être pas correctement avec la bonne méthode) de créer une nouvelle option qui contiendrait en fait mes données manquantes.
Donc je suis toujours encore à la recherche d'une solution.
oui autant pour moi, le return est bien présent mais était une ligne en dessous :
AuthorDAO
<?php
namespace MyBooks\DAO;
use MyBooks\Domain\Author;
class AuthorDAO extends DAO
{
/**
* @var \MyBooks\DAO\BookDAO
*/
private $bookDAO;
public function setBookDAO(BookDAO $bookDAO) {
$this->bookDAO = $bookDAO;
}
public function findAllByBook($bookId) {
$book = $this->bookDAO->find($bookId);
$sql = "select * from book where book_id=? order by book_id";
$result = $this->getDb()->fetchAll($sql, array($bookId));
// Convert query result to an array of domain objects
$authors = array();
foreach ($result as $row) {
$authId = $row['auth_id'];
$author = $this->buildDomainObject($row);
$author->setBook($book);
$authors[$authId] = $author;
}
return $authors;
}
/**
* Creates an author object based on a DB row.
*
* @param array $row The DB row containing author data.
* @return \MyBooks\Domain\Author
*/
protected function buildDomainObject(array $row) {
$author = new Author();
$author->setAuthId($row['auth_id']);
$author->setAuthFirst($row['auth_first_name']);
$author->setAuthLast($row['auth_last_name']);
return $author;
}
}
le fichier class Author lui ne contient que les attributs, setters et getters :
<?php
namespace MyBooks\Domain;
class Author{
private $authId;
private $authFirst;
private $authLast;
public function getAuthId() {
return $this->authId;
}
public function getAuthFirst() {
return $this->authFirst;
}
public function getAuthLast() {
return $this->authLast;
}
public function setAuthId($authId) {
$this->authId = $authId;
return $this;
}
public function setAuthFirst($authFirst) {
$this->authFirst = $authFirst;
return $this;
}
public function setAuthLast($authLast) {
$this->authLast = $authLast;
return $this;
}
}//end class Author
L'index.html.twig est correct à l'affichage, l'erreur se génère au passage à la seconde vue... donc je pense à un soucis dans une fonction.
peut-être que mon findAllByBook() devrait être findAllByAuthor() et du coup se trouver dans le BookDAO... mais si je fais ça,il ne restera que la fonction buildDomainObject() dans AuthorDAO.
Dans cette réflexion je me sens un peu perdu, sachant que je ne suis pas encore un pro non plus pour déclarer les routes...
PS: heureusement que j'ai deux mois de stage, mais déjà 15 jours de passés sur ça que j'ai pas encore commencé le cahier des charges ...oulala
Je précise au passage que finalement j'ai abandonné Silex pour Symfony et ça marche du tonnerre.
Je pensais qu'aborder Symfony allait être d'une certaine complexité et finalement en ayant suivi le cours de Silex, puis en suivant le cours de Symfony, petit à petit je découvre et j'ai réussi à faire avec Symfony en une matinée ce que je n'avais pas réussi à faire avec Silex en 3 jours.
Je ne dis pas que je ne me heurte pas à certains problèmes avec Symfony, c'est un outil que je ne connais pas et que je dois apprivoiser, mais ça m'a déjà permis de me débarrasser de plusieurs problèmes qui, après réflexion, n'ont peut-être pas vraiment de solution sans bidouillage avec Silex. Et comme je n'aime pas bidouiller ...
Bref ... merci beaucoup à ceux qui ont tenté de m'apporter certaines solutions.
RESOLU :C'est mon fichier htaccess qui bloquait l'accès
Bonjour,
Au cours de l'activité 1 (Créer une application de gestion de livres) :
- j'ai un fichier "test.css" dans mon dossier [mypath]/MyBooks/web/css :
* { border: 1px dotted red; }
html { font-color: blue; }
body { background-color: green; }
(Plusieurs propriétés pour avoir au moins un rendu, même en cas d'erreur de frappe)
- mon Vhost est configuré pour cibler [mypath]/MyBooks/web
Ma page s'affiche via le ServerName dans la barre d'adresse, donc mon VHost et mon hosts doivent être bien configurés
- mon [mypath]/MyBooks/views/index.html.twig possède un link
<link href="/css/test.css" rel="stylesheet" />
Ma page s'affiche, MAIS ma feuille de style n'est pas prise en compte car je n'ai aucun rendu !
- J'ai essayé de placer le fichier test.css à plusieurs endroits (en même temps) dans mon projet - J'ai essayé de changer le chemin d'accès (../web/css/, ./web/css/, web/css/, ../css/, ./css/, /css/, css/, suivi -bien sûr- par test.css) - J'ai essayé d'installer et d'utiliser les assets
EDIT : Puis j'ai vérifié mon htaccess qui contenait :
RewriteCond %(REQUEST_FILENAME) !-f
au lieu de :
RewriteCond %{REQUEST_FILENAME} !-f
(ce sont des accolades qu'il faut, et non des parenthèses )
J'ai suivi pas à pas le cours "Évoluez vers une architecture PHP professionnelle" et j'ai créé ma propre application lamemoiredutemps.fr sur le modele de MicroCMS.
Problème : Sur le site de mon hebergeur (LWS), lors de l'accès à la table t_user (login, ou affichage des users), une erreur est retournée FastCGI: server "/var/www/lamemoiredutemps.fr/cgi-bin/php5.6.external" stderr: PHP message: PHP Fatal error: Class 'LMDT\\Domain\\User' not found in /htdocs/LMDT/src/DAO/UserDAO.php on line 109, referer: http://www.lamemoiredutemps.fr/LMDT/web/index.php/login alors qu'il n'y a pas de problème sur mon pc en LOCALHOST !
1) Pour app.php j'ai conservé les mêmes paramètres du firewall
2) la structure de t_user est la même que MicroCMS
3) UserDAO.php : identique à MicroCMS
public function refreshUser(UserInterface $user) { $class = get_class($user); if (!$this->supportsClass($class)) { <= ligne 109 throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $class)); } return $this->loadUserByUsername($user->getUsername()); }
4) DOMAIN/user.phpidentique à MicroCMS et est bien sur le serveur
5) Je peux lire la table t_user du serveur par un programme en php (hors SILEX et hors firewall)
Je te conseille de mettre en commentaire le lien de personnalisation des messages d'erreurs, puis de nous renvoyer l'erreur explicitement. Avec ce que tu nous donne là je ne pense pas qu'on pourra d'aider.
Seul le message d'erreur pourra nous dire ce qui en ai !!!
Et mets ton code complet de la page où l'erreur se situe.
Merci beaucoup pour votre tentative de réponse car je me sentais complètement perdu. Question où puis-je trouver le lien de personnalisation des messages d''erreurs ? Car pour l'instant il retourne la page view/error.html.twig.
Le code complet de la page qui retourne des erreurs est le suivant src\Form\Type\CommentType.php :
<?php
namespace MicroCMS\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Symfony\Component\Validator\Constraints as Assert;
class CommentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
<?php
namespace MicroCMS\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Symfony\Component\Validator\Constraints as Assert;
class CommentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
Code qui retourne une errreur...
$builder->add('email', EmailType::class, array(
'label' => 'Votre eMail ',
'attr' => ['placeholder' => '(ne sera pas publié)'],
'required' => true,
'invalid_message' => 'Cette eMail n\'est pas valide.',
'constraints' => new Assert\Email(['checkMX' => true]),
))
Code qui retourne une errreur
->add('website', UrlType::class, array(
'label' => 'Your webSite',
'required' => false,
'constraints' => new Assert\Url(),
))
Ce code NE RETOURNE PAS D'ERREUR ...
->add('content', TextareaType::class, array(
'label' => 'Your comment',
'required' => true,
'constraints' => new Assert\NotBlank(),
));
}
public function getName() {
return 'comment';
}
}
Les tests donne les résultats suivants :
C:\wamp64\www\microCMSi14>vendor\bin\phpunit.bat
PHPUnit 4.8.36 by Sebastian Bergmann and contributors.
......F....
Time: 8.12 seconds, Memory: 22.00MB
There was 1 failure:
1) MicroCMS\Test\AppTest::testPageIsSuccessful with data set #6 ('/admin/comment/1/edit')
Failed asserting that false is true.
C:\wamp64\www\microCMSi14\tests\Tests\AppTest.php:23
FAILURES!
Tests: 11, Assertions: 11, Failures: 1.
Le fichier microCMSi14\tests\Tests\AppTest.php contient :
<?php
namespace MicroCMS\Test;
require_once __DIR__.'/../../vendor/autoload.php';
use Silex\WebTestCase;
class AppTest extends WebTestCase
{
/**
* Basic, application-wide functional test inspired by Symfony best practices.
* Simply checks that all application URLs load successfully.
* During test execution, this method is called for each URL returned by the provideUrls method.
*
* @dataProvider provideUrls
*/
public function testPageIsSuccessful($url)
{
$client = $this->createClient();
$client->request('GET', $url);
$this->assertTrue($client->getResponse()->isSuccessful()); Ligne contenant l'erreur...
}
/**
* {@inheritDoc}
*/
public function createApplication()
{
$app = new \Silex\Application();
require __DIR__.'/../../app/config/dev.php';
require __DIR__.'/../../app/app.php';
require __DIR__.'/../../app/routes.php';
// Generate raw exceptions instead of HTML pages if errors occur
unset($app['exception_handler']);
// Simulate sessions for testing
$app['session.test'] = true;
// Enable anonymous access to admin zone
$app['security.access_rules'] = array();
return $app;
}
/**
* Provides all valid application URLs.
*
* @return array The list of all valid application URLs.
*/
/**
* Provides all valid application URLs.
*
* @return array The list of all valid application URLs.
*/
public function provideUrls()
{
return array(
array('/'),
array('/article/1'),
array('/login'),
array('/admin'),
array('/admin/article/add'),
array('/admin/article/1/edit'),
array('/admin/comment/1/edit'),
array('/admin/user/add'),
array('/admin/user/1/edit'),
array('/api/articles'),
array('/api/article/1'),
);
}
/**
* Provides all valid application URLs.
*
* @return array The list of all valid application URLs.
*/
}
[2017-09-15 16:44:23] MicroCMS.CRITICAL: Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException: Neither the property "email" nor one of the methods "getEmail()", "email()", "isEmail()", "hasEmail()", "__get()" exist and have public access in class "MicroCMS\Domain\Comment". (uncaught exception) at C:\wamp64\www\microCMSi14\vendor\symfony\property-access\PropertyAccessor.php line 508 {"exception":"[object] (Symfony\\Component\\PropertyAccess\\Exception\\NoSuchPropertyException(code: 0): Neither the property \"email\" nor one of the methods \"getEmail()\", \"email()\", \"isEmail()\", \"hasEmail()\", \"__get()\" exist and have public access in class \"MicroCMS\\Domain\\Comment\". at C:\\wamp64\\www\\microCMSi14\\vendor\\symfony\\property-access\\PropertyAccessor.php:508)"} []
Autre code qui peut vous être utile src\Form\Type\Comment.php :
<?php
namespace MicroCMS\Domain;
class Comment
{
/**
* Comment id.
*
* @var integer
*/
private $id;
/**
* Comment author.
*
* @var \MicroCMS\Domain\User
*/
private $author;
/**
* Comment content.
*
* @var integer
*/
private $content;
/**
* Associated article.
*
* @var \MicroCMS\Domain\Article
*/
private $article;
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
return $this;
}
public function getAuthor() {
return $this->author;
}
public function setAuthor(User $author) {
$this->author = $author;
return $this;
}
public function getContent() {
return $this->content;
}
public function setContent($content) {
$this->content = $content;
return $this;
}
public function getArticle() {
return $this->article;
}
public function setArticle(Article $article) {
$this->article = $article;
return $this;
}
}
Voilà, j'espère que cela vous aidera à trouver la solution à mon problème. Encore merci pour aide.
Bonjour Chris 79, sauf erreur de ma part, tu essaies de faire rentrer dans un formulaire « commentaires » un e-mail et une URL alors que dans ta classe tu n'as pas de méthodes getEmail() et getUrl() ni les setters qui vont avec…
c'est un paramètre dans ton php.ini qui est à modifier :
; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 8M
Il est par défaut à 2M (d'où la limite que tu as rencontrée)
Si tu utilises WAMP en localhost, clique sur l'icône 'W' vert en bas à droite de ton écran, menu 'PHP', 'php.ini. Ca ouvre le fichier de config dans notepad, tu cherches le paramètre, le mets à jour et tu redémarres WAMP pour qu'il le prenne en compte, ça devrait être ok !
@chris79
Mets en commentaire la ligne return $app['twig'] de cette fonction
// Register error handler
$app->error(function(\Exception $e, Request $request, $code) use($app) {
switch ($code) {
case 403:
$message = 'Access denied.';
break;
case 404:
$message = 'The requested resource could not be found.';
break;
default:
$message = 'Something went wrong.';
}
//return $app['twig']->render('error.html.twig', ['message' => $message]);
});
Cours Architecture PHP professionnelle / Questions
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Vincent ERHART
Formateur / Développeur web
Vincent ERHART
Formateur / Développeur web
Vincent ERHART
Formateur / Développeur web
Vincent ERHART
Formateur / Développeur web
Vincent ERHART
Formateur / Développeur web
Vincent ERHART
Formateur / Développeur web
Vincent ERHART
Formateur / Développeur web
Vincent ERHART
Formateur / Développeur web