深入分析PHP运算符优先级

 更新时间:2016年11月25日 14:59  点击:1330
刚看PHP手册中 Boolean 布尔类型 数据类型时,看到了评论中一个关于运算符优先级的问题,以前也讲过在实际项目中不要出现这些需要人为判断运算符优先级的代码,都应该使用括号来规避这个问题的出现

周五一朋友来着一段代码来问我,说他看不懂这段代码,觉得这段代码有问题,代码类似:

 代码如下 复制代码

$array1 = array(1, 2);
$array2 = array(3, 4);

$result = empty($array1) == 3 ? $array1 : $array2;

我一看应该是运算符优先级的问题。
按理说,这些运算符优先级的问题是不应该让它出现在项目代码中的,只能让它在面试问题中,程序员应该在书写代码过程中使用括号来避免这种不确定问题的出现。项目中的代码应该是那种我们一看就知道结果的,而不是需要我们费劲脑子才能知道结果的。这种优先级代码的结果有时候并不是我们相信的那样,看看下面的例子:

 代码如下 复制代码

<?php
if ($a = 100 && $b = 200) {
     var_dump($a, $b);
}

上面代码也许你会认为是:

 代码如下 复制代码
<?php
if ($a = (100 && $b) = 200) {
     var_dump($a, $b);
}

但是实际上不是这样的,实际结果是:

 代码如下 复制代码
<?php
if ($a = (100 && $b = 200)) {
     var_dump($a, $b);
}

至于为什么会这样?那是因为PHP并不完全遵守优先级的定义,PHP手册上中有说明

Note: Although = has a lower precedence than most other operators, PHP will still allow expressions similar to the following: if (!$a = foo()), in which case the return value of foo() is put into $a.

代码:

代码1:

 代码如下 复制代码

<?php
$x=TRUE;
$y=FALSE;
$z=$y OR $x; ?>
代码2:
<?php
$x=TRUE;
$y=FALSE;
$z=$y || $x;
?>

这种代码在实际项目中是不应该出现的,都应该用下面的代码替换:

 代码如下 复制代码

$z = ($y OR $x);

$z = ($y || $x);

这是最简单的类型。 boolean 表达了真值,可以为 TRUE 或 FALSE ,布尔类型也是我们开发中常碰到的功能,下面我就来给各位同学整理一下它的用法。

语法:

要指定一个布尔值,使用关键字 TRUE 或 FALSE 。两个都不区分大小写。 

 

 代码如下 复制代码
<?php
$foo  =  True ;  // assign the value TRUE to $foo
?>

通常运算符所返回的 boolean 值结果会被传递给控制流程。 

 代码如下 复制代码

<?php
// == 是一个操作符,它检测两个变量是否相等,并返回一个布尔值
if ( $action  ==  "show_version" ) {
    echo  "The version is 1.23" ;
}

// 这样做是不必要的...
if ( $show_separators  ==  TRUE ) {
    echo  "<hr>n" ;
}

// ...因为可以使用下面这种简单的方式:
if ( $show_separators ) {
    echo  "<hr>n" ;
}
?>

转换为布尔值

要明确地将一个值转换成 boolean ,用 (bool) 或者 (boolean) 来强制转换。但是很多情况下不需要用强制转换,因为当运算符,函数或者流程控制结构需要一个 boolean 参数时,该值会被自动转换。 

当转换为 boolean 时,以下值被认为是 FALSE : 


1.布尔值 FALSE 本身
2.整型值 0(零)
3.浮点型值 0.0(零)
4.空字符串,以及字符串 "0"
5.不包括任何元素的数组
6.不包括任何成员变量的对象(仅 PHP 4.0 适用)
7.特殊类型 NULL(包括尚未赋值的变量)
8.从空标记生成的 SimpleXML 对象
所有其它值都被认为是 TRUE (包括任何资源)。

注意:1 和其它非零值(不论正负)一样,被认为是 TRUE ! 

 

 代码如下 复制代码
<?php
var_dump ((bool)  "" );         // bool(false)
var_dump ((bool)  1 );          // bool(true)
var_dump ((bool) - 2 );         // bool(true)
var_dump ((bool)  "foo" );      // bool(true)
var_dump ((bool)  2.3e5 );      // bool(true)
var_dump ((bool) array( 12 ));  // bool(true)
var_dump ((bool) array());    // bool(false)
var_dump ((bool)  "false" );    // bool(true)
?>
作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。


单例模式的特点:

1、构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化;

2、拥有一个保存类的实例的静态成员变量

3、拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)

