从 class 导入静态方法并为其设置别名
import and alias a static method from a class
我正在尝试为 utility/helper class 中的静态方法添加别名,documentation 没有给出任何有关静态方法的信息,并且使用那里定义的方法对静态方法不起作用方法(看起来如此)。
所以说我有这个 class:
namespace App\Helpers;
class HTTP {
public static function extract_path_from_url( string $url ) {
$parsed_url = wp_parse_url( $url );
if ( ! isset( $parsed_url['path'] ) ) {
return false;
}
return (string) $parsed_url['path'];
}
}
然后尝试在不同的文件上使用它:
<?php
echo \App\Helpers\HTTP::extract_path_from_url( 'http://example.com/test' );
上面那个有效
但试图给它取别名:
<?php
use \App\Helpers\HTTP\extract_path_from_url as extract_path;
echo extract_path( 'http://example.com/test' );
会输出
Fatal error: Uncaught Error: Call to undefined function App\Helpers\HTTP\extract_path_from_url()
甚至:
<?php
use \App\Helpers\HTTP::extract_path_from_url as extract_path;
echo extract_path( 'http://example.com/test' );
显示这个奇怪的错误:
Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
这可能吗?
此致,
如手册所述,您可以通过 use
classes、函数和常量导入。 class(即使是静态方法)的方法不是函数。
因此,例如您有:
namespace My\Super\NameSpace;
const MY_CONST = 42;
class MyClass {
public function do() { /* code */ } // this is NOT a function
public static function doStatic() { /* code */ } // this is NOT a function too
}
function my_function() { /* code */ } // this is function
在其他文件中你可以这样写:
namespace YaNamespace;
use const My\Super\NameSpace\MY_CONST;
use My\Super\NameSpace\MyClass;
use function My\Super\NameSpace\my_function as func_alias;
这就是您可以使用 use
导入的所有项目。
别名不会神奇地将方法转换为函数,请试试这个
<?php
use \App\Helpers\HTTP as extract_path;
echo extract_path::extract_path_from_url( 'http://example.com/test' );
此外(不言而喻)当您使用别名时,这只会影响命名空间和 class 名称,而不影响 class 的方法。这些通常用于 2 件事中的 1 件事。解决命名冲突
use NamespaceOne\Someclass;
use NamespaceTwo\Someclass as SecondClass;
如果这些都没有别名,那么使用
Someclass::method()
会有歧义。
它们的第二个用途是,如果您需要从一个命名空间导入大量 classes。比如这样:
use App\Exceptions\NoFile;
use App\Exceptions\FileSize;
use App\Exceptions\FileType;
throw new NoFile();
throw new FileSize();
throw new FileType();
可以这样做:
use App\Exceptions as E;
throw new E\NoFile();
throw new E\FileSize();
throw new E\FileType();
这不仅更短,而且更易于维护,如果您更改命名空间,您只需更改别名即可,然后一切都很好。所以简而言之,它并不是真正为你想要使用它的目的而设计的。
包起来
你总是可以为它做一个包装器:
if(!function_exists('extract_path_from_url')){
function extract_path_from_url($url){
return \App\Helpers\HTTP::extract_path_from_url($url);
}
}
然后随心所欲地调用它。在性能方面,您确实可以通过包装来进行额外的调用,但通常包装器可以使其更易于维护。例如,如果您重命名该方法或 class,您可以在包装器中更改它,一切都很好。因此,对于任何一个选项都存在争论。
您不必检查该函数是否存在,但根据您整个系统的工作方式,这可能不是一个坏主意,因此为了完整起见,我将其包含在示例中。就我个人而言,在这种情况下,我认为将它与 class 放在同一个文件中没有任何问题,只需记住加载它即可。如果您正在使用自动加载,除非您手动加载文件或以其他方式强制它自动加载,否则不会包含这些功能。当然,假设没有别的东西首先使用 class。
我过去使用过的一种方法,我非常喜欢,是创建一个名为 http_functions
(classname + _functions) 的文件,然后将静态方法添加到 class 注册函数:
class HTTP {
public static function regester_fuctions(){
require 'http_functions.php'
}
}
然后当您调用 HTTP::regester_fuctions()
时,它会自动加载 HTTP
class 并包含所有功能包装器。事实上,我在我非常棒的调试打印中做了这件事class(队列无耻插件)https://github.com/ArtisticPhoenix/Debug
一些想法,尽情享受吧!
解决方法是使用带命名空间的 helpers.php
文件并在其中定义 'simple' 函数,这些函数仅通过参数传递。
// lib/My/Deeply/Nested/Namespace/MyClass.php
<?php
namespace My\Deeply\Nested\Namespace;
class MyClass
{
public static function aVeryUsefulFunction(string $var): string
{
// ...Do some stuff
return $magic;
}
}
// lib/helpers.php
namespace App;
use My\Deeply\Nested\Namespace\MyClass;
function doMagic(...$args)
{
return MyClass::aVeryUsefulFunction(...$args);
}
// templates/my-view.php
<?php use function App\doMagic; ?>
<div>I am doing <?= doMagic('magic') ?>!</div>
请注意,通过在我的 'pass through' 函数中使用扩展运算符 ...$args
,我可以更改 'target' 函数的要求,而无需在两个地方更新它。
这会破坏 IDE 完成,因为它只会建议 ...$args
而不是 string $var
。我不知道有什么方法可以 docblock 一个函数来告诉它从 另一个 函数读取参数。
我正在尝试为 utility/helper class 中的静态方法添加别名,documentation 没有给出任何有关静态方法的信息,并且使用那里定义的方法对静态方法不起作用方法(看起来如此)。
所以说我有这个 class:
namespace App\Helpers;
class HTTP {
public static function extract_path_from_url( string $url ) {
$parsed_url = wp_parse_url( $url );
if ( ! isset( $parsed_url['path'] ) ) {
return false;
}
return (string) $parsed_url['path'];
}
}
然后尝试在不同的文件上使用它:
<?php
echo \App\Helpers\HTTP::extract_path_from_url( 'http://example.com/test' );
上面那个有效
但试图给它取别名:
<?php
use \App\Helpers\HTTP\extract_path_from_url as extract_path;
echo extract_path( 'http://example.com/test' );
会输出
Fatal error: Uncaught Error: Call to undefined function App\Helpers\HTTP\extract_path_from_url()
甚至:
<?php
use \App\Helpers\HTTP::extract_path_from_url as extract_path;
echo extract_path( 'http://example.com/test' );
显示这个奇怪的错误:
Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
这可能吗?
此致,
如手册所述,您可以通过 use
classes、函数和常量导入。 class(即使是静态方法)的方法不是函数。
因此,例如您有:
namespace My\Super\NameSpace;
const MY_CONST = 42;
class MyClass {
public function do() { /* code */ } // this is NOT a function
public static function doStatic() { /* code */ } // this is NOT a function too
}
function my_function() { /* code */ } // this is function
在其他文件中你可以这样写:
namespace YaNamespace;
use const My\Super\NameSpace\MY_CONST;
use My\Super\NameSpace\MyClass;
use function My\Super\NameSpace\my_function as func_alias;
这就是您可以使用 use
导入的所有项目。
别名不会神奇地将方法转换为函数,请试试这个
<?php
use \App\Helpers\HTTP as extract_path;
echo extract_path::extract_path_from_url( 'http://example.com/test' );
此外(不言而喻)当您使用别名时,这只会影响命名空间和 class 名称,而不影响 class 的方法。这些通常用于 2 件事中的 1 件事。解决命名冲突
use NamespaceOne\Someclass;
use NamespaceTwo\Someclass as SecondClass;
如果这些都没有别名,那么使用
Someclass::method()
会有歧义。
它们的第二个用途是,如果您需要从一个命名空间导入大量 classes。比如这样:
use App\Exceptions\NoFile;
use App\Exceptions\FileSize;
use App\Exceptions\FileType;
throw new NoFile();
throw new FileSize();
throw new FileType();
可以这样做:
use App\Exceptions as E;
throw new E\NoFile();
throw new E\FileSize();
throw new E\FileType();
这不仅更短,而且更易于维护,如果您更改命名空间,您只需更改别名即可,然后一切都很好。所以简而言之,它并不是真正为你想要使用它的目的而设计的。
包起来
你总是可以为它做一个包装器:
if(!function_exists('extract_path_from_url')){
function extract_path_from_url($url){
return \App\Helpers\HTTP::extract_path_from_url($url);
}
}
然后随心所欲地调用它。在性能方面,您确实可以通过包装来进行额外的调用,但通常包装器可以使其更易于维护。例如,如果您重命名该方法或 class,您可以在包装器中更改它,一切都很好。因此,对于任何一个选项都存在争论。
您不必检查该函数是否存在,但根据您整个系统的工作方式,这可能不是一个坏主意,因此为了完整起见,我将其包含在示例中。就我个人而言,在这种情况下,我认为将它与 class 放在同一个文件中没有任何问题,只需记住加载它即可。如果您正在使用自动加载,除非您手动加载文件或以其他方式强制它自动加载,否则不会包含这些功能。当然,假设没有别的东西首先使用 class。
我过去使用过的一种方法,我非常喜欢,是创建一个名为 http_functions
(classname + _functions) 的文件,然后将静态方法添加到 class 注册函数:
class HTTP {
public static function regester_fuctions(){
require 'http_functions.php'
}
}
然后当您调用 HTTP::regester_fuctions()
时,它会自动加载 HTTP
class 并包含所有功能包装器。事实上,我在我非常棒的调试打印中做了这件事class(队列无耻插件)https://github.com/ArtisticPhoenix/Debug
一些想法,尽情享受吧!
解决方法是使用带命名空间的 helpers.php
文件并在其中定义 'simple' 函数,这些函数仅通过参数传递。
// lib/My/Deeply/Nested/Namespace/MyClass.php
<?php
namespace My\Deeply\Nested\Namespace;
class MyClass
{
public static function aVeryUsefulFunction(string $var): string
{
// ...Do some stuff
return $magic;
}
}
// lib/helpers.php
namespace App;
use My\Deeply\Nested\Namespace\MyClass;
function doMagic(...$args)
{
return MyClass::aVeryUsefulFunction(...$args);
}
// templates/my-view.php
<?php use function App\doMagic; ?>
<div>I am doing <?= doMagic('magic') ?>!</div>
请注意,通过在我的 'pass through' 函数中使用扩展运算符 ...$args
,我可以更改 'target' 函数的要求,而无需在两个地方更新它。
这会破坏 IDE 完成,因为它只会建议 ...$args
而不是 string $var
。我不知道有什么方法可以 docblock 一个函数来告诉它从 另一个 函数读取参数。