Before questions or criticisms arise, it is not possible to do this, simply because static methods do not have access to public, private, and protected variables and methods, because they are accessible even without an instance of the class, I just say that, this I already know.
It happens that at the moment it's starting to bother me a little bit the simple fact that you always have to instantiate a new class by using keyword new at all times, because sometimes I'm forced to run like this.
Let's look at, for example:
<?php
class Teste {
const EU = "<b>Disse ele:</b>\n";
public function eu(){
return self::EU . $this->ele();
}
private function ele(){
return 'Pertenço a 3º pessoa';
}
}
$teste = new Teste();
print $teste->eu();
?>
The first method is public only, and has access to both public, private, and protected class properties and methods, without any problems.
Next we have this:
class Teste1 {
const EU = "<b>Disse ele:</b>\n";
public static function eu(){
return self::EU . $this->ele();
}
private function ele(){
return 'Pertenço à 3º pessoa';
}
}
print Teste1::eu();
What this will return is already obvious:
Fatal error: Using $ this when not in object context in ...
Doing this:
<?php
class Teste1 {
static $instance;
const EU = "<b>Disse ele:</b>\n";
public static function get(){
if(empty(self::$instance)):
self::$instance = new Teste1();
endif;
return self::$instance;
}
public static function eu(){
return self::EU . self::$instance->ele();
}
private function ele(){
return 'Pertenço à 3º pessoa';
}
}
print Teste1::get()->eu();
?>
You can work around the situation, that is, it is not exactly bypass, since you create an instance using keyword%, but it works, and automates the rest. The examples I have just given may not explain exactly why I need to avoid using new
, but perhaps these two examples explain why.
The only reason that makes me want this is that in my classes, not all methods are / should be accessible even with an instance of this class, because they are only complementary methods / articulations to the static methods that I am creating, in a class with about 10 methods, only 3 of them are accessible, and the type of access I want for this average of 3 methods is direct access, without any previous instance.
1st Example - Expected:
<?php
class Hash {
static $hash;
const COST = "$2y$10$";
public static function hash_create($password){
return crypt($password, $this->salt(self::COST)); # <--- $this
}
public static function hash_verify($password, $db_hash){
$hash = crypt($password, $db_hash);
return $this->are_equal($hash, $db_hash); # <--- $this
}
// métodos projectados apenas para uso interno
private function random(){
return md5(uniqid(), true);
}
private function fix_random($random){
$encode = base64_encode($random);
return str_replace("+", ".", $encode);
}
private function half_salt($size=null){
$size = empty($size) ? 22 : $size;
return substr($this->fix_random($this->random()), 0, $size);
}
private function salt($cost){
return $cost.$this->half_salt();
}
private function are_equal($x, $y){
if($x === $y):
return true;
else:
return false;
endif;
}
}
## 3º Método - PRETENDIDO (nada será executado) ##
print Hash::hash_create('password');
print "<br/>";
$db_hash = Hash::hash_create('password');
var_dump(Hash::hash_verify('password', $db_hash)); # (null);
?>
2nd Example - The (forced) track:
<?php
class Hash {
static $hash;
const COST = "$2y$10$";
# 1º notação
public function create($password){
return crypt($password, $this->salt(self::COST));
}
public function verify($password, $db_hash){
$hash = crypt($password, $db_hash);
return $this->are_equal($hash, $db_hash);
}
// métodos projectados apenas para uso interno
private function random(){
return md5(uniqid(), true);
}
private function fix_random($random){
$encode = base64_encode($random);
return str_replace("+", ".", $encode);
}
private function half_salt($size=null){
$size = empty($size) ? 22 : $size;
return substr($this->fix_random($this->random()), 0, $size);
}
private function salt($cost){
return $cost.$this->half_salt();
}
private function are_equal($x, $y){
if($x === $y):
return true;
else:
return false;
endif;
}
}
## 1º Método - NORMAL ##
$hash = new Hash(); # <---
print $hash->create('password');
print "<br/>";
$db_hash = $hash->create('password');
var_dump($hash->verify('password', $db_hash)); # (true);
?>
This above, although it works, does exactly what I want to avoid, yet it's the right one.
3rd Example - HACK (The solution I found)
<?php
class Hash {
static $hash;
const COST = "$2y$10$";
public static function instance(){
if(empty(self::$hash)){
self::$hash = $self = new Hash();
}
return self::$hash;
}
# 2º notação
public static function hash_create($password){
return crypt($password, self::$hash->salt(self::COST));
}
public static function hash_verify($password, $db_hash){
$hash = crypt($password, $db_hash);
return self::$hash->are_equal($hash, $db_hash);
}
// métodos projectados apenas para uso interno
private function random(){
return md5(uniqid(), true);
}
private function fix_random($random){
$encode = base64_encode($random);
return str_replace("+", ".", $encode);
}
private function half_salt($size=null){
$size = empty($size) ? 22 : $size;
return substr($this->fix_random($this->random()), 0, $size);
}
private function salt($cost){
return $cost.$this->half_salt();
}
private function are_equal($x, $y){
if($x === $y):
return true;
else:
return false;
endif;
}
}
## 2º Método - HACK ##
print Hash::instance()->hash_create('password');
print "<br/>";
$db_hash = Hash::hash_create('password');
var_dump(Hash::hash_verify('password', $db_hash)); # (true);
?>
Although it works, and basically giving me what I want, hacks are not really my strong, and I worry too much about good practices. Once this solution is adopted, what evils will I forget? Is it really acceptable? I say, because sometimes, when we create a solution we also create new problems.