PHP Class __Constructor parameters are NULL once function call happened - php

After all, searching enough in SO I couldn't find out a most generic with best practice solution for PHP __constructor with multiple parameter into a class function
I am trying to define a function inside a PHP class. Where I will be using this function multiple times through a simple function call. Where the function will be having 2 or more parameters.
When I do a function call by passing the parameter, it's just NULL when it reaches the __constructor.
Why it's NULL?
Also, note that there are objects nested inside the function addFruitCheckBox.
What I am doing wrong?
I may also wanted to pass a function call instead of $this->addFruitCheckBoxItemName sometimes.
There are lot of specific problems and solutions in SO. However, I believe this generic question will help me and all, for passing mulitple parameter into __constructor function in a PHP class
ini_set('display_errors', 1);
$_GET['SELECTEDTABNAME'] = 'properties';
/* all include files that are involved in function call within a function will be declared here */
class AddFruitController
{
protected $addFruitCheckBoxItemName;
protected $addFruitCheckBoxLabel;
protected $addFruitMenuItemName;
protected $addFruitChoiceItemName;
protected $addFruitTimeItemName;
public $trustedFruits;
public $trustedFruitsModel;
public $trustedFruitsSpeed;
public $addNewFruit;
public $additionalTub;
public $chooseParent;
public $FruitDown;
public $FruitSell;
public $timeTitle;
public $addFruitbutton;
public function __construct($addFruitCheckBoxItemName, $addFruitCheckBoxLabel, $addFruitMenuItemName, $addFruitTimeItemName)
{
global $interpreterMan, $fetchSeedForSapling;
// var_dump($this->addFruitCheckBoxLabel);
// var_dump($this->addFruitCheckBoxItemName);
$this->trustedFruits = $interpreterMan("Trusted Fruits");
$this->trustedFruitsModel = $interpreterMan("Model");
$this->trustedFruitsSpeed = $interpreterMan("Speed");
$this->addNewFruit = $interpreterMan("New Fruit");
$this->additionalTub = $interpreterMan("Additional Options");
$this->chooseParent = $interpreterMan("Choose Parent");
$this->FruitDown = $interpreterMan("Download Schedule");
$this->FruitSell = $interpreterMan("Install Schedule");
$this->timeTitle = $interpreterMan("Time");
$this->addFruitbutton = $interpreterMan("Add Fruit(s)");
$this->addFruitCheckBoxItemName = $addFruitCheckBoxItemName;
$this->addFruitCheckBoxLabel = $addFruitCheckBoxLabel;
$this->addFruitMenuItemName = $addFruitMenuItemName;
$this->addFruitChoiceItemName = $addFruitChoiceItemName;
var_dump($addFruitChoiceItemName);
$this->addFruitTimeItemName = $addFruitTimeItemName;
}
public function addFruitMenu()
{
global $interpreterMan;
$theWidfetch = new FruitMenu();
$theWidfetch->AssignAddJsCode(false);
$theWidfetch->AssignChoiceOrder(array($interpreterMan("English")));
$theWidfetch->AssignChoiceText(array($interpreterMan("English") => $interpreterMan("English")));
$theWidfetch->AssignGroupHeader($this->addFruitMenuItemName);
$theWidfetch->AssignItemName($this->addFruitMenuItemName);
$theWidfetch->AssignSaveLocation($this->addFruitMenuItemName);
$theWidfetch->AssignValueToUse("ipad");
$theWidfetch->WaterPath(true, true);
}
public function addFruitChoiceTable()
{
global $fetchSeedForSapling, $interpreterMan;
$weekChoiceSelection = new FruitChoiceTable();
$weekChoiceSelection->AssignAddJsCode(false);
$weekChoiceSelection->AssignChoiceOrder(
array("sun", "mon", "tue", "wed", "thu", "fri", "sat"));
$weekChoiceSelection->AssignChoiceText(array(
"sun" => $interpreterMan("SUN"),
"mon" => $interpreterMan("MON"),
"tue" => $interpreterMan("TUE"),
"wed" => $interpreterMan("WED"),
"thu" => $interpreterMan("THU"),
"fri" => $interpreterMan("FRI"),
"sat" => $interpreterMan("SAT"),
));
var_dump($weekChoiceSelection->AssignGroupHeader($this->addFruitChoiceItemName));
$weekChoiceSelection->AssignItemName("Weekday");
$weekChoiceSelection->AssignNumColumns(7);
$weekChoiceSelection->AssignValueToUse($fetchSeedForSapling("dayOfWeek"));
$weekChoiceSelection->WaterPath(true, true);
}
public function addFruitTime()
{
global $fetchSeedForSapling;
$FruitTimeSelect = new FruitTime();
$FruitTimeSelect->AssignGroupHeader($addFruitTimeItemName);
$FruitTimeSelect->AssignItemName($addFruitTimeItemName);
$FruitTimeSelect->AssignValueToUse($fetchSeedForSapling("minuteOfDay"));
$FruitTimeSelect->WaterPath(true, true);
}
public function addFruitCheckBox()
{
global $fetchSeedForSapling;
$addFruitCheckBoxObj = new FruitCheckbox();
$addFruitCheckBoxObj->AssignAddJsCode(false);
$addFruitCheckBoxObj->AssignCheckboxLabel($this->addFruitCheckBoxLabel);
$addFruitCheckBoxObj->AssignItemName($this->addFruitCheckBoxItemName);
$addFruitCheckBoxObj->AssignSaveLocation("somejob");
$addFruitCheckBoxObj->AssignValueToUse($fetchSeedForSapling("somejob"));
$addFruitCheckBoxObj->WaterPath(true, true);
}
}

