首页 > 编程技术 > php

PHP匿名函数与注意事项详解

发布时间:2016-11-25 14:56

匿名函数是PHP5.3引进来了,php5.3不但引进了匿名函数还有更多更好多新的特性了,下面我们一起来了解一下PHP匿名函数与注意事项详解


PHP5.2 以前:autoload, PDO 和 MySQLi, 类型约束
PHP5.2:JSON 支持
PHP5.3:弃用的功能,匿名函数,新增魔术方法,命名空间,后期静态绑定,Heredoc 和 Nowdoc, const, 三元运算符,Phar
PHP5.4:Short Open Tag, 数组简写形式,Traits, 内置 Web 服务器,细节修改
PHP5.5:yield, list() 用于 foreach, 细节修改
PHP5.6: 常量增强,可变函数参数,命名空间增强


现在基本上都使用PHP5.3以后的版本,但是感觉普遍一个现象就是很多新特性,过了这么长时间,还没有完全普及,在项目中很少用到。

看看PHP匿名函数:

 'test' => function(){
        return 'test'
},

PHP匿名函数的定义很简单,就是给一个变量赋值,只不过这个值是个function。

以上是使用Yii框架配置components文件,加了一个test的配置。

在另一个模板页面打印试试:

 

<?= app-="">test ?>//test
OK.

什么是PHP匿名函数?

看官方解释:

匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。

匿名函数示例

<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
    return strtoupper($match[1]);
}, 'hello-world');
// 输出 helloWorld
?>

闭包函数也可以作为变量的值来使用。PHP 会自动把此种表达式转换成内置类 Closure 的对象实例。把一个 closure 对象赋值给一个变量的方式与普通变量赋值的语法是一样的,最后也要加上分号:

匿名函数变量赋值示例


<?php
$greet = function($name)
{
    printf("Hello %s\r\n", $name);
};
 
$greet('World');
$greet('PHP');
?>
闭包可以从父作用域中继承变量。 任何此类变量都应该用 use 语言结构传递进去。

从父作用域继承变量

<?php
$message = 'hello'
 
// 没有 "use"
$example = function () {
    var_dump($message);
};
echo $example();
 
// 继承 $message
$example = function () use ($message) {
    var_dump($message);
};
echo $example();
 
// Inherited variable's value is from when the function
// is defined, not when called
$message = 'world'
echo $example();
 
// Reset message
$message = 'hello'
 
// Inherit by-reference
$example = function () use (&$message) {
    var_dump($message);
};
echo $example();
 
// The changed value in the parent scope
// is reflected inside the function call
$message = 'world'
echo $example();
 
// Closures can also accept regular arguments
$example = function ($arg) use ($message) {
    var_dump($arg . ' ' . $message);
};
$example("hello");
?>

以上例程的输出类似于:


Notice: Undefined variable: message in /example.php on line 6
NULL
string(5) "hello"
string(5) "hello"
string(5) "hello"
string(5) "world"
string(11) "hello world"


php中的匿名函数的注意事项

在php5.3以后,php加入匿名函数的使用,今天在使用匿名的时候出现错误,不能想php函数那样声明和使用,详细看代码

$callback=function(){
  return "aa";
};
echo $callback();
 这是打印出来是aa;

看下面的例子:

echo $callback();
$callback=function(){
  return "aa";
};
 这是报错了!报的错误时:

Notice: Undefined variable: callback in D:\php\www\zf2\public\04.php on line 9
Fatal error: Function name must be a string in D:\php\www\zf2\public\04.php on line 9

$callback为未声明,

但是使用php自己声明的函数都不会报错的!

function callback(){
  return "aa";
}
echo callback();  //aa
 
echo callback();  //aa
function callback(){
  return "aa";
}
 这两个都打印出来aa;

在使用匿名函数的时候,匿名函数当做变量,须提前声明,js中也是这样的!!!!!

百度搜索了一下关于PHP5.6新特性发现本站有整理过一篇相关的文章,但仔细对比了一下本文章与它有一些区别,下面我们来看看


