我目前正在开发一个框架,遇到了一个障碍...当有人调用框架中的函数时,我应该如何处理不正确的参数类型?
例子:
// Title is expected to be string, comment_num is expected to be int
function example1($title, $comment_num) {
// Doesnt throw error, just converts type
$title = (string) $title;
$comment_num = (int) $comment_num;
}
或
// Title is expected to be string, comment_num is expected to be int
function example2($title, $comment_num) {
if (!is_string($title)) {
trigger_error('String expected for first parameter', E_USER_WARNING);
return;
}
if (!is_string($title)) {
trigger_error('Int expected for second parameter', E_USER_WARNING);
return
}
}
或者两者混合会起作用吗?抛出错误并转换类型?
这样做的最佳方法是什么?我计划发布它,所以它不仅仅是我使用它,因此我也想为其他人考虑最好的方法。谢谢。
编辑!!!
所以我决定给出答案,但我也想发布我制作的代码,它允许我快速检查类型。它有点粗糙,但效果很好。
function __type_check($params) {
if (count($params) < 1) {
return;
}
$types = func_get_args();
array_shift($types);
$backtrace = debug_backtrace();
$backtrace = $backtrace[1];
$global_types = array(
'bool' => 'boolean',
'int' => 'integer',
'float' => 'double'
);
$error = false;
for ($i = 0, $j = count($types); $i < $j; ++$i) {
if (strpos($types[$i], ',') === false) {
$type = strtolower($types[$i]);
if (isset($global_types[$type])) {
$type = $global_types[$type];
}
if (gettype($params[$i]) != $type) {
$error = true;
break;
}
} else {
$current_types = array_map('trim', explode(',', $types[$i]));
foreach ($current_types as $type) {
$type = strtolower($type);
if (isset($global_types[$type])) {
$type = $global_types[$type];
}
if (gettype($params[$i]) == $type) {
continue 2;
}
}
$error = true;
break;
}
}
if ($error) {
trigger_error($backtrace['function'] . '() expects parameter ' . ($i + 1) . ' to be ' . $types[$i] . ', ' . gettype($params[$i]) . ' given', E_USER_WARNING);
return false;
}
return true;
}
你会像这样使用它:
function string_manipulation($str, $str2, $offset = 1) {
if (!__type_check(func_get_args(), 'string', 'string', 'int,float')) {
return false;
}
// do manipulation here
}
这基本上会检查第一个和第二个参数是字符串,第三个参数是整数还是 float 。您可以组合任何类型 'string、int、array、object' 等,所有有效类型都取自 gettype
/* 已知错误 */ null 是一种类型,无法决定它是否应该 如果您输入一个类名,它不会检查实例,而只会进行类型检查 还没想出触发错误的好方法……嗯
我就是这样,错误很容易修复 :D
最佳答案
视情况而定。
PHP 是一种动态类型的语言,有时这是有充分理由的。由于它处理大量 HTTP 数据,这些数据一直都是字符串,因此数字不一定总是 int 类型,并且对于一般操作仍然可以正常工作。
严格执行基本类型通常非常不符合 PHP 风格,使用起来可能很麻烦。
在 PHP 中做事的通常方法是接受几乎任何类型的参数并真诚地使用它们,直到您需要特定的结果或类型成为问题。
function example1($title, $comment_num) {
// do some operations that should work error-free regardless of type
if ($result != 'something specific you expect here') {
throw new Exception('Something went wrong!');
// or
trigger_error('Something went wrong!');
return false;
}
// continue with $result
}
您可以采用 OOP 路线并以这种方式构造对象。对象将在某种程度上灵活地接受它们。如果它们成功构建,您就有了一个特定类型的已定义对象,您可以将其用于 PHP 强制类型提示:
function example1(TitleObject $title) {
// rest assured that $title is of the right type
}
关于PHP函数参数类型最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4754759/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了