奥门新浦京官方网站PHP进阶学习之命名空间基本用法分析_php技巧_脚本之家

命名空间

什么是命名空间呢?

命名空间(英语:Namespace)表示标识符(identifier)的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。

简单说来命名空间是为了解决不同库在同一个环境下使用时出现的命名冲突。例如我自己有一个函数名叫A,但是系统已经有一个A函数了,那就会出现冲突。

本文实例讲述了PHP进阶学习之命名空间基本用法。分享给大家供大家参考,具体如下:

类与对象


PHP中的命名空间

PHP从5.3版本开始引入了命名空间,之后许多现有PHP类库以及框架都开始支持它。那么PHP的命名空间怎么用呢?

前言

基本概念

每个类的定义都是关键class开头。

<?php
namespace NS
{
    class A
    {
        // 成员属性
        public $temp = '成员属性';

        // 方法
        public function displayVar()
        {
            // 使用伪变量$this调用成员属性
            echo $this->temp . "<br>";
        }
    }
// 使用new关键字实例化一个类
    $temp = new A();
    echo $temp->displayVar();

    class B extends A
    {
        // 构造方法
        function __construct()
        {
            $this->temp = '成员属性B继承于A';
        }
    }
    $temp = new B();
    echo $temp->displayVar();

    echo A::class;
}
?>

定义命名空间

下面是一个定义命名空间的例子

<?php    
//file a.php
namespace A;

const test = 'Atest'; 

function test() { 
    return __FUNCTION__; 
}

class Test{
    public function __construct(){
        return __METHOD__;
    }
}
?>

上面例子中就是一个典型的命名空间定义方法,只有constfunction,class受命名空间的约束。

命名空间,在编程语言中,是对作用域的一种特殊的抽象.它表示着一个标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其他命名空间中。

访问控制

public(公有),protected(受保护)或 private(私有)。

使用命名空间

使用命名空间的方式如下:

<?php 
namespace B;
use A;

const test = 'Btest';
function test() { 
    return __FUNCTION__; 
}

class Test{
    public function __construct(){
        return __METHOD__;
    }
}

include "a.php";//必须包含A命名空间的文件

// 完全限定
// `Btest`从绝对位置查找输出,如果是全局函数则`test`
echo Btest;   //输出Btest

// 限定名称  
// 这里已经通过`use A`申明了在这个文件可以通过`A...`使用A命名空间的函数
echo Atest;    //输出Atest

// 非限定名称
// 非限定名称的函数`test`会从当前命名控件查找,即B
echo test;      //输出Btest

// namespace关键字代表当前命名空间
echo namespace/test;
?>

首先要注意的是命名空间只起申明作用,也就是在使用了命名空间的时候依然得把这个命名空间申明的那个文件包含进来。在使用中可以通过__NAMESPACE__来查看当前命名空间。

更多内容可以查看PHP官方文档

在PHP中也存在命名空间的用法,由它控制可见范围的这个标识符一般指的就是类和函数。

成员变量使用

可以用 ->(对象运算符):$this->property(其中 property
是该属性名)这种方式来访问非静态属性。 静态属性则是用
::(双冒号):self::$property 来访问。

自动加载

每个文件既要申明命名控件又要手动include是非常不智能的事情,所以在自己的PHP系统或者框架中可以使用自动加载技术,让系统自己去找

最简单的方式是利用函数__autoload函数,但是这个函数只能在非命名控件下定义,也就是全局情况下:

