Enregistrer le tableau PHP sur MySQL?

88

Quel est le bon moyen de sauvegarder un tableau de données dans un seul champ mysql?

Aussi, une fois que j'ai interrogé ce tableau dans la table mysql, quel est un bon moyen de le remettre sous forme de tableau?

La sérialisation et la désérialisation sont-elles la réponse?

JasonDavis
la source

Réponses:

87

Il n'y a pas de bonne façon de stocker un tableau dans un seul champ.

Vous devez examiner vos données relationnelles et apporter les modifications appropriées à votre schéma. Voir l'exemple ci-dessous pour une référence à cette approche.

Si vous devez enregistrer le tableau dans un seul champ, les fonctions serialize()et unserialize()feront l'affaire. Mais vous ne pouvez pas effectuer de requêtes sur le contenu réel.

Comme alternative à la fonction de sérialisation, il existe également json_encode()et json_decode().

Considérez le tableau suivant

$a = array(
    1 => array(
        'a' => 1,
        'b' => 2,
        'c' => 3
    ),
    2 => array(
        'a' => 1,
        'b' => 2,
        'c' => 3
    ),
);

Pour l'enregistrer dans la base de données, vous devez créer une table comme celle-ci

$c = mysql_connect($server, $username, $password);
mysql_select_db('test');
$r = mysql_query(
    'DROP TABLE IF EXISTS test');
$r = mysql_query(
    'CREATE TABLE test (
      id INTEGER UNSIGNED NOT NULL,
      a INTEGER UNSIGNED NOT NULL,
      b INTEGER UNSIGNED NOT NULL,
      c INTEGER UNSIGNED NOT NULL,
      PRIMARY KEY (id)
    )');