另外,需要创建__clone()方法防止对象被复制(克隆)

DEMO(链接数据库):

 代码如下 复制代码

/* 例子:数据库连接职责的集中控制 */
class Database {
 
private $_db;
static $_instance;
 
private function __construct() {
$this->_db = pg_connect('dbname=example_db');
}
 
private __clone() {};
 
public static function getInstance() {
 if(! (self::$_instance instanceof self) )
 {
 self::$_instance = new self();
 }
 return self::$_instance;
 
}
 
public function query($sql) {
// 使用 $this->_db 执行一个查询
return pg_query($this->_db, $sql);
}
}

文章主要是一个站长在学习php过程中一些用到的函数与方法及对各种方法的理解与简单的实例,下面全部放出来希望对你学习php有帮助。

PHP使用header函数设置HTTP头的示例方法

 代码如下 复制代码

//定义编码
header( Content-Type:text/html;charset=utf-8 );
//Atom
header(Content-type: application/atom+xml);
//CSS
header(Content-type: text/css);
//Javascript
header(Content-type: text/javascript);
//JPEG Image
header(Content-type: image/jpeg);
//JSON
header(Content-type: application/json);
//PDF
header(Content-type: application/pdf);
//RSS
header(Content-Type: application/rss+xml; charset=ISO-8859-1);
//Text (Plain)
header(Content-type: text/plain);
//XML
header(Content-type: text/xml);
// ok
header(HTTP/1.1 200 OK);
//设置一个404头:
header(HTTP/1.1 404 Not Found);
//设置地址被永久的重定向
header(HTTP/1.1 301 Moved Permanently);
//转到一个新地址
header(Location: http://www.example.org/);
//文件延迟转向:
header(Refresh: 10; url=http://www.example.org/);
print You will be redirected in 10 seconds;
//当然,也可以使用html语法实现
// <meta http-equiv="refresh" content="10;http://www.example.org/ />
// override X-Powered-By: PHP:
header(X-Powered-By: PHP/4.4.0);
header(X-Powered-By: Brain/0.6b);
//文档语言
header(Content-language: en);
//告诉浏览器最后一次修改时间
$time = time() - 60; // or filemtime($fn), etc
header(Last-Modified: .gmdate(D, d M Y H:i:s, $time). GMT);
//告诉浏览器文档内容没有发生改变
header(HTTP/1.1 304 Not Modified);
//设置内容长度
header(Content-Length: 1234);
//设置为一个下载类型
header(Content-Type: application/octet-stream);
header(Content-Disposition: attachment; filename="example.zip");
header(Content-Transfer-Encoding: binary);
// load the file to send:
readfile(example.zip);
// 对当前文档禁用缓存
header(Cache-Control: no-cache, no-store, max-age=0, must-revalidate);
header(Expires: Mon, 26 Jul 1997 05:00:00 GMT); // Date in the past
header(Pragma: no-cache);
//设置内容类型:
header(Content-Type: text/html; charset=iso-8859-1);
header(Content-Type: text/html; charset=utf-8);
header(Content-Type: text/plain); //纯文本格式
header(Content-Type: image/jpeg); //JPG***
header(Content-Type: application/zip); // ZIP文件
header(Content-Type: application/pdf); // PDF文件
header(Content-Type: audio/mpeg); // 音频文件
header(Content-Type: application/x-shockw**e-flash); //Flash动画

//显示登陆对话框
header(HTTP/1.1 401 Unauthorized);
header(WWW-Authenticate: Basic realm="Top Secret");
print Text that will be displayed if the user hits cancel or ;
print enters wrong login data;

php中static静态变量的使用方法详解
php中的变量作用范围的另一个重要特性就是静态变量(static 变量)。静态变量仅在局部函数域中存在且只被初始化一次,当程序执行离开此作用域时,其值不会消失,会使用上次执行的结果。

编程实例:

 代码如下 复制代码
function test()
{
  static $aa = 0;
  return $aa++;
}
$aa = "1000";
echo $aa;
echo test();
echo test();
echo $aa;
 

本函数每调用test()都会输出 $aa的值并加一。
上文代码运行输出:

1000
0
1
1000
 静态变量也提供了一种处理递归函数的方法。递归函数是一种自己调用自己的方法。写递归函数时要小心,因为可能会无穷递归下去,没有出口.务必确保 有方法来中止递归。

一维数组按照元素或者键值分组变为二维数组
有时候查询数据库记录后会对数据库查询结果进行分组,即将一维数组变为二维数组,方便调用使用(通常是json)

 代码如下 复制代码

$arr = array(
    '0'=>array(
            'firmware'=>'f1',
            'version'=>'1',
        ),
    '1'=>array(
            'firmware'=>'f1',
            'version'=>'2',
        ),
    '2'=>array(
            'firmware'=>'f1',
            'version'=>'3',
        ),
    '3'=>array(
            'firmware'=>'f2',
            'version'=>'1',
        ),
    '4'=>array(
            'firmware'=>'f2',
            'version'=>'2',
        ),
    );
    $new_arr  =  array();
    foreach ($arr as $row ){
        $new_arr[$row['firmware']][] = $row['version'];
    }
    var_dump($new_arr);
转换后

Array
(
    [f1] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

    [f2] => Array
        (
            [0] => 1
            [1] => 2
        )

)

PHP的静态绑定和动态绑定(private/public)
子类Foo的对象调用了test()方法,test()方法调用了$this->testPrivate();这个$this此时应该是子类的引用,按理说应该调用子类的testPrivate()方法,实际上却调用了父类的testPrivate()方法

 代码如下 复制代码

class Bar
{
    public function test() {
        $this->testPrivate();
        $this->testPublic();
    }

    public function testPublic() {
        echo "Bar::testPublicn";
    }
   
    private function testPrivate() {
        echo "Bar::testPrivaten";
    }
}

class Foo extends Bar
{
    public function testPublic() {
        echo "Foo::testPublicn";
    }
   
    private function testPrivate() {
        echo "Foo::testPrivaten";
    }
}

$myFoo = new Foo();
$myFoo->test();
// 运行结果
// Bar->testPrivate
// Foo->testPublic

这是PHP的动态绑定和静态绑定的一种情况。

public是动态绑定,在编译期不绑定,所以在运行期调用父类的test()方法的时候,会解析为子类的public方法。

而private是私有的,不会继承到子类,在编译期就绑定了,是一种“静态”的绑定(类似5.3后的self)。

与这个相关的是LSB,静态延迟绑定,PHP5.3因为有了这个特性之后,使PHP的OOP得到加强

public: 可以被继承,也可以被外部调用。

private: 不可以被继承,也不可以被外部调用。

protected: 可以被继承,但不能被外部调用。

PHP三种运行方式mod_php5/cgi/fast-cgi
a.通过HTTPServer内置的模块来实现,
例如Apache的mod_php5,类似的Apache内置的mod_perl可以对perl支持;

b.通过CGI来实现
这个就好比之前perl的CGI,该种方式的缺点是性能差,因为每次服务器遇到这些脚本都需要重新启动脚本解析器来执行脚本然后将结果返回给服务器;另一方面就是不太安全;该方面几乎很少使用了。

c.最新出现一种叫做FastCGI。
所谓FastCGI就是对CGI的改进。它一般采用C/S结构,一般脚本处理器会启动一个或者多个daemon进 程,每次HTTPServer遇到脚本的时候,直接交付给FastCGI的进程来执行,然后将得到的结果(通常为html)返回给浏览器。

该种方法的问题存在一个小问题是当遇到大流量的频繁请求的话,脚本处理器的daemon进程可能会超负荷从而变得很慢,甚至发生内存泄漏;

但是比较起Apache的内置模块的方式的优点是由于Server和脚本解析器完全分开各负其责,因此服务器不再臃肿,可以专心地进行静态文件响 应或者将动态脚本解析器的结果返回给用户客户端。所以比较起Apache的内置模块方式,有时候性能要提高很多。有人测试可能会达到 Apache+mod_php的5~10倍。

三种常用模式:
Apache+mod_php5;

lightppd+spawn-fcgi;

nginx+PHP-FPM

我们可以使用到生产环境中的:
0) 如果不是server cluster的话:
可以使用以上任一种,不过有各种测试表明nginx+PHP-FPM性能优越,但是Apache+mod_php5很经典模块多,比如对.htaccess等的支持。

如果构建server cluster的话:
1) nginx作为反向代理服务器,后台多台Apache+mod_php5。
nginx处理静态文件,及对php并发请求对后台多台app server的负载均衡;

