Goede avond allemaal,

Ik ben al enige tijd bezig met het uitdenken van een CMS. Ik probeer zoveel mogelijk functionaliteiten in te voegen zodat ik gelijk op veel punten terecht kom en zoveel mogelijk leer. Dat is immers het voornaamste doel van dit project.

Nu heeft Wouter J mij in een vorig topic behoorlijk geholpen. Aan de hand hiervan ben ik toch nog verder gaan zoeken naar uitleg over interfaces en abstract classes. Ik vroeg mij nu af gebruik ik het nu niet overkill? Is mijn huidige opzet wel OOP? Zou ik hiermee verder kunnen als ik een simpele cms wil bouwen? Mis ik dingen?

Mij nieuwe opzet is hier te vinden: klikerdeklik

Altijd in voor opbouwende kritiek.

Gr, Milo
Ik zou alle delete() methods weghalen uit de view classes. In mijn ervaring gebruik je dat nooit. Je maakt de pagina pas op op het moment dat je alle gegevens hebt, dus je weet op dat moment al wat er op de pagina moet komen en wat niet.
In je hele applicatie maar 1 interface? Elke klasse heeft recht op zijn interface.

Tevens heb je het nut van interfaces nog niet helemaal door. Een constructor is naar mijn mening totaal niet iets wat in een interface thuis hoort. Een interface voeg je toe om zeker te zijn dat een bepaalde klasse bepaalde methods heeft. Bijv:
<?php
class Dog
{
public function playSound()
{
echo 'Woefwaf';
}
}
class Person
{
private $animal;

public function setAnimal(Dog $animal)
{
$this->animal = $animal;
}

public function makeAnimalHappy()
{
$this->animal->playSound();
}
}

$dog = new Dog();
$person = new Person($dog);

$person->makeAnimalHappy(); // >> 'woefwaf'
?>
Nu typehinten we op de Dog klasse, dit zorgt ervoor dat de $animal property alleen een Dog klasse kan zijn. Hierdoor weten we zeker welke methods hij heeft.

Maar stel je voor dat onze persoon geen hond maar een kat heeft? Dan werkt deze methode dus niet. We moeten onze applicatie met het oog op flexibiliteit dus aanpassen. Hoe kunnen we er nou voor zorgen dat de method playSound() beschikbaar is in de Person klasse? Dat doen we door alle dieren een interface te laten implementeren die vastlegt dat deze klasse minimaal de method playSound heeft:
<?php
interface AnimalInterface
{
public function playSound();
}

class Dog implements AnimalInterface
{
public function playSound()
{
echo 'Woefwaf';
}
}
class Cat implements AnimalInterface
{
public funciton playSound()
{
echo 'Miau';
}
}

// we kunnen ook leuke dingen doen :)
abstract class SilentAnimal implements AnimalInterface
{
final public function playSound()
{
echo '';
}
}
// deze is nu stil, hij kan NOOIT geluid maken
class Ant extends SilentAnimal
{
}

class Person
{
// ...
public function setAnimal(AnimalInterface $animal)
{
$this->animal = $animal;
}
// ...
}
?>

[offtopic]Sorry, dit gaat weer alleen over interfaces. Ik kijk binnenkort nog wel eens naar het complete plaatje.[/offtopic]
Als ik het alleen even over de User_Interface, User klasse, abstracte Role klasse en de moderator / admin / customer klasse heb zou ik het heel anders moeten doen.
Omdat ik in alle gevallen een username en password wil weten van een gebruiker zal ik dit vast kunnen stellen in mijn interface.


+---------------------+
|    User_Interface   |
+---------------------+
|   + getUsername()   |
|   + setUsername()   |
|   + getPassword()   |
|   + setPassword()   |
+---------------------+


Vervolgens kan ik hier mijn userclasse op implenteren. Als ik dan de rollen erbij haal, moderator / administrator / klant extend ik deze van elkaar of de abstracte Role klasse.


+-------------------+
|       Role        | (abstract)
+-------------------+
|   + getRights()   |
|   + setRights()   |
+-------------------+

+-------------------+
|      Customer     | (extends Role)
+-------------------+
|   + getRole()     |
|   + setRole()     |
|   + getAdress()   |
|   + setAdress()   |
+-------------------+


