在foreach循环中,如果我们需要更改迭代的元素或是为了提高效率,运用引用是一个好办法: $arr = array(1,2,3,4);
这里有个问题很多人会迷糊。循环结束后,$value并未,$value其实是数组中最后一个元素的引用,这样在后续对$value的使用中,如果不知道这一点,会引发一些莫名奇妙的错误:)看看下面这段代码:
对于isset函数,变量不存在时会返回lse,变量值为null时也会返回lse。这种行为很容易把人弄迷糊。。。看下面的代码:
写这段代码的人本意可能是如果$data[‘keyShouldBeSet’]未设置,则执行对应逻辑。但问题在于即使$data[‘keyShouldBeSet’]已设置,但设置的值为null,还是会执行对应的逻辑,这就不符合代码的本意了。
判断一个变量是否真正被设置(区分未设置和设置值为null),array_key_exists函数或许更好。重构的第一个例子,如下:
另外,结合get_defined_vars函数,我们可以更加可靠的检测变量在当前作用域内是否被设置:
问题出在哪呢?问题就在于的代码混淆了返回值和返回引用。在PHP中,除非你显示的指定返回引用,否则对于数组PHP是值返回,也就是数组的拷贝。因此代码对返回数组赋值,实际是对拷贝数组进行赋值,非原数组赋值。
如果你就是想要改变原数组,也就是要反回数组引用,那应该如何处理呢?办法就是显示指定返回引用即可:
如果你想的是会和一样输出“ Undefined index”错误,那你就错了。代码会正常输出“test”。原因在于PHP对于对象默认就是按引用返回的,而不是按值返回。
综上所述,我们在使用函数返回值时,要弄清楚是值返回还是引用返回。PHP中对于对象,默认是引用返回,数组和内置基本类型默认均按值返回。这个要与其它语言区别开来(很多语言对于数组是引用传递)。
像其它语言,比如Java或C#,利用getter或setter来访问或设置类属性是一种更好的方案,当然PHP默认不支持,需要自己实现:
的代码给调用者可以访问或设置数组中的任意值而不用给与数组public访问权限。感觉怎么样:)
当然的代码是没有什么错误的。问题在于我们在迭代过程中$valueRepository-findByValue可能每次都执行了sql查询:
如果迭代了10000次,那么你就分别执行了10000次sql查询。如果这样的脚本在多线程程序中被调用,那很可能你的系统就挂了。。。
在编写代码过程中,你应该要清楚什么时候应该执行sql查询,尽可能一次sql查询取出所有数据。
有一种业务场景,你很可能会犯上述错误。假设一个表单提交了一系列值(假设为IDs),然后为了取出所有ID对应的数据,代码将遍历IDs,分别对每个ID执行sql查询,代码如下所示:
一次sql查询获取多条记录比每次查询获取一条记录效率肯定要高,但如果你使用的是php中的MySQL扩展,那么一次获取多条记录就很可能会导致内存溢出。
根据内存使用量来看,貌似一切正常。为了更加确定,试着一次获取100000条记录,结果程序得到如下输出:
题出在php的mysql模块的工作方式,mysql模块实际上就是libmysqlclient的一个代理。在查询获取多条记录的同时,这些记录会直接
保存在内存中。由于这块内存不属于php的内存模块所管理,所以我们调用memory_get_peak_usage函数所获得的值并非真实使用内存
我们可以使用mysqlnd来代替mysql,mysqlnd编译为php自身扩展,其内存使用由php内存管理模块所控制。如果我们用mysqlnd来实现的代码,则会更加真实的反应内存使用情况:
更加糟糕的是,根据php的文档,mysql扩展存储查询数据使用的内存是mysqlnd的两倍,因此原来的代码使用的内存是显示的两倍左右。
联系提到的错误4可以看出,在实际的编码过程中,要做到一种平衡,才能既满足功能要求,又能性能。
php编程中,在处理非ascii字符时,会遇到一些问题,要很小心的去对待,要不然就会错误遍地。举个简单的例子,strlen($name),如果$name包含非ascii字符,那结果就有些出乎意料。在此给出一些,尽量避免此类问题:
如果你对unicode和utf-8不是很了解,那么你至少应该了解一些基础。推荐阅读这篇文章。
最好使用mb_*函数来处理字符串,避免使用老的字符串处理函数。这里要确保PHP的“multibyte”扩展已。
PHP中的$_POST并非总是包含表单POST提交过来的数据。假设我们通过jQuery.ajax方法向服务器发送了POST请求:
不错,的代码的确会输出’a’到’z’,但除此之外,还会输出’aa’到’yz’。我们来分析下为什么会是这样的结果。
在PHP中不存在char数据类型,只有string类型。明白这点,那么对’z’进行递增操作,结果则为’aa’。对于字符串比较大小,学过C的应该都知道,’aa’是小于’z’的。这也就解释了为何会有的输出结果。
没有统一的编码标准会使你的项目出现很多问题。最明显的就是你的项目代码不具有一致性。更坏的地方在于,你的代码将更加难以调试、扩展和。这也就意味着你的团队效率会降低,包括做一些很多无意义的劳动。
对于PHP开发者来说,是比较幸运的。因为有PHP编码标准推荐(PSR),由下面5个部分组成:
PSR最初由PHP社区的几个大的团体所创建并遵循。Zend, Drupal, Symfony, Joomla及其它的平台都为此标准做过贡献并遵循这个标准。即使是PEAR,早些年也想让自己成为一个标准,但现在也加入了PSR阵营。
某些情况下,使用什么编码标准是无关紧要的,只要你使用一种编码风格并一直使用即可。但是遵循PSR标准不失为一个好办法,除非你有什么特殊的原因要
自己弄一套。现在越来越多的项目都开始使用PSR,大部分的PHP开发者也在使用PSR,因此使用PSR会让新加入你团队的更快的熟悉项目,写代码时
一些PHP开发人员喜欢用empty函数去对变量或表达式做布尔判断,但在某些情况下会让人很困惑。
首先我们来看看PHP中的数组Array和数组对象ArrayObject。看上去好像没什么区别,都是一样的。真的这样吗?
在这顺便提一下,因为PHP中会将数值0认为是布尔值lse,因此 count函数可以直接用在 if条件语句的条件判断中来判断数组是否为空。另外,count函数对于数组来说复杂度为O(1),因此用 count函数是一个明智的选择。
再来看一个用 empty函数很的例子。当在魔术方法 __get中结合使用 empty函数时,也是很的。我们来定义两个类,每个类都有一个 test属性。
很不幸的是,如果一个类使用魔法 __get函数来访问类属性的值,没有简单的方法来检查属性值是否为空或是不存在。在类作用域外,你只能检查是否返回 null值,但这并不一定意味着没有设置相应的键,因为键值可以被设置为 null 。
相比之下,如果我们访问 Regular类的一个不存在的属性,则会得到一个类似下面的Notice消息:
因此,对于 empty函数,我们要小心的使用,要不然的话就会结果出乎意料,甚至潜在的你。
推荐:
网友评论 ()条 查看