Static methods requiring var - php

Ok, i'm stuck on this, why don't i get what i need?
class config
{
private $config;
# Load configurations
public function __construct()
{
loadConfig('site'); // load a file with $cf in it
loadConfig('database'); // load another file with $cf in it
$this->config = $cf; // $cf is an array
unset($cf);
}
# Get a configuration
public static function get($tag, $name)
{
return $this->config[$tag][$name];
}
}
I'm getting this:
Fatal error: Using $this when not in object context in [this file] on line 22 [return $this->config[$tag][$name];]
And i need to call the method in this way: config::get()...

public static function get
need to be
public function get
You can't use $this in static methods.
EDITED
I could do this, but I'm not sure if it's the best design for you.
class config
{
static private $config = null;
# Load configurations
private static function loadConfig()
{
if(null === self::$config)
{
loadConfig('site'); // load a file with $cf in it
loadConfig('database'); // load another file with $cf in it
self::$config = $cf; // $cf is an array
}
}
# Get a configuration
public static function get($tag, $name)
{
self::loadConfig();
return self::$config[$tag][$name];
}
}

The problem is that you're Using $this when not in object context... Declaring a method as static removes the possibility to use the $this-reference inside the method.

There is no $this reference inside static methods as they belong to the class. Static methods can only access static members, so if it is important that get() is a static method, make $this->config a static member and return self::$config[$tag][$name]. However, the static keyword makes methods accessible without an instance of the class and I'd advise either making get() non-static, or making the class a singleton (depending on how you wish to use it).

Related

Calling static method inside constructors php

public function __construct($docID) {
self::getTranscriptionInfo($docID);
}
protected static function getTranscriptionInfo($docID) {
$cache_dir = $this->cache_dir;
}
I get error"Uncaught Error: Using $this when not in object context in". How to fix it?
I want to make getTranscriptionInfo() static
I want to call getTranscriptionInfo() inside construct.

Static function of a class

I have a code here,
class someClass {
public $someMember;
public function __construct() {
$this->someMember = 1;
}
public static function getsomethingstatic() {
return $this->someMember * 5;
}
}
$obj = new someClass();
echo $obj::getsomethingstatic();
and return an error, I know it has something to do with static but I couldn't find good explanation. I know how to fix this, I'm just looking for an explanation which will add to my understanding.
Anyone?
A static function ($obj::) cannot return/use a non-static ($this) class property, you'd have to make getsomethingstatic non-static to return the variable or make the variable static and update your other functions respectively.
As $this refers to the instance in question and static functions by definition are used outside of the instance it is not possible to mix.
ProTip
In the future, please include the error in the OP. It was easy to spot the error in this question but it might not have been in another case so included the required information speeds up the process.
You don't use the object accessor -> within Static methods. Use the Scope-Resolution Operator :: instead; prefixing it with either self or static as shown below. However be sure to use only static member variables/properties within Static methods as well...
class someClass {
public static $someMember;
public function __construct() {
self::$someMember = 1;
// OR
static::$someMember = 1;
}
public static function getsomethingstatic() {
return self::$someMember * 5;
// OR
return static::$someMember * 5;
}
}
// TO CALL A STATIC METHOD OF A CLASS,
// YOU NEED NOT INSTANTIATE THE CLASS...
// SIMPLY CALL THE METHOD DIRECTLY ON THE CLASS ITSELF....
echo someClass::getsomethingstatic();

Cannot access to changed property

