- Model: Transfer Objects (Beans) - e.g., Page, User, Configuration
- DAO Layer: Data Access Objects handle persistence
- Base DAO: Extends PDO, provides base CRUD operations
- XmlDAO: For XML file-based storage
- SqliteDAO: For SQLite database storage (extends DAO, uses PDO)
- View: Template-based rendering with token replacement
- Controller: Handles business logic and coordinates Model/View
Helper classes provide utility/factory methods for specific managers. They serve THREE purposes:
- Lazy loading of DAO, Controller, and Bean classes
- Factory pattern for creating DAO instances (using static variable caching)
- Convenience methods for common operations
Critical Pattern: Helper methods use static $variable for caching DAO instances:
function getDao($refresh=false) {
static $Dao; // Cached across calls
if (! is_object($Dao) || $refresh) {
if (! class_exists('SomeDAO')) {
SomeHelper::initialize();
}
$Dao = new SomeDAO();
}
return $Dao;
}IMPORTANT: Helpers are called STATICALLY throughout the codebase (Helper::method()), but methods may NOT be declared static. This is the PHP 8 incompatibility!
- Abstract layer over PDO
- Child classes: SqliteDAO, XmlDAO
- Methods: index(), getItem(), insert(), update(), delete()
- Constructor requires DB_HOST, DB_USER, DB_PASS constants
- These are defined in Config::load()
- Uses PDO with SQLite DSN:
"sqlite:" . DB_HOST
- Stores data in XML files under
/custom/data/xml/ - Uses Core->xmlHandler for XML parsing
- No database constants needed
index.php
→ define constants
→ require base.php
→ loads all core classes
→ loads MVC.php
→ loads Controller, View, DAO base classes
→ loads SqliteDAO from /custom/daos/
→ new Core()
→ LoadConstants() - defines SB_MANAGERS_DIR, etc.
→ LoadHelperClasses()
→ Loads PluginHelper
→ Loads PageHelper
→ Config::load()
→ ConfigurationHelper::getConfiguration()
→ ConfigurationHelper::getDao()
→ ConfigurationHelper::initialize()
→ loads ConfigurationDAO (extends SqliteDAO)
→ loads Configuration bean
→ loads ConfigurationController (extends Controller)
→ $Core->GetActiveSkin()
→ SkinHelper::getActiveSkin()
→ SkinHelper::getDao()
→ new SkinDAO() (extends SqliteDAO - needs DB constants)
Used for shared instances: Session, LanguageHelper, RequestObject, Authenticate, Authorize
$Session = Singleton::getInstance('Session');- Core extends Publisher
- Event::register(), Event::trigger()
- Events: beforeInitPage, afterShowPage, etc.
Helper classes have methods called statically but NOT declared static.
In PHP 5.x, this worked:
class Helper {
function getDao() { /*...*/ } // NOT static
}
Helper::getDao(); // Called statically - works in PHP 5In PHP 8.2, this generates "Non-static method cannot be called statically" fatal error OR causes infinite loops/hangs.
- Convenience:
ConfigurationHelper::getConfiguration()is simpler than$helper = new ConfigurationHelper(); $helper->getConfiguration(); - Caching: Using
static $Daoinside methods provides cross-call caching - Factory Pattern: Helpers act as factories, not stateful objects
From the codebase analysis:
- ConfigurationHelper - methods called statically but not declared static
- SkinHelper - methods called statically but not declared static
- CheckoutsHelper - methods called statically but not declared static
- FileSystem - methods called statically but not declared static
- PageHelper - methods called statically but not declared static (partially fixed)
- Event, Timer, Loader - already fixed
Make Helper methods static where they're called statically:
- Identify which methods are called with
:: - Add
statickeyword to method declarations - Test that
static $varcaching still works (it does)
ConfigurationController loading hangs the system.
From debug logs, execution stops when requiring ConfigurationController.php. The file loads fine in isolation but hangs in the full framework context. This suggests:
- Circular dependency: Something ConfigurationController needs tries to load ConfigurationController again
- Missing dependency: Controller.php loads CheckoutsHelper which may have issues
- PHP 8 incompatibility: Some code in the loading chain causes infinite recursion
Next steps: Need to trace EXACTLY what happens when ConfigurationController.php is required in the actual runtime environment, not test scripts.
/src
/skyblue - Core framework
/includes - Core classes (Core, Config, Event, etc.)
/mvc - MVC base classes (Controller, View, DAO, Loader)
/auth - Authentication/Authorization
/utils - Utility classes
/managers - Business logic modules
/configuration
/page
/skin
/users
/menus
(etc.)
/config - Configuration files and constants
/plugins - System plugins
/custom - User/site-specific overrides
/daos - Custom DAO implementations
/plugins - User plugins
/data - Data storage
/xml - XML data files
/data.sqlite - SQLite database
/webroot - Public web files
index.php - Frontend entry point
src/webroot/index.php- Frontend entry pointsrc/skyblue/base.php- Loads all core framework filessrc/skyblue/includes/Core.php- Core framework classsrc/skyblue/includes/Config.php- Configuration loadersrc/skyblue/includes/mvc/MVC.php- MVC framework loadersrc/skyblue/includes/mvc/Controller.php- Base controllersrc/skyblue/includes/mvc/DAO.php- Base DAO (extends PDO)src/custom/daos/SqliteDAO.php- SQLite DAO implementation