PHP的命名空间使用详解

 更新时间:2016年11月25日 14:55  点击:1349
命名空间在php中创建一个命名空间需要使用namespace关键字了,这个是php7才有的关键字了,下面我们来看一篇PHP的命名空间使用详解.

PHP的命名空间(namespace)是php5.3之后才有的。这个概念在C#中已经很早就有了,php中的namespace其实和c#的概念是一样的。

为什么php中要使用namespace?

假设如果不使用namespace,那么每个类在一个项目中的名字就必须是固定的。因为php在new的时候不管是调用autoload还是调用已加载过的类,都存在一个类名对应的文件。所以在没有namespace的时候,我们会想各种命名规则来区分不同的类,比如project1_school1_class1_Student或者project2_school_class_Student。

引入namespace之后就可以将这个有效规避了,一个namespace就相当于对应一个文件路径,查找这个类的时候,就会去对应的文件路径查找类定义文件了。

注明:

本文提到的常量:PHP5.3开始const关键字可以用在类的外部。const和define都是用来声明常量的(它们的区别不详述),但是在命名空间里,define的作用是全局的,而const则作用于当前空间。我在文中提到的常量是指使用const声明的常量。


基础
命名空间将代码划分出不同的空间(区域),每个空间的常量、函数、类(为了偷懒,我下边都将它们称为元素)的名字互不影响, 这个有点类似我们常常提到的‘封装'的概念。

namespace的定义和使用

定义:

<?php
 
namespace Myproject;
或者

<?php
 
namespace Myproject {
 
}
使用:

<?php
 
use Myproject/School;
<?php
 
use Myproject/Schoolas School1;  // 别名
命名空间是运行时解析的。use就相当于一种声明,并不解析和加载。比如下面这个例子:

test.php

<?php
use my\name;
require_once("/home/yejianfeng/handcode/test/namespace1.php");
$a =new my\name\A();
$a->Print1();
namespace1.php

<?php
namespace my\name;
class A {
        public function Print1(){
                echo 11;
        }
}

虽然require_once在use下面,也是可以正常运行的,因为程序只有在new my\name\A()的时候才去加载命名空间my\name

全局类和命名空间类

如果要new一个全局类使用 new \A()

如果要new一个命名空间类,使用new my\namespace\A()

命名空间的顺序

自从有了命名空间之后,最容易出错的该是使用类的时候,这个类的寻找路径是什么样的了。

如果能弄清楚manual中的这个例子就能全部弄清楚寻找顺序了。

<?php
namespace A;
use B\D, C\Eas F;
 
// 函数调用
 
foo();      // 首先尝试调用定义在命名空间"A"中的函数foo()
            // 再尝试调用全局函数 "foo"
 
\foo();     // 调用全局空间函数 "foo"
 
my\foo();   // 调用定义在命名空间"A\my"中函数 "foo"
 
F();        // 首先尝试调用定义在命名空间"A"中的函数 "F"
            // 再尝试调用全局函数 "F"
 
// 类引用
 
new B();   // 创建命名空间 "A" 中定义的类 "B" 的一个对象
            // 如果未找到,则尝试自动装载类 "A\B"
 
new D();   // 使用导入规则,创建命名空间 "B" 中定义的类 "D" 的一个对象
            // 如果未找到,则尝试自动装载类 "B\D"
 
new F();   // 使用导入规则,创建命名空间 "C" 中定义的类 "E" 的一个对象
            // 如果未找到,则尝试自动装载类 "C\E"
 
new \B();  // 创建定义在全局空间中的类 "B" 的一个对象
            // 如果未发现,则尝试自动装载类 "B"
 
new \D();  // 创建定义在全局空间中的类 "D" 的一个对象
            // 如果未发现,则尝试自动装载类 "D"
 
new \F();  // 创建定义在全局空间中的类 "F" 的一个对象
            // 如果未发现,则尝试自动装载类 "F"
 
// 调用另一个命名空间中的静态方法或命名空间函数
 
B\foo();    // 调用命名空间 "A\B" 中函数 "foo"
 
B::foo();   // 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法
            // 如果未找到类 "A\B" ,则尝试自动装载类 "A\B"
 
D::foo();   // 使用导入规则,调用命名空间 "B" 中定义的类 "D" 的 "foo" 方法
            // 如果类 "B\D" 未找到,则尝试自动装载类 "B\D"
 
\B\foo();   // 调用命名空间 "B" 中的函数 "foo"
 
\B::foo();  // 调用全局空间中的类 "B" 的 "foo" 方法
            // 如果类 "B" 未找到,则尝试自动装载类 "B"
 
// 当前命名空间中的静态方法或函数
 
A\B::foo();   // 调用命名空间 "A\A" 中定义的类 "B" 的 "foo" 方法
              // 如果类 "A\A\B" 未找到,则尝试自动装载类 "A\A\B"
 
\A\B::foo();  // 调用命名空间 "A\B" 中定义的类 "B" 的 "foo" 方法
              // 如果类 "A\B" 未找到,则尝试自动装载类 "A\B"
?>

创建一个命名空间需要使用namespace关键字,这样:

 

<?php
 

//创建一个名为'Article'的命名空间
namespace Article;

?>


要注意的是,当前脚本文件的第一个命名空间前面不能有任何代码,下面的写法都是错误的:

 

//例一
//在脚本前面写了一些逻辑代码
 

<?php

$path = "/";

class Comment { }

namespace Article;

?>

 

//例二
//在脚本前面输出了一些字符

<html></html>
<?php

namespace Article;

?>


为什么要说第一个命名空间呢?因为同一脚本文件中可以创建多个命名空间。

 

下面我创建了两个命名空间,顺便为这两个空间各自添加了一个Comment类元素:

 

<?php
 

//创建一个名为'Article'的命名空间
namespace Article;

//此Comment属于Article空间的元素
class Comment { }


//创建一个名为'MessageBoard'的命名空间
namespace MessageBoard;

//此Comment属于MessageBoard空间的元素
class Comment { }
?>


在不同空间之间不可以直接调用其它元素,需要使用命名空间的语法:

 