function __autoload($class) {
  $dir = './';
  set_include_path(get_include_path().PATH_SEPARATOR.$ids_dir);
  $class = str_replace('\', '/', $class) . '.php'; 
  require_once($class); }

如果在已经有了命名空间的类中,可以使用函数spl_autoload_register来注册一个类中的方法来代替__autoload

一、PHP命名空间基础

类常量

<?php
class MyClass
{
    const constant = 'constant value';

    function showConstant() {
        echo  self::constant . "n";
    }
}

echo MyClass::constant . "n";

$classname = "MyClass";
echo $classname::constant . "n"; // 自 5.3.0 起

$class = new MyClass();
$class->showConstant();

echo $class::constant."n"; // 自 PHP 5.3.0 起
?>

从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如PHP的类名是不可以重复的,但是经常我们需要引入一些第三方的类库,常常类名就会在项目中产生重复冲突,所以,命名空间就是解决这个冲突的一种方法。

类的自动加载

spl_autoload_register()
函数可以注册任意数量的自动加载器,当使用尚未被定义的类(class)和接口(interface)时自动去加载。

本例尝试分别从 MyClass1.php 和 MyClass2.php 文件中加载 MyClass1 和
MyClass2 类。

<?php
spl_autoload_register(function ($class_name) {
    require_once $class_name . '.php';
});

$obj  = new MyClass1();
$obj2 = new MyClass2();
?>

在PHP5.3以后,就已经引入了命名空间的概念,即同个命名空间下的类名不能重复,不同命名空间下可以存在同名的类。

构造函数

<?php
class BaseClass {
   function __construct() {
       print "In BaseClass constructorn";
   }
}

class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();
       print "In SubClass constructorn";
   }
}

class OtherSubClass extends BaseClass {
    // inherits BaseClass's constructor
}

// In BaseClass constructor
$obj = new BaseClass();

// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();

// In BaseClass constructor
$obj = new OtherSubClass();
?>

这样,在引入第三方类库的时候,只有各个类库的命名空间不一样,就不会产生冲突。

析构函数

<?php
class MyDestructableClass {
   function __construct() {
       print "In constructorn";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "Destroying " . $this->name . "n";
   }
}

$obj = new MyDestructableClass();
?>

所以根据官方所说,在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:

Static(静态)关键字

由于静态方法不需要通过对象即可调用,所以伪变量 $this
在静态方法中不可用。

静态属性不可以由对象通过 -> 操作符来访问。

用静态方式调用一个非静态方法会导致一个 E_STRICT 级别的错误。

1、用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。2、为很长的标识符名称创建一个别名的名称,提高源代码的可读性。

抽象类

任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。

<?php
abstract class AbstractClass
{
 // 强制要求子类定义这些方法
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

    // 普通方法(非抽象方法)
    public function printOut() {
        print $this->getValue() . "n";
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }

    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."n";
?>

同个文件下可以存在多个命名空间; 不同命名空间内的类可以相互调用。

对象接口

使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。

接口是通过 interface
关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。

接口中定义的所有方法都必须是公有,这是接口的特性。

二、PHP命名空间的用法

实现(implements)

要实现一个接口,使用 implements
操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。
类可以实现多个接口,用逗号来分隔多个接口的名称。

1、定义

Trait代码复用

<?php

class A
{
    public function sayHello()
    {
        echo "Hello ";
    }
}

trait mytrait
{
    public function traitFunction()
    {
        parent::sayHello();
        echo "world!";
    }

}

class B extends A
{
    use mytrait;
}

$temp = new B();
$temp->traitFunction();

命名空间的定义采用关键字namespace,定义方式如下:

匿名类

PHP 7 开始支持匿名类。

<?php

// PHP 7 之前的代码
class Logger
{
    public function log($msg)
    {
        echo $msg;
    }
}

$util->setLogger(new Logger());

// 使用了 PHP 7+ 后的代码
$util->setLogger(new class {
    public function log($msg)
    {
        echo $msg;
    }
});
namespace example

魔术方法

public void __set ( string $name , mixed $value )

public mixed __get ( string $name )

public bool __isset ( string $name )

public void __unset ( string $name )

在给不可访问属性赋值时,__set() 会被调用。

读取不可访问属性的值时,__get() 会被调用。

当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。

当对不可访问属性调用 unset() 时,__unset() 会被调用。

参数 $name 是指要操作的变量名称。__set() 方法的 $value 参数指定了
$name 变量的值。

属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。
所以这些方法都不能被 声明为 static。从 PHP 5.3.0 起,
将这些魔术方法定义为 static 会产生一个警告。

则该命名空间下的类都归属于该命名空间,example命名空间下的类不能重名。

遍历对象

PHP 5 提供了一种定义对象的方法使其可以通过单元列表来遍历, 例如用
foreach 语句。默认情况下,所有可见属性都将被用于遍历。

<?php

class MyClass
{
    public $var1 = 'value 1';
    public $var2 = 'value 2';
    public $var3 = 'value 3';