+-------------------+
|       Moderator   | (extends Role)
+-------------------+
|   + getRole()     |
|   + setRole()     |
|   eventuele extra |
|   functies van    |
|   een moderator   |
|   ophalen         |
+-------------------+


+-------------------+
|       Admin       | (extends Moderator)
+-------------------+
|   + getRole()     |
|   + setRole()     |
|   eventuele extra |
|   functies van    |
|   een admin       |
|   ophalen         |
+-------------------+


Is dit een beetje het princiepe wat jullie bedoelen? Of zou jij, Wouter, zeggen Roles moet ook een interface hebben om zo zijn punten vast te leggen? Door nu een abstract klasse ervan te maken heb ik toch altijd de benodigde functies maar kan ik toch (eventueel) oneindig uitbreiden.

@ Erwin,
Zo had ik hier nooit over nagedacht. Als je dat wel doet zie je inderdaad in dat de kans klein is dat jij met een klasse (bijvoorbeeld) je formulier veld weghaalt. Aan de andere kant stel nou dat het wel nodig is?
Goedeavond,

Ik ben nog steeds bezig met hetzelfde systeem, steeds probeer ik vraagstukken uit te sluiten en ben tot de conclusie gekomen dat ik het graag een stap voor stap wil doorlopen. Als de eerste basis maar goed is dan kan ik namelijk met een goede ondergrond verder borduren. Ik ga proberen minstens iedere avond een stap verder te komen, willen jullie mij hierbij helpen?

De eerste opzet voor de interfaces en klasse ziet er als volgt uit:

User_Interface
User [color=red]implements[/color] User_Interface
Authentication [color=red]implements[/color] User_Interface

Role_Interface
Role [color=red]implements[/color] Role_Interface
Moderator [color=red]extends[/color] Role
Administrator [color=red] extends [/color] Role

User_Mapper_Interface
User_Mapper [color=red]implements[/color] User_Interface

De rollen staan bij de gebruiker in de database. Hier hoef ik dan geen Role_Mapper voor aan te maken, want dat gaat dan via de User_Mapper, toch?


Page_Interface
Page [color=red]implements[/color] Page_Interface
News [color=red]extends[/color] Page

Page_Mapper_Interface
Page_Mapper [color=red]implements[/color] Page_Interface


de nieuws klasse implenteer ik in de page klasse, omdat dit feitelijk hetzelfde is plus wat uitbreidingen. Voor de Page mapper geld dan dus ook dat hij ook data van de News klasse kan opslaan, of moet ik hier dan wel een extra mapper voor gebruiken?


Image_Interface
Image [color=red]implements[/color] Image_Interface

Image _Mapper_Interface
Image_Mapper [color=red]implements[/color] Image_Interface


Database_Interface
Database [color=red]implements[/color] Database_Interface
MySQL [color=red] extends [/color] Database


Wat vinden jullie, waar liggen de opmerkingen, graag hoor ik ze en wat dan de betere oplossing zou zijn.
Allereerst zou ik eens gaan nadenken welke naming conventions je gaat gebruiken. Ik raad je de PSR-0 standaarden aan. Deze zijn opgezet door de PHP Fig (Framework Integration Group). Deze groep wil bereiken dat iedereen ong. dezelfde standaarden gebruikt, waardoor je erg makkelijk iemand anders library kan gebruiken.

Authentication implements User_Interface

Lijkt me niet correct. UserInterface zou de overkoppelende factor voor een User moeten zijn. Authentication is het kijken wie de huidige bezoeker is. Authentication gaat uit eindelijk een User maken.

Role implements Role_Interface

Gewoon om even zeker te zijn, Role is abstract?

User_Mapper_Interface
User_Mapper implements User_Interface

Allereerst zou ik geen specifieke mapper interfaces voor elke mapper maken. Ik zou 1 grote MapperInterface maken die sowieso de CRUD (create, read, update en delete) functies verplicht stelt.

Ten tweede moet de UserMapper ook totaal geen UserInterface implementeren. Overal waar je 'implements' hebt staan moet je kunnen veranderen in 'IS EEN'. Je kan niet zeggen UserMapper IS EEN User.

De rollen staan bij de gebruiker in de database. Hier hoef ik dan geen Role_Mapper voor aan te maken, want dat gaat dan via de User_Mapper, toch?

