alpa/tools_sucker
Composer 安装命令:
composer require alpa/tools_sucker
包简介
For unit testing. The sucker for classes and objects to call private methods.
README 文档
README
For unit testing. The sucker for classes and objects to call private methods.
The component provides access to private properties of an object / class.
Install
composer require alpa/tools_sucker:1.0.*
Preface
Let's create classes for examples.
<?php class A{ private $private_prop='hello'; private static $static_private_prop='hello'; private function private_method($arg) { return $arg; } private function & private_methodByReference(&$arg=null) { return $arg; } } class B extends A{ private $private_prop='bay'; private static $static_private_prop='bay'; private function private_method($arg) { return strtoupper($arg); } }
syntactic sugar
There are 3 ways (API) to use the component.
1 way - if you need efficiency and a minimum of executable code under the hood.
use A; use B; use Alpa\Tools\Sucker\SuckerObjectHandlers; use Alpa\Tools\Sucker\SuckerClassHandlers; $handler=new SuckerObjectHandlers(new B); //scope B class echo $handler->get('private_prop');// bay echo "\n"; // scope A class; echo $handler->setScope(A::class)->get('private_prop');// hello echo "\n"; $handler->setScope(null);// reset scope $staticHandlers=new SuckerClassHandlers(B::class); echo $staticHandlers->get('static_private_prop');// hello echo "\n"; echo $handler->setScope(A::class)->get('static_private_prop');// hello echo "\n"; // environment maintained at A class level echo $handler->get('static_private_prop');// hello $handler->setScope(null); // reset scope
2 way - Wrapper pattern. Improves the previous solution.
use A; use B; use Alpa\Tools\Sucker\Sucker; $sucker=new Sucker(new B); echo $sucker->get('private_prop');// bay echo "\n"; echo $sucker(A::class)->get('private_prop');// hello echo "\n"; // Warn : The Scope is automatically reset after calling methods that are responsible for accessing members of the observable object echo $sucker->get('private_prop');// bay echo "\n"; $sucker=new Sucker(B::class); echo $sucker->get('static_private_prop');// bay echo "\n"; echo $sucker(A::class)->get('static_private_prop');// hello echo "\n"; // Warn : The Scope is automatically reset after calling methods that are responsible for accessing members of the observable object echo $sucker->get('static_private_prop');// bay echo "\n";
3 way - Proxy. syntactic sugar.
use A; use B; use Alpa\Tools\Sucker\Proxy; $proxy=new Proxy(new B); echo $proxy->private_prop;// bay echo $proxy(A::class)->private_prop;// hello // Warn : The Scope is automatically reset after calling methods that are responsible for accessing members of the observable object echo $proxy->private_prop;// bay $proxy=new Proxy(B::class); echo $proxy->static_private_prop;// bay echo $proxy(A::class)->static_private_prop;// hello // Warn : The Scope is automatically reset after calling methods that are responsible for accessing members of the observable object echo $proxy->static_private_prop;// bay
Basic principle
The code implements the following principle:
<?php Class A { private $prop='hello'; } $call=function(){ // var_dump($this);//$target // var_dump(self::class);//$slaveClass return $this->prop; }; $target= new A(); $slaveClass=A::class; $call=$call->bindTo($target,$slaveClass); echo $call();
Get value properties
<?php use Alpa\Tools\Sucker\SuckerObjectHandlers; use Alpa\Tools\Sucker\Sucker; use Alpa\Tools\Sucker\Proxy; $handler=new SuckerObjectHandlers(new B); echo $handler->get('private_prop');// bay echo $handler->setScope(A::class)->get('private_prop');// hello //get by reference $var = & $handler->get('private_prop');// & return A::$private_prop ==='hello' $handler->setScope(null); //or $sucker=new Sucker(new B); echo $sucker->get('private_prop');// bay echo $sucker(A::class)->get('private_prop');// hello //get by reference $var = & $sucker(A::class)->get('private_prop');// & return A::$private_prop ==='hello' //or $proxy=new Proxy(new B); echo $proxy->private_prop;// bay echo $proxy(A::class)->private_prop;// hello //get by reference $var = & $proxy(A::class)->private_prop;// & return A::$private_prop ==='hello'
Set value to properties.
<?php use Alpa\Tools\Sucker\SuckerObjectHandlers; use Alpa\Tools\Sucker\Sucker; use Alpa\Tools\Sucker\Proxy; $handler=new SuckerObjectHandlers(new B); //the value is passed by reference. Therefore it is necessary to pass it through a variable $var='BAY'; // set by reference $handler->set('private_prop',$var); //B::$private_prop=$var=>'BAY'; $handler->setScope(A::class)->set('private_prop',$var); //A::$private_prop=$var=>'BAY'; $handler->setScope(null); //or $sucker=new Sucker(new B); $sucker->set('private_prop','HELLO');//B::$private_prop=$var=>'HELLO'; $sucker(A::class)->set('private_prop','HELLO');// //A::$private_prop=$var=>'HELLO'; //get by reference $var='HELLO'; $sucker(A::class)->setRef('private_prop',$var);// A::$private_prop = &$var=>'HELLO' //or $proxy=new Proxy(new B); $proxy->private_prop='HELLO';// B::$private_prop='HELLO' $proxy(A::class)->private_prop='HELLO';// A::$private_prop='HELLO' //With a proxy, transmission by reference is not possible
Check (isset) property
use Alpa\Tools\Sucker\SuckerObjectHandlers; use Alpa\Tools\Sucker\Sucker; use Alpa\Tools\Sucker\Proxy; $handler=new SuckerObjectHandlers(new B); echo $handler->isset('private_prop'); //check $obj(B)::$private_prop; echo $handler->setScope(A::class)->isset('private_prop'); //check $obj(A)::$private_prop; $handler->setScope(null); //or $sucker=new Sucker(new B); $sucker->isset('private_prop');//check $obj(B)::$private_prop $sucker(A::class)->isset('private_prop');// check $obj(A)::$private_prop //or $proxy=new Proxy(new B); echo isset($proxy->private_prop);// check $obj(B)::$private_prop echo isset($proxy(A::class)->private_prop);// $obj(A)::$private_prop
Unset property
use Alpa\Tools\Sucker\SuckerObjectHandlers; use Alpa\Tools\Sucker\Sucker; use Alpa\Tools\Sucker\Proxy; $handler=new SuckerObjectHandlers(new B); $handler->unset('private_prop'); //unset $obj(B)::$private_prop; $handler->setScope(A::class)->unset('private_prop'); //unset $obj(A)::$private_prop; $handler->setScope(null); //or $sucker=new Sucker(new B); $sucker->unset('private_prop');//check $obj(B)::$private_prop $sucker(A::class)->unset('private_prop');// check $obj(A)::$private_prop //or $proxy=new Proxy(new B); unset($proxy->private_prop);// check $obj(B)::$private_prop unset($proxy(A::class)->private_prop);// $obj(A)::$private_prop
Iterate properties
use Alpa\Tools\Sucker\SuckerObjectHandlers; use Alpa\Tools\Sucker\Sucker; use Alpa\Tools\Sucker\Proxy; $handler=new SuckerObjectHandlers(new B); $handler->each(function($key, &$value){ // $value variable passed by reference echo self::class===B::class; // $this =>object B return true; // break }); //unset $obj(B)::$private_prop; $handler->setScope(A::class)->each(function ($key,$value){ echo self::class===A::class; return true; // break }); $handler->setScope(null); //or $sucker=new Sucker(new B); $sucker->each(function($key, &$value){ // $value variable passed by reference echo self::class===B::class; // $this =>object B return true; // break }); $sucker(A::class)->each(function ($key,$value){ echo self::class===A::class; return true; // break }); //or $proxy=new Proxy(new B); foreach($proxy as $key => $value){ // your code } foreach($proxy(A::class) as $key => $value){ // your code }
Call methods
<?php use Alpa\Tools\Sucker\SuckerObjectHandlers; use Alpa\Tools\Sucker\Sucker; use Alpa\Tools\Sucker\Proxy; $handler=new SuckerObjectHandlers(new B); $arg='hello'; // passing a variable by reference $var = $handler->call('private_method',$arg);// HELLO $var = $handler->setScope(A::class)->call('private_method',$arg);// hello // return by reference $var = & $handler->call('private_methodByReference',$arg);// $var = &$arg variables are linked by reference $handler->setScope(null); unset($var,$arg); //or $sucker=new Sucker(new B); $arg='hello'; $var = $sucker->call('private_method','hello');// HELLO $var = $sucker(A::class)->call('private_method','hello');// hello //return by reference $var = & $sucker(A::class)->call('private_method','hello');// hello // arguments by reference $var = & $sucker(A::class)->apply('private_methodByReference',[&$arg]); // $var = &$arg variables are linked by reference unset($var,$arg); //or $proxy=new Proxy(new B); $var = $proxy->private_method('hello');// HELLO $var = $proxy(A::class)->private_method('hello');// hello //return by reference $var = & $proxy(A::class)->private_method('hello');
Sandbox
<?php use Alpa\Tools\Sucker\SuckerObjectHandlers; use Alpa\Tools\Sucker\Sucker; use Alpa\Tools\Sucker\Proxy; $handler=new SuckerObjectHandlers(new B); $arg='hello'; // passing a variable by reference $var = $handler->sandbox(function($arg){ echo self::class===B::class; // $this - object B return $arg; },[$arg]);// hello $var = $handler->setScope(A::class)->sandbox(function($arg){ echo self::class===A::class; // $this - object A return $arg; },[$arg]);// hello //references $var = & $handler->sandbox(function & (&$arg){ return $arg; },[&$arg]);// $var = &$arg variables are linked by reference $handler->setScope(null); unset($var,$arg); //or $sucker=new Sucker(new B); $arg='hello'; $var = $sucker->sandbox(function($arg){ echo self::class===B::class; // $this - object B return $arg; },[$arg]); $var = $sucker(A::class)->setScope(A::class)->sandbox(function($arg){ echo self::class===A::class; // $this - object A return $arg; },[$arg]); // references $var = & $sucker(A::class)->sandbox(function & (&$arg){ return $arg; },[&$arg]); // $var = &$arg variables are linked by reference unset($var,$arg); //or $proxy=new Proxy(new B); $arg='hello'; $var = $proxy(function($arg){ echo self::class===B::class; // $this - object B return $arg; },[$arg]);// hello $var = $proxy(A::class)(function($arg){ echo self::class===A::class; // $this - object A return $arg; },[$arg]);// hello //references $var = & $proxy(function & (&$arg){ return $arg; }); // $var = &$arg variables are linked by reference
alpa/tools_sucker 适用场景与选型建议
alpa/tools_sucker 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 12 次下载、GitHub Stars 达 1, 最近一次更新时间为 2023 年 02 月 17 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 alpa/tools_sucker 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 alpa/tools_sucker 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 12
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 5
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2023-02-17