Trying to get some data from one method in side static method(using it inside a other class) but I get the 'Using $this when not in object context in...' error.
Below a basic example
class mClass{
public $someVar = 'Hello world...';
public function passFunc(){
$give = $this->someVar;
return $give;
}
public static function showFunc(){
$show = self::passFunc();
return $show;
}
}
mClass::showFunc();// show error: Using $this when not in object context in...
You can't use $this, when you are working with static variables. $this is a pointer to the current object, but static variables belongs to class.
A class method (or static function) isn't tied to a particular instance of your class, i.e. it doesn't have $this although self is available.
A class method can access static properties or methods, but accessing anything else within the class will raise an error. It's best to look at static methods as a means to organize functions; as such, they operate in between external functions and instance methods.
In your case, you'd have to create an instance inside your static method:
public static function showFunc()
{
$o = new self;
$show = $o->passFunc();
return $show;
}
Related
I am curious as to why this is allowed to work, whereby you can call and successfully execute a private method on an object from outside of the object scope providing you are making the call from a class of the same type.
The private method call from a public scope to me seems not to satisfy the criteria of a private method, so why is this allowed in both PHP and Java?
<?php
class A
{
public function publicMethod ()
{
$obj = new static;
$obj->privateMethod ();
}
private function privateMethod ()
{
echo 'why does this execute?';
}
}
$obj = new A;
$obj->publicMethod ();
Objects of the same type will have access to each others private and protected members even though they are not the same instances. This is because the implementation specific details are already known when inside those objects.
-- Visiblity, PHP Manual
Private modifier Defines that you call the property or method in the local scope By that i mean the same class.
Although it's own class is the only caller, you can use it in a public method and then call that public method outside the local scope ( the owner class )
I've seen this use of syntax a few times on the Yii framework. I tried searching for an explanation but got no examples. A link will be nice if possible. It goes something like class::model()->function();
My understanding is that model is an object of class therefore it can access the function. So I tried to code it but I get " Call to a member function sound() on a non-object in". Here's my code
class animal
{
private static $obj;
public static function obj($className = __CLASS__)
{
return self::$obj;
}
public static function walk()
{
return "walking";
}
}
include('animal.php');
class cat extends animal
{
public static function obj($className = __CLASS__)
{
return parent::obj($className);
}
public static function sound()
{
return "meow";
}
}
echo cat::obj()->sound();
Also what benefits does it have?
That is called an object operator and this, ->, calls a class method from your created object which is defined in that class.
Here is an explanation and some examples.
$obj = new Class; // Object of the class
$obj->classMethod(); // Calling a method from that class with the object
echo cat::obj()->sound();
This will display the output of the sound() method, called on the object that is returned from cat::obj().
The reason it's failing for you is because cat::obj() is not returning a valid object.
And the reason for that is because the obj() method returns the static obj property, but you're not actually setting that obj property anywhere.
The pattern you're trying to use here is known as a "Singleton" object. In this pattern, you call an obj() method to get the single instance of the class; every call to the method will give you the same object.
However the first call to the method needs to instantiate the object; this is what you're missing.
public static function obj($className = __CLASS__){
if(!static::$obj) {static::$obj = new static;}
return static::$obj;
}
See the new line where the object is created if it doesn't exist.
Also note that I've changed self to static. The way you're using this with class inheritance means that you probably expect to have a different static object for each class type, self will always return the root animal::$obj property, whereas static will return the $obj property for whichever class you're calling it from.
There are a few other bugs you need to watch out for too. For example, you've defined the sound() method as static, but you're calling it with ->, so it shouldn't be static.
Hope that helps.
The cat::obj() returns you a object of the type cat. With ->sound(); you're executing the function sound() from the class cat. All that should return "meow".
cat::obj() returns an object; ->sound(); execute a method of this object. Equivalent is
$o = cat::obj();
$o->sound();
Due to the fact that you can not use $this-> inside a static functio, how are you supposed to access regular functions inside a static?
private function hey()
{
return 'hello';
}
public final static function get()
{
return $this->hey();
}
This throws an error, because you can't use $this-> inside a static.
private function hey()
{
return 'hello';
}
public final static function get()
{
return self::hey();
}
This throws the following error:
Non-static method Vote::get() should not be called statically
How can you access regular methods inside a static method? In the same class*
Static methods can only invoke other static methods in a class. If you want to access a non-static member, then the method itself must be non-static.
Alternatively, you could pass in an object instance into the static method and access its members. As the static method is declared in the same class as the static members you're interested in, it should still work because of how visibility works in PHP
class Foo {
private function bar () {
return get_class ($this);
}
static public function baz (Foo $quux) {
return $quux -> bar ();
}
}
Do note though, that just because you can do this, it's questionable whether you should. This kind of code breaks good object-oriented programming practice.
You can either provide a reference to an instance to the static method:
class My {
protected myProtected() {
// do something
}
public myPublic() {
// do something
}
public static myStatic(My $obj) {
$obj->myProtected(); // can access protected/private members
$obj->myPublic();
}
}
$something = new My;
// A static method call:
My::myStatic($something);
// A member function call:
$something->myPublic();
As shown above, static methods can access private and protected members (properties and methods) on objects of the class they are a member of.
Alternatively you can use the singleton pattern (evaluate this option) if you only ever need one instance.
I solved this by creating an object of the concerning class inside a static method. This way i can expose some specific public functions as static function as well. Other public functions can only be used like $object->public_function();
A small code example:
class Person
{
public static function sayHi()
{
return (new Person())->saySomething("hi");
}
public function saySomething($text)
{
echo($text);
}
private function smile()
{
# dome some smile logic
}
}
This way you can only say hi if using the static function but you can also say other things when creating an object like $peter->saySomething('hi');.
Public functions can also use the private functions this way.
Note that i'm not sure if this is best practice but it works in my situation where i want to be able to generate a token without creating an object by hand each time.
I can for example simply issue or verify a token string like TokenManager::getTokenToken(); or TokenManager::verifyToken("TokenHere"); but i can also issue a token object like $manager = new TokenGenerator(); so i can use functionality as $manager->createToken();, $manager->updateToken(updateObjectHere); or $manager->storeToken();
What's the difference between these object callings?
Non Static:
$var = new Object;
$var->function();
Static:
$var = User::function();
And also inside a class why should I use the static property for functions?
example:
static public function doSomething(){
...code...
}
Static functions, by definition, cannot and do not depend on any instance properties of the class. That is, they do not require an instance of the class to execute (and so can be executed as you've shown without first creating an instance). In some sense, this means that the function doesn't (and will never need to) depend on members or methods (public or private) of the class.
Difference is in the variable scope. Imagine you have:
class Student{
public $age;
static $generation = 2006;
public function readPublic(){
return $this->age;
}
public static function readStatic(){
return $this->age; // case 1
return $student1->age; // case 2
return self::$generation; // case 3
}
}
$student1 = new Student();
Student::readStatic();
You static function cannot know what is $this because it is static. If there could be a $this, it would have belonged to $student1 and not Student.
It also doesn't know what is $student1.
It does work for case 3 because it is a static variable that belongs to the class, unlike previous 2, which belong to objects that have to be instantiated.
Static methods and members belong to the class itself and not to the instance of a class.
Static functions or fields does not rely on initialization; hence, static.
Questions regarding STATIC functions keep coming back.
Static functions, by definition, cannot and do not depend on any instance properties of the class. That is, they do not require an instance of the class to execute (and so can be executed.
In some sense, this means that the function doesn't (and will never need to) depend on members or methods (public or private) of the class.
class Example {
// property declaration
public $value = "The text in the property";
// method declaration
public function displayValue() {
echo $this->value;
}
static function displayText() {
echo "The text from the static function";
}
}
$instance = new Example();
$instance->displayValue();
$instance->displayText();
// Example::displayValue(); // Direct call to a non static function not allowed
Example::displayText();
I have the following class in PHP
class MyClass
{
// How to declare MyMember here? It needs to be private
public static function MyFunction()
{
// How to access MyMember here?
}
}
I am totally confused about which syntax to use
$MyMember = 0; and echo $MyMember
or
private $MyMember = 0; and echo $MyMember
or
$this->MyMember = 0; and echo $this->MyMember
Can someone tell me how to do it?
I am kind of not strong in OOPS.
Can you do it in the first place?
If not, how should I declare the member so that I can access it inside static functions?
class MyClass
{
private static $MyMember = 99;
public static function MyFunction()
{
echo self::$MyMember;
}
}
MyClass::MyFunction();
see Visibility and Scope Resolution Operator (::) in the oop5 chapter of the php manual.
This is a super late response but it may help someone..
class MyClass
{
private $MyMember;
public static function MyFunction($class)
{
$class->MyMember = 0;
}
}
That works. You can access the private member that way, but if you had $class you should just make MyFunction a method of the class, as you would just call $class->MyFunction(). However you could have a static array that each instance is added to in the class constructor which this static function could access and iterate through, updating all the instances. ie..
class MyClass
{
private $MyMember;
private static $MyClasses;
public function __construct()
{
MyClass::$MyClasses[] = $this;
}
public static function MyFunction()
{
foreach(MyClass::$MyClasses as $class)
{
$class->MyMember = 0;
}
}
}
Within static methods, you can't call variable using $this because static methods are called outside an "instance context".
It is clearly stated in the PHP doc.
<?php
class MyClass
{
// A)
// private $MyMember = 0;
// B)
private static $MyMember = 0;
public static function MyFunction()
{
// using A) // Fatal error: Access to undeclared static property:
// MyClass::$MyMember
// echo MyClass::$MyMember;
// using A) // Fatal error: Using $this when not in object context
// echo $this->MyMember;
// using A) or B)
// echo $MyMember; // local scope
// correct, B)
echo MyClass::$MyMember;
}
}
$m = new MyClass;
echo $m->MyFunction();
// or better ...
MyClass::MyFunction();
?>
Static or non-static?
Did you ever asked yourself this question?
You can not access non static parameters / methods from inside
static method (at least not without using dependency injection)
You can however access static properties and methods from with in non-static method (with self::)
Properties
Does particular property value is assign to class blueprint or rather to it instance (created object from a class)?
If the value is not tight to class instance (class object) then you could declare it as as static property.
private static $objectCreatedCount; // this property is assign to class blueprint
private $objectId; // this property is assign explicitly to class instance
Methods
When deciding on making a method static or non-static you need to ask yourself a simple question. Does this method need to use $this? If it does, then it should not be declared as static.
And just because you don't need the $this keyword does not
automatically mean that you should make something static (though the
opposite is true: if you need $this, make it non-static).
Are you calling this method on one individual object or on the class in general? If you not sure which one to use because both are appropriate for particular use case, then always use non-static. It will give you more flexibility in future.
Good practice is to always start to design your class as non-static and force static if particular us case become very clear.
You could try to declare your parameters as static... just so you can access it from static method but that usually is not what you want to do.
So if you really need to access $this from static method then it means that you need to rethink/redesign your class architecture because you have don it wrong.