1. xPDOSimpleObject extends xPDOObject. The only real difference is that xPDOSimpleObject has a built-in, autoincrement, primary key named 'id' so you don't have to create one. If you look closely at the Doodles tutorial, you'll see that the base class is xPDOObject, but the Doodle class itself extends xPDOSimpleObject.
2. Once the class and map files are generated, you can do whatever you want (within reason) to the class files and add any functionality you want. You can certainly add the $this->modx reference to the constructor and getChunk(), or any other methods you want.
3. I have never completely understood the differences between getService(), addPackage(), and loadClass() and I find the docs on them thin and misleading.
addPackage() supposedly loads the class and sets up the paths to the directories of the package, but with this code, addPackage() is successful and loadClass() fails:
$loginModelPath = MODX_CORE_PATH . 'components/login/model/';
$success = $modx->addPackage('Login',$loginModelPath , '');
echo "\naddPackage " . ($success? 'OK' : 'Failed');
// OK
$success = $modx->loadClass('login.Login');
echo "\nloadClass " . ($success ? 'OK' : 'Failed');
// Failed
The docs imply that addPackage() will let you access other classes in the package, but this code works fine without addPackage():
$loginModelPath = MODX_CORE_PATH . 'components/login/model/';
$success = $modx->loadClass('recaptcha.reCaptcha', $loginModelPath, true, true);
$reCaptcha = new reCaptcha($modx);
I've never been sure what addPackage() does that loadClass() doesn't. My best guess is that addPackage() also loads the class metadata, which would mean that it's only useful for classes that represent objects in the database.
getService() loads the class file, but it also adds the class to the $modx object. So if you've added the doodles class with getService(), for example, you could use $modx->doodles->getChunk(). This will work inside another class or anywhere the $modx object is available. This is very handy for CMPs like Doodles. It returns null on failure, and as long as you include the path, you don't need to run either addPackage() or loadClass() before calling it:
$loginModelPath = MODX_CORE_PATH . 'components/login/model/';
$success = $modx->getService('login', 'login.Login', $loginModelPath);
echo "\ngetService" . ($success != null ? 'OK' : 'Failed');
// OK
if ($modx->login instanceof Login) {
echo "\n Login OK";
}
// Login OK
Both addPackage() and loadClass() return false on failure, but I've found that in some circumstances (e.g., when you fail to include the path), they can return non-false but you still can't instantiate the class.
Again, I'm guessing somewhat, but I think this is about right:
- If you just want to instantiate some class that doesn't represent a DB object, use loadClass().
- If you want to instantiate some class that *does* represent a DB object and have generated class and map files for it, use addPackage().
- If you want the class to be available as $modx->className, or if the class is already registered as a MODX service (e.g., modMail, modLexicon, modError) use getService(). In the latter case, you don't need a path.
Hopefully, someone more enlightened will chime in here and clarify this.