Documenting implicit input parameters such as $_SESSION - php

If a function relies on $_SESSION['some_var'] then the header comment out to make that clear. How do you do it? Just as text, or what?
Or even #param?

You could maybe use #uses to document superglobals

Wow, I never even thought about that. I don't even doc things like that. I would say to just state it in the method detail like
/**
* Takes the some_var session variable and uses it to solve world hunger
* #return food
*/
Makes the most sense to me.
There is #global, but that seems to indicate the creation of a global var. I think #param should only refer to method parameters passed to the method. There is no #note, that I know of.

#global has two usages: to denote a global var's definition, and to highlight a global's usage in a method. This second usage fits your use case.
However, assuming that you are referencing $_SESSION['some_var'] directly in that method, and never denoting it via the "global" keyword, it's possible that phpDocumentor's #global tag won't find it when the method is parsed. As such, #uses is probably the best alternative as a means to highlight the method's reliance on that superglobal.
[1] -- http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_tags.global.pkg.html

If your code depends on something global, or external, to be present in order to work (for example, it requires the sqlite to be installed) you can use #use as Nev mentioned.
HOWEVER...
In general, I would say it is a bad practice to have a function populate or use global variables (or use superglobals), as it breaks the encapsulation of the function and creates a strong dependency between the code inside the function and outside.
If any code external to the function is supposed to create or access those globals, the values should instead be passed as parameters to the function.
For example, instead of
function doMagic(){
if ($_SESSION['use_black_magic'] == true){ // var coming from the outside
$_SESSION['magic_results'] = 'dead chicken';
}else{
$_SESSION['magic_results'] = 'unicorn';
}
}
$_SESSION['use_black_magic'] = false;
doMagic();
echo $_SESSION['magic_results']; // (unicorn) variable set within doMagic()
it should be
function doMagic( $use_black_magic = true ){
if ($use_black_magic == true){
return 'dead chicken';
}else{
return 'unicorn';
}
}
$magic_results = doMagic( false );
echo $magic_results; // unicorn
This way, doMagic() doesn't need to know anything about where the results are to be stored, nor where to find the parameter value. And the external code, doesn't need to know that the function doMagic() is doing something with $_SESSION variables.
As soon as your code grows just a little bit, maintaining, sharing, debugging, and extending this kind of code becomes a nightmare...
http://en.wikipedia.org/wiki/Separation_of_concerns

Related

PHP variables inside a function

I have not been able to find a good example for this particular case. Most people who ask this question have a more complex use case and so the answer usually involves a complex solution. I simply have a few variables at the beginning of the script that need to be available throughout all the code including several functions. Otherwise I would have to set it in each function, and considering this is a user set value, changing it all throughout the code is just not possible.
<?php
//**** Example User Config Area ****
$name = "blah";
$tag = "blah";
//**********************************
function taco() {
echo $name; //this function needs to use these user set variables
echo $tag;
}
?>
Everyone says NOT to use global variables. Is this a case where global variables actually DOES make sense? If not, what should I do here to make this work?
It should be noted that those values do not change in the program. They only change if the user edits them. Like a DB location or a username etc.
Just pass these variables:
function taco($name, $tag) {
echo $name;
echo $tag;
}
// and
taco($name, $tag);
There are two main ways you can do configuration in PHP.
The first is to create a configuration object that you can pass around to each function. Some people consider this a little clunky, but it does get around using global variables.
That being said, if you're just trying to store configuration details, a global variable is not a bad option and has been discussed on this site before.
You need to think about your use case. If you're dealing with something that could create a race condition, then global variables are of course a bad idea. If you just want to store some static information to reference throughout your code... it's not the end of the world.

Pre-declare all private/local variables?

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.

Do I need to define functions before I use them in object-oriented PHP?

Not sure if I phrased the question correctly but let me explain. In a procedural program, for example:
function getUserId()
{
// some stuff
return $someUserId;
}
function getUsername()
{
$id = getUserId();
$query = mysql_query(" SELECT * FROM users WHERE id = '$id' ");
while ($row = mysql_fetch_assoc($query))
{
return $row['username'];
}
}
In the above, the getUsername function called the getUserId function. Since that function was called it must be above the one that called it, otherwise it won't work.
What I would like to know is, in object oriented programming, does the order of functions (methods) in a class matter? Can I call a method within another method even if the method being called is defined further down in the script?
The order of the functions don't matter, for several reasons:
The methods are not executed at compile time, so the compiler can "look ahead" for functions that might not exist yet. (Note: this is an oversimplification...)
PHP is a dynamic language, in that functions don't even have to exist at compile time. They can be loaded dynamically during the run time.
PHP loads methods by name, so it will look for a method that matches the name during runtime.
An example of the third case is:
$object = new MyObject();
$method = 'my_method';
echo $object->${my_method}();
That will call the method my_method, if it exists, on the object $object, which is an instance of the MyObject class. (If that method doesn't exist, it will throw a runtime exception.)
From technical standpoint - it does not matter at all. All that matters is readability and easy of modification, so it is up to you to decide what works best for you. You may want to order functions chronologically, alphabetically, or, sometimes, by purpose. IMHO, the best way is to order them alphabetically - it makes it easier to search for them in code navigation tools.
Depends on the language.
In JavaScript for example, your getUsername() function can be defined first, so long as it is called after getUserId() has been defined.
In Java as another example, it generally does not matter (except for static initilization blocks)
Even in procedural style functions don't need to be declared in order. They only need to exist at the time they are called. This will work perfectly fine, because neither function is actually ever called:
function foo() {
bar();
}
function bar() {
}
The same goes for OOP, a function must exist when it is called. In which order they are declared is irrelevant.
You can call them logically in any order. Some languages enforce an order of declaration which may/maynot be different. But at the root, if you are using a module/class/chunk of code that declares a number of functions or methods you may call them entirely willy nilly.

How to define constant in class constructor?

Can I define a class constant inside the class constructor function ?
(based on certain conditions)
That goes against the idea of class constants - they should not be dependent on a specific instance. You should use a variable instead.
However, if you insist on doing this, are very adventurous and can install PHP extensions, you can have a look at the runkit extension that allows to modify classes and their constants at runtime. See this doc: http://www.php.net/manual/en/function.runkit-constant-add.php
I don't think you can.
It wouldn't make sense, either - a class constant can be used in a static context, where there is no constructor in the first place.
You'll have to use a variable instead - that's what they're there for.
Try look here:
http://php.net/manual/en/language.oop5.constants.php
http://php.net/manual/en/language.oop5.static.php
Hope this helps.
As far as standard instance constructors go, there is no way to do this, and as others have pointed out, it wouldn't make sense. These constructors are called per created object instance, at the point they are created. There is no guarantee this constructor would get called before some code tried to access the constant. It also doesn't make sense in that the code would get called over and over again each time a new instance was constructed, whereas a const should only get set once.
It would be nice if PHP either offered some kind of static constructor that let you set the value one time for uninitialized constants, or allowed more types of expressions when defining constants. But these are not currently features of PHP. In 2015 an RFC was made that proposed adding static class constructors, but it is, at the time of me writing this answer, still in the draft status, and has not been modified since 2017.
I think the best alternative for now is to not use constants in this kind of scenario, and instead use static methods that return the value you want. This is very simple in that it only uses the PHP language features as is (not requiring any special extensions), these static methods can be called in the standard way, and you don't need to hack the autoloading process to call some kind of initializer function that sets static variables. The method might need to rely on private static variables in order to make sure the same instance is returned every time, if an object instance is being returned. You would need to write the implementation of this method to be constant like in the sense that it will always return the same thing, but takes advantage of being able to do things you can't do with a constant, like return on object instance or rely on complex expressions or function calls. Here is an example:
final class User
{
/** #var DefinitelyPositiveInt|null */ private static $usernameMaxLength;
public static function getUsernameMaxLengthConst(): DefinitelyPositiveInt
{
if ($usernameMaxLength === null) {
$usernameMaxLength = new DefinitelyPositiveInt(40);
}
return $usernameMaxLength;
}
}
$usernameInput.maxLength = User::getUsernameMaxLengthConst();
This is still not a perfect solution because it relies on the programmer to write these in a constant like way when that is desired (always returning the same value). Also, I don't like that the best place to document the fact that it is a const is in the method name, thus making it even longer to call. I also don't like that you now have to call it as a method instead of just accessing a property, which would be syntactically nicer.
This example is essentially an implementation of a singleton, but sometimes the purpose of a singleton is to be a constant rather than just a singleton. What I mean is, you might want the instance to always exist, and it might be an immutable type (none of the properties are public or mutable, only having methods that return new objects/values).
I am sorry to break it to you but it is not possible in vanilla PHP.
I am not very sure about frameworks or extensions but I am sure that it is not possible in vanilla PHP.
I recommend you to use variables instead.
You still can't, but maybe some of these (progressively weirder) ideas (just ideas, not true solutions) will work for you:
(1) You could use a private property, with a public getter method. The property cannot be modified outside the class, such as constants, but unfortunately it is accessed as a method, not as a constant, so the syntax is not the same.
class aClass{
private $const;
function __construct($const){
$this->const=$const;
}
function const(){
return $this->const;
}
}
$var1=new aClass(1);
echo $var1->const(); //Prints 1
(2) If you really want this value to be accessed as constant from outside, you can use define () inside the constructor. Unfortunately it doesn't get tied to the class or object name (as it do when you use const, using for example myClass::myConst). Furthermore, it only works if you create a single instance of the class. The second object you create is going to throw an error for redefining the constant, because is untied.
class otherClass{
function __construct($const){
define('_CONST',$const);
}
function const(){
return _CONST;
}
}
$var2=new otherClass('2');
echo $var2->const(); //Prints 2
echo _CONST; //Prints 2
#$var3=new aClass('3'); //Notice: Constant _CONST already defined
echo _CONST; //Still prints 2!
(3) Perhaps that last problem can be solved by giving variable names to the constants, related to the object to which they belong. This may be a bit weird... but maybe it works for someone.
class onemoreClass{
private $name;
function __construct($const,$name){
$this->name=$name;
$constname=$this->name."_CONST";
define($constname,$const);
}
function const(){
return constant($this->name.'_CONST');
}
}
$name='var4';
$$name=new onemoreClass(4,$name);
echo $var4->const(); //Prints 4
echo var4_CONST; //Prints 4
$name='var5';
$$name=new onemoreClass(5,$name);
echo $var5->const(); //Prints 5
echo var5_CONST; //Prints 5

Can i change the value of local variable sitting inside the function in PHP?

I was reading an article about Data Encapsulation in PHP, and the author explained in such a way that it made me to wonder if this is really possible? here is what he said.
The primary purpose of encapsulation
(scope) is to ensure that you write
code that can't be broken. This
applies to scope in general, so let me
use a simpler example of a local
variable inside a function:
function xyz ($x) {
$y = 1;
while ($y <= 10) {
$array[] = $y * $x;
$y++;
}
return $array;
}
The purpose of this function is to
pass a number and return an array. The
example code is pretty basic. In order
for function xyz() to be dependable,
you need to be guaranteed that it does
the exact same thing every time. So
what if someone had the ability to
from the outside change that initial
value of $y or $array? Or even $x? If
you were able to do that from outside
of the function, you could no longer
guarantee what that function is
returning.
Now this made me wonder can i really change the value of local variable sitting inside the function without using any argument as demonstrated above ?? if it is possible how do i do it?
thank you..
For this example you wouldn't be able to change any of the variables, because they're all declared inside of the function.
But if you had a class with a public class variable, you could change that outside of the class if you wanted to. (That's bad form and might screw a lot of things up, though.)
Unless you add a magic setter method ( __set($key,$value) ), and configure it in such a way that you can access that internal member, then no. You can change the key when you make the function if you're using some form of factory, but if you haven't made it public, there's no other way.
The only visible exception would be with a singleton factory: you could make a new instance of your singleton method with different parameters (changing it everywhere else), but I doubt you'd be likely to do that with a method.

Categories