Salvar array de PHP no MySQL?

88

Qual é uma boa maneira de salvar um array de dados em um único campo mysql?

Além disso, depois de consultar esse array na tabela mysql, qual é uma boa maneira de colocá-lo de volta na forma de array?

É serializar e desserializar a resposta?

JasonDavis
fonte

Respostas:

87

Não é bom maneira de armazenar um array em um único campo.

Você precisa examinar seus dados relacionais e fazer as alterações apropriadas em seu esquema. Veja o exemplo abaixo para uma referência a esta abordagem.

Se você deve salvar a matriz em um único campo, o serialize()eunserialize() funções resolverão o problema. Mas você não pode realizar consultas no conteúdo real.

Como alternativa à função de serialização, existe também json_encode()e json_decode().

Considere a seguinte matriz

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

Para salvá-lo no banco de dados você precisa criar uma tabela como esta

$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)
    )');

Para trabalhar com os registros você pode realizar consultas como essas (e sim, este é um exemplo, cuidado!)

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();

A connect()função retorna um recurso de conexão mysql

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

Geralmente, sim, serializar e desserializar são o caminho a percorrer.

Porém, se seus dados forem simples, salvar como uma string delimitada por vírgulas provavelmente seria melhor para o espaço de armazenamento. Se você sabe que seu array será apenas uma lista de números, por exemplo, você deve usar implodir / explodir. É a diferença entre 1,2,3e a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}.

Caso contrário, serialize e desserialize o trabalho para todos os casos.

Matchu
fonte
22
Já que você está aqui, leitor, vou apenas reservar um tempo para anunciar que descobri, através de anos de experiência, que esse não é realmente o caminho a percorrer. A resposta aceita é uma abordagem muito mais forte.
Matchu
4
Se você está aqui, leitor, vou compartilhar com você que simplesmente depende de suas necessidades. Se você não precisa consultar por seus valores de matriz e precisa de algo que seja muito RÁPIDO, você pode armazenar com segurança seus dados como este em um único campo (que é o que a pergunta claramente afirma), coloque uma chave primária nele e pronto . Se você quer saber o que é o aplicativo: enviar dados para um arquivo que fica cronizado a cada 5 minutos. Outro cron cria os arrays, o que leva muito mais tempo. O que busca os dados calculados e os passa para uma API de terceiros. Não há melhor maneira de fazer isso.
Rid Iculous
1
@RidIculous Estou confuso, você está falando sobre seu próprio aplicativo pessoal ou o aplicativo que levou à pergunta?
Peter Lindqvist
1
Embora isso seja irrelevante para a premissa de minha declaração, o prefixo "Se você quer saber qual é o aplicativo" deve fornecer clareza.
Rid Iculous em
10

Basta usar a função serializar PHP:

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

No entanto, se você estiver usando matrizes simples como essa, também pode usar implodir e explodir. Use uma matriz em branco em vez de nova.

KramerC
fonte
9

Serializar / desserializar array para armazenamento em um banco de dados

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

Do Manual do PHP:

Procure em "Devolução" na página

Retorna uma string contendo uma representação de fluxo de bytes de valor que pode ser armazenada em qualquer lugar.

Observe que esta é uma string binária que pode incluir bytes nulos e precisa ser armazenada e tratada como tal. Por exemplo, a saída serialize () geralmente deve ser armazenada em um campo BLOB em um banco de dados, ao invés de um campo CHAR ou TEXT.

Nota: Se você quiser armazenar html em um blob, certifique-se de codificá-lo em base64 ou pode interromper a função de serialização.

Codificação de exemplo:

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

$YourSerializedData agora está pronto para ser armazenado no blob.

Depois de obter os dados do blob, você precisa usar base64_decode e desserializar a decodificação de exemplo:

$theHTML = unserialize(base64_decode($YourSerializedData));
Robalo
fonte
8

A melhor maneira que descobri para mim mesmo é salvar array como string de dados com caracteres separadores

$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 . "');";

Você pode então pesquisar dados, armazenados em sua matriz com uma consulta simples

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

use a função explode () para converter a string "array_data" em array

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

observe que isso não está funcionando com arrays multidimensionais e certifique-se de que seu "array_separator" é único e não existia em valores de array.

Seja cuidadoso !!! se você apenas pegar os dados do formulário e colocá-los no banco de dados, estará em uma armadilha, porque os dados do formulário não são seguros para SQL! você deve lidar com o valor do seu formulário com mysql_real_escape_string ou se você usar MySQLi mysqli :: real_escape_string ou se os valores forem inteiros ou boolean cast (int) (boolean) neles

$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']);
atormentar
fonte
No meu caso, acho que essa é a melhor opção para mim.
Imtiaz
6

Serializar e desserializar são bastante comuns para isso. Você também pode usar JSON via json_encode e json_decode para um formato menos específico do PHP.

ceejayoz
fonte
5

Como mencionado antes - se você não precisa pesquisar dados dentro do array, você pode usar serializar - mas isso é "somente php". Portanto, eu recomendaria usar json_decode / json_encode - não apenas para desempenho, mas também para legibilidade e portabilidade (outras linguagens como javascript podem lidar com dados json_encoded).

Sebastian Lasse
fonte
3

Uhh, não sei por que todo mundo sugere serializar o array.

Eu digo, a melhor maneira é realmente encaixá-lo em seu esquema de banco de dados. Não tenho ideia (e você não deu pistas) sobre o significado semântico real dos dados em sua matriz, mas geralmente há duas maneiras de armazenar sequências como essa

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

