Can I somehow chain methods in PHP - php

Basically, I am looking for a way I could optimize the following.
Not really a PHP programmer, and in the Ruby world this would be easy, but at the moment I have this:
if(count($methods) == 1) {
$resp = $this->$methods[0];
}
else if(count($methods) > 1) {
$resp = $this->$methods[0]->$methods[1];
}
Is there somehow a way I could loop over the methods array here, and chain them together?
Thanks!

What you want is essentially an array reduction:
$resp = array_reduce($methods, function ($o, $p) { return $o->$p; }, $this);
It's unclear whether you want $o->$p (property access) or $o->$p() (method call), but you can figure that out.

Related

better way to avoid call to a member function

I need to know if there is a better way to avoid Call to a member function xxxx() on null
currently I'm coding as follows but it is cumbersome.
if($event->getForm()
&& $event->getForm()->getParent()
&& $event->getForm()->getParent()->getParent()
&& $event->getForm()->getParent()->getParent()->getData()
&& $event->getForm()->getParent()->getParent()->getData()->getComponente()
){
$componente = $event->getForm()->getParent()->getParent()->getData()->getComponente();
$formModifier($event->getForm(), $componente, $defaultComponente);
}
In PHP 7 this is actually a catchable Error (if you're using hhvm it's a regular Exception):
try {
$componente = $event->getForm()->getParent()->getParent()->getData()->getComponente();
} catch (\Error $e) {
$componente = null;
}
if ($componente !== null) {
$formModifier($event->getForm(), $componente, $defaultComponente);
}
In PHP 5 there is a workaround using intermediate variables and the and keyword instead of &&:
if (
$f = $event->getForm() and
$p = $f->getParent() and
$p2 = $p->getParent() and
$d = $p2->getData() and
$componente = $d->getComponente()
) {
$formModifier($f, $componente, $defaultComponente);
}
If you use && instead of and you'll get "undefined variable" notices and this workaround won't work.
Working examples: https://3v4l.org/0S6ps
no there is no way, but at least you can do some performance improvement
$form = $event->getForm();
if(!$form){
//do error handling
return;
}
$parent = $form->getParent();
if(!$parent){
//do error handling
return;
}
$p_parent = $parent->getParent();
if(!$p_parent){
//do error handling
return;
}
$data = $p_parent->getData();
if(!$data){
//do error handling
return;
}
$component = $data->getComponente();
...
this way you call each function only once and you can do better error handling
I think this is a great example of a bad code. By having a code like this you're breaking several rules and making your life much harder than it should be.
Your code is rigid, fragile, hard to understand and maintain etc.
Simpler is ALWAYS better.
If you can't make your $xx->getComponent() a proper object easily accessible without such ugly nested relationship, you should at least encapsulate the method into something appropriate and use that instead, so if anything changes, you don't have to go full mental and change it all over the place.
This class seems strange in it's creation, but if you are not extracting these methods dynamically using __call(), you can use method_exists() in a loop inside a function, something similar to:
function getMethodChain($class,$arr = ['getForm','getParent','getParent','getData','getComponente'])
{
# First check the object is set
if(!is_object($class))
return false;
# Loop intended method chain
foreach($arr as $method) {
# Check if the method exists in the current class or passed already
$useClass = (!isset($classPass))? $class : $classPass;
# Check if the method exists in the current class
if(is_object($useClass) && method_exists($useClass,$method)) {
# Assign this class/method to use next in the loop
$classPass = $useClass->{$method}();
}
else
return false;
}
# Just send back
return (isset($classPass))? $classPass : false;
}
The use would be something like:
# This will either be the data you expect or false
$componente = getMethodChain($event);

Nice way to add retry functionality to api calls?

