学习要点

  • 常用函数
  • 命名空间
  • 类的自动加载

常用函数

class_exists

作用:检查类是否已定义

语法格式:

bool class_exists ( string $class_name [, bool $autoload = true ] )

  

参数说明:

class_name:类名。名字的匹配是不分区大小写的。

autoload:是否默认调用 __autoload。

interface_exists

作用:检查接口是否已被定义

语法格式:

bool interface_exists ( string $interface_name [, bool $autoload = true ] )

参数说明: 

interface_name:接口名。

autoload:默认是否调用 __autoload。

method_exists

作用:检查类的方法是否存在

语法格式:

bool method_exists ( mixed $object , string $method_name )

  

参数说明:

object:对象示例或者类名。

method_name:方法名。

is_object

作用: 检测变量是否是一个对象。

语法格式:

bool is_object ( mixed $var )

如果 var 是一个 object 则返回 TRUE,否则返回 FALSE。

类似数据类型检测用法: is_bool()、is_int()、is_integer()、is_float()、is_string() 和 is_array()。

命名空间

官方文档对PHP命名空间的说明:

http://php.net/manual/zh/language.namespaces.php

简要

命名空间解决的问题:

  1. 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
  2. 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。

PHP 命名空间提供了一种将相关的类、函数和常量组合到一起的途径。

定义

语法格式

<?php
namespace MyProject;

语法说明:除了用于定义源文件编码方式的 declare 语句,所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前。

定义单个命名空间

<?php
namespace MyProject;

相同namesapce声明可以出现在多个文件中,用于将代码组织在一起。

定义子命名空间

与目录和文件的关系很象,PHP 命名空间也允许指定层次化的命名空间的名称。因此,命名空间的名字可以使用分层次的方式定义。

例如:声明分层次的单个命名空间

<?php
namespace MyProject\Application\Admin; const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ } ?>

  

命名空间基础用法

访问命名空间

使用命名空间之前,必须了解 PHP 是如何知道要使用哪一个命名空间中的元素的。

文件的的访问:

  1. 相对文件名形式如foo.txt。它会被解析为 currentdirectory/foo.txt,其中 currentdirectory 表示当前目录。因此如果当前目录是 /home/foo,则该文件名被解析为/home/foo/foo.txt
  2. 相对路径名形式如subdirectory/foo.txt。它会被解析为 currentdirectory/subdirectory/foo.txt
  3. 绝对路径名形式如/main/foo.txt。它会被解析为/main/foo.txt

同理,PHP命名空间中使用三种方式引入类。

  1. 非限定名称,或不包含前缀的类名称。例如 $a=new foo(); 或 foo::staticmethod();。如果当前命名空间是 currentnamespace,foo 将被解析为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元素逻辑上进行分类,来实现对类、函数和常量管理(无法管理变量)。

示例

<?php
namespace MyProject {
//定义常量
CONST E = 2.78; //定义函数
function getNameSpace()
{
echo __NAMESPACE__ . "\n";//输出命名空间命名
} //定义类
class MyClass
{
public function m()
{
echo __NAMESPACE__ . "," . __METHOD__ . "\n";//输出方法名称和命名空间名称
} }
} namespace MyProject2 {
//定义常量
CONST E = 2.78; //定义函数
function getNameSpace()
{
echo __NAMESPACE__ . "\n";//输出命名空间命名
} //定义类
class MyClass
{
public function m()
{
echo __NAMESPACE__ . "," . __METHOD__."\n";//输出方法名称和命名空间名称
}
}
} namespace MyProject3 {
CONST C = 888; function getNameSpace()
{
echo __NAMESPACE__ . "\n";//输出命名空间命名
} class MyClass
{
public function m()
{
echo __NAMESPACE__ . "," . __METHOD__."\n";//输出方法名称和命名空间名称
} } echo "访问全局变量不需要添加前缀:" . __NAMESPACE__ . "\n";
echo "访问当前命名空间的常量不需要添加前缀:" . C . "\n";
echo "访问当前空间函数:".getNameSpace()."\n"; $mc=new MyClass();//非限定名访问当前空间类
$mc->m(); use \MyProject2;
$mc2= new MyProject2\MyClass();//限定名访问MyProject2命名空间下的类
$mc2->m(); $mc3=new \MyProject\MyClass();//全限定名访问MyProject空间下的类
$mc3->m(); }

  

说明:

  1. 在同一个文件表示多个空间,空间的表示要保持一致:或者一起使用"{}"或者一起不使用。
  2. 访问当前空间的元素不需要添加前缀。
  3. 没有使用use引入其他命名空间,如果要使用该空间的元素,需要使用全限定名称访问。
  4. 使用use分为两种情况,一种是use空间:访问类需要使用非权限定名称;另一种是use到具体类,使用非限定名访问。

父空间和子空间之间的访问

通过全限定名和限定名的方式访问。

