Tobie też by się takie ćwiczenie przydało, skoro napisałeś taki post

. W jednym masz rację: słowo
abstract też powinno znaleźć się na liście słów zakazanych, bo bez
extends nie ma sensu

.
A czemu, przecież napisałem:
Cytat
(...) to jest istota programowania obiektowego ogołocona ze wszystkich ogłupiaczy. Dopiero gdy się tego nauczysz, będziesz wiedział, że cała reszta to zwykły lukier składniowy i pomoc, która jednak jest pomocą tylko wtedy, gdy znajduje się w doświadczonych rękach.
Programowanie obiektowe to nie są klasy abstrakcyjne,
static czy
extends. To sposób myślenia i projektowania. Dopóki ktoś się go nie nauczy, będzie jedynie programistą, który umie używać klas oraz dziedziczenia i nic poza tym. Klasy abstrakcyjne, dziedziczenie i cała reszta to jedynie narzędzia i lukier składniowy. OK, dziedziczenie nie do końca się do tego zalicza, ale akurat jest jedną z bardziej zwodniczych koncepcji. Naucz się najpierw dobrze podstaw, a później siadaj za pulpitem sterowniczym elektrowni jądrowej.
--- [odpowiedź dla kilera] ----
Który sposób będzie tam poprawny? Nie ma na to pytanie jednej odpowiedzi, może poza tym, że ID to ja bym jako argument przekazywał, jeśli już

. Zapytasz się mnie, co w sytuacji, gdy identyfikacja wiersza wymaga większej liczby pól, a ja Ci odpowiem: niech argument z identyfikatorem będzie obiektem implementującym interfejs
Identifier. Wtedy sobie zaimplementujesz różne typy identyfikatorów, jakie masz w aplikacji i będziesz mógł nimi operować w sposób uniwersalny. To jest właśnie przykład obiektowego podejścia.
A dlaczego żadnemu z Twoich sposobów nie można nadać etykietki "poprawny"/"niepoprawny"? Ponieważ tutaj to już tak naprawdę zależy od tego, co chcesz zrobić i co te Twoje obiekty mają reprezentować. Metoda #2 to zwykłe mapowanie obiektowo-relacyjne, gdzie obiekty reprezentują jeden wiersz w bazie. Jest to popularne, zwłaszcza w zastosowaniach typu CRUD, natomiast do bardziej zaawansowanych rzeczy ja preferuję metodę #1 ze wspomnianą już modyfikacją, ponieważ jest ona bardziej ogólna i mniej przekombinowana w przypadku złożonych schematów.
Co do przykładu z cache, to wyjaśnij mi, czym to, co zrobiłeś, różni się od wywołania funkcji np.
apc_get(), albo zwykłego wstawienia
global? Ja Ci już podpowiem prawidłową odpowiedź, że absolutnie niczym. Przede wszystkim kto powiedział, że potrzebujesz dokładnie jeden obiekt cache'u? Pomyśl. Cache'ujemy różne rodzaje danych, różne rodzaje danych mają różne wymagania (cykliczne aktualizacje, aktualizacje na żądanie, dłuższe, krótsze itp. itd.)? Wprowadzasz tu pojęcie zasobu (np. "konfiguracja", "dane", "kod HTML"), polityki (czyli jakiej funkcjonalności oczekujesz od cache'u) oraz strategii (czyli już konkretna implementacja). Politykę kodujesz jako interfejs, strategię jako klasę implementującą ten interfejs, a zasób jako pytanie do menedżera obiektów strategii "panie, podaj mi tu obiekt, który potrafi cache'ować zasób z rodziny 'konfiguracja'". Dostajesz obiekt, upewniasz się co do obsługiwanej przez niego polityki, robisz operacje i po sprawie. Chcesz zmienić strategię dla konkretnego zasobu, w menedżerze rejestrujesz dla niego inną strategię i tyle.
Cytat
Problem jest jednak taki, że nie mam za bardzo czasu na dokładne teoretyczne studiowanie tego tylko uczę się przy okazji stałego rozwijania CMSu (który bądź co bądź na mnie zarabia poniekąd).
Dlatego radzę Ci, byś zostawił tego CMS-a w takim kształcie, jak on jest (ew. nie bawił się tu na razie w obiektówkę), a zaoszczędzony czas poświęcił na jakieś prostsze ćwiczenia. Szkoda marnować i wspomniany czas, i CMS-a nieudolną przebudową. CMS Ci nie ucieknie, a dzięki temu później zrobisz go lepiej i szybciej. Ja np. bardzo żałuję, że w czasach, gdy miałem swoje pierwsze próby z klasami (11 lat temu), nie było nikogo, kto by mi powiedział to, co napisałem teraz Tobie, przez co mnóstwo mojej pracy poszło na marne.