Storing data: to key – or not to key
Introduction
You’ve got so many ways to compose data! So, how do you choose which one is right for you?
We don’t know. But here are the options that we do know about. What do YOU think?
Recap and....
Is an array actually an associative array in disguise?
This will set the stage.
Single property, list of properties, collection of key:value pairs, collection of anything and everything you can think up… (as long as you follow the rules)
“and that’s not really going to help you…” (note key => value)
Associative array basics
<?php
// array
$array = [1, true, "three"];
// associative array (called 'Objects' in JavaScript)
$item = [
"key1" => "Value1",
"key2" => "Value2",
];
// array of associative arrays
$list = [
[
"key1" => "Value1",
"key2" => "Value2",
],
[
"key1" => "Value3",
"key2" => "Value4",
],
];
echo $array[2];
echo $item[0]['key2'];
echo $list[1]['key1']; // you know what these will print, right?
You’re solid on how this works ^ right?
“Anonymous” arrays
<?php
$team = [
[
"id" => "a123",
"name" => "Ivy",
"slug" => "ivy",
"alive" => true,
],
[
"id" => "b456",
"name" => "Derek",
"slug" => "derek",
"alive" => true,
],
];
?>
<ul>
<?php foreach ($team as $person) { ?>
<li>
<h2><?=$person['name']?></h2>
</li>
<?php } ?>
</ul>
We’ve never heard this really given a name, but see how the associative arrays for Ivy and Derek don’t have their own key. They are just kinda in there. You can access them via their index $team[0]
but you can’t access them by a named key. What if we changed the order? Then the indexes would be different. Then $team[0]
would no longer point to Ivy’s info.
So, we’ve taken to referring to these lists as a list of anonymous arrays. The arrays are just floating in there – without a name. (like anonymous functions – which you’ll see soon enough – if you haven’t yet)
This array style (the collection of data in a list) – is super standard. But you’ll almost always use JSON going forward.
“Named” arrays
<?php
$team = [
"ivy" => [
"id" => "a123",
"name" => "Ivy",
"slug" => "ivy",
"alive" => true,
],
"derek" => [
"id" => "b456",
"name" => "Derek",
"slug" => "derek",
"alive" => true,
],
];
?>
<ul>
<?php foreach ($team as $person) { ?>
<li>
<h2><?=$person['name']?></h2>
</li>
<?php } ?>
</ul>
Again, we don’t know if there’s an official name (or need for a name) for these. But they seem less anonymous. So, we’ll call them named arrays for this talk.
You could use the id
for the key but we’re going to use the slug
in this case to hopefully make it more clear.
Accessing the key as well as the value
<?php
$collection = [
"key1" => "Value1",
"key2" => "Value2",
];
foreach ($collection as $value) {
echo "<li>$value</li>";
}
// Value1
// Value2
foreach ($collection as $key => $value) {
echo "<li>$key : $value</li>";
}
// key1 : Value1
// key2 : Value2
foreach ($collection as $key => $value) {
echo "<li>$key</li>";
}
// key1
// key2
Sometimes you need to access the key – and not just the value.
So, instead of just having access to the value, you can write the foreach loop a little differently and access both. And the syntax is pretty nice because it looks just like the key:value pairs in the array with the arrow.
Adding things to arrays
<?php
// if you aren't using a utility function like this to look at your code...
// then why not?
function display($code) {
echo "<pre>";
echo "<code>";
print_r($code);
echo "</code>";
echo "</pre>";
}
$item = "Item value";
// assigning 1 item to an empty array
$arrayName[] = $item;
display($arrayName);
// adding 1 item to the end of an existing array
array_push($arrayName, $item);
display($arrayName);
// adding many item to the end of an existing array
array_push($arrayName, $item, $item, $item);
display($arrayName);
// placing an item at a specific index in an array
$arrayName[2] = "Two";
$arrayName[13] = "Thirteen";
display($arrayName);
// what happens to [5] and [10] etc? ?
echo $arrayName[5]; // ?
display($arrayName);
// adding an item to the start of the array
array_unshift($arrayName, "start");
display($arrayName);
// WAT
There are a whole bunch of built-in array methods. Take a look at this big list and write down the 5 or 6 you think you’ll end up using often (then try them out of course).
(We don’t find ourselves using array_unshift()
very often.)
Accessing things in an anonymous array
<?php
$team = [
[
"id" => "a123",
"name" => "Ivy Reynolds",
"slug" => "ivy",
],
[
"id" => "f376",
"name" => "Karen Rinard",
"slug" => "karen",
],
[
"id" => "b456",
"name" => "Derek Wood",
"slug" => "sheriffderek",
],
[
"id" => "c789",
"name" => "Brian Lowery",
"slug" => "brian",
],
[
"id" => "d321",
"name" => "Derek McCall",
"slug" => "derek-mccall",
],
];
Some data to search. (pretend there are 100+ records in this database)
<?php
include('team-data.php');
// find by id (procedural)
$found = null;
$idToMatch = "c789";
foreach ($team as $person) {
if ($person['id'] === $idToMatch) {
$found = $person;
break;
}
}
if ($found) {
echo "We found $found[name] in the system under id: $idToMatch";
} else {
echo "No user found for id: $idToMatch.";
}
This does the trick! But it’s not very reusable or easy to read.
<?php
include('team-data.php');
// find by id (functional)
function findRecordById($array, $id) {
foreach ($array as $item) {
if ($item['id'] === $id) {
return $item;
break;
}
}
}
$response = findRecordById($team, 'd321'); // this is easy to read
if ($response) {
echo "We found $response[name] in the system";
} else {
echo "No user found";
}
<?php
include('team-data.php');
// find by key and match it's value (functional)
function findRecordByKey($array, $key, $value) {
foreach ($array as $item) {
if ($item[$key] === $value) {
return $item;
break;
}
}
}
$response = findRecordByKey($team, 'slug', 'ivy');
if ($response) {
echo "We found $response[name] in the system";
} else {
echo "No user found";
}
This one is more universal, but is it too universal?
Maybe in some situations. It’s not a problem to have a findById()
and findBySlug()
and any number of specific functions. It’s up to you. Try them all out.
Accessing things in a named array
<?php
$team = [
"a123" => [
"name" => "Ivy Reynolds",
"slug" => "ivy",
],
"f376" => [
"name" => "Karen Rinard",
"slug" => "karen",
],
"b456" => [
"name" => "Derek Wood",
"slug" => "sheriffderek",
],
"c789" => [
"name" => "Brian Lowery",
"slug" => "brian",
],
"d321" => [
"name" => "Derek McCall",
"slug" => "derek-mccall",
],
];
Take a look at how this one is different. Each item in the array has an explicit key.
<?php
include('team-data.php');
$response = $team["b456"]; // if you know the id you want, you can just access it
if ($response) {
echo "We found $response[name] in the system";
} else {
echo "No user found";
}
This one is a lot less code, right? Is it too good to be true?
What if you wanted to find it by slug instead? (well – a universally unique identifier (uuid) is going to likely be a better choice)
Then you can just get the slug like this: $team["b456"]['slug']
Removing items from an array
<?php
include('team-data');
$idToRemove = "f376"; // karen's id
$filtered = [];
foreach ($team as $person) {
if ($person['id'] !== $idToRemove) {
array_push($filtered, $person);
}
}
$team = $filtered;
display($team); // should now have an array with Karen removed
This is one way to do it…
You could also use unset()
once you find it, or array_splice()
if you know the index that it’s at already.
<?php
include('team-data');
unset($team['a123']); // (ivy's id)
display($team); // should now have an array with Ivy removed
Well, this is just one line.
Updating a record
You can try this one out.
What if you needed to update someone’s name? You only have their id
. How would you do that with an anonymous array? And then how would you do that with a named array?
(We’ll come back to it when we have time.)
Side note... how long do these operations take?
<?php
$timesToRun = 1000000; // 1 million
$startTime = microtime(true); // current time in milliseconds
$array = array();
for($i = 0; $i < $timesToRun; $i++) {
$array[] = $i;
}
echo 'a: ' . microtime(true) - $startTime;
// current - start time == time it took...
echo '<hr>';
$startTime = microtime(true);
$array = array();
for($i = 0; $i < $timesToRun; $i++) {
array_push($array, $i);
}
echo 'p: ' . microtime(true) - $startTime;
During your time in DFTW – always just make it work. These types of micro optimizations are only important in extreme situations – and you’ll only think about them after it’s working anyway. But just for fun…
Which one is faster when run 1 million times?
Derek goes over over all of those situations
Video in the works!
Probably not even necessary with all of these code examples!
Exercises
-
Create a dead simple CRUD app
How will you store your data?