示例:

<?php
//子空间
namespace Admin\Home\Action; function m(){
echo __NAMESPACE__."\n";
} //父空间
namespace Admin\Home; function m(){
echo __NAMESPACE__."\n";
} m();//非限定名方式访问本空间函数(父空间函数)
\Admin\Home\Action\m();//全限定名称访问子空间函数
Action\m();//限定名方式访问子空间函数

  

非限定名称访问:访问当前空间元素。

限定名称访问:访问子空间元素。

全限定名称访问:访问任意一个空间元素。(子空间访问父空间元素)

动态变量访问命名空间

使用动态变量参数表示类、函数或者变量,必须使用完全限定名称(包括命名空间前缀的类名称)。

注意因为在动态的类名称、函数名称或常量名称中,限定名称和完全限定名称没有区别,因此其前导的反斜杠不是必要的。

示例:

<?php
//使用动态变量参数表示类、函数或者变量,必须使用完全限定名称(包括命名空间前缀的类名称)。
//注意因为在动态的类名称、函数名称或常量名称中,限定名称和完全限定名称没有区别,因此其前导的反斜杠不是必要的。
namespace example1 {
const constname = "global";
function m()
{
echo __FUNCTION__, "===\n";
} class MyClass
{
function __construct()
{
echo __METHOD__, "\n";
}
}
} namespace example2 {
//访问本空间下的元素代码略
$a = '\example1\MyClass';//注意:如果使用双引号,则需要使用双反斜杠
$b = "example1\\MyClass";
$obja = new $a();//动态类名
$objb = new $b(); $c="\\example1\\constname";
echo constant($c),"\n"; $d='example1\m';
$d();
}

  

命名空间的导入和别名

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

所有支持命名空间的PHP版本支持三种别名或导入方式:为类名称使用别名、为接口使用别名或为命名空间名称使用别名。PHP 5.6开始允许导入函数或常量或者为它们设置别名。

别名:use引入类导致两个空间类名冲突的时候,可以在引入类的时候为引入类起别名。

使用use关键字实现。

示例:

<?php

namespace Home\View {

    class MyClass
{
public function __construct()
{
echo __CLASS__;
}
}
}
namespace Admin\Controller {
use Home\View\MyClass as MC;
$obj = new MC();
}

  

注意:use语句后面的空间路径不可以使用前导反斜杠,因为use必须使用全限定名称导入命名空间,而不会根据当前文件的相对位置进行解析。

使用use导入多个命名空间,语法格式:

use 命名空间1,命名空间2,...命名空间n;

  

导入操作只影响非限定名称和限定名称。完全限定名称由于是确定的,故不受导入的影响。

问题:在A空间引入B空间文件,A和B空间有同样的函数,是如何运行的?

定义D05A.php

<?php
namespace A; function m(){
echo "A命名空间".__NAMESPACE__."\n";
}

  

定义D05B.php

namespace B;

function m(){
echo "B命名空间".__NAMESPACE__."\n";
} include "D05A.php";
m();//输出的结果是?输出B空间m函数
\A\m();//输出A空间m函数。

  

运行结果:

原因分析:无论是使用require还是include指令,在编译阶段没有把D05A.php文件载入到D05B.php文件。

如何访问加载空间中的元素?

使用完全限定访问。

全局空间的访问

如果没有定义命名空间,则表示全局空间元素。使用“\”访问。

示例代码:

D05A.php文件

<?php
function m(){
echo "A命名空间".__NAMESPACE__."\n";
}

  

D05B.php文件

<?php
namespace B; function m(){
echo "B命名空间".__NAMESPACE__."\n";
} require "D05A.php"; //m();//访问B空间m函数
\m();//访问全局命名空间

  

类的自动加载

示例目录结构如下图,在控制器和模型模块中,分别按照规范定义了相关类和命名空间。

类名规范:类名骆驼命名法则.class.php

空间命名规范:目录名\目录名\..

问题:假如需要在index.php中实例化模块中的类,在实例化的时候需要加载类文件。

如果项目规模增加,需要加载的类文件越来越多,如何解决?__autoload()函数能够解决吗?

function __autoload($className){
include $className.'.class.php';
}

  

如上__autoload()函数只能加载当前命名空间下的类文件,无法加载其他空间文件。

解决方案:自定义自动加载函数,并注册到PHP全局加载中。

定义Common类,注册自定义自动加载函数。

代码和说明如下:

<?php
namespace Core;
class Common
{
//定义静态自动加载函数
public static function myAutoLoad($className){
//完成由命名空间构成的类路径信息的类文件的加载
//例如:Application\Admin\Controller\AdminController
//问题:include等加载函数使用的是正斜杠路径,需要进行转换为:Application/Admin/Controller/AdminController.".class.php"
$path=str_replace("\\","/",$className);
$filePath=$path.".class.php";
if(file_exists($filePath)) {
include_once $filePath;
}else{
die("无法加载文件:".$filePath);
}
} //注册自动加载函数
public static function registerAutoLoad(){
spl_autoload_register("self::myAutoLoad");
} }

  