Dessa forma, você está armazenando seu array em uma única linha.

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
)

A desvantagem do primeiro método é, obviamente, que se você tiver muitos itens em seu array, trabalhar com aquela tabela não será a coisa mais elegante. Também é impraticável (possível, mas também deselegante - apenas tornar as colunas anuláveis) trabalhar com sequências de comprimento variável.

Para o segundo método, você pode ter sequências de qualquer comprimento, mas de apenas um tipo. Você pode, é claro, fazer aquele tipo varchar ou algo assim e serializar os itens de seu array. Não é a melhor coisa a fazer, mas certamente é melhor do que serializar todo o array, certo?

De qualquer forma, qualquer um desses métodos obtém uma vantagem clara de ser capaz de acessar um elemento arbitrário da sequência e você não precisa se preocupar com a serialização de matrizes e coisas feias como essa.

Quanto a recuperá-lo. Bem, pegue a linha / sequência de linhas apropriada com uma consulta e, bem, use um loop .. certo?

brilhante
fonte
Às vezes, um array é realmente apropriado. Se você for acessá-lo apenas como um atributo do primeiro objeto, faz sentido.
Matchu
1
Eu tenho que discordar nos termos mais severos - parece bastante inapropriado para mim armazenar blobs de dados aleatórios, não estruturados (php "arrays" na verdade não são arrays, certo?), Blobs de dados não digitados em um banco de dados relacional . O que você vai usar como separador de qualquer maneira, se o seu array pode conter alguma string? Isso é apenas pedir problemas de muitas maneiras diferentes. Em 99,9% dos casos, existe outra forma mais natural. Vou dar um palpite aqui e sugerir que o caso do questionador não cai nos 0,1% restantes.
shylent
2
Na verdade, às vezes é muito apropriado armazenar um array em um campo de um banco de dados. Os exemplos seriam metadados como uma tabela de 'variáveis' global na qual os plug-ins e módulos do sistema podem armazenar suas configurações variadas. uma tabela que armazena dados arbitrários de 'sessão' pode ser melhor implementada usando um campo que contém uma matriz associativa de chaves / valores. serializar e desserializar (que é a resposta correta) cuidar dos separadores. verifique alguns dos vários projetos de código aberto populares e bem-sucedidos, como WordPress ou Drupal - e você verá que às vezes os arrays são armazenados no banco de dados como este
Scott Evernden
@Scott Evernden: Acho que você está certo afinal. php não é minha linguagem "principal", então eu estava julgando a solução do ponto de vista do design do banco de dados. Se o que você descreve é ​​realmente a maneira comum de fazer essas coisas (em php), então que seja. Não me faz gostar :)
shylent
5
NUNCA é apropriado armazenar uma matriz em um campo em um banco de dados. É uma violação não da quarta forma normal, terceira forma normal ou mesmo segunda forma normal: é uma VIOLAÇÃO DA PRIMEIRA FORMA NORMAL. Se você não consegue aderir nem mesmo à primeira forma normal, há algo muito errado com sua inscrição. Isso vale para Drupal e Wordpress; se eles fazem isso, certamente não é porque essa faceta de seus aplicativos é bem projetada. Eu tive esse argumento no meu último trabalho e, como o XCart estava fazendo esse absurdo, tornou algo que deveria ser possível, extremamente difícil.
Dexygen
2

Você pode salvar seu array como um json.
há documentação para o tipo de dados json: https://dev.mysql.com/doc/refman/5.7/en/json.html
Acho que esta é a melhor solução e ajudará você a manter seu código mais legível, evitando funções malucas .
Espero que isso seja útil para você.

Roberto Murguia
fonte
0

Sim, serializar / desserializar é o que eu mais vi em muitos projetos de código aberto.

Eduardo
fonte
0

Eu sugeriria o uso de implodir / explodir com um caractere que você sabe que não estará contido em nenhum dos itens individuais da matriz. Em seguida, armazene-o no SQL como uma string.

user1478500
fonte
3
Esta pergunta foi feita há 3 anos e tem uma resposta aceita. Você pode achar mais útil responder a perguntas mais recentes ou perguntas sem respostas.
MDrollette
0

verifique a função implodir, uma vez que os valores estão em uma matriz, você deseja colocar os valores da matriz em uma consulta mysql que insere os valores em uma tabela.

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

Se os valores na matriz forem valores de texto, você precisará adicionar aspas

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

mysql_query($query);

Além disso, se você não quiser valores duplicados, mude "INto" para "IGNORE" e apenas valores únicos serão inseridos na tabela.

j0k
fonte
Se você tiver uma chave primária, não obterá duplicatas com INSERT INTO de qualquer maneira. Se você não tem uma chave primária ou um índice, IGNORE não faz diferença.
Peter Lindqvist
0

você pode inserir o objeto serializado (array) no mysql, example serialize($object)e você pode desserizar o objeto exampleunserialize($object)

Vildan Bina
fonte
-5

Em vez de salvá-lo no banco de dados, salve-o em um arquivo e chame-o mais tarde.

O que muitos aplicativos php fazem (como o sugarcrm) é apenas usar var_export para ecoar todos os dados do array para um arquivo. Isso é o que eu uso para salvar meus dados de configuração:

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

Acho que essa é a melhor maneira de salvar seus dados!

AntonioCS
fonte
É outra maneira, não necessariamente melhor.
Peter Lindqvist
De fato. Só acho que acessar o arquivo é muito mais fácil do que consultar o banco de dados para recuperar os dados do array e inicializar o array. Desta forma, você apenas inclui o arquivo e está feito.
AntonioCS