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.
Related
I have found no information about this in the documentation, but it seems logical to exist. How to make a type hinting for a returning a value of object type? (I'm talking about any object, not a certain object of for instance \DateTime etc.)
function getParticipant(): ?object
{
//...
$x = new Cat();
return $x;
}
It is not working and what is really unfair is that print getType($x) will result in object. So we have an object type but can't say strictly that we will return an object?
You may say that it is really not necessary and I could have just written : Cat, but that's not what I need when I overwrite a method which has got * #return object|null */ in his PHPDoc.
Type-hinting for a generic object doesn't yet exist in PHP, but should be available from version 7.2.0 onwards as a result of RFC Object typehint which passed by 32 votes to 3 on 31st May 2017.
Although normally (where possible) it is still better to type-hint to a specific class or interface.
:object does not resolve for variables which have this type. In fact, PHP will look for class named object and expect that instance of this class will be returned.
Using your example you should indicate that function will return an instance of Cat so it should look like this:
function getParticipant(): Cat
{
return new Cat();
}
I'd say that it's fine that PHPDoc says that object will be returned. IDE's should resolve it and for PHP interpreter it doesn't matter.
In case you're overwriting method you can simply overwrite #return statement in PHPDoc.
I can't find an exact explanation but at the moment you can return Classes, scalar values and since PHP 7.1 you have void as return value. But in your case "object" as return value doesn't exist.
And in my eyes it make a lot more sense to check which object you return to be clear that you return the correct object. So in your case:
function getParticipant(): Cat
{
//...
$x = new Cat();
return $x;
}
Then you can be sure that your function return the object you expect.
This may be a basic question, but it has kept me wondering for quite some time now.
Should I declare all private/local variables being private? Or is this only necessary for "important" variables?
For instance, I have the (temporary) result of a calculation. Should I pre-declare this variable?
Hope someone can point this out.
Since you're talking about private, protected and public I take it you're talking about properties, instead of variables.
In that case: yes, you should declare them beforehand.
Because of how PHP objects are designed, an array (properties_table) is created on compile time. This array ensures that accessing a given property is as fast as possible. However, if you add properties as you go along, PHP needs to keep track of this, too. For that reason, an object has a simple properties table, too.
Whereas the first (properties_table) is an array of pointers, the latter is a simple key => value table.
So what? Well, because the properties_table contains only pointers (which are of a fixed size), they're stored in a simple array, and the pointers are fetched using their respective offsets. The offsets are stored in yet another HashTable, which is the ce->properties_info pointer.
As bwoebi pointed out to me in the comments: getting the offset (HashTable lookup) is a worst-case linear operation (O(n)) and predefined property lookups are constant-time complex operations (O(1)). Dynamic properties, on the other hand need another HashTable lookup, a worst-case linear operation (O(n)). Which means that, accessing a dynamic property takes in average about twice as long. Authors of the Wikipedia can explain Time-Complexity far better than I can, though.
At first, access modifiers might seem irrelevant. As you go along, you'll soon find that sometimes, you just don't want to take the chance that some property of some object gets modified by some bit of code. That's when you see the value of private.
If an object contains another object, that holds all sorts of settings that your code will rely upon, for example, you'll probably use a getter method to access those settings from the outside, but you'll leave that actual property tucked away nicely using private.
If, further down the line, you're going to add data models and a service layer to your project, there's a good change you'll write an (abstract) parent class, if only for type-hinting.
If those service instances contain something like a config property, you'll probably define that getter in the parent class (to only define it once). private means that only the current class has access to a property, but since you're not going to have an instance of the parent to work with, but an instance of the child, you'll see why protected is invaluable when dealing with larger projects, too.
As far as temporary variables are concerned, be it in methods, functions or anywhere else, you don't have to predeclare them, except for, in certain cases arrays:
public function foo()
{
$temp = $this->getSomeValue();
return $temp ? $temp +1 : null;
}
Is perfectly valid, and wouldn't work any better if you were to write
public function foo()
{
$temp;// or $temp = null;
$temp = $this->getSomeValue();
return $temp ? $temp +1 : null;
}
However, it's not uncommon to see simething like this:
public function bar($length = 1)
{
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
This code relies on PHP being kind enough to create an array, and assign it to $return when the $return[] = rand(); statement is reached. PHP will do so, but setting your ini to E_STRICT | E_ALL will reveal that it doesn't do so without complaining about it. When passing 0 to the method, the array won't be created, and PHP will also complain when it reaches the return $return; statement: undeclared variable. Not only is it messy, it's also slowing you down! You're better off declaring $return as an array at the top of the scope:
public function bar($length = 1)
{
$return = array();//that's it
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
To be on the safe side, I'd also check the argument type:
/**
* construct an array with random values
* #param int $length = 1
* #return array
**/
public function bar($length = 1)
{
$length = (int) ((int) $length > 0 ? $length : 1);//make length > 0
$return = array();
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
In most if not all cases: yes.
If the variables are class properties they absolutely should be declared before use.
If the variable is local to a function, declare it in that function before you use it. Function variables are confined to the function's scope (local variables). They don't have to be declared before use but it's good practice to do so, and it gets rid of a warning message if you do. If they are not used anywhere else, they should not be properties though,
If you are using it in the context of the whole class, then yes, you should define your variable as a member of the class.
However, if you are talking about a local variable within the context of a single function and the variable does not need to be used elsewhere (or is not returned), then no.
Essentially you need to determine the importance and scope of your variable before deciding whether to make it a class property or not.
For example:
<?php
class Test {
private $test; // Private property, for use in the class only
public $public_test; // Public Property, for use both internally and external to the class as a whole
public function testing() {
$local = 5; // Local variable, not needed outside of this function ever
$this->test = rand(1, 5);
$calc = $local * $this->test; // Local variable, not needed outside of this function ever
$this->public_test = $calc / 2; // The only thing that the whole class, or public use cares about, is the result of the calculation divided by 2
}
}
It's generally a good rule of thumb for variables to define and initialize them before use. That includes not only definition and initial value but also validation and filtering of input values so that all pre-conditions a chunk of code is based on are established before the concrete processing of the data those variables contain.
Same naturally applies to object members (properties) as those are the variables of the whole object. So they should be defined in the class already (by default their value is NULL in PHP). Dynamic values / filtering can be done in the constructor and/or setter methods.
The rule for visibility is similar to any rule in code: as little as necessary (the easy rule that is so hard to achieve). So keep things local, then private - depending if it's a function variable or an object property.
And perhaps keep in the back of your mind that in PHP you can access private properties from within the same class - not only the same object. This can be useful to know because it allows you to keep things private a little bit longer.
For instance, I have the (temporary) result of a calculation. Should I pre-declare this variable?
This is normally a local variable in a function or method. It's defined when it receives the return value of the calculation method. So there is no need to pre-declare it (per-se).
...
function hasCalculation() {
$temp = $this->calculate();
return (bool) $temp;
}
...
If the calculation is/was expensive it may make sense to store (cache) the value. That works easily when you encapsulate that, for example within an object. In that case you'll use a private property to store that value once calculated.
Take these rule with a grain of salt, they are for general orientation, you can easily modify from that, so this is open to extend, so a good way to keep things flexible.
I want to create a function such that if it is called the first time, it behaves differently and for rest of the time it behaves differently. Now to do this I know I can use a "state" variable. Some other techniques were also given here:
Check if function has been called yet
However I somehow got a hint from a colleague that debug_backtrace() can be used to solve this problem. I read about it but cannot understand how ? This function gives a stack trace of the function call. How can this tell if the function has been called first time or not ?
The exact code that baffles me is here:
/**
* Holds the states of first timers
* #var array
*/
private static $firstTimeCSS=array();
private static $firstTimeJS=array();
/**
* Tells whether it is the first time this function is called on
* ANY CLASS object or not. Useful for one-time scripts and styles
*
* #param string $class name optional. Usually you should send __CLASS__ to this, otherwise the instance ($this) class would be used.
* #return boolean
*/
final protected function IsFirstTime($class=null)
{
$t=debug_backtrace();
if ($t[1]['function']=="JS")
$arr=&self::$firstTimeJS;
else
$arr=&self::$firstTimeCSS;
if ($class===null)
$class=$this->Class;
if (isset($arr[$class]))
return false;
else
{
$arr[$class]=true;
return true;
}
}
I personally don't see how this is possible or why you would want to do it this way. I suspect debug_backtrace() is a lot more expensive than a static variable, to begin with.
The only backtrace characteristic that seems to change between calls is, as you pointed out, the line number (from where the function was called). And, that wouldn't even change if you ran the functions in, say, a loop, since they would all be called from the same line on each iteration.
Demonstration 1 (individual calls): CodePad
Demonstration 2 (loop): CodePad
If I were you, I'd stick with a state variable; as for your colleague, you could perhaps ask him to show you a code which demonstrates his methodology if you're curious as to how it works (I know I am!).
Edit (from comments): Basically, your colleague's debug_backtrace() method stores a boolean value in an array using the key of the class which is called.
In plain English, here's what happens:
Is the calling function called "JS"?
If so, store in a JS-labelled array; otherwise, use a CSS-labelled array.
Check if a class was specified; if it wasn't, use this class.
If we have a boolean value for the given class in the labelled array, it's not the first time.
Otherwise, set the boolean value for the given class to true.
I know what you're thinking: This makes no sense, it doesn't even store the calling function's name! And you'd be right; this method is not extensible, and has a huge overhead.
If you want to do what this method does, just use a static variable in the class in question to keep track of whether or not functions have been called. Your colleague's method—sorry to say—is inefficient and ineffective.
Take A hidden input field and
<input type="hidden" id="start_function_count" value="0">
and then call a function
<li onclick="myFunction('start_function_count')">
js function
MyFunction(count_id) {
var function_count = $("#"+count_id).val();
if(function_count == 0){
// CODE HERE for 1st time function call
// SET HIDDEN FIELD
$("#"+count_id).val(1);
} else{
// SECOnd time code;
}
}
just use a static field in the function. This static field will only be initialized once and not overwritten on new function calls.
If you use this in class methods, do take care that each inherited child class will have it's own version. So a static function field updated in ParentClass won't update the static function field in ChildClass extends ParentClass.
See it in action https://ideone.com/iR7J5O
function beDifferentFirstTime()
{
static $firstTime = true;
if($firstTime) {
$firstTime = false;
echo "I will say this only once, so listen carefully\n";
}
echo "The cabbage is in the cart. I repeat, the cabbage is in the cart.\n";
}
beDifferentFirstTime();
beDifferentFirstTime();
Even though there's some discussions regarding this issue I wanted to check on certain example what would be the best approach.
Instead of using existing solutions I created my own persistence layer (like many do)
So my approach is also in question here.
For every table in db I have model class that has appropriate getters and setters and some mandatory methods. I also created only one generic DAO class that handles all types of model objects.
So, for example to save any model object I instantiate genericDAO class and call save method that I pass model object as attribute.
Problem is that in runtime genericDAO class doesn't know whitch model object it gets and what methods (getters and setters) exist in it, so I need to call mandatory model class method that retrieves list of attributes as multiple string array.
For example for every attribute there's array(table_column_name,attribute_name,is_string).
When I call save function it looks like this:
public function save(&$VO) {
$paramArray = $VO->getParamArray();//get array of attributes
$paramIdArray = $paramArray[0]; //first attribute is always id
/*create and execute getId() and store value into $void to check if it's save or update*/
eval('$voId = $VO->get'.ucfirst($paramIdArray[1]).'();');
...
Currently I'm using eval to execute those methods, but as it is well known eval is very slow.
I'm thinking of changing that into call_user_func method
Something like:
$voId = call_user_func(array($VO, 'get'.ucfirst($paramIdArray[1])));
But also there's other solutions. I can maybe use something like this $method = 'get'.ucfirst($paramIdArray[1]));
$voId = $VO->$method();
or else
$method = 'get'.ucfirst($paramIdArray[1]));
$voId = $VO->{$method}();
What would be the best way?
First of all, there's no need to pass references like you are doing. You should give this a read to try to understand how PHP handles object references.
So public function save(&$VO) { should become public function save($VO) {.
Second, there is no need to use eval (in fact, it's better not to because of speed, debugability, etc). You can't stack-trace an eval call like you can a dynamic one.
Third, call_user_func is all but useless since PHP supports dynamic variable functions. Instead of call_user_func(array($obj, $method), $arg1), just call $obj->$foo($arg1). The call_user_func_array function is still useful since it supports variable length arguments and supports passing references.
So, ultimately, I would suggest this:
$method = 'get' . ucfirst($paramIdArray[1]);
$voId = $VO->$method();
Note that there's no need to call method_exists, since it may be callable and not exist due to __get magic method support...
I normally would use:
$method = 'get'.ucfirst($attribute);
if(method_exists($obj, $method){
$obj->$method();
}
But unless there is a very good reason i would just return a key => value array from getParamArray. And operate on that instead of using the getters...
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.