php对象工具

php对象工具

php和包

包是由一组相关的类以某种方式组合,可以用于隔离系统中的各个部分。

命名空间

名空间类似于操作系统的物理文件系统,但有本质的不同。命名空间是一种虚拟的概念,没必要和文件系统中的目录结构完全相同。例如 User 在命名空间 App\Model 中, 但真实的文件目录却是 app\User.php 并没有 model 目录。 不过为了兼容PSR-4自动加载标准,一般都会把命名空间放到对应的文件系统的目录中。可以说命名空间的为现代PHP生态系统和基于组件的新型架构的实现奠定了坚实的基础。

类名可以通过三种方式引用:

1.非限定名称,或不包含前缀的类名称,例如 $a=new foo();foo::staticmethod();。如果当前命名空间是 currentnamespacefoo 将被解析为 currentnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为foo。 警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。详情参见 使用命名空间:后备全局函数名称/常量名称。

2.限定名称,或包含前缀的名称,例如 $a = new subnamespace\foo();subnamespace\foo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为subnamespace\foo

3.完全限定名称,或包含了全局前缀操作符的名称,例如, $a = new \currentnamespace\foo();\currentnamespace\foo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名(literal name)currentnamespace\foo

代码清单

    <?php
    /**
     * Created by PhpStorm.
     * User: mali@mali
     * Date: 2020/8/4
     * Time: 9:10 下午
     */
    namespace Foo\Bar;
    include 'file1.php';
    
    const FOO = 2;
    class foo
    {
        static function staticmethod() {
            echo "file2.php<br/>";
        }
    }
    
    /* 非限定名称 */
    foo(); //这样操作的话是报错的,因为解析的是 Foo\Bar中的foo文件,但是这个文件是不存在的
    subnamespace\foo();//可以正常解析
    echo FOO;//解析为resolves to constant Foo\Bar\FOO
    
    die();
    subnamespace\foo();// 解析为函数 Foo\Bar\subnamespace\foo
    subnamespace\foo::staticmethod(); // 解析为类 Foo\Bar\subnamespace\foo,
    echo subnamespace\FOO; // 解析为常量 Foo\Bar\subnamespace\FOO
    
    
    /* 完全限定名称 */
    //\Foo\Bar\foo(); // 解析为函数 Foo\Bar\foo,报错
    \Foo\Bar\foo::staticmethod(); // 解析为类 Foo\Bar\foo, 以及类的方法 staticmethod
    echo \Foo\Bar\FOO; // 解析为常量 Foo\Bar\FOO
    
    die;

use和命名空间的配合使用,我们在用use和命名空间的时候必须先引入。

namespace popp\ch05\batch04\util;


class Debug
{
    public static function hellowWord()
    {
        print "hello from Debug\n";
    }
}



namespace popp\ch05\batch04;
use popp\ch05\batch04\util\Debug;
Debug::hellowWord();
自动加载

require_once知识单独加载,但是开发人员完全不必在高层次执行require语句,简单的依赖加载就行。spl_autoload_register函数就可以实现自动加载。

我们在实例化失败的时候,spl_autoload_register就回接收一个参数(实例化失败的类名字),这个函数是,每次试图实例化的时候都会执行一次。

代码清单

实例化Blah失败后,php就会发现我们用spl_autoload_register()注册了一个自动加载函数,然后回调用这个函数,并且将Blah作为参数传给它。这个自动加载只是简单的尝试包含Blah.php文件。仅当该文件存在于声名自动加载代码所处的位置。

    <?php
/**
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/4
 * Time: 10:24 下午
 */

class Blah{
    public function wave()
    {
        print "saying hi from root";
    }
}
<?php
/**
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/4
 * Time: 10:05 下午
 */

//自动加载
$basic = function ($classname){
    $file = __DIR__ . "/index.php";
    if(file_exists($file)){
        require_once($file);
    }
};

\spl_autoload_register($basic);//如果 $blah = new Blah();实例化失败的话,会将类名当作参数参入spl_autoload_register中去
$blah = new Blah();
$blah->wave();


die();
spl_autoload_register();
$write = new Util\Writer();

下面的代码,包含以传统方式命名的类文件,如(PEAR包中的类文件)

自动加载函数会将$classname中的下划线替换为/,然后尝试包含这个类文件(util/Blah.php)。如果这个类文件正确,程序就可以正确的实例化对象,这里就要求程序员不能移下划线的方式命名类文件。

代码清单

-w184

<?php
/**
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/4
 * Time: 10:37 下午
 */

class util_Blah
{
    public function wave()
    {
        print "saying hi from underscore file";
    }
}
<?php
/**
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/4
 * Time: 10:34 下午
 */


