CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 2.6 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 2.6
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Packages

  • Cake
    • Cache
      • Engine
    • Configure
    • Console
      • Command
        • Task
    • Controller
      • Component
        • Acl
        • Auth
    • Core
    • Error
    • Event
    • I18n
    • Log
      • Engine
    • Model
      • Behavior
      • Datasource
        • Database
        • Session
      • Validator
    • Network
      • Email
      • Http
    • Routing
      • Filter
      • Route
    • TestSuite
      • Coverage
      • Fixture
      • Reporter
    • Utility
    • View
      • Helper

Classes

  • ConsoleErrorHandler
  • ConsoleInput
  • ConsoleInputArgument
  • ConsoleInputOption
  • ConsoleInputSubcommand
  • ConsoleOptionParser
  • ConsoleOutput
  • HelpFormatter
  • Shell
  • ShellDispatcher
  • TaskCollection
  1: <?php
  2: /**
  3:  * ConsoleOptionParser file
  4:  *
  5:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  6:  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  7:  *
  8:  * Licensed under The MIT License
  9:  * For full copyright and license information, please see the LICENSE.txt
 10:  * Redistributions of files must retain the above copyright notice.
 11:  *
 12:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 13:  * @link          http://cakephp.org CakePHP(tm) Project
 14:  * @since         CakePHP(tm) v 2.0
 15:  * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 16:  */
 17: 
 18: App::uses('TaskCollection', 'Console');
 19: App::uses('ConsoleOutput', 'Console');
 20: App::uses('ConsoleInput', 'Console');
 21: App::uses('ConsoleInputSubcommand', 'Console');
 22: App::uses('ConsoleInputOption', 'Console');
 23: App::uses('ConsoleInputArgument', 'Console');
 24: App::uses('ConsoleOptionParser', 'Console');
 25: App::uses('HelpFormatter', 'Console');
 26: 
 27: /**
 28:  * Handles parsing the ARGV in the command line and provides support
 29:  * for GetOpt compatible option definition. Provides a builder pattern implementation
 30:  * for creating shell option parsers.
 31:  *
 32:  * ### Options
 33:  *
 34:  * Named arguments come in two forms, long and short. Long arguments are preceded
 35:  * by two - and give a more verbose option name. i.e. `--version`. Short arguments are
 36:  * preceded by one - and are only one character long. They usually match with a long option,
 37:  * and provide a more terse alternative.
 38:  *
 39:  * ### Using Options
 40:  *
 41:  * Options can be defined with both long and short forms. By using `$parser->addOption()`
 42:  * you can define new options. The name of the option is used as its long form, and you
 43:  * can supply an additional short form, with the `short` option. Short options should
 44:  * only be one letter long. Using more than one letter for a short option will raise an exception.
 45:  *
 46:  * Calling options can be done using syntax similar to most *nix command line tools. Long options
 47:  * cane either include an `=` or leave it out.
 48:  *
 49:  * `cake myshell command --connection default --name=something`
 50:  *
 51:  * Short options can be defined signally or in groups.
 52:  *
 53:  * `cake myshell command -cn`
 54:  *
 55:  * Short options can be combined into groups as seen above. Each letter in a group
 56:  * will be treated as a separate option. The previous example is equivalent to:
 57:  *
 58:  * `cake myshell command -c -n`
 59:  *
 60:  * Short options can also accept values:
 61:  *
 62:  * `cake myshell command -c default`
 63:  *
 64:  * ### Positional arguments
 65:  *
 66:  * If no positional arguments are defined, all of them will be parsed. If you define positional
 67:  * arguments any arguments greater than those defined will cause exceptions. Additionally you can
 68:  * declare arguments as optional, by setting the required param to false.
 69:  *
 70:  * `$parser->addArgument('model', array('required' => false));`
 71:  *
 72:  * ### Providing Help text
 73:  *
 74:  * By providing help text for your positional arguments and named arguments, the ConsoleOptionParser
 75:  * can generate a help display for you. You can view the help for shells by using the `--help` or `-h` switch.
 76:  *
 77:  * @package       Cake.Console
 78:  */
 79: class ConsoleOptionParser {
 80: 
 81: /**
 82:  * Description text - displays before options when help is generated
 83:  *
 84:  * @see ConsoleOptionParser::description()
 85:  * @var string
 86:  */
 87:     protected $_description = null;
 88: 
 89: /**
 90:  * Epilog text - displays after options when help is generated
 91:  *
 92:  * @see ConsoleOptionParser::epilog()
 93:  * @var string
 94:  */
 95:     protected $_epilog = null;
 96: 
 97: /**
 98:  * Option definitions.
 99:  *
100:  * @see ConsoleOptionParser::addOption()
101:  * @var array
102:  */
103:     protected $_options = array();
104: 
105: /**
106:  * Map of short -> long options, generated when using addOption()
107:  *
108:  * @var string
109:  */
110:     protected $_shortOptions = array();
111: 
112: /**
113:  * Positional argument definitions.
114:  *
115:  * @see ConsoleOptionParser::addArgument()
116:  * @var array
117:  */
118:     protected $_args = array();
119: 
120: /**
121:  * Subcommands for this Shell.
122:  *
123:  * @see ConsoleOptionParser::addSubcommand()
124:  * @var array
125:  */
126:     protected $_subcommands = array();
127: 
128: /**
129:  * Command name.
130:  *
131:  * @var string
132:  */
133:     protected $_command = '';
134: 
135: /**
136:  * Construct an OptionParser so you can define its behavior
137:  *
138:  * @param string $command The command name this parser is for. The command name is used for generating help.
139:  * @param bool $defaultOptions Whether you want the verbose and quiet options set. Setting
140:  *  this to false will prevent the addition of `--verbose` & `--quiet` options.
141:  */
142:     public function __construct($command = null, $defaultOptions = true) {
143:         $this->command($command);
144: 
145:         $this->addOption('help', array(
146:             'short' => 'h',
147:             'help' => __d('cake_console', 'Display this help.'),
148:             'boolean' => true
149:         ));
150: 
151:         if ($defaultOptions) {
152:             $this->addOption('verbose', array(
153:                 'short' => 'v',
154:                 'help' => __d('cake_console', 'Enable verbose output.'),
155:                 'boolean' => true
156:             ))->addOption('quiet', array(
157:                 'short' => 'q',
158:                 'help' => __d('cake_console', 'Enable quiet output.'),
159:                 'boolean' => true
160:             ));
161:         }
162:     }
163: 
164: /**
165:  * Static factory method for creating new OptionParsers so you can chain methods off of them.
166:  *
167:  * @param string $command The command name this parser is for. The command name is used for generating help.
168:  * @param bool $defaultOptions Whether you want the verbose and quiet options set.
169:  * @return ConsoleOptionParser
170:  */
171:     public static function create($command, $defaultOptions = true) {
172:         return new ConsoleOptionParser($command, $defaultOptions);
173:     }
174: 
175: /**
176:  * Build a parser from an array. Uses an array like
177:  *
178:  * ```
179:  * $spec = array(
180:  *      'description' => 'text',
181:  *      'epilog' => 'text',
182:  *      'arguments' => array(
183:  *          // list of arguments compatible with addArguments.
184:  *      ),
185:  *      'options' => array(
186:  *          // list of options compatible with addOptions
187:  *      ),
188:  *      'subcommands' => array(
189:  *          // list of subcommands to add.
190:  *      )
191:  * );
192:  * ```
193:  *
194:  * @param array $spec The spec to build the OptionParser with.
195:  * @return ConsoleOptionParser
196:  */
197:     public static function buildFromArray($spec) {
198:         $parser = new ConsoleOptionParser($spec['command']);
199:         if (!empty($spec['arguments'])) {
200:             $parser->addArguments($spec['arguments']);
201:         }
202:         if (!empty($spec['options'])) {
203:             $parser->addOptions($spec['options']);
204:         }
205:         if (!empty($spec['subcommands'])) {
206:             $parser->addSubcommands($spec['subcommands']);
207:         }
208:         if (!empty($spec['description'])) {
209:             $parser->description($spec['description']);
210:         }
211:         if (!empty($spec['epilog'])) {
212:             $parser->epilog($spec['epilog']);
213:         }
214:         return $parser;
215:     }
216: 
217: /**
218:  * Get or set the command name for shell/task.
219:  *
220:  * @param string $text The text to set, or null if you want to read
221:  * @return string|$this If reading, the value of the command. If setting $this will be returned.
222:  */
223:     public function command($text = null) {
224:         if ($text !== null) {
225:             $this->_command = Inflector::underscore($text);
226:             return $this;
227:         }
228:         return $this->_command;
229:     }
230: 
231: /**
232:  * Get or set the description text for shell/task.
233:  *
234:  * @param string|array $text The text to set, or null if you want to read. If an array the
235:  *   text will be imploded with "\n"
236:  * @return string|$this If reading, the value of the description. If setting $this will be returned.
237:  */
238:     public function description($text = null) {
239:         if ($text !== null) {
240:             if (is_array($text)) {
241:                 $text = implode("\n", $text);
242:             }
243:             $this->_description = $text;
244:             return $this;
245:         }
246:         return $this->_description;
247:     }
248: 
249: /**
250:  * Get or set an epilog to the parser. The epilog is added to the end of
251:  * the options and arguments listing when help is generated.
252:  *
253:  * @param string|array $text Text when setting or null when reading. If an array the text will be imploded with "\n"
254:  * @return string|$this If reading, the value of the epilog. If setting $this will be returned.
255:  */
256:     public function epilog($text = null) {
257:         if ($text !== null) {
258:             if (is_array($text)) {
259:                 $text = implode("\n", $text);
260:             }
261:             $this->_epilog = $text;
262:             return $this;
263:         }
264:         return $this->_epilog;
265:     }
266: 
267: /**
268:  * Add an option to the option parser. Options allow you to define optional or required
269:  * parameters for your console application. Options are defined by the parameters they use.
270:  *
271:  * ### Options
272:  *
273:  * - `short` - The single letter variant for this option, leave undefined for none.
274:  * - `help` - Help text for this option. Used when generating help for the option.
275:  * - `default` - The default value for this option. Defaults are added into the parsed params when the
276:  *    attached option is not provided or has no value. Using default and boolean together will not work.
277:  *    are added into the parsed parameters when the option is undefined. Defaults to null.
278:  * - `boolean` - The option uses no value, its just a boolean switch. Defaults to false.
279:  *    If an option is defined as boolean, it will always be added to the parsed params. If no present
280:  *    it will be false, if present it will be true.
281:  * - `choices` A list of valid choices for this option. If left empty all values are valid..
282:  *   An exception will be raised when parse() encounters an invalid value.
283:  *
284:  * @param ConsoleInputOption|string $name The long name you want to the value to be parsed out as when options are parsed.
285:  *   Will also accept an instance of ConsoleInputOption
286:  * @param array $options An array of parameters that define the behavior of the option
287:  * @return $this
288:  */
289:     public function addOption($name, $options = array()) {
290:         if (is_object($name) && $name instanceof ConsoleInputOption) {
291:             $option = $name;
292:             $name = $option->name();
293:         } else {
294:             $defaults = array(
295:                 'name' => $name,
296:                 'short' => null,
297:                 'help' => '',
298:                 'default' => null,
299:                 'boolean' => false,
300:                 'choices' => array()
301:             );
302:             $options += $defaults;
303:             $option = new ConsoleInputOption($options);
304:         }
305:         $this->_options[$name] = $option;
306:         if ($option->short() !== null) {
307:             $this->_shortOptions[$option->short()] = $name;
308:         }
309:         return $this;
310:     }
311: 
312: /**
313:  * Add a positional argument to the option parser.
314:  *
315:  * ### Params
316:  *
317:  * - `help` The help text to display for this argument.
318:  * - `required` Whether this parameter is required.
319:  * - `index` The index for the arg, if left undefined the argument will be put
320:  *   onto the end of the arguments. If you define the same index twice the first
321:  *   option will be overwritten.
322:  * - `choices` A list of valid choices for this argument. If left empty all values are valid..
323:  *   An exception will be raised when parse() encounters an invalid value.
324:  *
325:  * @param ConsoleInputArgument|string $name The name of the argument. Will also accept an instance of ConsoleInputArgument
326:  * @param array $params Parameters for the argument, see above.
327:  * @return $this
328:  */
329:     public function addArgument($name, $params = array()) {
330:         if (is_object($name) && $name instanceof ConsoleInputArgument) {
331:             $arg = $name;
332:             $index = count($this->_args);
333:         } else {
334:             $defaults = array(
335:                 'name' => $name,
336:                 'help' => '',
337:                 'index' => count($this->_args),
338:                 'required' => false,
339:                 'choices' => array()
340:             );
341:             $options = $params + $defaults;
342:             $index = $options['index'];
343:             unset($options['index']);
344:             $arg = new ConsoleInputArgument($options);
345:         }
346:         $this->_args[$index] = $arg;
347:         ksort($this->_args);
348:         return $this;
349:     }
350: 
351: /**
352:  * Add multiple arguments at once. Take an array of argument definitions.
353:  * The keys are used as the argument names, and the values as params for the argument.
354:  *
355:  * @param array $args Array of arguments to add.
356:  * @see ConsoleOptionParser::addArgument()
357:  * @return $this
358:  */
359:     public function addArguments(array $args) {
360:         foreach ($args as $name => $params) {
361:             $this->addArgument($name, $params);
362:         }
363:         return $this;
364:     }
365: 
366: /**
367:  * Add multiple options at once. Takes an array of option definitions.
368:  * The keys are used as option names, and the values as params for the option.
369:  *
370:  * @param array $options Array of options to add.
371:  * @see ConsoleOptionParser::addOption()
372:  * @return $this
373:  */
374:     public function addOptions(array $options) {
375:         foreach ($options as $name => $params) {
376:             $this->addOption($name, $params);
377:         }
378:         return $this;
379:     }
380: 
381: /**
382:  * Append a subcommand to the subcommand list.
383:  * Subcommands are usually methods on your Shell, but can also be used to document Tasks.
384:  *
385:  * ### Options
386:  *
387:  * - `help` - Help text for the subcommand.
388:  * - `parser` - A ConsoleOptionParser for the subcommand. This allows you to create method
389:  *    specific option parsers. When help is generated for a subcommand, if a parser is present
390:  *    it will be used.
391:  *
392:  * @param ConsoleInputSubcommand|string $name Name of the subcommand. Will also accept an instance of ConsoleInputSubcommand
393:  * @param array $options Array of params, see above.
394:  * @return $this
395:  */
396:     public function addSubcommand($name, $options = array()) {
397:         if (is_object($name) && $name instanceof ConsoleInputSubcommand) {
398:             $command = $name;
399:             $name = $command->name();
400:         } else {
401:             $defaults = array(
402:                 'name' => $name,
403:                 'help' => '',
404:                 'parser' => null
405:             );
406:             $options += $defaults;
407:             $command = new ConsoleInputSubcommand($options);
408:         }
409:         $this->_subcommands[$name] = $command;
410:         return $this;
411:     }
412: 
413: /**
414:  * Remove a subcommand from the option parser.
415:  *
416:  * @param string $name The subcommand name to remove.
417:  * @return $this
418:  */
419:     public function removeSubcommand($name) {
420:         unset($this->_subcommands[$name]);
421:         return $this;
422:     }
423: 
424: /**
425:  * Add multiple subcommands at once.
426:  *
427:  * @param array $commands Array of subcommands.
428:  * @return $this
429:  */
430:     public function addSubcommands(array $commands) {
431:         foreach ($commands as $name => $params) {
432:             $this->addSubcommand($name, $params);
433:         }
434:         return $this;
435:     }
436: 
437: /**
438:  * Gets the arguments defined in the parser.
439:  *
440:  * @return array Array of argument descriptions
441:  */
442:     public function arguments() {
443:         return $this->_args;
444:     }
445: 
446: /**
447:  * Get the defined options in the parser.
448:  *
449:  * @return array
450:  */
451:     public function options() {
452:         return $this->_options;
453:     }
454: 
455: /**
456:  * Get the array of defined subcommands
457:  *
458:  * @return array
459:  */
460:     public function subcommands() {
461:         return $this->_subcommands;
462:     }
463: 
464: /**
465:  * Parse the argv array into a set of params and args. If $command is not null
466:  * and $command is equal to a subcommand that has a parser, that parser will be used
467:  * to parse the $argv
468:  *
469:  * @param array $argv Array of args (argv) to parse.
470:  * @param string $command The subcommand to use. If this parameter is a subcommand, that has a parser,
471:  *    That parser will be used to parse $argv instead.
472:  * @return Array array($params, $args)
473:  * @throws ConsoleException When an invalid parameter is encountered.
474:  */
475:     public function parse($argv, $command = null) {
476:         if (isset($this->_subcommands[$command]) && $this->_subcommands[$command]->parser()) {
477:             return $this->_subcommands[$command]->parser()->parse($argv);
478:         }
479:         $params = $args = array();
480:         $this->_tokens = $argv;
481:         while (($token = array_shift($this->_tokens)) !== null) {
482:             if (substr($token, 0, 2) === '--') {
483:                 $params = $this->_parseLongOption($token, $params);
484:             } elseif (substr($token, 0, 1) === '-') {
485:                 $params = $this->_parseShortOption($token, $params);
486:             } else {
487:                 $args = $this->_parseArg($token, $args);
488:             }
489:         }
490:         foreach ($this->_args as $i => $arg) {
491:             if ($arg->isRequired() && !isset($args[$i]) && empty($params['help'])) {
492:                 throw new ConsoleException(
493:                     __d('cake_console', 'Missing required arguments. %s is required.', $arg->name())
494:                 );
495:             }
496:         }
497:         foreach ($this->_options as $option) {
498:             $name = $option->name();
499:             $isBoolean = $option->isBoolean();
500:             $default = $option->defaultValue();
501: 
502:             if ($default !== null && !isset($params[$name]) && !$isBoolean) {
503:                 $params[$name] = $default;
504:             }
505:             if ($isBoolean && !isset($params[$name])) {
506:                 $params[$name] = false;
507:             }
508:         }
509:         return array($params, $args);
510:     }
511: 
512: /**
513:  * Gets formatted help for this parser object.
514:  * Generates help text based on the description, options, arguments, subcommands and epilog
515:  * in the parser.
516:  *
517:  * @param string $subcommand If present and a valid subcommand that has a linked parser.
518:  *    That subcommands help will be shown instead.
519:  * @param string $format Define the output format, can be text or xml
520:  * @param int $width The width to format user content to. Defaults to 72
521:  * @return string Generated help.
522:  */
523:     public function help($subcommand = null, $format = 'text', $width = 72) {
524:         if (isset($this->_subcommands[$subcommand]) &&
525:             $this->_subcommands[$subcommand]->parser() instanceof self
526:         ) {
527:             $subparser = $this->_subcommands[$subcommand]->parser();
528:             $subparser->command($this->command() . ' ' . $subparser->command());
529:             return $subparser->help(null, $format, $width);
530:         }
531:         $formatter = new HelpFormatter($this);
532:         if ($format === 'text' || $format === true) {
533:             return $formatter->text($width);
534:         } elseif ($format === 'xml') {
535:             return $formatter->xml();
536:         }
537:     }
538: 
539: /**
540:  * Parse the value for a long option out of $this->_tokens. Will handle
541:  * options with an `=` in them.
542:  *
543:  * @param string $option The option to parse.
544:  * @param array $params The params to append the parsed value into
545:  * @return array Params with $option added in.
546:  */
547:     protected function _parseLongOption($option, $params) {
548:         $name = substr($option, 2);
549:         if (strpos($name, '=') !== false) {
550:             list($name, $value) = explode('=', $name, 2);
551:             array_unshift($this->_tokens, $value);
552:         }
553:         return $this->_parseOption($name, $params);
554:     }
555: 
556: /**
557:  * Parse the value for a short option out of $this->_tokens
558:  * If the $option is a combination of multiple shortcuts like -otf
559:  * they will be shifted onto the token stack and parsed individually.
560:  *
561:  * @param string $option The option to parse.
562:  * @param array $params The params to append the parsed value into
563:  * @return array Params with $option added in.
564:  * @throws ConsoleException When unknown short options are encountered.
565:  */
566:     protected function _parseShortOption($option, $params) {
567:         $key = substr($option, 1);
568:         if (strlen($key) > 1) {
569:             $flags = str_split($key);
570:             $key = $flags[0];
571:             for ($i = 1, $len = count($flags); $i < $len; $i++) {
572:                 array_unshift($this->_tokens, '-' . $flags[$i]);
573:             }
574:         }
575:         if (!isset($this->_shortOptions[$key])) {
576:             throw new ConsoleException(__d('cake_console', 'Unknown short option `%s`', $key));
577:         }
578:         $name = $this->_shortOptions[$key];
579:         return $this->_parseOption($name, $params);
580:     }
581: 
582: /**
583:  * Parse an option by its name index.
584:  *
585:  * @param string $name The name to parse.
586:  * @param array $params The params to append the parsed value into
587:  * @return array Params with $option added in.
588:  * @throws ConsoleException
589:  */
590:     protected function _parseOption($name, $params) {
591:         if (!isset($this->_options[$name])) {
592:             throw new ConsoleException(__d('cake_console', 'Unknown option `%s`', $name));
593:         }
594:         $option = $this->_options[$name];
595:         $isBoolean = $option->isBoolean();
596:         $nextValue = $this->_nextToken();
597:         $emptyNextValue = (empty($nextValue) && $nextValue !== '0');
598:         if (!$isBoolean && !$emptyNextValue && !$this->_optionExists($nextValue)) {
599:             array_shift($this->_tokens);
600:             $value = $nextValue;
601:         } elseif ($isBoolean) {
602:             $value = true;
603:         } else {
604:             $value = $option->defaultValue();
605:         }
606:         if ($option->validChoice($value)) {
607:             $params[$name] = $value;
608:             return $params;
609:         }
610:         return array();
611:     }
612: 
613: /**
614:  * Check to see if $name has an option (short/long) defined for it.
615:  *
616:  * @param string $name The name of the option.
617:  * @return bool
618:  */
619:     protected function _optionExists($name) {
620:         if (substr($name, 0, 2) === '--') {
621:             return isset($this->_options[substr($name, 2)]);
622:         }
623:         if ($name{0} === '-' && $name{1} !== '-') {
624:             return isset($this->_shortOptions[$name{1}]);
625:         }
626:         return false;
627:     }
628: 
629: /**
630:  * Parse an argument, and ensure that the argument doesn't exceed the number of arguments
631:  * and that the argument is a valid choice.
632:  *
633:  * @param string $argument The argument to append
634:  * @param array $args The array of parsed args to append to.
635:  * @return array Args
636:  * @throws ConsoleException
637:  */
638:     protected function _parseArg($argument, $args) {
639:         if (empty($this->_args)) {
640:             $args[] = $argument;
641:             return $args;
642:         }
643:         $next = count($args);
644:         if (!isset($this->_args[$next])) {
645:             throw new ConsoleException(__d('cake_console', 'Too many arguments.'));
646:         }
647: 
648:         if ($this->_args[$next]->validChoice($argument)) {
649:             $args[] = $argument;
650:             return $args;
651:         }
652:     }
653: 
654: /**
655:  * Find the next token in the argv set.
656:  *
657:  * @return string next token or ''
658:  */
659:     protected function _nextToken() {
660:         return isset($this->_tokens[0]) ? $this->_tokens[0] : '';
661:     }
662: 
663: }
664: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs