Salta el contingut

Exercicis PHP Orientat a objectes

✏️ EXERCICI 112 (exercici112Empleat.php): Crea una classe Empleat amb el seu nom, llinatges i sou. Encapsula les propietats mitjançant getters/setters i afegeix mètodes per a:

  • Obtenir el seu nom complet → getNomComplet(): string
  • Que retorni un booleà indicant si ha de pagar o no impostos (es paguen quan el sou és superior a 3333€) → hadePagarImpostos(): bool

✏️ EXERCICI 113 (exercici113EmpleatTelefons.php): Copia la classe de l'exercici 112 i modifica-la. Afegeix una propietat privada que emmagatzemi una matriu de números de telèfons. Afegeix els mètodes següents:

  • public function afegirTelefon(int $telefo) : void → Afegeix un telèfon a la matriu
  • public function llistarTelefons(): string → Mostra els telèfons separats per comes
  • public function buidarTelefons(): void → Elimina tots els telèfons

✏️ EXERCICI 114 (exercici114EmpleatConstructor.php): Copia la classe de l'exercici 113 i modifica-la. Elimina els setters de nom i llinatges, de manera que aquestes dades s'assignin mitjançant el constructor (utilitza la sintaxi de PHP7). Si el constructor rep un tercer paràmetre, serà el sou del Empleat. Si no, se li assignaran 1000€ com a sou inicial.

exercici114EmpleatConstructor8.php: Modifica la classe i utilitza la sintaxi del PHP 8 de promoció de les propietats del constructor.

✏️ EXERCICI 115 (exercici115EmpleatConstant.php): Copia la classe de l'exercici 114 i modifica-la. Afegeix una constant SOU_MAXIM amb el valor del sou que ha de pagar impostos, i modifica el codi per utilitzar la constant.

✏️ EXERCICI 116 (exercici116EmpleatSou.php):Copia la classe de l'exercici 115 i modifica-la. Canvia la constant per una variable estàtica souMaxim, de manera que mitjançant getter/setter puguis modificar el seu valor.

