Can someone please explain what it means to have a class instance within the argument of another class instance:
$controller = new controllerObject(new dependenciesObject());
I understand the basics of classes and class instances but have never seen code like the above before. What does it mean? The controllerObect is a class so what does it mean to pass it an object instance in the argument?
All this means is that the controllerObject constructor accepts an object of type dependenciesObject.
You instantiate a dependenciesObject and use it as an argument to instantiate a controllerObject, which is assigned to $controller. If it helps you understand, this is equivalent to:
$dependency = new dependenciesObject();
$controller = new controllerObject($dependency);
unset($dependency);
What you're doing is assigning $controller an instance of controllerObject.
As you said controllerObject is a class with a constructor that needs a reference to an object of :dependenciesObject type.
class controllerObject
{
function __construct(dependanciesObject $dependancies)
{
//etc
}
}
It just means that the controllerObject gets another object passed to its constructor. By doing it like this - instead of instantiating a dependenciesObject in a separate variable - you will not create a global variable for the passed object, keeping the number of global variables to a minimum.
An example would be to pass a database object to the controllerObject if the controllerObject cannot function without it.
Same as passing any other argument to a constructor.. new controllerObject(5) for instance.
If it helps understanding, use a temporary variable:
$dependencies = new dependenciesObject();
$controller = new controllerObject($dependencies);
Related
I have 2 classes MyClass and MyClass2. I need to call a new instance of MyClass using reflection, passing to the constructor an instance of MyClass2. This works fine until I try using the reference in MyClass2 constructor, $classObject in this case will be null.
Why is this problem occurring? Knowing that this does not happen while testing a similar function call between two function within the same class without reflection!!
$className = 'MyClass';
$args = array(new MyClass2());
$classReflection = new ReflectionClass($className);
$classObject = $classReflection->newInstanceArgs($args);
MyClass
public function __construct(&$myClass2)
The straightforward solution is to modify MyClass's constructor so it no longer requires a reference:
public function __construct($myClass2) { }
As deceze notes in his comment above, there's generally no need to pass objects by reference; they are always passed by object identifier, which functions as a pointer and ensures all variables to which an object is assigned operate directly on that object's data.
However, your example illustrates some unusual behaviour in PHP. Like vuliad says, your code as written fails on PHP 7 with this warning:
PHP Warning: Parameter 1 to MyClass::__construct() expected to be a reference, value given
This is surprising, because the PHP manual says,
Since PHP 5, new returns a reference automatically...
So $args should hold an array that contains a reference, as MyClass's constructor expects. But the only way I can get your original code to work is by first assigning the new instance of MyClass2 to a variable, like this:
$newClass2 = new MyClass2();
$args = array(&$newClass2);
$classReflection = new ReflectionClass($className);
$classObject = $classReflection->newInstanceArgs($args);
This is a solution, too. But again, passing objects by reference is unnecessary, so I recommend simply changing the MyClass constructor.
You can do this via arguments unpacking:
$classObject = new $className(...$args);
This is really interesting case, for php7.0+ we can see Error:
Warning: Parameter 1 to MyClass::__construct() expected to be a reference, value given in /in/Bgjlj on line 15
try here https://3v4l.org/Bgjlj
I understand you cannot duplicate constant. I am just confused as to why it does not work with different objects.
In one of my project I used them to pass settings to my object.
Here is an example:
class someClass {
function __construct($config) {
define("PRIVATE_KEY", $config['private_key']);
}
}
and here is how I create the objects
$objectA = new someClass($config['A']);
$objectB = new someClass($config['B']); //ERROR!!
I get the error:
Constant PRIVATE_KEY already defined
Most people that get this error had included the same constant multiple times.
In My case they are being used in separate objects. I will add some check to make sure they are not being redefined. but I am still curious to know why this happening.
Aren't object disposed/destroyed when no longer used?
Yes, objects are destroyed at some point, but define declarations are global and persist until they are undefined. Your code is defining the same constant twice.
Private properties, static properties, or maybe class constants are more appropriate for what you're attempting to do since they are encapsulated within the object.
class someClass {
private $private_key;
// constructor
function __construct($config) {
$this->private_key = $config['private_key'];
}
}
What are you using PRIVATE_KEY for? Is it supposed to be an instance variable? If so, you shouldn't use define() because its scope is global. You could instead do $this->private_key = $config['private_key'].
I'm new to PHP and Magento and am trying to figure out what the difference is between the following two lines:
$helper = Mage::helper('catalog/category');
$helper = $this->helper('catalog/category');
I've seen similar code in the template file, but when and why would I use one instead of the other?
The first line $helper = Mage::helper('catalog/category'); is assigning an object to helper.
The second line $helper = $this->helper('catalog/categry'); is assigning a property of an object to a variable - but can only be used WITHIN the object as it uses the $this-> syntax.
Inside an object refer to it's properties by $this-> while outside, refer to it via the variable name, then the property $someVar->.
The other thing to note is that your first statement is (as Eric correctly points out) is that the first can be a call to a static method (which is a lovely way to have an object function run without creating an instance of the object - which normally doesn't work).
Normally you have to create an object before you can use it:
class something
{
public $someProperty="Castle";
public static $my_static = 'foo';
}
echo $this->someProperty; // Error. Non-object. Using '$this->' outside of scope.
echo something::$someProperty; // Error. Non Static.
echo something::$my_static; // Works! Because the property is define as static.
$someVar = new something();
echo $someVar->someProperty; // Output: Castle
i would like to know the difference between this two methods for initializing the object of a class
Method 1 (Using Scope resolution operator) :
Test::foo();
Method 2 (creating an instance of an object):
$test = new Test;
$test->foo();
also what is this -> operator called?
Test::foo() is merely statically calling a method of a class, it doesn't do anything with objects. It might initialize static values in the class, but you don't usually use static initializers. A static initializer may be used internally in the case of Singletons, but you should never call a public static initializer like this.
$test = new Test is actually instantiating an object, in which process it is likely initialized.
Please note the difference between initialize (setting up the initial state of an object/class/variable) and instantiate (create an object instance from a class).
-> is the T_OBJECT_OPERATOR.
:: is called "Paamayim Nekudotayim" (it's hebrew), -> is the object operator:
http://www.php.net/manual/en/language.oop5.paamayim-nekudotayim.php
Neither should be used to initialize your class. There's a magic __construct() method for that, which is called automatically by the new operator:
http://php.net/manual/en/language.oop5.decon.php
Test::foo() means call method foo() statically, outside of the scope of an actual object. Think of it as some kind of (slow) namespaced function.
$test->foo() means call method foo() for object $test.
http://www.php.net/manual/en/language.oop5.static.php
You need lear oop (Object Oriented Programming), and this implementation on PHP
The functions inside of classes, are called methods, this methods can be called on an instance of the class, or in static mode, The first call, don't create an instance of class*, this called the method 'foo' static.
class Test {
public static $static_atribute;
public $normal_atribute;
public function Foo($q) {
$this->normal_atribute = $q;
}
public static function SFoo ($q) {
// I dont can access to $this
self::$static_atribute = $q;
}
}
Test::Foo("hello");
// This thrown an error because $this dont exist in static mode
Test::SFoo("hello");
//This works, and the static property change
echo Test::$static_atribute;
// this puts "hello"
echo Test::$normal_atribute;
// this thrown an error
$a = new Test();
// $a is an instance of Test
$a->foo("hello");
// this works and the normal_atribute change in THIS instance
$b = new Test();
// $b is anoter instance of Test
$b->foo("bye");
// normal_atribute change in THIS instance
echo $a->normal_atribute;
// puts hello
echo $b->normal_atribute;
// puts bye
There is a pattern in which sused. called Singleton Pattern
I call it an arrow... but the difference is that with the arrow method, you're creating a new instance of that class as an object, which can then be referenced as an object. The other one simply calls a certain method of a certain class. With the object, you can store properties and call functions and store things in that object, and you can call multiple instances of that object and use them all separately... I'm rambling but there are tons of things you can do with an object that are limited with only calling the individual method.
Is it ok to use a singleton method inside of a __constructor to initiate the class if it wasn't already?
No -- A singleton method is an alternative to using a constructor.
Instead of saying $session = new Session();
you should say
$session = Session::getStaticSession();
Then define Session::getStaticSession() as a function tht returns an internal static var, and calls "new Session()" if the internal static var is null.
If you create it in each constructor that uses it, then it isn't a singleton.
If you follow this tutorial then it should help you understand how to use the singleton design pattern in php.
http://www.developertutorials.com/tutorials/php/php-singleton-design-pattern-050729/page1.html
You can't use a singleton method inside a constructor, as the object has already been created, and you can't return anything. Your singleton method, on the other hand, needs to either return the current object or create a new one.
You can use a single method to do that, however, such as the following:
<?php
class X {
// ...
function instance() {
static $instance;
if(!is_a($instance, 'X')) {
$instance = new X();
}
}
?>