<?php
 

namespace Article;

class Comment { }


namespace MessageBoard;

class Comment { }

//调用当前空间(MessageBoard)的Comment类
$comment = new Comment();

//调用Article空间的Comment类
$article_comment = new \Article\Comment();

?>


可以看到,在MessageBoard空间中调用article空间里的Comment类时,使用了一种像文件路径的语法: \空间名\元素名

 

除了类之外,对函数和常量的用法是一样的,下面我为两个空间创建了新的元素,并在MessageBoard空间中输出了它们的值。

 

<?php
 

namespace Article;

const PATH = '/article';

function getCommentTotal() {
    return 100;
}

class Comment { }


namespace MessageBoard;

const PATH = '/message_board';

function getCommentTotal() {
    return 300;
}

class Comment { }

//调用当前空间的常量、函数和类
echo PATH; ///message_board
echo getCommentTotal(); //300
$comment = new Comment();

//调用Article空间的常量、函数和类
echo \Article\PATH; ///article
echo \Article\getCommentTotal(); //100
$article_comment = new \Article\Comment();

?>


然后我的确得到了Article空间的元素数据。

 


子空间
命名空间的调用语法像文件路径一样是有道理的,它允许我们自定义子空间来描述各个空间之间的关系。

抱歉我忘了说,article和message board这两个模块其实都是处于同一个blog项目内。如果用命名空间来表达它们的关系,是这样:

 

<?php
 

//我用这样的命名空间表示处于blog下的article模块
namespace Blog\Article;

class Comment { }


//我用这样的命名空间表示处于blog下的message board模块
namespace Blog\MessageBoard;

class Comment { }

//调用当前空间的类
$comment = new Comment();

//调用Blog\Article空间的类
$article_comment = new \Blog\Article\Comment();

?>


而且,子空间还可以定义很多层次,比如说 Blog\Article\Archives\Date

 


公共空间
我有一个common_inc.php脚本文件,里面有一些好用的函数和类:

 

<?php
 

function getIP() { }

class FilterXSS { }

?>


在一个命名空间里引入这个脚本,脚本里的元素不会归属到这个命名空间。如果这个脚本里没有定义其它命名空间,它的元素就始终处于公共空间中:

 

<?php
 

namespace Blog\Article;

//引入脚本文件
include './common_inc.php';

$filter_XSS = new FilterXSS(); //出现致命错误:找不到Blog\Article\FilterXSS类

$filter_XSS = new \FilterXSS(); //正确

?>


调用公共空间的方式是直接在元素名称前加 \ 就可以了,否则PHP解析器会认为我想调用当前空间下的元素。除了自定义的元素,还包括PHP自带的元素,都属于公共空间。

 

要提一下,其实公共空间的函数和常量不用加 \ 也可以正常调用(不明白PHP为什么要这样做),但是为了正确区分元素,还是建议调用函数的时候加上 \


名称术语
在说别名和导入之前,需要知道关于空间三种名称的术语,以及PHP是怎样解析它们的。官方文档说得非常好,我就直接拿来套了。

1.非限定名称,或不包含前缀的类名称,例如 $comment = new Comment();。如果当前命名空间是Blog\Article,Comment将被解析为Blog\Article\Comment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。

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

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

其实可以把这三种名称类比为文件名(例如 comment.php)、相对路径名(例如 ./article/comment.php)、绝对路径名(例如 /blog/article/comment.php),这样可能会更容易理解。

我用了几个示例来表示它们:

 

<?php
 

//创建空间Blog
namespace Blog;

class Comment { }

//非限定名称,表示当前Blog空间
//这个调用将被解析成 Blog\Comment();
$blog_comment = new Comment();

//限定名称,表示相对于Blog空间
//这个调用将被解析成 Blog\Article\Comment();
$article_comment = new Article\Comment(); //类前面没有反斜杆\

//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 Blog\Comment();
$article_comment = new \Blog\Comment(); //类前面有反斜杆\

//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 Blog\Article\Comment();
$article_comment = new \Blog\Article\Comment(); //类前面有反斜杆\


//创建Blog的子空间Article
namespace Blog\Article;

class Comment { }

?>


其实之前我就一直在使用非限定名称和完全限定名称,现在它们终于可以叫出它们的名称了。

 


别名和导入
别名和导入可以看作是调用命名空间元素的一种快捷方式。PHP并不支持导入函数或常量。

它们都是通过使用use操作符来实现:

 

<?php
 

namespace Blog\Article;

class Comment { }


//创建一个BBS空间(我有打算开个论坛)
namespace BBS;

//导入一个命名空间
use Blog\Article;
//导入命名空间后可使用限定名称调用元素
$article_comment = new Article\Comment();

//为命名空间使用别名
use Blog\Article as Arte;
//使用别名代替空间名
$article_comment = new Arte\Comment();

//导入一个类
use Blog\Article\Comment;
//导入类后可使用非限定名称调用元素
$article_comment = new Comment();

//为类使用别名
use Blog\Article\Comment as Comt;
//使用别名代替空间名
$article_comment = new Comt();

?>


我注意到,如果导入元素的时候,当前空间有相同的名字元素将会怎样?显然结果会发生致命错误。

 

例:

 

<?php
 

namespace Blog\Article;

class Comment { }


namespace BBS;

class Comment { }

Class Comt { }


//导入一个类
use Blog\Article\Comment;
$article_comment = new Comment(); //与当前空间的Comment发生冲突,程序产生致命错误

//为类使用别名
use Blog\Article\Comment as Comt;
$article_comment = new Comt(); //与当前空间的Comt发生冲突,程序产生致命错误

?>


动态调用
PHP提供了namespace关键字和__NAMESPACE__魔法常量动态的访问元素,__NAMESPACE__可以通过组合字符串的形式来动态访问:

 

<?php
 

namespace Blog\Article;

const PATH = '/Blog/article';

class Comment { }


//namespace关键字表示当前空间
echo namespace\PATH; ///Blog/article
$comment = new namespace\Comment();