2) nginx作为反向代理器,后台多台PHP-FPM
nginx处理静态文件及将php并发请求发送到后台php-fpm来解析;

三种变量命名规则(匈牙利法,小驼峰法,大驼峰法)
1. 匈牙利命名:
•开头字母用变量类型的缩写,其余部分用变量的英文或英文的缩写,要求单词第一个字母大写。
•For example: long lsum = 0;"l"是类型的缩写;
2. 小驼峰式:(little camel-case)
•第一个单词首字母小写,后面其他单词首字母大写。
•For example: string firstName = string.Empty;
3. 大驼峰式:(big camel-case)
•每个单词的第一个字母都大写;
•For example:string FirstName = string.Empty;
解决 Json 中文转码问题

 代码如下 复制代码
//代码
$data = array(
    'status'=>'1',
    'method'=>'登陆',
    'message'=>'成功',
);
echo json_encode($data);
//显示
{"status":"1","method":"u767bu9646","message":"u6210u529f"}

json_encode 只能接受utf-8格式的数据,最终的json中中文部分被替换为unicode编码。我们要解决的就是将对象转换为json并保证对象内部的中文在json中仍然是以正常的中文出现。

先将类中的中文字段进行url编码(urlencode),然后再对对象进行json编码(jsonencode),最后url解码(urldecode)json,即最终的json,里面的中文依旧是那个中文。

 代码如下 复制代码
