Tôi thực sự tìm thấy cách tốt nhất để có một tài liệu tham khảo phản ánh một cách dễ dàng có sẵn là đệ quy tokenise các thư mục chính xác và sau đó xây dựng một tài liệu xml như là một kết quả. Caching tài liệu xml cho tốc độ và sử dụng xpath để lấy dữ liệu.
Plugin xây dựng xml phản chiếu và lưu trữ nó sau này. Tôi đã lấy mã này ra khỏi triển khai ban đầu của nó, do đó, nó nhiều hơn để cung cấp cho bạn một cảm giác chứ không phải là sao chép và dán.
Tất nhiên, cơ sở dữ liệu cũng hoạt động tốt ở đây. Nhưng nếu bạn đang cố giới hạn truy vấn của mình trên mỗi trang, một tài liệu xml được lưu trong bộ nhớ cache hoạt động khá tốt.
class My_Reflection_Plugin extends My_Controller_Plugin_Abstract
{
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
$cache = $this -> getCacheManager() -> getCache('general');
if (!$xml = $cache->load("Reflection"))
{
$paths = array(
PATH_APPLICATION . "/Core",
PATH_SITE . "/Project"
);
foreach ($paths as $path)
{
$this -> inspectDir($path);
}
$cache -> save($this->getReflectionXML(), "Reflection");
}
else
{
$this -> getReflectionXML($xml);
}
}
private function inspectDir($path)
{
$rdi = new RecursiveDirectoryIterator($path);
$rii = new RecursiveIteratorIterator($rdi);
$filtered = new My_Reflection_Filter($rii);
iterator_apply($filtered, array($this, 'process'), array($filtered));
}
private function process($it = false)
{
$this -> getReflectionXML() -> addItem($it -> current());
return true;
}
}
Tokenisation xảy ra bên trong bộ lọc:
class My_Reflection_Filter extends FilterIterator
{
public function accept()
{
$file = $this->getInnerIterator()->current();
// If we somehow have something other than an SplFileInfo object, just
// return false
if (!$file instanceof SplFileInfo) {
return false;
}
// If we have a directory, it's not a file, so return false
if (!$file->isFile()) {
return false;
}
// If not a PHP file, skip
if ($file->getBasename('.php') == $file->getBasename()) {
return false;
}
// Resource forks are no good either.
if (substr($file->getBaseName(), 0, 2) == '._')
{
return false;
}
$contents = file_get_contents($file->getRealPath());
$tokens = token_get_all($contents);
$file->className = NULL;
$file->classExtends = NULL;
$file->classImplements = array();
$last = null;
while (count($tokens) > 0)
{
$token = array_shift($tokens);
if (!is_array($token))
{
continue;
}
list($id, $content, $line) = $token;
switch ($id)
{
case T_ABSTRACT:
case T_CLASS:
case T_INTERFACE:
$last = 'object';
break;
case T_EXTENDS:
$last = "extends";
break;
case T_IMPLEMENTS:
$last = "implements";
break;
case T_STRING:
switch ($last)
{
case "object":
$file -> className = $content;
break;
case "extends":
$file -> classExtends = $content;
break;
case "implements":
$file -> classImplements[] = $content;
break;
}
break;
case T_WHITESPACE:
// Do nothing, whitespace should be ignored but it shouldnt reset $last.
break;
default:
// If its not directly following a keyword specified by $last, reset last to nothing.
$last = null;
break;
}
}
return true;
}
}
Một khi bạn đã xml phản ánh của bạn cư với bất kỳ thông tin bạn cần ra khỏi lớp, plugin acl bạn có thể đến sau khi nó và truy vấn thông tin đó với xpath .
Tại sao cần phải có TẤT CẢ các hành động và tên bộ điều khiển? Chỉ cần nghĩ đến một danh sách trắng: chỉ các hành động hoặc bộ điều khiển nằm trong một nhóm đặc biệt mới được phép truy cập. Tất cả những người khác thì không. – powtac
Bạn nên đặt câu trả lời này là đúng. Một danh sách trắng thực sự là cách tốt nhất để tiến hành với bộ điều khiển/hành động dựa trên ACL –
Chỉ có một vấn đề nếu bạn sử dụng Zend_Navigation và tài nguyên không tồn tại trong ACL của bạn có ném một ngoại lệ. Và tôi muốn sử dụng cơ sở dữ liệu để từ chối và cho phép truy cập. Vì vậy, tôi phải xây dựng cơ sở dữ liệu đầu tiên. Và nếu tôi phải làm bằng tay thì đó là một nỗi đau để làm điều đó. –