PHP成员变量获取对比(类成员变量)

 更新时间:2016年11月25日 14:59  点击:6265
下面本文章来给大家介绍在php中成员变量的一些对比了,文章举了四个例子在这例子中分别对不同成员变量进行测试与获取操作,下面一起来看看。

有如下4个代码示例,你认为他们创建对象,并获得成员变量的速度排序是怎样的?

1:将成员变量设置为public,通过赋值操作给成员变量赋值,直接获取变量

 

 代码如下 复制代码

class Foo {
  public $id;
 }
 
 $data = new Foo;
 $data->id = 10;
 echo $data->id;2:将成员变量设置为public,通过构造函数设置成员变量的值,直接获取变量

        class Foo2 {
  public $id;
  public function __construct($id) {
   $this->id = $id;
  }
 }
 
 $data = new Foo2(10);
 echo $data->id;


3:将成员变量设置为protected,通过构造函数设置成员变量的值,通过魔术方法获取变量

 

 代码如下 复制代码

     class Foo3 {
  protected $id;
  public function __construct($id) {
   $this->id = $id;
  }
 
  public function getId() {
   return $this->id;
  }
 }
 $data = new Foo3(10);
 echo $data->getId();


4:将成员变量设置为protected,通过构造函数设置成员变量的值,通过成员方法获取变量

 

 代码如下 复制代码

     class Foo4 {
  protected $id;
  public function __construct($id) {
   $this->id = $id;
  }//www.111cn.net
 
  public function __get($key) {
   return $this->id;
  }
 }
 $data = new Foo4(10);
 echo $data->id;


按执行速度快慢排序: 1243
咱们先看其opcode:

 代码如下 复制代码

1:

    1  ZEND_FETCH_CLASS 4  :4  'Foo'
 2  NEW         $5 :4
 3  DO_FCALL_BY_NAME   0         
 4  ASSIGN         !0, $5
 5  ZEND_ASSIGN_OBJ   !0, 'id'
 6  ZEND_OP_DATA    10
 7  FETCH_OBJ_R   $9 !0, 'id'
 8  ECHO            $92:

 1  ZEND_FETCH_CLASS 4  :10 'Foo2'
 2  NEW               $11 :10
 3  SEND_VAL           10
 4  DO_FCALL_BY_NAME  1
 5  ASSIGN        !1, $11
 6  FETCH_OBJ_R   $14 !1, 'id'
 7  ECHO            $143:

 1  ZEND_FETCH_CLASS 4  :15 'Foo3'
 2  NEW            $16 :15
 3  SEND_VAL        10
 4  DO_FCALL_BY_NAME   1         
 5  ASSIGN         !2, $16
 6  ZEND_INIT_METHOD_CALL !2, 'getId'
 7  DO_FCALL_BY_NAME  0  $20    
 8  ECHO           $204:

 1  ZEND_FETCH_CLASS 4  :21 'Foo4'
 2  NEW            $22 :21
 3  END_VAL         10
 4  DO_FCALL_BY_NAME  1         
 5  ASSIGN           !3, $22
 6  FETCH_OBJ_R    $25 !3, 'id'
 7   ECHO      $25


根据上面的opcode,参照其在zend_vm_execute.h文件对应的opcode实现,我们可以发现什么?

一、PHP内核创建对象的过程分为三步:

1.ZEND_FETCH_CLASS 根据类名获取存储类的变量,其实现为一个hashtalbe EG(class_table) 的查找操作
2.NEW 初始化对象,将EX(call)->fbc指向构造函数指针。
3.调用构造函数,其调用和其它的函数调用是一样,都是调用zend_do_fcall_common_helper_SPEC
二、魔术方法的调用是通过条件触发的,并不是直接调用,如我们示例中的成员变量id的获取(zend_std_read_property),其步骤为:

1.获取对象的属性,如果存在,转第二步;如果没有相关属性,转第三步
2.从对象的properties查找是否存在与名称对应的属性存在,如果存在返回结果,如果不存在,转第三步
3.如果存在__get魔术方法,则调用此方法获取变量,如果不存在,报错
回到排序的问题:

一、第一个和第二个的区别是什么?

第二个的opcode比第一个要少,反而比第一个要慢一些,因为构造函数多了参数,多了一个参数处理的opcode。参数处理是一个比较费时的操作,当我们在做代码优化时,一些不必要的参数能去掉就去掉;当一个函数有多个参数时,可以考虑通过一个数组将其封装后传递进来。

