IPB

Bienvenue invité ( Connexion | Inscription )

 
Reply to this topicStart new topic
> php PDO insert ligne avec valeurs par défaut ?
Options
toluol
posté 8 Jul 2019, 13:23
Message #1


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 790
Inscrit : 14 Nov 2003
Lieu : Genève
Membre no 11 656



Bonjour,

J'ai un problème d'insertion dans une base de données mysql en PDO.

Une insertion basique se faisant ainsi :
Code
$sql = "INSERT INTO users (id, name, surname) VALUES (?,?,?)";
$pdo->prepare($sql)->execute([$id, $name, $surname]);

... en inscrivant tous les champs et leurs valeurs.

Comment insérer une ligne "vide" avec les valeurs par défaut de MySql ?
Ceci ne fonctionnant pas :
Code
$sql = "INSERT INTO $table () VALUES ()";
$pdo->prepare($sql)->execute();


Note : Je suis sous sous php 7.3
D'avance, je vous remercie pour vos lumières !
Go to the top of the page
 
+Quote Post
hellomorld
posté 8 Jul 2019, 16:20
Message #2


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 5 677
Inscrit : 31 Oct 2003
Membre no 11 118



Citation (toluol @ 8 Jul 2019, 13:23) *
Comment insérer une ligne "vide" avec les valeurs par défaut de MySql ?
Ceci ne fonctionnant pas :
Code
$sql = "INSERT INTO $table () VALUES ()";
$pdo->prepare($sql)->execute();


Pourquoi pas (non testé)
Code
$sql = "INSERT INTO $table (id) VALUES (?)";
$pdo->prepare($sql)->execute(NULL);



--------------------
Go to the top of the page
 
+Quote Post
Jaypee
posté 9 Jul 2019, 08:36
Message #3


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 382
Inscrit : 29 Aug 2002
Membre no 3 340



Bonjour,

Cette question a été posée sur StackOverflow, et apparemment le code doit être plus compliqué, et utiliser Coalesce() et Default(). Le code est facilement lisible :
https://stackoverflow.com/questions/2464535...-default-values

@+JP

Ce message a été modifié par Jaypee - 9 Jul 2019, 08:38.
Go to the top of the page
 
+Quote Post
toluol
posté 10 Jul 2019, 00:18
Message #4


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 790
Inscrit : 14 Nov 2003
Lieu : Genève
Membre no 11 656



@hellomorld : hélas, non... It doesn't work. J'espérais une solution du style et j'en ai essayé plein, mais on dirait qu'on ne peut pas faire aussi simple avec PDO+prepare

@jaypee : Je suis tombé sur cette page aussi de stackoverflow... Le souci est le même : c'est qu'il faut connaître les colonnes à l'avance et...

En fait, je n'ai pas précisé... il faut que j'explique que c'est pour une classe : J'essayais de faire mon propre ORM (pour apprendre) et que j'utiliserais aussi en Ajax. Et je voulais pouvoir insérer des lignes complètement vides avec les valeurs par défaut de la base, le tout sans connaître au préalable les champs. (Donc seulement avec le nom de la table)
pour l'utiliser par ex. ainsi : $object->insert();

Le mieux que j'ai trouvé, c'est de préalablement extraire toutes les valeurs par défaut des colonnes de la table avec une première requête comme : $query = $this->db->prepare("SHOW COLUMNS FROM `$table`"), puis une requête pour trouver le prochain id de la table, puis d'extraire des listes des champs et de chaque valeur par défaut avec une dernière requête ($sql = "INSERT INTO `$this->table` ($fields) VALUES ($values)"; $this->db->prepare($sql)->execute();)

..Mais c'est vraiment batard de faire 3 requêtes pour insérer une ligne vide ! laugh.gif laugh.gif
Go to the top of the page
 
+Quote Post
Jaypee
posté 11 Jul 2019, 08:34
Message #5


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 382
Inscrit : 29 Aug 2002
Membre no 3 340



D'une manière ou d'une autre, si on veut se protéger contre l'injection SQL, il faut pouvoir accepter ou rejeter un couple (nom de colonne, valeur), et donc connaître les noms de colonne valides.

https://phpdelusions.net/pdo/sql_injection_example
Dans les premières versions de MS SQL Server, on pouvait attaquer la db à travers le champ "Username" de la page de login, il ne faut jamais négliger la sécurité.

C'est un peu la responsabilité de l'ORM de faire le "sale boulot" pour faciliter le travail du développeur final, alors une ou trois requêtes, où est le problème ?
Ensuite dans ton approche, il faut penser aussi aux implications de l'intégrité provisoire de la db, puisque la rangée vide peut être lue avant d'être complétée avec des valeurs, sauf si l'ORM. gère sa propre colonne "ready", et fait un "AND" implicite dessus.

Il y a un exemple unique de ce genre de "découverte" de la structure de la db par le code client, il s'agit des « Type Providers » de F# de Microsoft, repris plus tard par Scala. C'est une technologie de niche, peu connue. L'intérêt est qu'on peut "exposer" juste quelques colonnes au client et construire un service dessus sans besoin que le client en sache plus sur le reste de la db. La même db peut être vue comme une source de "Personne" pour une application, ou source de "Produit" pour une autre.
https://docs.microsoft.com/en-us/dotnet/fsh...type-providers/