//代码
foreach ( $data as $key => $value ) {
    $newData[$key] = urlencode ( $value );
}
echo urldecode(json_encode($newData));
//显示
{"status":"1","method":"登陆","message":"成功"}

Ajax跨域请求CORS错误
编写Json api供其他站点查询调用的时候有时候使用ajax方式获取,此时,可能ACAO的设置,那么将发生CROS错误。

//报错
XMLHttpRequest cannot load http://www.111cn.net . No 'Access-Control-Allow-Origin' header is present on the requested resource.
//解决办法

 代码如下 复制代码

header('Access-Control-Allow-Origin: *'); 
header('Access-Control-Allow-Origin: ccdd.com');
codeigniter指定地址实现HTTPS访问管理
//启动hooks
//app/config/config.php
$config['enable_hooks'] = TRUE;

//hooks配置
///app/config/hooks.php
$hook['post_controller_constructor'][] = array(
        'function' => 'check_ssl',
        'filename' => 'ssl.php',
        'filepath' => 'hooks',
    );

//插件编写
//app/hooks/ssl.php
function check_ssl(){
$CI =& get_instance();
$class = $CI->router->fetch_class();
$method = $CI->router->fetch_method();


$ssl = $CI->config->item('ssl_class_method');  
$partial = $CI->config->item('no_ssl_class_method');   

if(in_array($class.'/'.$method,$ssl)){
    //force_ssl();
    $CI =&get_instance();
    $CI->config->config['base_url'] = str_replace('http://', 'https://', $CI->config->config['base_url']);
    if ($_SERVER['SERVER_PORT'] != 443) redirect($CI->uri->uri_string());
}
else if(in_array($class.'/'.$method,$partial))
{
        return;
    }
    else{
        //unforce_ssl
        $CI =&get_instance();
        $CI->config->config['base_url'] = str_replace('https://', 'http://', $CI->config->config['base_url']);
        if ($_SERVER['SERVER_PORT'] == 443) redirect($CI->uri->uri_string());
    }
}

//config 配置需要使用https的 class method
//app/config/config.php
$config['ssl_class_method'] = array(
    'U_class/A_method',
    'V_class/B_method',
    'W_class/C_method',
    'X_class/D_method',
    ); //强制使用ssl
$config['no_ssl_class_method'] = array();

//强制不使用ssl

