PHP内部函数和闭包
2018-02-02 09:07:54 377
  • 收藏

    通常,您会听到熟悉其他语言的程序员抱怨PHP的内部函数方法。他们常常得出这样的结论:它们大多是在浪费时间,因为它们不是本地的,它们没有实现闭包,并且如果外部函数执行不止一次,就会导致错误。


    实际上,只要您了解它们的工作原理,它们就会非常有用,而没有它们,您的代码确实会非常混乱。


    当将它们与PHP 5.3.0中添加的匿名函数放在一起时,您所获得的东西几乎(但不完全)与其他语言所提供的相等。


    但是首先让我们看一下PHP函数的基础知识。 


    功能是全局的

    PHP函数很容易定义:


    function MyFunction()

    {

     instructions that make up the function

    }


    您可以包括参数和return语句。


    重要的一点是,以这种方式定义的任何函数都具有全局范围。可以从整个程序中的任何位置调用它,包括从另一个函数中甚至从类或类的实例中调用。


    例如,如果我们定义函数:


    function MyFunction()

    {

     echo("My Function");

    }


    然后可以在一个类中使用它:


    class MyClass

    {

     public function MyMethod()

     {

      MyFunction();

     }

    }


    以及何时调用该方法


    $MyObject=new MyClass();

    $MyObject->MyMethod();


    调用MyFunction。


    作为一个PHP程序员,这对于您来说似乎是完全正常的,但是大多数其他面向对象的语言甚至都不允许您在类之外定义函数,即所有函数都是方法,因此不会出现具有全局函数的想法。


    以这种方式使用函数不是一个好主意,即使可以合理地认为它可以为您创建的对象提供“辅助”函数。通常,类的功能应始终包含在类中,并且不能由全局实体使用。


    您可以说字符串函数是应该是全局的实用程序函数的示例,例如count_chars是一个全局函数,该函数返回字符串中的字符数,但这仅表明您没有足够的面向对象的指示。如果函数对字符串执行某些操作,即它是一个字符串操作,则它应该是字符串类的一部分。


    要查找应该具有全局性的令人信服的函数示例,您必须查看涉及多个类型的操作(该函数应属于哪个类),或者单个函数可以处理多种类型。通常使用泛型在完全面向对象的语言中处理多种类型,但是松散类型的语言(如PHP)仅允许您忽略类型问题并编写全局函数。它可以完成工作,并且避免在语言中引入复杂的想法。


    内部功能

    如果在函数内定义变量,则该变量在该函数中是局部的。您还可以在另一个函数中定义一个函数,从逻辑上讲,这也应该是局部变量,但要记住所有函数都是全局的规则。


    在PHP中,内部函数是全局的,因此其行为与在任何包含函数之外声明的行为相同。


    这意味着内部功能是无用的。


    因为它们是全局的,所以它们与以通常方式声明的函数具有相同的上下文,这又意味着它们无法支持其他语言提供的任何巧妙技巧,例如闭包。


    闭包是内部函数可以访问包含它的函数的局部变量的地方-即使外部函数不再存在。由于内部函数是全局函数,因此它们无权访问声明它们的函数的局部变量。同样,由于函数是全局函数,因此它们永远不会超出范围,因此永远不会被破坏。


    因此,PHP函数缺少使闭包成为可能和有用功能的两件事,而这两者都是由于函数是全局的。


     

     


    需要明确的是:内部函数的行为与在其包含函数之外被声明的行为完全相同。它无法访问其包含函数的局部变量,并且诸如闭包之类的概念根本不适用。 


    使用期限

    函数具有全局性这一事实意味着它们不会超出范围,这意味着它们永远不会被破坏。


    但这并不意味着每个函数都与其所包含的程序具有相同的生存期。


    您只要声明为程序文本的一部分的任何函数,就可以认为该函数在程序开始运行后就存在,并且一直存在到程序结束。但是,PHP是一种动态解释型语言,这意味着它可以使用自己的文本来执行操作,而其他语言则不能。


    例如,您可以有条件地声明一个函数:


    if($test) {

     function MyFunction()

     {

      echo("My Function");

     }

    }


     


    这将导致MyFunction在程序中不存在,直到执行if语句且条件为true为止。一旦发生这种情况,该功能就存在并继续存在,直到程序结束。


    您可以认为这是


    “该功能从PHP开始阅读以来就存在”。


    这是一种完全通用的机制,适用于其他PHP代码中函数的任何声明。


    请注意,由于无法在PHP中重新定义函数,因此这意味着声明该函数的任何代码只能执行一次-否则,必须确保该逻辑不会再次创建该函数。 


    它也适用于内部函数,这意味着在调用外部函数之前,内部函数不存在。这似乎比前面给出的条件示例奇怪得多,但实际上它是相同的原理。


    例如,如果定义两个函数,则一个在另一个内:


    function MyFunction()

    {

     echo("My Function");

     function MyInnerFunction()

     {

       echo('MyInnerFunction ');

     }

    }


    然后,如果仅调用MyInnerFunction(),它将失败。要使其正常工作,您首先必须调用外部函数,然后才存在内部函数。那是:


    MyFunction();

    MyInnerFunction();


    可以,但是一旦调用MyFunction,就无法再次调用它而不会产生错误。


    尝试多次创建函数的问题的解决方案是利用条件声明的思想。例如:


    function MyFunction()

    {

     echo("My Function");

     if(!function_exists("MyInnerFunction")){

      function MyInnerFunction()

      {

       echo('MyInnerFunction ');

      }

     }

    }


    现在,这种工作方式应该显而易见。if语句仅检查函数名称是否在全局范围内。如果确实如此,则不会再次声明该函数,并且不会发生错误。


    您应该始终将内部函数声明包含在if语句中-这样可以使它们更安全并且花费很少。


    现在我们到达了一个微妙的地步,但事实证明它具有实际意义。


    您可以从包含它的函数中调用内部函数吗?


    答案是肯定的,但只有在定义好之后。例如; 你不能使用


    function MyFunction()

    {

     echo("My Function");

     MyInnerFunction();

     if(!function_exists("MyInnerFunction")){

       function MyInnerFunction()

       {

        echo('MyInnerFunction ');

       }

     }

    }


     


    问题是,当您尝试调用MyInnerFunction时,尚未对其进行声明。但是,如果将呼叫移至if之后,则一切正常:


    function MyFunction()

    {

     echo("My Function");

     if(!function_exists("MyInnerFunction")){

       function MyInnerFunction()

       {

        echo('MyInnerFunction ');

       }

     }

     MyInnerFunction();

    }


     


    这很奇怪,需要一段时间才能习惯,但这是完全合乎逻辑的。


    当然,第二次调用MyFunction已经定义了内部函数,并且原则上您可以在任意位置调用内部函数-因为内部函数实际上是您希望的任何地方都是全局的!


    上一页:没有了 下一页:PHP重定向到另一个URL /网页脚本示例
    
    全部评论(0)