资讯专栏INFORMATION COLUMN

PHP学习 Day 4 语言参考(下半篇)

WelliJhon / 2509人阅读

摘要:如果有此需要,同样要使用匿名函数。以上两点可以总结为函数对应于常量,匿名函数对应于变量。匿名函数生成类的实例类声明通过表明继承关系,不支持多重继承。覆盖方法时,参数必须保持一致,否则会抛出警告。

函数

函数具有全局作用域,可以定义在一个函数之内而在该函数之外调用。


function foo() { function bar() { echo "I don"t exist until foo() is called. "; } } /* 现在还不能调用bar()函数,因为它还不存在 */ foo(); /* 现在可以调用bar()函数了,因为foo()函数 的执行使得bar()函数变为已定义的函数 */ bar();

如果要保证定义在函数内部的函数外部不可用,需要使用匿名函数:


function foo() { $bar = function() { echo "inside"; }; }

函数无法重载,无法取消和重定义。如果有此需要,同样要使用匿名函数。

以上两点可以总结为:函数对应于常量,匿名函数对应于变量。

递归函数调用过百可能会使堆栈崩溃。

函数的默认参数只能用常量表达式定义,不能是变量、函数调用!

函数不能返回多个值。

从函数返回引用时,必须在函数声明和指派返回值时都使用引用运算符:

function &returns_reference()
{
    return $someref;
}

$newref =& returns_reference();

匿名函数访问闭包内的变量需要用use ($var)声明,只读访问。

PHP也支持类似Perlsh的函数定义,在定义时不指定参数,通过func_num_args()func_get_arg()func_get_args()处理应用函数时传入的参数。

函数的参数可以指定类型,例如对象(指定类的名字)、接口、数组、或者callable,但是不能是数字或字符串,Traits也不允许。(据说SVN里有支持数字、字符串的一个实现,但是最后PHP是否会支持这一特性仍然未定。)

匿名函数生成Closure类的实例:

boris> $lambda = function() { echo "hi"; };
 → object(Closure)(

)

class声明通过extends表明继承关系,不支持多重继承。

可以通过parent::访问被覆盖的方法或属性。

父类定义方法时声明final,则不可覆盖。(final还可用于声明类,final类不能被继承。)

覆盖方法时,参数必须保持一致,否则会抛出E_STRICT警告。

使用ClassName::class可以获取类的完全名称,对使用了命名空间的类尤其有用。

类的属性只能初始化为定值!

{
   // 错误的属性声明
   public $var1 = "hello " . "world";
   public $var2 = <<

类中可以定义__construct(),用于建立对象时的初始化工作。显式地销毁某个对象,或者对某个对象的所有引用都没删除时,会执行__destruct()

属性必须被定义为publicprotected(子类、父类可见)、private之一。

类中的方法同理,但是默认public

声明属性或方法为static,就可以不实例化而直接访问,例如通过::。静态属性不能通过对象来访问(但静态方法可以)。

abstract类不能被实例化。一旦有一个方法被声明为abstract,类就必须被声明为abstract。继承抽象类的时候,子类必须定义父类中的所有抽象方法,并且这些方法的访问控制不能比父类严格。

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

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

和抽象类相似的概念是接口,接口的特性是接口中定义的所有方法都必须是公有的。

interface a
{
    public function foo();
}

interface b extends a
{
    public function baz(Baz $baz);
}


class c implements b
{
    public function foo()
    {
    }

    public function baz(Baz $baz)
    {
    }
}

实现接口的类必须实现接口中定义的所有方法。

类可以实现多个接口,用逗号来分隔多个接口的名称。(实现多个接口时,接口中的方法不能有重名。)

接口中定义的常量不能被子类或子接口所覆盖。

使用trait可以水平组合功能:

trait Hello {
    public function sayHello() {
        echo "Hello ";
    }
}

trait World {
    public function sayWorld() {
        echo "World";
    }
}

class MyHelloWorld {
    use Hello, World;
    public function sayExclamationMark() {
        echo "!";
    }
}

trait不能实例化,优先级比类当前成员低,但比继承的成员高。

多个trait冲突时,使用insteadof指明使用哪一个方法,as将方法以其他名称引入。

class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
}

as还可用于修改访问控制:

class MyClass1 {
    use HelloWorld { sayHello as protected; }
}
class MyClass2 {
    use HelloWorld { sayHello as private myPrivateHello; }
}

trait可以互相引用:

trait HelloWorld {
    use Hello, World;
}

trait同样支持抽象方法:

trait Hello {
    public function sayHelloWorld() {
        echo "Hello".$this->getWorld();
    }
    abstract public function getWorld();
}

trait不能定义static 变量,trait定义的静态方法,使用trait的类可以用。

trait定义了属性之后,类不能定义同样名称的属性。

PHP的重载和别的语言不一样,它指动态地创建属性和方法。

属性:

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

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

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

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

方法:

在对象中调用一个不可访问方法时,__call() 会被调用。

用静态方式中调用一个不可访问方法时,__callStatic() 会被调用。

foreach可以遍历对象的所有可见属性。可以通过实现IteratorIteratorAggregate接口来指明如何遍历。

Traversable是一个抽象接口,可以用来检查是否可以被foreach遍历:

if( !is_array( $items ) && !$items instanceof Traversable )
        //Throw exception here

使用clone关键字可以复制一个对象,对象的所有属性是浅复制。如果定义了__clone()方法,那么复制完成会调用该方法,可用于修改属性的值。

==属性、属性值、类均同。===同一对象。

PHP 5.3.0 起支持了 late static bindings,绑定的方法会调用运行时(late)首先调用该方法的类,复用了static关键字。

class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // Here comes Late Static Bindings
    }
}

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

B::test(); //  B

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

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

魔术方法以__开头,除了上面提到的以外,还有:

__sleep()__wakeup(),分别对应于serialize()unserialize(),一个常用于提交未提交的数据,一个常用于执行初始化操作。

__toString() 方法用于一个类被当成字符串时应怎样回应。

__invoke() 当尝试以调用函数的方式调用一个对象时调用此方法。

__set_state(),用于 var_export() 导出类时。

如果类实现了Serializable接口,那么这个类就不再支持__sleep()__wakeup()

命名空间

类、函数、常量受命名空间的影响。

通过namespace声明,必须在所有代码(除declare编码语句)之前(包括非PHP代码)。

同一个命名空间的内容可以分割存放在不同文件中。

命名空间可以分层定义:

namespace MyProjectSubLevel;

可以在同一文件中定义多个命名空间,但是不推荐。如果实在要这么做,建议用大括号括起不同的命名空间。将全局的非命名空间代码和命名空间的代码组合时,必须加大括号。全局代码用不带名称的namespace语句声明。

常量__NAMESPACE__的值是包含当前命名空间名称的字符串。关键字namespace可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。

命名空间名称或类名称可以使用别名:

namespace foo;
use MyFullClassname as Another;

命名空间内部,用 表示该名称是全局空间中的名称。

异常处理

使用throwcatchtry语句。

function inverse($x) {
    if (!$x) {
        throw new Exception("Division by zero.");
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "
";
    echo inverse(0) . "
";
} catch (Exception $e) {
    echo "Caught exception: ",  $e->getMessage(), "
";
}

// Continue execution
echo "Hello World";

Exception 类

Exception {
  /* 属性 */
  protected string $message ;
  protected int $code ;
  protected string $file ;
  protected int $line ;
  /* 方法 */
  public __construct ([ string $message = "" [, int $code = 0 [, Exception $previous = NULL ]]] )
  final public string getMessage ( void )
  final public Exception getPrevious ( void )
  final public int getCode ( void )
  final public string getFile ( void )
  final public int getLine ( void )
  final public array getTrace ( void )
  final public string getTraceAsString ( void )
  public string __toString ( void )
  final private void __clone ( void )
生成器

通常只需用yield取代return

例如,用生成器重新实现低内存占用的range()函数:

function xrange($start, $limit, $step = 1) {
    if ($start < $limit) {
        if ($step <= 0) {
            throw new LogicException("Step must be +ve");
        }

        for ($i = $start; $i <= $limit; $i += $step) {
            yield $i;
        }
    } else {
        if ($step >= 0) {
            throw new LogicException("Step must be -ve");
        }

        for ($i = $start; $i >= $limit; $i += $step) {
            yield $i;
        }
    }
}

yield可以返回键值对:

function input_parser($input) {
    foreach (explode("
", $input) as $line) {
        $fields = explode(";", $line);
        $id = array_shift($fields);

        yield $id => $fields;
    }
}

生成器函数第一次调用时,会返回一个内部的Generator类(无法使用new实例化的类)的对象。类似于Iterator接口,但是多了一个send()方法。

Generator::send()允许迭代的时候插入值。插入的值会被yield语句返回,并且可以在生成器函数中使用。

相比实现一个Iterator类,生成器要简单地多,往往能提升代码可读性。

超全局变量

在一个脚本的全部作用域中都可用。

$GLOBALS

$_SERVER

$_GET

$_POST

$_FILES

$_COOKIE

$_SESSION

$_SESSION

$_REQUEST

$_ENV

其他预定义变量

$php_errormsg (仅在 php.ini 文件中的 track_errors 配置项开启的情况下可用。默认关闭。)

$argc

$argv

ArrayAccess接口

实现了这一接口的类可以当数组用。

ArrayAccess {
  /* Methods */
  abstract public boolean offsetExists ( mixed $offset )
  abstract public mixed offsetGet ( mixed $offset )
  abstract public void offsetSet ( mixed $offset , mixed $value )
  abstract public void offsetUnset ( mixed $offset )
}

Day 0 - 5 列表

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/20637.html

相关文章

  • PHP学习之路 目录

    这个系列就暂时告一段落了。这是一个目录。 Day 0 起步 Day 1 基本语法 Day 2 REPL 和 包管理 Day 3 语言参考 Day 4 语言参考(下半篇) Day 5 练手程序

    liaosilzu2007 评论0 收藏0
  • PHP学习 Day 3 语言参考

    摘要:扫下手册的语言参考。允许的强制转换有。错误控制置于表达式前时,忽略该表达式产生的错误信息。运行外部程序使用反引号,效果等同于函数。文件未找到时,给出错误,而仅仅给出警告。目标位置用目标名称加上冒号标记,必须位于同一文件和作用域。 扫下手册的语言参考。(函数以前) 类型 有boolean、integer、float、string、array等类型。 可以通过gettype函数查看类...

    sean 评论0 收藏0
  • PHP学习 Day 2 REPL 和 包管理

    摘要:包管理试用了,新一代的包管理器,感觉不错。习题答案习题见图书优惠活动,计算需要付的金额。文件读写函数有,表示追加,锁定文件,避免别的进程同时读写。 最新版 Debian Wheezy下的PHP是5.4的,day0时说图方便就装了5.4。但是看文档是5.5的,所以琢磨着还是用最新版算了。 Debian Wheezy有dotdeb.org提供php-5.5。安装很方便。 将下列内容加...

    microelec 评论0 收藏0
  • PHP学习 Day 0 起步

    摘要:记录一下学习的轨迹。起步推荐用最新的。内建服务器这年头大部分语言都支持这一出了。交互式的环境学习方便,推荐下家的是用写的。结尾可以省略,然后可以简写成,于是上面的可以简写成当然像这种一行的,用也成练习题感谢出题搭好环境,写出第一个。 记录一下学习的轨迹。 入门资料 对我而言好的入门资料要符合两个要求: 能够切实帮助以比较正的方式入门 薄 真没找到什么好的入门资料。没有《Di...

    Cruise_Chan 评论0 收藏0
  • 云计算下半场 哪些会成为关注点

    摘要:云计算从概念萌芽期如今正在成为基础设施的水和电。他们共同对云计算的下一步发展特点以及企业关注重点等问题进行了讨论。所以,在国内说云计算发展的下一个阶段似乎比下半场更加合适,那么下一个阶段将有哪些新的特点呢各位嘉宾也提出了自己的看法。 云计算可以说是近几年企业服务发展最快的领域之一,同时也是产业互联网发展的基础。云计算从概念萌芽期如今正在成为 IT 基础设施的水和电。12 月 21 日,几位云...

    Achilles 评论0 收藏0

发表评论

0条评论

WelliJhon

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<