✏️ EXERCICI 117 (exercici117EmpleatStatic.php: Copia la classe de l'exercici 116 i modifica-la. Completa el mètode següent amb una cadena HTML que mostri les dades d'un empleat dins d'un paràgraf i tots els telèfons mitjançant una llista ordenada (per a això, hauràs de crear un getter per als telèfons):

  • public static function toHtml(Empleat $emp): string

✏️ EXERCICI 118 (exercici118Persona.php): Copia la classe de l'exercici anterior a exercici118Empleat.php i modifícala.

Crea una classe Persona que sigui pare d'Empleat, de manera que Persona contingui el nom i els cognoms, i en Empleat quedi el salari i els telèfons.

Exercici 118

✏️ EXERCICI 119 (exercici119PersonaH.php): Copia les classes de l'exercici anterior i modifícales. Crea en Persona el mètode estàtic toHtml(Persona $p), i modifica en Empleat el mateix mètode toHtml(Persona $p), però canvia la funció perquè rebi una Persona com a paràmetre. Per accedir a les propietats de l'empleat amb la persona que rebem com a paràmetre, comprovarem el seu tipus:

<?php
class Empleat extends Persona {
    /// reste del codi


    public static function toHtml(Persona $p): string {
        if ($p instanceof Empleat) {
            // Aqui ja podem accedir a les propietats i mètodes d'Empleat
        }
    }
}

✏️ EXERCICI 120 (exercici120PersonaE.php): Copia les classes de l'exercici anterior i modifícales. Afegeix en Persona un atribut edat A l'hora de saber si un empleat ha de pagar impostos, ho farà sempre que tingui més de 21 anys i depengui del valor del seu sou. Modifica tot el codi necessari per mostrar i/o editar l'edat quan sigui necessari.

✏️ EXERCICI 121 (exercici121PersonaS.php): Copia les classes de l'exercici anterior i modifícales. Afegeix nous mètodes que facin una representació de totes les propietats de les classes Persona i Empleat, de forma similar als realitzats en HTML, però sense que siguin estàtics, de manera que obtingui les dades mitjançant $this.

function public __toString(): string

Magic methods

El mètode__toString() és un mètode màgic que s'invoca automàticament quan volem obtenir la representació en cadena d'un objecte.

✏️ EXERCICI 122 (exercici122PersonaA.php): Copia les classes de l'exercici anterior i modifícales. Transforma Persona a una classe abstracta on el seu mètode estàtic toHtml(Persona $p) hagi de ser redefinit en tots els seus fills.

✏️ EXERCICI 123 (exercici123Treballador.php): Copia les classes de l'exercici anterior i modifícales.

  • Canvia l'estructura de classes conforme al gràfic respectant tots els mètodes que ja estan fets.
  • Treballador és una classe abstracta que ara emmagatzema els telefons i on calcularSou és un mètode abstracte de manera que:
  • El sou d'un Empleat es calcula a partir de les hores treballades i el que cobra per hora.
  • Per als Gerents, el seu sou s'incrementa percentualment en base a la seva edat: salari + salari*edat/100
Exercici 123

✏️ EXERCICI 124 (exercici124Empresa.php): Utilitzant les classes dels exercicis anteriors:

  • Crea una classe Empresa que a més del nom i la direcció, contingui una propietat amb un vector de Treballador, ja siguin Empleats o Gerents.
  • Afegeix getters/setters per al nom i adreça.
  • Afegeix mètodes per afegir i llistar els treballadors.
  • public function afegirTreballador(Treballador $t)
  • public function llistarTreballadorsHtml() : string -> utiliza Treballador::toHtml(Persona $p)
  • Afegeix un mètode per obtenir el cost total en nòmines.
  • public function getCostNomines(): float -> recorre els treballadors i invoca el mètode 'calcularSou()'.

✏️ EXERCICI 125 (exercici125EmpresaI.php): Copia les classes de l'exercici anterior i modifícales.

  • Crea un interfície JSerialitzable, de manera que ofereixi els mètodes:
  • toJSON(): string → utilitza la funció json_encode(mixed). Tingues en compte que com que tenim les propietats dels objectes privats, has de recórrer les propietats i col·locar-les en un mapa. Per exemple:

<?php
public function toJSON(): string {
    foreach ($this as $clau => $valor) {
        $mapa->$clau = $valor;
    }
    return json_encode($mapa);
}
?>
* toSerialize(): string → utilitza la funció serialize(mixed) * Modifica totes les classes que no són abstractes perquè implementin l'interfície creat.

Projecte Videoclub

En els següents exercicis simularem un petit projecte d'un Videoclub (basat en la proposta que fa el tutorial de desarrolloweb.com), el qual realitzarem mitjançant un desenvolupament incremental i seguint la pràctica de programació en parelles (pair programming).

Abans de res, crea un repositori privat a GitHub i puja el projecte actual de Videoclub. Un cop creat, convida el teu company al repositori com a col·laborador.

  • Inicialitza en local el teu repostori de git, mitjançant git init
  • Afegeix i puja els canvis al teu repositori, mitjançant git add . i després git commit -m 'Inicialitzant projecte'.
  • Connecta el teu repositori amb GitHub i puja els canvis (mira les instruccions de GitHub: ordres git remote y git push).
  • El teu company haurà de descarregar el projecte amb les seves credencials.

Projecte no real

El següent projecte està pensat des d'un punt de vista formatiu. Algunes de les decisions que es prenen no s'han de fer servir (com fer echo, dins de les classes) o provar el codi comparant el resultat al navegador.

Cada classe ha d'anar en un arxiu php separat. Per facilitar la seva implementació, es mostra l'estructura UML del model i un fragment de codi per provar les classes:

Cream el soport

✏️ EXERCICI 126. Crea una classe per emmagatzemar suports (Soport.php). Aquesta classe serà la classe pare dels diferents suports amb els quals treballi el nostre videoclub (cintes de vídeo, videojocs, etc...):

  • Crea el constructor que inicialitzi les seves propietats. Fixeu-vos que la classe no té mètodes setters.
  • Definir una constant mitjançant una propietat privada i estàtica anomenada IVA amb un valor del 21%
  • Crear un arxiu ('inici.php') per usar les classes i copia el següent fragment:
<?php
include "Soport.php";

$soport1=new Soport("Tenet", 22, 3);
echo "<strong>" . $soport1->titol . "</strong>";
echo "<br>Preu: " . $soport1->getPreu() . " euros";
echo "<br>Preu IVA inclos: " . $soport1->getPreuAmbIva() . " euros";
$soport1->mostraResum();

Tenet
Preu: 3 euros
Preu IVA inclos: 3.48 euros
Tenet
3 € (IVA no inclos)

Afegim cinta de video

✏️ EXERCICI 127. Crea la classe CintaVideo la qual hereta de Soport. Afegeix l'atribut durada sobreescriu tant el contructor com el mètode mostraResum (des de CintaVideo hauràs d'invocar al mètode mostraResum del pare).

Afegeix a 'inici.php' el codi per provar la classe:

<?php
include "CintaVideo.php";

$laMevaCinta = new CintaVideo("Los cazafantasmas", 23, 3.5, 107);
echo "<strong>" . $laMevaCinta->titol . "</strong>";
echo "<br>Preu: " . $laMevaCinta->getPreu() . " euros";
echo "<br>Preu IVA inclos: " . $laMevaCinta->getPreuAmbIva() . " euros";
$laMevaCinta->mostraResum();

 Los cazafantasmas
 Preu: 3.5 euros
 Preu IVA inclos: 4.06 euros
 Pel·Lícula en VHS:
 Los cazafantasmas
 3.5 € (IVA no inclos)
 Durada: 107 minutos
 




Afegim DVD

✏️ EXERCICI 128. Crea la classe DVD la qual hereta de Soport. Afegeix els atributs idiomes i formatPantalla. A continuació sobreescriu tant el contructor com el mètode mostraResum.

Afegeix a 'inici.php' el codi per provar la classe:

<?php
include "Dvd.php";

$elMeuDvd = new Dvd("Origen", 24, 15, "es,en,fr", "16:9");
echo "<strong>" . $elMeuDvd->titol . "</strong>";
echo "<br>Preu: " . $elMeuDvd->getPreu() . " euros";
echo "<br>Preu IVA inclos: " . $elMeuDvd->getPreuAmbIva() . " euros";
$elMeuDvd->mostraResum();

Origen
Preu: 15 euros
Preu IVA inclos: 17.4 euros
Pel·Lícula en DVD:
Origen
15 € (IVA no inclos)
Idiomes:es,en,fr
Format Pantalla:16:9




Afegim Joc

✏️ EXERCICI 129. Crea la classe Joc la qual hereta de Soport. Afegeix els atributs consola, minNumJugadors y maxNumJugadors. A continuació afegeix el mètode mostraJugadorsPossibles, el qual ha de mostrar Per a un jugador, Per a X jugadors o De X a Y jugadors depenent dels valors de les atributs creats. Finalment, sobreescriu tant el contructor com el mètode mostraResum.

Afegeix a 'inici.php' el codi per provar la classe:

<?php
include "Joc.php";

$elMeuJoc = new Joc("The Last of Us Part II", 26, 49.99, "PS4", 1, 1);
echo "<strong>" . $elMeuJoc->titol . "</strong>";
echo "<br>Preu: " . $elMeuJoc->getPreu() . " euros";
echo "<br>Preu IVA inclos: " . $elMeuJoc->getPreuAmbIva() . " euros";
$elMeuJoc->mostraResum();

