簡體   English   中英

無法使用PHP名稱空間將Class給定名稱解析為字符串

[英]Unable to resolve Class given name as string using PHP namespaces

我正在遷移PHP Web應用程序以使用名稱空間,以准備將其放置在GitHub上。 多數操作很簡單,但是我有一個地方,當類名由字符串提供時,代碼必須從類中獲取靜態信息,而在這種情況下,我找不到正確的語法:

if ($className == '')
{
    $className          = 'Record';
    $information['classname']   = 'Record';
}
if (!class_exists(__NAMESPACE__ . "\\" . $className))
    {
        print "<p>include '". __NAMESPACE__ . "/" . $className . ".inc'</p>\n";
        include __NAMESPACE__ . "/" . $className . ".inc";
    }

    // BOTH of the following statements report Class 'Blog' not found
    // when $className == "Blog"
$order  = $className::$defaultOrder;
$order  = __NAMESPACE__ . "\\" . $className::$defaultOrder;

當在變量中提供類的名稱時,引用名稱空間中類的靜態成員的正確語法是什么? 調用上述代碼的網頁的輸出為:

include 'Genealogy/Blog.inc'
Blog.inc included
Fatal error: Uncaught Error: Class 'Blog' not found in /home/jcobban/includes/Genealogy/Record.inc:2043 Stack trace: #0 /home/jcobban/includes/Genealogy/RecordSet.inc(418): Genealogy\Record::getInformation('Blogs') #1 /home/jcobban/includes/Genealogy/Template.inc(2898): Genealogy\RecordSet->__construct('Blogs', Array) #2 /home/jcobban/includes/Genealogy/Template.inc(764): Genealogy\FtTemplate->customization() #3 /home/jcobban/public_html/Genealogy/genealogy.php(82): Genealogy\Template->__construct('/home/jcobban/p...') #4 {main} thrown in /home/jcobban/includes/Genealogy/Record.inc on line 2043

上面的代碼在“ Genealogy / Record.inc”中實現的基類Genealogy \\ Record中。 定義此基類:

<?php
namespace Genealogy;
use \PDO;
use \Exception;
use \ArrayAccess;
use \Countable;
use \Iterator;
class Record implements Iterator, ArrayAccess
{
...
protected static    $defaultOrder   = '';

派生類Genealogy \\ Blog在“ Genealogy / Blog.inc”中實現如下:

<?php
namespace Genealogy;
use \PDO;
use \Exception;
require_once __NAMESPACE__ . '/Record.inc';
print "<p>Blog.inc included</p>\n";
class Blog extends Record
{
...

Blog類不會覆蓋靜態成員$ defaultOrder的基本定義。

僅供參考,我通過運行以下PERL腳本將庫的代碼轉換為使用名稱空間:

use strict;
use warnings;
use 5.010;

use File::Find;
use File::Slurp;

my @content;
find( \&wanted, '/home/jcobban/includes/');

exit;

sub wanted {
  if ((substr $File::Find::dir, -9) ne "Genealogy" && -f)
  {
    print "wanted: ",  $File::Find::name, "\n";
my @lines   = read_file($File::Find::name);
my $first   = shift @lines;
if ((substr $first, 0, 5) eq '<?php')
{
    foreach my $line (@lines){
    $line   =~ s#require_once(\s*)(['"])#require_once$1__NAMESPACE__ . $2/#;
    $line   =~ s#require(\s*)(['"])#require$1__NAMESPACE__ . $2/#;
    $line   =~ s#include(\s*)(['"])#include$1__NAMESPACE__ . $2/#;
    $line   =~ s#include(\s*)\$#include$1__NAMESPACE__ . "/" . \$#;
    $line   =~ s#class_exists\((['"])#class_exists(__NAMESPACE__ . $1\\\\#;
    $line   =~ s#class_exists\((\$)#class_exists(__NAMESPACE__ . "\\\\" . $1#;
    }
    my $newfile = $File::Find::dir . "/Genealogy/" . $_;
    print "add namespace and write to $newfile\n";
    unshift @lines, "use \\Iterator;\n";
    unshift @lines, "use \\Countable;\n";
    unshift @lines, "use \\ArrayAccess;\n";
    unshift @lines, "use \\Exception;\n";
    unshift @lines, "use \\PDO;\n";
    unshift @lines, "namespace Genealogy;\n";
    unshift @lines, $first;
    write_file($newfile, @lines);
}
  }
  return;
}

我認為這並不重要,但是該網站運行的是PHP版本7.2.10。

該庫中的類實現了SQL數據庫的面向對象的接口。 也就是說,應用程序代碼使用子腳本符號訪問記錄中的字段,並通過$ record-> save()更新記錄,該記錄確定是否使用INSERT或UPDATE來應用更改並為SQL Server使用正確的語法。 出現在異常中的RecordSet類封裝了一個SQL查詢,並顯示了Record實例數組的外觀,並允許執行該集合的所有成員的更新和刪除。 這兩個類以及從它們派生出來以支持單個表的類將應用程序代碼與SQL完全隔離。

我遇到的問題似乎是::運算符在連接之前已處理。 當我將代碼更改為:

$nsclass                = __NAMESPACE__ . "\\" . $className;
if (!class_exists($nsclass))
{
    include __NAMESPACE__ . "/" . $className . ".inc";
}
$order                  = $nsclass::$defaultOrder;

有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM