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
Related
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 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.
I have seen function called from php classes with :: or ->.
eg:
$classinstance::function
or
$classinstance->function
whats the difference?
:: is used for scope resolution, accessing (typically) static methods, variables, or constants, whereas -> is used for invoking object methods or accessing object properties on a particular object instance.
In other words, the typical syntax is...
ClassName::MemberName
versus...
$Instance->MemberName
In the rare cases where you see $variable::MemberName, what's actually going on there is that the contents of $variable are treated as a class name, so $var='Foo'; $var::Bar is equivalent to Foo::Bar.
http://www.php.net/manual/en/language.oop5.basic.php
http://www.php.net/manual/language.oop5.paamayim-nekudotayim.php
The :: syntax means that you are calling a static method. Whereas the -> is non-static.
MyClass{
public function myFun(){
}
public static function myStaticFun(){
}
}
$obj = new MyClass();
// Notice how the two methods must be called using different syntax
$obj->myFun();
MyClass::myStaticFun();
Example:
class FooBar {
public function sayHi() { echo 'Hi!'; }
public /* --> */ static /* <-- */ function sayHallo() { echo 'Hallo!'; }
}
// object call (needs an instance, $foobar here)
$foobar = new FooBar;
$foobar->sayHi();
// static class call, no instance required
FooBar::sayHallo(); // notice I use the plain classname here, not $foobar!
// As of PHP 5.3 you can write:
$nameOfClass = 'FooBar'; // now I store the classname in a variable
$nameOfClass::sayHallo(); // and call it statically
$foobar::sayHallo(); // This will not work, because $foobar is an class *instance*, not a class *name*
::function is for static functions, and should actually be used as:
class::function() rather than $instance::function() as you suggest.
You can also use
class::function()
in a subclass to refer to parent's methods.
:: is normally used for calling static methods or Class Constants. (in other words, you don't need to instantiate the object with new) in order to use the method. And -> is when you've already instantiated a object.
For example:
Validation::CompareValues($val1, $val2);
$validation = new Validation;
$validation->CompareValues($val1, $val2);
As a note, any method you try to use as static (or with ::) must have the static keyword used when defining it. Read the various PHP.net documentation pages I've linked to in this post.
With :: you can access constants, attributes or methods of a class; the variables and methods need to be declared as static, otherwise they do belong to an instance and not to the class.
And with -> you can access attributes or methods of an instance of a class.
I always see people in serious projects use :: everywhere, and -> only occasionally in local environment.
I only use -> myself and never end up in situations when I need a static value outside of a class. Am I a bad person?
As I understand, the only situation when -> won't work is when I try following:
class StaticDemo {
private static $static
}
$staticDemo = new StaticDemo( );
$staticDemo->static; // wrong
$staticDemo::static; // right
But am I missing out on some programming correctness when I don't call simple public methods by :: ?
Or is it just so that I can call a method without creating an instance?
The double colon is used when you don't instantiate a class
class StaticDemo {...};
StaticDemo::static
if you do instantiate, use -->
class StaticDemo {...};
$s = new StaticDemo();
$s->static;
This is explained further at http://php.net/manual/en/language.oop5.patterns.php
:: is for referencing static properties or methods of a class. -> is for referencing instance properties and methods. You aren't missing out on any programming correctness, and if you are a bad person then it isn't because of this. Which one you use depends on the purpose of your class and how its written. But also, PHP didn't have namespaces until very recently so many people encapsulated their code in static classes to emulate namespaces to avoid naming collisions. It is possible you are seeing code that does that.
You caused a strict standards warning in E_STRICT mode. You are a bad person.
<?php
error_reporting(E_ALL | E_STRICT);
header('Content-type: text/plain');
class Foo {
public $msg = "Hello, public.\n";
public static $msgStatic = "Hello, static.\n";
public function write() {
echo "Hello, write.\n";
}
public static function writeStatic() {
echo "Hello, writeStatic.\n";
}
}
//echo Foo::$msg; // Fatal error: Access to undeclared static property: Foo::$msg
echo Foo::$msgStatic;
echo Foo::write(); // Strict Standards: Non-static method Foo::write() should not be called statically
echo Foo::writeStatic();
echo "------------------------\n";
$f = new Foo;
echo $f->msg;
echo $f->msgStatic; // Strict Standards: Accessing static property Foo::$msgStatic as non static
// Notice: Undefined property: Foo::$msgStatic
echo $f->write();
echo $f->writeStatic();
Output:
Hello, static.
Strict Standards: Non-static method Foo::write() should not be called statically in /home/adam/public_html/2010/05/10/bad.php on line 22
Hello, write.
Hello, writeStatic.
------------------------
Hello, public.
Strict Standards: Accessing static property Foo::$msgStatic as non static in /home/adam/public_html/2010/05/10/bad.php on line 29
Notice: Undefined property: Foo::$msgStatic in /home/adam/public_html/2010/05/10/bad.php on line 29
Hello, write.
Hello, writeStatic.
-> is for an instanciated class.
:: is a static call.
:: is used in inheritance constructors (a child accessing a parent constructor) and when referring to a static method inside another method.
I wouldn't say not using static calls makes you a bad person either!
Yes, you can call a method or access a value without creating an instance.
It would be useful, for example, if you have a value that all instances of a class use. Say this value, however, needs to be initialized at the beginning of your app. You could use something like StaticDemo::static = 42; to initialize it, and then all instances of your class would be able to access it.
As I understand it the static is shared between objects of the same type:
class test{
static function print_test(){
print "hello!";
}
}
$objectA = new test();
$objectB = new test();
The function print_test will be "shared" between the two objects. But the catch is the function print_test() should not reference anything inside the class! even thou PHP 5 accepts it.
Since the function print_test in the example just prints out "hello!" and doesn't reference anything inside the class why allocate memory for it in $objectA and $objectB? Just make one static function and $objectA and $objectB should point to it automatically.
Well that's the theory behind it in other languages, but since php5 allows you to reference $this in a static function I don't believe its a true static function since it would have to be dynamic to get any properties for ($this->variable) that unique object.
:: is used for static methods, which you call if you have no object instance.
Use "->" when in object context and "::" when accessing the class directly. In your example that would be:
class StaticDemo {
public static $staticVar = 'blabla';
public $normalVar = 'foobar';
}
$foo = new StaticDemo();
echo $foo->normalVar; //object context, echoes "foobar"
echo StaticDemo::staticVar; //class or "static" context, echoes "blabla"
Read this for detailed intel.
Or is it just so that I can call a method without creating an instance?
Correct.
The :: (scope resolution operators) are used when calling static methods/members. You don't have to create an instance to do this (like you did in your example).
Using -> and :: in the right context is the key to object-orientated programming correctness. You should only create static variables/methods when they apply to the class as a whole, and not only to a specific instance (object) of the class.
Static methods and properties are independent of a particular instantiation of a class. These must be accessed using double colons (::). Non-static methods and properties should be accessed using ->
This allows you do to some pretty cool things. A trivial example is a counter that keeps track of the number of instances of the class exists:
class foo {
public static $i = 0;
public function __construct() {
self::$i++;
}
}
$a = new foo();
$b = new foo();
echo foo::$i;
// outputs 2
As others have said,
:: 'double colon' is for referencing a static property or method.
-> 'dash arrow' is for referencing a property or method of a class instance.
But also its worth noting that
:: is often used in texts as shorthand to refer to a property or method that belongs to a certain class (whether it's static or instance).
See the 'Note...in documentation...' : http://books.google.co.uk/books?id=qVLjFk_4zVYC&lpg=PA66&dq=php%205%20objects&pg=PA46#v=onepage&q=php%205%20objects&f=false
Well you're right about how to use -> and ::. But sometimes it just doesn't make much sense to create objects of a class. Here's an example
Compare
class Settings
{
public static $setting1;
public static $setting2;
... // lots of other vars and functions
}
if(Setting::$setting1)
//do something
vs
class Settings
{
public $setting1;
public $setting2;
... // lots of other vars and functions
}
$set = new Settings()
if($set->setting1)
//do something
As I said It doesn't make sense to create instances as there's always only required one. in this case static fits better. It turns out in web we mostly deal with this kind of case unless you're dealing with real Objects e.g. users etc hence the prevalence of the former
Should an object's method be able to access a protected property of another object of the same class?
I'm coding in PHP, and I just discovered that an object's protected property is allowed to be accessed by a method of the same class even if not of the same object.
In the example, at first, you'll get "3" in the output - as function readOtherUser will have successfully accessed the value -, and after that a PHP fatal error will occur - as the main program will have failed accessing the same value.
<?php
class user
{
protected $property = 3;
public function readOtherUser ()
{
$otherUser = new user ();
print $otherUser->property;
}
}
$user = new user ();
$user->readOtherUser ();
print $user->property;
?>
Is this a PHP bug or is it the intended behaviour (and I'll have to relearn this concept… :)) (and are there references to the fact)? How is it done in other programming languages?
Thanks!
This is intended. It's even possible to access the private members of the same class. So think of the modifiers to be class wise modifiers, not objectwise modifiers.
PHP is not the only language that has this feature. Java for example has this too.
It's intended behavior. A protected variable or function means that it can be accessed by the same class or any class that inherits from that class. A protected method may only be called from within the class, e.g. you cannot call it like this:
$object = new MyClass();
$object->myProtectedFunction();
This will give you an error. However, from within the defined class 'MyClass', you can perfectly call the protected function.
Same applies for variabeles. Summarized:
use PROTECTED on variables and functions when:
1. outside-code SHOULD NOT access this property or function.
2. extending classes SHOULD inherit this property or function.