Exact

de nieuws klasse implenteer ik in de page klasse, omdat dit feitelijk hetzelfde is plus wat uitbreidingen. Voor de Page mapper geld dan dus ook dat hij ook data van de News klasse kan opslaan, of moet ik hier dan wel een extra mapper voor gebruiken?

Als de News klasse andere waardes bevat dan de page klasse heb je hiervoor een aparte mapper nodig.

Page_Mapper implements Page_Interface

Weer hetzelfde als voor UserMapper en Authentication.

Image_Interface
Image implements Image_Interface

Ik zou je interface globaler maken, bijv. MediaInterface. Hierdoor heb je mooi alle typen media, youtube filmpje, afbeelding, ect. op gevangen. Tevens kun je alsnog een ImageInterface behouden als je vindt dat de afbeelding andere methods heeft dan een youtube filmpje. Je krijgt dan Image implements MediaInterface, ImageInterface

Image_Mapper implements Image_Interface

Zie andere Mapper opmerkingen

Database implements Database_Interface
MySQL extends Database

Om duidelijk te maken zou ik MySQL suffixen met 'Database', MySQLDatabase.
MapperInterface

UserInterface
User [color=red]extends[/color] UserInterface
Authentication

RoleInterface
Role [color=green]abstract[/color] [color=red]implements[/color] RoleInterface
Moderator [color=red]extends[/color] Role
Administrator [color=red]extends[/color] Role

UserMapper [color=red]extends[/color] User


PageInterface
Page [color=red]implements[/color] PageInterface
News [color=red]extends[/color] Page

PageMapper [color=red]extends[/color] Page
NewsMapper [color=red]extends[/color] News


MediaInterface
Image [color=red]implements[/color] MediaInterface
Image_Mapper [color=red]extends[/color] Image

Bij de media interface kunnen altijd andere media klasse worden toegevoegd, bijvoorbeeld een music klasse...

Ik vraag mij af of ik wel een dergelijke database klasse nodig heb, kan ik hier niet PDO voor gebruiken? Nadeel zou zijn dat ik heel de zooi aan moet passen wanneer ik iets anders wil gebruiken. Hoe zien jullie dat?
Kloppen mijn aanpassingen nu wel? Ik kan niet wachten om verder te borduren...
Oké, je hebt de relaties nog steeds niet door. Allereerst kan 'UserMapper implements User' natuurlijk nooit, User is een klasse en moet dus geëxtend worden. En vervolgens zeg je nu UserMapper IS EEN User, is dat waar?

Lees eens deze tutorial over relaties tussen objecten: http://wouterj.nl/php/oo-de-onbekende-kant/476/

Page abstract implements PageInterface

Dit betekend dat Page niet op zichzelf staat, maar alleen als een overkoepelende klasse mag gebruikt worden. Vindt je dat echt?
Jou tutorial gelezen te hebben ben ik tot de volgende conclusie gekomen...

IS EEN = implements
HEEFT EEN = extens

Niet waar?

Wat betreft de page class ben ik dronken geweest denk ik.

Mijn gedachte gang was dat ik de methodes van page wilde vast stellen voor de news klasse, maar die extend al van page welke die functies al verplicht is door de pageInterface.
Snap je wat ik bedoel?

Ik voer de wijzigingen door en ben benieuwd of dit dan de sleutel is..
Niet waar?

Inderdaad, dat is niet waar. :) Zowel extends als implements is een IS EEN relatie. Een HEEFT EEN relatie is niet iets wat je vastlegt bij het definiëren van een klasse. Een voorbeeld:
<?php
class Page
{
// ...
}

// NewsPost IS EEN Page
class NewsPost extends Page
{
private $author;

// NewsPost HEEFT EEN Author
public function setAuthor(User $author)
{
$this->author = $author;
}
}
?>

Allereerst kan 'UserMapper implements User' natuurlijk nooit, User is een klasse en moet dus geëxtend worden


Dan hier van uitgaande ga ik de volgende gedurfde uitspraak doen... Je gebruikt extends zodra je een class IS EEN class relatie hebt en je gebruikt implements zodra je een class IS EEN interface relatie hebt.

Of ga ik nu helemaal stom brabbelen?

Reageren