    protected $protected = 'protected var';
    private $private = 'private var';

    function iterateVisible()
    {
        echo "MyClass::iterateVisible:<br>";
        foreach ($this as $key => $value)
        {
            print '$key=>' . $key . "<br>";
            print '$value=>' . $value . "<br>";
        }
    }
}

$class = new MyClass();
$class->iterateVisible();

foreach ($class as $key => $value)
{
    print '$key=>' . $key . "<br>";
    print '$value=>' . $value . "<br>";
}

或者可以定义多级命名空间:

Final 关键字

PHP 5 新增了一个 final 关键字。如果父类中的方法被声明为
final,则子类无法覆盖该方法。 如果一个类被声明为 final,则不能被继承。

<?php

class BaseClass
{
    public function display()
    {
        echo 'final';
    }

    final public function test()
    {
        echo 'Hello World!';
    }
}

class A extends BaseClass
{
    public function display()
    {
        echo 'A';
    }

    public function test()
    {
        echo 'haha';
    }
}

$temp = new A();
$temp->test();
#会报错,final方法不能重写
namespace exampletestdemo

对象复制

在多数情况下,我们并不需要完全复制一个对象来获得其中属性。但有一个情况下确实需要:如果你有一个
GTK 窗口对象,该对象持有窗口相关的资源。

你可能会想复制一个新的窗口,保持所有属性与原来的窗口相同,但必须是一个新的对象(因为如果不是新的对象,那么一个窗口中的改变就会影响到另一个窗口)。

还有一种情况:

如果对象 A 中保存着对象 B 的引用,当你复制对象 A
时,你想其中使用的对象不再是对象 B 而是 B 的一个副本,那么你必须得到对象
A 的一个副本。

则改命名空间下的类全归属于exampletestdemo命名空间。

对象比较

当使用比较运算符(==)比较两个对象变量时,比较的原则是:

如果两个对象的属性和属性值
都相等,而且两个对象是同一个类的实例,那么这两个对象变量相等。

而如果使用全等运算符(===),这两个对象变量一定要指向某个类的同一个实例(即同一个对象)。

定义后的命名空间可以用_​_​NAMESPACE_​_​魔法变量来获取当前命名空间。

类型约束

PHP 5 可以使用类型约束。

如果一个类或接口指定了类型约束,则其所有的子类或实现也都如此。

类型约束不能用于标量类型如 int 或 string。Traits 也不允许。

<?php

class MyClass
{
    public function test_class(OtherClass $otherclass)
    {
        echo $otherclass->var;
        echo "<br>";
    }

    public function test_array(array $input_array)
    {
        print_r($input_array);
    }
}

class OtherClass
{
    public $var = 'Hello World!';
}

$myclass    = new MyClass();
$otherclass = new OtherClass();
$myclass->test_class($otherclass);

$input_array = ['one' => 'first', 'two' => 'second'];
$myclass->test_array($input_array);

2、引入

后期静态绑定

自 PHP 5.3.0 起,PHP
增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。

引入命名空间使用关键字use,可以通过多个use在一个文件中引入多个命名空间:

self:: 的限制

使用 self::
或者 CLASS 对当前类的静态引用,取决于定义当前方法所在的类:

use example;use exampletestdemo;

后期静态绑定的用法

<?php

class A
{
    public static function who()
    {
        echo __CLASS__;
    }
    public static function test()
    {
//        self::who(); // 输出A
        static::who(); // 输出B
    }
}

class B extends A
{
    public static function who()
    {
        echo __CLASS__;
    }
}

$temp = new B();
$temp::test();

需要使用到哪个命名空间的类和方法,则use哪个命名空间,前提是这些命名空间的实际文件地址已经包含进来了,或者说能实现自动的类加载了。

对象和引用

在php5
的对象编程经常提到的一个关键点是“默认情况下对象是通过引用传递的”。

但其实这不是完全正确的。下面通过一些例子来说明。

PHP 的引用是别名,就是两个不同的变量名字指向相同的内容。 在 PHP
5,一个对象变量已经不再保存整个对象的值。只是保存一个标识符来访问真正的对象内容。
当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,
只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容。

<?php

class A
{
    public $foo = 1;

}

$a = new A();
$b = $a;

$b->foo = 2;
echo $a->foo . "n"; // 输出为2

3、实例化

对象序列化

序列化对象 – 在会话中存放对象

所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。
unserialize()函数能够重新把字符串变回php原来的值。
序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

<?php
//
//include("class.inc");
//
//$a = new A();
//$a->show_one();
//
//$s = serialize($a);
//file_put_contents('store', $s);

// 反序列化必须要包含此文件。
include("class.inc");
$s = file_get_contents('store');
$a = unserialize($s);

$a->show_one();

在程序中实例化并使用某个命名空间下的类方法,同样使用new关键字进行实例化,但是需要在类名前面加上命名空间前缀。

命名空间