二、为啥第三个最慢?

因为其获取参数其本质上是一次对象成员方法的调用,方法的调用成本高于变量的获取

三、为啥第四个比第三个要快?

因为第四个的操作实质上获取变量,只不过其内部实现了魔术方法的调用,相对于用户定义的方法,内部函数的调用的效率会高。因此,当我们有一些PHP内核实现的方法可以调用时就不要重复发明轮子了。

四、为啥第四个比第二个要慢?

因为在PHP的对象获取变量的过程中,当成员变量在类的定义不在在时,会去调用PHP特有的魔术方法__get,多了一次魔术方法的调用。

总结一下:

1.使用PHP内置函数
2.并不是事必面向对象(OOP),面向对象往往开销很大,每个方法和对象调用都会消耗很多内存。
3.尽量少用魔术方法 -- 除非有必要,不要用框架,因为框架都有大量的魔术方法使用。
4.在性能优先的应用场景中,将成员变量不失为一种比较好的方法,当你需要用到OOP时。
5.能使用PHP语法结构的不要用函数,能使用内置函数的不要自己写,能用函数的不要用对象

命名空间是一种特殊的作用域,它包含处于该作用域下的标识符,同时它本身也是一种标识符。可以把命名空间与操作系统的目录对应起来。一个命名空间相当于一个目录,命名空间里的类,函数,常量,相当于目录里的文件。同一个目录(命名空间)里的文件名不能相同,但是不同的目录里可以有相同名字的文件。

2、使用命名空间为了解决什么问题?

. 解决名字冲突,比如定义了一个类,正好这个类与PHP内部的类或是include进来的一个类库里的类重名了。

. 提高代码可读性,命名空间有一个别名功能,它可以帮你给一个长达十几个字符的类名起一个别名,从而缩短代码,也不用担心与其他空间的命名冲突。

3、哪一些代码会受命名空间的影响。

三类:类、函数、常量。只有它们兄弟三受影响,其他的该干嘛,还干嘛去。说到常量,php 5.3以后可以使用const关键字来定义常量,5.3这前使用define,命名空间只对const关键字有效。

4、命名空间如何定义

 代码如下 复制代码

namespace MyProject;
const CONNECT_OK = 1;//php5.3以后
class Connection { /* ... */ }
function connect() { /* ... */  }

#例子二

namespace MyProjectSubLevel;

const CONNECT_OK = 1;//php5.3以后
class Connection { /* ... */ }
function connect() { /* ... */  }

使用 `namespace 空间名` 来申明一个空间,在namespace之前除了declare语句不能有任何其他php语句,同时也不能有任何非php代码,连空格都不能有。

以下为错误的形式

 代码如下 复制代码

$a = 1;
namespace MyProject;
?>www.111cn.net
//Fatal error: Namespace declaration statement has to be the very first statement in the script...

 另外同一个命名空间是可以定义在多个文件中,这对于组织框架是非常有用的。即以同一个namespace MyProject;开头的文件,它们是同一个命名空间。所以注意文件之间可不要有相同的类/函数/常量名哦。

当然同一个文件也可以定义多个命名空间,不过非常不建议这样做的。(了解同一个文件定义多个命名空间)

5、命名空间如何使用
命名空间有三种使用形式:

. 非限定名称 -- 没有使用任何的分割符,直接使用类/函数/常量名,如:new Foo(); foo(); echo FOO; 当文件有使用命名空间时,

 代码如下 复制代码
<?php
namespace MyObject;
new Foo(); // 调用MyObjectFoo();
foo(); //调用MyObjectFoo();
echo FOO; //调用MyObjectFOO;     

 

. 非完全限定名称 -- 不是以分割符开头,如 new SubFoo(); 这种形式与非限定名称方式一样。

 代码如下 复制代码

<?php
namespace MyObject; new SubFoo(); //调用MyObjectSubFoo();

. 完全限定名称 -- 以分割符开头的方式,相当于操作系统里的绝对地址。如 new OtherNSFoo();

 代码如下 复制代码

<?php
namespace MyObject; new OtherNSFoo(); //调用OtherNsFoo(); 不管MyObject命名空间。

Tip: 对于函数和常量,还有一个特殊的地方(后备全局函数/常量)。

 代码如下 复制代码

