PHP 命名空间删除/映射和重写标识符
我正在尝试自动从 PHP 类集合中删除命名空间,以使它们与 PHP 5.2 兼容。 (共享托管提供商不喜欢流氓 PHP 5.3 安装。不知道为什么。而且有问题的代码不使用任何 5.3 功能添加,只是使用该语法。自动转换似乎比手动执行或重新实现代码库更容易。
)我基本上在 tokenizer 列表上运行 *.php 脚本。标识符查找+合并已经完成。但我现在有点困惑如何完成实际的重写。
function rewrite($name, $namespace, $use) {
global $identifiers2; // list of known/existing classes
/*
bounty on missing code here
*/
return strtr($name, "\\", "_"); // goal: backslash to underscore
}
该函数将在每个找到的标识符(无论是类、函数还是常量)上调用。它将接收一些上下文信息,将本地标识符转换为绝对/全局 $name:
$name =
rewrite(
"classfuncconst", # <-- foreach ($names as $name)
"current\name\space",
array(
'namespc' => 'use\this\namespc',
'alias' => 'from\name\too',
...
)
);
在这个阶段,我已经准备了一个 $identifiers2
列表。它包含所有已知类、函数和常量名称的列表(为简单起见,此处合并)。
$identifiers2 = array( // Alternative suggestions welcome.
"name\space\Class" => "Class", // - list structure usable for task?
"other\ns\func1" => "func1", // - local name aliases helpful?
"blip\CONST" => "CONST", // - (ignore case-insensitivity)
rewrite()
函数接收到的 $name
参数可以是本地、不合格、 \absolute 或 name\spaced 标识符(但只是标识符,没有表达式)。 $identifiers2
列表对于解析不合格标识符至关重要,它可以引用当前命名空间中的事物,或者如果在那里找不到的话,则可以引用全局事物。
除了命名空间解析和优先级规则之外,还必须考虑各种使用命名空间
别名,并增加一些复杂性。
那么,您将如何/以何种顺序尝试在这里转换类/函数名称的变体?
精神懒惰赏金。
为了使这个问题变得不那么明显,plzsendtehcodez 问题:解释性指令列表或伪代码答案也符合条件。如果另一种方法更适合该任务,请详细说明。 (但是不行,升级 PHP 或更改托管服务器不是一个选项。)
我想我已经弄清楚了,但问题仍然有待答案/实施建议。 (否则赏金显然会流向nikic。)
I'm attempting to automate the removal of namespaces from a PHP class collection to make them PHP 5.2 compatible. (Shared hosting providers do not fancy rogue PHP 5.3 installations. No idea why. Also the code in question doesn't use any 5.3 feature additions, just that syntax. Autoconversion seems easier than doing it by hand or reimplementing the codebase.)
For rewriting the *.php scripts I'm basically running over a tokenizer list. The identifier searching+merging is already complete. But I'm a bit confused now how to accomplish the actual rewriting.
function rewrite($name, $namespace, $use) {
global $identifiers2; // list of known/existing classes
/*
bounty on missing code here
*/
return strtr($name, "\\", "_"); // goal: backslash to underscore
}
That function is going to be invoked on each found identifier (whether class, function or const). It will receive some context information to transform a local identifier into an absolute/global $name:
$name =
rewrite(
"classfuncconst", # <-- foreach ($names as $name)
"current\name\space",
array(
'namespc' => 'use\this\namespc',
'alias' => 'from\name\too',
...
)
);
At this stage I've already prepared an $identifiers2
list. It contains a list of all known classes, functions and constant names (merged for simplicity here).
$identifiers2 = array( // Alternative suggestions welcome.
"name\space\Class" => "Class", // - list structure usable for task?
"other\ns\func1" => "func1", // - local name aliases helpful?
"blip\CONST" => "CONST", // - (ignore case-insensitivity)
The $name
parameter as received by the rewrite()
function can be a local, unqualified, \absolute or name\spaced identifier (but just identifers, no expressions). The $identifiers2
list is crucial to resolve unqualified identifiers, which can refer to things in the current namespace, or if not found there, global stuff.
And the various use namespace
aliases have to be taken into account and add some complication besides the namespace resolving and precedence rules.
So, how / in which order would you attempt to convert the variations of class/function names here?
Mental Laziness Bounty.
To make this a less blatant plzsendtehcodez question: an explainative instruction list or pseudo-code answer would be eligible too. And if another approach would be more suitable for the task, please elaborate on that rather. (But no, upgrading PHP or changing the hoster is not an option.)
I think I've figured it out meanwhile, but the question is still open for answers / implementation proposals. (Otherwise the bounty will obviously go to nikic.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在有关命名空间迁移的现有问题中到伪命名空间代码我已经引入了一个转换工具,这是我作为一个更大项目的一部分编写的。从那时起我就不再维护这个项目了,但据我记得命名空间替换确实有效。 (我可能会在某个时候使用适当的解析器重新实现这个项目。事实证明,使用普通令牌这是一项相当乏味的任务。)
您会发现我的命名空间实现 -> namespace.php。我的实现基于 命名空间解析规则,它将可能对你也有帮助。
为了让这个答案不那么明显,这里是代码执行的基本步骤:
self
和parent
类,也不解析true
、false< /code> 和
null
常量。使用
列表):class
,请检查该标识符是否为别名,如果是,则将其替换为别名类。class
,则在当前命名空间前面添加所有 NS 分隔符并用下划线替换并结束此算法。assumeGlobal
标志,我也不会执行此操作。相反,我总是插入动态调度代码。)附加说明:不要忘记也可以写
namespace\some\ns
。我在NS function
(它还负责查找命名空间声明)。
In an existing question on migration of namespaces to pseudo namespaced code I already introduced a conversion tool I have written as part of a larger project. I haven't maintained this project anymore since that point, but as far as I remember the namespace replacements did work. (I may reimplement this project using a proper parser at some point. Working with plain tokens has proven to be quite a tedious task.)
You will find my implementation of namespace -> pseudo-namespace resolution in the namespace.php. I based the implementation on the namespace resolution rules, which will probably be of help for you, too.
To make this a less blatant readmycodez answer, here the basic steps the code does:
self
andparent
classes, nor thetrue
,false
andnull
constants.use
list):class
, check whether the identifier is an alias and if it is, replace it with the aliased class.class
prepend the current namespace, replace all NS separators with underscores and end this algorithm.assumeGlobal
flag is set. Instead I always insert the dynamic dispatch code.)Additional note: Don't forget that one can also write
namespace\some\ns
. I resolve these constructs in theNS
function (which is also responsible for finding namespace declarations).