//魔法常量__NAMESPACE__的值是当前空间名称
echo __NAMESPACE__; //Blog\Article
//可以组合成字符串并调用
$comment_class_name = __NAMESPACE__ . '\Comment';
$comment = new $comment_class_name();

?>


字符串形式调用问题

上面的动态调用的例子中,我们看到了字符串形式的动态调用方式,如果要使用这种方式要注意两个问题。

 

1. 使用双引号的时候特殊字符可能被转义

 

<?php
 

namespace Blog\Article;

class name { }

//我是想调用Blog\Article\name
$class_name = __NAMESPACE__ . "\name"; //但是\n将被转义为换行符

$name = new $class_name(); //发生致命错误

?>


2. 不会认为是限定名称

 

PHP在编译脚本的时候就确定了元素所在的空间,以及导入的情况。而在解析脚本时字符串形式调用只能认为是非限定名称和完全限定名称,而永远不可能是限定名称。

 

<?php
 

namespace Blog;

//导入Common类
use Blog\Article\Common;
//我想使用非限定名称调用Blog\Article\Common
$common_class_name = 'Common';
//实际会被当作非限定名称,也就表示当前空间的Common类,但我当前类没有创建Common类
$common = new $common_class_name(); //发生致命错误:Common类不存在

//我想使用限定名称调用Blog\Article\Common
$common_class_name = 'Article\Common';
//实际会被当作完全限定名称,也就表示Article空间下的Common类,但我下面只定义了Blog\Article空间而不是Article空间
$common = new $common_class_name(); //发生致命错误:Article\Common类不存在


namespace Blog\Article;

class Common { }

?>


总结
我对PHP的命名空间刚刚接触,也不能随便给一些没有实践的建议。我个人认为命名空间的作用和功能都很强大,如果要写插件或者通用库的时候再也不用担心重名问题。不过如果项目进行到一定程度,要通过增加命名空间去解决重名问题,我觉得工作量不会比重构名字少。也不得不承认它的语法会对项目增加一定的复杂度,因此从项目一开始的时候就应该很好的规划它,并制定一个命名规范。

数组在php中应用非常的多了在我们找工作时可能数组试题也多在学习中也就到比较多,这里给各位整理了大量的关于php数组的例子,有兴趣的和小编来看这篇php入门数组的使用到面试题文章。


1.数组的概念

  数组就是一个用来存储一系列变量值的命名区域。

  每个数组元素有一个相关的索引(也成为关键字),它可以用来访问元素。

  PHP允许间隔性地使用数字或字符串作为数组的索引。

2.数字索引数组

  2.1 数字索引数组的初始化

$products = array(‘Tires’,’Oil’,’Spark Plugs’);
如果需要将按升序排列的数字保存在一个数组中,可以使用range()函数自动创建这个数组。

  创建一个1-10的数字数组:

$numbers = range(1,10);
可选的第三个参数允许设定值之间的步幅。

  创建一个1-10之间的奇数数组:

$odds = range(1,10,2);
2.2 访问数组的内容

  默认情况下,0元素是数组的第一个元素,使用$products[0]、$products[1]、$products[2],就可以使用数组$products的内容了。

  除了访问,数组的内容可以修改和添加:

$products[3] = ‘Fuses’;
像PHP的其他变量一样,数组不需要预先初始化或创建。在第一次使用它们的时候,它们会自动创建。

  如下代码创建了一个与前面使用array()语句创建的$products数组相同的数组:

$products[0] = ‘Tires’;

$products[1] = ‘Oil’;

$products[2] = ‘Spark Plugs’;
数组的大小将根据所增加的元素多少动态地变化。

  2.3 使用循环访问数组

  就是遍历数组:

foreach($products as $current){

    echo $current.” “;

}
以上代码将依次保存$current变量中的每一个元素并且打印它们。

 

3.使用不同索引的数组

  在上面的$products数组中,允许PHP为每个元素指定一个默认的索引。这就意味着,所添加的第一个元素为元素0,第二个元素为1等。PHP还支持关联数组。

  3.1 初始化关联数组

  如下所示的代码可以创建一个以产品名称为关键字、以价格作为值的关联数组:

$prices = array(‘Tires’=>100,’Oil’=>10,’Spark Plugs’=>4);

  3.2 使用循环语句

  因为关联数组的索引不是数字,因此无法使用for循环语句对数组进行操作。但是可以使用foreach循环或list()和each()结构。

  当使用foreach循环语句对关联数组进行操作时,可以按如下方式使用关键字:

foreach($prices as $key => $value){

    echo $key.” - ”.$value.”<br />”;

}
如下所示的代码将使用each()结构打印$prices数组的内容。


while($element = each($prices)){

    echo $element[‘key’];

    echo “ - ”;

    echo $element[‘value’];

    echo “<br />”;

}

  在这段代码中,变量$element是一个数组。当调用each()时,它将返回一个带有4个数值和4个指向数组位置的索引的数组。位置key和0包含了当前元素的关键字,而位置value和1包含了当前元素的值。

  除了以上两种方式,函数list()可以用来将一个数组分解为一系列的值。

while(list($product,$price) = each($prices)){

    echo “$product - $price<br />”;
   
}
这个看起来挺高大上,使用each()从$prices数组中取出当前元素,并且将它作为数组返回,然后再指向下一个元素。还使用list()将从each()返回的数组中所包含0、1两个元素变为两个名为$product和$price的新变量。

  三种输出方式的结果相同:

 

  注意,当使用each()函数时,数组将记录当前元素。如果希望在相同的脚本中两次使用该数组,就必须使用函数reset()将当前元素重新设置到数组开始处。要再次遍历该数组,可以使用以下代码:

reset($prices);

while( list( $product, $price ) = each( $prices ))

echo “$product - $price<br />”;
以上代码可以将当前元素重新设置到数组开始处,因此允许再次遍历数组。

 

4.数组操作符

  其中联合操作符(+)尝试将$b中的元素添加到$a的末尾。如果$b中的元素与$a中的一些元素具有相同的索引,它们将不会被添加。即$a中的元素将不会被覆盖。

 

5.多维数组

  5.1 二维数组

