PHP的反射机制浅析
1. 介绍
-- PHP5添加了一项新的功能:Reflection。这个功能使得phper可以reverse-engineer class, interface,function,method and extension。通过PHP代码,就可以得到某object的所有信息,并且可以和它交互。
-- 反射是什么?
它是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。反射是操纵面向对象范型中元模型的API,其功能十分强大,可帮助我们构建复杂,可扩展的应用。
其用途如:自动加载插件,自动生成文档,甚至可用来扩充PHP语言。
php反射api由若干类组成,可帮助我们用来访问程序的元数据或者同相关的注释交互。借助反射我们可以获取诸如类实现了那些方法,创建一个类的实例(不同于用new创建),调用一个方法(也不同于常规调用),传递参数,动态调用类的静态方法。
反射api是php内建的oop技术扩展,包括一些类,异常和接口,综合使用他们可用来帮助我们分析其它类,接口,方法,属性,方法和扩展。这些oop扩展被称为反射。
通过ReflectionClass,我们可以得到Person类的以下信息:
1)常量 Contants
2)属性 Property Names
3)方法 Method Names静态
4)属性 Static Properties
5)命名空间 Namespace
6)Person类是否为final或者abstract
2. 具体例子
创建一个Person类,然后使用ReflectionClass反射它
2.1)【创建Persion类】
classPerson {
/**
* For the sake of demonstration, we"re setting this private
*/
private$_allowDynamicAttributes= false;
/** type=primary_autoincrement */
protected$id= 0;
/** type=varchar length=255 null */
protected$name;
/** type=text null */
protected$biography;
publicfunction getId()
{
return$this->id;
}
publicfunctionsetId($v)
{
$this->id =$v;
}
publicfunctiongetName()
{
return$this->name;
}
publicfunctionsetName($v)
{
$this->name =$v;
}
publicfunctiongetBiography()
{
return$this->biography;
}
publicfunctionsetBiography($v)
{
$this->biography =$v;
}
}
Persion
|
2.2)【反射过程】
接下来反射它,只要把类名"Person"传递给ReflectionClass就可以了:
$class=newReflectionClass('Person');//建立 Person这个类的反射类
$instance=$class->newInstanceArgs($args);//相当于实例化Person 类
|
2.3)【反射后使用】
2.3.1)获取属性(Properties)
$properties=$class->getProperties();
foreach($propertiesas$property) {
echo$property->getName()."\n";
}
// 输出:
// _allowDynamicAttributes
// id
// name
// biography
|
默认情况下,ReflectionClass会获取到所有的属性,private 和 protected的也可以。如果只想获取到private属性,就要额外传个参数:
privateproperties=privateproperties=class->getProperties(ReflectionProperty::IS_PRIVATE);
可用参数列表:
- ReflectionProperty::IS_STATIC
- ReflectionProperty::IS_PUBLIC
- ReflectionProperty::IS_PROTECTED
- ReflectionProperty::IS_PRIVATE
如果要同时获取public 和private 属性,就这样写:ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED。
通过$property->getName()可以得到属性名。
2.3.2)【获取注释】
通过getDocComment可以得到写给property的注释。
foreach($propertiesas$property) {
if($property->isProtected()) {
$docblock=$property->getDocComment();
preg_match('/ type\=([a-z_]*) /',$property->getDocComment(),$matches);
echo$matches[1]."\n";
}
}
// Output:
// primary_autoincrement
// varchar
// text
|
2.3.3)【获取类的方法】
获取方法(methods):通过getMethods() 来获取到类的所有methods。
2.3.4)【执行类的方法】
$instance->getBiography();//执行Person 里的方法getBiography
//或者:
$ec=$class->getmethod('getName');//获取Person 类中的getName方法
$ec->invoke($instance); //执行getName 方法
|
一、利用选择工具
Photoshop中的选择工具包括遮罩工具(Marquee)、套索工具(Lasso)、魔术棒(Magic Wand)、字体遮罩(Type Mask)以及由路径转换来的选区等,其中包括不同羽化值的设置。利用这些工具在通道中进行编辑与对一个图象的操作是相同的,你所需的仅仅是一点点勇气。
使用选择工具可以完成一些最基本的操作,可是如果你要我确切的举例来说明,倒也有些难处,因为我实在记不起在我近来的工作中有哪一部分是单纯利用选择工具来编辑通道的。或许是在对一个已经通过其他方法建立的选区稍做修改的时候?实在是这种方法太基本了,你必须要明白却又几乎察觉不到它的存在。
二、利用绘图工具
绘图工具包括喷枪(Airbrush)、画笔(Paintbrush)、铅笔(Pencil)、图章(Stamp)、橡皮擦(Eraser)、渐变(Gradient)、油漆桶(PaintBucket)、模糊锐化和涂抹(Blur、Sharpen、Smudge)、加深减淡和海绵(Dodge、Burn、Sponge)。
现在应该很容易理解我们平时操作的通道所具备的颜色的问题。当你看到任何一种选择带来的白色时,就应该有一种用手指去涂抹一下的冲动。
当然这样做带来的后果也许只能改变你心爱的的显示屏的颜色,但你大可用画笔这类的工具作为替代品去实验一下,相信第一次这样做所引起的后果是激动人心的(如果你说不,那你向我保证你绘画时所用的颜色与你正涂抹位置的颜色不一样)。
的确任何选择区域你都可以用你随手可以捡到的绘图工具去创建,其间唯一的区别也许只是你看不到那些黑白相间不断行动的线条了。
利用绘图工具编辑通道的一个优势在于你可以精确的控制笔触(虽然比不上绘图板),从而可以得到更为柔和以及足够复杂的边缘。实际的去运用一下,你很快会喜欢上它们。现在我所做的每一幅图片,只要涉及通道,80% 以上时从画笔开始的。因为我并不需要一团黑或者一团白。
这里要提一下的,是渐变工具。因为这种工具比较特别。不是说它特别复杂,而是说它特别容易被人忽视。但相对于通道确又是特别的有用。它是我所知道的photoshop中严格意义上的一次可以涂画多种颜色而且包含平滑过度的绘画工具,针对于通道而言,也就是带来了平滑细腻的渐变。我想当你要把自己完美的融合到大自然中去时,从这里开始是个不错的主意。
三、利用滤镜
曾经有人问我怎样才算是好的美术作品。当时我告诉他是那些完美地把自然因素与人为创作结合在一起的作品。实质上,一直以来,我同样也在思考这个问题。
同大多数人一样,我坚信人的创造力和想象力是无限的,但我也深知,这并不代表一个人可以想象出所有的东西。有时候,把自己隔离开,任由Photoshop去创作未尝不是一件好事,实际上那是相当有趣的一个方式。
在通道中进行滤镜操作,通常是在有不同灰度的情况下,而运用滤镜的原因,通常是因为我们刻意追求一种出乎意料的效果或者只是为了控制边缘。
原则上讲,你可以在通道中运用任何一个滤镜去试验,当然这只是在你没有任何目的的时候,实际上大部分人在运用滤镜操作通道时通常有着较为明确的愿望,比如锐化或者虚化边缘,从而建立更适合的选区。各种情况比较复杂,需要根据目的的不同做相应处理,但你尽可试一下,总会有收获的。
四、利用调节工具
特别有用的调节工具包括色阶(level)和曲线(curves)。
在你用这些工具调节图象时,你会看到对话框上有一个channel选单,在这里可以所要编辑的颜色通道。当你选中希望调整的通道时,按住shift键,再单击另一个通道,最后打开图象中的复合通道。这样你就可以强制这些工具同时作用于一个通道。
对于编辑通道来说,这当然是有用的,但实际上并不常用的,因为你大可以建立调节图层而不必破坏最原始的信息,实际上,如果你再前面还不明白通道是什么的话,现在就应该明白了。说到底,对通道的理解不过是个感觉问题,也许顿悟就再一瞬间。
再强调一点,单纯的通道操作是不可能对图象本身产生任何效果的,必须同其他工具结合,如选区和蒙板(其中蒙板是最重要的),所以再理解通道时最好与这些工具联系起来,才能知道你精心制作的通道可以在图象中起到什么样的作用。
App接口返回的数据有两种xml或json数据了,当然json数据是最常见了就是我们接受到app请求我们返回json数据即可,这个操作非常的简单几乎可以不用学习即可开发App接口程序了,下面来看一篇文章。搭建PHP环境
由于本人使用的电脑是Mac,因此推荐大家使用MAMP PRO这款软件,不过是收费版,相信不想花钱的大家会有办法搞定的!
MAMP PRO这款软件是集成环境软件,已经有apache、mysql、php了,具备运行解析PHP的环境了!
如果不想使用集成环境,可以自己搭建。Mac自带了apache和PHP环境的,只需要稍加配置一下就可以使用了,然后再安装一下mysql就可以了!
启动服务器
这里是以MAMP PRO软件为例,如何启动服务器。如下图,我们假设服务地址为www.api.com,然后将项目目录与这个服务地址关联起来,看图中右下角圈圈部分:
标哥的技术博客
环境启动后,就可以在浏览器中直接输入www.api.com运行起来了!
开始GET接口
我们的空项目在首次运行后,会自动生成index.php这个文件,我们删除里面的内容,然后修改如下:
<?php
$data = array(
'tid' => 100,
'name' => '标哥的技术博客',
'site' => 'www.111cn.net');
$response = array(
'code' => 200,
'message' => 'success for request',
'data' => $data,
);
echo json_encode($response);
我们这里的结构是日常App开发中最常见的返回数据结构了吧?通常都是状态码、状态信息和客户端业务数据。
PHP其实也好给力,声明数组后,通过json_encode函数就可以输出json格式数据了!
iOS调GET接口
我们有了服务器,也写了接口了,那么客户端如何请求又如何获取数据呢?我们先来看一下最简单的GET请求例子,其中使用了HYBNetworking笔者的这个开源库:
NSString *url = @"http://www.api.com/index.php";
[HYBNetworking getWithUrl:url refreshCache:YES success:^(id response) {
} fail:^(NSError *error) {
}];
我们看一下iOS客户端的响应结果:
标哥的技术博客
从响应结果可以看到,与我们服务器接口所返回的是一致的,看下图在浏览器中访问的效果:
PHP POST接口
假设我们要求传参数type过来,而且要求是数值型,用于返回不同的数据,当我们做接口测试时,就可以通过这么来干,就不需要等后台给接口了!
<?php
$type = $_POST['type'];
$data = '';
if (isset($type) && is_numeric($type) && $type >= 0) {
if ($type == 1) {
$data = array(
'type' => $type,
'name' => '标哥的技术博客',
'site' => 'www.111cn.net');
} else if ($type == 2) {
$data = array(
'type' => $type,
'name' => '公众号:标哥的技术博客',
'site' => 'weixin search: biaogedejishuboke');
}
$response = array(
'code' => 200,
'message' => 'success for request',
'data' => $data,
);
echo json_encode($response);
return;
}
$response = array(
'code' => 999,
'message' => 'argument error for request',
'data' => $data,
);
echo json_encode($response);
iOS调POST接口
下面是iOS客户端如何调用刚才所写的PHP POST接口,其中使用了HYBNetworking笔者的这个开源库:
NSString *url = @"http://www.api.com/index.php";
NSDictionary *params = @{@"type" : @(1)};
[HYBNetworking postWithUrl:url refreshCache:YES params:params success:^(id response) {
} fail:^(NSError *error) {
}];
我们看看效果如下,可看到如愿地接收到了服务器返回的接口数据并解析出来了:
在PHP中单引号和双引号并非是互通的,具体区别如下:
” ” 双引号里面的字段会经过编译器解释,然后再当作HTML代码输出。
‘ ‘ 单引号里面的不进行解释,直接输出。
从字面意思上就可以看出,单引号比双引号要快了。
例如:
$abc=’my name is tome’;
echo $abc //结果是:my name is tom
echo ‘$abc’ //结果是:$abc
echo “$abc” //结果是:my name is tom
在SQL语句中
这是会经常遇到的问题,在插入数据库的SQL语句是采用单引号来定义字符串,如果要将一个含有单引号的字符串插入数据库,这个SQL语句就会出错。
如:$sql="insert into userinfo (username,password) Values('O'Kefee','123456')"
此时,处理的方法之一是在SQL语句中加入转义符反斜线,
即:……Values('O\'Kefee',……
当然也可以使用函数 addslashes(),该函数的功能就是加入转义符,
即:$s = addslashes("O'Kefee") ……Values('".$s."',……
还有一种方法是设置php.ini中的magic-quotes选项,打开该选项,则通过表单提交的信息中如果有单引号是,将会自动加上如转义符。因此不用使用其他函数了。
补充: 这就要从双引号和单引号的作用讲起: 双引号里面的字段会经过编译器解释然后再当作HTML代码输出,但是单引号里面的不需要解释,直接输出。
$val ='a';
sql =" select * from table where name like '%$val%'"; //将自动替换里面的$val,但如果要用单引号来组织语句则表示为:
sql =' select * from table where name like \'%'.$val.'%\''; //麻烦很多
但用单引号代替双引号来包含字符串,这样做会更快一些,因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会。
假设查询条件中使用的是常量,例如:
select * from abc_table where user_name=’abc’;
SQL语句可以写成:
SQLstr = “select * from abc_table where user _name= ‘abc’” ;
假设查询条件中使用的是变量,例如:
$user_name = $_REQUEST['user_name']; //字符串变量
或
$user=array (”name”=> $_REQUEST['user_name‘,"age"=>$_REQUEST['age'];//数组变量
SQL语句就可以写成:
SQLstr = “select * from abc_table where user_name = ‘ ” . $user_name . ” ‘ “;
SQLstr = “select * from abc_table where user_name = ‘ ” . $user["name"] . ” ‘ “;
对比一下:
SQLstr=”select * from abc_table where user_name = ‘ abc ‘ ” ;
SQLstr=”select * from abc_table where user_name =’ ” . $user _name . ” ‘ “;
SQLstr=”select * from abc_table where user_name =’ ” . $user["name"] . ” ‘ “;
SQLstr可以分解为以下3个部分:
1:”select * from table where user_name = ‘ ” //固定SQL语句
2:$user //变量
3:” ‘ ”
1,2,3部分字符串之间用”.” 来连接
PHP效率计:从引号开始(单引号、双引号效率区别)
实验一:在普通情况下的效率
我们的实验是5000次执行10000个字节的文件,获得解析过程中的速度。
首先,本实验特别规定一个单位,这是为了更好地表示以及排除计算机本身效率的差异。
时间单位 TT,表示约 7.2×10[sup]-8[/sup]s 。
我们获得四组实验数据,可理解为表示 'a' 比 "a" 快的时间:
0.29 TT,大概0.0000000206s
0.46 TT,大概0.0000000328s
0.38 TT,大概0.0000000275s
0.41 TT,大概0.0000000292s
平均值:0.39 TT ('aaaa....(139个)' 的效率接近于 "aaa...(100个)" )
结论:在数据量相同,并且在普通情况下(不借助转义),使用单引号速度更快。
实验二:单引号转义的效率
我们的实验是5000次分别以「单引号、双引号」执行两份数据相同,但其中一份特别用\'表示单引号。
时间单位 TT,表示约 7.2×10[sup]-8[/sup]s 。
我们获得四组实验数据,可理解为表示 " ' " 比 ' \' ' 快的时间:
0.19 TT,大概0.0000000138s
0.15 TT,大概0.0000000110s
0.23 TT,大概0.0000000162s
0.24 TT,大概0.0000000173s
平均值:0.2 TT (” ''''...(12个) " 的效率接近于 ' \'\'...(10个)" )
结论:如果字符串中需要表示单引号(MySQL查询),应尽可能避免转义,所以应使用双引号。
实验三:花括号的效率
我们的实验是1000次执行含有数量一定的变量标记的文件,获得解析过程中的速度。
时间单位 TT,表示约 1.581×10[sup]-7[/sup]s~1.666×10[sup]-7[/sup]s 。(TT 变化)
得到三组数据,表示 "{$abc}" 比 "$abc" 快。
15.3 TT,大概0.0000024186s
14.5 TT,大概0.0000024093s
15.3 TT,大概0.0000024152s
这数据是十分惊人的,平均结果 15 TT。
这意味着:使用花括号的解析速度,大约是不使用花括号的16倍。
结论:在双引号中表示变量,尽可能使用花括号。
实验四:连续与非连续的效率
我们的实验是1000次执行含有数量一定的变量标记的文件,获得解析过程中的速度。
时间单位 TT,表示约 1.581×10[sup]-7[/sup]s~1.666×10[sup]-7[/sup]s 。(TT 变化)
第一组实验数据,表示 "{$abc}{$abc}{$abc}..." 比 $abc.$abc.$abc 平均每个变量解析快
22.45 TT,大概0.0000035498s
21.03 TT,大概0.0000035037s
22.12 TT,大概0.0000034930s
花括号(连续)比单引号(非连续)快的时间,平均结果 22 TT。
这意味着:使用花括号的解析速度,大约是使用不连续的单引号的23倍。
结论:在单引号中表示多个变量(或数据总量少),尽可能换用双引用,并使用花括号。
第二组实验数据,表示 "...$abc$abc$abc..." 比 ‘...’.$abc.$abc.$abc.'...' 平均每个变量解析快
7.15 TT,大概0.0000011311s
6.57 TT,大概0.0000010943s
6.83 TT,大概0.0000010777s
双引号(连续)比单引号(非连续)快的时间,平均结果 7 TT。(该数据变化)
这意味着:变量多时,使用双引号(不使用花括号)的解析速度,大约是使用不连续的单引号的8倍。
结论:在双引号中表示多个变量(或数据总量少),比使用单引号而需要用「连接运算符」要快。
结论:表示多个变量时(或数据总量少),应可能范围内使用双引号,并使用花括号。
(附:作者推测,这可能和内存空间的分配有关系,连续符可能会使内存不断调整)
最终结论:
首先,表示简单的数据时(不需要转义),尽量用单引号。
'Cal: Are you good at long jump?'
但如果因为使用单引号,而需要进行转义(即包含单引号),考虑使用双引号。
'Cal: Yes. But, you know, it\'s written.' => "Cal: Yes. But, you know, it's written."
如果需要表示变量,应尽量使用花括号。
"Cal: $to" => "Cal: {$to}, you shouldn't go shopping."
尽量使其连续:
'Cal: '.$calsaid => "Cal: $calsaid" => "Cal: {$calsaid}"
相关文章
- 说到php的运行机制还要先给大家介绍php的模块,PHP总共有三个模块:内核、Zend引擎、以及扩展层;PHP内核用来处理请求、文件流、错误处理等相关操作;Zend引擎(ZE)用以将源文件转换成机器语言,然后在虚拟机上运行它;扩展层是一组...2015-11-24
- 其实说白了,反射就是能知道我们未知类型的类型信息这么一个东西.没什么神秘可讲!反射的核心是System.Type。System.Type包含了很多属性和方法,使用这些属性和方法可以在运行时得到类型信息...2020-06-25
- 这篇文章主要介绍了C#反射的相关知识,文中讲解的非常详细,代码帮助大家更好的参考学习,感兴趣的朋友可以了解下...2020-06-25
- 这篇文章主要介绍了详解C语言进程同步机制的的相关资料,文中代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-06-18
- 这篇文章主要介绍了 Jasper的自动检测实现的机制比较简单,依靠某后台线程不断检测JSP文件与编译后的class文件的最后修改时间是否相同,若相同则认为没有改动,但倘若不同则需要重新编译,需要的朋友可以参考下...2016-12-02
- 这篇文章主要介绍了C# 通过反射获取类型的字段值及给字段赋值的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-19
跟我学Node.js(四)---Node.js的模块载入方式与机制
其它的如通过NPM安装的第三方模块(third-party modules)或本地模块(local modules),每个模块都会暴露一个公开的API。以便开发者可以导入。如复制代码 代码如下:var mod = require('module_name')此句执行后,Node内部会载入...2014-06-07- 这篇文章主要介绍了通过实例了解Python异常处理机制底层实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-24
- 反射是.NET中的重要机制,下面这篇文章主要给大家介绍了关于.NET/C#如何使用反射注册事件的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧...2021-09-22
- 这篇文章主要帮助大家更好的理解js回收机制,通俗易懂,便于大家理解,感兴趣的小伙伴们可以参考一下...2016-03-01
- 这篇文章主要介绍了asp.net反射简单应用,结合完整实例形式分析了asp.net反射的原理与简单使用方法,需要的朋友可以参考下...2021-09-22
- 这篇文章主要介绍了c# 如何用好垃圾回收机制GC,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下...2020-11-03
- 这篇文章主要介绍的是前端JavaScript中的反射和代理,本文主要围绕JavaScript中的内置Reflect、JavaScript中的内置Proxy、Proxy实现观察者模式三个话题展开文章内容,需要的朋友可以参一考下...2021-10-22
- 这篇文章主要介绍了JAVA 反射机制的相关知识,文中讲解的非常细致,代码帮助大家更好的理解学习,感兴趣的朋友可以了解下...2020-06-17
- 这篇文章主要介绍了php面向对象之反射功能与用法,结合实例形式简单分析了php5面向对象反射的概念及具体用法,需要的朋友可以参考下...2017-04-03
- JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,这篇文章主要给大家介绍了关于Java反射之基础篇的相关资料,需要的朋友可以参考下...2021-11-18
- 其实说白了,反射就是能知道我们未知类型的类型信息这么一个东西.没什么神秘可讲!反射的核心是System.Type。System.Type包含了很多属性和方法,使用这些属性和方法可以在运行时得到类型信息...2020-06-25
- 这篇文章主要给大家介绍了关于C++反射的一种实现方法,文中通过示例代码介绍的非常详细,对大家学习或者使用C++具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-04-25
- 这篇文章主要介绍了C#泛型和反射实例解析,对于C#初学者理解泛型和反射有很好的帮助借鉴作用,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了详解CocosCreator项目结构机制,只有了解这些机制后,才能更好的进行项目开发,避免潜在错误,并且快速的除错...2021-04-15