Php-adgang til et objektelement. Objektorienteret programmering i PHP

Hej alle! I denne artikel vil vi se på forskellen mellem nulstil.css Og normalisere.css og finde ud af, hvad der er bedst at bruge.

Så det er ingen hemmelighed, at browsere viser sider anderledes. Men vi har brug for kompatibilitet på tværs af browsere, dvs. identisk sidevisning i alle browsere af alle versioner. For at løse dette problem blev det opfundet nulstil.css.

RESET.CSS - en fil, der viser alle mulige tags html og deres værdier nulstilles. På denne måde vil du ikke have nogen indrykning, alle afsnit, overskrifter osv. vil blive vist i samme skrifttype og størrelse. Alt du skal gøre er at oprette forbindelse nulstil.cssøverst på siden og medtag derefter din stilfil.

NORMALIZE.CSS er en fil, hvor stilene for hvert tag ikke nulstilles, men normaliseres, dvs. Indrykninger, afsnit, overskrifter osv. bringes til standarden. I dette tilfælde behøver du ikke længere at omskrive alle styles, hvilket naturligvis sparer tid.

Ingen vil give dig et specifikt svar på, hvad du skal bruge. Dette er et spørgsmål om smag, alt efter hvad der passer dig bedst. Som regel udvikler layoutdesignere deres egen efter nogen tids brug af den første eller anden fil.

Så det er det. Tak for din opmærksomhed og held og lykke!

I denne tutorial lærer du det grundlæggende i objektorienteret programmering i PHP. Du vil lære om principperne for OOP generelt og lære at skrive simple scripts i PHP.

Velkommen til den første i rækken af ​​lektioner om OOP i PHP! Efter at have gennemført alle lektionerne i denne serie, vil du lære om de grundlæggende principper og begreber i OOP og lære, hvordan du hurtigt og nemt opretter nyttige applikationer i PHP.

I denne tutorial vil jeg begynde at få dig op at køre og fortælle dig om de grundlæggende begreber i OOP. Du vil lære:

  • hvad er OOP
  • hvordan OOP vil hjælpe dig med at skabe bedre PHP-scripts
  • nogle grundlæggende begreber som klasser, objekter, metoder, klassevariable
  • hvor skal man begynde at skrive et PHP-script

Er du klar til at dykke ned i PHP-objekternes verden? Så gå videre!

Hvad er objektorienteret programmering?

Hvis du nogensinde har oprettet og brugt brugerdefinerede funktioner i PHP, har du brugt en proceduremæssig programmeringsstil. I proceduremæssig programmering opretter man typisk datastrukturer - tal, strenge, arrays mv. - at gemme nogle data, og derefter behandle disse strukturer med specielle funktioner, der manipulerer disse data.

Objektorienteret programmering, eller OOP, er rykket frem, fordi vi her gemmer datastrukturer og de funktioner, der behandler dem i en enkelt enhed kaldet et objekt. I stedet for at behandle dataene med en eller anden funktion, indlæser du disse data i et objekt og kalder derefter dets metoder til at manipulere det og få det ønskede resultat.

Oftest afspejler objekter oprettet ved hjælp af OOP virkelige enheder. For eksempel, hvis du opretter et forum for dit websted, vil du oprette et medlemsobjekt, der gemmer oplysninger om hvert forummedlem (navn, login, e-mail, adgangskode osv.), samt metoder, der behandler disse oplysninger ( registrering, autorisation, logout, forbud osv.).

Hvorfor bruge OOP?

Procedurel og objektorienteret er to forskellige måder at gøre det samme på. Dermed ikke sagt, at den ene af dem er bedre end den anden – alle skriver som de vil, så du kan endda nemt kombinere disse to tilgange i ét manuskript.

Men her er nogle fordele ved OOP for udviklere:

  • Det er nemmere at afspejle virkelige situationer: Som jeg bemærkede ovenfor, afspejler objekter virkelige enheder - mennesker, produkter, kort, blogartikler osv. Dette forenkler opgaven i høj grad, når du lige er begyndt at designe din applikation, da formålet med hvert objekt er som et mål forhold mellem objekter vil være klare og forståelige.
  • Det er lettere at skrive modulære programmer: OOP involverer at skrive moduler. Ved at opdele din kode i moduler bliver det nemmere for dig at administrere, fejlsøge og udvide den.
  • Det er nemmere at skrive kode, der vil blive brugt mange gange: At skrive kode, der kan bruges mere end én gang, vil spare tid, når du skriver en applikation, og over tid kan du endda oprette et helt bibliotek af den slags moduler, som du kan bruge i mange applikationer. Med OOP bliver det forholdsvis nemmere at skrive sådan kode, da datastrukturerne og funktionerne er indkapslet i et enkelt objekt, der kan bruges et vilkårligt antal gange.

Nogle grundlæggende koncepter

Før du begynder at skrive scripts, skal du have en god forståelse af begreberne klasse, objekt, klassevariabel og metode.

Klasser

En klasse er en ramme for et objekt. Dette er et stykke kode, der definerer:

  • Datatyper, som de oprettede klasseobjekter vil indeholde
  • Funktioner, der vil indeholde disse objekter.

Når du opretter en OOP-applikation, vil du normalt oprette flere klasser, der repræsenterer de forskellige typer entiteter i din applikation. For at oprette et forum kan du f.eks. oprette klasserne Forum, Emne, Indlæg og Medlem.

Objekter

Et objekt er en speciel type variabel, der oprettes gennem en klasse. Den indeholder faktiske data og funktioner til at manipulere dem. Du kan oprette så mange objekter, du vil, fra en enkelt klasse. Hver funktion af et objekt er uafhængig af et andet objekt, selvom de er oprettet fra den samme klasse.

Til sammenligning med virkelige enheder:

  • En klasse er rammen for en bil: den definerer, hvordan bilen vil se ud og agere, men den er stadig en abstrakt enhed
  • Et objekt er en rigtig bil skabt af en wireframe: den har virkelige egenskaber (såsom hastighed) og adfærd (såsom acceleration eller bremsning).

Bemærk: Et objekt kaldes ofte essensen af ​​en klasse, og processen med at skabe et objekt af en klasse kaldes en implementering.

Klassevariabler

Dataværdierne, der er gemt i et bestemt objekt, skrives til specielle variabler kaldet klassevariabler. Klassevariabler er tæt forbundet med dets objekt. Selvom alle objekter i en klasse har de samme variabler, kan deres værdier variere.

Metoder

Funktioner defineret i en klasse og brugt på objekter i den klasse kaldes metoder. De er ikke meget forskellige fra almindelige funktioner - du kan sende værdier til dem, de kan indeholde lokale variabler og returnere værdier. Metoder arbejder dog oftere med objektvariabler. For eksempel kan login()-metoden til at logge brugere på dit forum indstille klassen logdIn-variablen til true.

Hvordan opretter man en klasse i PHP?

Nu hvor du allerede ved, hvad klasser, metoder, klassevariabler og objekter er, er det tid til at oprette et par klasser og objekter i PHP-kode.

Lad os først se på, hvordan man rent faktisk opretter en klasse. Grundlæggende ser scriptet til at oprette en klasse sådan ud:

Klasse Klassenavn ( // (klassedefinition) )

For eksempel, hvis du opretter en medlemsklasse til dit forum, vil du skrive dette:

Klassemedlem ( // (klassedefinition) )

Det er ret simpelt. Naturligvis vil denne klasse ikke gøre noget, før du tilføjer variabler og metoder til den. Ovenstående kode opretter dog en gyldig PHP-klasse, som kan bruges.

En god tommelfingerregel: placer hver klasse i en separat fil med samme navn som klassenavnet. Indsæt for eksempel Member-klassen i Member.php-filen og gem den i en mappe, f.eks. klasser.

Hvordan opretter man objekter i PHP?

Du kan oprette et objekt ved hjælp af det nye nøgleord:

Nyt klassenavn()

Denne kode vil oprette et objekt af klassen ClassName. Du skal bruge dette objekt senere, så du skal gemme det i en variabel. Lad os for eksempel oprette et objekt af klassen Member og gemme det i $member-variablen:

$medlem = nyt medlem();

Vi kan også oprette et andet objekt af samme klasse:

$medlem2 = nyt medlem();

Selvom vi har oprettet disse to objekter fra samme klasse, er variablerne $member og $member2 uafhængige af hinanden.

Oprettelse af klassevariabler

Nu hvor vi allerede ved, hvordan man opretter klasser og klasseobjekter, lad os se på, hvordan man opretter klassevariabler. Der er 3 accessorer til klassevariabler, der kan tilføjes til en klasse:

  • Offentlige klassevariabler (offentlige): tilgængelige - dvs. de kan læses og/eller ændres - hvor som helst i scriptet, uanset hvor denne kode er placeret - inde i klassen eller uden for den
  • Private klassevariabler (private): kun tilgængelige for klassemetoder. Det er bedst at gøre klassevariabler private for at adskille objekter fra resten af ​​koden.
  • Beskyttede klassevariabler: Tilgængelige for metoder i din egen klasse, såvel som for metoder til nedarvede klasser (vi taler om nedarvning senere).

For at oprette en klassevariabel skal du skrive nøgleordet offentlig, privat eller beskyttet og derefter indtaste navnet på variablen:

Klasse Klassenavn (offentlig $propertyName; privat $propertyName; beskyttet $propertyName;)

Lad os tilføje en offentlig klassevariabel til vores medlemsklasse for at gemme brugernavnet:

Klassemedlem (offentlig $username = ""; )

Bemærk, at vi har initialiseret vores klassevariabel, dens værdi er den tomme streng, "". Det betyder, at når en ny bruger oprettes, vil brugernavnet som standard være den tomme streng. Ligesom i tilfældet med almindelige variabler i PHP, skal klassevariabler ikke initialiseres, men det er bedre ikke at være doven. Hvis du ikke initialiserer en klassevariabel, er dens standardværdi null.

Adgang til klassevariabler

For at få adgang til en variabel af et objekt, brug -> operatoren:

$objekt->egenskabsnavn

Lad os prøve. Lad os skrive et script, der erklærer en medlemsklasse og en klassevariabel, opretter et objekt af denne klasse og derefter indstiller værdien af ​​klassevariablen og viser den på skærmen:

brugernavn = "Fred"; echo $medlem->brugernavn; // Udskriv "Fred" ?>

Kør denne kode, den vil vise strengen "Fred", værdien af ​​klassevariablen $member->username. Som du kan se, opererer du på en objektvariabel ligesom en almindelig variabel - du kan indstille den til en værdi og læse den.

Tilføjelse af metoder til en klasse

Hvad med at skabe metoder? Som jeg nævnte tidligere, er metoder bare almindelige funktioner, der er en del af en klasse. Så du bliver måske ikke overrasket over, at de er oprettet ved hjælp af det samme funktionsnøgleord. Den eneste forskel fra at oprette almindelige funktioner er, at du også kan tilføje en af ​​adgangsidentifikatorerne (offentlig, privat, beskyttet) til dens erklæring. På denne måde ligner metoder klassevariabler:

Klasse Klassenavn ( offentlig funktion metodeNavn() ( // (kode) ) privat funktion metodeNavn() ( // (kode) ) beskyttet funktion metodeNavn() ( // (kode) ) )

Bemærk: ligesom i tilfældet med klassevariabler, kan offentlige metoder kaldes fra hvor som helst, private metoder kan kun kaldes inden for klassen, og beskyttede metoder kan kaldes fra selve klassen og dens efterkommer.

Lad os prøve at tilføje nogle metoder og klassevariabler til vores klasse:

  • private $loggedIn klassevariabel for at identificere brugeren, dvs. om han kom ind eller ej,
  • login()-metoden, som vil logge ind på forummet ved at indstille klassevariablen $loggedIn til sand,
  • logout()-metoden, som vil logge ud af forummet ved at sætte klassevariablen $loggedIn til false,
  • isLoggedIn() metode, som returnerer værdien af ​​klassevariablen $loggedIn.

Her er vores kode:

loggetIn = sand; ) public function logout() ( $this->loggedIn = false; ) public function isLoggedIn() ( return $this->loggedIn; ) ) ?>

Du har måske bemærket, at vi brugte et nyt $this søgeord. I sammenhæng med et objekts metoder refererer den specielle variabel $this til selve objektet. Ved at bruge $this i en objektmetode kan metoden få adgang til enhver klassevariabel og metode for objektet.

For eksempel kan login()-metoden få adgang til objektets $loggedIn-klassevariabel via $this->loggedIn.

Vores klassevariabel er i øvrigt privat, så den kan ikke kaldes fra nogen del af scriptet, men kun fra login(), logout() og isLoggedIn() metoderne. Dette er en god tilgang, fordi det indre af objektet (såsom præcis hvordan det registrerer, om brugeren er logget ind eller ej) er adskilt fra resten af ​​koden. Når det er muligt, så prøv at bruge private klassevariabler, så dine objekter er autonome, mobile og beskyttede.

Bemærk: klassevariablen $username i vores eksempel er offentlig. Jeg gjorde dette bare for at demonstrere, hvordan du kan få adgang til et objekts klassevariabler. I rigtige projekter vil du hellere gøre denne variabel privat og oprette specielle offentlige klassevariabler for at indstille brugernavnsværdier, hvis det er nødvendigt.

Brug af metoder

For at kalde en metode på et objekt skal du bruge operatoren ->, som du allerede er blevet fortrolig med.

$object->methodName()

Dette fungerer ligesom at kalde en almindelig funktion. Du kan sende argumenter i parentes (forudsat at det kræver alle argumenter selvfølgelig), og metodekaldet kan også returnere specifikke værdier, som du derefter kan bruge.

loggetIn = sand; ) public function logout() ( $this->loggedIn = false; ) public function isLoggedIn() ( return $this->loggedIn; ) ) $medlem = nyt medlem(); $member->username = "Fred"; echo $member->brugernavn . "er". ($medlem->
"; $member->login(); echo $member->brugernavn . " er " . ($member->isLoggedIn() ? "logged in" : "logged out") . "
"; $member->logout(); echo $member->brugernavn . " er " . ($member->isLoggedIn() ? "logged in" : "logged out") . "
"; ?>

Dette script vil vise følgende:

Fred er logget ud Fred er logget ind Fred er logget ud

Sådan fungerer det:

  1. Efter at have beskrevet Member-klassen oprettede vi dens objekt og gemte det i $member-variablen. Vi gav også klassevariablen $brugernavn for dette objekt værdien "Fred".
  2. Vi kaldte derefter $member->isLoggedIn() metoden for at bestemme, om brugeren er logget ind eller ej. Denne metode returnerer simpelthen værdien af ​​klassevariablen $loggedIn. Da standardværdien for denne klassevariabel er falsk, vil resultatet af at kalde $member->isLoggedIn() være falsk, så meddelelsen "Fred er logget ud" vil blive vist.
  3. Så kalder vi login() metoden. Det vil sætte klassevariablen $loggedIn til sand.
  4. Nu, når du kalder $member->isLoggedIn() metoden, vil den returnere true og vise beskeden "Fred er logget på".
  5. Lad os kalde logout()-metoden, som sætter værdien af ​​$loggedIn-egenskaben til false.
  6. Lad os kalde $member->isLoggedIn() metoden en tredje gang. Det vil nu returnere false, fordi $loggedIn-egenskaben er sat til false igen. Så beskeden "Fred er logget ud" vil blive vist igen.

Bemærk: hvis du så dette først: ?: er en ternær operator. Dette er en forenklet version af if...else-blokke. Du kan lære om disse typer operatører.

konklusioner

I denne tutorial lærte du det grundlæggende i OOP i PHP. Du lærte om ting som:

  • Hvad er OOP, og hvorfor er det nyttigt?
  • begreber om klasser, objekter, klassevariabler og metoder
  • hvordan man opretter klasser og objekter
  • hvordan man opretter og bruger klassevariabler
  • koncepter for offentlige, private, beskyttede adgangsidentifikatorer
  • hvordan man opretter og bruger klassemetoder

Du har allerede lært meget om det, og du vil lære meget mere i de følgende lektioner. Men hvis du har gennemarbejdet alle de eksempler, jeg har givet, har du et solidt fundament. Du kan begynde at oprette applikationer ved hjælp af OOP.

JavaScript er blokeret i din browser. Aktiver venligst JavaScript for at siden kan fungere!

Objekt programmering

Objektorienteret programmering (OOP) i PHP

Et objekt er en samling af specielle variable - ejendomme og specielle funktioner - metoder. Det, der blev kaldt en variabel i proceduremæssig programmering, kaldes en egenskab i OOP. Det, der blev kaldt en funktion i proceduremæssig programmering, kaldes en klassemetode i OOP. Objekter oprettet fra en klasse kaldes forekomster af klassen eller blot objekter.

Adgang til egenskaber fra en metode kun gennem $this serviceord: $this->name; (bemærk fraværet af et dollartegn før navn) At kalde en anden metode inde i en metode er også via $this: $this->foo(); For at få adgang til et objekts egenskaber og metoder, brug "->" operatoren: $this->name; (bemærk manglen på et dollartegn før navn)
At kalde en anden metode inde i en metode er også via $this: $this->foo(); . Et objekt oprettes ved hjælp af operatoren ny baseret på en skabelon kaldet klasse. Klassen er defineret af nøgleordet klasse.

Eksempel 1

Klasse med egenskab og metode ".$this->name."! Hej!"; ) funktion While($a) ( $this->name = $a; echo "

".$this->name."! Farvel!

"; ) ) $obj = new classN1(); $obj->Hej(); $obj->name = "Misha"; $obj->Hej(); $obj->Bye("Yasha"); $ obj->Hej();

Adgangsmodifikatorer i OOP:

  • offentlig- giver dig adgang til egenskaber og metoder fra hvor som helst (globalt omfang)
  • beskyttet- adgang til den overordnede og nedarvede klasse (efterfølgerklasseområde)
  • privat- kun adgang fra den klasse, hvori selve elementet er erklæret (omfanget af selve klassen)
Standardmetoden er offentlig. Egenskaber har ikke en standardmodifikatorværdi.

Klassekonstanter i OOP

const NAVN = 2; På denne måde kan du skabe konstanter uden for klassen. Disse er klassekonstanter, de hører ikke til noget objekt, de er fælles for alle objekter, så ved at bruge inde i en metode: funktion printname() ( echo self::NAME; ) self er selve klassen! Kald uden for klassen (kan kaldes fra det globale omfang uden at initialisere en klasseinstans): echo OurClass::NAME;

dette og mig selv

En speciel variabel bruges inde i klassen det her. Det er en pointer, hvormed et objekt kan henvise til sig selv.

For at få adgang til statiske metoder, brug selv::

Mens metoden videregives et argument på samme måde som en almindelig funktion. Når denne metode kaldes, ændrer objektet sin navnegenskab.

RESULTAT AF EKSEMPEL 1:

Masha! Hej!

Misha! Hej!

Yasha! Farvel!

Yasha! Hej!

En konstruktør er en metode, der automatisk kaldes, når et nyt objekt oprettes: public function __construct()() . Når et objekt initialiseres6 gennem den nye servicekonstruktion, leder PHP efter __construct, og hvis det findes, kaldes det.

Du kan også oprette en metode, hvis navn er det samme som navnet på klassen - sådan en metode vil også blive betragtet som en konstruktør. Konstruktøren kan tage argumenter, hvilket i høj grad forenkler arbejdet med klasser.

Eksempel 2

Klasse med konstruktør navn = $a; ) funktion Hello() ( echo "

".$this->name."! Hej!

"; ) ) $obj0 = new classN2(); $obj1 = new classN2("Misha"); $obj2 = new classN2("Masha"); $obj0->Hej(); $obj1->Hej(); $obj2->Hej();

RESULTAT AF EKSEMPEL 2:

Nogen er der! Hej!

Misha! Hej!

Masha! Hej!

Ved at lægge alt ovenstående sammen kan du skabe en mere meningsfuld klasse. For eksempel en klasse, der vil arrangere data i form af en tabel med navngivne kolonner.

Eksempel 3

Bordklasse headers = $headers; ) funktion addRow ($row) ( $tmp = ; foreach ($this->headers som $header) ( if (! isset($row[$header])) $row[$header] = ""; $tmp = $row[$header]; array_push($this->
"; foreach ($this->
"; foreach ($this->
"; ) ekko "
"; ) ) $test = ny tabel (array("a","b","c")); $test->addRow(array("a"=>1,"b"=>3,"c "=>2)); $test->addRow(array("b"=>1,"a"=>3)); $test->addRow(array("c"=>1,"b"= >3,"a"=>4)); $test->output();

Egenskaberne for Table-klassen er en række tabelkolonnenavne og en todimensionel række af datarækker. Konstruktøren af ​​Table-klassen modtager en række tabelkolonnenavne. AddRow-metoden tilføjer en ny række data til tabellen. Outputmetoden viser tabellen på skærmen.

RESULTAT AF EKSEMPEL 3:

a b c 1 3 2 3 1 4 3 1

Skjulte egenskaber og metoder

Egenskaber og metoder for en klasse kan enten være åbne (offentlige) eller skjulte (private). Skjulte egenskaber og metoder er ikke tilgængelige uden for klassen, dvs. fra et script, hvor denne klasse bruges, eller fra en anden klasse.

Arv

Baseret på eksisterende klasser kan du oprette nye vha arvemekanisme. Arvemekanismen er brugen af ​​en tidligere defineret klasse som forælder. I dette tilfælde kan sættet af egenskaber og metoder for den overordnede klasse udvides. Husk, at en afledt klasse kun har én forælder.

For at oprette en ny klasse, der arver adfærden fra en eksisterende klasse, skal du bruge nøgleordet extends i dens erklæring. For eksempel:

Klasse klasseN2 udvider klasseN1 ( ....... )

Her er klasseN1 den overordnede klasse, klasseN2 er den afledte klasse.

Hvis en afledt klasse ikke indeholder sin egen konstruktør, så bruges konstruktøren af ​​den overordnede klasse, når dens objekt oprettes. Hvis en afledt klasse har sin egen konstruktør, kaldes den overordnede klasses konstruktør ikke. Hvis du skal kalde konstruktøren af ​​den overordnede klasse, skal dette gøres eksplicit. For eksempel:

KlasseN1::klasseN1();

Den afledte klasse vil have alle egenskaber og metoder for den overordnede klasse. Men de kan også tilsidesættes i en afledt klasse.

Eksempel 4

Tilsidesættelse af en overordnet klassemetode ".$this->name."! Hej!"; ) ) klasse klasseN4 udvider klasseN3 ( funktion Hello() ( echo "

".$this->name."! Hvilket møde!

"; ) ) $obj = new classN4(); $obj->Hej(); ?>

Hello-metoden tilsidesættes for en afledt klasse. Navneegenskaben er arvet fra forælderen.

RESULTAT AF EKSEMPEL 4:

Masha! Hvilket møde!

Fra version 4 af PHP er det muligt at kalde en metode for en overordnet klasse, der er blevet tilsidesat i et objekt af en afledt klasse.

Eksempel 5

Kald en overordnet klassemetode ".$this->name."! Hej!"; ) funktion While() ( echo "

".$this->name.", farvel!

"; ) ) /** * Klasse klasseN6 */ klasse klasseN6 udvider klasseN5 ( /** * */ funktion Hello() ( echo "

".$this->name."! Hvilket møde!

"; classN5::Hej(); ) ) $obj = new classN6(); $obj->Hej(); $obj->Bye(); ?>

RESULTAT AF EKSEMPEL 5:

Masha! Hvilket møde!

Masha! Hej!

Masha, farvel!

Så en afledt klasse kan arve, tilsidesætte og udvide egenskaberne og metoderne for en anden klasse.

Følgende eksempel opretter en HTMLTable-klasse baseret på Table-klassen fra eksempel 3. Den nye klasse tager de data, der er gemt af den overordnede klasses addRow-metode og viser dem i en HTML-tabel. Egenskaberne $cellpadding og $bgcolor giver dig mulighed for at ændre de tilsvarende argumenter, og $cellpadding-variablen får en standardværdi på 2.

Eksempel 6

Tabel og HTMLTable klasser headers = $headers; ) funktion addRow ($row) ( $tmp = ; foreach ($this->headers som $header) ( if (! isset($row[$header])) $row[$header] = ""; $tmp = $row[$header]; ) array_push ($this->data, $tmp ) funktionsoutput () (ekko "
"; foreach ($this->headers som $header) ekko "$header "; echo "
"; foreach ($this->data som $y) (foreach ($y som $x) echo "$x "; echo "
"; ) ekko "
"; ) ) klasse HTMLTable udvider tabeller ( public $cellpadding = "2"; public $bgcolor; function HTMLTable ($headers, $bg="FFFFFF") ( Tables::Tables($headers); $this->bgcolor = $bg; ) funktionssætCellpadding ($padding) ( $this->cellpadding = $padding; ) funktionsudgang () ( echo " cellpadding.""> "; foreach ($this->headers som $header) ekko " "; foreach ($y som $x) ekko"
bgcolor."">".$header; foreach ($this->data som $y) ( echo "
bgcolor."">$x"; ) echo "
"; ) ) $test = ny HTML-tabel (array("a","b","c"), "#00FFFF"); $test->setCellpadding (7); $test->addRow(array("a "=>1,"b"=>3,"c"=>2)); $test->addRow(array("b"=>1,"a"=>3)); $test->addRow (array("c"=>1,"b"=>3,"a"=>4)); $test->output();

Bemærk, at værdien af ​​cellpadding-egenskaben ændres ved hjælp af en separat setCellpadding-metode. Selvfølgelig kan ejendomsværdier ændres direkte uden for objektet:

$test->cellpadding = 7 ;

Men dette betragtes som dårlig form, fordi... i komplekse objekter, når en af ​​egenskaberne ændres, kan andre egenskaber også ændre sig.

RESULTAT AF EKSEMPEL 6:

-enbc
1 3 2
3 1
4 3 1

Skal jeg bruge objektprogrammeringsteknikker eller ej? På den ene side kan et objektintensivt projekt optage for mange ressourcer under kørsel. På den anden side vil en korrekt organiseret objekttilgang reducere udviklingstiden betydeligt og gøre programmet mere fleksibelt.

Sletning af objekter

Du kan slette et tidligere oprettet objekt på følgende måde:

Unset($objName);

Nedenfor er et eksempel, hvor et objekt af klassen Bil oprettes og derefter slettes.

$myCar = ny bil; unset($myCar);

Efter unset() er kaldt, eksisterer objektet ikke længere. PHP har en speciel metode __destruct(), der automatisk kaldes, når et objekt slettes. Nedenfor er klassen, der indeholder denne metode.

Klasse Bridge ( funktion __destruct() ( ekko "Bro ødelagt"; ) ) $bigBridge = ny bro; unset($bigBridge);

Hvis du opretter et Bridge-objekt og derefter sletter det, vil du se følgende meddelelse:

Bro ødelagt

Det vises på grund af kaldet til __destruct()-metoden, når funktionen unset() kaldes. Når du sletter et objekt, skal du muligvis lukke nogle filer eller skrive information til databasen.

Kopiering (kloning) af et objekt

Kloning af et objekt:

$a = klon $b;

Konstruktøren kaldes ikke ved kloning, den magiske metode kaldes __klon()(). Det tager INGEN argumenter og kan ikke tilgås som en metode.

Konvertering af et objekt til en streng

For at konvertere et objekt til en streng og omvendt, bruges følgende funktioner:
serialize()- accepterer et objekt og returnerer en strengrepræsentation af dets klasse og egenskaber;
unserialize()- tager en streng produceret af serialize() og returnerer et objekt.

serialize() og unserialize() virker på alle datatyper, men de virker ikke på ressourcer.


Særlige metoder til at betjene funktionerne serialize() og unserialize():
__søvn()- Kaldes strengt før objektet serialiseres ved hjælp af serialize()-funktionen. Funktionen __sleep() skal returnere en liste over klassens felter, som funktionen serialize() vil inkludere i den returnerede streng. Du kan bruge dette til at udelukke unødvendige felter fra strengrepræsentationen af ​​et objekt. For eksempel:

Offentlig funktion __sleep() ( // clean up return array_keys(get_object_vars($this)); ) __Vågn op()- Kaldes umiddelbart efter objektet er deserialiseret ved hjælp af unserialize().

Abstrakt klasse

Abstrakt klasse er en klasse, der ikke kan instansieres, det vil sige, du kan ikke oprette et objekt af klassen, hvis det er abstrakt. I stedet opretter du børneklasser ud fra det og laver stille og roligt objekter fra disse børneklasser. Abstrakte klasser er skabeloner til at oprette klasser. abstrakt klasse Person ( privat $firstName = ""; privat $lastName = ""; offentlig funktion sætNavn($firstName, $lastName) ( $this->firstName = $firstName; $this->lastName = $lastName; ) offentlig funktion getName() ( returner "$this->firstName $this->lastName"; ) abstrakt offentlig funktion showWelcomeMessage(); er blot dens erklæring Enhver underordnet klasse skal tilføje og beskrive metoden showWelcomeMessage */ .

Interface

Interface er en skabelon, der specificerer adfærden for en eller flere klasser. Her er de vigtigste forskelle mellem grænseflader og abstrakte klasser:

  • Ingen metode kan beskrives i en grænseflade. De er alle abstrakte. En abstrakt klasse kan have ikke-abstrakte metoder.
  • En grænseflade kan ikke indeholde felter - kun metoder.
  • En klasse implementerer en grænseflade, og en klasse arver eller udvider en anden klasse.
  • En klasse kan implementere flere grænseflader på samme tid. Den samme klasse kan arve fra en anden klasse. Men en børneklasse kan kun have én superklasse (abstrakt eller ej).
interface MyInterface ( offentlig funktion aMethod(); offentlig funktion anotherMethod(); ) klasse MyClass implementerer MyInterface ( offentlig funktion aMethod() ( // (metodeimplementering) ) offentlig funktion anotherMethod() ( // (metodeimplementering) ) )

Interceptor-metoder (magiske metoder)

Et eksempel på brug af ikke-erklærede klasseegenskaber

Hvor og hvorfor kan interceptor-metoder bruges?

For eksempel har du en tabel i databasen kaldet bruger, og der er nogle felter i den, for eksempel id, navn, e-mail, telefon, adgangskode, avatar. Og du har oprettet en klasse til at arbejde med brugere, det er, hvad de kaldte den - Bruger

Hvilke egenskaber vil denne klasse have? Hvis du gør det samme som i databasen - id, navn, e-mail og så videre, så viser det sig, at hver gang databasen ændres, skal du ændre koden i User-klassen, da det ikke er særlig praktisk. For eksempel tilføjede du webstedsfeltet, hvilket betyder, at du skal tilføje det til brugerklassen, og så videre.
Ved at bruge metoderne __get() og __set() kan du automatisere alt dette. I din brugerklasse vil du ikke have en eneste egenskab fra databasen, vi har kun én $data - vi tog den dertil og indlæste alt, der er i databasen for denne bruger. Og så, når programmøren anmoder om noget, for eksempel $user->email, kan vi simpelthen kigge i __get() metoden - hvis vi downloadede sådan information fra databasen, og det er i $data["email"] - så her har vi den til dig og returnerer den. Og i __set() er det omvendt. Er der et sådant felt i databasen? Så lad os tildele det en ny betydning.

/** * Klassebruger * @property-read heltal-id for den aktuelle bruger * @property-write String site returnerer et link til brugerens websted */ class User ( private $data; private $f_write=false; public function __set( $navn, $værdi) ($this->data[$name] = $value; $this->f_write=true; // tegn på, at dataene skal gemmes) offentlig funktion __get($name) (hvis (empty($data))( // læs en post fra databasen til data ) returner $this->data[$name] ) funktion __destruct() (if(!empty($data)&&$this->f_write) ( // gem ændringer til databasen ) ) ) $user=ny bruger(); $user->site="http://kdg.site/"; //tildele til variabel echo $user->site; //output værdien af ​​variablen //skriv den til databasen. Du behøver ikke at gøre dette eksplicit, fordi... når scriptet slutter, sker dette automatisk unset($user);

Et eksempel på brug af en ikke-erklæret klasseegenskab som et array-element

Bemærk, at __get returnerer et link:

Klasse Foo (privat $data = ; offentlig funktion __set($navn, $værdi) ($this->data[$navn] = $værdi;) offentlig funktion & __get($navn) (retur $this->data [$ navn]; ) ) $foo = new Foo(); $foo->bar = "lol"; var_dump($foo->bar);

Brug af interceptorer til at få adgang til ikke-erklærede klassemetoder

klasse OurClass ( public function __call($name,array $params) ( ekko "Du ville kalde $Object->".$name.", men det eksisterer ikke, og nu bliver ".__METHOD__."()" udført; return; ) public static funktion __callStatic($name,array $params) (ekko "Du ville kalde ".__CLASS__."::".$name.", men den eksisterer ikke, og ".__METHOD__. "()" udføres i øjeblikket"; return; ) ) $Object=ny OurClass; $Object->DynamicMethod(); OurClass::StaticMethod();

Et eksempel på omgåelse af private klassemetas:

Klasse _byCallStatic( // Et eksempel på omgåelse af de "private" metoder i en klasse, // ved brug af "__callStatic()" metoden til at kalde en statisk metode. public static function __callStatic($_name, $_param) ( return call_user_func_array( "static::". $ _name, $_param ) privat statisk funktion _newCall() ( echo "Method: ". __METHOD__; ) ) echo _byCallStatic::_newCall(114, "Integer", 157); # Resultat: Metode: _byCallStatic::_newCall

Sådan kalder du enhver dynamisk metode gennem en statisk metode:

/** * Klasse o * @metode statisk void __f(int $a1 = 1) */ klasse o (offentlig statisk funktion __callStatic($metode, $args) ( $class = get_called_class(); $obj = new $class( $args); $metode = substr($metode, 2); 1) ( var_dump("oo", func_get_args()); ) ) klasse a udvider o ( offentlig funktion f($a1 = 1, $a2 = 2) ( var_dump(" aa", $a1); ) ) klasse b udvider o (offentlig funktion f($b1 = 1) ( var_dump("bb", $b1); ) ) a::__f(1,2,3); b::__f(4,5,6);

En nyttig beskrivelse af arbejdet med ReflectionClass, når du kan analysere klassens egenskaber og metoder, kontrollere parametre ved hjælp af skabeloner osv.: http://habrahabr.ru/post/139649/

Hvordan bruger man et objekt som en funktion?

klasse Hund ( privat $navn; offentlig funktion __construct($dogName = "Tush") ( $this->name = $dogName; ) offentlig statisk funktion __invoke() ( $args = func_get_args(); ekko "Hund modtaget: " . implode(" og ", $args) ) $dog = new Dog("Mukhtar"); $dog("knogle", "snor");

Hunden fik: en knogle og en snor

Hvordan får man adgang til et objekt som et array?

For at gøre dette skal du oprette et objekt, der implementerer ArrayAccess-grænsefladen fra SPL. Følgende eksempel implementerer et objekt, hvis data kan tilgås både i stil med at få adgang til et array og ved at hente egenskaber:

Class MyArray implementerer ArrayAccess (beskyttet $arr = array(); public function offsetSet($key, $value) ($this->arr[$key] = $value;) public function offsetUnset($key) (unset( $this ->arr[$key] ) public function offsetGet($key) (retur $this->arr[$key]; ) public function offsetExists($key) (retur isset($this->arr[$ key] ); ) public function __get($key) (retur $this->offsetGet($key); ) public function __set($key, $val) ( $this->offsetSet($key, $val);) ) $ a = new MyArray(); $a["whoam"] = "Er jeg værdien af ​​et array eller et objekt?
"; echo $a["whoam"]; echo $a->whoam;

Er jeg værdien af ​​et array eller et objekt? Er jeg værdien af ​​et array eller et objekt?

Autoloading klasser

Autoloading klassefiler er normalt placeret på en fælles placering, såsom /include/class/. Filnavnet er dannet i formatet CLASS_NAME.php. Denne kode skal være inkluderet i alle PHP-scripts: spl_autoload_register(function ($class_name) ( //echo "Autoload ".$class_name; $file = $_SERVER["DOCUMENT_ROOT"] . "/include/class/" . strtolower($ class_name) ".php"; if (fil_exists($file) == false) (if($GLOBALS["DEBUG"]) ekko "Ingen fil ".$fil; return false; ) include_once($file); ;

For at autoloade klasser kan du også bruge funktionsdefinitionen __autoload();

Håndtering af undtagelser i OOP

Undtagelser bruges til at håndtere ikke-kritiske fejl.

Prøv ( $a = 1; $b = 0; if($b == 0) smid ny undtagelse ("division med nul!"); $c = $a/$b; ) catch (undtagelse $e) ( ekko $e->getMessage(); echo $e->getLine();

Undtagelsen er en indbygget klasse. Hvis du rammer kast, bliver nedenstående kode ikke eksekveret, og overgangen foretages til catch-blokken.

Try-catch-blokken bruges i både procedure- og OOP-programmering. Den bruges til at fange fejl - en stor forsøgsblok med mange kast og alle er fanget på ét sted - catch-blokken.

Undtagelse kan nedarves, men det er tilrådeligt at genindlæse konstruktøren: klasse MyException udvider Exception ( funktion __construct($msg)( parent::__construct($msg); ) )

Der kan være flere catch-blokke - for hver klasse, der arver Undtagelse.

Variabler, der er medlemmer af en klasse, kaldes "egenskaber". De kaldes også for at bruge andre udtryk såsom "attributter" eller "felter", men i forbindelse med denne dokumentation vil vi henvise til dem som egenskaber. De defineres ved hjælp af nøgleord offentlig, beskyttet eller privat, efter reglerne for korrekt deklaration af variabler. Denne erklæring kan indeholde en initialisering, men denne initialisering skal være en konstant værdi, dvs. værdien skal beregnes på kompileringstidspunktet og må ikke afhænge af information modtaget under kørsel for at beregne dem.

$this pseudo-variablen er tilgængelig i enhver klassemetode, når denne metode kaldes fra en objektkontekst. $dette er en reference til det objekt, der kaldes (normalt det objekt, som metoden tilhører, men muligvis et andet objekt, hvis metoden kaldes statisk fra konteksten af ​​et andet objekt).

Eksempel #1 Definition af egenskaber

klasse SimpleClass
{
public $var1 = "hej" . "verden" ;
offentlig $var2 =<<Hej Verden
EOD;
// korrekt egenskabsdefinition fra PHP 5.6.0:
offentlig $var3 = 1 + 2 ;
// forkert egenskabsdefinition:
public $var4 = self::myStaticMethod();
offentlig $var5 = $myVar ;

// korrekt egenskabsdefinition:
public $var6 = minKonstant ;
public $var7 = array(sand, falsk);

// korrekt egenskabsdefinition fra PHP 5.3.0:
offentlig $var8 =<<<"EOD"
Hej Verden
EOD;
}
?>

Kommentar:

Siden PHP 5.3.0 og nowdocs kan bruges i enhver statisk datakontekst, inklusive definition af egenskaber.

Eksempel #2 Eksempel på brug af nowdoc til at initialisere egenskaber

klasse foo(
// Med PHP 5.3.0
offentlig $bar =<<<"EOT"
bar
EOT;
offentlig $baz =<<baz
EOT;
}
?>

Kommentar:

Nowdoc og Heredoc support blev tilføjet i PHP 5.3.0.

7 år siden

Hvis dette sparer nogen tid, brugte jeg evigheder på at finde ud af, hvorfor følgende ikke virkede:

klasse MyClass
{
privat $foo = FALSK;


{
$this->$foo = SAND;

Echo($this->$foo);
}
}

$bar = ny MyClass();

giver "Fatal fejl: Kan ikke få adgang til tom ejendom i ...test_class.php på linje 8"

Den subtile ændring med at fjerne $ før adgang til $foo løser dette:

klasse MyClass
{
privat $foo = FALSK;

Offentlig funktion __construct()
{
$this->foo = SAND;

Echo($this->foo);
}
}

$bar = ny MyClass();

Jeg tror, ​​fordi det behandler $foo som en variabel i det første eksempel, så prøv at kalde $this->FALSE (eller noget i den retning), hvilket ikke giver nogen mening. Det er indlysende, når du først har indset det, men der er der ikke nogen eksempler på adgang på denne side, der viser det.

for 4 år siden

Du kan få adgang til egenskabsnavne med bindestreger i dem (for eksempel fordi du konverterede en XML-fil til et objekt) på følgende måde:

$ref = ny StdClass();
$ref ->( "ref-type" ) = "Journalartikel" ;
var_dump ($ref);
?>

8 år siden

$dette kan castes til array. Men når du gør det, præfikser den ejendomsnavnene/nye array-nøgler med visse data afhængigt af ejendomsklassifikationen. Offentlige ejendomsnavne ændres ikke. Beskyttede egenskaber er præfikset med et mellemrumspolstret "*". Private ejendomme er forankret med det mellemrumspolstrede klassenavn...

Klasseprøve
{
offentlig $var1 = 1 ;
beskyttet $var2 = 2 ;
privat $var3 = 3 ;
statisk $var4 = 4 ;

Offentlig funktion tilArray()
{
returnere (array) $this ;
}
}

$t = ny test ;
print_r($t -> toArray());

/* udgange:

Array
=> 1
[ * var2] => 2
[test var3] => 3
)

*/
?>
Dette er dokumenteret adfærd, når ethvert objekt konverteres til et array (sePHP manual side). Alle egenskaber uanset synlighed vil blive vist, når et objekt castes til array (med undtagelse af nogle få indbyggede objekter).

For at få en matrix med alle egenskabsnavne uændrede, skal du bruge funktionen "get_object_vars($this)" i en hvilken som helst metode inden for klasseomfang for at hente en matrix af alle egenskaber uanset ekstern synlighed, eller "get_object_vars($object)" uden for klasseomfang for at hente en række kun offentlige ejendomme (se:PHP manual side).

9 år siden

Forveksle ikke phps version af egenskaber med egenskaber på andre sprog (C++ for eksempel). I php er egenskaber det samme som attributter, simple variabler uden funktionalitet. De bør kaldes attributter, ikke egenskaber.

Egenskaber har implicit accessor- og mutatorfunktionalitet. Jeg har oprettet en abstrakt klasse, der tillader implicit egenskabsfunktionalitet.

Abstrakt klasse PropertyObject
{
offentlig funktion __get ($navn)
{
if (metode_eksisterer ($this , ($method = "get_" . $navn )))
{
returner $this -> $metode ();
}
ellers returnere;
}

Offentlig funktion __isset ($name)
{
if (metode_eksisterer ($this , ($method = "isset_" . $navn )))
{
returner $this -> $metode ();
}
ellers returnere;
}

Offentlig funktion __set ($navn, $værdi)
{
if (metode_eksisterer ($this , ($method = "set_" . $navn )))
{
$this -> $metode ($værdi );
}
}

Offentlig funktion __unset ($name)
{
if (metode_eksisterer ($this , ($method = "unset_" . $navn )))
{
$dette -> $metode();
}
}
}

?>

efter at have udvidet denne klasse, kan du oprette accessorer og mutatorer, der vil blive kaldt automatisk ved hjælp af phps magiske metoder, når den tilsvarende egenskab er tilgået.

for 5 år siden

Opdateret metode objectThis() til transtypage klasse array-egenskaber eller array til stdClass.

Håber det hjælper dig.

public function objectThis($array = null) (
if (!$array) (
foreach ($this som $property_name => $property_values) (
if (is_array($egenskabsværdier) && !tom($egenskabsværdier)) (
$this->($property_name) = $this->objectThis($property_values);
) else if (is_array($property_values) && empty($property_values)) (
$this->($property_name) = new stdClass();
}
}
) andet (
$objekt = ny stdClass();
foreach ($array som $index => $værdier) (
if (is_array($værdier) && tomme($værdier)) (
$object->($index) = new stdClass();
) else if (is_array($values)) (
$object->($index) = $this->objectThis($værdier);
) andet (
$objekt->($indeks) = $værdier;
}
}
returnere $objekt;
}
}

Velkommen til anden lektion i serien om OOP. I den første artikel lærte du det grundlæggende i OOP i PHP, herunder begreberne klasser, metoder, felter og objekter. Du lærte også, hvordan du opretter en enkel klasse og implementerer den.

I denne artikel vil du lære endnu mere om klassemetoder og -felter. Dette vil give dig et godt grundlag for at begynde at lære mere avancerede teknikker såsom arv.

Her er en liste over, hvad jeg vil fortælle dig om i denne artikel:

  • Konstruktører og destruktorer, som giver dig mulighed for at tildele specifikke handlinger til et objekt, når det oprettes og slettes;
  • Statiske felter og metoder er de felter og metoder, der ikke er knyttet til specifikke objekter i en klasse;
  • Klassekonstanter, nyttige til lagring af faste værdier relateret til en specifik klasse;
  • En eksplicit typeindikation, der bruges til at sætte begrænsninger på de typer parametre, der kan overføres til en bestemt metode;
  • Særlige metoder __get() og __set(), som bruges til at indstille og læse værdierne af klassefelter;
  • En speciel metode __call() bruges til at kalde en klassemetode.

Du er klar? Så gå videre!

Konstruktører og destruktorer

Nogle gange er der behov for at udføre nogle handlinger samtidig med oprettelsen af ​​et objekt. For eksempel kan det være nødvendigt at indstille værdier for et objekts felter umiddelbart efter dets oprettelse, eller initialisere dem med værdier fra databasen.

I lighed med dette skal du muligvis også udføre visse handlinger for at fjerne et objekt fra hukommelsen, såsom at slette objekter, der afhænger af den, der slettes, at lukke databaseforbindelsen eller lukke filer.

Bemærk: hvordan sletter man et objekt? PHP fjerner automatisk et objekt fra hukommelsen, når der ikke er nogen variable tilbage, der peger på det. For eksempel, hvis du opretter et nyt objekt og gemmer det i $myObject-variablen og derefter sletter det ved hjælp af unset($myObject)-metoden, vil selve objektet også blive slettet. Desuden, hvis du har oprettet en lokal variabel i en funktion, vil den (sammen med objektet) blive slettet, når funktionen afsluttes.

PHP har to specielle metoder, der kan bruges til at udføre specifikke handlinger for at oprette og slette objekter:

  • Konstruktøren kaldes umiddelbart efter du har oprettet objektet;
  • Destruktoren kaldes strengt, før objektet fjernes fra hukommelsen.

Arbejder med konstruktører

Brug konstruktører til at angive de handlinger, der skal udføres for at skabe et objekt i en klasse. Disse handlinger kan omfatte initialisering af klassefelter, åbning af filer, læsning af data.

For at oprette en konstruktør skal du tilføje en speciel metode __construct() til din klasse (to understregninger før ordet construct). PHP vil automatisk kalde denne metode, når du implementerer din klasse, det vil sige, når du opretter et objekt af den klasse.

Her er et eksempel på en konstruktør:

Klasse MyClass ( offentlig funktion __construct() ( ekko "Jeg er lige blevet oprettet!"; ) ) $myObject = new MyClass(); // vil vise "Jeg er lige blevet oprettet!"

MyClass-klassen har en konstruktør, der udskriver strengen "Jeg er lige blevet oprettet!" til siden. Den sidste kodelinje opretter et nyt objekt i MyClass-klassen. Når dette sker, kalder PHP automatisk konstruktøren, og meddelelsen er vises i browseren Nu i praksis - initialiseringsklassefelter:

Klassemedlem (privat $username; privat $location; privat $homepage; offentlig funktion __construct($username, $location, $homepage) ( $this->username = $username; $this->location = $location; $this- >hjemmeside = $hjemmeside ) offentlig funktion showProfile() ( echo ";

"; ekko "
Brugernavn:
$this->brugernavn
"; ekko "
Beliggenhed:
$this->placering
"; ekko "
Hjemmeside:
$this->hjemmeside
"; ekko "
"; ) ) $aMember = nyt medlem("fred", "Chicago", "http://example.com/"); $aMember->showProfile();

Dette script vil vise følgende på siden:

Brugernavn: fred Sted: Chicago Hjemmeside: http://example.com/

Vores medlemsklasse har tre felter og en konstruktør, der tager 3 værdier som parametre - en for hvert felt. Konstruktøren vil tildele de værdier, der modtages som argumenter, til objektets felter. Klassen har også en metode til at vise værdierne af et objekts felter på siden.

Derefter opretter koden et objekt af Member-klassen, hvortil vi sender 3 værdier "fred", "Chicago" og "http://example.com/", da konstruktøren tager præcis 3 parametre. Konstruktøren skriver disse værdier til felterne i det oprettede objekt. Til sidst kaldes showProfile()-metoden på det oprettede objekt for at vise de resulterende værdier.

Arbejde med destruktorer

Brug en destruktor, når et objekt fjernes fra hukommelsen. Du skal muligvis gemme objektet i databasen, lukke åbne filer, der interagerede med objektet. For at oprette en destruktor skal du tilføje metoden __destruct() til klassen. Det vil blive kaldt lige før objektet slettes automatisk. Her er et simpelt eksempel:

Klasse MyClass ( offentlig funktion __destruct() ( ekko "Jeg er ved at forsvinde - farvel!"; // (ryd hukommelse) ) ) $myObject = new MyClass(); unset($myObject); // viser "I "Jeg er ved at forsvinde - farvel!"

Vi har lavet en simpel destruktor, der viser en besked på siden. Vi oprettede derefter et objekt af vores klasse og slettede det straks ved at kalde metoden unset() på den variabel, der refererer til objektet. Lige før objektet blev slettet, blev destruktoren kaldt, som viste beskeden "Jeg er ved at forsvinde - farvel!" i browseren.

Bemærk: I modsætning til konstruktører kan du ikke videregive nogen parametre til destruktorer.

Destruktoren kaldes også, når scriptet afsluttes, da alle objekter og variabler slettes, når metoden afsluttes. Så den følgende kode vil også kalde destruktoren:

Klasse MyClass ( offentlig funktion __destruct() ( ekko "Jeg er ved at forsvinde - farvel!"; // (ryd hukommelse) ) ) $myObject = new MyClass(); exit; // viser "Jeg er ved at forsvind - farvel!"

Hvis scriptet stopper med at køre på grund af en fejl, vil destruktoren også blive kaldt.

Bemærk: Når du opretter objekter af en efterkommerklasse, kaldes konstruktørerne af den overordnede klasse ikke automatisk. Kun konstruktøren af ​​selve arvingen kaldes. Du kan dog kalde forælderens konstruktør fra en underklasse som denne:

forælder::__construct(). Det samme gælder destruktorer. Du kan kalde forældrenes destruktor sådan her: parent:__destruct(). Jeg fortæller dig om forældre- og børneklasser i næste lektion om arv.

Statiske klassefelter

Vi dækkede statiske variabler i artiklen PHP Variable Scope: All You Need to Know. Ligesom en almindelig lokal variabel er en statisk variabel kun tilgængelig i en funktion. Men i modsætning til almindelige lokale variabler beholder statiske variable deres værdier mellem funktionskald.

Statiske klassefelter arbejder efter samme princip. Et statisk klassefelt er knyttet til dets klasse, men det bevarer sin værdi gennem hele scriptet. Sammenlign dette med almindelige felter: de er knyttet til et bestemt objekt, og de går tabt, når dette objekt slettes.

Statiske felter er nyttige i tilfælde, hvor du skal gemme en specifik værdi, der gælder for en hel klasse i stedet for et individuelt objekt. De ligner globale klassevariabler.

For at oprette en statisk variabel skal du tilføje det statiske nøgleord til dets definition:

Klasse MyClass (offentlig statisk $myProperty;)

Her er et eksempel på, hvordan statiske variabler fungerer:

Klassemedlem (privat $brugernavn; offentlig statisk $nummerMembers = 0; offentlig funktion __construct($brugernavn) ( $this->brugernavn = $brugernavn; self::$numMembers++; ) ) echo Member::$numMembers. "
"; // vil vise "0" $aMember = nyt medlem("fred"); echo Member::$numMembers . "
"; // vil vise "1" $anotherMember = nyt medlem("mary"); echo Member::$numMembers . "
"; // viser "2"

Der er et par interessante ting, så lad os tage et kig på dette script:

  • Member-klassen har to felter: det private felt $brugernavn og det statiske felt $numMembers, som oprindeligt er sat til 0;
  • Konstruktøren tager $brugernavn-argumentet som en parameter og indstiller feltet for det nyoprettede objekt til værdien af ​​denne parameter. Samtidig øger det værdien af ​​$numberMembers-feltet og gør det klart, at antallet af objekter i vores klasse er steget med 1.

Bemærk, at konstruktøren får adgang til det statiske felt sådan her: self::$numMembers. Selvsøgeordet ligner $this, som vi så på i sidste lektion. Mens $this refererer til det aktuelle objekt, refererer self til den aktuelle klasse. Mens du også bruger -> til at få adgang til et objekts felter og metoder, skal du i dette tilfælde bruge :: til at få adgang til felter og metoder i en klasse.

  • Til sidst opretter scriptet flere objekter af Member-klassen og viser deres nummer på siden, dvs. værdien af ​​den statiske variabel $antalMembers. Bemærk, at denne variabel bevarer sin værdi i hele scriptet, på trods af klasseobjekter.

Så for at få adgang til et statisk felt i en klasse, brug ::-operatoren. Her kan vi ikke bruge self nøgleordet, fordi koden er uden for klassen, så vi skriver klassenavnet, derefter ::, og derefter feltnavnet (Member::$numMembers). Inden for konstruktøren skal du også bruge netop en sådan struktur, og ikke dig selv.

Bemærk: det var nemt for vores script at få adgang til klassefeltet $numMembers, før det første objekt i denne klasse blev oprettet. Der er ingen grund til at oprette objekter af en klasse for at bruge dens statiske felter.

Statiske metoder

Sammen med statiske klassefelter kan du også oprette statiske metoder. Statiske metoder, ligesom felter, er forbundet med en klasse, men der er ingen grund til at oprette et objekt af klassen for at kalde en statisk metode. Dette gør sådanne metoder nyttige, hvis du har brug for en klasse, der ikke fungerer på rigtige objekter.

For at oprette en statisk metode skal du tilføje det statiske søgeord til dets erklæring:

Klasse MyClass ( offentlig statisk funktion myMethod() ( // (handlinger) ) )

Vores tidligere eksempel vedrørende statiske felter var det statiske felt $numberMembers. At gøre felter private og metoder til at få adgang til dem offentlige er god praksis. Lad os gøre vores statiske felt privat og skrive en offentlig statisk metode for at få værdien af ​​det givne felt:

Klassemedlem (privat $brugernavn; privat statisk $numMembers = 0; offentlig funktion __construct($brugernavn) ( $this->brugernavn = $brugernavn; self::$numMembers++; ) offentlig statisk funktion getNumMembers() ( return self::$ numMembers; ) ) echo Member::getNumMembers() . "
"; // vil vise "0" $aMember = nyt medlem("fred"); echo Member::getNumMembers() . "
"; // vil vise "1" $anotherMember = nyt medlem("mary"); echo Member::getNumMembers() . "
"; // viser "2"

Her har vi lavet en statisk metode getNumMembers() som returnerer værdien af ​​det statiske felt $numMembers. Vi gjorde også dette felt privat, så dets værdi ikke kan opnås udefra.

Vi ændrede også opkaldskoden til at bruge metoden getNumMembers() til at få værdien af ​​feltet $numMembers. Bemærk, at du kan kalde denne metode uden at oprette et objekt af klassen, fordi metoden er statisk.

Klasse konstanter

Konstanter giver dig mulighed for at indstille en global værdi for hele din kode. Denne værdi er fast og kan ikke ændres. Klassekonstanter ligner almindelige konstanter. Den største forskel er, at ud over at en klassekonstant er global, kan den tilgås fra den klasse, hvor den er defineret. Klassekonstanter er nyttige i tilfælde, hvor du skal gemme specifikke værdier, der tilhører en bestemt klasse.

Du kan definere en klassekonstant ved hjælp af nøgleordet const. For eksempel:

Klasse MyClass ( const CONSTANT_NAME = værdi; )

Du kan efterfølgende få adgang til en klassekonstant gennem klassenavnet og ::-operatoren. For eksempel sådan her:

MyClass::CONSTANT_NAME

Bemærk: Som med statiske felter og metoder, kan du få adgang til en konstant ved hjælp af selv nøgleordet.

Lad os se på klassekonstanter med et eksempel. Lad os tilføje konstanter til medlemsklassen, der gemmer værdierne for deres rolle (deltager, moderator eller administrator). Ved at bruge konstanter i stedet for almindelige numeriske værdier gjorde vi koden mere læsbar. Her er scriptet:

Klassemedlem ( const MEMBER = 1; const MODERATOR = 2; const ADMINISTRATOR = 3; privat $brugernavn; privat $niveau; offentlig funktion __construct($brugernavn, $niveau) ( $this->brugernavn = $brugernavn; $this-> level = $level ) public function getUsername() ( return $this->username; ) public function getLevel() ( if ($this->level == self::MEMBER) returner "et medlem"; if ($this ->niveau == self::MODERATOR) returner "en moderator" hvis ($this->level == self::ADMINISTRATOR) returnerer "ukendt" ) $aMember = new Member(" fred ", Medlem::MEMBER); $anotherMember = nyt medlem("mary", Member::ADMINISTRATOR); echo $aMember->getUsername() . "er". $aMember->getLevel() . "
"; // vil vise "fred er et medlem" echo $anotherMember->getUsername() . " er " . $anotherMember->getLevel() . "
"; // viser "mary er administrator"

Vi oprettede tre klassekonstanter: MEMBER, MODERATOR og ADMINISTRATOR, og gav dem henholdsvis værdierne 1, 2 og 3. Derefter tilføjer vi et $level-felt for at gemme roller og ændrer konstruktøren lidt for også at initialisere dette felt. Klassen tilføjede også en anden metode - getLevel(), som returnerer en specifik besked afhængigt af værdien af ​​$level-feltet. Den sammenligner denne værdi med hver af klassekonstanterne og returnerer den ønskede streng.

Scriptet opretter flere objekter med forskellige roller. For at tildele roller til objekter er det klassekonstanter, der bruges, og ikke simple numeriske værdier. Derefter kaldes metoderne getUsername() og getLevel() på hvert objekt, og resultaterne vises på siden.

Eksplicit specificering af funktionsargumenttyper

I PHP behøver du ikke angive datatyper, så du behøver ikke bekymre dig om, hvilke argumenter du videregiver til metoder. For eksempel kan du sikkert sende en numerisk værdi til strlen()-funktionen, som beregner længden af ​​en streng. PHP vil først konvertere tallet til en streng og derefter returnere dets længde:

Ekko strlen(123); // vis "3"

Nogle gange er det nyttigt at angive typen eksplicit, men det kan føre til fejl, der er svære at håndtere, især hvis du arbejder med komplekse datatyper såsom objekter.

For eksempel

Se på denne kode:

Klassemedlem ( privat $brugernavn; offentlig funktion __construct($brugernavn) ( $this->brugernavn = $brugernavn; ) offentlig funktion getUsername() ( return $this->brugernavn; ) ) klasse Emne (privat $medlem; privat $emne ; offentlig funktion __construct($medlem, $emne) ( $this->member = $medlem; $this->subject = $emne; ) offentlig funktion getUsername() (retur $this->member->getUsername();) ) $aMember = nyt medlem("fred"); $aTopic = nyt emne($aMember, "Hej alle sammen!"); echo $aTopic->getUsername(); // vil vise "fred"

Dette script fungerer således:

  • Vi opretter vores medlemsklasse med et $brugernavn-felt, en konstruktør og en getUsername()-metode;
  • Vi opretter også en emneklasse til at administrere forumartikler. Den har to felter: $member og $subject. $member er et objekt af Member-klassen, dette vil være forfatteren til artiklen. $subject-feltet er emnet for artiklen.
  • Klassen Topic indeholder også en konstruktør, der tager et Member-objekt og en streng, der repræsenterer artiklens emne. Det initialiserer klassefelterne med disse værdier. Den har også en getUsername() metode, som returnerer navnet på forummedlemmet. Dette opnås ved at kalde metoden getUsername() for Member-objektet.
  • Til sidst opretter vi et objekt af klassen Member med feltværdien brugernavn "fred". Derefter opretter vi et objekt af klassens emne, sender det Fred og emnet for artiklen "Hej alle sammen!". Til sidst kalder vi getUsername()-metoden for Topic-klassen og viser brugernavnet ("fred") på siden.

Det hele er meget godt, men...

Lad os gøre det bedre!

Lad os tilføje dette stykke kode til sidst:

Klasse-widget ( privat $farve; offentlig funktion __construct($farve) ( $this->colour = $colour; ) offentlig funktion getColour() ( return $this->colour; ) ) $aWidget = new Widget("blå") ; $anotherTopic = nyt emne($aWidget, "Ups!"); // vil vise "Fatal error: Call to undefined method Widget::getUsername()" echo $anotherTopic->getUsername();

Her opretter vi en Widget-klasse med et $colour-felt, en konstruktør og en getColour()-metode, der returnerer widgettens farve.

Vi vil så oprette et objekt af denne klasse, efterfulgt af et Topic-objekt med argumentet $aWidget, når vi faktisk skal forbi artiklens forfatter, dvs. Medlemsklasseobjekt.

Lad os nu prøve at kalde metoden getUsername() i klassen Topic. Denne metode kalder metoden getUsername() for Widget-klassen. Og da der ikke er en sådan metode i denne klasse, får vi en fejl:

Fatal fejl: Kald til udefineret metode Widget::getUsername()

Problemet er, at årsagen til fejlen ikke er så let at forstå. Hvorfor leder emneobjektet efter en metode i Widget-klassen og ikke Member? I et komplekst klassehierarki vil det være meget svært at finde en vej ud af denne form for situation.

Vi giver et hint

Det ville være bedre at begrænse emnekonstruktøren til at acceptere argumenter, så den kun kan acceptere medlemsobjekter som dens første parameter, og derved forhindre fatale fejl.

Det er præcis, hvad eksplicit typespecifikation gør. For eksplicit at angive typen af ​​en parameter skal du indsætte klassenavnet før argumentnavnet i metodeerklæringen:

Funktion myMethod(Klassenavn $objekt) ( // (handlinger) )

Lad os justere konstruktøren af ​​emneklassen, så den kun accepterer Medlem:

Klasseemne ( privat $medlem; privat $emne; offentlig funktion __construct(Medlem $medlem, $emne) ( $this->medlem = $medlem; $this->subject = $emne; ) offentlig funktion getUsername() ( return $ dette->medlem->getBrugernavn();

Lad os nu prøve at oprette et emneobjekt igen ved at give det en widget:

$aWidget = ny widget("blå"); $anotherTopic = nyt emne($aWidget, "Ups!");

Denne gang vil PHP vise en specifik fejl:

Fangbar fatal fejl: Argument 1 videregivet til Topic::__construct() skal være en forekomst af Member, forekomst af Widget givet, kaldet script.php på linje 55 og defineret i script.php på linje 24

Dette problem vil være meget lettere at håndtere, da vi ved præcis, hvad årsagen til fejlen er - vi forsøgte at videregive en parameter til konstruktøren af ​​den forkerte type. Fejlmeddelelsen viser endda de nøjagtige kodelinjer, hvor metoden, der forårsagede fejlen, blev kaldt.

Initialisering og læsning af klassefeltværdier ved hjælp af __get() og __set()

Som du allerede ved, indeholder klasser normalt felter:

Klasse MyClass ( offentlig $aProperty; offentlig $anotherProperty; )

Hvis klassens felter er offentlige, kan du få adgang til dem ved hjælp af ->-operatoren:

$myObject = ny MyClass; $myObject->aProperty = "hej";

PHP giver dig dog mulighed for at oprette "virtuelle" felter, som faktisk ikke er i klassen, men som kan tilgås via -> operatoren. De kan være nyttige i følgende tilfælde:

  • Når du har mange felter, og du vil oprette et array for dem for ikke at erklære hvert felt separat;
  • Når du har brug for at gemme et felt uden for et objekt, såsom i et andet objekt, eller endda i en fil eller database;
  • Når du skal beregne feltværdier i farten, i stedet for at gemme deres værdier et eller andet sted.

For at oprette sådanne "virtuelle" felter skal du tilføje et par magiske metoder til klassen:

  • __get($propName) kaldes automatisk, når man forsøger at læse værdien af ​​det "usynlige" felt $propName;
  • __set($propName,$propValue) kaldes automatisk, når man forsøger at sætte det "usynlige" felt $propName til $propValue.

"Usynlig" betyder i denne sammenhæng, at disse felter ikke kan tilgås direkte i denne kodesektion. For eksempel hvis et sådant felt slet ikke findes i klassen, eller hvis det findes, men det er privat, og der ikke er adgang til et sådant felt uden for klassen.

Lad os gå videre til praksis. Lad os ændre vores medlemsklasse, så der ud over $username-feltet er andre tilfældige felter, der vil blive gemt i $data-arrayet:

Klassemedlem (privat $brugernavn; privat $data = array(); offentlig funktion __get($property) (if ($property == "brugernavn") (retur $this->brugernavn; ) else (if (array_key_exists($property) , $this->data)) ( return $this->data[$property]; ) else (retur null; ) ) public function __set($property, $value) (if ($property == "brugernavn" ) ( $this->username = $value; ) else ( $this->data[$property] = $value; ) ) ) $aMember = nyt medlem(); $aMember->brugernavn = "fred"; $aMember->location = "San Francisco"; echo $aMember->brugernavn . "
"; // viser "fred" echo $aMember->placering . "
"; // viser "San Francisco"

Sådan fungerer det:

  • Medlemsklassen har et konstant felt privat $brugernavn og et privat array $data til lagring af tilfældige "virtuelle" felter;
  • Metoden __get() tager en enkelt parameter $property - navnet på det felt, hvis værdi skal returneres. Hvis $property = "brugernavn", vil metoden returnere værdien af ​​$brugernavn-feltet. Ellers vil metoden kontrollere, om en sådan $egenskab forekommer i nøglerne til $dataarrayet. Hvis en sådan nøgle findes, returnerer den værdien af ​​dette felt, ellers - null.
  • Metoden __set() tager 2 parametre: $property - navnet på det felt, der skal initialiseres, og $value - den værdi, der skal indstilles for dette felt. Hvis $property = "brugernavn", initialiserer metoden $brugernavn-feltet med værdien fra parameteren $værdi. Ellers tilføjer du $property-nøglen med værdien $value til $dataarrayet.
  • Efter at have oprettet Member-klassen, opretter vi et objekt af denne klasse og initialiserer dets $username-felt med værdien "fred". Dette kalder metoden __set(), som vil sætte værdien $username til objektet. Derefter sætter vi værdien af ​​$location-feltet til "San Francisco". Da et sådant felt ikke findes i objektet, skriver metoden det til $data-arrayet.
  • Til sidst fjerner vi værdierne for $username og $location og viser dem på siden. Metoden __get() henter den faktiske $brugernavn-værdi fra det eksisterende $brugernavn-felt og $location-værdien fra $dataarrayet.

Som du kan se, har vi ved hjælp af metoderne __get() og __set() skabt en klasse, der kan indeholde både rigtige felter og alle "virtuelle" felter. Fra et stykke kode, hvor der er sat en værdi for et bestemt felt, er det ikke nødvendigt at vide, om et sådant felt findes eller ej i objektet. Ved at bruge den sædvanlige -> operator kan du indstille en værdi til et felt eller læse det.

Eksemplet viser også, hvordan du nemt kan oprette metoder, kaldet "getters" og "settere", for at få adgang til private felter. Vi behøver ikke oprette separate getUsername()- og setUsername()-metoder for at få adgang til det private $username-felt. I stedet oprettede vi metoderne __get() og __set() til at manipulere dette felt. Det betyder, at vi kun har brug for 2 metoder i alt, frem for 2 metoder for hvert privat felt.

Bemærk: Et ord om indkapsling. Brug af private klassefelter i kombination med gettere og sættere er bedre end at bruge offentlige variabler. Gettere og sættere kan desuden behandle data givet til og fra et objekts felter, såsom at kontrollere om en værdi er i det korrekte format eller konvertere den til det ønskede format. Gettere og sættere skjuler også detaljerne om, hvordan felterne i en klasse er implementeret, hvilket gør det nemmere at ændre det interne i en klasse, fordi du ikke behøver at omskrive koden, der opererer på objekter i den klasse. For eksempel vil du pludselig gerne gemme værdien af ​​et felt i en database. Hvis du allerede havde gettere og settere, er alt hvad du skal gøre at omskrive dem. Og opkaldskoden forbliver den samme. Denne teknik kaldes indkapsling, og det er en af ​​hovedfordelene ved OOP.

Overbelastningsmetoder med __call()

Gettere og sættere bruges til at nægte adgang til private variabler. I samme retning bruges metoden __call() til at nægte adgang til private metoder. Når kode kalder en klassemetode, der enten ikke eksisterer eller ikke er tilgængelig, kaldes metoden __call() automatisk. Her er den generelle syntaks for metoden:

Offentlig funktion __call($methodName, $arguments) ( // (handlinger) )

Når der gøres et forsøg på at kalde en utilgængelig klassemetode, kalder PHP automatisk __call()-metoden, hvortil den sender en streng - navnet på den kaldte metode og en liste over beståede parametre i et array. Din __call()-metode skal derefter håndtere opkaldet på en bestemt måde og returnere værdier, hvis det er nødvendigt.

Metoden __call() er nyttig i situationer, hvor du har brug for at videregive nogle funktioner i en klasse til en anden klasse. Her er et simpelt eksempel:

Klassemedlem ( privat $brugernavn; offentlig funktion __construct($brugernavn) ( $this->brugernavn = $brugernavn; ) offentlig funktion getUsername() ( return $this->brugernavn; ) ) klasse Emne (privat $medlem; privat $emne ; offentlig funktion __construct($medlem, $emne) ( $this->member = $medlem; $this->subject = $emne; ) offentlig funktion getSubject() (retur $this->subject;) offentlig funktion __call($ metode, $arguments) ( return $this->member->$method($arguments); ) ) $aMember = nyt medlem("fred"); $aTopic = nyt emne($aMember, "Hej alle sammen!"); echo $aTopic->getSubject() . "
"; // vil vise "Hej alle sammen!" echo $aTopic->getUsername() . "
"; // viser "fred"

Dette eksempel ligner det, der er givet i afsnittet om eksplicit specificering af typer. Vi har en Medlemsklasse med et felt $brugernavn og en Emneklasse med et felt - et objekt fra Medlemsklassen (forfatter til artiklen) og et felt $subject - artiklens emne. Topic-klassen indeholder en getSubject()-metode til at hente emnet for en artikel, men den har ikke en metode, der returnerer navnet på artiklens forfatter. I stedet har den en __call()-metode, der kalder en ikke-eksisterende metode og videregiver argumenter til medlemsklassens metode.

Når din kode kalder $aTopic->getUsername() metoden, forstår PHP, at der ikke findes en sådan metode i klassen Topic. Derfor kaldes __call()-metoden, som igen kalder getUsername()-metoden for Member-klassen. Denne metode returnerer forfatterens navn til __call() metoden, som sender den resulterende værdi til den kaldende kode.

Bemærk: PHP har andre metoder, der håndterer overbelastning, såsom __isset(), __unset() og __callStatic().

Konklusion

I denne lektion har du uddybet din viden om OOP i PHP ved at se mere detaljeret på felter og metoder. Du har studeret:

  • Konstruktører og destruktorer, nyttige til initialisering af felter og rydning af hukommelse, efter at objekter er slettet;
  • Statiske felter og metoder, der fungerer på klasseniveau snarere end på objektniveau;
  • Klassekonstanter, nyttige til lagring af faste værdier, der er nødvendige på klasseniveau;
  • Eksplicit indikation af typer, hvormed du kan begrænse de typer argumenter, der sendes til metoden;
  • De magiske metoder __get(), __set() og __call(), som bruges til at få adgang til private felter og metoder i en klasse. Implementering af disse metoder giver dig mulighed for at oprette "virtuelle" felter og metoder, der ikke findes i klassen, men som samtidig kan kaldes.

Med den viden, der er opnået i denne og de tidligere tutorials, kan du begynde at skrive OOP. Men dette er kun begyndelsen! I den næste lektion vil vi tale om kraften ved OOP - klassernes evne til at arve funktionalitet fra andre klasser.

God programmering!