PHP的隐藏function?
我知道这听起来像是一个唠叨的问题,但让我解释我来自哪里。
大学gradle后,我在一家PHP商店find了一份工作。 我在那里工作了一年半,认为我已经学习了所有有关编程的知识。
然后,我在一家规模庞大的公司里find了一个单人内部开发的工作,所有的工作都是用C#来完成的。 在我对这个职位的承诺中,我开始阅读了大量的博客和书籍,很快就意识到我以为自己什么都懂。 我学习了unit testing,dependency injection和装饰器模式,松散耦合的devise原理,inheritance争论的构成等等,我依然非常感兴趣。 不用说我的编程风格在去年完全改变了。
现在我发现自己正在为一个朋友的启动编写一个PHP项目,我觉得完全受到限制,而不是用C#编程。 它真的困扰我,所有类variables的variables必须通过追加'$ this->'来引用。 令我感到懊恼的是,我尝试过的所有IDE都没有非常好的智能感知,而且我的SimpleTestunit testing方法必须以“testing”这个词开头。 这令我发疯,dynamictypes让我无法隐式地指定方法所期望的参数types,而且您必须编写一个switch语句来执行方法重载。 我不能忍受,你不能有嵌套的命名空间,必须使用::运算符来调用基类的构造函数。
现在我不打算开始一个PHP和C#的辩论,而是我的意思是说,我确定有一些我不知道或知道的PHPfunction,但没有正确使用。 我置身于C#宇宙之中,无法在玻璃碗外看到。
所以我问,你最喜欢的PHPfunction是什么? 你可以做什么,你不能或者在.Net语言中更难?
文档 。 文件得到我的投票。 我还没有遇到过一个编程语言的更彻底的在线文档 – 我必须从各种网站和手册页拼凑一切。
数组 。 从这个问题的答案来看,我不认为人们完全理解PHP是多么容易和有用的数组。 PHParrays同时充当列表,地图,堆栈和通用数据结构。 数组在语言核心中实现,并在各处使用,从而产生良好的CPUcaching局部性。 Perl和Python都使用单独的语言构造列表和地图,导致更多的复制和可能混淆的转换。
stream处理程序允许您扩展“文件系统”,据我所知在其他大多数语言中很难做到这一点。
例如,使用MS-Excel Stream处理程序,您可以通过以下方式创buildMS Excel文件:
$fp = fopen("xlsfile://tmp/test.xls", "wb"); if (!is_resource($fp)) { die("Cannot open excel file"); } $data= array( array("Name" => "Bob Loblaw", "Age" => 50), array("Name" => "Popo Jijo", "Age" => 75), array("Name" => "Tiny Tim", "Age" => 90) ); fwrite($fp, serialize($data)); fclose($fp);
魔术方法是贯穿的方法,当你调用一个不存在的方法或者分配或者读取一个不存在的属性时,这些方法会被调用。
interface AllMagicMethods { // accessing undefined or invisible (eg private) properties public function __get($fieldName); public function __set($fieldName, $value); public function __isset($fieldName); public function __unset($fieldName); // calling undefined or invisible (eg private) methods public function __call($funcName, $args); public static function __callStatic($funcName, $args); // as of PHP 5.3 // on serialize() / unserialize() public function __sleep(); public function __wakeup(); // conversion to string (eg with (string) $obj, echo $obj, strlen($obj), ...) public function __toString(); // calling the object like a function (eg $obj($arg, $arg2)) public function __invoke($arguments, $...); // called on var_export() public static function __set_state($array); }
这里的C ++开发者可能注意到,PHP允许重载一些运算符,例如()
或(string)
。 实际上PHP允许超载,例如[]
操作符( ArrayAccess ), foreach
语言结构( Iterator和IteratorAggregate )和count
函数( Countable )。
标准class是一个整洁的容器。 我最近才知道的
而不是使用数组来保存多个属性
$person = array(); $person['name'] = 'bob'; $person['age'] = 5;
你可以使用标准的类
$person = new stdClass(); $person->name = 'bob'; $person->age = 5;
这在访问string中的这些variables时特别有用
$string = $person['name'] . ' is ' . $person['age'] . ' years old.'; // vs $string = "$person->name is $person->age years old.";
包含文件可以具有可以分配给variables的返回值 。
// config.php return array( 'db' => array( 'host' => 'example.org', 'user' => 'usr', // ... ), // ... ); // index.php $config = include 'config.php'; echo $config['db']['host']; // example.org
你可以利用这个事实: or
操作符的优先级比=
低来做这个事情:
$page = (int) @$_GET['page'] or $page = 1;
如果第一个赋值的值为true
,则忽略第二个赋值。 另一个例子:
$record = get_record($id) or throw new Exception("...");
__autoload()
(class-)文件由set_include_path()
协助。
在PHP5中,现在不需要在进行体面的OOP时指定长的“include_once”语句列表。
只要定义一个小的一组目录,其中类库文件结构合理,并设置自动包含path:
set_include_path(get_include_path() . PATH_SEPARATOR . '../libs/');`
现在, __autoload()
例程:
function __autoload($classname) { // every class is stored in a file "libs/classname.class.php" // note: temporary alter error_reporting to prevent WARNINGS // Do not suppress errors with a @ - syntax errors will fail silently! include_once($classname . '.class.php'); }
现在,PHP将按需自动包含所需的文件,节省parsing时间和内存。
轻松 。 最大的特点是新开发人员坐下来写“工作”脚本和理解代码是多么容易。
最糟糕的情况是新开发人员坐下来写“工作”脚本并认为他们理解代码是多么的容易。
围绕PHP 的社区的开放性以及大量开放源代码的PHP项目对于进入开发世界的人来说并不那么令人恐惧,并且像您一样可以成为更成熟的语言的垫脚石。
在我之前,我不会讨论任何技术问题,但是如果您将PHP看作是一个社区而不是Web语言,那么当您开始开发时明显拥抱您的社区,这些好处真的可以说明一切。
variables和函数毫无疑问!
$foo = 'bar'; $bar = 'foobar'; echo $$foo; //This outputs foobar function bar() { echo 'Hello world!'; } function foobar() { echo 'What a wonderful world!'; } $foo(); //This outputs Hello world! $$foo(); //This outputs What a wonderful world!
同样的概念适用于对象参数($ some_object – > $ some_variable);
非常非常棒。 使用循环和模式进行编码非常简单,而且比eval更快,更受控(Thanx @Ross&@Joshi Spawnbrood!)t
您可以使用函数 func_get_args()
使用具有未定义数量的参数 。
<?php function test() { $args = func_get_args(); echo $args[2]; // will print 'd' echo $args[1]; // will print 3 } test(1,3,'d',4); ?>
我喜欢远程文件 。 对于Web开发来说,这种function特别有用。
需要处理网页的内容? 一个简单的
$fp = fopen('http://example.com');
而且你已经准备好了一个文件句柄,就像其他普通文件一样。
或者如何读取远程文件或网页直接在一个string?
$str = file_get_contents('http://example.com/file');
这种特殊方法的用处很难夸大。
想分析一个远程图像? 如何通过FTP做到这一点?
$imageInfo = getimagesize('ftp://user:password@ftp.example.com/image/name.jpg');
几乎所有与文件一起工作的PHP函数都可以用于远程文件。 您甚至include()
通过这种方式远程include()
或require()
代码文件。
strtr函数的效率()
这是非常快的,太多了,你会惊讶。 在内部,它可能使用一些疯狂的b-treetypes的结构来按照它们的通用前缀来排列你的匹配。 我用200多个查找和replacestring,它仍然在不到100毫秒内通过1MB。 除了细小的string之外,strtr()在执行完全相同的事情上甚至比strtolower()更快,即使考虑到字符集也是如此。 你也许可以使用连续的strtr调用来编写一个完整的parsing器,它会比通常的正则expression式匹配更快,找出标记types,输出这个或那个,下一个正则expression式类的东西。
我正在写一个文本标准化器,用于将文本分解为文字,压缩文字,删除标点符号等等,而strtr是我的瑞士军刀,它把正规expression式甚至str_replace()打败了。
PHP的一个不是很着名的function是extract()
,它是一个将关联数组解压缩到本地名称空间的函数。 这可能存在于autoglobal abormination中,但对于模板非常有用:
function render_template($template_name, $context, $as_string=false) { extract($context); if ($as_string) ob_start(); include TEMPLATE_DIR . '/' . $template_name; if ($as_string) return ob_get_clean(); }
现在你可以使用render_template('index.html', array('foo' => 'bar'))
,只有$foo
和值"bar"
出现在模板中。
Range()本身并不隐藏,但我仍然看到很多人在迭代:
for ($i=0; $i < $x; $i++) { // code... }
当他们可以使用:
foreach (range(0, 12) as $number) { // ... }
你可以做简单的事情
foreach (range(date("Y"), date("Y")+20) as $i) { print "\t<option value=\"{$i}\">{$i}</option>\n"; }
使用PHP的webspace通常比使用(asp).net的东西便宜。 你可以称之为function;-)
static
关键字在OOP的立场之外是有用的。 您可以使用以下简单的方法快速轻松地实现“记忆”或functioncaching:
<?php function foo($arg1) { static $cache; if( !isset($cache[md5($arg1)]) ) { // Do the work here $cache[md5($arg1)] = $results; } return $cache[md5($arg1)]; } ?>
static
关键字创build一个variables,该variables只在该函数的执行范围内持续存在。 这种技术对于像get_all_books_by_id(...)
或get_all_categories(...)
这样的命中数据库的函数来说非常有用,因为在页面加载期间您将多次调用这个函数。
警告:确保你find了最好的方法来为你的哈希键,在几乎所有的情况下,上面的md5(...)
不是一个好的决定(速度和输出长度问题),我用它作为说明的目的。 根据上下文sprintf('%u', crc32(...))
或spl_object_hash(...)
可能会好得多。
CLI的一个很好的function是CLI 。 它不是如此“促进”在文档中,但如果您需要例行脚本/控制台应用程序,使用cron + php cli开发起来非常快!
然后“打印”把戏
<?php $flag and print "Blah" ?>
如果$ flag为真会回应Blah。 不适用于ECHO。
这在模板中非常方便,并replace? :这不是很容易阅读。
您可以在variables名称中使用减号字符,如下所示:
class style { .... function set_bg_colour($c) { $this->{'background-color'} = $c; } }
为什么使用它? 不知道:也许是一个CSS模型? 或者你需要输出一些奇怪的JSON。 这是一个奇怪的function:)
HEREDOC语法是我最喜欢的隐藏function。 总是很难find,因为你不能谷歌的<<<,但它阻止你不得不逃离HTML的大块,并仍然允许你把variables放入stream中。
echo <<<EOM <div id="someblock"> <img src="{$file}" /> </div> EOM;
可能没有多less人知道可以将常量“variables”指定为函数参数的默认值:
function myFunc($param1, $param2 = MY_CONST) { //code... }
string可以像使用数组一样使用 :
$str = 'hell o World'; echo $str; //outputs: "hell o World" $str[0] = 'H'; echo $str; //outputs: "Hell o World" $str[4] = null; echo $str; //outputs: "Hello World"
关于PHP代码的一个最有用的事情是,如果我不太明白一个函数,我可以使用浏览器来查找它并input:
上个月,我在一些代码中看到了“范围”function。 这是我设法永远不会使用的数百个函数之一,但却是非常有用的:
该url是http://us2.php.net/manual/en/function.range.php的别名。; 将函数和关键字映射到URL的这个简单的想法是非常棒的。
我希望其他的语言,框架,数据库,操作系统有一个简单的查找文档的机制。
快速的块评论
/* die('You shall not pass!'); //*/ //* die('You shall not pass!'); //*/
如果一个代码块被一个字符评论,这些注释允许您切换。
我的名单..他们大多比“最喜欢的function”(我希望!)更多地落在“隐藏的function”之下,而不是全部都是有用的,但..是的。
// swap values. any number of vars works, obviously list($a, $b) = array($b, $a); // nested list() calls "fill" variables from multidim arrays: $arr = array( array('aaaa', 'bbb'), array('cc', 'd') ); list(list($a, $b), list($c, $d)) = $arr; echo "$a $b $c $d"; // -> aaaa bbb cc d // list() values to arrays while (list($arr1[], $arr2[], $arr3[]) = mysql_fetch_row($res)) { .. } // or get columns from a matrix foreach($data as $row) list($col_1[], $col_2[], $col_3[]) = $row; // abusing the ternary operator to set other variables as a side effect: $foo = $condition ? 'Yes' . (($bar = 'right') && false) : 'No' . (($bar = 'left') && false); // boolean False cast to string for concatenation becomes an empty string ''. // you can also use list() but that's so boring ;-) list($foo, $bar) = $condition ? array('Yes', 'right') : array('No', 'left');
You can nest ternary operators too, comes in handy sometimes.
// the strings' "Complex syntax" allows for *weird* stuff. // given $i = 3, if $custom is true, set $foo to $P['size3'], else to $C['size3']: $foo = ${$custom?'P':'C'}['size'.$i]; $foo = $custom?$P['size'.$i]:$C['size'.$i]; // does the same, but it's too long ;-) // similarly, splitting an array $all_rows into two arrays $data0 and $data1 based // on some field 'active' in the sub-arrays: foreach ($all_rows as $row) ${'data'.($row['active']?1:0)}[] = $row; // slight adaption from another answer here, I had to try out what else you could // abuse as variable names.. turns out, way too much... $string = 'f.> <!-? o+'; ${$string} = 'asdfasf'; echo ${$string}; // -> 'asdfasf' echo $GLOBALS['f.> <!-? o+']; // -> 'asdfasf' // (don't do this. srsly.) ${''} = 456; echo ${''}; // -> 456 echo $GLOBALS['']; // -> 456 // I have no idea.
Right, I'll stop for now 🙂
Hmm, it's been a while..
// just discovered you can comment the hell out of php: $q/* snarf */=/* quux */$_GET/* foo */[/* bar */'q'/* bazz */]/* yadda */;
So, just discovered you can pass any string as a method name IF you enclose it with curly brackets. You can't define any string as a method alas, but you can catch them with __call(), and process them further as needed. Hmmm….
class foo { function __call($func, $args) { eval ($func); } } $x = new foo; $x->{'foreach(range(1, 10) as $i) {echo $i."\n";}'}();
Found this little gem in Reddit comments:
$foo = 'abcde'; $strlen = 'strlen'; echo "$foo is {$strlen($foo)} characters long."; // "abcde is 5 characters long."
You can't call functions inside {} directly like this, but you can use variables-holding-the-function-name and call those! (*and* you can use variable variables on it, too)
Array manipulation.
Tons of tools for working with and manipulating arrays. It may not be unique to PHP, but I've never worked with a language that made it so easy.
I'm a bit like you, I've coded PHP for over 8 years. I had to take a .NET/C# course about a year ago and I really enjoyed the C# language (hated ASP.NET) but it made me a better PHP developer.
PHP as a language is pretty poor, but, I'm extremely quick with it and the LAMP stack is awesome. The end product far outweighs the sum of the parts.
That said, in answer to your question:
I love the SPL , the collection class in C# was something that I liked as soon as I started with it. Now I can have my cake and eat it.
安德鲁
I'm a little surprised no-one has mentioned it yet, but one of my favourite tricks with arrays is using the plus operator. It is a little bit like array_merge()
but a little simpler. I've found it's usually what I want. In effect, it takes all the entries in the RHS and makes them appear in a copy of the LHS, overwriting as necessary (ie it's non-commutative). Very useful for starting with a "default" array and adding some real values all in one hit, whilst leaving default values in place for values not provided.
Code sample requested:
// Set the normal defaults. $control_defaults = array( 'type' => 'text', 'size' => 30 ); // ... many lines later ... $control_5 = $control_defaults + array( 'name' => 'surname', 'size' => 40 ); // This is the same as: // $control_5 = array( 'type' => 'text', 'name' => 'surname', 'size' => 40 );
Here's one, I like how setting default values on function parameters that aren't supplied is much easier:
function MyMethod($VarICareAbout, $VarIDontCareAbout = 'yippie') { }
Quick and dirty is the default.
The language is filled with useful shortcuts, This makes PHP the perfect candidate for (small) projects that have a short time-to-market. Not that clean PHP code is impossible, it just takes some extra effort and experience.
But I love PHP because it lets me express what I want without typing an essay.
PHP:
if (preg_match("/cat/","one cat")) { // do something }
JAVA:
import java.util.regex.*; Pattern p = Pattern.compile("cat"); Matcher m = p.matcher("one cat") if (m.find()) { // do something }
And yes, that includes not typing Int .