  1. 解决PHP内部的类、函数、常量或第三方类、函数、常量之间的名字冲突。
  2. 为很长的标识名称创建一个别名,提高源代码的可读性。

<?php

namespace myname;

class MyClass{}

function myfunction(){}

const MYCONST = 1;

$a = new MyClass();
$c = new mynameMyClass;
$a = strlen('hi');
$d = namespaceMYCONST;
$d = __NAMESPACE__ . 'MYCONST';
echo $d;
echo constant($d);
$class = new examplea();//实例化example命名空间下的a类$class = new exampletestdemob(); //实例化exampletestdemo命名空间下的b类

定义命名空间

虽然任意合法的PHP代码都可以包含在命名空间中,但只有以下类型的代码受命名空间的影响,它们是:

类、接口、函数和常量。

命名空间通过关键字namespace来声明。如果一个文件中包含命名空间,它必须在其它代码之前声明命名空间,
有一个除外:declare关键字。

<?php

namespace spaceMyProject;

const CONNECT_OK = 1;

class Connection{}
function connect(){}

echo __NAMESPACE__;

如果在文件前面已经引入了这些命名空间,则可以不需要类的前缀:

在同一个文件中定义多个命名空间

在同一个文件中定义多个命名空间有两种语法形式。

不建议使用这种语法在单个文件中定义多个命名空间,区间会显得不明确。

<?php

namespace MyProject;

const CONNECT_OK = 1;
class Connection
{
}

function connect()
{
}

echo __NAMESPACE__ . "<br>";

namespace AnotherProject;

const CONNECT_OK = 1;
class Connection
{
}

function connect()
{
}

echo __NAMESPACE__ . "<br>";
// 不建议使用这种语法在单个文件中定义多个命名空间,区间会显得不明确。
use example;use exampletestdemo;$class = new a();//实例化example命名空间下的a类$class = new b(); //实例化exampletestdemo命名空间下的b类

使用大括号来定义多个命名空间

<?php

namespace MyProject
{
    const CONNECT_OK = 1;
    class Connection
    {
    }

    function connect()
    {
    }

    echo __NAMESPACE__ . "<br>";
}

namespace AnotherProject
{
    const CONNECT_OK = 1;
    class Connection
    {
    }

    function connect()
    {
    }

    echo __NAMESPACE__ . "<br>";

}

注:如果use的时候是use exampletest;则在实例化b类时要带上相对命名空间路径,即new demob();

使用命名空间:别名、导入

允许通过别名引用或导入外部的完全限定名称,是命名空间的一个重要特征。

<?php

namespace MyProject
{
    const CONNECT_OK = 1;
    class Connection
    {
        public function __construct()
        {
            echo "MyProject __construct" . "<br>";
        }
    }

    function connect()
    {
        echo "MyProject connect" . "<br>";
    }

    echo __NAMESPACE__ . "<br>";
}

namespace AnotherProject
{
    const CONNECT_OK = 1;
    class Connection
    {
        public function __construct()
        {
            echo "AnotherProject __construct" . "<br>";
        }
    }

    function connect()
    {
        echo "AnotherProject connect" . "<br>";
    }

    $temp = new MyProjectConnection();
    use MyProject as A;
    $temp = new AConnection();
    use MyprojectConnection as AConnection;
    $temp = new AConnection();

