Link to home
Start Free TrialLog in
Avatar of Richard Lloyd
Richard Lloyd

asked on

What is the best way to store an array in a database?

Please can someone advise the best way to store an array in a database?

I normally pass arrays via a session cookie, but there are times that I need to store and retrieve an array in a database. I store a serialised version, as below:

<?php
$params=array($foo, $bar);
$_SESSION['params']=serialize($params);
?>

Open in new window


When I retrieve the session cookie and apply the $params (usually to a parameterised sql query, the array works.

However when I store it in a database, it works for a time, then after I update the database record, either updating or leaving the array alone, the array gets returns with added slashes,

The working unserialized array looks like this and works:
string(181) "array ( 0 => 'WROES', 1 => 'john', 2 => 'john%', 3 => 'baker', 4 => 'baker%', 5 => '', 6 => '%', 7 => '', 8 => '', 9 => '', 10 => '', 11 => '', 12 => '', )"

Open in new window


After any database manipulation, it looks like this and fails:
string(181) "array ( 0 => \'WROES\', 1 => \'john\', 2 => \'john%\', 3 => \'baker\', 4 => \'baker%\', 5 => NULL, 6 => \'%\', 7 => NULL, 8 => NULL, 9 => NULL, 10 => NULL, 11 => NULL, 12 => NULL, )"

Open in new window


The code I am using to update the database (SQLserver and PHP with sqlsrv_query) that seems to cause the problem is:

if(($_POST['postback']=='update-profile')){

$id=($_POST['id']);
$paramsprofile=$_POST['paramsprofile'];
$profilename=($_POST['profilename']);

$sql="update tblprofiles set profilename=?, sql=?, params=? where id=?";
$params=array($profilename, $sqlprofile, $paramsprofile, $id);
$result=sqlsrv_query($conn, $sql, $params);
}

$id=test($_GET['id']);
$sql="select profilename, profileid, sql, params from tblprofiles where id=?";
$params=array($id);
$result=sqlsrv_query($conn, $sql, $params);
$row=sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC);

echo "<h1>Edit Profile</h1>";
echo "<form action'#' method='post' id='profile-add'>";
echo "<table cellpadding='5px' cellspacing='5px' class='tableform' >";
echo "<tr><td>SQL</td><td><textarea name='sqlprofile' id='sqlprofile' style='width:100%'>".htmlspecialchars($row['sql'],ENT_QUOTES)."</textarea></td></tr>";
echo "<tr><td style='width:150px'>Params</td><td><input type='text' name='paramsprofile' id='paramsprofile' autocomplete='off' value='".$row['params'] ."' /></td></tr>";
echo "<tr><td style='width:150px'>Name</td><td><input type='text' name='profilename' id='profilename' value='".htmlspecialchars($row['profilename'],ENT_QUOTES)."'/>";
echo "</td></tr><tr><td>";
echo "<input type='hidden' name='id' value='$id'/>";
echo "<input type='hidden' name='postback' value='update-profile'/>";
echo "<input type='submit' id='submit' value='Update' />";
echo "</td></tr></table>";
echo "</form>";

Open in new window


I have tried encoding the serialised array with base64, using "magic_quotes", "htmlspecialchars" etc and nothing seems to work.

Can anyone advise how to correct or a better way to store the array for long term / cross session availability?
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

It depends on what you want to do but if you are going to serialize then I would recommend using JSON instead.

json_encode() / json_decode()
Avatar of Richard Lloyd
Richard Lloyd

ASKER

Thanks. I'll give it a go.
No luck.

I store the array in json in a session to pass it to another page, eg:

$params=array($a, $b, $c);
$_SESSION['params'] = json_encode($params);

Open in new window


I then store the encoded array in a database:
$params = $_SESSION['params'];

$sql="insert into tblprofiles  params) values (?)";
$params=array($params);
$result=sqlsrv_query($conn, $sql, $params);

Open in new window


The array is stored correctly in json format,

["smart","%smart%","test"]

Open in new window


when I retrieve it I and decode it for the array, I get this, which works.:

string(59) "array ( 0 => 'smart', 1 => '%smart%', 2 => 'test', )"

Open in new window


When I then "edit" the database record, but make no changes,

if(($_POST['postback']=='update-profile')){

$id=($_POST['id']);
$paramsprofile=$_POST['paramsprofile'];
$profilename=($_POST['profilename']);

$sql="update tblprofiles set profilename=?, sql=?, params=? where id=?";
$params=array($profilename, $sqlprofile, $paramsprofile, $id);
$result=sqlsrv_query($conn, $sql, $params);
}

