V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  raincious  ›  全部回复第 82 页 / 共 107 页
回复总数  2127
1 ... 78  79  80  81  82  83  84  85  86  87 ... 107  
2014-05-14 23:29:43 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming


> 写了这么长完全不知道你要吐槽什么。”直接因为$str['check']这个根本不合法而直接返回false啊“这个不在我的模式范围内所以我不多做讨论。

这是我14楼以来一直在抱怨的啊,我就是想如果能那样该多好阿,简直直接乌托邦了啊。现在都46楼了中间这么多你干啥去了?我们在进行什么欢乐的娱乐活动么亲?PHP原理猜猜猜?看似是的呢。



> “函数名就说明了人家就是用来获取文件内容的”

isset函数名说明了这是用来检测某个变量是否存在的,那么解析这个变量的时候给我埋这个坑是不是也是Bug?



另外你要知道,其实,你想要解释的那些Test1 ~ Test 4已经说明白了。

比如你27楼str['f']['f'],只是做了Test1 + Test 3而已。


当然,我原先的认知也不是对的,我一开始是认为,因为'check'这个索引找不到,所以才会是false,而不是isset检查过了索引,因为是非法的所以返回了false。


我只想知道为什么不能想我说的那样实现isset,让Test 1和Test 3一起false。然而这个问题我是一直没有得到答案的。

至于死循环是这样的:我一直想问为何不能这样 => 你没有答案 => 你解释PHP怎么这么做 => 我:艹我没问这个问题啊 => 回到1。这是很正常的轮询结构不是么o_o。


其实我已经不想接着讨论这个问题了,所以才发上面那个帖子。老实说吧,我觉得在这里讨论不出任何有价值的信息了,因为……你也不知道源代码说了什么啊,根本不知道应该告诉我什么。再着么下去估计就得吵起来了不是么,就此打住我们还是好朋友,一包薯片都能分着吃的那种:我一包,。


PS。如果VLD不只能打印出Opcode,也能跟踪整个工作流,我想就不会有这么多解释不清的麻烦了。现在只能看到FETCH_DIM_IS拿了check(后来应该是0才对吧)出来然后给到ISSET_ISEMPTY_DIM_OBJ,却不能知道IS出来的东西到底给编译器搞成什么了。

其实我觉得,一直将输入数组当成DIM来用,次序也是从左往右的,ASSIGN的时候也知道目标数据类型了(是的,如果是数组的话会先INIT_ARRAY的亲),那,实现让isset遇到非数字下标直接return false能有多复杂呢。

好了。我还是安心去等PHP那边有没有响应又或者永远没有响应。你也安了吧,消消气,睡个好觉。
2014-05-14 21:28:44 +08:00
回复了 yxz00 创建的主题 程序员 程序结构想好了,就不想动手写,怎么破
我是这样的:一直开着Sublime,放在可见的角落里,上面写着TODO: blablabla ……
2014-05-14 21:11:22 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming

哈哈。其实,我搞清楚这个问题之后,一直是在抱怨,可能我用了疑问句,所以让你误解了。我觉得我再不说清楚咱们俩都得进入死循环了。

因为我知道这个问题就算我在这里问也是搞不清楚的,因为要认真的阅读过源代码才会了解。所以我希望是在PHP新闻组上得到解答,或者被忽略。

不过你说的这个“因为只有得到 $str['check']是什么才能确定是否有0键”,没错啊,但是不一定要先估值转换啊,它可以直接因为$str['check']这个根本不合法而直接返回false啊对不对?



这个问题呢,就像是我写了个很垃圾的函数,叫做,嗯……比如说get_file_contents,嗯,get_file_contents。它是用来打开文件的,但是这个函数有个很讨厌的功能,就是如果这个文件不存在并且目标文件的文件名是以PHP结尾的话,他会给你建立一个文件,然后写入“PHP是最好的语言”这个字符串,然后返回。

有一天,你用到了这个函数,用来它来获得一个文件,比如叫“任何文件”。但是这个文件可能存在也可能不存在。问题是这个文件的文件名不是由你控制的(而是由其他程序员以及配置控制的)。

你搞清楚了get_file_contents的机制知道有这个问题。于是为了安全,你效验了文件名,写下了如下代码:

if (文件名的结尾(文件名变量) != 'PHP') {
return get_file_contents(文件名变量);
} elseif (文件存在(文件名变量)) {
return 另一个更加麻烦或者因为某些原因不建议使用的函数(文件名变量);
}

然后你开始了抱怨,是啊,如果get_file_contents没有判断文件是不是以PHP结尾这样糟糕的特性该多好,那时候你就可以直接return get_file_contents(文件名变量);了不是么?

于是你抱怨上了论坛。询问get_file_contents为什么会这样?

这个时候另一个人看到了你的问题,会答到:

