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.3 API

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