我试图帮助一个伙伴和她坚持阵列,所以这次没有数据库使用:( countys页面显示所有的计数,当点击一个时,它被带到显示该县的步行的不同页面.
$countys = array();
$countys[101] = array(
"name" => "Armagh",
"img" => "css/images/map.jpg",
"largeimg" => "css/images/banmap.jpg"
);
$countys[102] = array(
"name" => "Antrim",
"img" => "css/images/map.jpg",
"largeimg" => "css/images/banmap.jpg"
);
$walks = array();
$walks[1] = array(
"name" => "Portadown Walk",
"county" => "Armagh",
"img" => "css/images/map.jpg",
"location" => "Portadown",
"largeimg" => "css/images/banmap.jpg"
);
$walks[2] = array(
"name" => "Antrim Walk",
"county" => "Antrim",
"img" => "css/images/map.jpg",
"location" => "Causeway"
);
Run Code Online (Sandbox Code Playgroud)
多维数组是否正常工作或者可能是for/while循环来检查$ walk ['county']是否等于该县?
Dav*_*dom 15
表格
如果要将数组用作数据库,显然建模表的最佳方法是使用2D数组:
$counties = array();
$countiesKey = 0;
// add a row
$counties[++$countiesKey] = array(
"name" => "Armagh",
"img" => "css/images/map.jpg",
"largeimg" => "css/images/banmap.jpg"
);
// and another...
$counties[++$countiesKey] = array(
"name" => "Antrim",
"img" => "css/images/map.jpg",
"largeimg" => "css/images/banmap.jpg"
);
Run Code Online (Sandbox Code Playgroud)
这大致相当于下面的表定义(为了简单起见,我们将使用MySQL进行比较并假设所有字符串字段都是VARCHAR(1024)):
CREATE TABLE counties (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(1024),
img VARCHAR(1024),
largeimg VARCHAR(1024)
);
Run Code Online (Sandbox Code Playgroud)
独特的索引
所以我们使用数组索引作为主键.但是为了根据主键以外的任何"列"搜索数据库,它需要一个O(n)操作:我们需要迭代整个表并检查每一行的相关值.这是索引发挥作用的地方.如果我们想在我们的县名上添加索引怎么办?好吧,我们可以使用一个单独的关联数组:
$countiesNameIndex = array();
$countiesNameIndex['Armagh'] = 1;
$countiesNameIndex['Antrim'] = 2;
Run Code Online (Sandbox Code Playgroud)
关联数组实现为哈希表,因此粗略地按键访问元素O(1).这使我们在按县名搜索时可以大大加快对行的访问速度:
$search = 'Antrim';
$result = array();
if (isset($countiesNameIndex[$search])) {
$result[$countiesNameIndex[$search]] = $counties[$countiesNameIndex[$search]];
}
return $result;
Run Code Online (Sandbox Code Playgroud)
添加和删除行时,可以动态维护此索引:
// Insert a row
$row = array( /* row data */ );
if (isset($countiesNameIndex[$row['name']])) {
// insert fails, duplicate value in column with unique index
}
$counties[++$countiesKey] = $row;
$countiesNameIndex[$row['name']] = $countiesKey;
// Delete a row
$idOfRowToDelete = 2;
if (isset($counties[$idOfRowToDelete])) {
unset(
$countiesNameIndex[$counties[$idOfRowToDelete]['name']],
$counties[$idOfRowToDelete]
);
}
Run Code Online (Sandbox Code Playgroud)
随着数据集变大,这种索引方法将大大加快数据访问速度.
非聚集索引
让我们快速看看我们如何实现一个非唯一索引,它不包含有关它引用的行的顺序的信息 - 实现非常相似.这将比我们的唯一索引慢一点,但明显快于迭代整个数据集:
$countiesImgIndex = array();
// Insert a row
// INSERT INTO counties ( ... ) VALUES ( ... )
$row = array( /* row data */ );
if (!isset($countiesImgIndex[$row['img']])) {
$countiesImgIndex[$row['img']] = array();
}
$counties[++$countiesKey] = $row;
$countiesImgIndex[$row['img']][] = $countiesKey;
// Search using the index
// SELECT * FROM counties WHERE img = 'css/images/map.jpg'
$search = 'css/images/map.jpg';
$result = array();
if (isset($countiesImgIndex[$search])) {
foreach ($countiesImgIndex[$search] as $rowId) {
$result[$rowId] = $counties[$rowId];
}
}
return $result;
// Delete a row
// DELETE FROM counties WHERE id = 2
$idOfRowToDelete = 2;
if (isset($counties[$idOfRowToDelete])) {
$key = array_search($idOfRowToDelete, $countiesImgIndex[$counties[$idOfRowToDelete]['img']]);
if ($key !== false) {
array_splice($countiesImgIndex[$counties[$idOfRowToDelete]['img']], $key, 1);
}
unset($counties[$idOfRowToDelete]);
}
Run Code Online (Sandbox Code Playgroud)
使用多个索引
我们甚至可以使用这些索引来执行更复杂的操作 - 考虑如何实现SQL查询
SELECT *
FROM counties
WHERE name = 'Antrim'
AND img = 'css/images/map.jpg'
Run Code Online (Sandbox Code Playgroud)
首先我们来看一下最具体的索引(唯一索引):
$result = array();
$nameSearch = 'Antrim';
$imgSearch = 'css/images/map.jpg';
if (!isset($countiesNameIndex[$nameSearch])) {
return $result;
}
Run Code Online (Sandbox Code Playgroud)
接下来,我们检查该行是否与其他条件匹配:
if ($counties[$countiesNameIndex[$nameSearch]]['img'] === $imgSearch) {
$result[$countiesNameIndex[$nameSearch]]
= $counties[$countiesNameIndex[$nameSearch]];
}
return $result;
Run Code Online (Sandbox Code Playgroud)
您可以看到,在这种情况下,我们只需要使用1个索引,因为要查询的其中一个列具有唯一索引.这意味着我们可以直接进入唯一重要的行并检查它是否符合条件.现在让我们假设我们在另一个非唯一列上有一个索引 - largeImg.此操作稍微复杂一点,但我们可以使用以下快捷方式array_intersect():
$result = array();
$imgSearch = 'css/images/map.jpg';
$largeImgSearch = 'css/images/banmap.jpg';
if (!isset($countiesImgIndex[$imgSearch], $countiesLargeImgIndex[$largeImgSearch])) {
return $result;
}
return array_intersect(
$counties[$countiesImgIndex[$imgSearch]],
$counties[$countiesLargeImgIndex[$largeImgSearch]]
);
Run Code Online (Sandbox Code Playgroud)
外键和连接表
但是当我们开始想要加入另一张桌子时呢?好吧,这就像我们在SQL中做的那样.让我们假设我们有以下SQL表定义:
CREATE TABLE walks (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(1024),
location VARCHAR(1024),
county INT
);
Run Code Online (Sandbox Code Playgroud)
显然我们从另一个数组开始,并插入一些行:
$walks = array();
$walksKey = 0;
$walks[++$walksKey] = array(
"name" => "Portadown Walk",
"county" => 1,
"location" => "Portadown",
);
$walks[++$walksKey] = array(
"name" => "Antrim Walk",
"county" => 2,
"location" => "Causeway"
);
Run Code Online (Sandbox Code Playgroud)
非常明显的是,该county列引用了$counties表中行的ID .顺便提一下,我们使用计数器来跟踪ID而不是使用$arr[] =赋值语法的原因有两个:首先,它确保当从表中删除行时ID始终是常量,其次它使得它更容易(计算成本更低) )提取最后插入的行的ID - 这将有助于创建具有外键的复杂表结构,如此处所示.
现在让我们看一下将这些数据联系起来.想象一下,我们运行了这个SQL查询:
SELECT c.*, w.*
FROM walks w
JOIN counties c ON w.county = c.id
LIMIT 0, 10
Run Code Online (Sandbox Code Playgroud)
这可以实现如下:
$result = array();
$i = 0;
foreach ($walks as $walkId => $walksRow) {
$result[$walkId] = array_merge($counties[$walksRow['county']], $walksRow);
if (++$i == 10) {
break;
}
}
return $result;
Run Code Online (Sandbox Code Playgroud)
现在您可能已经发现了这个问题:两个表都包含一个名为name的列.上面的代码将返回的值name从walks表中的每一行.您可以轻松调整此行为,但具体如何实现这将取决于您想要的结果.
订购结果集
PHP提供了一个功能,可以在这里完成大部分工作 - array_multisort().最重要的一点是,在提取结果行之后应该应用顺序,以最小化所需操作的数量.
SELECT c.*, w.*
FROM walks w
JOIN counties c ON w.county = c.id
ORDER BY w.location ASC
Run Code Online (Sandbox Code Playgroud)
// Collect the result set in $result as above
$location = array();
foreach ($result as $row) {
$location[] = $row['name'];
}
array_multisort($location, SORT_ASC, $result);
return $result;
Run Code Online (Sandbox Code Playgroud)
希望以上示例应该开始演示一些可用于使用PHP数组实现RDBMS上的某些功能的逻辑.可以进行某些相当简单的优化,即使在数据集增长时也能保持这些操作相对便宜.