PHP通知抑制;仅在某些情况/方法下
tl;dr - 在非常严格的环境中工作时,是否有一种有效的方法来管理 PHP 的错误报告级别,因为某些过程会变得更容易不太严格的级别?
好吧;首先,我不相信“错误抑制”是一个解决方案。我(相当确定我)从未使用过 @
错误抑制运算符,并且无意这样做。我利用 set_error_handler()
和 ErrorException
(或其派生),并在 error_reporting(-1)< 中进行开发/code> (面向未来
E_ALL | E_STRICT
)
现在,我不想改变这些习惯,因为我发现它们是一个很好的实践(还有;如果有人有建议为了进一步改进我的开发/生产环境设置/实践,我洗耳恭听)
但是,当涉及到视图生成时,这可能会有点乏味。如果控制器出于某种原因无法将某些数据传递到视图,则正确的数据(数组索引、变量等)并不总是可用。只要此数据对于视图生成不重要,视图仍应呈现。
我更喜欢这种语法,因为它并不冗长,但(我认为)非常容易理解:
// e() is a shortcut function; given the passed value evaluates to a boolean true
// it will echo() and return true, otherwise it simply returns false
<p><?php e($data['field']) or e('No data found'); ?></p>
当然,如果 $data['field']
没有调用 offsetGet ()
并在缺少索引的情况下返回 null
,我们遇到了问题。通知遇到异常,异常遇到脚本失败。
我尝试了不同的实现,包括使用类似节点的类创建数据树来管理传递到视图的数据列表/行。 __get()
实际上会创建不存在的节点(在分配或访问时)(为了简化节点数据分配,并防止发出通知。__isset()
测试了有效性,并且会适当地返回false
)它还实现了ArrayAccess
来访问节点数据,并且在缺失时简单地返回 null
指数。
由于 PHP 魔法的开销,我选择放弃这个实现(虽然我学到了很多关于重构/优化和分析的知识),但
我已经使用了原生数组,但现在我的观点的代码库与 isset()
乱七八糟,坦率地说,这只是令人恼火(几乎超过上述实现的性能损失)
现在,我我认为最简单的修复方法是根据我们在脚本中的位置上下滑动 error_reporting()
缺口:
// View::render()
public function render($data){
error_reporting(E_ALL & ~E_NOTICE);
// view generation logic
error_reporting(-1);
}
但这似乎不是最干净的(也不是最安全的) 修复;特别是在视图中调用辅助函数时。我采用了一种 HMVC 方法,并且可以从视图发出子请求,因此我需要找到所有 render()
转义点并使用 保护它们错误报告(-1)。
我还有其他选择吗?
tl;dr - Is there an effective way to manage the error reporting level of PHP when working in a very strict environment, given certain processes would be made easier with a less strict level?
Alright; first off, I don't believe "error suppression" is a solution. I (am reasonably certain that I) have never used the @
error suppression operator, and have no intention of doing so. I take advantage of set_error_handler()
and ErrorException
(or some derivation of) and I develop in an error_reporting(-1)
(future proof E_ALL | E_STRICT
)
Now, I don't want to change these habits, as I find they are a great practice (also; if anyone has suggestions to further improve my development/production environment settings/practices, I'm all ears)
However, when it comes to view generation this can get slightly tedious. The correct data (array indices, variables, etc.) are not always available, given a controller fails to pass certain data to the view for whatever reason. As long as this data is non-critical to view generation, the view should still render.
I rather like this syntax as it's not verbose but (I think) highly understandable:
// e() is a shortcut function; given the passed value evaluates to a boolean true
// it will echo() and return true, otherwise it simply returns false
<p><?php e($data['field']) or e('No data found'); ?></p>
Of course, if $data['field']
isn't invoking offsetGet()
with null
returned in absence of the index, we have a problem. Notice meet exception, exception meet script failure.
I've experimented with different implementations, including creating a data tree using a node-like class to manage lists/rows of data passed to the view. __get()
would actually create nodes (on assignment or access) that don't exist (as to simplify node data assignment, and to prevent issuing notices. __isset()
tested for validity and would return false
appropriately though) It also implemented ArrayAccess
for accessing the node data, and would simply return null
on a missing index.
I've opted to abandon this implementation due to the overhead of PHP's magic (though I learned alot about refactoring/optimization and profiling)
I've gone with native arrays instead, but now the codebase for my views is littered with isset()
, and frankly that's just irritating (nearly more than the performance loss of the aforementioned implementation)
Now, I was thinking the easiest fix would be to slide the error_reporting()
notch up and down based on where we are in the script:
// View::render()
public function render($data){
error_reporting(E_ALL & ~E_NOTICE);
// view generation logic
error_reporting(-1);
}
But that doesn't seem like the cleanest (nor safest) fix; especially when helper functions are called within a view. I've gone for a sort of HMVC approach, and sub-requests can be issued from a view, so I'd need to find all the render()
escape points and guard them with error_reporting(-1)
.
Do I have any other options?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
“未定义的变量”通知非常有价值,即使在视图模板中也是如此,因为它们有助于发现拼写错误;但这需要定义控制器中的每个变量,或者检查它们是否在视图中设置。
正如您所注意到的,这两个明显的解决方案都有一些开销或缺点。即使禁用错误报告也会产生一些开销,因为错误仍然会生成(错误消息被格式化,内部和用户错误处理程序被调用等;它们只是被隐藏)。这隐藏了您可能从视图调用的辅助方法中的错误;这对调试没有帮助。
我建议您使用模板引擎。有些生成 PHP 代码的速度与手写代码一样快。他们会为你处理这个问题,并且会做更多的事情(比如转义,你的视图也应该充斥着 htmlspecialchars() 调用;))。
"undefined variable" notices are very valuable, even in view templates, as they help to spot typos; but this requires to either define every variable in the controllers, or to check if they are set in views.
As you noticed, the two obvious solutions have some overhead or drawbacks. Even disabling error reporting has some overhead since errors are still generated (the error message is formatted, internal and user error handlers are called, etc; they are just hidden). And this hides errors from helper methods you may call from the views; this doesn't helps debugging.
I would recommand you to go with a template engine. Some generate PHP code as fast as hand-written code. They will handle this for you, and will do more (like escaping, your views should also be littered with htmlspecialchars() calls ;) ).
继续报告E_NOTICE,这是值得的。也就是说,我同意
未定义索引
与未定义变量的错误程度不同,并且isset($options['boolean_flag']) && $options['boolean_flag']
有点难看。我从事的一个项目有数千个这样的通知,因此为了不断看到 E_NOTICE 级别的错误而不被未定义索引
淹没,我实际上重新编译了语言以忽略该错误特定类型的通知。 (我使用的是 HHVM 而不是 PHP,但它们是相同的区别)。是的,这是一个极端的解决方案,但它是一个紧要关头的选择。显然,您需要使用官方的生产版本。
注意:我写下了重新编译的步骤,如果有人想尝试,可以将其发布,但这有点超出了原始问题的范围。
Keep reporting E_NOTICE, it's worth it. That said, I agree that
Undefined Index
is not the same caliber of error as an undefined variable, andisset($options['boolean_flag']) && $options['boolean_flag']
is a bit ugly. A project I work on has thousands of those notices, so in order to keep seeing E_NOTICE-level errors without getting flooded byUndefined Index
, I actually recompiled the language to ignore that particular type of notice. (I'm using HHVM rather than PHP, but it's the same difference).Yeah, that's an extreme solution, but it is an option in a tight spot. Obviously you'll want to use an official build on production.
Note: I wrote down the steps to recompile and could post that if anyone would like to try, but it's a little outside the scope of the original question.