    echo __NAMESPACE__ . "<br>";
}

当然所有的实例化都可以直接使用绝对路径形式,即在命名空间前面加字符,如new exampletestdemob();这样就采用了绝对路径形式实例化了b类。

全局空间

如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与PHP引入命名空间概念前一样。

在名称前加上前缀””表示该名称是全局空间中的名称,即使该名称位于其它的命名空间中时也是如此。

<?php

namespace wwwweb;

class MyClass
{
    public function display()
    {
        try
        {
            echo 'Hello World!';
        }
        catch (Exception $e)
        {
            echo 'try...catch';
        }
    }
}

$temp = new MyClass();
$temp->display();

4、别名

使用命名空间:后备全局函数/常量

在一个命名空间中,当PHP遇到一个非限定的类、函数或常量名称时,它使用不同的优先策略来解析该名称。

类名称总是解析到当前命名空间中的名称。因此在访问系统内部或不包含在命名空间中的类名称时,必须使用完全限定名称。

对于函数和常量来说,如果当前命名空间中不存在该函数或常量,PHP会退而使用全局空间中的函数或常量。

<?php

namespace ABC;

class Exception extends Exception
{
}

$a = new Exception('message');
$b = new Exception('message');

echo strlen('Hello World!'); // 正常输出12
$c = new ArrayObject(); // 致命错误,找不到ABCArrayObject类

在用namespace定义命名空间的时候,为了避免之后引用的时候命名空间过长,可以在定义时采用as关键字为一个命名空间指定别名

命名空间名称解析规则

namespace exampletestdemo as testDemo;

命名空间名称定义

  • 非限定名称Unqualified name

名称中不包含命名空间分隔符的标识符,例如Foo

  • 限定名称Qualified name

名称中含有命名空间分隔符的标识符,例如FooBar

