Many good IDEs for Webdevelopment cannot automatically understand the structure of a framework and its classes/objects. They need a small file initializing the objects so that they know in which context they appear.
E.g.: $this->Session (Session Helper) its impossible for the IDE to know that the the helpers are inside the View class. Same goes for controller components and model behaviors
I wrote a little script which produces mockup code. My IDE “PHPDesigner” works very well with it.
Usage
Drop this script into the /shells folder (either vendors or app).
Now just type cake cc inside the cake shell.
Code
<?php App::import('Core', 'Folder'); App::import('Core', 'File'); /** * Code Completion * 2009-12-26 ms */ class CcShell extends Shell { var $uses = array(); private $content = ''; function main() { $this->out('AutoComplete Dump'); //TODO: ask for version (1.2 etc - defaults to 1.3!) $this->filename = APP.'code_completion__.php'; # get classes $this->models(); $this->components(); $this->helpers(); //TODO: behaviors # write to file $this->_dump(); $this->out('...done'); } /** * @deprecated * now use: Configure::listObjects() */ function __getFiles($folder) { $handle = new Folder($folder); $handleFiles = $handle->read(true, true); $files = $handleFiles[1]; foreach ($files as $key => $file) { $file = extractPathInfo('file', $file); if (mb_strrpos($file, '_') === mb_strlen($file) - 1) { # ending with _ like test_.php unset($files[$key]); } else { $files[$key] = Inflector::camelize($file); } } return $files; } public function _getFiles($type) { $files = App::objects($type); # lib $paths = (array)App::path($type.'s'); $libFiles = App::objects($type, $paths[0] . 'lib' . DS, false); $plugins = App::objects('plugin'); if (!empty($plugins)) { foreach ($plugins as $plugin) { $pluginFiles = App::objects($type, App::pluginPath($plugin) . $type.'s' . DS, false); if (!empty($pluginFiles)) { foreach ($pluginFiles as $t) { $files[] = $t; //"$plugin.$type"; } } } } $files = array_merge($files, $libFiles); $files = array_unique($files); $appIndex = array_search('App', $files); if ($appIndex !== false) { unset($files[$appIndex]); } # no test/tmp files etc (helper.test.php or helper.OLD.php) foreach ($files as $key => $file) { if (strpos($file, '.') !== false || !preg_match('/^[\da-zA-Z_]+$/', $file)) { unset($files[$key]); } } return $files; } function models() { //$files = App::objects('component', null, false); $files = $this->_getFiles('model'); //$files = $this->_getFiles(COMPONENTS); $content = LF.'<?php'.LF; $content .= '/*** model start ***/'.LF; $content .= 'class AppModel extends Model {'.LF; if (!empty($files)) { $content .= $this->_prepModels($files); } $content .= '}'.LF; $content .= '/*** model end ***/'.LF; $content .= '?>'; $this->content .= $content; } function components() { $files = $this->_getFiles('component'); $content = LF.'<?php'.LF; $content .= '/*** component start ***/'.LF; $content .= 'class AppController extends Controller {'.LF; if (!empty($files)) { $content .= $this->_prepComponents($files); } $content .= '}'.LF; $content .= '/*** component end ***/'.LF; $content .= '?>'; $this->content .= $content; } function helpers() { $files = $this->_getFiles('helper'); $content = LF.'<?php'.LF; $content .= '/*** helper start ***/'.LF; $content .= 'class AppHelper extends Helper {'.LF; if (!empty($files)) { $content .= $this->_prepHelpers($files); } $content .= '}'.LF; $content .= '/*** helper end ***/'.LF; $content .= '?>'; $this->content .= $content; } function _prepModels($files) { $res = ''; foreach ($files as $name) { $res .= ' /** * '.$name.' */ public $'.$name.'; '.LF; } $res .= ' function __construct() {'; foreach ($files as $name) { $res .= ' $this->'.$name.' = new '.$name.'();'; } $res .= '}'.LF; return $res; } function _prepComponents($files) { $res = ''; foreach ($files as $name) { $res .= ' /** * '.$name.'Component */ public $'.$name.'; '.LF; } $res .= ' function __construct() {'; foreach ($files as $name) { $res .= ' $this->'.$name.' = new '.$name.'Component();'; } $res .= '}'.LF; return $res; } function _prepHelpers($files) { # new ones $res = ''; foreach ($files as $name) { $res .= ' /** * '.$name.'Helper */ public $'.$name.'; '.LF; } $res .= ' function __construct() {'; foreach ($files as $name) { $res .= ' $this->'.$name.' = new '.$name.'Helper();'; } # old ones $res .= ''.LF; /* foreach ($files as $name) { $res .= ' $'.lcfirst($name).' = new '.$name.'Helper(); '; } $res .= LF; */ $res .= ' }'.LF; return $res; } function _dump() { $file = new File($this->filename, true); $content = '<?php exit();'.LF; $content .= '//Add in some helpers so the code assist works much better'.LF; $content .= '//Printed: '.date('d.m.Y, H:i:s').LF; $content .= '?>'.LF; $content .= $this->content; return $file->write($content); } } ?>
Result
The file will look like:
class AppModel extends Model { /** * Address */ public $Address; ... function __construct() { $this->Address = new Address(); ... } } class AppController extends Controller { /** * AclComponent */ public $Acl; ... function __construct() { $this->Acl = new AclComponent(); ... } } class AppHelper extends Helper { /** * AjaxHelper */ public $Ajax; ... function __construct() { $this->Ajax = new AjaxHelper(); ... } }
Final notes
Feel free to update the TODOs and send me the improved file. A test file would be awesome, too, i guess
For LF constants see my article about “bootstrap goodies”.