这是因为get_file_contents会判断文件名结尾,然后调用另一个函数put_file_contents来写入“PHP是最好的语言”。

然后你说,为什么需要这样?难道返回一个false不是更好么?

这时候那人又说,你得读文件啊,文件必须读过才知道是不是有内容啊,这都发生在put_file_contents之后。



所以你看,我们的方向是不一样的。我期待的讨论是,是不是底层上有什么结构会导致我的设想无法成立,另外是不是我的设想就不对呢?接着我还可能会问“那么为什么不能实现我的设想,因为那样更加直觉正确”,最后可能真的能促成这件事(虽然,这,简直微乎其微,大PHP怎么会为这点小事而改动)。


我期待的结果可能是比如这样的讨论“$string对于编译器来说是一个T_VARIABLE,除此之外编译器对其一无所知。而isset发生与编译阶段,于是它只知道$string的类型,而不知道$string其中内容的类型”。当然前面是扯淡,PHP会解析这些东西,然后得到所有TOKEN的必要信息,包括它是什么以及他里面是什么(何况或许根本就没有“里面”这东西,只是地址引用)。

所以,嗯,咱们继续等那边啥情况吧,或许我真的被忽略了。

不过就我自己这种情况来看,isset($string['check'][1]) + is_string($string['check'])工作良好。但或许我应该改成!empty($string['check']) + is_string($string['check'])。因为我发现他们都是通过zend_do_isset_or_isempty来实现的,只是作为第一个参数type,被设定成ZEND_ISEMPTY或者ZEND_ISSET而已。

而这个type也就是在检查zend_is_function_or_method_call以及设定op编译扩展信息的时候用了下。(当然我还没完整看过代码,还是闭嘴的好。)


好了不吧唧了,我继续做项目去了。也感谢你一直聊这个话题。
2014-05-14 19:39:54 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming

你以为我不明白你29楼在说什么?

> isset($str['check'][0])的意思是检查 $str['check'] 这个 数组/字符串 内是否存在 0 键.. 所以$str['check']会先转换

(事实上你也说过好多次了。)

就这个问题,更准确的说,我40楼是在问“为什么要转换?”,为什么不发现'check'这个数组是非法下标之后直接return false?

好了,我觉得你已经清楚我12后之后一直在说什么了。
2014-05-14 17:07:05 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming 那么Test 1为什么没有返回false,它也是非法下标啊(又没说具体是第几个)? 是因为有第二条规则,即非数字偏移量会被估值转然后换成0(PHP 5.3的做法)。

其实我的意思就是,PHP应该在检测到第一个下标是非数字偏移量的时候,就return false;而他这么做很明显就是为了照顾isset($str['1'])。

我觉得应该烧死那帮用isset($str['1'])的人。
2014-05-14 16:45:40 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming 所以我觉得我们一直在纠结一个乌虚有的问题。

因为你的帖过档案之后,7楼我已经说过了,跟这个没有关系。简单一点来说,我在意的是单维和多维数组得到的结论不相符的问题。但可能我没解释清楚(抱歉,我还在一边做原型设计,然后实现,还要处理框架变更,所以抱歉,精力有限,做出了“你可能懂的”假设。)

isset($string['check']); // Test 3
isset($string['check'][0]); // Test 1

* Sigh *,这两个例子我贴上去之后,竟然没有也感到很奇怪的。

难道没有发现一个检查到了'check'之后false,一个估值成了0然后true这两种结论然后觉得很奇怪的。
2014-05-14 16:28:59 +08:00
回复了 michaelup 创建的主题 程序员 大家还有在关注 CSDN 吗?
关注CSDN?他们又泄露密码了么?求下载地址。
2014-05-14 16:26:15 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming 我……不是已经给你分了么……

另外其实,文档里的解释是不全面的,因为根据var_dump(isset($str['1x']));在5.4下会返回bool(false)的事实,不应该得出Test1为Found的结果。

我们讨论的是,为什么isset($str['check'])是false,而isset($str['check'][0])则会是true(Test 1和Test 3)。

说了这么多……我想你应该明白了……

以上。


嗯……为什么我们在说这个?我觉得应该聊聊更有意义的话题,比如PHP为什么是最好的语言。
2014-05-14 16:04:01 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming

关于isset为什么会出现这种情形。我12楼已经推导了(我已经说了好多次了),那是正确的结论,请不要继续纠结。

关于你那个$str['f']['f']还是得继续研究下。不过我想我们都应该意识到猜测是没有意义的,必须去阅读PHP的源代码来找到答案。

如果PHP新闻组那边有什么有价值的更新,或许我会在这里Append。
2014-05-14 13:44:13 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming 哦,很抱歉,我没给你看邮件原文,很明显这造成了你理解的问题,这是 Topic: http://news.php.net/php.general/323297

