php trait 多重继承的实现案例
自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 traits。
Traits 是一种为类似 PHP 的单继承语言而准备的代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用方法集。Traits 和类组合的语义是定义了一种方式来减少复杂性,避免传统多继承和混入类(Mixin)相关的典型问题。
Trait 和一个类相似,但仅仅旨在用细粒度和一致的方式来组合功能。Trait 不能通过它自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用类的成员不需要继承。
在我理解说白了就是在继承类链中隔离了子类继承父类的某些特性(就是子类“要用父类的特性的时候”,如果trait有,就优先调用trait的方法、属性等)。
<?php
trait MyTrait
{
protected $var = "MyTrait_var";
protected $var1 = "MyTrait_var";
function __construct()
{
echo $this->var.PHP_EOL;
}
function a()
{
echo "a".PHP_EOL;
}
}
interface MyInterface
{
function __construct();
function b();
}
abstract class MyAbstract
{
protected $var2 = "MyAbstract_var";
use MyTrait;
function b()
{
echo "b".PHP_EOL;
}
}
class MyClass extends MyAbstract implements MyInterface
{
protected $var3 = "MyClass_var";
//也可以在这里引用,不区分继承关系
//use MyTrait;
function c()
{
echo "c".PHP_EOL;
}
}
$class = new MyClass();
$class->a();
$class->b();
$class->c();
输出结果
MyTrait_var
a
b
c
优先级
从基类继承的成员被 trait 插入的成员所覆盖,来自当前类的成员覆盖 trait 的方法。
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();
echo 'World!';
}
public function sayHellos() {
echo 'Hello World!';
}
}
class MyHelloWorld extends Base {
use SayWorld;
public function sayHellos() {
echo 'Hello Universe!';
}
}
$o = new MyHelloWorld();
$o->sayHello(); #Hello World!
$o->sayHellos(); #Hello Universe!
3、多个 trait
通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World';
}
}
class MyHelloWorld {
use Hello, World;
}
$o = new MyHelloWorld();
$o->sayHello(); # Hello
$o->sayWorld(); # World
4、多Traits冲突的解决
如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。
以上方式仅允许排除掉其它方法,as 操作符可以将其中一个冲突的方法以另一个名称来引入。
trait A{
public function smallTalk(){
echo 'a';
}
public function bigTalk(){
echo 'A';
}
}
trait B{
public function smallTalk(){
echo 'b';
}
public function bigTalk(){
echo 'B';
}
}
class Talker{
use A,B{
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
}
class Talkers{
use A,B{
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as bTalk;
}
}
$o = new Talker();
$o->smallTalk(); # b
$o->bigTalk(); # A
$os = new Talkers();
$os->smallTalk(); # b
$os->bigTalk(); #A
$os->bTalk(); # B
5、修改方法的访问控制
还可以使用as语法来改变Traits中函数的访问权限属性。
trait HelloRuesin {
public function sayHello() {
echo 'Hello Ruesin';
}
}
class Hello {
use HelloRuesin {
sayHello as protected; ## 修改 sayHello 的访问控制
}
}
class Ruesin {
use HelloRuesin {
sayHello as private sayHellos; ## 给方法一个改变了访问控制的别名 而原版 sayHello 的访问控制则没有发生变化
}
}
$o = new Hello();
$os = new Ruesin();
#$o->sayHello(); # 无法访问
$os->sayHello(); # Hello Ruesin
#$os->sayHellos(); # 无法访问
6、用Traits组成新Traits
正如类能够使用 trait 一样,其它 trait 也能够使用 trait。在 trait 定义时通过使用一个或多个 trait,它能够组合其它 trait 中的部分或全部成员。
trait Hello {
public function sayHello() {
echo 'Hello';
}
}
trait Ruesin {
public function sayRuesin() {
echo 'Ruesin';
}
}
trait HelloRuesin {
use Hello,Ruesin;
}
class SayHelloRuesin {
use HelloRuesin;
}
$o = new SayHelloRuesin();
$o->sayHello(); #Hello
$o->sayRuesin(); #Ruesin
7、Trait 的抽象成员
为了对使用的类施加强制要求,trait 支持抽象方法的使用。表示通过抽象方法来进行强制要求
trait Hello {
public function sayHelloRuesin() {
echo 'Hello '.$this->getName();
}
abstract public function getName();
}
class HelloRuesin {
private $name;
use Hello;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
(new HelloRuesin('Ruesin'))->sayHelloRuesin(); # Hello Ruesin
8、trait 的静态成员
静态变量可以被 trait 的方法引用,但不能被 trait 定义。Traits 能够为使用的类定义静态方法。
trait Counter {
public function inc() {
static $c = 0;
$c = $c + 1;
echo "$c\n";
}
public static function HelloRuesin() {
#return 'Doing something';
echo 'Hello Ruesin';
}
}
class C {
use Counter;
}
$o = new C();
$o->inc(); # 1
$o->inc(); # 2
C::HelloRuesin(); #Hello Ruesin'
9、Trait 定义属性
文章来自ruesin.com
如果 trait 定义了一个属性,那类将不能定义同样名称的属性,否则会产生一个错误。如果该属性在类中的定义与在 trait 中的定义兼容(同样的可见性和初始值)则错误的级别是 E_STRICT,否则是一个致命错误。
Ruesin's Blog
trait PropertiesTrait {
public $x = 1;
}
class PropertiesExample {
use PropertiesTrait;
#public $same = true; # Strict Standards
#public $different = true; # 致命错误
}
$example = new PropertiesExample;
$example->x; # 1
总结:
从本质上说,trait和include文件的概念差不多
trait可以更加方便的实现代码复用,因为我们用继承关系实现的无法在父类中访问子类的private属性与方法,而trait就和把代码直接写在对象里效果一样。
使用trait时候应该坚决避免命名冲突,尤其是同时使用多个trait时。
如果产生了命名冲突,如果两者的可见性、初始值、static与否完全相同,则trait中的会覆盖掉对象中的,并抛出E_STRICT错误,否则会抛出E_COMPILE_ERROR错误,终止编译。
方法1:
(最好的方法)在php.ini里加上找到date.timezone项,设置date.timezone = "Asia/Shanghai",重启环境就ok了。
方法2:
在需要用到这些时间函数的时候,在页面添加date_default_timezone_set("PRC");
方法3:
在页头加上设置时区ini_set('date.timezone','Asia/Shanghai');
总结,方法一和方法三一般要有服务器权限的才比较有效,而方法2技术人员就可以控制当前页面了,也是程序员比较常用的方法了。
PHP变量和定义变量名在开发中我多次有介绍过昨天也分享了相关的文章,下面我们再来看看关于变量在php中农常用的一些方法。1.定义常量define(“CONSTANT”, “Hello world.”);
常量只能包含标量数据(boolean,integer,float 和 string)。
调用常量时,只需要简单的用名称取得常量的值,而不能加“$”符号,如:echo CONSTANT;
注: 常量和(全局)变量在不同的名字空间中。这意味着例如 TRUE 和 $TRUE 是不同的。
2.普通变量$a = “hello”;
3.可变变量(使用两个美元符号($))
$$a = “world”;
两个变量都被定义了:
$a 的内容是“hello”并且 $hello 的内容是“world”。
因此,可以表述为:
echo “$a ${$a}”;或者 echo “$a $hello”;它们都会输出:hello world
要将可变变量用于数组,必须解决一个模棱两可的问题。这就是当写下 $$a[1] 时,解析器需要知道是想要 $a[1] 作为一个变量呢,还是想要 $$a 作为一个变量并取出该变量中索引为 [1] 的值。解决此问题的语法是,对第一种情况用 ${$a[1]},对第二种情况用 ${$a}[1]。
4.静态变量
在函数内部static $a = 0;
注意:声明中用表达式的结果对其赋值会导致解析错误如static $a =3+3;(error)
静态变量仅在局部函数域中存在(函数内部),函数执行完之后,变量值不会丢失,可用于递归调用
5.全局变量
在函数体内定义的global变量,函数体外可以使用,在函数体外定义的global变量不能在函数体内使用,在全局范围内访问变量可以用特殊的 PHP 自定义 $GLOBALS 数组:
如:$GLOBALS[“b”] = $GLOBALS[“a”] + $GLOBALS[“b”];
在一个函数域内用 global 语句导入的一个真正的全局变量实际上是建立了一个到全局变量的引用
global $obj;
注:对于变量的 static 和 global 定义是以 应用 的方式实现的
6.给变量赋值:传地址赋值(简单引用):
$bar = &$foo; //加&符号到将要赋值的变量前
改动新的变量将影响到原始变量,这种赋值操作更加快速
注意:只有命名变量才可以传地址赋值
注意:如果
$bar = &$a;
$bar = &$foo;
改变$bar的值只能改变变量foo的值,而不改变a的值(引用改变了)
7.PHP 超全局变量$GLOBALS :
包含一个引用指向每个当前脚本的全局范围内有效的变量。该数组的键标为全局变量的 名称。从 PHP 3 开始存在 $GLOBALS 数组。
$_SERVER : 变量由 Web 服务器设定或者直接与当前脚本的执行环境相关联。类似于旧数组 $HTTP_SERVER_VARS 数组(依然有效,但反对使用)。
$_GET : 经由 HTTP GET 方法提交至脚本的变量。
$_POST : 经由 HTTP POST 方法提交至脚本的变量。
$_COOKIE : 经由 HTTP Cookies 方法提交至脚本的变量。
$_FILES : 经由 HTTP POST 文件上传而提交至脚本的变量。
文件上传表单中要有 enctype=”multipart/form-data”
$_ENV : 执行环境提交至脚本的变量。
$_REQUEST :经由 GET,POST 和 COOKIE 机制提交至脚本的变量,因此该数组并不值得信任。所有包含在该数组中的变量的存在与否以及变量的顺序均按照 php.ini 中的 variables_order 配置指示来定义。该数组没有直接模拟 PHP 4.1.0 的早期版本。参见 import_request_variables()。
注意: 自 PHP 4.3.0 起,$_FILES 中的文件信息不再存在于 $_REQUEST 中。
$_SESSION :当前注册给脚本会话的变量。
如何禁用phpinfo():
php.ini中
disable_functions = phpinfo()
重启web服务器。
php中的常量
常量只能用define(常量名,常量值);
常量只能包含标量数据(boolean,integer,float 和 string)。
可以简单的通过指定其名字来取得常量的值,不要在常量前面加上 $ 符号。如果常量名是动态的,也可以用函数
constant() 来读取常量的值。用 get_defined_constants() 可以获得所有已定义的常量列表。
注: 常量和(全局)变量在不同的名字空间中。这意味着例如 TRUE 和 $TRUE 是不同的。
如果使用了一个未定义的常量,PHP 假定想要的是该常量本身的名字,如同用字符串调用它一样(CONSTANT 对应 “CONSTANT”)。此时将发出一个 E_NOTICE 级的错误。参见手册中为什么 $w3sky[bar] 是错误的(除非事先用 define() 将 bar 定义为一个常量)。如果只想检查是否定义了某常量,用 defined() 函数。
常量和变量不同:
* 常量前面没有美元符号($);
* 常量只能用 define() 函数定义,而不能通过赋值语句;
* 常量可以不用理会变量范围的规则而在任何地方定义和访问;
* 常量一旦定义就不能被重新定义或者取消定义;
* 常量的值只能是标量。
定义常量
< ?PHP
define("CONSTANT", "Hello world.");
echo CONSTANT; // outputs "Hello world."
echo Constant; // outputs "Constant" and issues a notice.
?>
一个PHP自动转化变量类型的例子是加法的操作符’+’。如果任何一个操作数都是双精度数,那么所有的操作数被当作双精度数求值,并且结果也是双精度数。 否则,操作数将被认为是整数,结果也将会是整数。注意这并不影响每个操作数本身的变量类型,唯一的变化就是操作数在计算的过程中被如何处理。
$foo = "0"; // $foo 是一个字符串 ,值是“0”(ASCII 48)
$foo++; // $foo 是一个字符串,值是“1”(ASCII 49)
$foo += 1; // $foo 现在是一个整数(2)了
$foo = $foo + 1.3; // $foo 现在是一个双精度数(3.3)了
$foo = 5 + "10 Little Piggies"; // $foo 是一个整数 (15)
$foo = 5 + "10 Small Pigs"; // $foo 是一个整数 (15)
如果你觉得上面例子中最后两个表达式看起来有点奇怪的话,请看 “字符串的转化”部分。
如果你希望强制一个变量被当作某种固定的类型来计算,请看 “类型强制(casting)” 一节。如果你希望转变一个变量的类型,请看函数“settype()”的说明。
确定一个变量的类型
因为PHP自己决定变量的类型并且一般按照需要转化他们,一个特定的变量的类型不是在任何时间都非常明显。PHP包括一些函数可以找出这个变量的类型。这 些函数是gettype(), is_long(), is_double(), is_string(), is_array(), 和 is_object().
类型强制(type casting)
在PHP中类型强制同在C语言中大抵相似:将需要的类型的种类写在要强制的变量的前面的圆括号中。
$foo = 10; // $foo 是一个整数
$bar = (double) $foo; // $bar 是一个双精度数
以下的强制方式是允许的:
(int), (integer) – 强制成整数
(real), (double), (float) – 强制成双精度数
(string) – 强制成字符串
(array) – 强制成数组
(object) – 强制成对象
注意在圆括号中允许制表符(tabs)和空格(spaces) ,因此下面的语句是等价的:
$foo = (int) $bar;
$foo = ( int ) $bar;
字符串转化
当一个字符串被当作数字型的值来计算时,他的结果和类型如下面所述的决定。
如果这个字符串含有字符’.’,’e’,或者’E’,则被当作双精度类型变量来处理,否则当作是整数。
这个字符串的值由词首部分决定。如果这个字符串以任何有效的数字的数据开始,那么这个数字数据就是这个字符串参加运算的值。否则,值为零(zero)。有 效的数字数据是遵循下面的这些标记的,跟随在一个或多个数字后面(可以包含小数点),跟随在一个可选的指数后面。指数是由一个或多个数字跟在’e’或 ’E’后面构成的。
$foo = 1 + "10.5"; // $foo 是双精度数 (11.5)
$foo = 1 + "-1.3e3"; // $foo 是双精度数(-1299)
$foo = 1 + "bob-1.3e3"; // $foo 是整数 (1)
$foo = 1 + "bob3"; // $foo 是整数 (1)
$foo = 1 + "10 Small Pigs"; // $foo 是整数 (11)
$foo = 1 + "10 Little Piggies"; // $foo 是整数 (11);
// 这个字符串包括字符’e’
以下三种写法中,哪种是正确的?
在php程序中,变量的命名规则是怎样的,以下三种写法中,哪种是正确的?
第1种:
<?php
$myname='aa';
?>
第2种:
<?php
$myName='aa';
?>
第3种:
<?php
$MyName='aa';
?>
经验分享
姓名,年龄:
<?php
/*
*变量名字以$开头
*变量的名称声明时一定要有意义
*变量不能以数字开头命名,可以用下划线开头,$和变量名不能有空格
*变量名中不能出现运算符号:加减乘除
*别的编程语言变量可能不能出现系统关键字,不过php可以,因为php有一个$
*/
$name = "毕恩竹";
$age = 20;
$php = 40;
echo $age;
变量名称区只有部分大小写
<?php
/*
$int和$INT区分大小写,echo不区分大小写
*/
$int = 10;
$INT = 20;
echo $int,"<br>";
eCho $INT;
驼峰式命名方式:one two three
<?php
$oneTwoThree = 10;
变量是用于临时存储值得容器。这些值可以是数字、文本、或者复杂得多的排列组合。是用于跟踪几乎所有类型信息的简单工具。
PHP是一种非常弱的类型语言。在大多数编程语言中,变量只能保持一种类型的数据,而且这个类型必须在使用变量前声明,例如C语言中。而在PHP中,变量的类型必须在使用变量前声明,例如C语言中。而在PHP中,变量的类型通常不是由程序员设定的,确切地说,是根据该变量使用的上下文在运行时(即变量的值)决定的。PHP不要求在使用变量之前声明变量,当第一次给第一个变量赋值时,你才创建了这个变量。
PHP的变量声明是以$符开始的,后面跟大小写字母,数字和下划线,但不能以数字开头。
<?php
$a=100; //声明一个变量a,赋予整数100
$b=”string”; //声明一个变量b,赋予字符串string
$c=true //声明一个变量c,赋予布尔值true
$d=99.99; //声明一个变量d,赋予浮尔点99.99
$key=$a; //声明一个key变量,并将a变量的值赋予
$a=$b=$c=$d=”value” //同时声明多个变量,并赋予相同的值
可以使用函数()释放指定的变量,isset()函数检测变量是否设置,empty()数数检查一个变量是否为空
同时声明多个变量
<?php
$a = $b = $c =$d =10;
echo $a;
echo "<br>";
echo $b;
echo "<br>";
echo $c;
echo "<br>";
echo $d;
echo "<br>";
var_dump();可以打印输出变量类型和内容
<?php
var_dump(10);
$a=100;
var_dump($a);
isset()函数检测变量是否设置
<?php
$bool = isset($a);
var_dump($bool);
$a = 20;
$bool = isset($a);
var_dump($bool);
unset();删除一个变量
<?php
$a = 20;
unset($a);
$bool = isset($a);
var_dump($bool);
empty()数数检查一个变量是否为空,空的话返回true
<?php
$a = 20;
$b = '';
$c = 0;
$d = null;
$e = ' ';
var_dump(empty($a));
var_dump(empty($b));
var_dump(empty($c));
var_dump(empty($d));
var_dump(empty($e));
var_dump(empty($f));
回到文章开头,我们来看看如何解答
总结
1、各人喜好没有一定之规
2、目前的php对变量是不区分大小写的(据说php6将区分大小写)所以$myName='aa';被写成$myname='aa';时效果不便但可读性较差不如 $my_name='aa';清爽
3、对于区分大小写的语言,一般推荐使用“匈牙利表示法”
变量名由变量类型和若干以大写字母开头的表示变量含义的单词组成
比如
$myname='aa';
就写做
$sMyName='aa';
而
$myname=1;
就写做
$iMyName=1;
4、对于不区分大小写的语言,一般建议变量名由若干由下划连接的表示变量含义的单词组成
比如
$myname='aa';
就写做
$my_name='aa';
相关文章
- php语言实现redis的客户端与服务端有一些区别了因为前面介绍过服务端了这里我们来介绍客户端吧,希望文章对各位有帮助。 为了更好的了解redis协议,我们用php来实现...2016-11-25
- 有时我们在页面上需要选择数值范围,如购物时选取价格区间,购买主机时自主选取CPU,内存大小配置等,使用直观的滑块条直接选取想要的数值大小即可,无需手动输入数值,操作简单又方便。HTML首先载入jQuery库文件以及jRange相关...2015-03-15
- 本文实例讲述了JS实现的简洁纵向滑动菜单(滑动门)效果。分享给大家供大家参考,具体如下:这是一款纵向布局的CSS+JavaScript滑动门代码,相当简洁的手法来实现,如果对颜色不满意,你可以试着自己修改CSS代码,这个滑动门将每一...2015-10-21
jQuery+slidereveal实现的面板滑动侧边展出效果
我们借助一款jQuery插件:slidereveal.js,可以使用它控制面板左右侧滑出与隐藏等效果,项目地址:https://github.com/nnattawat/slideReveal。如何使用首先在页面中加载jquery库文件和slidereveal.js插件。复制代码 代码如...2015-03-15- 翻板抽奖的实现流程:前端页面提供6个方块,用数字1-6依次表示6个不同的方块,当抽奖者点击6个方块中的某一块时,方块翻转到背面,显示抽奖中奖信息。看似简单的一个操作过程,却包含着WEB技术的很多知识面,所以本文的读者应该熟...2015-10-21
SQLMAP结合Meterpreter实现注入渗透返回shell
sqlmap 是一个自动SQL 射入工具。它是可胜任执行一个广泛的数据库管理系统后端指印, 检索遥远的DBMS 数据库等,下面我们来看一个学习例子。 自己搭建一个PHP+MYSQ...2016-11-25- 复制代码 代码如下: // 第一种写法 $da = date("w"); if( $da == "1" ){ echo "今天是星期一"; }else if( $da == "2" ){ echo "今天是星期二"; }else if( $da == "3" ){ echo "今天是星期三"; }else if( $da == "4"...2013-10-04
- js里面设置DOM节点透明度的函数属性:filter= "alpha(opacity=" + value+ ")"(兼容ie)和opacity=value/100(兼容FF和GG)。 先来看看设置透明度的兼容性代码: 复制代码 代码如下: function setOpacity(ele, opacity) { if (...2014-06-07
- 本文我们需要解决的问题是如何实现Http请求来实现通信,解决Android 2.3 版本以后无法使用Http请求问题,下面请看正文。 Android开发中使用HttpClient来开发Http程序...2016-09-20
- 复制代码 代码如下:call PROCEDURE_split('分享,代码,片段',',');select * from splittable;复制代码 代码如下:drop PROCEDURE if exists procedure_split;CREATE PROCEDURE `procedure_split`( inputstring varc...2014-05-31
- 这篇文章主要介绍了c# 继承的相关资料,文中讲解的非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-11-03
- 这篇文章主要为大家详细介绍了php构造方法中析构方法在继承中的表现,感兴趣的小伙伴们可以参考一下...2016-04-15
- 这篇文章主要介绍了javascript中的3种继承实现方法,包括使用Object.create实现类式继承、使用utilities工具包自带的util.inherites、使用extends关键字,非常的实用,希望对大家了解javascript继承能够有所帮助...2016-01-30
- JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一,那么这篇文章主要给大家介绍了关于原生Javascript实现继承方式及其优缺点的相关资料,需要的朋友可以参考下...2021-07-21
- 这篇文章主要为大家举例介绍了js对象继承的几种模式,内容很全面,感兴趣的小伙伴们可以参考一下...2016-01-26
- 这篇文章主要给大家介绍了关于js继承的6种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-06
- 基本思想就是:在JS动态创建select控件的option,通过Ajax获取在PHP从SQL数据库获取的省市区信息,代码有点长,但很多都是类似的,例如JS中省、市、区获取方法类似,PHP中通过参数不同执行不同的select语句。index.html代码:复制...2014-05-31
- 下面代码用JS实现了程序的暂停与继续 复制代码 代码如下: <script type="text/javascript"> /*Javascript中暂停功能的实现 Javascript本身没有暂停功能(sleep不能使用)同时 vbscript也不能使用doEvents,故编写此函数实...2013-10-13
- 这篇文章主要介绍了JavaScript中的封装与继承特性,封装与继承是基于对象编程概念中的基本特性,需要的朋友可以参考下...2016-03-22
Spring Cloud中使用Feign,@RequestBody无法继承的解决方案
这篇文章主要介绍了Spring Cloud中使用Feign,@RequestBody无法继承的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-22