$products = array( array( ‘TIR’, ‘Tires’, 100 ),

array( ‘OIL’, ‘Oil’, 10 ),

array( ‘SPK’, ‘Spark Plugs’, 4 ));
可以使用双重for循环来访问每个元素:


for($row = 0; $row < 3; $row++){

    for($column = 0; $column < 3; $column++){

        echo ‘|’.$products[$row][$column];

    }

    echo ‘|<br />’;

}

 

  可以使用列名称来代替数字。要保存产品的相同集合,可以使用如下代码:


$products = array( array( ‘Code’=>’TIR’,

        ‘Description’=>’Tires’,

        ‘Price’=>100

    ),

    array( ‘Code’=> ‘OIL’,

        ‘Description’=>’Oil’,

        ‘Price’=>10

    ),

    array(‘Code’=>’SPK’,

        ‘Decription’=>’Spark Plugs’,

        ‘Price’=>4

    )

 );           

   如果希望检索单个值,那么使用这个数组会容易得多。 使用描述性索引,不需要记住某个元素是存放在[x][y]位置的。使用一对有意义的行和列的名称作为索引可以使你很容易找到所需的数据。

  描述性索引的遍历:


for( $row = 0; $row < 3; $row++ ){

    while( list( $key, $value ) =each( $products[$row] ) ){

        echo “|$value”;

    }

    echo ‘|<br />’;

}

 

  5.2 三维数组

  三维数组是一个包含了数组的数组的数组。


$categories = array(

    array(

        array('CAR_TIR','Tires',100),

        array('CAR_OIL','Oil',10),

       array('CAR_SPK','Spark Plugs',4)

    ),

    array(

        array('VAN_TIR','Tires',120),

        array('VAN_OIL','Oil',12),

        array('VAN_SPK','Spark Plugs',5)

    ),

    array(

        array('TRK_TIR','Tires',150),

        array('TRK_OLL','Oil',15),

        array('TRK_SPK','Spark Plugs',6)

    )

);           

  遍历:


for($layer = 0;$layer < 3;$layer++){

    echo "Layer $layer<br />";

    for($row = 0;$row < 3;$row++){

        for($column = 0;$column < 3;$column++){

            echo '|'.$categories[$layer][$row][$column];

        }

        echo '|<br />';

    }

}

 

  根据创建多维数组的方法,可以创建四维、五维或六维数组。感兴趣可以试下。

 

6.数组排序

  6.1 使用sort()函数

  sort()函数可以将数组按字母升序进行排序:


$products = array('LiLei','HanMeimei','Wo');

    sort($products);

    foreach ($products as $key) {

    echo $key." ";

}

 

  还可以按数字顺序进行排序。需要注意的是,sort()函数是区分大小写的。所有大写字母都在小写字母前面。

  第二个参数可选,可指定排序类型:SORT_REGULAR(默认值)、SORT_NUMERIC或SORT_STRING。

  6.2 使用asort()函数和ksort()函数对关联数组排序

  如果用关联数组存储各个项目和它们的价格,就需要用不同的排序函数使关键字和值在排序时仍然保持一致。

  如下创建一个包含3个产品和价格的数组:

$prices = array('Tires'=>100,'Oil'=>10,'Spark Plugs'=>4);
函数asort()根据数组的每个元素值进行排序:


asort($prices);

while(list($product,$price) = each($prices)){

    echo "$product - $price<br />";

}

 

  而函数ksort()则是根据数组的每个关键字进行排序:


ksort($prices);

while(list($product,$price) = each($prices)){

    echo "$product - $price<br />";

}

 

  6.3 反向排序

  即降序排序,与sort()、asort()、ksort()分别对应的是rsort()、arsort()、krsort()。

 

7.多维数组的排序

  7.1 用户定义排序


$products = array(

    array( 'TIR', 'Tires', 100 ),

    array( 'OIL', 'Oil', 10 ),

    array( 'SPK', 'Spark Plugs', 4 )

);

  自定义排序需要用函数usort()告诉PHP如何比较各个元素。为此需要编写自己的比较函数。

  如下所示对订单数组中的第二列按字母进行排序:


function compare($x, $y){

    if($x[1] == $y[1]){

        return 0;

    }

    else if($x[1] < $y[1]){

        return -1;

    }

    else{

        return 1;

    }

}

usort($products,'compare');

for($row = 0; $row < 3; $row++){

    for($column = 0; $column < 3; $column++){

        echo '|'.$products[$row][$column];

    }

    echo '|<br />';

}   

 

  为了能够被usort()函数使用,compare()函数必须比较$x和$y。如果$x等于$y,该函数必须返回0,如果$x小于$y,该函数必须返回负数,大于则返回正数。最后一句调用了内置函数usort(),该函数使用的参数分别是希望保存的数组($products)和比较函数的名称(compare())。

  如果要让数组按另一种顺序存储,只要编写一个不同的比较函数。

  usort()中的“u”代表“user”,因为这个函数要求传入用户定义的比较函数。

  7.2 反向用户排序

  用户定义的排序没有反向变体,但可以对一个多维数组进行反向排序。由于用户应该提供比较函数,因此可以编写一个能够返回相反值的比较函数:


function reverse_compare($x, $y){

  if($x[2] == $y[2]){

    return 0;

  }

  else if($x[1] < $y[1]){

    return 1;

  }

  else{

    return -1;

  }

}

 

8.对数组进行重新排序

  shuffle()函数:将数组各元素进行随机排序。

  array_reverse()函数:给出一个原来数组的反向排序。

 

9.从文件载入数组

  当前的订单文件:

 


<?php
//create short variable name
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];

$orders= file("$DOCUMENT_ROOT/orders.txt");

$number_of_orders = count($orders);
if ($number_of_orders == 0) {
  echo "<p><strong>No orders pending.
       Please try again later.</strong></p>";
}

for ($i=0; $i<$number_of_orders; $i++) {
  echo $orders[$i]."<br />";
}
?>

 

  还可以将订单中的每个区段载入到单独的数组元素中,从而可以分开处理每个区段或将它们更好地格式化。

  用PHP分离、格式化显示订单内容:

 


<?php
  //create short variable name
  $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];
