回调函数:Callback (即call then back 被主函数调用运算后会返回主函数),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。
回调函数其实就是callback类型,在方法中可以使用callable关键字来申明形参是回调函数;在方法体内可以使用is_callable($entry)方法来判断是否可回调。
public function with(callable $entry){
if(is_callable($entry)){
//TODO
}else{
throw new Exception('参数entry不是回调函数')
}
}
到底怎么使用回调函数呢?其实很多例子
$number=[1,2,'a'];
$filter=array_filter($number,function ($value){
if(is_numeric($value)){
return true;
}else{
return false;
}
});
class mysql
{
public function init()
{
try{
$con=new Con();
$con->startTrasnaction();
//TODO
$con->commit();
}catch (\Exception $e){
$con->rollBack();
}
}
}
$a = new mysql();
$a->init();
缺点就是:每次都需要重复写一些new Con(),startTrasnaction(),commit(),rollBack()的代码,所以这里我就可以使用回调函数的方式来轻松降低代码的重复复,如下:
class mysql
{
public function init()
{
$a=$this->a;
$b=$this->b;
$con = new SrmCon();//con类的子类
self::transaction(function ()use ($con){
//TODO
},$con);
}
public static function transaction(callable $func,Con $con)
{
if(is_callable($func)){
try{
$con->startTrasnaction();
//call_user_func_array()
call_user_func($func);//调用回调函数
$con->commit();
}catch (\Exception $e){
$con->rollBack();
}
}else{
throw new Exception('参数不是回调函数');
}
}
}
////回调函数
$a = new mysql();
$a->init();
通过封装了transaction()方法,在执行一些事务操作时再也不需要写startTrasnaction、commit、rollBack这些了。
transaction这个方法的封装,有俩大特点需要注意下:
$callback, array $param_arr): mixed$callback): mixed 也是调用回调函数的,和上面那个的区别就是这里没有第二个参数,只有一个回调函数参数。$this, 'test'], ...$this->params),其实call_user_func和call_user_func_array函数并不是只可调用回调函数,普通的方法也可以调。像这个表达式指的是调用本类的test方法,省去了new实例了
PHP将匿名函数和闭包视作相同的概念,下面统称闭包,顾名思义就是没有名字的函数。
匿名函数通常用在回调函数中,同时匿名函数也可以赋值给一个变量后使用,还能像其他任何 PHP 对象那样传递,不过匿名函数仍然是函数,因此可以调用,并且可以传入参数。
闭包函数的定义通常有以下几种方法
$func_name = function($arg){statement};我们以第一种方式定义一个闭包函数,匿名函数可以作为变量的值来使用。此时 PHP 会自动把此种表达式转换成内置类Closure 的对象实例
<?php
$url = function (){
return 'http://c.biancheng.net/php/';
};
?>
判断是不是闭包,有俩种方式,通过Closure内置类或者is_callable方法都可以判断
if($url instanceof Closure){
echo '是匿名函数';
}else{
echo '不是匿名函数';
}
if(is_callable($url)){
echo '是匿名函数';
}else{
echo '不是匿名函数';
}
闭包说白了还是一个函数,所以调用闭包函数是在变量后面需要加上(),可能变量后面加()有点不适应,按照正常的思维,变量是直接调用,所以看到变量后面加()的,就知道该变量代表的是一个匿名函数。
echo $url();
$b=serialize($url);
$c=unserialize($url);
var_dump($c);
会报错
Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in /Users/sftc/workerDir/sf-odp-2.0/script/xulie.php:114
可以看出闭包在php是不允许序列化的,那如果我们遇到了序列化的场景怎么办
composer require opis/closure
//(2).序列化闭包函数,输出序列化后的字符串
$b = \Opis\Closure\serialize($url);
//(3).反序列化闭包函数,执行还原的闭包函数
$c = \Opis\Closure\unserialize($b);
$c();
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
我没有理解以下行为(另请参阅inthisSOthread):defdef_testputs'def_test.in'yieldifblock_given?puts'def_test.out'enddef_testdoputs'def_testok'endblock_test=procdo|&block|puts'block_test.in'block.callifblockputs'block_test.out'endblock_test.calldoputs'block_test'endproc_test=procdoputs'proc_test.in'yieldifblock_gi
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只