index.php文件中执行自动加载注册,并测试运行:

<?php
//require "Application/Admin/Controller/AdminController.class.php";
require "Core/Common.class.php";
\core\Common::registerAutoLoad(); //引入命名空间类实例化
use Application\Admin\Controller\AdminController;
new AdminController(); //实例化限定名类
new Application\Home\Model\HomeModel();

  

PHP20 PHP面向对象辅助的更多相关文章

  1. Javascript 面向对象编程(一):封装

    Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类). 那么,如果 ...

  2. Javascript面向对象(封装、继承)

    Javascript 面向对象编程(一):封装 作者:阮一峰 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程( ...

  3. .NET应用架构设计—面向对象分析与设计四色原型模式(彩色建模、领域无关模型)(概念版)

    阅读目录: 1.背景介绍 2.问自己,UML对你来说有意义吗?它帮助过你对系统进行分析.建模吗? 3.一直以来其实我们被一个缝隙隔开了,使我们对OOAD遥不可及 4.四色原型模式填补这个历史缝隙,让我 ...

  4. javascript面向对象(一):封装

    本文来自阮一峰 学习Javascript,最难的地方是什么? 我觉得,Object(对象)最难.因为Javascript的Object模型很独特,和其他语言都不一样,初学者不容易掌握. 下面就是我的学 ...

  5. 面向对象架构模式之:领域模型(Domain Model)

    一:面向对象设计中最简单的部分与最难的部分 如果说事务脚本是 面向过程 的,那么领域模型就是 面向对象 的.面向对象的一个很重要的点就是:“把事情交给最适合的类去做”,即:“你得在一个个领域类之间跳转 ...

  6. Javascript 面向对象编程初探(一)--- 封装

    Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类). 那么,如果 ...

  7. 从Prototype学习JavaScript面向对象编程

    概述 JavaScript是一种基于对象的编程语言.它是灵活的,既有面向过程(也就是面向函数)的编程,也有面向对象的编程.因此我称它是基于对象的编程语言. 对于JavaScript的面向过程的编程特性 ...

  8. 0021 Java学习笔记-面向对象-包、构造器

    封装 面向对象的三大特征: 封装 继承 多态 封装: 将对象的状态信息隐藏,不允许外部程序直接访问 通过该类提供的方法来访问和操作 有啥用: 隐藏类的实现细节 在方法中加入控制逻辑,限制对成员变量的不 ...

  9. 实验二 Java面向对象程序设计

    实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计 ...

随机推荐

  1. hdu5822 color

    首先考虑假如是树上的做法:考虑dp,f(i)表示对i的子树染色的方案数.用hash可以实现查询两棵子树是否相同.从而根据hash值排序分类,将相同的子树放在一类. (1)f(i)等于每一类的f(p)乘 ...

  2. hdoj5818【模拟】

    2016 Multi-University Training Contest 7 1010 思路: 我相信T的绝对是直接根据题目意思来了. 正确的一点小转变,比较一下那个队列小,然后把小的给大的,每次 ...

  3. poj1312dfs基础

    就是很简单的DFS-因为数据偏小,上去就是干了 #include <stdio.h> #include <string.h> #include <math.h> # ...

  4. Log2Net组件代码详解(附开源代码)

    上一篇,我们介绍了Log2Net的需求和整体框架,我们接下来介绍我们是如何用代码实现Log2Net组件的功能的. 一.整体介绍 Log2Net组件本身是一个Dll,供其他系统调用. 本部分由以下几部分 ...

  5. tomcat复习

    javaEE 服务器: java企业版服务器:是一个标准 BS/CS: 1> CS: client/Server 优点:易操作性比较高 缺点:客户端需要升级维护. 2> BS: Brows ...

  6. Ubuntu18 安装jdk8

    按照网上能找到的方法,添加仓库已经不行了,具体原因如下: I look up to the webupd8 site and it seems that the ppa was discontinue ...

  7. 统计Apache或nginx日志里访问次数最多的前十个IP

    1.根据访问IP统计UV awk '{print $1}' access.log|sort | uniq -c |wc -l 2.统计访问URL统计PV awk '{print $7}' access ...

  8. 点击a标签的子元素不跳转 ,阻止默认行为

  9. A.华华听月月唱歌

    链接:https://ac.nowcoder.com/acm/contest/392/A 题意: 月月唱歌超级好听的说!华华听说月月在某个网站发布了自己唱的歌曲,于是把完整的歌曲下载到了U盘里.然而华 ...

  10. April Fools Contest 2017 C

    Description DO YOU EXPECT ME TO FIND THIS OUT? WHAT BASE AND/XOR LANGUAGE INCLUDES string? DON'T BYT ...