<?php
namespace MyObject;
funcname(); //如果MyObjectFuncname存在则调用MyObjectFuncname(),否则试着调用funcname(); echo FOO; //同上。

对于类,也有一个特殊的地方。

 代码如下 复制代码

<?php
namespace MyObject;
new Foo(); //*如果MyObjectFoo存在,调用之,如果不存在,调用__autoload试着加载MyObjectFoo类进来。

           //注意对于类是不会去自动去调用全局作用域下的类的。*/

之前说了,命名空间还有一个用途-取别名。

 代码如下 复制代码

namespace MyObject;
use OtherNSSub as Other;
use OtherNSSub2; //相当于use OtherNSSub2 as Sub2;
use /MyClass;

new Foo(); //调用MyObjectFoo();
new OtherFoo(); //调用 OtherNSSubFoo();
new Sub2Foo(); //调用OtherNSSub2Foo();
new MyClass(); //调用MyClass();

6、动态命名空间

动态总是能让人摸不着头脑,然而又带来灵活性。命名空间同样可以使用动态语言特点,但要注意由于直接调用命名空间是编译时解析的,而动态特征并非编译时解析。所以一定要加前缀。如:

 代码如下 复制代码

namespace MyObjectSub;
new Foo(); //调用 MyObjectSubFoo(), 编译时已经解析成MyObjectSubFoo
$a = 'Foo';
new $a(); //调用的是Foo(),而不是MyObjectSubFoo()
$b = 'MyObjectSubFoo'; //等价于 MyObjectSubFoo
new $b(); //调用MyObjectSubFoo()
//如果使用双引号,要用\,如 $a = "\MyObject\Sub";

附1:同一个文件定义多个命名空间
方法有两种:

 代码如下 复制代码

namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
namespace AnotherProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

方法一,记流水帐。

 代码如下 复制代码

namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}
namespace AnotherProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}
namespace { //全局
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

方法二,使用大括号把同一个命名空间的代码放在大括号里。这种方法,要求在大括号外不能有任何除了declare之外的代码。对于全局作用域的代码使用没有空间名的大括号包围起来

在已知URL参数的情况下,我们可以根据自身情况采用$_GET来获取相应的参数信息($_GET[\\\'name\\\']);那,在未知情况下如何获取到URL上的参数信息呢?

第一种、利用$_SERVER内置数组变量

相对较为原始的$_SERVER['QUERY_STRING']来获取,URL的参数,通常使用这个变量返回的会是类似这样的数据:name=tank&sex=1

如果需要包含文件名的话可以使用$_SERVER["REQUEST_URI"](返回类似:/index.php?name=tank&sex=1)


第二种、利用pathinfo内置函数
01 <?php
02 $test = pathinfo("http://localhost/index.php");
03 print_r($test);
04 /*
05 结果如下
06 Array
07 (
08     [dirname] => http://localhost //url的路径
09     [basename] => index.php  //完整文件名
10     [extension] => php  //文件名后缀
11     [filename] => index //文件名
12 )
13 */
14 ?>


第三种、利用parse_url内置函数
01 <?php
02 $test = parse_url("http://localhost/index.php?name=tank&sex=1#top");
03 print_r($test);
04 /*
05 结果如下
06 Array
07 (
08     [scheme] => http //使用什么协议
09     [host] => localhost //主机名
10     [path] => /index.php //路径
11     [query] => name=tank&sex=1 // 所传的参数
12     [fragment] => top //后面根的锚点
13 )
14 */
15 ?>


第四种、利用basename内置函数
1 <?php
2 $test = basename("http://localhost/index.php?name=tank&sex=1#top");
3 echo $test;
4 /*
5 结果如下
6 index.php?name=tank&sex=1#top
7 */
8 ?>


另外,还有就是自己通过正则匹配的处理方式来获取需要的值了。这种方式较为精确,效率暂不考虑。。。

下面拓展实践下正则处理方式:
01 <?php
02 preg_match_all("/(\w+=\w+)(#\w+)?/i","http://localhost/index.php?name=tank&sex=1#top",$match);
03 print_r($match);
04 /*
05 结果如下
06 Array
07 (
08     [0] => Array
09         (
10             [0] => name=tank
11             [1] => sex=1#top
12         )
13     [1] => Array
14         (
15             [0] => name=tank
16             [1] => sex=1
17         )
18     [2] => Array
19         (
20             [0] =>
21             [1] => #top
22         )
23 )
24 */
25 ?>


路途漫漫...还有待继续挖掘...

在php中浮点数是一个非常有用的数据类型了,但是他同样也给我们带来很多的细节问题,下面我来举个实例来分析PHP浮点数的一个常见问题

先看看这段代码:

 代码如下 复制代码

<?php
    $f = 0.58;
    var_dump(intval($f * 100)); //为什么输出57
?>

为什么输出是57?

我相信有很多的同学有过这样的疑问,bugs.php.net上经也常有人问。

要搞明白这个原因, 首先我们要知道浮点数的表示(IEEE 754):

浮点数, 以64位的长度(双精度)为例, 会采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位).

符号位:最高位表示数据的正负,0表示正数,1表示负数。

指数位:表示数据以2为底的幂,指数采用偏移码表示

尾数:表示数据小数点后的有效数字.

这里的关键点就在于, 小数在二进制的表示, 关于小数如何用二进制表示, 大家可以百度一下, 我这里就不再赘述, 我们关键的要了解, 0.58 对于二进制表示来说, 是无限长的值(下面的数字省掉了隐含的1)..


0.58的二进制表示基本上(52位)是: 0010100011110101110000101000111101011100001010001111
0.57的二进制表示基本上(52位)是: 0010001111010111000010100011110101110000101000111101

而两者的二进制, 如果只是通过这52位计算的话,分别是:


0.58 -> 0.57999999999999996
0.57 -> 0.56999999999999995

至于0.58 * 100的具体浮点数乘法, 我们不考虑那么细, 有兴趣的可以看(Floating point), 我们就模糊的以心算来看… 0.58 * 100 = 57.999999999

那你intval一下, 自然就是57了….

可见, 这个问题的关键点就是: “你看似有穷的小数, 在计算机的二进制表示里却是无穷的”

so, 不要再以为这是PHP的bug了, 这就是这样的.

本文章介绍从url带参数传值与在表单中传值的获取方法,希望本文章对各位同学会带来帮助。

例子、单表单内容发送和接收

我们都是如果要实现内容发送或者接收我们首先都需要一个表单也就是form标签 下面这个是前端的html代码

 代码如下 复制代码

<form  action="1.php">
<p>Get 发送方式:
<input type="text" name="wz"/></p>

<p>Post 发送发送:
<input type="text" name="wz1"/></p>

<input type="submit" value="OK"/>
</form>

 

后台的php就是从上面的name内的值获取需要的内容

 

 代码如下 复制代码

<?php
$a = $_GET ['wz'];
if($a==null){echo "对方没输入"."</br>";}else{
echo "我是GET接收方式:".$a."</br>";}

$b = $_GET ['wz1'];
if($b==null){echo "对方没输入"."</br>";}else{
echo "我是POST接收方式:".$b."</br>";}
?>


这里的php意思以get模式来获取标签内属性name里面的值

然而echo 在php中就是打印出来 if就是先加以判断~ 注意:如果表单是post传值我们必须使用$_POST才可以接受数据

例子、url传值

 这个是要发送的php代码

   

 代码如下 复制代码

<?php
include_once('zq/db.php');
$sql = "select * from wd_sql";
$query=mysql_query($sql);
 $i = 1;
 while ($result = mysql_fetch_array($query)) {
 $x = $i++;
   "<br><a href='del.php?xx=".$result['id']."&ccxc=wd_sql'>删除</a>"//在这里实现了传值
}
?>


这个是接收值的php

 代码如下 复制代码

<?php
$uid = $_GET['xx'];
$db_sql = $_GET['ccxc'];
if(mysql_query($sql) == 1)
{echo "<script>alert('删除成功!');history.go(-1);</script>";}
?> 

[!--infotagslink--]

相关文章

  • PHP成员变量获取对比(类成员变量)

    下面本文章来给大家介绍在php中成员变量的一些对比了,文章举了四个例子在这例子中分别对不同成员变量进行测试与获取操作,下面一起来看看。 有如下4个代码示例,你认...2016-11-25
  • php 获取用户IP与IE信息程序

    php 获取用户IP与IE信息程序 function onlineip() { global $_SERVER; if(getenv('HTTP_CLIENT_IP')) { $onlineip = getenv('HTTP_CLIENT_IP');...2016-11-25
  • php获取一个文件夹的mtime的程序

    php获取一个文件夹的mtime的程序了,这个就是时间问题了,对于这个问题我们来看小编整理的几个例子,具体的操作例子如下所示。 php很容易获取到一个文件夹的mtime,可以...2016-11-25
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • 源码分析系列之json_encode()如何转化一个对象

    这篇文章主要介绍了源码分析系列之json_encode()如何转化一个对象,对json_encode()感兴趣的同学,可以参考下...2021-04-22
  • R语言 如何删除指定变量或对象

    这篇文章主要介绍了R语言删除指定变量或对象的操作方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-06
  • php中去除文字内容中所有html代码

    PHP去除html、css样式、js格式的方法很多,但发现,它们基本都有一个弊端:空格往往清除不了 经过不断的研究,最终找到了一个理想的去除html包括空格css样式、js 的PHP函数。...2013-08-02
  • 如何获取网站icon有哪些可行的方法

    获取网站icon,常用最简单的方法就是通过website/favicon.ico来获取,不过由于很多网站都是在页面里面设置favicon,所以此方法很多情况都不可用。 更好的办法是通过google提供的服务来实现:http://www.google.com/s2/favi...2014-06-07
  • jquery如何获取元素的滚动条高度等实现代码

    主要功能:获取浏览器显示区域(可视区域)的高度 : $(window).height(); 获取浏览器显示区域(可视区域)的宽度 :$(window).width(); 获取页面的文档高度 $(document).height(); 获取页面的文档宽度 :$(document).width();...2015-10-21
  • 解决vue的router组件component在import时不能使用变量问题

    这篇文章主要介绍了解决vue的router组件component在import时不能使用变量问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27
  • jquery获取div距离窗口和父级dv的距离示例

    jquery中jquery.offset().top / left用于获取div距离窗口的距离,jquery.position().top / left 用于获取距离父级div的距离(必须是绝对定位的div)。 (1)先介绍jquery.offset().top / left css: 复制代码 代码如下: *{ mar...2013-10-13
  • Jquery 获取指定标签的对象及属性的设置与移除

    1、先讲讲JQuery的概念,JQuery首先是由一个 America 的叫什么 John Resig的人创建的,后来又很多的JS高手也加入了这个团队。其实 JQuery是一个JavaScript的类库,这个类库集合了很多功能方法,利用类库你可以用简单的一些代...2014-05-31
  • index.php怎么打开?如何打开index.php?

    index.php怎么打开?初学者可能不知道如何打开index.php,不会的同学可以参考一下本篇教程 打开编辑:右键->打开方式->经文本方式打开打开运行:首先你要有个支持运行PH...2017-07-06
  • Vue select 绑定动态变量的实例讲解

    这篇文章主要介绍了Vue select 绑定动态变量的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-23
  • 深入理解PHP变量的值类型和引用类型

    在PHP中,大部分变量类型,如字符串,整型,浮点,数组等都是值类型的,而类和对象是引用类型,在使用的时候,需要注意这一点。看到网友在讨论PHP的&符号,要彻底理解它的用法,就有必要讨论一下变量的两种形式。PHP的变量在内存中是这样...2015-10-23
  • C#获取字符串后几位数的方法

    这篇文章主要介绍了C#获取字符串后几位数的方法,实例分析了C#操作字符串的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • PHP中func_get_args(),func_get_arg(),func_num_args()的区别

    复制代码 代码如下:<?php function jb51(){ print_r(func_get_args()); echo "<br>"; echo func_get_arg(1); echo "<br>"; echo func_num_args(); } jb51("www","j...2013-10-04
  • DOM XPATH获取img src值的query

    复制代码 代码如下:$nodes = @$xpath->query("//*[@id='main_pr']/img/@src");$prurl = $nodes->item(0)->nodeValue;...2013-10-04
  • jquery获取tagName再进行判断

    如果是为了取到tagName后再进行判断,那直接用下面的代码会更方便: $(element).is('input') 如果是要取到标签用作到别的地方,可以使用一下代码: $(element)[0].tagName 或: $(element).get(0).tagName...2014-05-31
  • java中String类型变量的赋值问题介绍

    下面小编就为大家带来一篇java中String类型变量的赋值问题介绍。小编觉得挺不错的。现在分享给大家,给大家一个参考。...2016-03-28