Load functions dynamically into class from external file - php

Is it possible in php to load a function, say from a external file to include in a class.
I'm trying to create a loader for helper functions so that I could call:
$registry->helper->load('external_helper_function_file');
after that it should be able call the function in file like this:
$registry->helper->function();
Thanks for any help

Setting aside opinions it it's good OOP design. It's possible even with current version of PHP, although not as clean, as it can be with PHP5.3.
class Helper {
/* ... */
function load($file) {
include_once($file);
}
function __call($functionName, $args) {
if(function_exists($functionName))
return call_user_func_array($functionName, $args);
}
}

ok, 1st, i agree that this is bad manners. also, in 5.3, you could use the new closure syntax with the __call magic word to use operators as functions (JS style).
now, if we want to supply a way of doing this you way, i can think of using create_fnuction, mixed with the __call magic.
basically, you use a regex pattern to get convert the functions into compatible strings, and put themin a private member. than you use the __call method to fetch them. i'm working on a small demo.
ok, here is the class. i got the inspiration from a class i saw a few weeks ago that used closures to implement JS-style objects:
/**
* supplies an interface with which you can load external functions into an existing object
*
* the functions supplied to this class will recive the classes referance as a first argument, and as
* a second argument they will recive an array of supplied arguments.
*
* #author arieh glazer <arieh.glazer#gmail.com>
* #license MIT like
*/
class Function_Loader{
/**
* #param array holder of genarated functions
* #access protected
*/
protected $_funcs = array();
/**
* loads functions for an external file into the object
*
* a note- the file must not contain php tags.
*
* #param string $source a file's loaction
*
* #access public
*/
public function load($source){
$ptrn = '/function[\s]+([a-zA-Z0-9_-]*)[\s]*\((.*)\)[\s]*{([\w\s\D]+)}[\s]*/iU';
$source = file_get_contents($source);
preg_match_all($ptrn,$source,$matches);
$names = $matches[1];
$vars = $matches[2];
$funcs = $matches[3];
for ($i=0,$l=count($names);$i<$l;$i++){
$this->_funcs[$names[$i]] = create_function($vars[$i],$funcs[$i]);
}
}
public function __call($name,$args){
if (isset($this->_funcs[$name])) $this->_funcs[$name]($this,$args);
else throw new Exception("No Such Method $name");
}
}
limitations- 1st, the source cannot have any php tags. 2nd, functions will always be public. 3rd- we can only mimic $this. what i did was to pass as a 1st argument $this, and the second is the array of arguments (which is a 4th limition). also, you will not be able to access non-public members and methods from within the class.
an example for a source file:
function a($self,$arr=array()){
//assuming the object has a member called str
echo $self->str;
}
this was a fun exercise for me, but a bad practice all in all

So you want to not just include a file, but include it into an object's scope?
...
I think you're going about this the wrong way. It makes more sense if the registry object has a series of helper members, which have functions of their own. The net result might look something like this:
$registry->aHelper->aFunction();
$registry->aDifferentHelper->aDifferentFunction();
With careful use of {} syntax, you should be able to dynamically add member objects to your god object.
At this point it's worth noting that a god object is almost invariable an anti-pattern. If you need those functions globally, use a bootstrapping include technique and put then in global scope. If you need to pass that data around, then either pass it to functions as required or store it in a database and retrieve it elsewhere.
I know that god object really looks like a good idea, but I promise you it will make things a mess later on.

Related

Is there an array-to-callable function?