?>
<html>
<head>
  <title>Bob's Auto Parts - Customer Orders</title>
</head>
<body>
<h1>Bob's Auto Parts</h1>
<h2>Customer Orders</h2>
<?php
  //Read in the entire file.
  //Each order becomes an element in the array
  $orders= file("$DOCUMENT_ROOT/orders.txt");

  // count the number of orders in the array
  $number_of_orders = count($orders);

  if ($number_of_orders == 0) {
    echo "<p><strong>No orders pending.
          Please try again later.</strong></p>";
  }

  echo "<table border=\"1\">\n";
  echo "<tr><th bgcolor=\"#CCCCFF\">Order Date</th>
            <th bgcolor=\"#CCCCFF\">Tires</th>
            <th bgcolor=\"#CCCCFF\">Oil</th>
            <th bgcolor=\"#CCCCFF\">Spark Plugs</th>
            <th bgcolor=\"#CCCCFF\">Total</th>
            <th bgcolor=\"#CCCCFF\">Address</th>
         <tr>";

  for ($i=0; $i<$number_of_orders; $i++) {
    //split up each line
    $line = explode("\t", $orders[$i]);

    // keep only the number of items ordered
    $line[1] = intval($line[1]);
    $line[2] = intval($line[2]);
    $line[3] = intval($line[3]);

    // output each order
    echo "<tr>
             <td>".$line[0]."</td>
             <td align=\"right\">".$line[1]."</td>
             <td align=\"right\">".$line[2]."</td>
             <td align=\"right\">".$line[3]."</td>
             <td align=\"right\">".$line[4]."</td>
             <td>".$line[5]."</td>
          </tr>";
  }

  echo "</table>";
?>
</body>
</html>

 

  这里使用了explode()函数来分隔每行,这样在开始打印前就可以再做一些处理与格式化。在上一篇中,保存数据的时候使用了制表符作为定界符,因此,将按如下方式调用:

explode(“\t”,$orders[$i]);
可以使用许多方法从字符串中提取数字。这里使用了intval()函数,可以将一个字符串转化成一个整数。

 

10.执行其他数组操作

  10.1 在数组中浏览:each()、current()、reset()、end()、next()、pos()和prev()

  如果创建一个新数组,那么当前指针就将被初始化,并指向数组的第一个元素。

  调用current($array_name)将返回第一个元素。

  调用next()或each()将使指针前移一个元素。其中调用each($array_name)会在指针前移一个位置之前返回当前元素。而调用next($array_name)先将指针前移,然后再返回新的当前元素。

  reset()函数将返回指向数组第一个元素的指针。

  end()函数将返回指向数组最后一个元素的指针。

  prec()函数将当前指针回移一个位置然后再返回新的当前元素。可使用end()和prev()进行反向遍历:


$array = array(7,8,9);

$value = end($array);

while($value){

  echo "$value<br />";

  $value = prev($array);

}

 

  10.2 对数组的每一个元素应用任何函数:array_walk()

  array_walk()函数可以以相同方式使用或者修改数组中的每一个元素。

bool array_walk(array arr,string func,[mixed userdata])
array_walk()的第一个参数是需要处理的数组,第二个参数是用户自定义并且将作用于数组中每个元素的函数。

  第三个参数可以作为一个参数传递给自己的函数,可选。

  10.3 统计数组元素的个数:count()、sizeof()和array_count_values()

  count()函数和sizeof()函数都可以返回数组元素的个数。

  调用array_count_values($array)将会统计每个特定的值在数组$array中出现过的次数(数组的基数集)。这个函数将返回一个包含频率表的关联数组。该数组包括关键字以及对应的出现次数。

10.4 将数组转换成标量变量:extract()

  函数extract()的作用是通过一个数组创建一系列的标量变量,这些变量的名称必须是数组中关键字的名称,而变量值则是数组中的值。

  extract()函数具有两个可选参数:extract_type和prefix。变量extract_type将告诉extract()函数将如何处理冲突。

  两个最常用的选项是EXTR_OVERWRITE(默认)和EXTR_PREFIX_ALL。

$array = array('key1'=>'value1','key2'=>'value2','key3'=>'value3');

extract($array,EXTR_PREFIX_ALL,'my_prefix');

echo "$my_prefix_key1 $my_prefix_key2 $my_prefix_key3";


可能你已经注意到了,extract()的关键字必须是一个有效的变量名称才行,以数字开始或包含空格的关键字将被跳过。

php常用数组函数小结


1.将数组的键名全部转换成小写和大写的函数是什么? 答:array_change_key_case($array [,CASE_LOWER|CASE_UPPER])

2.创建一个数组,用一个数组的值作为其键名,另一个数组的值作为其值的函数是什么? 答: array  array_combine (  array  $keys  ,  array  $values  )

3.统计数组中所有的值出现的次数的函数是什么? 答: array  array_count_values (  array  $input  )

4.返回数组中部分的或所有的键名的函数是什么? 答:array array_key($array [,$search_value [,true|false]])

5.将回调函数作用到给定数组的单元上的函数是什么? 答: array  array_map (  callable  $callback  ,  array  $arr1  [,  array  $...  ] )

6.合并一个或多个数组的函数是什么? 答: array  array_merge (  array  $array1  [,  array  $...  ] )

7.将数组最后一个元素弹出的函数是什么? 答: mixed  array_pop (  array  &$array  )

8.将一个或多个单元压入数组的末尾(入栈)的函数是什么? 答: int  array_push (  array  &$array  ,  mixed  $var  [,  mixed  $...  ] )

9.从数组中随机取出一个或多个单元的函数是什么? 答: mixed  array_rand (  array  $input  [,  int  $num_req  = 1 ] )

10.返回一个单元顺序相反的数组的函数是什么? 答: array  array_reverse (  array  $array  [,  bool  $preserve_keys  = false ] )

11.在数组中搜索给定的值,如果成功则返回相应的键名的函数是什么? 答: array_search (  mixed  $needle  ,  array  $haystack  [, $strict  = false ] )

12.将数组开头的单元移出数组的函数是什么? 答: mixed  array_shift (  array  &$array  )

