czwartek, 6 czerwca 2019

#1 PHP Errors & Exceptions - obiekty i klasy

  • PHP 7.3
  • bez deklarowania strict_types=1

Klasy i obiekty


FATAL ERROR - Instancjonowanie nieistniejącej klasy
new Example();
// Fatal Error: Uncaught Error: Class 'Example' not found

// -----------------------------------------
class Example {}

FATAL ERROR - Wywołanie nieistniejącej metody (ze statyczną jest tak samo)
(new Example())->doesntExists();
/Fatal Error: Uncaught Error: Call to undefined method Example::doesntExists()


FATAL ERROR - Wywołanie nieistniejącego pola statycznego
Example::$nonExistentProperty;
// Fatal Error: Uncaught Error: Access to undeclared static property: Example::$nonExistentProperty

NOTICE - Wywołanie nieistniejącego pola 
(new Example)->nonExistentProperty;
// Notice: Undefined property: Example::$nonExistentProperty

// trochę inaczej

NOTICE NOTICE - Ciekawy przykład zahaczający o Variable variables
class Example {
public $a = 5;
}
echo (new Example)->$a;
// Notice: Undefined variable: a
// Notice: Undefined property: Example::$

Jak wiadomo pierwszy Notice nie przerywa wykonywania kodu więc jak interpreter próbuje wywołać zmienną nic to okazuje się że nie ma pola nic klasy Example 

// -----------------------------------------

FATAL ERROR - Wywołanie pola prywatnego (z protected tak samo)
class Example { private $a = 5; }
(new Example)->a;
// Fatal Error: Uncaught Error: Cannot access private property Example::$a

FATAL ERROR - Wywołanie funkcji prywatnej (z protected tak samo)
class Example { private function foo() {} }
(new Example)->foo();
// Fatal Error: Uncaught Error: Call to private method Example::foo() from context

// -------- PHP 4 style constructor --------

class Example {
  public $a = 1;
function Example($a) {
$this->a = $a;
}
}

echo (new Example(2))->a; // 2


Powyższe wywołanie w PHP wersji 7.x powinno zwrócić E_DEPRECATED (jeżeli w klasie nie jest zadeklarowany __construct()) - ale co mnie dziwi - w przypadku moich testów, stary styl konstruktora klasy po prostu zadziałał bezbłędnie. Takiego komunikatu się spodziewałem: 


Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; Example has a deprecated constructor

Więcej na:

https://www.php.net/manual/en/migration70.deprecated.php

// -----------------------------------------
DEPRECATED FATAL ERROR - Wywołanie metody z $this w statyczny sposób
class Example {
public $a = 1;
function foo() {
echo $this->a;
}
}
Example::foo();
// Deprecated: Non-static method Example::foo() should not be called statically 
// Fatal Error: Uncaught Error: Using $this when not in object context

// -----------------------------------------
FATAL ERROR - Wywołanie nieistniejącej stałej klasy
class Example {}
echo Example::NON_EXISTEN_CONST;
// Fatal Error: Uncaught Error: Undefined class constant 'NON_EXISTEN_CONST'
// -----------------------------------------
RECOVERABLE ERROR - Kastowanie obiektu na string gdy jego klasa nie ma zaimplementowanej metody magiczne __toString()
class Example {}
$recoverable = new Example();
echo (string)$recoverable;
// Recoverable fatal error: Object of class Example could not be converted to string

RECOVERABLE ERROR - Kastowanie obiektu na string (poprzez wyświetlenie go konstruktem echogdy jego klasa ma zaimplementowaną metodę magiczną __toString() zwracającą integer
class Example {
public function __toString() {
return 1;
}
}
$recoverable = new Example();
echo $recoverable;
// Recoverable fatal error: Method Example::__toString() must return a string value

  • E_RECOVERABLE_ERROR (4094) (od wersji 5.2) - Fatal Error do przechwycenia. Określa prawdopodobnie groźną sytuację, ale nie pozostawia silnika PHP w niestabilnym stanie. Jeżeli programista nie napisał własnego handlera do obsługi błędu (set_error_handler()) to program przerwie wykonywanie jak w przypadku E_ERROR. Warto nadmienić że w PHP 5.x powodowało to z mety zatrzymanie skryptu, od wersji 7.0 się to jednak zmieniło.


// słowo kluczowe final... i nie tylko -----
FATAL ERROR - Dziedziczenie po klasie finalnej gdzie istotny czynnik odgrywa fakt, że klasa rodzica korzysta z nazwy zarezerwowanej (tak samo ze słowem kluczowym self)
final class Parent {}
class Child extends Parent {}
Fatal error: Cannot use 'Parent' as class name as it is reserved
Generuje błąd nie do przechwycenia. 

FATAL ERROR - Wywołanie nieistniejącej stałej klasy
final class Parent1 {}
class Child extends Parent1 {}
// Fatal error: Class Child may not inherit from final class (Parent1)
Generuje błąd nie do przechwycenia. 





Brak komentarzy:

Prześlij komentarz