function addTwoIntegers($value1, $value2) {
return $value1 + $value2;
}
echo addTwoIntegers(1, 2); // 3
Pana aici, nimic nu pare nou, dupa cum putem observa, am creat functia addTwoIntegers()
functie ce are doua argumente, reprezentand valorile ce vor fi adunate, returnand rezultatul.
Sa presupunem ca aceasta functie accepta doar valori ce au tipul de date integer
, ceea ce inseamna, ca in interiorul functiei trebuie sa facem niste modificari pentru a fi siguri ca parametrii introdusi au tipul de date acceptat, astfel, avem:
function addTwoIntegers($value1, $value2) {
if (!is_int($vakue1) || !is_int($value2)) {
die('Functia addTwoIntegers() accepta doar valori de tip integers');
}
return $value1 + $value2;
}
echo addTwoIntegers(1, "sdsd"); // se executa acel die
Observam ca in interiorul functiei addTwoIntegers()
facem aceste verificari, ceea ce inseamna ceva cod in plus, insa, PHP 7 a introdus posibilitatea de a specifica tipul de date acceptat de fiecare argument al unei functii, astfel putem face:
function addTwoIntegers(int $value1, int $value2) {
return $value1 + $value2;
}
echo addTwoIntegers(1, 2);
Interesant, folosind aceasta noua sintaxa, am scapat de acel bloc de cod necesar verificarii tipului de date.Dupa cum putem observa, am adaugat acel int
, reprezentand tipul de date integer
, in fata argumentelor.Acest lucru face ca acele argumente sa poata avea doar valori ce au tipul de date integer
sau numere intregi.
Evident, putem specifica si celelalte tipuri de date scalare ( integer, string, bool, float ).
function sayName(string $name) {
return $name;
}
echo sayName('Catalin'); // Catalin
function isOnline(bool $online) {
return $online;
}
isOnline(true);
function addTwoFloats(float $value1, float $value2) {
return $value1 + $value2;
}
echo addTwoFloats(15.7, 13.4); // 29.1
Trebuie sa retinam ca PHP poate converti tipul de date al unui parametru, pentru a satisface tipul de date al argumentului functiei.Astfel, daca un argument are nevoie de o valoare ce are tipul de date string
iar noi vom introduce un integer
pentru acel argument, valoarea va fi convertita ( daca se poate ) in string
, astfel avem:
function getFullName(string $fullName) {
return $fullName;
}
echo getFullName(13232); // 13232
PHP va converti integer in string si orice alt tip de date scalar in bool.De asemenea, va incerca sa converteasca string in integer daca valoarea string incepe cu o cifra.
Cum putem evita astfel de situatii?
Ei bine, putem folosi modul strict
prin adaugarea directivei declare(strict_types=1);
pe primul rand dupa tag-ul PHP de deschidere.
<?php
declare(strict_types=1);
function getFullName(string $fullName) {
return $fullName;
}
echo getFullName(13232); // o eroare fatal va fi emisa
PHP 5 ofera de asemenea posibilitatea de a specifica tipul de date al argumentelor pentru array si object
Putem merge chiar mai departe, astfel, putem folosi si tipuri de date array
si object
( din PHP 5 in sus )
function addTasks(array $tasks) {
//...
}
In ceea ce priveste tipul de date object
, trebuie sa folosim o alta abordare:
class User
{
protected $name;
public function setName(string $name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
}
class Mail
{
protected $message;
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function setMessage(string $message)
{
$this->message = $message;
}
public function send()
{
//...
}
}
$user = new User;
$mail = new Mail($user);
$mail->setMessage('Hello from Catalin');
$mail->send();
Am creat un exemplu foarte simplu.Dupa cum putem observa, in functia constructor a clasei Mail
, am speficicat ca argumentul $user
accepta doar instante ( obiecte ), ce sunt de tipul User
, ale clasei User
.
public function __construct(User $user)
{
$this->user = $user;
}
Ce se intampla daca se introduce o valoare ce are un tip de date diferit de cel specificat in semnatura functiei/metodei?
function getNumber(int $number) {
return $number;
}
echo getNumber("Cata");
Ei bine, PHP 7 va emite o eroare fatala, specificand mai multe detalii despre aceasta eroare, Fatal error: Uncaught TypeError: Argument 1 passed to getNumber() must be of the type integer, string given
Ce beneficii avem daca specificam tipul de date al argumentelor unei functii/metode?
Ei bine, se intelege de la sine, evitam scrierea unei portiuni de cod pentru a verifica daca parametrii au tipul de date necesar.Mai mult decat atat, codul scris devine mai sigur, astfel evitand tot felul de erori cauzate de introducerea unor alte valori decat cele necesare functionarii functiei/metodei.
Alte beneficii aduse
Ei bine, atunci cand vorbim de OOP, putem specifica chiar si interfete sau clase abstracte ca tip de date necesar argumentelor metodelor, astfel putem avea:
interface SocialAdapter
{
public function postStatus(string $status);
}
class TwitterAdaptar implements SocialAdapter
{
protected $twitter;
public function __construct(Twitter $twitter)
{
$this->twitter = $twitter;
}
public function postStatus(string $status)
{
$this->twitter->sendStatusMessage($status);
}
}
class UserController
{
protected $socialStream;
public function __construct(SocialAdapter $socialStream)
{
$this->socialStream = $socialStream;
}
public function sendSocialMessage(string $message)
{
$this->socialStream->postStatus($message);
}
}
// aceasta clasa face partea din libraria oferita de twitter
$twitter = new Twitter();
$twitterAdaptaer = new TwitterAdapter($twitter);
$userController = new UserController($twitterAdapter);
$userController->sendSocialMessage("Helloooo");
Dupa cum putem observa, in functia constructor a clasei UserController
am specificat ca tipul de date al argumentului $socialStream
sa fie SocialAdapter
ce este chiar interfata creata de noi.Astfel, acel argument accepta valori ce sunt instante ale claselor ce implementeaza interfata SocialAdapter
.Folosind aceasta tehnica, codul devine mult mai flexibil, putem schimba clasa TwitterAdapter
cu o alta clasa, sa zicem FacebookAdapter
, implementand aceeasi interfata, SocialAdapter
, clasa UserController
tot va functiona, ea asteapta o instanta a unei clase ce implementeaza interfata SocialAdapter
.Apropo, mai sus am folosit modelul de design adaptor, probabil o sa vorbim mai pe larg despre el intr-un alt articol.
Putem specifica tipul de date al valorii returnate de o functie/metoda?
Da, putem face si acest lucru, PHP 7 ne ofera posibilitatea de a specifica si ce tip de date o functie/metoda poate returna.
function getNumber(int $value) : int {
return $value;
}
echo getNumber(10); // 10
Prin adaugarea : int
dupa semnatura functiei, am specificat ca aceasta functie va returna valori ce au tipul de date integer
, foarte simplu si clar.
Pentru celelalte tipuri de date scalare putem folosi aceeasi sintaxa.
Daca functia/metoda returneaza o valoare ce are un tip de date diferit de cel specificat, o eroare fatala va fi emisa, spre exemplu:
function getNumber(int $value) : int {
return "Your number is {$value}";
}
echo getNumber(10);
FATAL ERROR Uncaught TypeError: Return value of getNumber() must be of the type integer, string returned
Trebuie sa retinam ca si atunci cand specificam tipul de date pe care o functie il poate returna, PHP va incerca sa converteaca valoarea returnata ( daca nu are tipul de date necesar ) pentru a respecta tipul de date ales.
Ei bine, cam atat cu acest tutorial, sfatul meu este sa folositi PHP 7 si noile functionalitati aduse, codul scris va fi mult imbunatatit si mult mai clar.