13.移除数组中重复的值的函数是什么? 答: array  array_unique (  array  $array  [,  int  $sort_flags  = SORT_STRING ] )

14.在数组开头插入一个或多个单元的函数是什么? 答: int  array_unshift (  array  &$array  ,  mixed  $var  [,  mixed  $...  ] )

15.返回数组中所有的值的函数是什么? 答: array  array_values (  array  $input  )

16.对数组进行逆向排序并保持索引关系的函数是什么? 答: bool  arsort (  array  &$array  [,  int  $sort_flags  = SORT_REGULAR ] )

17.对数组进行正向排序并保持索引关系的函数是射门? 答: bool  asort (  array  &$array  [,  int  $sort_flags  = SORT_REGULAR ] )

18.返回数组中当前的键/值对并将数组指针向前移动一步的函数是什么? 答: array  each (  array  &$array  ),例如:while(list($key,$value)=each($array)){}

19.对数组按照键名逆向排序的函数是什么? 答: bool  krsort (  array  &$array  [,  int  $sort_flags  = SORT_REGULAR ] )

20.对数组按照键名正向排序的函数是什么? 答: bool  ksort (  array  &$array  [,  int  $sort_flags  = SORT_REGULAR ] )

21.  对数组逆向排序的函数是什么? 答: bool  rsort (  array  &$array  [,  int   = SORT_REGULAR ] )

22.对数组正向排序的函数是什么? 答: bool  sort (  array   [,  int   = SORT_REGULAR ] )

23.将数组打乱的函数是什么? 答: bool  shuffle (  array   )

24. count() 的别名函数是什么? 答:sizeof()


非数组,也非NULL,通通返回1

<?php
$arr=array('春','夏','秋','冬');
echo count($arr);//4
echo '<br/>';

$str='false';
echo count($str);//1
echo '<br/>';

$res=null;
echo count($res);//0
echo "<br/>";

$arr=array('春','夏','秋','冬',array('a','b','c'));
echo count($arr),'<br/>';//5
echo count($arr,1),'<br/>';//第2个参数为1时,代表递归的来计算数组的单元个数

$arr=array('春','夏','秋','冬',array('a',array('b','c')));
echo count($arr,1),'<br/>';
?>
range函数

作用:建立一个包含指定范围单元的数组

返回值:返回的数组中从 start 到 limit 的单元,包括它们本身。

<?php
$arr=range(0,20);
foreach($arr as $v){
 echo $v.'<br/>';
}
$arr=range(0,20,2);
foreach($arr as $k=>$v){
  echo $k.'###'.$v.'<br/>';
}
?>
array_flip函数 array array_flip ( array $trans )

作用:交换键值

参数:array $trans 要交换键/值对的数组。

返回值:成功时返回交换后的数组,如果失败返回 NULL。键值对调后,出现2个相同的键,后面的会覆盖前面的键

<?php
$arr=array('a'=>1,'b'=>2,'c'=>3);
print_r($arr);//Array ( [0] => a [1] => b [2] => c )
print_r(array_flip($arr));//Array ( [a] => 0 [b] => 1 [c] => 2 )
?>
array_sum函数 number array_sum ( array $array )

作用:计算数组中所有值的和,将数组中的所有值的和以整数或浮点数的结果返回。

参数:array 输入的数组。

返回值:所有值的和以整数或浮点数的结果返回

<?php
$arr=range(1,100);
print_r($arr);
echo array_sum($arr);
?>
shuffle函数 bool shuffle ( array &$array )

作用: 将数组打乱

参数:array 待操作的数组

返回值:成功时返回 TRUE, 或者在失败时返回 FALSE。该函数是引用传值

<?php
$arr=range(1,100);
print_r($arr);
echo array_sum($arr);
if(shuffle($arr)){
echo '打乱成功';
print_r($arr);//
   }
?>
array_reverse函数 array array_reverse ( array $array [, bool $preserve_keys = false ] )

作用:接受数组 array 作为输入并返回一个单元为相反顺序的新数组。

参数:array 输入的数组。preserve_keys 如果设置为 TRUE 会保留数字的键。 非数字的键则不受这个设置的影响,总是会被保留。

返回值:返回反转后的数组。

<?php

$arr = array('a'=>'春','b'=>'夏','c'=>'秋','d'=>'冬');
print_r($arr); //Array ( [a] => 春 [b] => 夏 [c] => 秋 [d] => 冬 )
print_r(array_reverse($arr)); //Array ( [d] => 冬 [c] => 秋 [b] => 夏 [a] => 春 )
$arr = array('春','夏','秋','冬');
print_r($arr);
print_r(array_reverse($arr));
print_r(array_reverse($arr,true));
?>
array_push函数 int array_push ( array &$array , mixed $var [, mixed $... ] )

作用:将一个或多个单元压入数组的末尾(入栈)

参数:array 输入的数组。 var 要压入的值。

返回值:返回处理之后数组的元素个数。

<?php
$stack = array("orange", "banana");
array_push($stack, "apple", "raspberry");
print_r($stack);
?>
array_pop函数 mixed array_pop ( array &$array )

作用:将数组最后一个单元弹出(出栈)

参数:array 需要做出栈的数组。

返回值:返回 array 的最后一个值。如果 array 是空(如果不是一个数组),将会返回 NULL 。

<?php
$stack = array("orange", "banana", "apple", "raspberry");
$fruit = array_pop($stack);
print_r($stack);
?>
array_shift函数 mixed array_shift ( array &$array )

作用:将数组开头的单元移出数组

参数:array 输入的数组。

返回值:返回移出的值,如果 array 为 空或不是一个数组则返回 NULL。

<?php
$stack = array("orange", "banana", "apple", "raspberry");
$fruit = array_shift($stack);
print_r($stack);
?>
array_unshift函数 int array_unshift ( array &$array , mixed $var [, mixed $... ] )

作用:在数组开头插入一个或多个单元

参数:array 输入的数组。 var 开头插入的变量。

返回值:返回 array 数组新的单元数目。