Pour travailler avec les enregistrements, vous pouvez effectuer des requêtes comme celles-ci (et oui, c'est un exemple, méfiez-vous!)

function getTest() {
    $ret = array();
    $c = connect();
    $query = 'SELECT * FROM test';
    $r = mysql_query($query,$c);
    while ($o = mysql_fetch_array($r,MYSQL_ASSOC)) {
        $ret[array_shift($o)] = $o;
    }
    mysql_close($c);
    return $ret;
}
function putTest($t) {
    $c = connect();
    foreach ($t as $k => $v) {
        $query = "INSERT INTO test (id,".
                implode(',',array_keys($v)).
                ") VALUES ($k,".
                implode(',',$v).
            ")";
        $r = mysql_query($query,$c);
    }
    mysql_close($c);
}

putTest($a);
$b = getTest();

La connect()fonction renvoie une ressource de connexion mysql

function connect() {
    $c = mysql_connect($server, $username, $password);
    mysql_select_db('test');
    return $c;
}
Peter Lindqvist
la source
26

Généralement, oui, sérialiser et désérialiser sont la voie à suivre.

Si vos données sont simples, cependant, enregistrer sous forme de chaîne délimitée par des virgules serait probablement préférable pour l'espace de stockage. Si vous savez que votre tableau ne sera qu'une liste de nombres, par exemple, vous devez utiliser implode / éclatement. C'est la différence entre 1,2,3et a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}.

Sinon, sérialisez et désérialisez le travail pour tous les cas.

Matchu
la source
22
Puisque vous êtes ici, lecteur, je vais juste prendre le temps de vous annoncer que j'ai découvert depuis, grâce à des années d'expérience, que ce n'est vraiment pas la voie à suivre. La réponse acceptée est une approche beaucoup plus forte.
Matchu
4
Si vous êtes ici, lecteur, je vais partager avec vous que cela dépend simplement de vos besoins. Si vous n'avez pas besoin d'interroger les valeurs de votre tableau et que vous avez besoin de quelque chose de très RAPIDE, vous pouvez stocker vos données en toute sécurité comme celui-ci dans un seul champ (ce que la question énonce clairement), appliquez une clé primaire dessus et c'est parti . Si vous vous demandez ce qu'est l'application: pousser les données dans un que qui est créé toutes les 5 minutes. Un autre cron crée les tableaux, ce qui prend beaucoup plus de temps. Le que récupère les données calculées et les transmet à une API tierce. Il n'y a pas de meilleure façon de le faire.
Rid Iculous le
1
@RidIculous Je suis confus, parlez-vous de votre propre application personnelle ou de l'application qui a conduit à la question posée?
Peter Lindqvist
1
Bien que cela ne soit pas pertinent par rapport à la prémisse de ma déclaration, le préfixe «Si vous vous demandez quelle est la demande» devrait être clair.
Rid Iculous
10

Utilisez simplement la fonction de sérialisation de PHP:

<?php
$myArray = array('1', '2');
$seralizedArray = serialize($myArray);
?>

Cependant, si vous utilisez des tableaux simples comme celui-ci, vous pouvez aussi bien utiliser imploser et exploser.Utilisez un tableau vide au lieu de nouveau.

KramerC
la source
9

Sérialiser / désérialiser la baie pour le stockage dans une base de données

Visitez http://php.net/manual/en/function.serialize.php

À partir du manuel PHP:

Regardez sous "Retour" sur la page

Renvoie une chaîne contenant une représentation par flux d'octets de la valeur qui peut être stockée n'importe où.

Notez qu'il s'agit d'une chaîne binaire qui peut inclure des octets nuls, et doit être stockée et gérée comme telle. Par exemple, la sortie serialize () doit généralement être stockée dans un champ BLOB d'une base de données, plutôt que dans un champ CHAR ou TEXT.

Remarque: si vous souhaitez stocker du code HTML dans un objet blob, assurez-vous de l'encoder en base64 ou cela pourrait interrompre la fonction de sérialisation.

Exemple d'encodage:

$YourSerializedData = base64_encode(serialize($theHTML));

$YourSerializedData est maintenant prêt à être stocké dans le blob.

Après avoir récupéré les données de blob, vous devez base64_decode puis désérialiser Exemple de décodage:

$theHTML = unserialize(base64_decode($YourSerializedData));
Loup de mer
la source
8

Le meilleur moyen que je me suis trouvé est de sauvegarder le tableau sous forme de chaîne de données avec des caractères de séparation

$array = array("value1", "value2", "value3", "...", "valuen");
$array_data = implode("array_separator", $array);

$query = "INSERT INTO my_tbl_name (id, array_data) VALUES(NULL,'" . $array_data . "');";

Vous pouvez ensuite rechercher des données, stockées dans votre tableau avec une simple requête

$query = "SELECT * FROM my_tbl_name WHERE array_data LIKE '%value3%'";

utiliser la fonction explode () pour convertir la chaîne "array_data" en tableau

$array = explode("array_separator", $array_data);

notez que cela ne fonctionne pas avec des tableaux multidimensionnels et assurez-vous que votre "array_separator" est unique et n'existait pas dans les valeurs de tableau.

Faites attention !!! si vous prenez juste des données de formulaire et les mettez dans la base de données, vous serez dans le piège, car les données du formulaire ne sont pas sécurisées pour SQL! vous devez gérer la valeur de votre formulaire avec mysql_real_escape_string ou si vous utilisez MySQLi mysqli :: real_escape_string ou si la valeur est un entier ou un booléen cast (int) (booléen) sur eux

$number = (int)$_POST['number'];
$checked = (boolean) $_POST['checked'];

$name = mysql_real_escape_string($db_pt, $_POST['name']);
$email = mysqli_obj->real_escape_string($_POST['email']);
Harry
la source
Dans mon cas, je suppose que c'est la meilleure option pour moi.
Imtiaz
6

La sérialisation et la désérialisation sont assez courantes pour cela. Vous pouvez également utiliser JSON via json_encode et json_decode pour un format moins spécifique à PHP.

ceejayoz
la source
5

Comme mentionné précédemment - Si vous n'avez pas besoin de rechercher des données dans le tableau, vous pouvez utiliser serialize - mais c'est "php seulement". Je recommanderais donc d'utiliser json_decode / json_encode - non seulement pour les performances, mais également pour la lisibilité et la portabilité (d'autres langages tels que javascript peuvent gérer les données json_encoded).

