PHP - Pass named function to another function - php

I have a function collectRows that accepts a sqli_result object, and returns the query results as a array of rows:
function collectRows($result) {
...
}
and have another function that accepts a function to decide what to do with the query results before returning them:
function execQuery($query, $resultsF=null) {
...
}
I want to use execQuery like so:
execQuery("SELECT * FROM...", collectRows);
But I get complaints that it can't find the constant "collectRows".
Obviously, I could do something like:
execQuery("SELECT * FROM...", function($result) {
return collectRows($result);
});
But it would be nice to be able to write it a more succinctly.
Is there a way to pass a named function without wrapping it in an anonymous function?

Function name instead of function itself should be passed to a function:
function execQuery($query, $functionName=null) {
if (is_callable($functionName)) {
$functionName();
}
}
And call it:
execQuery("SELECT * FROM...", 'collectRows');
More info about callable type.

Quite simply, you only have to pass the name as a string. PHP doesn't care, it'll deal with it anyway.

Related

How to receive specific interface's array in PHP class method?

I want to receive array of MyInterface as the in the below code.
public function saveMultiple(
\Path\To\MyInterface $attachLinks[]
);
The above code doesn't work.
So please don't tell me that just remove \Path\To\MyInterface and to use a variable $attachLinks. I'm already aware of that but this is something which I require.
There are no generic types in php, so you can not specify type «array of something».
But you may do a trick. Check types of elements in array.
array_walk($attachLinks, function (\Path\To\MyInterface $item) {});
If you wrap it in assert, you will be able to disable this check.
assert('array_walk($attachLinks, function (\Path\To\MyInterface $item) {})');
So far this is what can be done using PHP7. Till date passing arrays with specific type is not possible.
public function saveMultiple(
array $attachLinks
);
It'll now at least make sure that the method only gets array as parameter.
Maybe you can use some type of setter like:
private $attachLinks = [];
public function setter(MyInterface $var)
{
$this->attachLinks[] = $var;
}
And than use a $this->attachLinks in your function
public function saveMultiple() {
print_r($this->attachLinks);
}

Laravel paginate() on custom static functions

I want to paginate a custom static function.
When using Eloquent goes like this People::paginate(5); and paginates the results.
I need to do the same for this static function People::getOwners();
Just do your query and pagination in the function, like this:
public function getOwners() {
return self::query()->paginate(5);
}
Depending on what is going on inside getOwners(), you could turn it into a query scope. On your People model, add the function:
public function scopeGetOwners($query) {
// $query->where(...);
// $query->orderBy(...);
// etc.
$return $query;
}
Now, getOwners() is treated like any other query scope modifier (e.g. where, orderBy, etc.):
People::getOwners()->paginate(5);

How to do hasKeys() in PHP Mockery, or create custom parameter expectations?

Mockery has a method hasKey(), which checks if a given parameter has a certain key. I want to make sure that the passed array has multiple keys. I would also like to assert that the array has x amount of elements.
Is there a built-in way to allow for custom parameter expectations? I tried using a closure that returns true or false based on the given parameter, but that didn't work.
Thanks.
Edit:
Example
$obj = m::mock('MyClass');
$obj->shouldReceive('method')->once()->with(m::hasKey('mykeyname'));
What I'm trying to do is to have more insight into what is passed to the method using with(). I want to assert that an array passed to a method has both key a AND key b. It would be great if I could use a closure somehow to create my own assertion, such as counting the number of array elements.
You can user a custom matcher.
Out of the top of my head (not tested) this could look something like this:
class HasKeysMatcher extends \Mockery\Matcher\MatcherAbstract
{
protected $expectedNumberOfElements;
public function __construct($expectedKeys, $expectedNumberOfElements)
{
parent::__construct($expectedKeys);
$this->expectedNumberOfElements =$expectedNumberOfElements;
}
public function match(&$actual)
{
foreach($this->_expected as $expectedKey){
if (!array_key_exists($expectedKey, $actual)){
return false;
}
}
return $this->expectedNumberOfElements==count($actual);
}
/**
* Return a string representation of this Matcher
*
* #return string
*/
public function __toString()
{
return '<HasKeys>';
}
}
and then use it like this:
$obj = m::mock('MyClass');
$obj->shouldReceive('method')->once()->with(new HasKeysMatcher(array('key1','key2'),5));

Passing function as an argument of another function in PHP

I want to pass function (not the result) as an argument of another function. Let's say I have
function double_fn($fn)
and i want to run given function ($fn) two times. Is there such mechanism in PHP? I know you in python function is a kind of variable but is PHP similar?
#edit
is there similar way to use methods?
function double_fn(parrot::sing())
Since 5.3 (note) you do this with closures quite naturally:
function double_fn(callable $fn)
{
$fn();
$fn();
}
double_fn(function() {
echo "hi";
});
(note) type hint only since 5.4
The callable type can be a few things:
a string comprising the function name to call,
a closure (as above)
an array comprising class (or instance) and method to call
Examples of the above is explained in the manual.
Update
edit is there similar way to use methods?
function double_fn(parrot::sing())
Doing that will pass the result of parrot::sing() into the function; to pass a "reference" to the static method you would need to use either:
double_fn('parrot::sing');
double_fn(['parrot', 'sing']);
It's... a bit different. Pass the function name as a string.
function foo()
{
echo "foobar\n";
}
function double_fn($fn)
{
$fn();
$fn();
}
double_fn('foo');
You can use anonymous functions introduced in PHP 5.3.0:
function double_fn($fn) {
$fn();
}
double_fn(function(){
// fonction body
});
or:
$myFn = function(){
// fonction body
};
double_fn($myFn);

Get number of parameters a function requires

This is an extension question of PHP pass in $this to function outside class
And I believe this is what I'm looking for but it's in python not php: Programmatically determining amount of parameters a function requires - Python
Let's say I have a function like this:
function client_func($cls, $arg){ }
and when I'm ready to call this function I might do something like this in pseudo code:
if function's first parameter equals '$cls', then call client_func(instanceof class, $arg)
else call client_func($arg)
So basically, is there a way to lookahead to a function and see what parameter values are required before calling the function?
I guess this would be like debug_backtrace(), but the other way around.
func_get_args() can only be called from within a function which doesn't help me here.
Any thoughts?
Use Reflection, especially ReflectionFunction in your case.
$fct = new ReflectionFunction('client_func');
echo $fct->getNumberOfRequiredParameters();
As far as I can see you will find getParameters() useful too
Only way is with reflection by going to http://us3.php.net/manual/en/book.reflection.php
class foo {
function bar ($arg1, $arg2) {
// ...
}
}
$method = new ReflectionMethod('foo', 'bar');
$num = $method->getNumberOfParameters();

Categories