If I understood your requirements correctly you could do something like this (one call to DB ONLY and NOT FULL TREE!!)
Full script can be found here : http://pastie.org/1250062
Hope it helps... :)
Example stored procedure call
call page_parents(5);
call page_parents(7);
Example PHP script
<?php
function hasValidParents($conn, $urls, $pageID){
$parents = array();
$valid = true;
//needs additional validation
$sproc = sprintf("call page_parents(%d)", $pageID);
$result = $conn->query($sproc);
while($row = $result->fetch_assoc()) $parents[] = $row["page_id"];
$result->close();
foreach($urls as $url)
if($url && !in_array($url,$parents)){ $valid=false; break; }
return $valid;
}
$urls = explode("/", "1/3/5"); // trim leading /
$conn = new mysqli("localhost", "foo_dbo", "pass", "foo_db", 3306);
echo hasValidParents($conn, $urls, $urls[count($urls)-1]) ? "true" : "false";
$conn->close();
?>
SQL
-- TABLES
drop table if exists pages;
create table pages
(
page_id smallint unsigned not null auto_increment primary key,
title varchar(255) not null,
parent_page_id smallint unsigned null,
key (parent_page_id)
)
engine = innodb;
-- TEST DATA
insert into pages (title, parent_page_id) values
('Page 1',null),
('Page 2',null),
('Page 1-2',1),
('Page 1-2-1',3),
('Page 1-2-2',3),
('Page 2-1',2),
('Page 2-2',2);
-- STORED PROCEDURES
drop procedure if exists page_parents;
delimiter #
create procedure page_parents
(
in p_page_id smallint unsigned
)
begin
declare v_done tinyint unsigned default 0;
declare v_depth smallint unsigned default 0;
create temporary table hier(
parent_page_id smallint unsigned,
page_id smallint unsigned,
depth smallint unsigned default 0
)engine = memory;
insert into hier select parent_page_id, page_id, v_depth from pages where page_id = p_page_id;
/* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */
create temporary table tmp engine=memory select * from hier;
while not v_done do
if exists( select 1 from pages pg inner join hier on pg.page_id = hier.parent_page_id and hier.depth = v_depth) then
insert into hier
select pg.parent_page_id, pg.page_id, v_depth + 1 from pages pg
inner join tmp on pg.page_id = tmp.parent_page_id and tmp.depth = v_depth;
set v_depth = v_depth + 1;
truncate table tmp;
insert into tmp select * from hier where depth = v_depth;
else
set v_done = 1;
end if;
end while;
select
pg.page_id,
pg.title as page_title,
b.page_id as parent_page_id,
b.title as parent_page_title,
hier.depth
from
hier
inner join pages pg on hier.page_id = pg.page_id
left outer join pages b on hier.parent_page_id = b.page_id
order by
hier.depth, hier.page_id;
drop temporary table if exists hier;
drop temporary table if exists tmp;
end #
delimiter ;
-- TESTING (call this stored procedure from php)
call page_parents(5);
call page_parents(7);