Sebastian Lasse
la source
3

Euh, je ne sais pas pourquoi tout le monde suggère de sérialiser le tableau.

Je dis que le meilleur moyen est de l'intégrer dans votre schéma de base de données. Je n'ai aucune idée (et vous n'avez donné aucun indice) sur la signification sémantique réelle des données de votre tableau, mais il y a généralement deux façons de stocker des séquences comme ça

create table mydata (
  id int not null auto_increment primary key,
  field1 int not null,
  field2 int not null,
  ...
  fieldN int not null
)

De cette façon, vous stockez votre tableau sur une seule ligne.

create table mydata (
    id int not null auto_increment primary key,
    ...
)

create table myotherdata (
    id int not null auto_increment primary key,
    mydata_id int not null,
    sequence int not null,
    data int not null
)

L'inconvénient de la première méthode est, évidemment, que si vous avez de nombreux éléments dans votre tableau, travailler avec cette table ne sera pas la chose la plus élégante. Il est également peu pratique (possible, mais tout à fait inélégant - il suffit de rendre les colonnes nullables) de travailler avec des séquences de longueur variable.

Pour la deuxième méthode, vous pouvez avoir des séquences de n'importe quelle longueur, mais d'un seul type. Vous pouvez, bien sûr, faire en sorte que ce type soit varchar ou quelque chose et sérialiser les éléments de votre tableau. Ce n'est pas la meilleure chose à faire, mais certainement mieux, que de sérialiser l'ensemble de la baie, non?

Dans tous les cas, n'importe laquelle de ces méthodes a l'avantage de pouvoir accéder à un élément arbitraire de la séquence et vous n'avez pas à vous soucier de la sérialisation des tableaux et des choses laides comme ça.

Quant à le récupérer. Eh bien, obtenez la ligne / séquence de lignes appropriée avec une requête et, bien, utilisez une boucle ... non?

timide
la source
Parfois, un tableau est vraiment approprié. Si vous n'allez y accéder qu'en tant qu'attribut du premier objet, cela a du sens.
Matchu
1
Je ne suis pas d'accord dans les termes les plus sévères - il me semble plutôt inapproprié de stocker des données aléatoires, non structurées (les "tableaux" php ne sont pas du tout des tableaux, n'est-ce pas?), Des gouttes de données non typées dans une base de données relationnelle . Qu'allez-vous utiliser pour un séparateur de toute façon, si votre tableau peut contenir des chaînes? C'est juste demander des ennuis de différentes manières. Dans 99,9% des cas, il existe une autre voie, plus naturelle. Je vais faire une supposition sauvage ici et suggérer que le cas du questionneur ne tombe pas dans les 0,1% restants.
shylent
2
En fait, il est parfois très approprié de stocker un tableau dans un champ d'une base de données. Un exemple serait des métadonnées comme une table globale de «variables» dans laquelle les plugins et modules d'un système peuvent stocker leurs divers paramètres. une table qui stocke des données de «session» arbitraires pourrait être mieux implémentée en utilisant un champ qui contient un tableau associatif de clés / valeurs. sérialiser et désérialiser (ce qui est la bonne réponse) s'occupe des séparateurs. Vérifiez certains des nombreux projets open source populaires et réussis, comme WordPress ou Drupal - et vous verrez que les tableaux sont parfois stockés dans la base de données comme ceci
Scott Evernden
@Scott Evernden: Je suppose que vous avez raison après tout. php n'est pas mon langage "principal", donc je jugeais la solution du point de vue de la conception de base de données. Si ce que vous décrivez est vraiment la manière courante de faire de telles choses (en php), qu'il en soit ainsi. Mais ça ne me fait pas aimer :)
shylent
5
Il n'est JAMAIS approprié de stocker un tableau dans un champ d'une base de données. Ce n'est pas une violation de la quatrième forme normale, de la troisième forme normale ou même de la deuxième forme normale: c'est une VIOLATION DE LA PREMIÈRE FORME NORMALE. Si vous ne pouvez même pas adhérer à la première forme normale, il y a quelque chose qui ne va pas avec votre application. Cela vaut pour Drupal et Wordpress; s'ils le font, ce n'est certainement pas parce que cette facette de leurs applications est bien conçue. J'ai eu cet argument lors de mon dernier travail, et parce que XCart faisait ce non-sens, cela a rendu quelque chose qui aurait dû être possible, extrêmement difficile à la place.
Dexygen
2