事实上这一系列的帖子或许旨在讨论一个问题:“如何使用isset来快速检测当前设定的数组是否为合法的结构”。当然,我觉得目前这个说明是足够的。

isset($string['check'][1]) && is_string($string['check']) 的目的在于,一旦$string是一个字符串,那么这个表达式将准确的返回false。

因为无论isset的行为如何或者'check'到底有没有估值成0,只有当$string['check']是一个字符串(isset中包括$string是否存在,以及$string['check']是否存在的检查),且至少有两个字符的时候,才会是true。

当输入是如下结构的时候:

$string => array(
'check' => 'whatever',
);

表达式将返回true;

而当结构如下的时候

$string = 'whatever';

表达式将返回false。

而且根据我12楼的推导,这样的检查将会是准确的,因为如果$string['check']真的会被估值为$string[0]。那么$string[0][1]总是不存在的,(相反$string[0][0]总是存在的,哪怕$string[0][0][0]...[0][0][0][0][0])。

所以其实我所有的问题都已经解决了。现在我希望能在PHP邮件列表上讨论下关于isset的细节。因为我想要的结果是isset($string['check'][0]) and isset($string['check'])都将返回false。也就是说isset不要对这个'check'进行估值,而应该先检查下数据类型,如果使用了不正确的下标则应该返回false而不是估值成0。

以上。
2014-05-14 11:32:39 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming

哦,14楼可能我让你理解错了。我想说的其实是不知道为什么这帮家伙会做出这样的决定。

总之,在看不懂源代码的情况下,咱们只能论断这两种可能了。要么就是'f'被估值成了0,要么就是PHP只估值了最后一个Key。

当然或许是我没搞清楚你的意思,但是我测试$string['check'][1]的时候,得到的是not found的结果,所以其实貌似不是只估值了最后一个。而还是$string[0][1]这样的,然后't'[1]不存在。如果只估值最后一个结果也就是[1]的话,那么应该得到的是h。

根据上面的来说,$str['f']['f'],或许只是变成$str[0]['f']了(如果这才是你的正确意思的话),所以这是有可能的。

总之,我发了个帖在PHP的新闻组里,然后有个家伙让我直接用array_key_exists代替。除此之外还没有更详细的回复。

http://news.php.net/php.general/323298

然后我就借机抱怨了下
http://news.php.net/php.general/323307

不知道会不会有什么进展。

总之我现在有两个方案来搞定这个问题了。

要么就老老实实地用着复杂组合。if (isset($val) && array_key_exists('key', $val) &&
is_string($val['key']) && !empty($val['key'])) {这些。

要么就利用上面的诡计if (isset($val['key'][1]) && is_string($val['key'])) {,这样一样能正确检测,但是数据不但必须不能是空的,还得多于2个字符。

当然还有一个做法是 isset($val['key'], $val['key'][0])。

我决定就这么纠结着用了。一边等邮件列表里的结果,虽然貌似看来不会有啥结果。

另外感谢你一直回复,我散点分给你哈。
2014-05-13 23:38:11 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming 我没说你陷入人家的模式啊,我只是说你接受了这个模式。当然,如果PHP那边觉得这样挺好,我也会接受这种模式,现在我已经学到了这个坑了,并且以后也会避免,只是可能我会多一个操作,比如去骂PHP是最好的语言。

(好在我聪明伶俐的在很久之前就在用户输入效验的模块里面加入了is_string判断,所以除了内部调用比如参数或配置填错了之外没有副作用。所以面对这问题我还是很轻松的。)

如果你有原理性的解释来解释为何会发生这种情况请但说无妨啊。不过你先看我12楼的对不对呢,如果 不对&&你愿意 的话帮我De个Bug。
2014-05-13 22:11:56 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming

1) 不,我只是借这个机会证明我是个诚实的人,哦呵呵。404我真不知道了,当然我刚才在Commit,不知道是不是Git在更新本地的数据。

2) 其实我看过那些内容了。也说了check到最后会变成0,所以……我真的已经看了。你可以看到剩下的我就开始不解为什么会这样了。

我的反应可能和你不一样,我猜测了原因(因为PHP的源代码真难看懂),因为数组下标和字符串下标在C里使用了不同的实现,所以导致处理方式上进行了不同的转换。isset是一种特殊的语法结构,他尝试在不操作目标的情况下对目标进检查(爬一下变量表嘛),然后再转换索引准备爬表的时候,使用了“绝顶聪明”的方法。

好吧,我真的不知道是怎么具体实现的。但是这样的设定,分明就是在造坑啊不是么。我是说,为什么isset($string['check'])能正确的搞出false,isset($string['check'][0])就得先雅蠛蝶的转换下变成$string[0][0]然后搞成true呢?因该也还是的设定false才对吧。 // 请作为用户视角来看待这个问题