Joc per PS4: The Last of Us Part II
49.99 € (IVA no inclos)
Per a 1 jugadorThe Last of Us Part II`
Preu: 49.99 euros
Preu IVA inclos: 60.4879 euros
Joc per PS4: The Last of Us Part II
49.99 € (IVA no inclos)
Per a 1 jugador

Arribats a aquest punt, el nostre model és similar al següent diagrama:

Model inicial de Videoclub

Afegim Client

✏️ EXERCICI 130. Crear la classe Client. El constructor rebrà el nom, numero y maxLloguerConcurrent, aquest últim podent ser opcional i prenent com a valor per defecte 3. Després d'això, afegeix getter/setter únicament a numero, i un getter a numSoportsLlogats (aquest camp ha d'emmagatzemar un comptador del total de lloguers que ha realitzat). La matriu de soports llogats contindrà classes que heretin de Soport. Finalment, afegeix el mètode mostraResum que mostri el nom i la quantitat de lloguers (tamany de la matriu soportsLlogats).

✏️ EXERCICI 131. Dins de Client, afegeix les operacions següents:

  • teLlogat(Soport $s): bool → Recorre el vector de soports i comprova si hi ha el soport
  • llogar(Soport $s): bool -→ Ha de comprovar si el soport està llogat i si no ha superat la quota de lloguers. En llogar, incrementarà el numSoportsLlogats i emmagatzemarà el soport al vector. Per cada cas ha de mostrar un missatge informant de l'ocorregut.

✏️ EXERCICI 132. Seguim amb Client per afegir les operacions:

  • tornar(int $numSoport): bool → Ha de comprovar que el soport estava llogat i actualitzar la quantitat de soports llogats. Per cada cas ha de mostrar un missatge informant de l'ocorregut
  • llistarLloguers(): void → Informa de quants lloguers té el client i els mostra.

Crea l'arxiu inici2.php amb el següent codi font per provar la classe:

<?php
include_once "CintaVideo.php";
include_once "Dvd.php";
include_once "Joc.php";
include_once "Client.php";

//instanciam un parell d'objectes client
$client1 = new Client("Bruce Wayne", 23);
$client2 = new Client("Clark Kent", 33);

//mostrem el número de cada client creat
echo "</br>L'identificador del client 1 és: " . $client1->getNumero();
echo "</br>L'identificador del client 2 és: " . $client2->getNumero();
echo "</br>";
//instancio alguns soports
$soport1 = new CintaVideo("Los cazafantasmas", 23, 3.5, 107);
echo "</br>";
$soport2 = new Joc("The Last of Us Part II", 26, 49.99, "PS4", 1, 1);
echo "</br>";
$soport3 = new Dvd("Origen", 24, 15, "es,en,fr", "16:9");
echo "</br>";
$soport4 = new Dvd("El Imperio Contraataca", 4, 3, "es,en","16:9");
echo "</br>";
//Llog alguns soports
$client1->llogar($soport1);
$client1->llogar($soport2);
$client1->llogar($soport3);

echo "</br>";
//vaig intentar llogar de nou un soport que ja té llogat
$client1->llogar($soport1);

echo "</br>";
//el client té 3 soports de lloguer com a màxim
//aquest soport no el pot llogar
$client1->llogar($soport4);

echo "</br>";
//aquest soport no el té llogat
$client1->tornar(4);
echo "</br>";
//torna un soport que sí que té llogat
$client1->tornar(26);
echo "</br>";
//llog un altre soport
$client1->llogar($soport4);
echo "</br>";
//faig un llistat dels elements llogats
$client1->llistarLloguers();
echo "</br>";
//aquest client no té lloguers
$client2->tornar(

L'identificador del client 1 és: 23
L'identificador del client 2 és: 33

Pel·lícula en VHS Los cazafantasmas 3.5 € (IVA no inclos) Durada: 107 minuts

Joc per PS4: The Last of Us Part II 49.99 € (IVA no inclos) Per a 1 jugador

Pel·lícula en DVD Origen 15 € (IVA no inclos) Idiomes: es,en,fr Format Pantalla: 16:9

Pel·lícula en DVD El Imperio Contraataca 3 € (IVA no inclos) Idiomes: es,en Format Pantalla: 16:9

Llogat correctament: Los cazafantasmas a client: Bruce Wayne Llogat correctament: The Last of Us Part II a client: Bruce Wayne Llogat correctament: Origen a client: Bruce Wayne

Ja tens aquest suport "Los cazafantasmas" llogat.

Has arribat al màxim de lloguers.

No tens aquest suport llogat.

"The Last of Us Part II" Suport retornat correctament.

Llogat correctament: El Imperio Contraataca a client: Bruce Wayne

Bruce Wayne té 3 lloguers: Pel·lícula en VHS Los cazafantasmas 3.5 € (IVA no inclos) Durada: 107 minuts


Pel·lícula en DVD Origen 15 € (IVA no inclos) Idiomes: es,en,fr Format Pantalla: 16:9


Pel·lícula en DVD El Imperio Contraataca 3 € (IVA no inclos) Idiomes: es,en Format Pantalla: 16:9


No tens aquest suport llogat.

✏️ EXERCICI 132. Arribat a aquest punt, anam a relacionar els clients i els soports mitjançant la classe Videoclub. Així doncs crea la classe que representa el gràfic, tenint en compte que:

  • products és un array de Soport
  • socis és un array de Client
  • Els mètodes públics d'incloure algun soport, crearan la classe i cridaran al mètode privat de incloureProducte, el qual és l'encarregat d'introduir-lo dins el vector.

El model complet es semblarà a això:

Model complet de Videoclub

I per provar el projecte, dins inici3.php col·locarem:

<?php
include_once "Videoclub.php"; // No incloem res més

$vc = new Videoclub("Cas Concos 45 baixos");

//inclouré uns quants soports de prova
$vc->incloureJoc("God of War", 19.99, "PS4", 1, 1);
$vc->incloureJoc("The Last of Us Part II", 49.99, "PS4", 1, 1);
$vc->incloureDvd("Torrente", 4.5, "es","16:9");
$vc->incloureDvd("Origen", 4.5, "es,en,fr", "16:9");
$vc->incloureDvd("El Imperio Contraataca", 3, "es,en","16:9");
$vc->incloureCintaVideo("Los cazafantasmas", 3.5, 107);
$vc->incloureCintaVideo("El nombre de la Rosa", 1.5, 140);

//llist els productes
$vc->llistarProductes();
echo "</br>";
//crearé alguns socis
$vc->incloureSoci("Tofol Verdera", 2);
$vc->incloureSoci("Biel Calafell");
echo "</br>";
$vc->llogarSociProducte(1,2);
$vc->llogarSociProducte(1,3);
// llogar una altra vegada el soport 2 al soci 1.
// no ha de deixar-me perquè ja el té llogat
$vc->llogarSociProducte(1,2);
// llogar el soport 6 al soci 1.
// no es pot perquè el soci 1 té 2 lloguers com a màxim
$vc->llogarSociProducte(1,6);

// llist els socis
$vc->llistarSocis();

Joc per PS4: God of War
19.99 € (IVA no inclos)
Per a 1 jugador
======
Inclòs soport 1
======
Joc per PS4: The Last of Us Part II
49.99 € (IVA no inclos)
Per a 1 jugador
======
Inclòs soport 2
======
Pel·lícula en DVD Torrente
4.5 € (IVA no inclos)
Idiomes: es
Format Pantalla: 16:9
======
Inclòs soport 3
======
Pel·lícula en DVD Origen
4.5 € (IVA no inclos)
Idiomes: es,en,fr
Format Pantalla: 16:9
======
Inclòs soport 4
======
Pel·lícula en DVD El Imperio Contraataca
3 € (IVA no inclos)
Idiomes: es,en
Format Pantalla: 16:9
======
Inclòs soport 5
======
Pel·lícula en VHS Los cazafantasmas
3.5 € (IVA no inclos)
Durada: 107 minuts
======
Inclòs soport 6
======
Pel·lícula en VHS El nombre de la Rosa
1.5 € (IVA no inclos)
Durada: 140 minuts
======
Inclòs soport 7
======
Llista de productes
7 productes disponibles

Joc per PS4: God of War 19.99 € (IVA no inclos) Per a 1 jugador Joc per PS4: The Last of Us Part II 49.99 € (IVA no inclos) Per a 1 jugador Pel·lícula en DVD Torrente 4.5 € (IVA no inclos) Idiomes: es Format Pantalla: 16:9 Pel·lícula en DVD Origen 4.5 € (IVA no inclos) Idiomes: es,en,fr Format Pantalla: 16:9 Pel·lícula en DVD El Imperio Contraataca 3 € (IVA no inclos) Idiomes: es,en Format Pantalla: 16:9 Pel·lícula en VHS Los cazafantasmas 3.5 € (IVA no inclos) Durada: 107 minuts Pel·lícula en VHS El nombre de la Rosa 1.5 € (IVA no inclos) Durada: 140 minuts

====== Inclòs soci Tofol Verdera amb número 1 ====== ====== Inclòs soci Biel Calafell amb número 2 ======

Llogat correctament: The Last of Us Part II a client: Tofol Verdera Llogat correctament: Torrente a client: Tofol Verdera Ja tens aquest suport "The Last of Us Part II" llogat. Has arribat al màxim de lloguers. Llista de socis

Client Tofol Verdera amb 2 lloguers. Client Biel Calafell amb 0 lloguers.

✏️ EXERCICI 133. Transforma Soport a una classe abstracta i comprova que tot continua funcionant. Què aconseguim en fer-la abstracta?

✏️ EXERCICI 134. Crea un interfície Resumible, de manera que les classes que l'implementin han d'oferir el mètode mostraResum(). Modifica la classe Soport i fes que implementi l'interfície. Fa falta que també l'implementin els fills?

Projecte Videoclub 2.0

Abans de començar amb la segona part del videoclub, crea una etiqueta mitjançant 'git tag' amb el nom 'v0.329' i puja els canvis a GitHub.

EXERCICI 135. Modifica les operacions de llogar, tant a Client com a Videoclub, per donar suport a l’encadenament de mètodes (revisa els apunts). Posteriorment, modifica el codi de prova per utilitzar aquesta tècnica.

EXERCICI 136. Fent ús de namespaces:

  • Col·loca totes les classes/interfaces a Dwes\ProjecteVideoclub
  • Cada classe ha de fer include_once dels recursos que utilitza
  • Col·loca els arxius de prova a la carpeta arrel (sense espai de noms)
  • Des de l’arxiu de proves, utilitza use per accedir sense qualificar
  • Etiqueta els canvis com a v0.331.

EXERCICI 137. Reorganitza les carpetes tal com hem vist en els apunts: app, test i vendor.

  • Crea un fitxer autoload.php per registrar les rutes on trobar les classes
  • Modifica tot el codi necessari, incloent autoload.php on calgui i elimina els includes previs.

EXERCICI 138. A continuació crearem un conjunt d’excepcions d’aplicació. Aquestes excepcions són simples, no necessiten sobreescriure cap mètode. Així, crea l’excepció d’aplicació VideoclubException al namespace Dwes\ProjecteVideoclub\Util. Posteriorment crea els fills següents (han d’heretar de VideoclubException), cadascun en el seu propi fitxer:

  • SoportJaLlogatException
  • QuotaSuperadaException
  • SoportNoTrobatException
  • ClientNoTrobatException

EXERCICI 139. A Client, modifica els mètodes llogar i tornar perquè facin ús de les noves excepcions (es llençaran quan calgui) i funcionin com a mètodes encadenats. Aquests mètodes no han de capturar les excepcions, només llençar-les. A Videoclub, modifica llogarSociProducte per capturar totes les excepcions que llença Client i informar l’usuari en conseqüència.

EXERCICI 140. Modifiquem el projecte perquè el videoclub sàpiga quins productes estan o no llogats:

  • A Soport, crea una propietat pública anomenada llogat que inicialment serà false. Quan es llogui, es posarà a true. Quan es torni, es tornarà a posar a false.
  • A Videoclub, crea dues propietats noves i els getters:
  • numProductesLlogats
  • numTotalLloguers

EXERCICI 141. Crea un mètode nou a Videoclub anomenat llogarSociProductes(int numSoci, array numerosProductos), que rebi un array amb els productes a llogar. Abans de llogar-los, ha de comprovar que tots els suports estiguin disponibles, de manera que si un no està, no se li llogui cap.

EXERCICI 142. Crea dos mètodes nous a Videoclub, i dedueix què han de fer:

  • tornarSociProducte(int numSoci, int numeroProducto)
  • tornarSociProductes(int numSoci, array numerosProductos)

Han de suportar l’encadenament de mètodes. Recorda actualitzar la propietat llogat dels diferents suports.

Quan hagis realitzat tots els exercicis, crea una etiqueta mitjançant git tag amb el nom v0.337 i puja els canvis a GitHub.