Vous pouvez enregistrer votre tableau en tant que json.
il existe une documentation pour le type de données json: https://dev.mysql.com/doc/refman/5.7/en/json.html
Je pense que c'est la meilleure solution, et vous aidera à maintenir votre code plus lisible en évitant les fonctions folles .
J'espère que cela vous sera utile.

Roberto Murguia
la source
0

Oui, sérialiser / désérialiser est ce que j'ai le plus vu dans de nombreux projets open source.

Eduardo
la source
0

Je suggérerais d'utiliser imploser / exploser avec un caractère dont vous savez qu'il ne sera contenu dans aucun des éléments individuels du tableau. Puis stockez-le dans SQL sous forme de chaîne.

user1478500
la source
3
Cette question a été posée il y a 3 ans et a une réponse acceptée. Vous trouverez peut-être plus utile de répondre à de nouvelles questions ou à des questions sans réponse.
MDrollette
0

consultez la fonction implode, puisque les valeurs sont dans un tableau, vous voulez mettre les valeurs du tableau dans une requête mysql qui insère les valeurs dans une table.

$query = "INSERT INto hardware (specifications) VALUES (".implode(",",$specifications).")";

Si les valeurs du tableau sont des valeurs de texte, vous devrez ajouter des guillemets

$query = "INSERT INto hardware (specifications) VALUES ("'.implode("','",$specifications)."')";

mysql_query($query);

De plus, si vous ne voulez pas de valeurs en double, changez "INto" sur "IGNORE" et seules les valeurs uniques seront insérées dans la table.

j0k
la source
Si vous avez une clé primaire, vous n'obtenez de toute façon aucun doublon avec INSERT INTO. Si vous n'avez pas de clé primaire ou d'index, IGNORE ne fait aucune différence.
Peter Lindqvist
0

vous pouvez insérer un objet sérialisé (tableau) dans mysql, exemple serialize($object)et vous pouvez déseriser l'exemple d'objetunserialize($object)

Vildan Bina
la source
-5

Au lieu de l'enregistrer dans la base de données, enregistrez-le dans un fichier et appelez-le plus tard.

Ce que font de nombreuses applications php (comme sugarcrm), c'est simplement utiliser var_export pour renvoyer toutes les données du tableau dans un fichier. C'est ce que j'utilise pour sauvegarder mes données de configuration:

private function saveConfig() {
    file_put_contents($this->_data['pathtocompileddata'],'<?php' . PHP_EOL . '$acs_confdata = ' . var_export($this->_data,true) . ';');        
}

Je pense que c'est une meilleure façon de sauvegarder vos données!

AntonioCS
la source
C'est une autre façon, pas nécessairement meilleure.
Peter Lindqvist
En effet. Je pense simplement que l'accès au fichier est beaucoup plus facile que d'interroger la base de données pour récupérer les données du tableau, puis initialiser le tableau. De cette façon, vous incluez simplement le fichier et c'est fait.
AntonioCS