  • 完全限定名称Fully qualified name

名称中包含命名空间分隔符,并以命名空间分隔符开始的标识符,例如FooBar。

这样在之后引用或实例化的时候就可以new testDemo();

生成器

生成器提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现Iterator接口的方式,性能开销和复杂性大大降低。

生成器允许你在foreach代码块中写代码来迭代一组数据而不需要在内存中创建一个数组,在内存中创建一个大数组可能会使你的内存达
到上限,或者会占据可观的处理时间。

生成器函数,就像一个普通的自定义函数一样,和普通函数只返回一次不同的是,生成器可以根据需要yield多次,以便生成需要迭代的值。

一个简单的例子就是使用生成器来重新实现 range() 函数。 标准的 range()
函数需要在内存中生成一个数组包含每一个在它范围内的值, 然后返回该数组,
结果就是会产生多个很大的数组。 比如,调用 range(0, 1000000)
将导致内存占用超过 100 MB。

<?php

function xrange($start, $end, $step = 1)
{
    for ($i = $start; $i <= $end; $i += $step)
    {
        yield $i;
    }
}
// 直接报500错误
foreach (range(0, 1000000) as $val)
{
    echo $val;
}
// 进入大循环
foreach (xrange(0, 1000000) as $val)
{
    echo $val;
}

三、基于PSR4的命名空间规范

生成器语法

我的理解就是链表来的,一个指针像游标一样,循环迭代。

一个生成器函数看起来像一个普通的函数,不同的是普通函数返回一个值,而一个生成器可以yield生成许多它所需要的值。

当一个生成器被调用的时候,它返回一个可以被遍历的对象。当你遍历这个对象的时候PHP将会在每次需要值的时候调用生成器函数,
并在产生一个值之后保存生成器的状态,这样它就可以在需要产生下一个值的时候恢复调用状态。

由于方法、类在不同项目中命名空间定义不一致,第三方类库的命名空间也定义不一致,所以相关php组织出台了一套约定俗成的规范,即PSR4规范,

yield关键字

生成器函数的核心就是yield关键字。它最简单的调用形式看起来像一个return申明,不同之处在于普通return会返回值并
终止函数的执行,而yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。

<?php

function test()
{
    for ($i = 0; $i <= 10; $i++)
    {
        // 注意:变量$i的值在不同的yield之间是保持传递的。
        yield $i;
    }
}

$temp = test();
foreach ($temp as $value)
{
    echo "$value" . "<br>";
}

用来规范命名空间的定义规则。

指定键名来生成值

<?php

$input = <<<'EOF'
1;PHP;Likes dollar signs
2;Python;Likes whitespace
3;Ruby;Likes blocks
EOF;

function input_parse($input)
{
    foreach (explode("n", $input) as $line)
    {
        $fields = explode(';', $line);
        $id     = array_shift($fields); // array_shift将数组开头的单元移出数组

        yield $id => $fields;
    }
}

foreach (input_parse($input) as $key => $value)
{
    echo '$key=>' . $key . "<br>";
    echo '$value=>' . print_r($value) . "<br>";
}
  1. 一个完整的类名需具有以下结构:

生成null值

yield可以在没有参数传入的情况下被调用来生成一个NULL值并配对一个自动的键名。

可以使用生成器来初始化一个null数组。

<?php

function test()
{
    foreach (range(1, 3) as $i)
    {
        yield;
    }
}
var_dump(iterator_to_array(test()));

* 1. 完整的类名 必须 要有一个顶级命名空间,被称为 “vendor
namespace”; 2. 完整的类名 可以 有一个或多个子命名空间; 3. 完整的类名
必须 有一个最终的类名; 4.
完整的类名中任意一部分中的下滑线都是没有特殊含义的; 5. 完整的类名 可以
由任意大小写字母组成; 6. 所有类名都 必须 是大小写敏感的。

使用引用来生成值

生成函数可以像使用值一样来使用引用生成。

<?php

function &test()
{
    $value = 10;

    while ($value > 0)
    {
        yield $value;
    }
}

foreach (test() as &$value)
{
    echo (--$value) . '...';
}
  1. 当根据完整的类名载入相应的文件

PHP中的引用

在PHP中引用意味着用不同的名字访问同一个变量内容。这并不像C的指针:
例如你不能对他们做指针运算,他们并不是实际的内存地址。

在PHP中,变量名和变量的内容是不一样的,因此同样的内容可以有不同的名字。

$a = 'Hello world!';
$b = &$a;
$b = 'new Hello world!';
//echo $a;

function test(&$temp){
    $temp = 'function Hello world!';
}
test($b);
echo $a;

.
完整的类名中,去掉最前面的命名空间分隔符,前面连续的一个或多个命名空间和子命名空间,作为「命名空间前缀」,其必须与至少一个「文件基目录」相对应;
. 紧接命名空间前缀后的子命名空间 必须
与相应的「文件基目录」相匹配,其中的命名空间分隔符将作为目录分隔符。 .
末尾的类名 必须 与对应的以 .php 为后缀的文件同名。 的实现 一定不可
抛出异常、一定不可 触发任一级别的错误信息以及 不应该 有返回值。

引用返回

引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。

不要用返回引用来增加性能,引擎足够聪明来自己进行优化。

仅在有合理的技术原因时才返回引用!要返回引用,请看如下示例:

class temp
{
    public $value = 100;