$id=test($_GET['id']);
$sql="select params from tblprofiles where id=?";
$params=array($id);
$result=sqlsrv_query($conn, $sql, $params);
$row=sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC);

echo "<h1>Edit Profile</h1>";
echo "<form action'#' method='post' id='profile-add'>";
echo "<input type='text' name='paramsprofile' id='paramsprofile' autocomplete='off' value='".$row['params'] ."' />";
echo "<input type='hidden' name='id' value='$id'/>";
echo "<input type='hidden' name='postback' value='update-profile'/>";
echo "<input type='submit' id='submit' value='Update' />";
echo "</form>";

Open in new window


I then get an array decoded as:

string(67) "'array ( 0 => \'smart\', 1 => \'%smart%\', 2 => \'test\', )'"

Open in new window


This then fails as it has the slashes before each apostrophe.

Any other ideas?
I am not clear on this bit
When I then "edit" the database record, but make no changes,
How does that relate to the code you posted
It shows the method I use to update the database record that holds the "params" array if I need to make any changes to it.

The array stays fine when I retrieve and decode it:

string(59) "array ( 0 => 'smart', 1 => '%smart%', 2 => 'test', )"

Open in new window


Until I use this form. Once I "update" the record, the array in the database still looks good, as below:

["smart","%smart%","WROES"]

Open in new window


but when I retrieve it from the database and json_decode it, I am faced with an array that looks like

string(67) "'array ( 0 => \'smart\', 1 => \'%smart%\', 2 => \'test\', )'"

Open in new window


which does not work against my previously store sql query because something is adding the slashes
Not sure where and how you're encoding and decoding, but this look off to me:

---
The array stays fine when I retrieve and decode it:

string(59) "array ( 0 => 'smart', 1 => '%smart%', 2 => 'test', )"
---
That tells me that the data is a 59 character string, when in fact it should be a 3 element array. If you're storing that string in your DB, then when you do this:

echo "<input type='text' name='paramsprofile' id='paramsprofile' autocomplete='off' value='".$row['params'] ."' />";

You are probably just outputting that string into your INPUT field, and when you then submit your form, it will slashify the content.
So let me understand.

You put the array in the db. It looks fine and you can retrieve it and display it
You update the database with the form - still looks fine i.e. identical to the above
You retrieve it and now it has ' in ?

Slashes are added to database fields to escape ' that could be used in an injection attack. This is fairly common practice.

What does not make sense is that you say after an update the array looks identical to its previous state - but is decoded differently - that part does not make sense.
I'll build a model and put it online to show you. Might take me a bit of time though.
Ref your previous comment - exactly the point! it does not make sense!
Sounds like you might be manually manipulating your serialized data. For example:

string(181) "array ( 0 => 'WROES', 1 => 'john', 2 => 'john%', 3 => 'baker', 4 => 'baker%', 5 => '', 6 => '%', 7 => '', 8 => '', 9 => '', 10 => '', 11 => '', 12 => '', )"

Open in new window


That's not valid. That says it's an 181 character string, but it's only 155 characters. So unless you're manually redacting/editing data just for posting them on here, then that is a problem.

The extra slashes makes it sound like you're double-escaping somewhere. Since it happens on updates rather than creation, the logical place to look would be to see if you're escaping data when it comes out of the database, so that when you put it onto the form, you end up with extra slashes.
ASKER CERTIFIED SOLUTION
Avatar of Mohan Nirkhede
Mohan Nirkhede
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks Mohan, Good idea.

I'm not working on the project at the moment but will use it as a workaround when I get back to the job.
Thanks Mohan, Good idea.

I'm not working on the project at the moment but will use it as a workaround when I get back to the job.
Comma separation is not a good idea in my experience. If your data contains commas you have a problem - now you have to start checking for quotes to ignore commas.

The standard practice is to use serialize() or preferably json_encode() - allows for structuring of the data - no issue with data contents as the encode / decode will escape key characters and no more work than an explode.
I agree with Julian - comma-separated is usually not the best way unless you're dealing 100% with raw numbers. Once string data enters the picture, you'll need to start checking for quotes and escaped quotes, and since that's the problem you currently have with serialized data, you'll be back to where you started.

You really need to solve the underlying issue you have with escaped quotes, since that will impact any other fields that have quotes. We didn't hear back from you after the last round of comments, so it's a little odd that you accepted a comment about CSV as the answer.