PHP5.6起CONST新特性定义类常量可以使用常量标量表达式(Constant scalar expressions),例如:


<?php
 
class MyTimer {
    const SEC_PER_DAY = 60 * 60 * 24;
}
 
?>

define和CONST的区别是define可以用于定义全局常量,而CONST是定义类的常量。


static静态变量与define,CONST的区别是static定义的变量是可以改变的,而后两者不行,并且static静态变量是随类直接在内存中初始化,可以直接用,如$oneclass::hobby.

define可以定义数组吗?例如define(‘A_ARRAY’,array(‘o’=>’ooo’,’x’=>’xxx’)).

在PHP5.6之前是不行的,但是可以通过serialize把数组序列化,如:


# define constant, serialize array
define ("FRUITS", serialize (array ("apple", "cherry", "banana")));
 
# use it
$my_fruits = unserialize (FRUITS);

PHP5.6之后可以直接const定义一个数组:

const DEFAULT_ROLES = array('guy', 'development team');

或者:

const DEFAULT_ROLES = ['guy', 'development team'];

如果是PHP7,可以直接用define定义数组:


define('DEFAULT_ROLES', array('guy', 'development team'));

用户注册对于初学php的朋友来说是非常实用的一个可以帮助你深入了解数据查询验证与数据入库及安全的一个比较经典的实现了,下面一起来看看。


 php写了一个简单的用户注册页面。本篇结合前一篇的内容,将注册页面上提交的信息post 给后面的页面register.php ,register.php将post的信息提交入库。

一、创建数据库与表结构

1、建库

mysql> create database 361way character set utf8;
Query OK, 1 row affected (0.00 sec)
上面我建了一个同我站点同命的库361way 。

2、创建表结构

CREATE TABLE IF NOT EXISTS `tblmember` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `fName` varchar(30) NOT NULL,
  `lName` varchar(30) NOT NULL,
  `email` varchar(50) NOT NULL,
  `password` varchar(60) NOT NULL,
  `birthdate` text NOT NULL,
  `gender` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
这里的字符编码我选择的是utf8 ,并且在该表的id值是从11开始的(前面预留了10个),数据库引擎类型用的InnoDB,具体可以根据自己的需求修改。

二、post提交php页面

向后端提交post请求的register.php代码如下:

<?php
//set up mysql connection
mysql_connect("localhost", "root", "123456") or die(mysql_error());
//select database
mysql_select_db("361way") or die(mysql_error());
//get the value from the posted data and store it to a respected variable
$fName     = $_POST['fName'];
$lName     = $_POST['lName'];
$email     = $_POST['email'];
$reemail   = $_POST['reemail'];
$password  = sha1($_POST['password']);
$month     = $_POST['month'];
$day       = $_POST['day'];
$year      = $_POST['year'];
$gender    = $_POST['optionsRadios'];
$birthdate = $year . '-' . $month . '-' . $day;
//insert data using insert into statement
$query = "INSERT INTO tblmember(id, fName, lName, email, password, birthdate, gender)
                    VALUES (NULL, '{$fName}', '{$lName}', '{$email}', '{$password}', '{$birthdate}', '{$gender}')";