For creating such complex objects, I suggest you to use Builder Design Pattern instead of assigning properties dynamically and directly.
Note: For better, you can add a layer of interface which Builder classes will implement. And you can have multiple Builder classes which generate different complex objects as per different use cases. Hope this make sense.
Try this code snippet here
<?php
class Builder {
public static function getMyClass($a, $b, $c) {
$myClass = MyClass::getInstance();
$myClass->setA($a);
$myClass->setB($b);
return $myClass;
}
}
class MyClass {
protected $a=0;
protected $b=0;
public static function getInstance() {
$myClass = new MyClass();
return $myClass;
}
function setA($a) {
$this->a = $a;
}
function setB($b) {
$this->b = $b;
}
}
$myClass = Builder::getMyClass("a", "b", "c");
print_r($myClass);
Explanation: In the above mentioned code we have a Builder class which is responsible for building such complex objects.
But still if you are still more towards dynamic assignment approach which nobody recommends, you can see this post

http://php.net/manual/en/language.oop5.decon.php
class MyClass {
protected $a1;
protected $a2;
protected $a3;
public function __construct($a1, $a2, $a3) {
$this->a1 = $a1;
$this->a2 = $a2;
$this->a3 = $a3;
}
}

Related

How to access and modify array inside class?

I'm having problems with an array inside a class. I can access it if I set it to static but I cannot figure out how to modify it and access it on my function if it's not static.
class Example {
protected static $_arr = array(
"count",
);
public static function run($tree) {
$_arr[] = "new";
print_r($_arr );
}
}
How do I access the array, modify it and print it from inside my public function "run"?
$_arr[] = "new";
refers to an array that will be local to your function. to access a static variable of your class, you have to use the syntax ==> self::staticVariableName
you code should be :
class Example {
protected static $_arr = array(
"count",
);
public static function run($tree) {
self::$_arr[] = "new";
print_r(self::$_arr );
}
I have just made a snippet from the code of #MQuirion . Here I wrote how to handle non-static properties in your class. I hope now you can work with your array inside your class.
class Example {
protected $_arr = array(
"count",
);
public function run($tree) {
// print new array + your properties
$this -> _arr[] = $tree;
//To print only new assigned values without your declared properties
$this -> _arr = $tree;
print_r($this->_arr );
}
}
$obj = new Example();
$tree = array('a','b','c');
$result = $obj->run($tree);

Accessing private/protected properties of an object in anonymous function in PHP

I'm trying to dump elements of an object's private property through an anonymous function - of course I could achieve this in any number of other ways, but this highlights a PHP conundrum I can't solve off the top of my head, short of $foo = $this and using $foo - but THAT won't give me the private stuff, so... suggestions ?
Sample code:
class MyClass
{
private $payload = Array( 'a' => 'A element', 'b' => 'B element');
static $csvOrder = Array('b','a');
public function toCSV(){
$values = array_map(
function($name) use ($this) { return $this->payload[$name]; },
self::$csvOrder
);
return implode(',',$values);
}
}
$mc = new MyClass();
print $mc->toCSV();
I believe there is absolutely no way to do directly what you propose.
However, you can work around it either by making the anonymous method a class method (this is not what you asked for, but it could be a practical solution) or pulling everything you need out of $this explicitly and passing the extracted values into the function:
class MyClass
{
private $payload = Array( 'a' => 'A element', 'b' => 'B element');
static $csvOrder = Array('b','a');
public function toCSV(){
$payload = $this->payload;
$values = array_map(
function($name) use ($payload) { return $payload[$name]; },
self::$csvOrder
);
return implode(',',$values);
}
}
You can hack around the limitation by creating a wrapper that utilizes Reflection to allow you to access all properties and methods. You can use it like this then:
$self = new FullAccessWrapper($this);
function () use ($self) { /* ... */ }
Here a sample implementation of the wrapper, taken from here:
class FullAccessWrapper
{
protected $_self;
protected $_refl;
public function __construct($self)
{
$this->_self = $self;
$this->_refl = new ReflectionObject($self);
}
public function __call($method, $args)
{
$mrefl = $this->_refl->getMethod($method);
$mrefl->setAccessible(true);
return $mrefl->invokeArgs($this->_self, $args);
}
public function __set($name, $value)
{
$prefl = $this->_refl->getProperty($name);
$prefl->setAccessible(true);
$prefl->setValue($this->_self, $value);
}
public function __get($name)
{
$prefl = $this->_refl->getProperty($name);
$prefl->setAccessible(true);
return $prefl->getValue($this->_self);
}
public function __isset($name)
{
$value = $this->__get($name);
return isset($value);
}
}
Obviously the above implementation doesn't cover all aspects (e.g. it can't use magic properties and methods).
As you said yourself, it is private and therefore in accessible.
You can:
Pass $this->payload as a parameter to the anonymous function.
Create a method in the class and use it instead.