Setting
Within SomeClass there is f2member taking two integer arguments and producing its sum. The test passes showing that the call actualy works and retrieves the expected result. Which is calling $gwith two parameters 1 and 1 returning 2.
Important: This works only for php 5.4.11 and upwards compatibility check
class SomeClass extends PHPUnit_Framework_TestCase
{
function f2member($a,$b)
{
return $a + $b;
}
/**
* #test
*/
public function test()
{
$g = array($this,'f2member');
$this->assertEquals(2, $g(1,1)); // squiggle line under $g
}
}
Problem
However, this produces a warning inside phpStorm on every method invocation and a squiggle line under $g:
Function name must be callable - string, Closure or class implementing __invoke, currently array
The origin of the warning is clear to me and now i am looking for ways to avoid these warnings.
A requirement is, that i dont want to change the style of calling the function. Another thing i don't want to do is to deactivate this warning.
I would rather prefer to wrap something around it, which provides the necessary information to the type system.
Attempt
I already encountered several solutions to remove the warnings. One is to define a user defined function, which only documents the required target type.
/**
* #param array $arr
*
* #return callable
*/
function callable_for($arr)
{
return $arr;
}
This returns an array, but also explicitly tells the type system what comes out of the callable_for function. With this type annotation in place phpStorm now stops complaining about this warning, although it still returns an array.
$g = callable_for(array($this,'f2member'));
Question
Isn't there something out of the box like my callable_for in php to achieve this? If the answer is no, then
i am looking for the most concise solution we can find.
I already tried looking on SO, php.net and google. Maybe, I just searched for the wrong word combinations, here are just two samples:
array to callable php
create callable method handle php
BigPicture
Just in case suspects arise this is a X/Y problem: I have another function taking a callable as a parameter. With closures it is very natural to define something, which can be invoked later on. However, how do i define a callable for a member or a static method without wrapping it in another delegation Closure? The array notation allows to be used to uniformly pass: closures or static/member method handles to my later function. I am now trying to find a concise solution to this, which comes close to this.
Thus, another advancement could be, to modify callable_for to take two arguments and wrap both responsibilities; to create the array and to document the target return type.
/**
* #param mixed $context
* #param string $method
*
* #return callable
*/
function callable_for($context, $method)
{
return array($context, $method);
}
Using this implementation raises the conciseness of $g's declaration to an acceptable level.
$g = callable_for($this,'f2member');
This function still returns an array, but the type system can use the given information to correctly treat this array for dynamic method invocation.
The question was asked four years ago but after some research I found the Closure::fromCallable method: https://www.php.net/manual/de/closure.fromcallable.php

PHP Private Static Function