//execute the query
if (mysql_query($query)) {
    //dislay a message box that the saving is successfully save
    echo "<script type=\"text/javascript\">
                alert(\"New member added successfully.\");
                window.location = \"registration.php\"
            </script>";
} else
    die("Failed: " . mysql_error());
?>

上面的代码使用时,数据库的用户名密码及库名根据实际情况修改。

三、测试代码

按上一篇的注册页面输入相关信息并提交后,会弹出如下信息,表示注册成功:

register-mysql

再看下mysql 里的信息:

mysql> select * from tblmember;
+----+-------+-------+------------------+------------------------------------------+-------------+--------+
| id | fName | lName | email            | password                                 | birthdate   | gender |
+----+-------+-------+------------------+------------------------------------------+-------------+--------+
| 10 | test  | yang  | admin@361way.com | a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 | 1997-Jan-28 | Female |
| 11 | aaa   | bbb   | test@91it.org    | 54df472f438b86fc96d68b8454183394ef26b8ac | 1997-Jan-18 | Female |
+----+-------+-------+------------------+------------------------------------------+-------------+--------+
2 rows in set (0.00 sec)


我执行了两次注册,这里有两台记录。

PHP中根据IP地址判断所在城市等信息 我们可以使用IP库或直接调用第三方的api接口了,下面我们介绍的是第二种调用淘宝的IP接口了,具体例子如下。


获得IP地址

在 PHP 中得到当前访问者的IP地址,还是比较简单的:

$ip = $_SERVER['REMOTE_ADDR']

上面IP有时获取不到真实IP地址我们可以如下操作


$ip = GetIP();


将IP转换为城市等信息

淘宝提供了一个IP数据接口: http://ip.taobao.com/service/getIpInfo.php?ip=ip地址

$response = file_get_contents('http://ip.taobao.com/service/getIpInfo.php?ip='.$ip);
$result   = json_decode($response);
print_r($result);

输出结果为:

stdClass Object
(
    [code] => 0
    [data] => stdClass Object
        (
            [country] => 中国
            [country_id] => CN
            [area] => 华南
            [area_id] => 800000
            [region] => 广东省
            [region_id] => 440000
            [city] => 深圳市
            [city_id] => 440300
            [county] =>
            [county_id] => -1
            [isp] => 电信
            [isp_id] => 100017
            [ip] => 183.16.191.102
        )
)

 

function GetIP() {
if ($_SERVER["HTTP_X_FORWARDED_FOR"])
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
else if ($_SERVER["HTTP_CLIENT_IP"])
$ip = $_SERVER["HTTP_CLIENT_IP"];
else if ($_SERVER["REMOTE_ADDR"])
$ip = $_SERVER["REMOTE_ADDR"];
else if (getenv("HTTP_X_FORWARDED_FOR"))
$ip = getenv("HTTP_X_FORWARDED_FOR");
else if (getenv("HTTP_CLIENT_IP"))
$ip = getenv("HTTP_CLIENT_IP");
else if (getenv("REMOTE_ADDR"))
$ip = getenv("REMOTE_ADDR");
else
$ip = "Unknown";
return $ip;
}
echo GetIP();

file_put_contents写入文件在我看到的phper中很少用到了,但小编以前做flash接受数据时就用到了file_put_contents函数了,下面我们来看看file_put_contents写入文件的优点

官方介绍

file_put_contents() 函数把一个字符串写入文件中。

与依次调用 fopen(),fwrite() 以及 fclose() 功能一样。

写入方法的比较

先来看看使用 fwrite 是如何写入文件的

$filename   = 'HelloWorld.txt';
$content    = 'Hello World!';
$fh         = fopen($filename, "w");
echo fwrite($fh, $content);
fclose($fh);

再看看使用 file_put_contents 是如何写入文件的

$filename   = 'HelloWorld.txt';
$content    = 'Hello World!';
file_put_contents($filename, $content);

以上我们可以看出,file_put_contents 一行就代替了 fwrite 三行代码,

可见其优点: 简洁、易维护,也不会出现,因 fclose() 忘写的不严密行为。

方法进阶

追加写入

file_put_contents 写入文件时,默认是从头开始写入,如果需要追加内容呢?

在 file_put_contens 方法里,有个参数 FILE_APPEND,这是追加写入文件的声明。

file_put_contents(HelloWorld.txt, 'Hello World!', FILE_APPEND);

锁定文件

在写入文件时,为避免与其它人同时操作,通常会锁定此文件,这就用到了第二个参数: LOCK_EX

file_put_contents(HelloWorld.txt, 'Hello World!', FILE_APPEND|LOCK_EX);

此外,为了确保正确写入,通常会先判断该文件是否可写

if (is_writable('HelloWorld.txt')) {
    file_put_contents(HelloWorld.txt, 'Hello World!', FILE_APPEND|LOCK_EX);
}

标签:[!--infotagslink--]

您可能感兴趣的文章: