我需要扩展一个项目。所有类都在单独的文件中,我需要扩展一些类而不重写其他文件中的现有代码。我的想法是使用命名空间,但我失败了。这是一个例子:
我已将原来的 A.php 类文件重命名为 A_Original.php :
class A
{
public function hello()
{
echo "hello world from Class A\n";
}
}
然后创建了一个新的 A.php :
namespace AOriginal {
include 'A_Original.php';
}
namespace {
class A
{
public function hello()
{
echo "hello world from Class A Extended\n";
}
}
}
这会失败,因为在原始A_Original.php文件的including
上,类被转储到全局范围(因此忽略命名空间命令)。
我无法修改A_Original.php文件中的现有代码,但重命名是可以的。
其他项目文件(我无法修改)使用require "A.php"
。
如何做到这一点?
答案 0 :(得分:3)
您可以在不修改现有行为的情况下扩展类:
class A {
public function foo(){
}
}
class MySubClassOfA extends A {
public function bar(){
}
}
您可以将自己的方法添加到MySubClassOfA,即bar()。您可以在MySubClassOfA上调用foo方法,它的行为是相同的,除非您在MySubClassOfA中定义了一个名为foo的方法。
答案 1 :(得分:1)
我猜你别无选择,只能在所有文件的顶部添加单行“namespace xxx;
”代码。以下PHP CLI脚本可能很有用。
<?php
function convert($namespace, $srcdir, $dstdir)
{
try
{
$files = glob("$srcdir/{*,.*}", GLOB_BRACE);
if ( ! file_exists($dstdir) && ! mkdir($dstdir) )
{
throw new Exception("Cannot create directory {$dstdir}");
}
if ( ! is_dir($dstdir) )
{
throw new Exception("{$dstdir} is not a directory");
}
foreach ( $files as $f )
{
extract(pathinfo($f)); // then we got $dirname, $basename, $filename, $extension
if ( $basename == '.' || $basename == '..' )
{
continue;
}
if ( is_dir($f) )
{
$d = $dstdir. substr($f, strlen($srcdir));
convert($namespace, $f, $d);
continue;
}
print "processing {$f} ... ";
if ( ($s = file_get_contents($f)) === FALSE )
{
throw new Exception("Error reading $f");
}
if ( preg_match("/^\s*namespace\s+\S+;/m", $s) )
{
print "already has namespace, skip";
}
else
{
$lines = preg_split("/(\n|\r\n)/", $s);
$output = array();
$matched = FALSE;
foreach ( $lines as $s )
{
$output[] = $s;
// check if this is a PHP code?
if ( ! $matched && preg_match('/<(\?(php )*|%)/', $s) )
{
$matched = TRUE;
print "insert namespace ... ";
$output[] = "namespace {$namespace};";
}
}
if ( file_put_contents("{$dstdir}/{$basename}" , implode("\n", $output)) === FALSE )
{
throw new Exception("Cannot save file {$dstdir}/{$basename}");
}
if ( ! $matched )
{
print ("not a PHP file, skip.");
}
else
{
print "done!";
}
}
print "\n";
}
}
catch (Exception $e)
{
print 'Error: '. $e->getMessage() .' ('. $e->getCode() .')' ."\n";
}
}
extract($_SERVER);
if ( $argc < 4 )
{
?>
Usage: php -F <?=$argv[0]?> <namespace> <source_dir(s)> <dst_dir>
Convert PHP code to be namespace-aware
<?
return;
}
else
{
for ( $i = 2; $i < $argc - 1; $i++ )
{
convert($argv[1], $argv[$i], $argv[$argc-1]);
}
}
?>
答案 2 :(得分:-4)
eval()
怎么样?
新 A.php
$lines = file('a_original.php');
array_unshift($lines, 'namespace AO;?>');
$string = implode(chr(13).chr(10), $lines);
eval($string);
class A extends AO\A
{
public function hello()
{
parent::hello();
echo "hello world from Class A Extended\n";
}
}