Is there a special object initializer construct in PHP like there is now in C#?

I know that in C# you can nowadays do:
var a = new MyObject
{
Property1 = 1,
Property2 = 2
};
Is there something like that in PHP too? Or should I just do it through a constructor or through multiple statements;
$a = new MyObject(1, 2);
$a = new MyObject();
$a->property1 = 1;
$a->property2 = 2;
If it is possible but everyone thinks it's a terrible idea, I would also like to know.
PS: the object is nothing more than a bunch of properties.
As of PHP7, we have Anonymous Classes which would allow you to extend a class at runtime, including setting of additional properties:
$a = new class() extends MyObject {
public $property1 = 1;
public $property2 = 2;
};
echo $a->property1; // prints 1
Before PHP7, there is no such thing. If the idea is to instantiate the object with arbitrary properties, you can do
public function __construct(array $properties)
{
foreach ($properties as $property => $value)
{
$this->$property = $value
}
}
$foo = new Foo(array('prop1' => 1, 'prop2' => 2));
Add variations as you see fit. For instance, add checks to property_exists to only allow setting of defined members. I find throwing random properties at objects a design flaw.
If you do not need a specific class instance, but you just want a random object bag, you can also do
$a = (object) [
'property1' => 1,
'property2' => 2
];
which would then give you an instance of StdClass and which you could access as
echo $a->property1; // prints 1
I suggest you use a constructor and set the variables you wish when initialising the object.
I went from c# to PHP too, so I got this working in PHP:
$this->candycane = new CandyCane(['Flavor' => 'Peppermint', 'Size' => 'Large']);
My objects have a base class that checks to see if there's one argument and if it's an array. If so it calls this:
public function LoadFromRow($row){
foreach ($row as $columnname=>$columnvalue)
$this->__set($columnname, $columnvalue);
}
It also works for loading an object from a database row. Hence the name.
Another way, which is not the proper way but for some cases okay:
class Dog
{
private $name;
private $age;
public function setAge($age) {
$this->age = $age;
return $this;
}
public function getAge() {
return $this->age;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function getName() {
return $this->name;
}
}
$dogs = [
1 => (new Dog())->setAge(2)->setName('Max'),
2 => (new Dog())->setAge(7)->setName('Woofer')
];

Why can't I overload constructors in PHP?

I have abandoned all hope of ever being able to overload my constructors in PHP, so what I'd really like to know is why.
Is there even a reason for it? Does it create inherently bad code? Is it widely accepted language design to not allow it, or are other languages nicer than PHP?
You can't overload ANY method in PHP. If you want to be able to instantiate a PHP object while passing several different combinations of parameters, use the factory pattern with a private constructor.
For example:
public MyClass {
private function __construct() {
...
}
public static function makeNewWithParameterA($paramA) {
$obj = new MyClass();
// other initialization
return $obj;
}
public static function makeNewWithParametersBandC($paramB, $paramC) {
$obj = new MyClass();
// other initialization
return $obj;
}
}
$myObject = MyClass::makeNewWithParameterA("foo");
$anotherObject = MyClass::makeNewWithParametersBandC("bar", 3);
You can use variable arguments to produce the same effect. Without strong typing, it doesn't make much sense to add, given default arguments and all of the other "work arounds."
For completeness, I'll suggest Fluent Interfaces. The idea is that by adding return $this; to the end of your methods you can chain calls together. So instead of
$car1 = new Car('blue', 'RWD');
$car2 = new Car('Ford', '300hp');
(which simply wouldn't work), you can do:
$car = (new Car)
->setColor('blue')
->setMake('Ford')
->setDrive('FWD');
That way you can pick exactly which properties you want to set. In a lot of ways it's similar to passing in an array of options to your initial call:
$car = new Car(['make' => 'Ford', 'seats' => 5]);
PHP Manual: Function Arguments, Default Values
I have overcome this simply by using default values for function parameters. In __constuct, list the required parameters first. List the optional parameters after that in the general form $param = null.
class User
{
private $db;
private $userInput;
public function __construct(Database $db, array $userInput = null)
{
$this->db = $db;
$this->userInput = $userInput;
}
}
This can be instantiated as:
$user = new User($db)
or
$user = new User($db, $inputArray);
This is not a perfect solution, but I have made this work by separating parameters into absolutely mandatory parameters no matter when the object is constructed, and, as a group, optional parameters listed in order of importance.
It works.
True overloading is indeed unsupported in PHP. As #Pestilence mentioned, you can use variable arguments. Some people just use an Associative Array of various options to overcome this.
they say this work:
<?php
class A
{
function __construct()
{
$a = func_get_args();
$i = func_num_args();
if (method_exists($this,$f='__construct'.$i)) {
call_user_func_array(array($this,$f),$a);
}
}
function __construct1($a1)
{
echo('__construct with 1 param called: '.$a1.PHP_EOL);
}
function __construct2($a1,$a2)
{
echo('__construct with 2 params called: '.$a1.','.$a2.PHP_EOL);
}
function __construct3($a1,$a2,$a3)
{
echo('__construct with 3 params called: '.$a1.','.$a2.','.$a3.PHP_EOL);
}
}
$o = new A('sheep');
$o = new A('sheep','cat');
$o = new A('sheep','cat','dog');
// results:
// __construct with 1 param called: sheep
// __construct with 2 params called: sheep,cat
// __construct with 3 params called: sheep,cat,dog
?>
and, it seem every one are happy with it, but for me it didn't work...
if you get it to work, its one kind of overloading too...
it take all argoments and pass them to the secondary function constructor...
<?php
//php do not automatically call parent class constructor at all if child class has constructor so you have to call parent class constructor explicitly, however parent class constructor is called automatically if child class has no constructor
class MyClass
{
function construct1($value1)
{
echo "<br/> dummy constructor is called with 1 arguments and it is $value1";
}
function construct2($value1,$value2)
{
echo "<br/> dummy constructor is called with 2 arguments and it is $value1, $value2";
}
function construct3($value1,$value2,$value3)
{
echo "<br/> dummy constructor is called with 3 arguments and it is $value1, $value2 , $value3";
}
public function __construct()
{
$NoOfArguments = func_num_args(); //return no of arguments passed in function
$arguments = func_get_args();
echo "<br/> child constructor is called $NoOfArguments";
switch ($NoOfArguments) {
case 1:
self::construct1($arguments[0]);
break;
case 2:
self::construct2($arguments[0],$arguments[1]);
break;
case 3:
self::construct3($arguments[0],$arguments[1],$arguments[2]);
break;
default:
echo "Invalid No of arguments passed";
break;
}
}
}
$c = new MyClass();
$c2 = new MyClass("ankit");
$c2 = new MyClass("ankit","Jiya");
$c2 = new MyClass("ankit","Jiya","Kasish");
?>
You can use conditional statements in your constructor and then perform your task.
Eg.
class Example
{
function __construct($no_of_args)
{// lets assume 2
switch($no_of_args)
{
case 1:
// write your code
break;
case 2:
//write your 2nd set of code
break;
default:
//write your default statement
}
}
}
$object1 = new Example(1); // this will run your 1st case
$object2 = new Example(2); // this will run your 2nd case
and so on...
You can of course overload any function in PHP using __call() and __callStatic() magic methods.
It is a little bit tricky, but the implementation can do exactly what your are looking for.
Here is the resource on the official PHP.net website:
https://www.php.net/manual/en/language.oop5.overloading.php#object.call
And here is the example which works for both static and non-static methods:
class MethodTest
{
public function __call($name, $arguments)
{
// Note: value of $name is case sensitive.
echo "Calling object method '$name' "
. implode(', ', $arguments). "\n";
}
/** As of PHP 5.3.0 */
public static function __callStatic($name, $arguments)
{
// Note: value of $name is case sensitive.
echo "Calling static method '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('in object context');
MethodTest::runTest('in static context'); // As of PHP 5.3.0
And you can apply this to constructors by using the following code in the __construct():
$clsName = get_class($this);
$clsName->methodName($args);
Pretty easy.
And you may want to implement __clone() to make a clone copy of the class with the method that you called without having the function that you called in every instance...
Adding this answer for completeness with respect to current PHP , since later versions of PHP , you can in fact overload constructors in a way . Following code will help to understand ,
<?php
class A
{
function __construct()
{
$a = func_get_args();
$i = func_num_args();
if (method_exists($this,$f='__construct'.$i)) {
call_user_func_array(array($this,$f),$a);
}
}
function __construct1($a1)
{
echo('__construct with 1 param called: '.$a1.PHP_EOL);
}
function __construct2($a1,$a2)
{
echo('__construct with 2 params called: '.$a1.','.$a2.PHP_EOL);
}
function __construct3($a1,$a2,$a3)
{
echo('__construct with 3 params called: '.$a1.','.$a2.','.$a3.PHP_EOL);
}
}
$o = new A('sheep');
$o = new A('sheep','cat');
$o = new A('sheep','cat','dog');
?>
Output :
__construct with 1 param called: sheep
__construct with 2 params called: sheep,cat
__construct with 3 params called: sheep,cat,dog
In this case I recommend using Interfaces:
interface IExample {
public function someMethod();
}
class oneParamConstructor implements IExample {
public function __construct(private int $someNumber) {
}
public function someMethod(){
}
}
class twoParamConstructor implements IExample {
public function __construct(private int $someNumber, string $someString) {
}
public function someMethod(){
}
}
than in your code:
function doSomething(IExample $example) {
$example->someMethod();
}
$a = new oneParamConstructor(12);
$b = new twoParamConstructor(45, "foo");
doSomething($a)
doSomething($b)
As far as I know, constructor overloading in PHP is not allowed, simply because the developers of PHP did not include that functionality - this is one of the many complaints about PHP.
I've heard of tricks and workarounds, but true overloading in the OOP sense is missing. Maybe in future versions, it will be included.
I think we can also use constructor with default arguments as a potential substitute to constructor overloading in PHP.
Still, it is really sad that true constructor overloading is not supported in PHP.
<?php
class myClass {
public $param1 = 'a';
public $param2 = 'b';
public function __construct($param1 = NULL, $param2 = NULL) {
if ($param1 == NULL && $param2 == NULL) {
// $this->param1 = $param1;
// $this->param2 = $param2;
} elseif ($param1 == NULL && $param2 !== NULL) {
// $this->param1 = $param1;
$this->param2 = $param2;
} elseif ($param1 !== NULL && $param2 == NULL) {
$this->param1 = $param1;
// $this->param2 = $param2;
} else {
$this->param1 = $param1;
$this->param2 = $param2;
}
}
}
// $myObject = new myClass();
// $myObject = new myClass(NULL, 2);
$myObject = new myClass(1, '');
// $myObject = new myClass(1, 2);
echo $myObject->param1;
echo "<br />";
echo $myObject->param2;
?>
public function construct1($user , $company)
{
dd("constructor 1");
$this->user = $user;
$this->company = $company;
}
public function construct2($cc_mail , $bcc_mail , $mail_data,$user,$company)
{
dd('constructor 2');
$this->mail_data=$mail_data;
$this->user=$user;
$this->company=$company;
$this->cc_mail=$cc_mail;
$this->bcc_mail=$bcc_mail;
}
public function __construct()
{
$NoOfArguments = func_num_args(); //return no of arguments passed in function
$arguments = func_get_args();
switch ($NoOfArguments) {
case 1:
self::construct1($arguments[0]);
break;
case 5:
self::construct2($arguments[0],$arguments[1],$arguments[2],$arguments[3],$arguments[4]);
break;
default:
echo "Invalid No of arguments passed";
break;
}
I'm really no OOP expert, but as I understand it overloading means the ability of a method to act differently depending in the parameters it receives as input. This is very much possible with PHP, you just don't declare the input types since PHP does not have strong typing, and all the overloading is done at runtime instead of compile time.

How to initialize static variables

I have this code:
private static $dates = array(
'start' => mktime( 0, 0, 0, 7, 30, 2009), // Start date
'end' => mktime( 0, 0, 0, 8, 2, 2009), // End date
'close' => mktime(23, 59, 59, 7, 20, 2009), // Date when registration closes
'early' => mktime( 0, 0, 0, 3, 19, 2009), // Date when early bird discount ends
);
Which gives me the following error:
Parse error: syntax error, unexpected '(', expecting ')' in /home/user/Sites/site/registration/inc/registration.class.inc on line 19
So, I guess I am doing something wrong... but how can I do this if not like that? If I change the mktime stuff with regular strings, it works. So I know that I can do it sort of like that..
Anyone have some pointers?
PHP can't parse non-trivial expressions in initializers.
I prefer to work around this by adding code right after definition of the class:
class Foo {
static $bar;
}
Foo::$bar = array(…);
or
class Foo {
private static $bar;
static function init()
{
self::$bar = array(…);
}
}
Foo::init();
PHP 5.6 can handle some expressions now.
/* For Abstract classes */
abstract class Foo{
private static function bar(){
static $bar = null;
if ($bar == null)
bar = array(...);
return $bar;
}
/* use where necessary */
self::bar();
}
If you have control over class loading, you can do static initializing from there.
Example:
class MyClass { public static function static_init() { } }
in your class loader, do the following:
include($path . $klass . PHP_EXT);
if(method_exists($klass, 'static_init')) { $klass::staticInit() }
A more heavy weight solution would be to use an interface with ReflectionClass:
interface StaticInit { public static function staticInit() { } }
class MyClass implements StaticInit { public static function staticInit() { } }
in your class loader, do the following:
$rc = new ReflectionClass($klass);
if(in_array('StaticInit', $rc->getInterfaceNames())) { $klass::staticInit() }
Instead of finding a way to get static variables working, I prefer to simply create a getter function. Also helpful if you need arrays belonging to a specific class, and a lot simpler to implement.
class MyClass
{
public static function getTypeList()
{
return array(
"type_a"=>"Type A",
"type_b"=>"Type B",
//... etc.
);
}
}
Wherever you need the list, simply call the getter method. For example:
if (array_key_exists($type, MyClass::getTypeList()) {
// do something important...
}
I use a combination of Tjeerd Visser's and porneL's answer.
class Something
{
private static $foo;
private static getFoo()
{
if ($foo === null)
$foo = [[ complicated initializer ]]
return $foo;
}
public static bar()
{
[[ do something with self::getFoo() ]]
}
}
But an even better solution is to do away with the static methods and use the Singleton pattern. Then you just do the complicated initialization in the constructor. Or make it a "service" and use DI to inject it into any class that needs it.
That's too complex to set in the definition. You can set the definition to null though, and then in the constructor, check it, and if it has not been changed - set it:
private static $dates = null;
public function __construct()
{
if (is_null(self::$dates)) { // OR if (!is_array(self::$date))
self::$dates = array( /* .... */);
}
}
best way is to create an accessor like this:
/**
* #var object $db : map to database connection.
*/
public static $db= null;
/**
* db Function for initializing variable.
* #return object
*/
public static function db(){
if( !isset(static::$db) ){
static::$db= new \Helpers\MySQL( array(
"hostname"=> "localhost",
"username"=> "root",
"password"=> "password",
"database"=> "db_name"
)
);
}
return static::$db;
}
then you can do static::db(); or self::db(); from anywhere.
In PHP 7.0.1, I was able to define this:
public static $kIdsByActions = array(
MyClass1::kAction => 0,
MyClass2::kAction => 1
);
And then use it like this:
MyClass::$kIdsByActions[$this->mAction];
You can't make function calls in this part of the code. If you make an init() type method that gets executed before any other code does then you will be able to populate the variable then.
In my case, I'm using both static and nonstatic class properties, and I might even have main program code referencing the static part of the class before defining the class. Since static portions of classes don't have constructors, just add a manual constructor to initialize any variables requiring nontrivial calculation:
class A
{
static $a; // Initialized by Init()
static function Init()
{
A::$a=nontrivial();
{
}
...
A::Init(); // Initialize static part of class
...
$obj=new A(); // Using initialized class as an object
Here is a hopefully helpful pointer, in a code example. Note how the initializer function is only called once.
Also, if you invert the calls to StaticClass::initializeStStateArr() and $st = new StaticClass() you'll get the same result.
$ cat static.php
<?php
class StaticClass {
public static $stStateArr = NULL;
public function __construct() {
if (!isset(self::$stStateArr)) {
self::initializeStStateArr();
}
}
public static function initializeStStateArr() {
if (!isset(self::$stStateArr)) {
self::$stStateArr = array('CA' => 'California', 'CO' => 'Colorado',);
echo "In " . __FUNCTION__. "\n";
}
}
}
print "Starting...\n";
StaticClass::initializeStStateArr();
$st = new StaticClass();
print_r (StaticClass::$stStateArr);
Which yields :
$ php static.php
Starting...
In initializeStStateArr
Array
(
[CA] => California
[CO] => Colorado
)

Categories