I've created a class called Boot, inside this I've a method that change the path of a file, so the user can call it to set a custom path, something like this:
class Boot
{
private static $_filePath = 'directory/';
public function __construct()
{
require 'system.php';
}
public function init()
{
new System();
}
public function setFilePath($newDir)
{
$this->_filePath = $newDir;
}
public static function getFilePath()
{
return self::_filePath;
}
}
so in my index.php file:
require 'boot.php';
$b = new Boot();
$b->setFilePath('directories/');
$b->init();
Now in the system class I call something like this:
echo Boot::getFilePath();
and should be displayed directories/ but I see again the default value: directory.
Now I though that this issue is related to the static field, but how can I access to the changed value so? Thanks.
Class variables defined with and without static are different variables.
One solution is to remove static from variable declaration and change getPath code, as you already have instance of Boot defined witn new:
class Boot
{
private $_filePath = 'directory/';
public function __construct()
{
require 'system.php';
}
public function init()
{
new System();
}
public function setFilePath($newDir)
{
$this->_filePath = $newDir;
}
public function getFilePath()
{
return $this->_filePath;
}
}
And call getFilePath() as
echo $b->getFilePath();
Another solution is to change both setFilePath and getFilePath:
public function setFilePath($newDir)
{
// set STATIC variable
self::$_filePath = $newDir;
}
public static function getFilePath()
{
// get STATIC variable
return self::$_filePath;
}
But in the end it's a bad approach because you will make mistakes deciding whether you need to access a static variable or a property of an object.
So it's better to make a decision - either you have an instance of Boot and get properties of it or you have only static methods in a class and forget about Boot instance.

Accessing a public/private function inside a static function?

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();

How to emulate __destruct() in a static class?

I've coded a simple configuration class for my own framework.
There are simple functions like get(), set() or loadFile().
But all functions and variables are static.
And now I want to implement an autosave mechanism. I had the idea to create an instance (in my init() function) whose __destruct() will call the static destruct() function:
<?php
class Config
{
static private $autoSave;
static public function get() {} /* set(), save(), load(), etc. */
static public function init($autoSave)
{
self::$autoSave = $autoSave;
new Config();
}
static public function destruct()
{
if (self::$autoSave)
self::save();
}
public function __destruct()
{
Config::destruct();
}
}
?>
Are there any better solutions or is my design pattern completely wrong in this case?
Are there any better solutions or is my design pattern completely wrong in this case?
Destructors are called on objects only, not for static classes.
Instead you could convert your class from static to regular so you can create an instance of it. Then it will have the destructor. Additionally it makes your code easier to re-use and test.
Additionally you're able to implement magic methods for __get and __set or ArrayAccess which often is useful for easy data storage and access as for a configuration.
Alternatively, you can add a destructor object to a static class member to achieve what you're looking for:
class ConfigDestructor
{
public function __destruct()
{
Config::destruct();
}
}
class Config
{
static private $destructorInstance;
static private $autoSave;
static public function get() {} /* set(), save(), load(), etc. */
static public function init($autoSave)
{
if (null === self::$destructorInstance)
self::$destructorInstance = new ConfigDestructor();
self::$autoSave = $autoSave;
}
static public function destruct()
{
if (self::$autoSave)
self::save();
}
}
Just FYI: You wrote you want to add an auto-save functionality. There is a common gap to fall over for both __destruct() and register_shutdown_function:
Note: Working directory of the script can change inside the shutdown function under some web servers, e.g. Apache.
You should specify an absolute path to access the file you want to save into. See as well: PHP file creation/write within destructor.
Inside your init method, add a call to register_shutdown_function:
register_shutdown_function(array('Config', 'destruct'));
Have you looked at register_shutdown_function? You could add your method to the shutdown part of the script.
It could also be worth it to look at the Singleton pattern.
You can create an instance of this static class on autoregister.
$instance = array();
spl_autoload_register(function ($class)
{
...
global $instance;
if ($isStatic) $instance[] = new $class();
...
});
This is working fine for me.
... and for those who don't like readable code (it is untested):
class staticInstances()
{
private static $list = array();
public static function add($class)
{
self::$list[] = new $class();
}
function __distruct()
{
foreach (self::$list as $class)
unset(self::$list);
}
}
$staticInstances = new staticInstances();
spl_autoload_register(function ($class)
{
...
if ($isStatic) staticInstances::add($class);
...
});

Categories