<?php
$queue = array("orange", "banana");
array_unshift($queue, "apple", "raspberry");
print_r($queue);
?>

对于排序算法我们可以说出好几种了,那么到底那种排序算法会比较好了,下面我们来测试一下吧,有兴趣和小编一起来看这篇php四种基础排序算法的运行时间比较例子。

/**
 * php四种基础排序算法的运行时间比较
 * @authors Jesse (jesse152@163.com)
 * @date    2016-08-11 07:12:14
 */
//冒泡排序法
function bubbleSort($array){
    $temp = 0;
    for($i = 0;$i < count($array) -1;$i++){
        for($j = 0;$j < count($array) - 1 -$i;$j++){
            if($array[$j] > $array[$j+1]){  //从小到大排列
                $temp = $array[$j];
                $array[$j] = $array[$j+1];
                $array[$j+1] = $temp;
            }
        }
    }
}
//选择排序法
function selectSort($array){
    $temp = 0;
    for($i = 0;$i < count($array) - 1;$i++){
        $minVal = $array[$i];  //假设$i就是最小值
        $minValIndex = $i;
        for($j = $i+1;$j < count($array);$j++){  
            if($minVal > $array[$j]){    //从小到大排列
                $minVal = $array[$j];     //找最小值
                $minValIndex = $j;
            }
        }
        $temp = $array[$i];
        $array[$i] = $array[$minValIndex];
        $array[$minValIndex] = $temp;
    }
}
//插入排序法
function insertSort($array){  //从小到大排列
    //先默认$array[0],已经有序,是有序表 
    for($i = 1;$i < count($array);$i++){
        $insertVal = $array[$i]; //$insertVal是准备插入的数
        $insertIndex = $i - 1; //有序表中准备比较的数的下标
        while($insertIndex >= 0 && $insertVal < $array[$insertIndex]){
            $array[$insertIndex + 1] = $array[$insertIndex]; //将数组往后挪
            $insertIndex--; //将下标往前挪,准备与前一个进行比较
        }
        if($insertIndex + 1 !== $i){
            $array[$insertIndex + 1] = $insertVal; 
        }
    }
}
//快速排序法
function quickSort($array){
    if(!isset($array[1]))
        return $array;
    $mid = $array[0]; //获取一个用于分割的关键字,一般是首个元素
    $leftArray = array();
    $rightArray = array();
    foreach($array as $v){
        if($v > $mid)
            $rightArray[] = $v;  //把比$mid大的数放到一个数组里
        if($v < $mid)
            $leftArray[] = $v;   //把比$mid小的数放到另一个数组里
    }
    $leftArray = quickSort($leftArray); //把比较小的数组再一次进行分割
    $leftArray[] = $mid;        //把分割的元素加到小的数组后面,不能忘了它哦
    $rightArray = quickSort($rightArray);  //把比较大的数组再一次进行分割
    return array_merge($leftArray,$rightArray);  //组合两个结果
}

$a = array_rand(range(1,3000), 1600);  //生成1600个元素的随机数组
shuffle($a);  //打乱数组的顺序

$t1 = microtime(true);
bubbleSort($a);   //冒泡排序
$t2 = microtime(true);
echo "冒泡排序用时:".(($t2-$t1)*1000).'ms'."\n";

$t3 = microtime(true);
selectSort($a);   //选择排序
$t4 = microtime(true);
echo "选择排序用时:".(($t4-$t3)*1000).'ms'."\n";

$t5 = microtime(true);
insertSort($a);   //插入排序
$t6 = microtime(true);
echo "插入排序用时:".(($t6-$t5)*1000).'ms'."\n";

$t7 = microtime(true);
quickSort($a);  //快速排序
$t8 = microtime(true);
echo "快速排序用时:".(($t8-$t7)*1000).'ms';

explode和split在php中都是可以通过特定字符把字符串转换成数组哦,那么explode和split既然是一样的为什么会有两个函数呢,那么explode和split的区别在哪里呢,我们来看看。

前言

之所以做这个,是因为这两个函数的作用很像,都是把字符串转换成数组。

explode

从下面的例子可以看出,生成的数组是有对应的顺序的。

 代码如下 复制代码

$pizza  = "piece1 piece2 piece3 piece4 piece5 piece6";
$pieces = explode(" ", $pizza);
echo $pieces[0]; // piece1
echo $pieces[1]; // piece2

// 示例 2
$data = "foo:*:1023:1000::/home/foo:/bin/sh";
list($user, $pass, $uid, $gid, $gecos, $home, $shell) = explode(":", $data);
echo $user; // foo
echo $pass; // *

注意的是,如果第一个参数为空字符串的话,就会产生Warning。

 代码如下 复制代码

var_dump( explode('','asdasd') );

//Warning: explode(): Empty delimiter in /tmp/e80c9663-e392-4f81-8347-35726052678f/code on line 3
//bool(false)
split

(PHP 4, PHP 5)

split — 用正则表达式将字符串分割到数组中

注意的是上面并没有PHP 7,也就是说split函数并不支持PHP 7.

 代码如下 复制代码

$date = "04/30/1973";
list($month, $day, $year) = split ('[/.-]', $date);
echo "Month: $month; Day: $day; Year: $year<br />\n";

//PHP 7 下的报错
Fatal error: Uncaught Error: Call to undefined function split() in /tmp/4d38c290-b4cb-43f5-846a-9fa90784a090/code:4
Stack trace:
#0 {main}
  thrown in /tmp/4d38c290-b4cb-43f5-846a-9fa90784a090/code on line 4

//PHP 5.6 下返回正常
Month: 04; Day: 30; Year: 1973

split的第一个参数为正则表达式,也就是说,如果想要匹配特殊字符,需要转义一下。

 代码如下 复制代码

$arr='2016\8\11';
$rearr = split ('[/\]', $arr);
var_dump($rearr)

/*
array(3) {
  [0]=>
  string(4) "2016"
  [1]=>
  string(1) "8"
  [2]=>
  string(2) "11"
}
*/

也正是因为要使用正则表达式 pattern 的语法,所以搜索的速度不会很快。