3) 我已经不知道咋讨论了,就像22楼说的,说不定人家说“这是你不会用”。不过,等有空还是去吧唧下,不管有没有效果什么的。

4) 我觉得强类型语言真省心啊有没有,比如Python啊,Go啊什么的。
2014-05-13 21:47:04 +08:00
回复了 jsjwl 创建的主题 问与答 你会和 boss 顶嘴吗?
大部分时候,如果你看到一件事情很奇葩的事,背后往往有着一些你不知道的原因。
2014-05-13 21:36:57 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming

* Sigh *

20楼


> 所以是isset和var_dump对待$string['check']的方式不一致时才会出现这个问题。

所以你不需要重新说明一遍,真的,12楼的时候我已经把出现这个现象的原因都解释了。

我发这个帖子的目的不是为了让别人挑我用法上的刺。因为本身这样用就是错误的,我也只是意外的填错了参数才发现了这个问题罢了(这是我第二遍说了亲)。如果你真的有空,那么去看看我的代码,做做Review,我真的太感激了。但是这段代码,至少5楼链接里的具体那一行是没有问题的。(当然,至于为什么会有throw、return、break这样奇葩的组合,那真是我很奇葩的原因。而我会在未来某个版本删除掉那些。)



> 以及5楼的URL已经打不开了,就不吐槽这神奇的情况了。以及,真的还是好好看看手册吧……

Github是经常被墙的。难道你认为是我神奇的从Git历史记录里删掉了那个文件来遮丑么?这框架里面有2000多个文件啊,删掉任何一个都会导致问题,我不会那么蠢的。其次,我犯过很多很小的错误,而且他们都还在历史记录里,你甚至能看到修复记录,我不是喜欢删掉罪证然后把他们当作没发生过的家伙。



我现在的想法,是如果有人也觉得这样比较奇葩的的话,我就鼓足勇气去PHP邮件组跟那群真正设计语言的人吧啦下,看看他们能不能思考下这个问题。因为这样也太怪异了。不是么?

不过现在我担心的问题是,当我说“这样设计不太好吧”的时候,他们也会说,“哦,那不是问题,是你用错了,你看我们的手册要怎么用再来吧唧”。就跟……这个帖子的情况一样。

当然,你觉得不怪异可能是你已经接受了这种世界设定,就像他们当初给丢出magic quotes时一样。



我的观点也已经说过了,14楼。
2014-05-13 20:27:52 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming 什么叫奇葩的代码?上面已经说了怎么发现的这样的情况,你可以看到5楼。发这个帖子的时候我自己的Bug已经修复好了。只是奇怪这样的情况才来问。

另外“在isset()之前'check'就已经被转换成0了”,如果真的是这样的话,那么var_dump也应该是[0][0]才对,那么Illegal string offset就不会出现了。

所以是isset和var_dump对待$string['check']的方式不一致时才会出现这个问题。

代码我已经翻了,对我来说太乱了,已经迷失。正考虑是不是要去PHP邮件组上把这个问题再吧啦一遍。
2014-05-13 20:10:52 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming 你不觉得当遇到“不规范”的写法时,isset就应该因为找不到‘check’这个索引而失败么?没事“好心”转换integer才是有问题吧。
2014-05-13 14:11:24 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@lizheming

嗯。

不明白为什么isset和取值会用两种方式。虽然在字符串上这样用多维下标不是正确的用法,但这样不规律的隐式转换感觉是欠考虑了啊,isset和取值应该都被隐式转换或都不被隐式转换才是正确的逻辑吧。

不明白那群家伙怎么想的,或许……是给忘了。
2014-05-13 11:29:29 +08:00
回复了 raincious 创建的主题 PHP 貌似,被 isset 坑了又。
@vibbow 是的。应该是有特殊的处理。

Test1里面的情况看起来是这样的:

$string['check'][0] => $string[(int)'check'][0] => $string[0][0]

看来PHP在取完$string[0]的值之后得到了字符t,然后比较了't'[0],然后isset就通过了。所以造成了上面的问题。

看来以后做这类比较的时候得先判断下数据类型,以免造成问题(甚至可能是安全问题)。


而且还得注意取值的时候并没有做这类转换。
2014-05-13 09:19:05 +08:00
回复了 ddyy 创建的主题 PHP 所有使用 namespace 的 php 框架,一律无视
@soli

你可以 use Name\Space\Solar;

然后Solar\Planet,Solar\Sun,Solar\Moon啊。
1 ... 78  79  80  81  82  83  84  85  86  87 ... 107  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5574 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 27ms · UTC 06:49 · PVG 14:49 · LAX 22:49 · JFK 01:49
Developed with CodeLauncher
♥ Do have faith in what you're doing.