最简单的全局变量函数就是$_SERVER[\'DOCUMENT_ROOT\']与$HTTP_SERVER_VARS[\'DOCUMENT_ROOT\']了,但是我们要调用文件的话就无法这样实现了,具体如何写呢,下面我们一起来看看。

用php开发网站的时候有时候经常要用到当前网站的根目录, 比如包含一个文件:

 代码如下 复制代码

include_once("./includefile.php");

那么要想写根目录的形式应该怎么写呢?

这时候通常用 dirname(__FILE__) 这个函数, 意思是获取当前文件所在的根目录, 

那么这个php语句就是这样的了:

 代码如下 复制代码

include_once(dirname(__FILE__) ."/includefile.php");


将下面的代码放在网站根目录下的一个文件中,以便在其它文件中引用。

路径方式:

 代码如下 复制代码

define('BASE_PATH',str_replace('\\','/',realpath(dirname(__FILE__).'/'))."/");

echo BASE_PATH;


输出结果:E:/www.111cn.net /

url方式:

 代码如下 复制代码

 

$PHP_SELF=$_SERVER['PHP_SELF'];

$url='http://'.$_SERVER['HTTP_HOST'].substr($PHP_SELF,0,strrpos($PHP_SELF,'/')+1);

echo $url;


//注意大小写问题, linux下对大小写敏感, 要养成认真对待大小写的习惯, 以免win主机换到linux下不兼容的问题

[!--infotagslink--]

相关文章

  • 源码分析系列之json_encode()如何转化一个对象

    这篇文章主要介绍了源码分析系列之json_encode()如何转化一个对象,对json_encode()感兴趣的同学,可以参考下...2021-04-22
  • php中去除文字内容中所有html代码

    PHP去除html、css样式、js格式的方法很多,但发现,它们基本都有一个弊端:空格往往清除不了 经过不断的研究,最终找到了一个理想的去除html包括空格css样式、js 的PHP函数。...2013-08-02
  • index.php怎么打开?如何打开index.php?

    index.php怎么打开?初学者可能不知道如何打开index.php,不会的同学可以参考一下本篇教程 打开编辑:右键->打开方式->经文本方式打开打开运行:首先你要有个支持运行PH...2017-07-06
  • MYSQL事务回滚的2个问题分析

    因此,正确的原子操作是真正被执行过的。是物理执行。在当前事务中确实能看到插入的记录。最后只不过删除了。但是AUTO_INCREMENT不会应删除而改变值。1、为什么auto_increament没有回滚?因为innodb的auto_increament的...2014-05-31
  • 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
  • c#的异或运算符介绍

    这篇文章介绍了c#的异或运算符,有需要的朋友可以参考一下...2020-06-25
  • 轻松学习C#的运算符

    轻松学习C#的运算符,对C#的运算符感兴趣的朋友可以参考本篇文章,帮助大家更灵活的运用C#的运算符。...2020-06-25
  • PHP编程 SSO详细介绍及简单实例

    这篇文章主要介绍了PHP编程 SSO详细介绍及简单实例的相关资料,这里介绍了三种模式跨子域单点登陆、完全跨单点域登陆、站群共享身份认证,需要的朋友可以参考下...2017-01-25
  • PHP实现创建以太坊钱包转账等功能

    这篇文章主要介绍了PHP实现创建以太坊钱包转账等功能,对以太坊感兴趣的同学,可以参考下...2021-04-20
  • C#中38个常用运算符的优先级的划分和理解

    这只我自己在学C#中的一些总结,其中对于各级的划分方式、各操作符的优先级的理解并不见得正确,只是自己的看法,拿出来与大家分享...2020-06-25
  • Mysql索引会失效的几种情况分析

    索引并不是时时都会生效的,比如以下几种情况,将导致索引失效: 1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)  注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引 ...2014-06-07
  • php微信公众账号开发之五个坑(二)

    这篇文章主要为大家详细介绍了php微信公众账号开发之五个坑,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-10-02
  • R语言运算符知识点讲解

    在本篇文章里小编给大家分享了一篇关于R语言运算符知识点讲解内容,有兴趣的朋友们可以参考下。...2021-05-06
  • ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单

    首先是数据库的设计。分类表叫cate.我做的是分类数据的二级联动,数据需要的字段有:id,name(中文名),pid(父id). 父id的设置: 若数据没有上一级,则父id为0,若有上级,则父id为上一级的id。数据库有内容后,就可以开始写代码,进...2014-05-31
  • PHP如何通过date() 函数格式化显示时间

    这篇文章主要介绍了PHP如何通过date() 函数格式化显示时间,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-13
  • C++编程中的或||、与&&、非!逻辑运算符基本用法整理

    这篇文章主要介绍了C++中的或||、与&&、非!逻辑运算符基本用法整理,是C++入门学习中的基础知识,需要的朋友可以参考下...2020-04-25
  • PHP+jQuery+Ajax实现多图片上传效果

    今天我给大家分享的是在不刷新页面的前提下,使用PHP+jQuery+Ajax实现多图片上传的效果。用户只需要点击选择要上传的图片,然后图片自动上传到服务器上并展示在页面上。...2015-03-15
  • python 爬取京东指定商品评论并进行情感分析

    本文主要讲述了利用Python网络爬虫对指定京东商城中指定商品下的用户评论进行爬取,对数据预处理操作后进行文本情感分析,感兴趣的朋友可以了解下...2021-05-28
  • JS不要再到处使用绝对等于运算符了

    这篇文章主要介绍了JS不要再到处使用绝对等于运算符了,对此感兴趣的同学,可以参考下...2021-05-01
  • Underscore源码分析

    Underscore 是一个 JavaScript 工具库,它提供了一整套函数式编程的实用功能,但是没有扩展任何 JavaScript 内置对象。这篇文章主要介绍了underscore源码分析相关知识,感兴趣的朋友一起学习吧...2016-01-02