I am a junior PHP programmer. I still have a lot to learn. That's why I ask this question. In a class you have a public function which you can call it from outside that class. Sometimes you have a private function which you can call several times in that class where the private function resides, for reusable purpose. I like to set the private function to static and I call that function with:
self::privateFunctionName();
By using self it reminds me that this private function resides in that class. if I use $this->privateFunctionName() for non-static function, it could be in the superclass/base class or in that subclass itself. That is why I like to use static private function. In a professional point of view, is it a good idea to use static private function instead of non-static? Is there any disadvantage that a professional programmer like you prefers to avoid the static function?
Only using self::... must not mean the method is static. parent:: and self:: work as well for non-static methods. You can find this in the PHP manual - Scope Resolution Operator (::) and I add some exemplary code excerpt at the end of the answer.
You perhaps might want to read through all answers of this earlier question:
When to use self over $this?
In total you will get there more details then my short description in this answer.
You might have been confused by the scope-resolution-operator :: which is used by those. I had a similar understanding problem grasping that.
However, do not just choose to use static methods for such a limited reason. Those static class methods should only be used in very limited and narrowed situations. As a rule of thumb:
"Do not use static class methods."
If you like to start with object oriented programming, just use normal object methods.
Here is an excerpt from existing code that shows that self:: as well as parent:: are used with standard (non-static) methods:
<?php
...
/**
* Class XMLElementIterator
*
* Iterate over XMLReader element nodes
*/
class XMLElementIterator extends XMLReaderIterator
{
private $index;
private $name;
private $didRewind;
/**
* #param XMLReader $reader
* #param null|string $name element name, leave empty or use '*' for all elements
*/
public function __construct(XMLReader $reader, $name = null)
{
parent::__construct($reader);
$this->setName($name);
}
/**
* #return void
*/
public function rewind()
{
parent::rewind();
$this->ensureCurrentElementState();
$this->didRewind = true;
$this->index = 0;
}
/**
* #return XMLReaderNode|null
*/
public function current()
{
$this->didRewind || self::rewind();
$this->ensureCurrentElementState();
return self::valid() ? new XMLReaderNode($this->reader) : null;
}
...
self:: does not in fact mean that the method is part of the same class, it may as well have been inherited from a parent class!
You should not use the semantics of static method calls to differentiate "internal" and "external" methods. There's no real point to it anyway, and you're just abusing language features for something they weren't meant for. Maybe let that be a primary lesson: don't try to invent clever new ways of using language features. Just don't.
You should view methods as small, self contained black boxes. You don't need to know and don't want to know what they do. All you know is that when you call method foo with parameter $bar, x will happen or it will return y. You don't care how this happens, just that it does because that's what the method is supposed to do.
As such, static and non-static methods convey a different use with different limitations. static methods are supposed to be called when you don't have an object, for example as alternative constructor methods (e.g. DateTime::createFromFormat).
Further, restricting a method to being static means it has no access to object instance data, which may limit you in the future. As your project evolves, you may find that your method now needs to take into account some additional data from the object to do its job. If you declared it as non-static from the beginning, all it takes is a little modification to the method itself; to the outside world it still does its job the same way (input → output). However, if you declared it as static and suddenly find yourself needing to make it non-static, you have to change a lot more code than just that one method.
Bottom line: if your method is not supposed to be exposed publicly because it's nobody's business to call it except for your own class, make it private. If the method needs to be static because it must work without object context, make it static. If it fulfils both requirements, make it private static. Otherwise, don't.
Well basically a "private static" function is a construct which is totally nonsense because it cannot be called from the outside.
There is no real difference between $this-> and using self:: expect the fact that it can be called from the outside without a object and its the same amount of work for the CPU to call the function, no matter in what namespace/class this function is located.
However the fact that a private function can only be called within the same class you always have an object and the "static" modifier is somewhat superflous here because it makes no difference.
In this cases I always like to say: do what you like its just a matter of your personal style but dont switch arround, keep it that way to develop and use the standard you feel comfortable with.
In some cases there is just "another" way and a "professional" way does not exist at all.
The trend often makes the one or the other method to become popular over time.

Is it a better practice to inject all variables in the constructor or to use setters and throw exceptions if they are not set?

Imagine you have this class
class Ai1ec_Less_Parser_Controller {
/**
* #var Ai1ec_Read_Variables_Startegy
*/
private $read_variable_strategy;
/**
* #var Ai1ec_Save_Variables_Strategy
*/
private $write_variable_strategy;
/**
* #var Ai1ec_Less_Variables_Collection
*/
private $less_variables_collection;
/**
* #var Ai1ec_Less_Parser
*/
private $ai1ec_less_parser;
/**
* We set the private variables in the constructor. I feel that there are too many parameters.
* Should i use setter instead and throw an exception if something is not set?
*
* #param Ai1ec_Read_Variables_Startegy $read_variable_strategy
* #param Ai1ec_Save_Variables_Strategy $write_variable_strategy
* #param Ai1ec_Less_Variables_Collection $less_variables_collection
* #param Ai1ec_Less_Parser $ai1ec_less_parser
*/
public function __construct( Ai1ec_Read_Variables_Startegy $read_variable_strategy,
Ai1ec_Save_Variables_Strategy $write_variable_strategy,
Ai1ec_Less_Variables_Collection $less_variables_collection,
Ai1ec_Less_Parser $ai1ec_less_parser ) {
}
}
I need those variables to be set and so i set them in the constructor ( but that look like too many parameters ). Another option would be to use setters to set them and then in a method throw an exception if one of the required variables is not set like this
public function do_something_with_parser_and_read_strategy() {
if( $this->are_paser_and_read_strategy_set === false ) {
throw new Exception( "You must set them!" );
}
}
private function are_paser_and_read_strategy_set () {
return isset( $this->read_variable_strategy ) && isset( $this->ai1ec_less_parser );
}
Do you think that one of the two methods is better?And why?
Is your class immutable? If so, then having 100% member population via the constructor is often the best way to do it, but I'll agree it can start to look ugly if you have more than a 5 or 6 parameters.
If your class is mutable then there's no benefit from having a constructor with required parameters. Expose the members via accessor/mutator methods (aka properties).
The factory pattern (as suggested by #Ray) can help, but only if you have a variety of similar classes - for a one-off then you can simply use static methods to instantiate the object, but you'll still have the "too many parameters" problem.
The final alternative is to accept an object with fields (one field for each parameter), but use this technique carefully - if some values are optional then just use method overloading (which unfortunately PHP doesn't support).
I'd just stick with what you're doing and only change it for something else if it presents a problem.
Class naming Controller somehow reflects MVC, or in general - any mechanism responsible for processing sequence.
Data object classes tend to have many fields in any case - it is their responsibility.
Regular object relying on many other objects could be possibly missing a point.
There are four objects, as I see: read, save, parse and provide collection interface to something.
Why shall one have different interfaces for reading and writing? Could this not be combined into one?
Parser shall be a library on itself, thus there may be no reason to combine it anywhere, although it could possible use readers/writers for itself, and, in return, provide collection. Thus could it be possible that parser would take an argument of reader and return a collection object?
That is more about specific case.
In general - having many arguments to the method (or initializing many fields within an object by other objects of different domains) indicates some sort of design flaw.
Kind of on-topic might be this article on Constructor Initialization - it advises to use in-constructor initialization. Just be sure to follow up to the point:
What if there's a lot of collaborators to provide in the constructor? A large list of construction parameters, like any large
parameter list, is a CodeSmell.
And as Ray has written - there is a possibility to initialize using setters, and there is article on that too. To the extent of my view - I think that Martin Fowler really summarizes these cases pretty well.
There is no "better" way. But here are few things you have to consider:
constructors are not inherited
if class requires too many objects, it is responsible for too much
This might have impact on your choice of what sort of interface your class implements.
The general rule of thumb would be this:
If parameters are mandatory for class to function, they should be injected through constructor.
The exception would be, if you initialize the instance by using a factory. It is quite common for factory to build instance form diverse classes, where some of them implement same interface and/or extend same parent class. Then it is easier to inject shared objects through setters.
Creating your objects using factories that call setters instead of using a constuctor of a set number of parameters is much more flexible. Check out the builder and factory patterns.
Throwing exceptions for accessing not fully built objects is good!
Any function that has over 2 (sometimes 3) arguments, I always pass an array, so it would look like:
public function __construct(array $options = array()) {
// Figure out which ones you truly need
if ((!isset($options['arg1'])) || (mb_strlen($options['arg1']) < 1)) {
throw new Exception(sprintf('Invalid $options[arg1]: %s', serialize($options)));
}
// Optional would look like
$this->member2 = (isset($options['arg1'])) && ((int) $options['arg2'] > 0)) ? $options['arg2'] : null;
// Localize required params (already validated above)
$this->member1 = $options['arg1'];
}
Passing an array of options allows for future growth without having to change the function signature. However it does have it's drawback in that the function must localize all elements of the array to ensure access doesn't throw warnings / errors (if an element is missing from the array).
The factory solution is in this case is not a good choice, because you are still left with the problem of passing the values to the factory so it can initialize the object with the correct values.
The standard solution to "too many constructor arguments" is the builder pattern. Your controller class itself will still have a long constructor, but clients can use setters on the builder, which in turn will later call the long constructor.
If you only construct your controller object in one or two places, it wouldn't even be worth all the trouble to create a builder; in that case, just stick with your current code.

so how does passing by reference in php REALLY work?

Really simple question but rather than asking for an academic explanation I want to keep it as pragmatic as possible: when will PHP create a copy of my huge class I'm passing into a function and when will it simply create a pointer to the relevant data? And if it creates pointers all the time, what's the use of specifying & (aside from closures, obviously)? I guess I don't know enough about the guts of the interpreter.
In PHP 5, all objects are passed by their handle. Whether you pass by reference or not is irrelevant in terms of performance. (In fact, passing by reference is warned to be slower in the manual.) The object you are working on inside the function is the same object as pointed to outside the function.
When you pass an object (handle) by reference, then you can alter what the outer variable points to. This is almost always unnecessary.
The & operator denotes a variable as being passed by reference.
$x = 'Hello World';
echo($x);
function asdf(&$var){
$var = 'Test';
}
asdf($x);
echo($x);
Same goes for assignment and pretty much any other statement. If it isn't passed or assigned by reference, assume it is passed or assigned by value instead.
Why bother with &, even though you can do so as please. This is how I do:
Assume I have a class 'Book' with some public methods and properties like title, author, year
then to make an object of it simply:
$book = new Book()
// then I can use all public methods and properties
$book->title;
$book->author;
$book->year;
If I like to then I can make a subclass say
class Novel extends Books{
function buildIt(Book $bk){
$bk->title;
// so on
}
}
In the function buildIt, I purposedly have an class object of Book 'parameter' in which
I can pass the whole object of class 'Book'.
I hope this help.
You can find a lot of uses of passing a variable by reference in the PHP manual. One of the best examples is preg_match.
preg_match will return the number of occurrences a pattern has been matched in the input string. It will then populate, if provided, a referenced $matches array containing the matches.
It can be seen as a way to return more than one value, although you ought to be careful with that. Per example:
class Server {
protected $_clientId = 0;
protected $_clients = array();
/**
* Get a pending connection.
*
* #param &$connection_id int The connection identifier.
* #return resource The socket resource.
*/
public function getNextClient(&$connection_id) {
$clientSocket = socket_accept($this->_server);
$connection_id = $this->_clientId++;
$this->_clients[$connection_id] = $clientSocket;
return $clientSocket;
}
}
$server = new Server;
$socket1 = $server->getNextClient($id);
echo $id; // 0
$socket2 = $server->getNextClient($id);
echo $id; // 1
Important note. Objects are passed-by-reference by default. They will not be cloned. Even without specifying the & in the function argument, modifying the passed object will result in the original object being modified as well. The only way to prevent this is to clone the object in the function/method.

PHP OOP: Unique method per argument type?

I'm writing a little homebrew ORM (academic interest). I'm trying to adhere to the TDD concept as a training exercise, and as part of that exercise I'm writing documentation for the API as I develop the class.
Case in point - I'm working on a classic "getCollection" type mapper class. I want it to be able to retrieve collections of asset X (let's say blog posts) for a specific user, and also collections based on an arbitrary array of numeric values. So - you might have a method like any one of these
$User = $UserMapper->load(1);
$ArticleCollection = $ArticleMapper->getCollection(range(10,20));
$ArticleCollection = $ArticleMapper->getCollection($User);
$ArticleCollection = $ArticleMapper->getCollection($User->getId());
So, in writing the documentation for the getCollection method - I want to declare the #param variable in the Docblock. Is it better to have a unique method for each argument type, or is it acceptable to have a method that delegates to the correct internal method/class based on argument type?
It is acceptable to have a method that delegates to the correct internal method. You could document it like this:
#param Array|User|Integer $argName optional explanation
but then again, there is no one hindering you having one method each
public function getCollectionByRange(array $range)
public function getCollectionByUser(User $user)
public function getCollectionByUserId($id)
In addition, you could use the magic __call method to pretend the above methods exist and then capture method calls to them and delegate to your internal methods (ZF does that f.i. for finding dependant database rows). You would document these methods with the #method annotation in the Class DocBlock. But keep in mind that the magic methods are always slower over having and/or calling the appropriate methods directly.
Use what you think makes most sense for your application and usecase.
You could achieve something like method overloading by checking the type of the passed parameter at runtime (PHP does not support this concept known from other languages like ADA, Java, C# or C++ e.g.):
[...]
/**
* #param User|array|integer $user
* #return array
*/
public function getCollection($user) {
// perhaps a switch-case would be better here
if ($user instanceof User) {
// do what has to be done if you passed in a User object
} else if (is_int($user) {
// do what has to be done if you passed in a user id
} else if (is_array($user)) {
// do what has to be done if you passed in an array of user ids
}
}
[...]
It sounds like you want to do function overloading, but PHP (even PHP5) does not do overloading like you would in, say Java. The Overloading section in the PHP manual is not function overloading:
Note: PHP's interpretation of
"overloading" is different than most
object oriented languages. Overloading
traditionally provides the ability to
have multiple methods with the same
name but different quantities and
types of arguments.
You might mean this:
class ArticleMapper {
public function getCollection($param) {
if (is_array($param)) { $this->getCollectionByArray($param); }
if (is_int($param)) { $this->getCollectionByInt($param); }
if (is_a($param, 'User')) { $this->getCollectionByUser($param); }
}
private function getCollectionByArray(array $param) { ... }
private function getCollectionByInt($param) { ... }
private function getCollectionByUser(User $param) { ... }
}
This seems like the a good way to do it to my eye.

Categories