I have an api class to contact a REST api for mailing list management. It includes methods such as subscribe(), unsubscribe(), update(), etc.
In my client code, I have lines such as
Api::subscribe($email, array(..));
Because of occasional failures, we want to add retry functionality to each call. If a call fails the first time, we want to retry once or twice more, before we finally give up.
The straight-forward way to do this is
public static function subscribe($email, array $lists ) {
$success = FALSE;
$retries = 3;
while ( ! success && retries > 0 ) {
// API call goes here
$retries--;
}
}
Rinse and repeat for each method.
In the interests of DRY (Don't Repeat Yourself), I was wondering if there was a nice, design-patterny way to wrap my calls in retries without having to repeat the while loop for each method.
If not, and the simple way is the best fit, that's fine. I just wanted to see if there was a better way out there that I was not aware of.
public function retry($apiCall, $retries) {
$success = false;
while (!$success && $retries > 0 ) {
$success |= $apiCall();
$retries--;
}
}
public static function subscribe($email, array $lists) {
retry(function() {
// your API call here
}, 3);
}
You simply construct an anomymous function and pass the anonomous function to the code that handles the retrying. Obviously this should be a bit more elaborate to allow returning values (which can be added quite trivially) or to be observable.
One way to make it observable is by passing a callback:
public function retry($apiCall, $retries, $callback) {
$success = false;
while (!$success && $retries > 0 ) {
$success |= $apiCall();
$retries--;
}
$callback($success);
}
You'd simply need to pass the proper callback that does the notification. You can expand greatly on this by passing more elaborate parameters about the kind of event and kind of failure, number of retries etc. depending on your exact needs.

Benefit of composition functions

I have four methods which alter the input and return the output.
class edit
{
function a($input) { return $input + 4; }
function b($input) { return $input - 2; }
function c($input) { return $input * 10; }
function d($input) { return $input / 8; }
}
Coincidentally these methods need to be called one after the other with the returned output from the previous as the input to the next.
We can handle this process multiple ways.
$handle = new edit();
$output = $handle->a(8);
$output = $handle->b($output);
$output = $handle->c($output);
$output = $handle->d($output);
or
create another method within the class to handle this entire procedure.
function all($input)
{
$output = $this->a($input);
$output = $this->b($output);
$output = $this->c($output);
$output = $this->d($output);
return $output;
}
$handle = new edit(8);
$handle->all();
These both achieve the same task.
However, I have recently learned about composition functions, Which is perfect for I need to achieve.
(note for the example here I have moved the methods a,b,c,d from the class and will call them as functions in a procedural manor, I have been unable to make this composition function OOP friendly, please excuse me for this.)
function compose($f,$g,$h,$i)
{
return function($x) use ($f, $g, $h, $i) { return $f($g($h($i($x)))); };
}
$comp = compose('a', 'b','c','d');
$result = $comp(8);
With all this being said, I want to know the benefit of achieving this task with the composition function?
I can only notice minimal improvement in that we do not have to pass the input four times, only once.
In my recent research, I have come across multiple software engineers talking about how great functional programming is.
I feel that I am missing something? Or is the only improvement what I mentioned?
PS - The language I use is PHP, The methods/functions I gave here are just simple examples to illustrate the point. I am also trying to adhere to SOLID principles.
Thanks.

Best practices to handle JSON data for API SDK

The company I work for has an API and I am porting that API over to PHP. Right now, the API returns to me a large JSON object and I'm trying to figure out how I should handle the data. I could have a whole bunch of "get" methods, like:
$t = new APIThing();
$t->getJSONObjects();
for ($i=0; ...) {
$t->getHeadline($i);
}
Or, I could return the JSON object and let people play with the data themselves, so that would be something like this
$t = new APIThing();
$t->getJSONObjects();
foreach ($t as $u) {
echo $u->headline;
}
So what do you think? Just expose the JSON object or wrap the whole thing up into functions?
instead of that you can have a class that gets anything from the JSON
class GETAPI {
protected $api;
function __construct(){
$this->api = new APIThing();
$this->api->getJSONObjects();
}
function getAllFromAPI($name){
foreach($this->api as $u){
echo $u->$name;
}
}
//or :
function getFromAPI($name, $index){
return $this->api[$index]->$name;
}
}
its rudimentary and could use some work, but that work over making many many get functions
than all you would have to do is something like:
$api = new GETAPI();
$api->getAllFromAPI('headline');
//or
echo $api->getFromAPI('headline', 1); // with one as the array index

How to handle REQUEST in PHP

is there a class to handle $_REQUEST that makes the life of a php developer easier?
I want to handle the client requests easier.
I dont want to test with if(is_set($_REQUEST['blabla'])) {makesomthing();}
I wish there could be a solution like this.
class rpclike
{
public function getMember()
{
$memberid = $this->inputhandler['memberid'];
$member = $this->memberclass->getmember($memberid);
foreach($member as $mem)
{
echo $mem->id;
}
}
}
$rpc = new rpclike();
then if i call the rpclike from a javascript like this
Get member
Which class can do something like that?
It's not recommended that you use $_REQUEST as it poses security concerns. You should be using one of $_GET, $_POST, or $_COOKIE depending on what global request var you are trying to retrieve. Your best bet would be to have something like the following:
class input {
public static function get($key, $value = false) {
return (!empty($_GET[$key])) ? $_GET[$key] : $value;
}
public static function post($key, $value = false) {
return (!empty($_POST[$key])) ? $_POST[$key] : $value;
}
public static function cookie($key, $value = false) {
return (!empty($_COOKIE[$key])) ? $_COOKIE[$key] : $value;
}
}
You could then use the class like:
if (input::post('field', null) != null) {
}
or
if (input::get('field', false) != false) {
}
Although this still requires testing, you can explicitly set the return values in the event no data was set for the global variable.
PHP doesn't really have a default class structure that you can utilize in that kind of manner, as it's origins are in procedural-based programming.
It would be fairly trivial for you to create a class like that if you felt the need for it. However, you would really just be adding overhead. If the convenience of it is worth it for you, then you could utilize the __get() and __set() methods to handle existence checks for you.
The fact that you want to use this for handling client requests in an easier fashion is probably a good indicator that you should move to something like an MVC framework, which usually handle URLs and route them to appropriate methods for you automatically. Most PHP frameworks will do this for you already. For a nice overview on how the process commonly works, you could see how CodeIgniter does it.
Aside from the obvious security risks involved in this, it is feasible. It's a common pattern to use for steering requests in an MVC system.
Say you request index.php?class=User&method=ViewProfile
$module = new $_GET['class']();
if(!method_exists($module,$_GET['method']))
$module->$eventName();
I don't think so. Being able to invoke an arbitrary method would be a massive security hole.
Do something like:
url: /foo/bar?req=getMembers&memberid=22
Then you can do:
$request = $_GET['req'];
$request();
Slightly less dangerous version:
$req_methods = array(
getMembers => 'some_function',
saveMembers => 'another_function',
sendMessage => 'send_him_an_email'
);
$request = $_GET['req'];
$req_methods[$request]();

Categories