php类中protected与const属性详解
const属性
用const属性定义的字段是一个常量,类中的常量和静态变量类似,不同之处就是常量的值一旦赋值不能被改变.const定义常量不需要加$符号,其结构形式如下:
const 常量名称 //常量名称不能用$符号
1、常量属性用 const 关键字来声明,不像常规属性一样用美元符$开头;
2、按照惯例,只能用大写字母来命名常量;
3、和全局变量一样,类常量一旦设置后就不能改变;
4、只包含基本数据类型的值,不能将一个对象指派给常量;
5、像静态属性一样,只能通过类而不能通过类的实例(对象)访问常量;
6、引用常量时不需要用美元符号为前导符;
7、给已经声明过的常量赋值会引起解析错误;
8、当需要在类的所有示例中都能访问某个属性,并且属性值无需改变时,应该使用常量。
代码如下 | 复制代码 |
<?php |
protected属性
protected限定的字段作用域在public和private之间,若该成员被声明称protected(保护),则代表只能在该类和该类的子类中使用该字段.
实例代码如下:
代码如下 | 复制代码 |
class me{ protected $Money =100; protected $price1=60; public function Sell($price){ if($this->price1<=$price){ echo "好,卖给你了. "; $this->Money = $this->Money+$price; return "我现在总共有 ".$this->Money." 元钱"; } else{ echo "我不卖 ,$price 太便宜了 "; return "现在我还是 ".$this->Money." 元钱"; } } } $now=new me; echo $now->Sell(30); ?> |
我们要在利用Content-type:text/json才可以正常显示是json数据哦。
代码如下 | 复制代码 |
<?php |
json_encode当然也可以输入json字符串了,下面看几个例子。
PHP生成JSON的函数是:json_encode($PHPcode);
PHP解析JSON的函数是:json_decode($JSONcode);
所以JSON的形式有多种,不同的形式在PHP解释出来后的形式也是不同的。
//形式1:完全是对象的形式,这种形式的数据在Javascript中又叫相关数组,与一般数组不同的是,它可以通过字符串作索引来访问(用“[]”或“.”来表示层级)
代码如下 | 复制代码 |
$json='{"item1":{"item11":{"n":"chenling","m":"llll"},"sex":"www.111cn.net","age":"25"},"item2":{"item21":"ling","sex":"女","age":"24"}}'; [sex] => www.111cn.net [item2] => stdClass Object |
比如说我要取得了值是chenling的那个属性,则应该这样访问:
$J->item1->item11->n;//这将取得属性n的值:chenling
其实这种访问形式跟访问普通的对象属性差不多,也相当于访问一个3维数组。
//形式2:对象和数组混合
代码如下 | 复制代码 |
$json='{"item1":[{"name":[{"chen":"chenling","ling":"chenli"}],"sex":"男","age":"25"},{"name":"sun","sex":"女","age":"24"}]}'; ) [sex] => 男 [1] => stdClass Object ) ) |
比如说我要取得了值是chenling的那个元素,则应该这样访问:
$J->item1[0]->name[0]->chen;//这将取得元素chen的值:chenling
其实这种访问形式结合了对象和数组的访问方式,也相当于访问一个5维数组。
//形式3:完全数组形式
代码如下 | 复制代码 |
$json='[["item1","item11"],["n","chenling"],["m","llll"]]'; [1] => Array [2] => Array |
比如说我要取得了值是chenling的那个元素,则应该这样访问:
$J[0][1];//这将取得元素值chenling的那个元素
但是用这种方式有一个缺点,就是无法用字符串作为索引,只能用数字,用完全对象的形式可以解决这个问题
其实这种访问形式就是数组的访问方式,相当于访问一个2维数组。
小结:
从上面的例子可以看出JSON有点类似XML,也可以在PHP和Javascript之间传递带结构的数据,使用起来很方便。
我大概是这样做的:
(1)生成用户验证token
用户登录后我会生成一个token,该token可能由如下信息组成:username+ip+expiration+salt【只是举例】,然后将组成信息用可逆加密函数加密得到token,并将该token保存到数据库,写入cookie;
(2)最后这样去校验信息,判断用户的登录状态
将token解密,验证用户username,如果存在,继续;然后验证token是否和存入数据库的token相同,如果相同继续;验证cookie的有效期expiration,如果有效继续;验证ip是否变化,若变化跳入登录。。。。。。甚至还可以验证user agent.
例子
php session应用实例--登录验证:
代码如下 | 复制代码 |
<html> <body> ------------------------------------------------------------------------------------------------------------------------- <?php ------------------------------------------------------------------------------------------------------------------------- <?php session_start(); // 最后彻底销毁session. echo "注销成功"; <?php 由此我们可以得出删除Session的步骤: -------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------cookie登录验证实例---------------------------------------------
<body> ------------------------------------------------------------------------------------------------------------------------- <?php ------------------------------------------------------------------------------------------------------------------------- <?php ------------------------------------------------------------------------------------------------------------------------- <?php
|
最后说明:
1.上面保证了token每次登录都会不一样,这回导致之前的token【既cookie】失效
2.cookie的有效期最好不超过一周
3.在客户端COOKIES中保存用户ID和一个加密码(规则只有我知道)
4.如果程序检测到客户端保存的COOKIES ID。就去跟数据库验证加密码,如果一致则返回对应用户的登录信息,否则返回FALSE
感觉效率和安全性都不是很好
1.用户访问每个页面都要去跟数据库验证一遍
2.加密码虽然规则很复杂,但是保存在客户端依然存在被破解的可能性
2、使用命名空间为了解决什么问题?
. 解决名字冲突,比如定义了一个类,正好这个类与PHP内部的类或是include进来的一个类库里的类重名了。
. 提高代码可读性,命名空间有一个别名功能,它可以帮你给一个长达十几个字符的类名起一个别名,从而缩短代码,也不用担心与其他空间的命名冲突。
3、哪一些代码会受命名空间的影响。
三类:类、函数、常量。只有它们兄弟三受影响,其他的该干嘛,还干嘛去。说到常量,php 5.3以后可以使用const关键字来定义常量,5.3这前使用define,命名空间只对const关键字有效。
4、命名空间如何定义
代码如下 | 复制代码 |
namespace MyProject; #例子二 namespace MyProjectSubLevel; const CONNECT_OK = 1;//php5.3以后 |
使用 `namespace 空间名` 来申明一个空间,在namespace之前除了declare语句不能有任何其他php语句,同时也不能有任何非php代码,连空格都不能有。
以下为错误的形式
代码如下 | 复制代码 |
$a = 1; |
另外同一个命名空间是可以定义在多个文件中,这对于组织框架是非常有用的。即以同一个namespace MyProject;开头的文件,它们是同一个命名空间。所以注意文件之间可不要有相同的类/函数/常量名哦。
当然同一个文件也可以定义多个命名空间,不过非常不建议这样做的。(了解同一个文件定义多个命名空间)
5、命名空间如何使用
命名空间有三种使用形式:
. 非限定名称 -- 没有使用任何的分割符,直接使用类/函数/常量名,如:new Foo(); foo(); echo FOO; 当文件有使用命名空间时,
代码如下 | 复制代码 |
<?php namespace MyObject; new Foo(); // 调用MyObjectFoo(); foo(); //调用MyObjectFoo(); echo FOO; //调用MyObjectFOO; |
. 非完全限定名称 -- 不是以分割符开头,如 new SubFoo(); 这种形式与非限定名称方式一样。
代码如下 | 复制代码 |
<?php |
. 完全限定名称 -- 以分割符开头的方式,相当于操作系统里的绝对地址。如 new OtherNSFoo();
代码如下 | 复制代码 |
<?php |
Tip: 对于函数和常量,还有一个特殊的地方(后备全局函数/常量)。
代码如下 | 复制代码 |
<?php |
对于类,也有一个特殊的地方。
代码如下 | 复制代码 |
<?php |
//注意对于类是不会去自动去调用全局作用域下的类的。*/
之前说了,命名空间还有一个用途-取别名。
代码如下 | 复制代码 |
namespace MyObject; new Foo(); //调用MyObjectFoo(); |
6、动态命名空间
动态总是能让人摸不着头脑,然而又带来灵活性。命名空间同样可以使用动态语言特点,但要注意由于直接调用命名空间是编译时解析的,而动态特征并非编译时解析。所以一定要加前缀。如:
代码如下 | 复制代码 |
namespace MyObjectSub; |
附1:同一个文件定义多个命名空间
方法有两种:
代码如下 | 复制代码 |
namespace MyProject; |
方法一,记流水帐。
代码如下 | 复制代码 |
namespace MyProject { const CONNECT_OK = 1; |
方法二,使用大括号把同一个命名空间的代码放在大括号里。这种方法,要求在大括号外不能有任何除了declare之外的代码。对于全局作用域的代码使用没有空间名的大括号包围起来
下面本文章来给大家介绍在php中成员变量的一些对比了,文章举了四个例子在这例子中分别对不同成员变量进行测试与获取操作,下面一起来看看。有如下4个代码示例,你认为他们创建对象,并获得成员变量的速度排序是怎样的?
1:将成员变量设置为public,通过赋值操作给成员变量赋值,直接获取变量
代码如下 | 复制代码 |
class Foo { class Foo2 { |
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' 1 ZEND_FETCH_CLASS 4 :10 'Foo2' 1 ZEND_FETCH_CLASS 4 :15 'Foo3' 1 ZEND_FETCH_CLASS 4 :21 'Foo4' |
根据上面的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语法结构的不要用函数,能使用内置函数的不要自己写,能用函数的不要用对象
相关文章
- 这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
- 以前我们开发大型项目时都会用到svn来同步,因为开发产品的人过多,所以我们会利用软件来管理,今天发有一居然可以利用php来管理svn哦,好了看看吧。 代码如下 ...2016-11-25
- 操作类就是把一些常用的一系列的数据库或相关操作写在一个类中,这样调用时我们只要调用类文件,如果要执行相关操作就直接调用类文件中的方法函数就可以实现了,下面整理了...2016-11-25
- 这篇文章主要介绍了源码分析系列之json_encode()如何转化一个对象,对json_encode()感兴趣的同学,可以参考下...2021-04-22
- PHP去除html、css样式、js格式的方法很多,但发现,它们基本都有一个弊端:空格往往清除不了 经过不断的研究,最终找到了一个理想的去除html包括空格css样式、js 的PHP函数。...2013-08-02
- 本文实例讲述了JS+CSS实现分类动态选择及移动功能效果代码。分享给大家供大家参考,具体如下:这是一个类似选项卡功能的选择插件,与普通的TAb区别是加入了动画效果,多用于商品类网站,用作商品分类功能,不过其它网站也可以用,...2015-10-21
- 本文章来人大家介绍一个php文件上传类的使用方法,期望此实例对各位php入门者会有不小帮助哦。 简介 Class.upload.php是用于管理上传文件的php文件上传类, 它可以帮...2016-11-25
- js修改input的type属性有些限制。当input元素还未插入文档流之前,是可以修改它的值的,在ie和ff下都没问题。但如果input已经存在于页面,其type属性在ie下就成了只读属性了,不可以修改。...2013-10-19
- index.php怎么打开?初学者可能不知道如何打开index.php,不会的同学可以参考一下本篇教程 打开编辑:右键->打开方式->经文本方式打开打开运行:首先你要有个支持运行PH...2017-07-06
- 无限级分类在开发中经常使用,例如:部门结构、文章分类。无限级分类的难点在于“输出”和“查询”,例如 将文章分类输出为<ul>列表形式; 查找分类A下面所有分类包含的文章。1.实现原理 几种常见的实现方法,各有利弊。其中...2015-10-23
- 在一些复杂的系统中,要求对信息栏目进行无限级的分类,以增强系统的灵活性。那么PHP是如何实现无限级分类的呢?我们在本文中使用递归算法并结合mysql数据表实现无限级分类。 递归,简单的说就是一段程序代码的重复调用,当把...2015-10-23
- 这篇文章主要介绍了C#类中static变量用法,实例分析了static变量使用技巧与相关注意事项,需要的朋友可以参考下...2020-06-25
- 这篇文章主要为大家介绍了Vue的计算属性,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助...2021-11-16
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- 这篇文章主要介绍了mybatis-plus实体类主键策略有3种(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-08-27
- ecshop商品无限级分类代码 function cat_options($spec_cat_id, $arr) { static $cat_options = array(); if (isset($cat_options[$spec_cat_id]))...2016-11-25
- 在php中要实现分页比起asp中要简单很多了,我们核心就是直接获取当前页面然后判断每页多少再到数据库中利用limit就可以实现分页查询了,下面我来详细介绍分页类实现程序...2016-11-25
- 这篇文章主要介绍了PHP编程 SSO详细介绍及简单实例的相关资料,这里介绍了三种模式跨子域单点登陆、完全跨单点域登陆、站群共享身份认证,需要的朋友可以参考下...2017-01-25
- 这篇文章主要介绍了PHP实现创建以太坊钱包转账等功能,对以太坊感兴趣的同学,可以参考下...2021-04-20
- System.Threading.Timer 是一个简单的轻量计时器,它使用回调方法并由线程池线程提供服务。在必须更新用户界面的情况下,建议不要使用该计时器,因为它的回调不在用户界面线程上发生...2020-06-25