首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
185 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
33
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
560
篇与
的结果
2023-08-11
PHP 7.4 FFI(外部函数接口)
PHP外部函数接口:FFI,是一个PHP扩展,允许您轻松地将一些外部库包含到PHP代码中。这意味着可以直接在PHP中使用C,Go,Rust等共享库,而无需在C中编写PHP扩展。这个概念在其他语言(如Python或Go)中已经存在多年了。UUID生成让我们从一个小例子开始:UUID生成。PHP 7.4 FFI(外部函数接口)使用PHP,有几种生成UUID的方法。最好的方法是使用PECL UUID扩展名。您可以在GitHub上阅读其代码。这个PHP扩展负责将PHP函数绑定到libuuid。要使其正常工作,您必须在系统上安装libuuid(不必担心,几乎总是这样)和PECL。这就是我们从PHP用户代码调用uuid_create()时发生的情况:your PHP code+---+-------------^---+ v ^+---v-------------+---+ | PHP engine | +---+-------------^---+ v ^+---v-------------+---+ | UUID ext | +---+-------------^---+ v ^+---v-------------+---+ | UUID lib | +---------------------+FFI承诺用纯PHP代码替换“ UUID扩展”层。在讨论PHP扩展或FFI层之前,我们需要解释什么是库。库通常是用C编写的。但是也可以用许多其他可以编译为共享库的语言来编写:C ++,Rust,Go等。在unix或linux上,该库将被编译成一个.so文件。在Windows上它将是一个.dll文件。也可以将库静态包含到二进制文件中,但是本章不在本文的讨论范围之内。在库代码源中,有.h文件。它们包含库能够执行的操作。这是uuid.h文件的摘录:…Some constants:define UUID_VARIANT_NCS 0define UUID_VARIANT_DCE 1define UUID_VARIANT_MICROSOFT 2define UUID_VARIANT_OTHER 3Some function declarations:void uuid_generate(uuid_t out);int uuid_compare(const uuid_t uu1, const uuid_t uu2);…一个.h文件类似于PHP接口的东西:它含有常量和函数签名。FFI/UUID 层为了工作,FFI 需要我们想要使用的基础库 (libuuid) 的函数签名。因此,我们将.h文件复制到我们的项目中。有时,您可以清理并调整此文件以满足您的需要。例如,您可以删除永远不会使用的函数。这就是我们的文件的样子:define FFI_LIB "libuuid.so.1"typedef unsigned char uuid_t[16];extern void uuid_generate_time(uuid_t out); // v1extern void uuid_generate_md5(uuid_t out, const uuid_t ns, const char *name, size_t len); // v3extern void uuid_generate_random(uuid_t out); // v4extern void uuid_generate_sha1(uuid_t out, const uuid_t ns, const char *name, size_t len); // v5这是最重要的,也是编写代码中更复杂的部分。完成后,我们可以将此文件包含在我们的PHP代码中:$ffi = FFI::load(__DIR__ . '/include/uuid-php.h');我们现在可以直接从PHP代码中使用libuuid。容易,不是吗?但等一下,libuuid不能完全那样工作。所有函数都期望一些类型化的参数,您可能已经看到过。这些函数不返回 UUID,但将通过引用第一个参数进行修改。因此,在调用 函数之前,我们需要此值:$output = $ffi->new('uuid_t');$output是的实例FFI\CData。根据的内部类型,CData由于文档中描述了不同的运算符,我们可以访问不同的值。最后,我们可以调用我们的函数。uuid_generate_random()匹配.h文件中库公开的名称:$ffi->uuid_generate_random($output);$output的内容将用组成 UUID 的十进制值数组进行更新。现在,我们需要将此数组转换为十六进制值的字符串:foreach ($output as $values[]);$uuid = sprintf('%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x', ...$values);你喜欢它吗?如果您不想麻烦复制它,我们为您制作了它,并且它是开源的:https: //github.com/jolicode/ffi-uuid🍾一些想法简单外部库的绑定确实很容易。最复杂的部分是创建最小 .h文件,并将PHP类型映射到库,反之亦然。性能看看我们实现的性能也很有趣。在我们的存储库中,您可以找到一个基准脚本。这是我们的实现与PECL之间进行比较的结果:FFI:[v1] 1.254s[v4] 5.301sPECL:[v1] 0.626s[v4] 4.583s可以看到,PECL比我们的UUID V1实现快两倍,但对于UUID V4仅快15%。我们可以很容易地解释一下:UUID V4仅由伪随机数据组成,而UUID V1包含许多静态块。获取随机数据有点慢,这就是为什么V4生成要慢得多的原因。在V4上,这两种实现的区别不明显,因为几乎所有时间都花在了内部libuuid。我们可以得出什么结论?FFI确实还很年轻(在撰写本文时甚至没有发布)。因此,我们可以期待一些性能上的改进。但是我们已经可以说:如果本机扩展已经存在并且可以安装,请使用它:如果扩展不存在,那么FFI是一个很好的候选项;如果应用程序中存在瓶颈,在 C、Rust 等中移植这些代码位并将其绑定到 FFI 可能很有趣。当 CPU 受限制时,FFI 会变得非常有趣:DOM 管理、大阵列、复杂计算等。原来的扩展是否将替换为FFI?现在说还真为时过早。但是,某些扩展(例如PDO)不仅仅具有简单绑定到库的功能。我非常有信心这些扩展将不会被FFI取代。但是,某些扩展可能会被替换。php-redis,amqp,uuid等就是这种情况。例如Remi Collet已经开始使用FFI来代替redis扩展。FFI敞开了大门:可以替换一些纯PHP库,而改用低级库。gitlib可以使用带有FFI的libgit2就是这种情况。在某些情况下,没有C扩展,也没有纯PHP实现。如果您曾经尝试在PHP中测试TensorFlow,您会知道它很复杂。Dmitry Stogov是最重要的PHP Core贡献者之一,也是PHP / FFI的作者,他创建了一个POC来将TensorFlow绑定到PHP。选择哪种语言将lib绑定到PHP?能够编译到共享库(.so)的所有语言在系统上都不能很好地绑定到PHP。最好使用没有运行时的语言(C / C ++ / Rust /…),因为运行时可能会有副作用。例如,在GO中,运行时具有垃圾回收器并管理goroutine的线程。这可能会降低执行速度,甚至破坏您的应用程序。如何将Rust lib绑定到PHP?我想尝试一下用另一种语言比PHP执行复杂的计算是否更快。从网页提取HTML片段是很常见的:为了测试您的网站,或在爬网时。Joel创建了一个小型库,用于提取与CSS表达式匹配的文档的第一个HTML元素。该代码确实很短,在某种程度上,Rust类型向C Type的转换代表了代码的2/3以上。PHP绑定看起来与UUID非常相似。但是这里我们将.so直接包含在源代码中:$ffi = FFI::cdef(<<<EOHconst char cssfilter(const char html, const char *filter);EOH, __DIR__.'/../target/release/libcssfilter.so');而且用法更简单:$value = $ffi->cssfilter($html, $selector);性能确实令人印象深刻,令人鼓舞:FFI: Duration: 1.731ssymfony/crawler: Duration: 2.321s我们可以轻松得出结论,如果计算复杂,将一部分PHP代码移植到另一种语言以提高应用程序性能可能非常有趣。结论FFI是个好东西。即使绑定尚不存在,FFI也会允许我们尝试一些库。它将使我们可以用Rust(例如)植入替换代码的某些慢速部分。而且我敢肯定,它将解锁一些我们还没有的想法。
2023年08月11日
10 阅读
0 评论
0 点赞
2023-08-11
PHP中闭包Closure::bind详解
PHP中闭包Closure::bind详解最近在看laravel底层代码时 ,发现代码中很多Closure::bind用法,查询各种资料,一直对它的使用一直半解(网上大多都是抄袭教材,解释的不清楚),还好经过我不懈努力,终于弄懂了其中道理。1、在正式解释前我们先了解一些基础的东西(稍安勿躁,磨刀不误砍柴工。大多说看不懂其用法的人,主要还是基础不牢)。php中 闭包我们也可以叫做匿名函数,匿名函数不了解的可以自行补一下,我这边简单举例:$say = function(){return '我是匿名函数';};//echo $say(); //这是最直接调用匿名函数方式 输出 我是匿名函数function test(Closure $callback){return $callback();}echo test($say); //这是间接调用匿名函数方式 同样输出 我是匿名函数当然也可以这样写 :echo test( function(){return '我是匿名函数';});2、接着我们来说一下php的public、protected、private三种访问控制模式的区别public: 公有类型 在子类中可以通过self::var调用public方法或属性,parent::method调用父类方法在实例中可以能过$obj->var 来调用 public类型的方法或属性protected: 受保护类型在子类中可以通过self::var调用protected方法或属性,parent::method调用父类方法在实例中不能通过$obj->var 来调用 protected类型的方法或属性private: 私有类型该类型的属性或方法只能在该类中使用,在该类的实例、子类中、子类的实例中都不能调用私有类型的属性和方法<?phpclassA{private $name ='王力宏';protected $age ='30';privatestatic $weight ='70kg';public $address ='中国';publicstatic $height ='180cm';}$obj = new A();//echo $obj->name;//报错 Cannot access private property A::$name//echo $obj->age;//报错 Cannot access protected property A::$age//echo A::$weight; //报错 Cannot access private property A::$weightecho $obj->address;//正常 输出 中国echoA::$height;//正常 输出 180cm$fun = function(){$obj = new A();return $obj->address;//实例对象可以获得公有属性, $obj->name等私有属性肯定不行 上面例子已列出报错}echo $fun();//正常 输出 中国$fun2 = function(){returnA::$height;// 类可以直接访问公有静态属性,但A::$weight肯定不行,因为weight为私有属性}echo $fun2();//正常 输出 180cm3、在以上都理解的情况下 我们来看看这样的情况,有如下匿名函数:$fun = function(){return$this->name;}或者$fun = function(){returnA::$height;}echo $fun();//会报错的其实单独这段代码是肯定不能运行 调用的,因为里面有个$this,程序压根不知道你这个$this是代表那个对象 或 那个类(并且就算知道那个对象或类,该对象是否拥有name属性,如果没有照样会有问题)因此想让其正常运行肯定有前提条件啊(就好比你想遍历某个数组一样,如果这个数组压根你就没提前定义 声明 肯定会报错的)如果这样:<?phpclass A{private $name ='王力宏';protected $age ='30';privatestatic $weight ='70kg';public $address ='中国';publicstatic $height ='180cm';}$fun = function(){return$this->name;} ;$cf = Closure::bind($fun,new A() ,'A'); //该函数返回一个新的 Closure 对象 或者在失败时返回 FALSEecho $cf();//输出 王力宏 为什么呢:bind第一个参数是匿名函数,第二个A实例对象,第三个代表作用域//网上很多讲解是说把匿名函数绑定到了实例对象上了 然后就怎么着......很多新手看了依然一脸懵逼。其实是匿名函数里的$this被指定到了或绑定到了A实例对象上了Closure::bind($fun,new A() );这个使用 你可以理解成对匿名函数做了如下过程:$fun = function(){$this=newA();//你可以想象认为,$this就成了A类的实例对象了,然后在去访问name属性,就和我们正常实例化类访问成员属性一样,上面2中的例子$obj = new A()就是这样,(因为$this是关键字,在这里我们其实不能直接$this = new A();这么写,为了好理解我写成$this,但是原理还是这个意思),但是我们都知道因为name属性是私有的,上面2中我已说过,实例对象不能访问私有属性,那该怎么办呢,于是添加第三个参数就很重要了,一般传入传入一个对应对象,或对应类名(对应的意思是:匿名函数中$this-name想获取name属性值,你这个$this想和那个类和对象绑定在一起呢,就是第二个参数,这时你第三个参数写和第二个参数写一样的对象或类就行了,就是作用域为这个对象或类,这就会让原理的name私有属性变为公有属性)return$this->name;} ;为了加深理解我在举两个例子:<?phpclass A{private $name ='王力宏';protected $age ='30';privatestatic $weight ='70kg';public $address ='中国';publicstatic $height ='180cm';}$fun = function(){$obj = new A();return $obj->address;};echo $fun();//正常 输出 中国 ,该例子其实在上面2中已经讲过了 如果跟这个还不能理解 就不要往下看了 好好补一下基础$fun2 = function(){return$this->address;};//echo $fun2();这样运行会报错 所以我们要进行匿名函数的绑定 是匿名函数里的$this有所指,必要时还要改变要访问属性的作用域$newfun2 = Closure::bind($fun2, new A() );//使用了该函数后 ,该函数返回一个全新的匿名的函数,和原来匿名函数$fun2一模一样,只是其中 $this被指向了A实例对象,这样就能访问address属性了echo $newfun2();//正常 输出 中国,在这里数一下bind这次为什么没添加第三个参数,因为我们要访问的address属性是公有的,一个对象实例是可以直接访问公有属性的,这个例子中只要匿名函数中$this被指向了A对象实例(或者叫绑定也可以),就能访问到公有属性,所以可以不用添加第三个参数,当然你加上了第三个参数 如这样Closure::bind($fun2, new A(), ‘A’ );或Closure::bind($fun2, new A(), nwe A() );不影响 照样运行,就好比把原来公有属性 变为公有属性 不影响的(一般当我们访问的属性为私有属性时,才使用第三个参数改变作用域 ,使其变为公有属性)下面来看最后一例子,再次加深一下理解:<?phpclass A{private $name ='王力宏';protected $age ='30';privatestatic $weight ='70kg';public $address ='中国';publicstatic $height ='180cm';}$fun = function(){returnA::$weight;};//echo $fun(); 运行会报错 因为weight为私有属性 上面2中例子访问height属性是可以的,height为公有属性,所以把weight改成height是可以正常运行的,但是我们现在就想访问这个私有静态属性,我们该怎么办,于是Closure::bind出场了$newfun = Closure::bind($fun,null,'A');//通过bind函数作用,返回一个和$fun匿名函数一模一样的匿名函数,只是该匿名函数中A::$weight, weight属性由私有变成公有属性了。echo $newfun();// 正常 输出 70kg ,为什么第二个参数又成null了呢,因为在该匿名函数中A::$weight 这属于正常类使用啊(php中 类名::公有静态属性,这是正常访问方法,上面2中例子已经说的很清楚了),所以不用绑定到某个对象上去了,于是第二个参数可以省略,唯一遗憾的是weight属性虽是静态属性,但是其权限是private私有属性,于是我们要把私有属性变公有属性就可以了,这时把第三个参数加上去就可以了,第三个参数可以是A类(Closure::bind($fun,null,'A')),也可以是A类的对象实例(Closure::bind($fun,null, new A() )),两种写法都可以,最终第三个参数的添加使私有属性变成了公有属性,(这个例子中当然你非得添加第二个参数肯定也没问题,只要第二个参数是A的实例对象就行Closure::bind($fun,new A(),'A'),不影响,只是说 A::$weight 这种使用方法本身就是正常使用,程序本身就知道你用的是A类,你在去把它指向到A类自己的对象实例上,属于多此一举,因此第二个参数加不加都行,不加写null就行)综上大家应该理解其用法了吧,有时第二个参数为null,有时第三个参数可以不要,这些都跟你匿名函数里 代码中访问的方式紧密相关总结:1、一般匿名函数中有$this->name类似这样用 $this访问属性方式时,你在使用bind绑定时 ,第二个参数肯定要写,写出你绑定那个对象实例,第三个参数要不要呢,要看你访问的这个属性,在绑定对象中的权限属性,如果是private,protected 你要使用第三个参数 使其变为公有属性, 如果本来就是公有,你可以省略,也可以不省略2、一般匿名函数中是 类名::静态属性 类似这样的访问方式(比如例子中A::$weight),你在使用bind绑定时,第二个参数可以写null,也可以写出具体的对象实例,一般写null就行(写了具体对象实例多此一举),第三个参数写不写还是得看你访问的这个静态属性的权限是 private 还是 public,如果是私有private或受保护protected的,你就得第三个参数必须写,才能使其权限变为公有属性 正常访问,如果本来就是公有public可以不用写,可以省略
2023年08月11日
17 阅读
0 评论
0 点赞
2023-08-11
PHP里如何获取函数的调用位置
PHP里如何获取函数的调用位置<?php function c() { a(); } function a() { b(); } function b() { $backtrace = debug_backtrace(); $aa= array_shift($backtrace); var_dump($aa); } c(); /* 输出 array(4) { ["file"]=> string(14) "/code/main.php" ["line"]=> int(6) ["function"]=> string(1) "b" ["args"]=> array(0) { } } */ ?>
2023年08月11日
19 阅读
0 评论
0 点赞
2023-08-11
异步PHP
异步PHP这里有一个新的程序包,它称为spatie/async,旨在在PHP中进行异步并行处理。对于许多Web开发人员而言,PHP中的并行处理似乎是一个边缘案例,但让我们看一下Spatie上的一些用例:图像优化PDF渲染并发网站爬网代码生成器静态网站生成器-像Stitcher我们想创建一个易于使用的程序包,但是它可以解决我们的用例。上面列出的有些示例将不使用新spatie/async软件包,因为Laravel还提供了一个队列系统。这就是我们程序包中的异步代码的样子。use Spatie\Async\Process;$pool = Pool::create();foreach (range(1, 5) as $i) {$pool[] = async(function () use ($i) { // Something to execute in a child process. })->then(function (int $output) { // Handle output returned from the child process. })->catch(function (Exception $exception) { // Handle exceptions thrown in the child process. });}await($pool);表现优于Amp?不完全如果您使用并行PHP,则可能听说过Amp和ReactPHP。我们的软件包的目标是不与这两个软件包竞争,因为它仅解决了PHP并行化的一个微小方面。并尝试以其他方式解决它。但是,我们确实运行了一些基准测试来比较我们的包与Amp的性能。特别感谢Amp的开发人员之一Niklas Keller。他指出了我们先前基准测试中的一些错误,并帮助使它们更加公平。新的基准测试比较了一些方案。前两组绘制了一个空进程的执行时间,而第三组和第四组则使用几个sleep时间间隔显示了具有不同完成时间的进程的执行时间。在这两组之间,我们还比较了有上限的并发配置和无上限的配置。上限意味着进程数量超过池一次执行的数量。基准代码可以在这里找到。比较Amp和Spatie/Async我试图从这些测试中得出一些结论。现实生活进程需要时间来运行和完成。对于我们的用例,“with logic”基准更为相关。关于进程执行时间,似乎我们的程序包开销较小:只要池不必管理并发,我们的处理速度就会更快。但是,在现实生活中的应用程序中,最大并发设置很有可能会生效,因此很明显,如果我们想要比Amp更好的性能,则需要改进代码库的这一部分。什么ReactPHP?我们已经将ReactPHP从基准测试中排除了,因为这不是一个公平的比较。ReactPHP不允许Tasks像Amp和我们的包那样运行闭包或作为子过程。使用ReactPHP,您可以使用简单的流程,因此无法与之进行比较。关于进程信号我们的程序包和Amp之间最大的区别是进程之间的通信方式。我们仅依靠进程信号来确定进程何时完成。它可以减少开销,但也可以将Windows排除在目标平台之外。UNIX系统中的进程可以相互发送信号。根据接收到的信号的种类,进程将有所不同。信号是由内核处理的,因此它们的电平很低。但是在PHP 7.1之前,您必须以declare(ticks=1)可靠的方式使用异步信号。这意味着PHP将更频繁地检查信号,但同时也会带来很多开销:tick是声明器中解析器执行的每N个低级tickable语句发生的事件。N的值是在声明块的指令部分中使用ticks = N来指定的。使用PHP 7.1,有一种新方法可以处理内核发送的中断。PHP 7.1中的Zend Engine扩展了安全超时和中断处理功能。实际上,PHP VM在每次循环迭代,用户函数进入或内部函数退出时检查EG(vm_interrupt)标志,并在必要时调用回调函数。通过使用pcntl_async_signals(true),PHP现在将以更高效的方式检查信号。可以在Dmitry Stogov提交的rfc中找到更深入的解释。正是由于这种机制,我们才能够以真正的异步方式对进程状态进行更改,而不必依赖套接字或进程状态轮询。
2023年08月11日
13 阅读
0 评论
0 点赞
2023-08-11
Laravel 将数据表中的数据导出,并生成seed文件
Laravel 将数据表中的数据导出,并生成seed文件在 laravel 开发过程中,我们为了将自己本地数据库中的数据导出给别人用有两种方法:最普通的也就是将自己的数据库用命令行或者图形操作工具导出成 .sql 的文件给对方使用 ,另外一种就是 laravel 提供的数据库 seed 文件,来看看怎么使用 seed :安装isseedcomposer require "orangehill/iseed": "2.1"然后把 seed 添加到 provider 中:'providers' => [ ... Orangehill\Iseed\IseedServiceProvider::class, ],到此 iseed 已经安装好了,下面来看看 iseed 的用法:假如要导出某张表的数据,命令为:``phpphp artisan iseed 表名如果要导出多张表的话,那么在命令后加 , 表名2 导出数据并且强制覆盖:php artisan iseed 表名1[,表名2...]--force导出指定的数据库里指定的表,并生成seed文件: php artisan iseed 表名--database=数据库名最后执行命令重新执行 migrate 文件并且填充 seed 文件数据:php artisan migrate:refresh --seed
2023年08月11日
15 阅读
0 评论
0 点赞
1
...
52
53
54
...
112