$underscore = function ($classname){
    $path = str_replace('_',DIRECTORY_SEPARATOR,$classname);
    $path = __DIR__."/$path";
    if(file_exists("{$path}.php")){
        require_once ("{$path}.php");
    }
};

\spl_autoload_register($underscore);

$blah = new util_Blah();//此刻实例化的类是 /www/wwwroot/pinche.sir6.cn/util/Blah.php
$blah->wave();

如果是命名空间的话呢,也就是/这种。其实就是找到并且替换斜杠。

传递给自动加载的函数总是会标准话一个完全限定的名字,没有开头的反斜杠,因此实例化对象时无需担心别名或者相对命名空间的问题。

代码清单

<?php
/**
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/4
 * Time: 11:01 下午
 */

namespace util;


class LocalPath
{
    public function wave()
    {
        print "hello from---".get_class();
    }
}
<?php
/**
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/4
 * Time: 11:02 下午
 */
$namespace = function ($path){
    if(preg_match('/\\\\/',$path)){
        $path = str_replace('\\',DIRECTORY_SEPARATOR,$path);
    }
    if(file_exists("{$path}.php")){
        require_once("index.php");
    }
};
\spl_autoload_register($namespace);
$obj = new util\LocalPath();
$obj->wave();

对象函数和类函数

php提供了一组检查类和对象的函数。

class_exists接收一个要检查类的字符串,如果存在,返回true;

$classname = "Task";
require_once("tasks/{$classname}.php");
$classname = "tasks\\$classname";
if(!class_exists($classname)){
    throw new \Exception("No such file as $classname");
}
$myObj = new $classname();

$myObj->doSpeak();

get_class返回对象实例 obj 所属类的名字。如果 obj 不是一个对象则返回 FALSE。

class foo {
    public function __construct()
    {
        // implements some logic
    }

    public function name()
    {
        echo "My name is " . get_class($this) . " ";
    }
}

$f = new foo();

// external call
echo "Its name is " , get_class($f) , " ";

// internal call
$f->name();

get_class_methods 得到类中的所有方法,参数是类的字符串

<?php
/**
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/5
 * Time: 11:42 上午
 */

class book{
    public function getList()
    {
        
    }

    public function getDetail()
    {
        
    }

    public function save()
    {
        
    }

    public function Update()
    {
        
    }
}

echo "<pre/>";
/**
 * Array
    (
    [0] => getList
    [1] => getDetail
    [2] => save
    [3] => Update
    )
 */
print_r(get_class_methods('book'));//得到类中的所有方法,参数是类的字符串

get_class_vars(),得到类的属性

<?php
/** 检查类的属性
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/5
 * Time: 1:25 下午
 */

class book{

    private $shop;
    public $time='2019:11:11';

    public function getList()
    {

    }

    public function getDetail()
    {

    }

    public function save()
    {

    }

    public function Update()
    {

    }
}

print_r(get_class_vars('book'));//Array ( [time] => 2019:11:11 )

get_declared_classes()列出所有的用户定义的类和php内置的类

<?php
/**
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/5
 * Time: 11:30 上午
 */
$classname = "Task";
require_once("tasks/{$classname}.php");
$classname = "tasks\\$classname";
if(!class_exists($classname)){
    throw new \Exception("No such file as $classname");
}
$myObj = new $classname();

$myObj->doSpeak();
echo "<pre/>";
$res = get_declared_classes();//列出所有的用户定义的类和php内置的类
print_r($res);

is_callable:检测类中方法是否可以使用

<?php
/**
 * 用于检测函数在当前环境中是否可以使用
 * Created by PhpStorm.
 * User: mali@mali
 * Date: 2020/8/5
 * Time: 11:46 上午
 */

class book{
    public function getList()
    {

    }

    public function getDetail()
    {

    }

    public function save()
    {

    }

    public function update()
    {

    }
}
$book = new book();
if(is_callable('book','update')){
    echo "次方法可以调用";
}else{
    echo '次方法不可以调用';
}

get_parent_class() 检测类是否是继承,输出的是父类的名字

方法调用 call_user_func()

把第一个参数作为回调函数调用

call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] ) : mixed

第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。

call_user_func(),既能调用函数,也能调用方法。

调用函数:需要传一个字符串做为第一个参数

调用方法: 需要传一个数组做为参数,数组中第一个元素是对象,第二个参数是需要调用的方法的名字。

反射API略,用到的地方太少,有机会再更新

posted on 2020-08-06 18:01  誓_言  阅读(63)  评论(0)    收藏  举报

导航