preg_split() 函数使用了 Perl 兼容正则表达式语法,通常是比 split() 更快的替代方案。如果不需要正则表达式的威力,则使用 explode() 更快,这样就不会招致正则表达式引擎的浪费

可能效率的原因导致了PHP 7 中直接放弃了这个函数吧。

[!--infotagslink--]

相关文章

  • 图解PHP使用Zend Guard 6.0加密方法教程

    有时为了网站安全和版权问题,会对自己写的php源码进行加密,在php加密技术上最常用的是zend公司的zend guard 加密软件,现在我们来图文讲解一下。 下面就简单说说如何...2016-11-25
  • ps怎么使用HSL面板

    ps软件是现在很多人都会使用到的,HSL面板在ps软件中又有着非常独特的作用。这次文章就给大家介绍下ps怎么使用HSL面板,还不知道使用方法的下面一起来看看。 &#8195;...2017-07-06
  • 解决IDEA占用C盘空间过大的问题

    这篇文章主要介绍了解决IDEA占用C盘空间过大的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-22
  • Plesk控制面板新手使用手册总结

    许多的朋友对于Plesk控制面板应用不是非常的了解特别是英文版的Plesk控制面板,在这里小编整理了一些关于Plesk控制面板常用的使用方案整理,具体如下。 本文基于Linu...2016-10-10
  • 使用insertAfter()方法在现有元素后添加一个新元素

    复制代码 代码如下: //在现有元素后添加一个新元素 function insertAfter(newElement, targetElement){ var parent = targetElement.parentNode; if (parent.lastChild == targetElement){ parent.appendChild(newEl...2014-05-31
  • 使用GruntJS构建Web程序之构建篇

    大概有如下步骤 新建项目Bejs 新建文件package.json 新建文件Gruntfile.js 命令行执行grunt任务 一、新建项目Bejs源码放在src下,该目录有两个js文件,selector.js和ajax.js。编译后代码放在dest,这个grunt会...2014-06-07
  • 使用percona-toolkit操作MySQL的实用命令小结

    1.pt-archiver 功能介绍: 将mysql数据库中表的记录归档到另外一个表或者文件 用法介绍: pt-archiver [OPTION...] --source DSN --where WHERE 这个工具只是归档旧的数据,不会对线上数据的OLTP查询造成太大影响,你可以将...2015-11-24
  • 如何使用php脚本给html中引用的js和css路径打上版本号

    在搜索引擎中搜索关键字.htaccess 缓存,你可以搜索到很多关于设置网站文件缓存的教程,通过设置可以将css、js等不太经常更新的文件缓存在浏览器端,这样访客每次访问你的网站的时候,浏览器就可以从浏览器的缓存中获取css、...2015-11-24
  • jQuery 1.9使用$.support替代$.browser的使用方法

    jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support 。 在更新的 2.0 版本中,将不再支持 IE 6/7/8。 以后,如果用户需要支持 IE 6/7/8,只能使用 jQuery 1.9。 如果要全面支持 IE,并混合...2014-05-31
  • 安装和使用percona-toolkit来辅助操作MySQL的基本教程

    一、percona-toolkit简介 percona-toolkit是一组高级命令行工具的集合,用来执行各种通过手工执行非常复杂和麻烦的mysql和系统任务,这些任务包括: 检查master和slave数据的一致性 有效地对记录进行归档 查找重复的索...2015-11-24
  • MySQL日志分析软件mysqlsla的安装和使用教程

    一、下载 mysqlsla [root@localhost tmp]# wget http://hackmysql.com/scripts/mysqlsla-2.03.tar.gz--19:45:45-- http://hackmysql.com/scripts/mysqlsla-2.03.tar.gzResolving hackmysql.com... 64.13.232.157Conn...2015-11-24
  • php语言中使用json的技巧及json的实现代码详解

    目前,JSON已经成为最流行的数据交换格式之一,各大网站的API几乎都支持它。我写过一篇《数据类型和JSON格式》,探讨它的设计思想。今天,我想总结一下PHP语言对它的支持,这是开发互联网应用程序(特别是编写API)必须了解的知识...2015-10-30
  • PHP实现无限级分类(不使用递归)

    无限级分类在开发中经常使用,例如:部门结构、文章分类。无限级分类的难点在于“输出”和“查询”,例如 将文章分类输出为<ul>列表形式; 查找分类A下面所有分类包含的文章。1.实现原理 几种常见的实现方法,各有利弊。其中...2015-10-23
  • C#注释的一些使用方法浅谈

    C#注释的一些使用方法浅谈,需要的朋友可以参考一下...2020-06-25
  • php类的使用实例教程

    php类的使用实例教程 <?php /** * Class program for yinghua05-2 * designer :songsong */ class Template { var $tpl_vars; var $tpl_path; var $_deb...2016-11-25
  • 双冒号 ::在PHP中的使用情况

    前几天在百度知道里面看到有人问PHP中双冒号::的用法,当时给他的回答比较简洁因为手机打字不大方便!今天突然想起来,所以在这里总结一下我遇到的双冒号::在PHP中使用的情况!双冒号操作符即作用域限定操作符Scope Resoluti...2015-11-08
  • PHP mysql与mysqli事务使用说明 分享

    mysqli封装了诸如事务等一些高级操作,同时封装了DB操作过程中的很多可用的方法。应用比较多的地方是 mysqli的事务。...2013-10-02
  • Postman安装与使用详细教程 附postman离线安装包

    这篇文章主要介绍了Postman安装与使用详细教程 附postman离线安装包,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-05
  • 浅析Promise的介绍及基本用法

    Promise是异步编程的一种解决方案,在ES6中Promise被列为了正式规范,统一了用法,原生提供了Promise对象。接下来通过本文给大家介绍Promise的介绍及基本用法,感兴趣的朋友一起看看吧...2021-10-21
  • 使用jquery修改表单的提交地址基本思路

    基本思路: 通过使用jquery选择器得到对应表单的jquery对象,然后使用attr方法修改对应的action 示例程序一: 默认情况下,该表单会提交到page_one.html 点击button之后,表单的提交地址就会修改为page_two.html 复制...2014-06-07