@+JP

Ce message a été modifié par Jaypee - 11 Jul 2019, 09:38.
Go to the top of the page
 
+Quote Post
scoch
posté 11 Jul 2019, 11:00
Message #6


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 4 476
Inscrit : 1 Jul 2010
Membre no 156 073



Citation (toluol @ 8 Jul 2019, 14:23) *
Comment insérer une ligne "vide" avec les valeurs par défaut de MySql ?
Ceci ne fonctionnant pas :
Code
$sql = "INSERT INTO $table () VALUES ()";
$pdo->prepare($sql)->execute();

Je viens de tester avec succès :
Code
$requete = $bdd->prepare('INSERT INTO machin() VALUES()');
$requete->execute();

$requete->closeCursor();

Les valeurs par défaut des champs sont bien appliquées aux champs de la nouvelle ligne.

Autre exemple pour insérer la valeur par défaut pour un seul champ :
Code
$requete = $bdd->prepare('INSERT INTO machin(prenom, nom, age) VALUES(:prenom, :nom, DEFAULT)');
$requete->execute(array(
    'prenom' => $prenom,
    'nom' => $nom
));

$requete->closeCursor();

Le champ "age" a bien la valeur par défaut.

Bien entendu, je ne me préoccupe pas de sécurité ici (voir le post de Jaypee).

Ce message a été modifié par scoch - 11 Jul 2019, 11:08.


--------------------
L'homme n'est que poussière... c'est dire l'importance du plumeau ! Alexandre Vialatte
Go to the top of the page
 
+Quote Post
toluol
posté 12 Jul 2019, 15:39
Message #7


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 790
Inscrit : 14 Nov 2003
Lieu : Genève
Membre no 11 656



Citation (scoch @ 11 Jul 2019, 11:00) *
Je viens de tester avec succès :


Je n'ai hélas pas le même résultat. Tu es en quelle version de php ?

Moi, c'est dans une classe, alors, ça donne ça :
Code
$requete = $this->db->prepare('INSERT INTO $this->table() VALUES()');
$requete->execute();
$requete->closeCursor();

Mais il n'y a pas de raison que ça change quelque chose...
Go to the top of the page
 
+Quote Post
scoch
posté 12 Jul 2019, 16:25
Message #8


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 4 476
Inscrit : 1 Jul 2010
Membre no 156 073



Citation (toluol @ 12 Jul 2019, 16:39) *
Je n'ai hélas pas le même résultat. Tu es en quelle version de php ?

PHP 7.3.n
Je ne me souviens pas de la version exacte mais me suis conformé avec ta configuration en utilisant PHP 7.3. J’ai testé cela sur un PC du taff avec une installation par défaut de wamp.


--------------------
L'homme n'est que poussière... c'est dire l'importance du plumeau ! Alexandre Vialatte
Go to the top of the page
 
+Quote Post
toluol
posté 12 Jul 2019, 20:34
Message #9


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 790
Inscrit : 14 Nov 2003
Lieu : Genève
Membre no 11 656



Bon... rolleyes.gif Effectivement, après avoir fait un tout petit script en dehors de ma classe, ça fonctionne effectivement...
Je vais devoir creuser la raison du problème dans ma classe. Merci ! tongue.gif
Go to the top of the page
 
+Quote Post
Jaypee
posté 13 Jul 2019, 09:34
Message #10


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 382
Inscrit : 29 Aug 2002
Membre no 3 340



Le pattern qui est implémenté ici est l'ActiveRecord (popularisé par Ruby On Rails) et il existe déjà plusieurs bibliothèques PHP qui apportent ce pattern aux objets d'une appli. Même si le but est de ne pas les utiliser, on peut quand même s'en inspirer.

Dans le cas présent, ça veut dire que la compétence d'accès à la db peut être héritée d'une classe comme celle-là.
Ou alors, si la simplicité est une priorité, il faudrait initialiser l'objet PDO au niveau global (hors de la classe) en tant que singleton (pas d'autre instance permise), puis l'injecter dans le constructeur de l'objet de l'appli.

On peut en effet se heurter sans le savoir à un problème de licence qui ne permet qu'un seul accès à la bd, et toujours sans le vouloir, créer deux accès distincts par deux objets différents. C'est le but du singleton, que de s'assurer que tous les accès soient centralisés par un seul connecteur.
Une autre piste : En mode développement on peut essayer une requête, qui échoue, le code s'arrête immédiatement sans restituer les ressources systèmes allouées pour le test (des connexions). Il est important de l'enrober dans un try except, et s'assurer que la connexion de db est bien refermée après l'erreur.

@+JP

Ce message a été modifié par Jaypee - 14 Jul 2019, 14:55.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 utilisateur(s) sur ce sujet (1 invité(s) et 0 utilisateur(s) anonyme(s))
0 membre(s) :

 



Nous sommes le : 21st July 2019 - 02:00