    public function &getValue()
    {
        return $this->value;
    }
}

$obj   = new temp();
$value = &$obj->getValue();
echo $value . '<br>'; // 输出100
$obj->value = 9;
echo $value . '<br>'; // 输出9

看起来很复杂,其实规范的要点就是,命名空间的路径要与当前文件的路径相对应,这样规范了所有项目命名空间的定义准则,虽然PHP官方没有

取水引用

当unset一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了。

$a = 1;
$b = &$a;
unset($a);

强制规定,但如今许多开源项目都已经约定俗成地使用了,这种规范便于查找命名空间下的类所在的路径。

引用定位

许多PHP的语法结构
是通过引用机制实现的,所以上述有关引用绑定的一切也都适用于这些结构。

例如,文件目录a/b/c下有d.php,则在a目录下的的文件引入d的类时,应该是use
b/c或use /a/b/c;

global引用

当用global $var声明一个变量时实际上建立了一个到全局变量的引用。

global $var;
$var = & $GLOBALS['var']; // 与上一行代码是等价的。

四、注意点

$this

在一个对象的方法中,$this永远是调用它的对象的引用。

1、代码复用类Trait也符合命名空间的规范,即通过命名空间下Trait类不能重名;2、虽然PSR4规定了命名空间路径与文件路径需要相对应,但是运行php时命名空间路径与文件路径是没有任何关系的,例如a/b/c下的文件类d,命名空间可以写成a1/b1/c1/d;只不过现在的许多开源框架在实现类自动加载的时候把两者规范为一致,否则会出现类文件加载到了,但是命名空间却加载不到的情况。3、在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间AB内部调用CDe会被转换为ABCDe,对非限定名称的函数调用是在运行时解析的。例如对函数foo在当前命名空间中查找名为ABfoo尝试查找并调用全局。5、在命名空间内部对非限定名称或限定名称类的调用是在运行时解析的。下面是调用new
C的解析过程:new C在当前命名空间中查找ABC类。尝试自动装载类ABC。

php如何使用类

class myclass{
    //成员变量(公有访问控制)
    public $myvar;
    //构造函数
    function __construct($myvar){
        $this->myvar = $myvar;
    }
    //封装
    function setValue($myvar){
        $this->myvar = $myvar;
    }
    function getValue(){
        return $this->myvar;
    }
    //析构函数
    function __destruct(){
        unset($this->myvar);
    }
}
//类继承
class myextends extends myclass{
}
$myclass = new myextends("Moments");
echo $myclass->getValue();
  • 如何使用静态变量

class myclass{
    //使用静态变量
    public static $myvar = "Moments";
    public function myfun(){
        return self::$myvar;
    }
}
$myclass = new myclass();
echo myclass::$myvar;
echo $myclass->myfun();        
  • 如何使用抽象类

abstract class myclass{
    public $myvar;
    //强制要求子类定义之些方法
    abstract protected function setValue($myvar);
    //普通方法
    public function getValue(){
        return $this->myvar;
    }
}
class myextends extends myclass{
    function setValue($myvar){
        $this->myvar = $myvar;
    }
    function getValue(){
        return parent::getValue();
    }
}
$myclass = new myextends();
$myclass->setValue("Moments");
echo $myclass->getValue();      
  • 如何使用对象接口

#接口中定义的所有方法都必须是公有
interface myinterface{
    //接口不支持成员变量,可以使用常量
    const myconst = "myconst";
    //类中必须实现接口中定义的所有方法。
    public function setValue($myvar);
    public function getValue();
}
class myextends implements myinterface{
    public function setValue($myvar){
        $this->myvar = $myvar;
    }
    public function getValue(){
        return $this->myvar;
    }
}
$myclass = new myextends();
$myclass->setValue("Moments");
echo $myclass->getValue();
echo myinterface::myconst;

 

以上内容引用了PSR4文档地址:

衿华客

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《PHP网络编程技巧总结》、《PHP数组操作技巧大全》、《php字符串用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

php 教程

  1. PHP简介
  2. PHP安装
  3. PHP语法
  4. PHP数据类型
  5. PHP变量
  6. PHP运算符
  7. PHP流程控制
  8. PHP函数
  9. PHP类与对象
  10. PHP字符串
  11. PHP正则表达示
  12. PHP文件
  13. PHP图形图像
  14. PHPXML
  15. PHP会话缓存
  16. PHP异常处理
  17. PHP数据库
  18. PHP日期时间戳
  19. PHP代码风格规范

希望本文所述对大家PHP程序设计有所帮助。

server 环境

  1. ubuntu入门
  2. docker入门
  3. git入门
  4. iterm入门

frame 框架

  1. laravel入门
  2. dingo入门
  3. JWT入门
  4. Laravel框架关键技术解析
  5. laravel则修笔记
  6. rpc入门
  7. rabbitmq入门
  8. opencc多国语言
  9. laravel兄弟连笔记
  10. laravel进阶

case 实例

  1. php面试题笔记
  2. python图标提取
  3. 字幕乱码问题
  4. 支付宝接口调用
  5. laravel开发笔记

db 数据库

  1. elasticsearch入门
  2. 数据库操作
  3. 数据库设计
  4. redis入门

help

  • 帮助文档
  • 流程图帮助文档

发表评论

电子邮件地址不会被公开。 必填项已用*标注