diff --git a/Makefile b/Makefile index 35b3755e1d425282bed6df9a267b6b1b8fba649b..04060607f583ed3b9c7045c8c1a4263e9a2efa7b 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ ES_HOST = # Languages that can be built. LANGS = en es fr ja pt zh -# pdflatex does not like ja or ru for some reason. +# pdflatex does not like ja for some reason. PDF_LANGS = en es fr pt DEST = website @@ -19,9 +19,9 @@ DEST = website # Clone the en/Makefile everywhere. SPHINX_DEPENDENCIES = $(foreach lang, $(LANGS), $(lang)/Makefile) -# Copy-paste the English Makefile everywhere it's needed. +# Copy-paste the English Makefile everywhere it's needed (if non existing). %/Makefile: en/Makefile - cp $< $@ + cp -n $< $@ # # The various formats the documentation can be created in. diff --git a/README.mdown b/README.mdown index 7e1fbe5336cdc418658ff6506b8806619ea15813..50c32433ade750874118060788524e0e472e7722 100644 --- a/README.mdown +++ b/README.mdown @@ -10,12 +10,12 @@ You can read all of the documentation within as its just in plain text files, ma * Make * Python -* Sphinx +* Sphinx 1.2.* (currently the make commands will not work with 1.3.* versions and up) * PhpDomain for sphinx You can install sphinx using: - easy_install sphinx + easy_install sphinx==1.2.3 You can install the phpdomain using: @@ -77,17 +77,6 @@ Translations Contributing translations requires that you make a new directory using the two letter name for your language. As content is translated, directories mirroring the english content should be created with localized content. - -Generating Meta Tags --------------------- - -If you are providing translations and want to automatically generate meta tags for the resulting HTML files, a MetatagShell is provided in -the `scripts` folder of this repo. In order to use it, copy it into any CakePHP 2.0 empty application inside `app/Console/Command`, execute -`Console/cake metatag` and follow the instructions. - -The script will process all the files under one of the translation folders and generate the possible description terms using an external API, -it is a good idea to go over the generated terms and clean-up whatever noise it might have generated. - Making Search Work Locally -------------------------- diff --git a/config/all.py b/config/all.py index d44315841831625584574f430e075d4b511e5ff1..2b19135075624097146c15876fee508c35ac364e 100644 --- a/config/all.py +++ b/config/all.py @@ -6,6 +6,7 @@ # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' +import datetime # Add any Sphinx extension module names here, as strings. # They can be extensions coming with Sphinx @@ -31,7 +32,7 @@ master_doc = 'contents' # General information about the project. project = u'CakePHP Cookbook' -copyright = u'2014, Cake Software Foundation, Inc' +copyright = u'%d, Cake Software Foundation, Inc' % datetime.datetime.now().year # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -247,7 +248,8 @@ man_pages = [ epub_title = u'CakePHP Cookbook' epub_author = u'Cake Software Foundation, Inc.' epub_publisher = u'Cake Software Foundation, Inc.' -epub_copyright = u'2013, Cake Software Foundation, Inc.' +epub_copyright = u'%d, Cake Software Foundation, Inc.' % datetime.datetime.now().year + epub_theme = 'cakephp-epub' @@ -294,7 +296,7 @@ epub_tocdup = False epub_use_index = False # Languages available. -languages = ['en', 'pt', 'es', 'ja', 'ru', 'fr', 'zh_CN'] +languages = ['en', 'pt', 'es', 'ja', 'fr', 'zh'] # The GitHub branch name for this version of the docs branch = '3.0' diff --git a/diagrams/request-cycle.graffle b/diagrams/request-cycle.graffle new file mode 100644 index 0000000000000000000000000000000000000000..701508b53369eec63c4ff6ee2e54b94cb8ebeddc --- /dev/null +++ b/diagrams/request-cycle.graffle @@ -0,0 +1,1516 @@ + + + + + ActiveLayerIndex + 0 + ApplicationVersion + + com.omnigroup.OmniGraffle + 139.18.0.187838 + + AutoAdjust + + BackgroundGraphic + + Bounds + {{0, 0}, {575.99998474121094, 733}} + Class + SolidGraphic + ID + 2 + Style + + shadow + + Draws + NO + + stroke + + Draws + NO + + + + BaseZoom + 0 + CanvasOrigin + {0, 0} + ColumnAlign + 1 + ColumnSpacing + 36 + CreationDate + 2015-07-16 02:19:33 +0000 + Creator + Mark Story + DisplayScale + 1 0/72 in = 1 0/72 in + GraphDocumentVersion + 8 + GraphicsList + + + Class + LineGraphic + Head + + ID + 26 + Info + 1 + + ID + 27 + Points + + {383.11111450195312, 345.75} + {383.11111450195312, 279.5} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + Tail + + ID + 12 + Info + 2 + + + + Bounds + {{326.61111450195312, 225.5}, {113, 54}} + Class + ShapedGraphic + ID + 26 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.737255 + g + 0.921569 + r + 0.976471 + + + shadow + + Draws + NO + + stroke + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Response} + + + + Class + LineGraphic + Head + + ID + 15 + + ID + 25 + Points + + {442.61111450195312, 376.25} + {463.16665649414062, 403} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + + + Class + LineGraphic + Head + + ID + 14 + Info + 4 + + ID + 24 + Points + + {439.61111450195312, 372.75} + {463.16665649414062, 343.75} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + Tail + + ID + 12 + Info + 3 + + + + Class + LineGraphic + Head + + ID + 9 + + ID + 23 + Points + + {307.88888549804688, 461} + {263.61111450195312, 370.25} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + Tail + + ID + 11 + + + + Class + LineGraphic + Head + + ID + 12 + + ID + 22 + Points + + {265.61111450195312, 373.25} + {326.61111450195312, 372.75} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + + + Class + LineGraphic + Head + + ID + 13 + + ID + 21 + Points + + {251.38888549804688, 488} + {227.61111450195312, 488} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + Tail + + ID + 11 + Info + 4 + + + + Class + LineGraphic + Head + + ID + 10 + + ID + 19 + Points + + {150.61111450195312, 370.25} + {123.61111450195312, 370.25} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + Tail + + ID + 9 + Info + 4 + + + + Class + LineGraphic + Head + + ID + 9 + Info + 2 + + ID + 18 + Points + + {207.11110687255859, 299} + {207.11111450195312, 343.25} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + Tail + + ID + 16 + + + + Class + LineGraphic + Head + + ID + 16 + + ID + 17 + Points + + {207.11110687255859, 213} + {207.11110687255859, 245} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + Tail + + ID + 5 + Info + 1 + + + + Bounds + {{150.61110687255859, 245}, {113, 54}} + Class + ShapedGraphic + ID + 16 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.866325 + g + 1 + r + 0.78566 + + + shadow + + Draws + NO + + stroke + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Dispatch Filters\ +& Routing} + + + + Bounds + {{463.16665649414062, 383.5}, {81.611114501953125, 39}} + Class + ShapedGraphic + ID + 15 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.945098 + g + 0.788235 + r + 0.470588 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.482353 + g + 0.466667 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Cell} + + + + Bounds + {{463.16665649414062, 324.25}, {81.611114501953125, 39}} + Class + ShapedGraphic + ID + 14 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.945098 + g + 0.788235 + r + 0.470588 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.482353 + g + 0.466667 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Helper} + + + + Bounds + {{326.61111450195312, 345.75}, {113, 54}} + Class + ShapedGraphic + ID + 12 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.945098 + g + 0.788235 + r + 0.470588 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.482353 + g + 0.466667 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 View} + + + + Bounds + {{251.38888549804688, 461}, {113, 54}} + Class + ShapedGraphic + ID + 11 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.258824 + g + 0.27451 + r + 0.85098 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.215686 + g + 0.145098 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Model} + + + + Bounds + {{42, 350.75}, {81.611114501953125, 39}} + Class + ShapedGraphic + ID + 10 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.172549 + g + 0.741176 + r + 0.945098 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.482353 + g + 0.466667 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Component} + + + + Bounds + {{150.61111450195312, 343.25}, {113, 54}} + Class + ShapedGraphic + ID + 9 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.172549 + g + 0.741176 + r + 0.945098 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.482353 + g + 0.466667 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Controller} + + + + Class + LineGraphic + Head + + ID + 5 + + ID + 6 + Points + + {126.61111450195312, 186} + {150.61110687255859, 186} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 1 + TailArrow + 0 + + + Tail + + ID + 4 + Info + 3 + + + + Bounds + {{150.61110687255859, 159}, {113, 54}} + Class + ShapedGraphic + ID + 5 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.866325 + g + 1 + r + 0.78566 + + + shadow + + Draws + NO + + stroke + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 autoload & bootstrap} + + + + Bounds + {{13.611114501953125, 159}, {113, 54}} + Class + ShapedGraphic + ID + 4 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.737255 + g + 0.921569 + r + 0.976471 + + + shadow + + Draws + NO + + stroke + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 index.php} + + + + Bounds + {{37, 345.75}, {81.611114501953125, 39}} + Class + ShapedGraphic + ID + 28 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.172549 + g + 0.741176 + r + 0.945098 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.482353 + g + 0.466667 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Component} + + + + Bounds + {{468.16665649414062, 318.25}, {81.611114501953125, 39}} + Class + ShapedGraphic + ID + 29 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.945098 + g + 0.788235 + r + 0.470588 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.482353 + g + 0.466667 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Helper} + + + + Bounds + {{468.16665649414062, 380.5}, {81.611114501953125, 39}} + Class + ShapedGraphic + ID + 30 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.945098 + g + 0.788235 + r + 0.470588 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.482353 + g + 0.466667 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Cell} + + + + Bounds + {{146, 468.5}, {81.611114501953125, 39}} + Class + ShapedGraphic + FontInfo + + Font + Helvetica + Size + 12 + + ID + 13 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.258824 + g + 0.27451 + r + 0.85098 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.215686 + g + 0.145098 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Behavior} + + + + Bounds + {{142, 463.5}, {81.611114501953125, 39}} + Class + ShapedGraphic + ID + 31 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.258824 + g + 0.27451 + r + 0.85098 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.215686 + g + 0.145098 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Behavior} + + + + Bounds + {{255.77777099609375, 456}, {113, 54}} + Class + ShapedGraphic + ID + 32 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + Color + + b + 0.258824 + g + 0.27451 + r + 0.85098 + + + shadow + + Draws + NO + + stroke + + Color + + b + 0.215686 + g + 0.145098 + r + 0.329412 + + CornerRadius + 5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Model} + + + + GridInfo + + GuidesLocked + NO + GuidesVisible + YES + HPages + 1 + ImageCounter + 1 + KeepToScale + + Layers + + + Lock + NO + Name + Layer 1 + Print + YES + View + YES + + + LayoutInfo + + Animate + NO + circoMinDist + 18 + circoSeparation + 0.0 + layoutEngine + dot + neatoSeparation + 0.0 + twopiSeparation + 0.0 + + LinksVisible + NO + MagnetsVisible + NO + MasterSheets + + ModificationDate + 2015-07-16 02:36:17 +0000 + Modifier + Mark Story + NotesVisible + NO + Orientation + 2 + OriginVisible + NO + PageBreaks + YES + PrintInfo + + NSBottomMargin + + float + 41 + + NSHorizonalPagination + + coded + BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG + + NSLeftMargin + + float + 18 + + NSPaperSize + + size + {611.99998474121094, 792} + + NSPrintReverseOrientation + + int + 0 + + NSRightMargin + + float + 18 + + NSTopMargin + + float + 18 + + + PrintOnePage + + ReadOnly + NO + RowAlign + 1 + RowSpacing + 36 + SheetTitle + Canvas 1 + SmartAlignmentGuidesActive + YES + SmartDistanceGuidesActive + YES + UniqueID + 1 + UseEntirePage + + VPages + 1 + WindowInfo + + CurrentSheet + 0 + ExpandedCanvases + + + name + Canvas 1 + + + Frame + {{61, 33}, {951, 742}} + ListView + + OutlineWidth + 142 + RightSidebar + + ShowRuler + + Sidebar + + SidebarWidth + 120 + VisibleRegion + {{-120, 0}, {816, 600}} + Zoom + 1 + ZoomValues + + + Canvas 1 + 1 + 1 + + + + + diff --git a/en/_static/img/typical-cake-request.png b/en/_static/img/typical-cake-request.png index f951d3619642a46a8c4de2b9123e47039c285760..76e9d66c1797536c4759da6f3eba61bf8e61e35a 100644 Binary files a/en/_static/img/typical-cake-request.png and b/en/_static/img/typical-cake-request.png differ diff --git a/en/appendices.rst b/en/appendices.rst index 5d90728b90321996de0408e9756fa2f18c154051..a6816226fd7f580bca435e580f3ad51c8615b5c4 100644 --- a/en/appendices.rst +++ b/en/appendices.rst @@ -7,15 +7,20 @@ introduced in each version and the migration path between versions. 3.0 Migration Guide =================== -3.0 is still under development, and any documented changes -will only be available in the ``3.0`` branch in git. - .. toctree:: :maxdepth: 1 appendices/3-0-migration-guide appendices/orm-migration +3.1 Migration Guide +=================== + +.. toctree:: + :maxdepth: 1 + + appendices/3-1-migration-guide + General Information =================== diff --git a/en/appendices/3-0-migration-guide.rst b/en/appendices/3-0-migration-guide.rst index b5f43921ad8169c1599dc1480e4ff61225a902af..4608d177f4676be3811a2523d2233c20ef996d7c 100644 --- a/en/appendices/3-0-migration-guide.rst +++ b/en/appendices/3-0-migration-guide.rst @@ -45,7 +45,7 @@ Namespaces ========== All of CakePHP's core classes are now namespaced and follow PSR-4 autoloading -specifications. For example ``src/Cache/Cache.php`` is namespaced as +specifications. For example **src/Cache/Cache.php** is namespaced as ``Cake\Cache\Cache``. Global constants and helper methods like :php:meth:`__()` and :php:meth:`debug()` are not namespaced for convenience sake. @@ -263,9 +263,10 @@ BakeShell / TemplateTask - Bake is no longer part of the core source and is superseded by `CakePHP Bake Plugin `_ -- Bake templates have been moved under ``src/Template/Bake``. +- Bake templates have been moved under **src/Template/Bake**. - The syntax of Bake templates now uses erb-style tags (``<% %>``) to denote templating logic, allowing php code to be treated as plain text. +- The ``bake view`` command has been renamed ``bake template``. Event ===== @@ -390,7 +391,7 @@ Dispatcher Filters Configuration Changed Dispatcher filters are no longer added to your application using ``Configure``. You now append them with :php:class:`Cake\\Routing\\DispatcherFactory`. This means if your application used ``Dispatcher.filters``, you should now use -php:meth:`Cake\\Routing\\DispatcherFactory::add()`. +:php:meth:`Cake\\Routing\\DispatcherFactory::add()`. In addition to configuration changes, dispatcher filters have had some conventions updated, and features added. See the @@ -514,8 +515,7 @@ Controller models + controllers were far more intertwined. - ``Controller::loadModel()`` now loads table objects. - The ``Controller::$scaffold`` property has been removed. Dynamic scaffolding - has been removed from CakePHP core, and will be provided as a standalone - plugin. + has been removed from CakePHP core. An improved scaffolding plugin, named CRUD, can be found here: https://github.com/FriendsOfCake/crud - The ``Controller::$ext`` property has been removed. You now have to extend and override the ``View::$_ext`` property if you want to use a non-default view file extension. @@ -542,8 +542,9 @@ Scaffold Removed ---------------- The dynamic scaffolding in CakePHP has been removed from CakePHP core. It was -infrequently used, and never intended for production use. It will be replaced by -a standalone plugin that people requiring that feature can use. +infrequently used, and never intended for production use. An improved +scaffolding plugin, named CRUD, can be found here: +https://github.com/FriendsOfCake/crud ComponentCollection Replaced ---------------------------- @@ -579,9 +580,9 @@ CookieComponent - Uses :php:meth:`Cake\\Network\\Request::cookie()` to read cookie data, this eases testing, and allows for ControllerTestCase to set cookies. -- Cookies encrypted in previous versions of CakePHP using the ``cipher`` method +- Cookies encrypted in previous versions of CakePHP using the ``cipher()`` method are now un-readable because ``Security::cipher()`` has been removed. You will - need to re-encrypt cookies with the ``rijndael`` or ``aes`` method before upgrading. + need to re-encrypt cookies with the ``rijndael()`` or ``aes()`` method before upgrading. - ``CookieComponent::type()`` has been removed and replaced with configuration data accessed through ``config()``. - ``write()`` no longer takes ``encryption`` or ``expires`` parameters. Both of @@ -683,7 +684,7 @@ new ORM. ConnectionManager ----------------- -- ConnectionManager has been moved to the ``Cake\Database`` namespace. +- ConnectionManager has been moved to the ``Cake\Datasource`` namespace. - ConnectionManager has had the following methods removed: - ``sourceList`` @@ -709,7 +710,7 @@ Behaviors TreeBehavior ------------ -The TreeBheavior was completely re-written to use the new ORM. Although it works +The TreeBehavior was completely re-written to use the new ORM. Although it works the same as in 2.x, a few methods were renamed or removed: - ``TreeBehavior::children()`` is now a custom finder ``find('children')``. @@ -775,14 +776,13 @@ Both these issues are solved by converting themes into plugins. View Folders Renamed -------------------- -The folders containing view files now go under ``src/Template`` instead of ``src/View``. +The folders containing view files now go under **src/Template** instead of **src/View**. This was done to separate the view files from files containing php classes (eg. Helpers, View classes). The following View folders have been renamed to avoid naming collisions with controller names: - ``Layouts`` is now ``Layout`` - ``Elements`` is now ``Element`` -- ``Scaffolds`` is now ``Scaffold`` - ``Errors`` is now ``Error`` - ``Emails`` is now ``Email`` (same for ``Email`` inside ``Layout``) @@ -834,6 +834,12 @@ JsonView variable. This allows you to configure the bit-mask options used when generating JSON. +XmlView +------- + +- :php:class:`Cake\\View\\XmlView` now supports the ``_xmlOptions`` view + variable. This allows you to configure the options used when generating + XML. View\\Helper ============ @@ -910,7 +916,7 @@ and reduce the problems people had in the past: no longer generate id attributes. - The ``inputDefaults`` option has been removed from ``create()``. - Options ``default`` and ``onsubmit`` of ``create()`` have been removed. Instead - one should use javascript event binding or set all required js code for ``onsubmit``. + one should use JavaScript event binding or set all required js code for ``onsubmit``. - ``end()`` can no longer make buttons. You should create buttons with ``button()`` or ``submit()``. - ``FormHelper::tagIsInvalid()`` has been removed. Use ``isFieldError()`` @@ -936,7 +942,7 @@ and reduce the problems people had in the past: - The ``submit()`` has had the ``div``, ``before`` and ``after`` options removed. You can customize the ``submitContainer`` template to modify this content. -- The ``inputs`` method no longer accepts ``legend`` and ``fieldset`` in the +- The ``inputs()`` method no longer accepts ``legend`` and ``fieldset`` in the ``$fields`` parameter, you must use the ``$options`` parameter. It now also requires ``$fields`` parameter to be an array. The ``$blacklist`` parameter has been removed, the functionality has been replaced by specifying @@ -1021,23 +1027,24 @@ NumberHelper SessionHelper ------------- -- ``SessionHelper::flash()`` is deprecated. You should use - :doc:`/views/helpers/flash` instead. +- The ``SessionHelper`` has been deprecated. You can use ``$this->request->session()`` directly, + and the flash message functionality has been moved into :doc:`/views/helpers/flash` instead. + JsHelper -------- - ``JsHelper`` and all associated engines have been removed. It could only - generate a very small subset of javascript code for selected library and - hence trying to generate all javascript code using just the helper often - became an impediment. It's now recommended to directly use javascript library + generate a very small subset of JavaScript code for selected library and + hence trying to generate all JavaScript code using just the helper often + became an impediment. It's now recommended to directly use JavaScript library of your choice. CacheHelper Removed ------------------- CacheHelper has been removed. The caching functionality it provided was -non-standard, limited and incompatible with non-html layouts and data views. +non-standard, limited and incompatible with non-HTML layouts and data views. These limitations meant a full rebuild would be necessary. Edge Side Includes have become a standardized way to implement the functionality CacheHelper used to provide. However, implementing `Edge Side Includes @@ -1158,7 +1165,7 @@ Inflector - The default value for ``$replacement`` argument of :php:meth:`Cake\\Utility\\Inflector::slug()` has been changed from underscore (``_``) to dash (``-``). Using dashes to - separate words in urls is the popular choice and also recommended by Google. + separate words in URLs is the popular choice and also recommended by Google. - Transliterations for :php:meth:`Cake\\Utility\\Inflector::slug()` have changed. If you use custom transliterations you will need to update your code. Instead diff --git a/en/appendices/3-1-migration-guide.rst b/en/appendices/3-1-migration-guide.rst new file mode 100644 index 0000000000000000000000000000000000000000..d8c31ed2e75c0936d3186a008db2f4a99c671146 --- /dev/null +++ b/en/appendices/3-1-migration-guide.rst @@ -0,0 +1,199 @@ +3.1 Migration Guide +################### + +CakePHP 3.1 is a fully API compatible upgrade from 3.0. This page outlines +the changes and improvements made in 3.1. + +Routing +======= + +- The default route class has been changed to ``DashedRoute`` in the + ``cakephp/app`` repo. Your current code base is not affected by this, but it is + recommended to use this route class from now on. +- Name prefix options were added to the various route builder methods. See the + :ref:`named-routes` section for more information. + +Console +======= + +- ``Shell::dispatchShell()`` no longer outputs the welcome message from the + dispatched shell. +- The ``breakpoint()`` helper function has been added. This function provides + a snippet of code that can be put into ``eval()`` to trigger an interactive + console. This is very helpful when debugging in test cases, or other CLI + scripts. + +Shell Helpers Added +------------------- + +- Console applications can now create helper classes that encapsulate re-usable + blocks of output logic. See the :doc:`/console-and-shells/helpers` section + for more information. + +RoutesShell +----------- + +- RoutesShell has been added and now provides you a simple to use CLI + interface for testing and debugging routes. See the + :doc:`/console-and-shells/routes-shell` section for more information. + +Controller +========== + +- The following Controller properties are now deprecated: + + * layout + * view + * theme + * autoLayout + * viewPath + * layoutPath + + Instead of setting these properties on your controllers, you should set them + on the view using methods with matching names:: + + // In a controller, instead of + $this->layout = 'advanced'; + + // You should use + $this->viewBuilder()->layout('advanced'); + +These methods should be called after you've determined which view class will be +used by a controller/action. + +AuthComponent +------------- + +- New config option ``storage`` has been added. It contains the storage class name that + ``AuthComponent`` uses to store user record. By default ``SessionStorage`` is used. + If using a stateless authenticator you should configure ``AuthComponent`` to + use ``MemoryStorage`` instead. +- New config option ``checkAuthIn`` has been added. It contains the name of the + event for which auth checks should be done. By default ``Controller.startup`` + is used, but you can set it to ``Controller.initialize`` if you want + authentication to be checked before you controller's ``beforeFilter()`` method + is run. +- The options ``scope`` and ``contain`` for authenticator classes have been + deprecated. Instead, use the new ``finder`` option to configure a custom finder + method and modify the query used to find a user there. + +FlashComponent +-------------- + +- ``FlashComponent`` now stacks Flash messages when set with the ``set()`` + or ``__call()`` method. This means that the structure in the Session for + stored Flash messages has changed. + +CsrfComponent +------------- + +- CSRF cookie expiry time can now be set as a ``strtotime()`` compatible value. +- Invalid CSRF tokens will now throw + a ``Cake\Network\Exception\InvalidCsrfTokenException`` instead of the + ``Cake\Network\Exception\ForbiddenException``. + +RequestHandlerComponent +----------------------- + +- ``RequestHandlerComponent`` now switches the layout and template based on + the parsed extension or ``Accept-Type`` header in the ``beforeRender()`` callback + instead of ``startup()``. + +Network +======= + +Http\Client +----------- + +- The default mime type used when sending requests has changed. Previously + ``multipart/form-data`` would always be used. In 3.1, ``multipart/form-data`` + is only used when file uploads are present. When there are no file uploads, + ``application/x-www-form-urlencoded`` is used instead. + +ORM +=== + +You can now :ref:`Lazily Eager Load Associations +`. This feature allows you to conditionally +load additional associations into a result set, entity or collection of +entities. + +Query +----- + +- ``Query::notMatching()`` was added. +- ``Query::leftJoinWith()`` was added. +- ``Query::innerJoinWith()`` was added. +- ``Query::select()`` now supports ``Table`` and ``Association`` objects as + parameters. These parameter types will select all the columns on the provided + table or association instance's target table. +- ``Query::distinct()`` now accepts a string to distinct on a single column. +- ``Table::loadInto()`` was added. +- ``EXTRACT``, ``DATE_ADD`` and ``DAYOFWEEK`` raw SQL functions have been + abstracted to ``extract()``, ``dateAdd()`` and ``dayOfWeek()``. + + +View +==== + +- You can now set ``_serialized`` to ``true`` for ``JsonView`` and ``XmlView`` + to serialize all view variables instead of explicitly specifying them. +- ``View::$viewPath`` is deprecated. You should use ``View::templatePath()`` + instead. +- ``View::$view`` is deprecated. You should use ``View::template()`` + instead. +- ``View::TYPE_VIEW`` is deprecated. You should use ``View::TYPE_TEMPLATE`` + instead. + +Helper +====== + +SessionHelper +------------- + +- The ``SessionHelper`` has been deprecated. You can use + ``$this->request->session()`` directly. + +FlashHelper +----------- + +- ``FlashHelper`` can render multiple messages if multiple messages where + set with the ``FlashComponent``. Each message will be rendered in its own + element. Messages will be rendered in the order they were set. + +FormHelper +---------- + +- New option ``templateVars`` has been added. ``templateVars`` allows you to + pass additional variables to your custom form control templates. + +Email +===== + +- ``Email`` and ``Transport`` classes have been moved under the ``Cake\Mailer`` + namespace. Their former namespaces are still usable as class aliases have + been set for them. + +Mailer +------ + +- The ``Mailer`` class was added. This class helps create reusable emails in an + application. + +I18n +==== + +Time +---- + +- ``Time::fromNow()`` has been added. This method makes it easier to calculate + differences from 'now'. +- ``Time::i18nFormat()`` now supports non-gregorian calendars when formatting + dates. + +Validation +========== + +- ``Validation::geoCoordinate()`` was added. +- ``Validation::latitude()`` was added. +- ``Validation::longitude()`` was added. diff --git a/en/appendices/glossary.rst b/en/appendices/glossary.rst index 864b896f0a81391dbf4f8be8ad1851137af4ec7a..0c5f745efa22706e162ceb033ac448e397a4df78 100644 --- a/en/appendices/glossary.rst +++ b/en/appendices/glossary.rst @@ -18,7 +18,7 @@ Glossary // Would generate class="my-class" target="_blank" - If an option can be minimized or accepts it's name as the value, then ``true`` + If an option can be minimized or accepts its name as the value, then ``true`` can be used:: // Given diff --git a/en/appendices/orm-migration.rst b/en/appendices/orm-migration.rst index 5de71a0b5f04c421a365ccab319cf7d6305c27d6..90a168abc98296998fa4ced860e80d029512c391 100644 --- a/en/appendices/orm-migration.rst +++ b/en/appendices/orm-migration.rst @@ -5,16 +5,16 @@ CakePHP 3.0 features a new ORM that has been re-written from the ground up. While the ORM used in 1.x and 2.x has served us well for a long time it had a few issues that we wanted to fix. -* Frankenstein - is it a record, or a table? Currently it's both. +* Frankenstein - Is it a record, or a table? Currently it's both. * Inconsistent API - Model::read() for example. * No query object - Queries are always defined as arrays, this has some limitations and restrictions. For example it makes doing unions and sub-queries much harder. -* Returns arrays. This is a common complaint about CakePHP, and has probably +* Returns arrays - This is a common complaint about CakePHP, and has probably reduced adoption at some levels. * No record object - This makes attaching formatting methods difficult/impossible. -* Containable - Should be part of the ORM, not a crazy hacky behaviour. +* Containable - Should be part of the ORM, not a crazy hacky behavior. * Recursive - This should be better controlled as defining which associations are included, not a level of recursiveness. * DboSource - It is a beast, and Model relies on it more than datasource. That @@ -45,7 +45,7 @@ operations. Now the ORM is split into more layers: bindings for each data type. For example datetime columns are represented as ``DateTime`` instances in your code now. * ``Cake\ORM\Table`` - The main entry point into the new ORM. Provides access - to a single table. Handles the definition of assocation, use of behaviors and + to a single table. Handles the definition of association, use of behaviors and creation of entities and query objects. * ``Cake\ORM\Behavior`` - The base class for behaviors, which act very similar to behaviors in previous versions of CakePHP. @@ -71,7 +71,7 @@ Table objects are the gateway into your data. They handle many of the tasks that - Providing finders. - Validating and saving entities. - Deleting entities. -- Defining & accessing associations. +- Defining and accessing associations. - Triggering callback events. - Interacting with behaviors. @@ -116,7 +116,7 @@ with table objects. Key Differences =============== -The new ORM is a large departure from the existing ``Model`` layer, there are +The new ORM is a large departure from the existing ``Model`` layer. There are many important differences that are important in understanding how the new ORM operates and how to update your code. @@ -178,7 +178,7 @@ ever:: $query->where(['id' => $favoritesQuery->select(['id'])]); You can decorate queries with iterators and call methods without even touching -the database, this is great when you have parts of your view cached and having +the database. This is great when you have parts of your view cached and having the results taken from the database is not actually required:: // No queries made in this example! @@ -189,12 +189,12 @@ the results taken from the database is not actually required:: }); Queries can be seen as the result object, trying to iterate the query, calling -``toArray`` or any method inherited from :ref:`collection `, +``toArray()`` or any method inherited from :ref:`collection `, will result in the query being executed and results returned to you. The biggest difference you will find when coming from CakePHP 2.x is that ``find('first')`` does not exist anymore. There is a trivial replacement for it, -and it is the ``first`` method:: +and it is the ``first()`` method:: // Before $article = $this->Article->find('first'); @@ -256,19 +256,20 @@ migrate this code in one of a few ways: 1. Override your entity constructor method and do additional formatting there. 2. Create accessor methods in your entity to create the virtual properties. -3. Redefine ``findAll()`` and attach a map/reduce function. +3. Redefine ``findAll()`` and use ``formatResults``. In the 3rd case above your code would look like:: public function findAll(Query $query, array $options) { - $mapper = function ($row, $key, $mr) { - // Your afterFind logic - }; - return $query->mapReduce($mapper); + return $query->formatResults(function ($results) { + return $results->map(function ($row) { + // Your afterfind logic + }); + }) } -You may have noticed that custom finders receive an options array, you can pass +You may have noticed that custom finders receive an options array. You can pass any extra information to your finder using this parameter. This is great news for people migrating from 2.x. Any of the query keys that were used in previous versions will be converted automatically for you in 3.x to the correct @@ -286,8 +287,15 @@ functions:: 'limit' => 10, ]); -Hopefully, migrating from older versions is not as daunting as it first seems, -much of the features we have added helps you remove code as you can better +If your application uses 'magic' or :ref:`dynamic-finders`, you will have to +adapt those calls. In 3.x the ``findAllBy*`` methods have been removed, instead +``findBy*`` always returns a query object. To get the first result, you need to +use the ``first()`` method:: + + $article = $this->Articles->findByTitle('A great post!')->first(); + +Hopefully, migrating from older versions is not as daunting as it first seems. +Many of the features we have added will help you remove code as you can better express your requirements using the new ORM and at the same time the compatibility wrappers will help you rewrite those tiny differences in a fast and painless way. @@ -327,7 +335,7 @@ In previous versions of CakePHP you needed to make extensive use of the properties. These features have been removed in 3.0. Because of how ResultSets iteratively generate entities, the ``afterFind`` callback was not possible. Both afterFind and virtual fields can largely be replaced with virtual -properies on entities. For example if your User entity has both first and last +properties on entities. For example if your User entity has both first and last name columns you can add an accessor for `full_name` and generate the property on the fly:: @@ -337,7 +345,7 @@ on the fly:: class User extends Entity { - public function getFullName() + protected function _getFullName() { return $this->first_name . ' ' . $this->last_name; } @@ -375,7 +383,7 @@ In previous versions of CakePHP the various associations your models had were defined in properties like ``$belongsTo`` and ``$hasMany``. In CakePHP 3.0, associations are created with methods. Using methods allows us to sidestep the many limitations class definitions have, and provide only one way to define -associations. Your ``initialize`` method and all other parts of your application +associations. Your ``initialize()`` method and all other parts of your application code, interact with the same API when manipulating associations:: namespace App\Model\Table; @@ -412,7 +420,7 @@ Validation No Longer Defined as a Property Like associations, validation rules were defined as a class property in previous versions of CakePHP. This array would then be lazily transformed into a ``ModelValidator`` object. This transformation step added a layer of -indirection, complicating rule changes at runtime. Futhermore, validation rules +indirection, complicating rule changes at runtime. Furthermore, validation rules being defined as a property made it difficult for a model to have multiple sets of validation rules. In CakePHP 3.0, both these problems have been remedied. Validation rules are always built with a ``Validator`` object, and it is trivial @@ -461,7 +469,7 @@ data into entities by using the ``validate`` option. See the documentation on :ref:`Application rules ` allow you to define rules that ensure your application's rules, state and workflows are enforced. Rules are defined in your Table's ``buildRules()`` method. Behaviors can add rules using -the ``buildRules()`` hook method. An example ``buildRules`` method for our +the ``buildRules()`` hook method. An example ``buildRules()`` method for our articles table could be:: // In src/Model/Table/ArticlesTable.php @@ -522,7 +530,7 @@ Updating Behaviors ================== Like most ORM related features, behaviors have changed in 3.0 as well. They now -attach to ``Table`` instances which are the conceptual descendent of the +attach to ``Table`` instances which are the conceptual descendant of the ``Model`` class in previous versions of CakePHP. There are a few key differences from behaviors in CakePHP 2.x: @@ -540,7 +548,7 @@ New Base Class The base class for behaviors has changed. Behaviors should now extend ``Cake\ORM\Behavior``; if a behavior does not extend this class an exception will be raised. In addition to the base class changing, the constructor for -behaviors has been modified, and the ``startup`` method has been removed. +behaviors has been modified, and the ``startup()`` method has been removed. Behaviors that need access to the table they are attached to should define a constructor:: @@ -572,7 +580,7 @@ behavior mixin methods can expect the **same** arguments provided to the table // Assume table has a slug() method provided by a behavior. $table->slug($someValue); -The behavior providing the ``slug`` method will receive only 1 argument, and its +The behavior providing the ``slug()`` method will receive only 1 argument, and its method signature should look like:: public function slug($value) diff --git a/en/bake.rst b/en/bake.rst index 64835ff59845a13bcd65a5fc94768c91d3a1e625..8a74a5fe542dd988bedcb83a57be660291b7a49e 100644 --- a/en/bake.rst +++ b/en/bake.rst @@ -3,11 +3,22 @@ Bake Console CakePHP's bake console is another effort to get you up and running in CakePHP – fast. The bake console can create any of CakePHP's basic ingredients: models, -behaviors, views, helpers, components, test cases, fixtures and plugins. And we -aren't just talking skeleton classes: Bake can create a fully functional +behaviors, views, helpers, controllers, components, test cases, fixtures and plugins. +And we aren't just talking skeleton classes: Bake can create a fully functional application in just a few minutes. In fact, Bake is a natural step to take once -an application has been scaffolded. The following sections cover bake more in -detail: +an application has been scaffolded. + +Installation +============ + +Before trying to use or extend bake, make sure it is installed in your +application. Bake is provided as a plugin that you can install with Composer:: + + composer require --dev cakephp/bake:~1.0 + +The above will install bake as a development dependency. This means that it will +not be installed when you do production deployments. The following sections +cover bake in more detail: .. toctree:: :maxdepth: 1 diff --git a/en/bake/development.rst b/en/bake/development.rst index 15f7c4a1c8d28732b12281151d815f937cd719b9..433f03ac0c9472848730bfcec9dd2e933d89f6c6 100644 --- a/en/bake/development.rst +++ b/en/bake/development.rst @@ -95,7 +95,7 @@ So, for example, when baking a shell like so:: bin/cake bake shell Foo -The template used (``vendor/cakephp/cakephp/src/Template/Bake/Shell/shell.ctp``) +The template used (**vendor/cakephp/bake/src/Template/Bake/Shell/shell.ctp**) looks like this:: `. .. meta:: :title lang=en: Code Generation with Bake diff --git a/en/console-and-shells.rst b/en/console-and-shells.rst index 3e8cf3707d1b7799b2120b6ff01e4dd3e45cb005..feecd4cfa973bdca350481093dfa260cf387c6fb 100644 --- a/en/console-and-shells.rst +++ b/en/console-and-shells.rst @@ -37,12 +37,16 @@ section will be in bash, but the CakePHP Console is Windows-compatible as well. This example assumes that the user is currently logged into a bash prompt and is currently at the root of a CakePHP application. -CakePHP applications contain a ``Console`` directory that contains all the -shells and tasks for an application. It also comes with an executable:: +A CakePHP application contains ``src/Shell`` and ``src/Shell/Task`` directories that contain all of its +shells and tasks. It also comes with an executable in the ``bin`` directory:: $ cd /path/to/app $ bin/cake +.. note:: + + For Windows, the command needs to be ``bin\cake`` (note the backslash). + Running the Console with no arguments produces this help message:: Welcome to CakePHP v3.0.0 Console @@ -63,7 +67,11 @@ Running the Console with no arguments produces this help message:: Available Shells: - [CORE] bake, i18n, server, test + [Bake] bake + + [Migrations] migrations + + [CORE] i18n, orm_cache, plugin, routes, server [app] behavior_time, console, orm @@ -74,6 +82,23 @@ Running the Console with no arguments produces this help message:: The first information printed relates to paths. This is helpful if you're running the console from different parts of the filesystem. +You could then run the any of the listed shells by using its name:: + + # run server shell + bin/cake server + + # run migrations shell + bin/cake migrations -h + + # run bake (with plugin prefix) + bin/cake bake.bake -h + +Plugin shells can be invoked without a plugin prefix if the shell's name does +not overlap with an application or framework shell. In the case that two plugins +provide a shell with the same name, the first loaded plugin will get the short +alias. You can always use the ``plugin.shell`` format to unambiguously reference +a shell. + .. php:class:: Shell Creating a Shell @@ -204,7 +229,7 @@ almost entirely of tasks. You define a tasks for a shell using the ``$tasks`` pr You can use tasks from plugins using the standard :term:`plugin syntax`. Tasks are stored in ``Shell/Task/`` in files named after their classes. So if we were to create a new 'FileGenerator' task, you would create -``src/Shell/Task/FileGeneratorTask.php``. +**src/Shell/Task/FileGeneratorTask.php**. Each task must at least implement a ``main()`` method. The ShellDispatcher, will call this method when the task is invoked. A task class looks like:: @@ -221,7 +246,7 @@ will call this method when the task is invoked. A task class looks like:: } } -A shell can also access it's tasks as properties, which makes tasks great for +A shell can also access its tasks as properties, which makes tasks great for making re-usable chunks of functionality similar to :doc:`/controllers/components`:: // Found in src/Shell/SeaShell.php @@ -270,6 +295,12 @@ Would load and return a ProjectTask instance. You can load tasks from plugins us $progressBar = $this->Tasks->load('ProgressBar.ProgressBar'); +Shell Helpers +============= + +If you have complex output generation logic, you can use +:doc:`/console-and-shells/helpers` to encapsulate this logic in a re-usable way. + .. _invoking-other-shells-from-your-shell: Invoking Other Shells from Your Shell @@ -291,6 +322,38 @@ as var args or as a string:: The above shows how you can call the schema shell to create the schema for a plugin from inside your plugin's shell. +Passing extra parameters to the dispatched Shell +------------------------------------------------ + +.. versionadded:: 3.1 + +It can sometimes be useful to pass on extra parameters (that are not shell arguments) +to the dispatched Shell. In order to do this, you can now pass an array to +``dispatchShell()``. The array is expected to have a ``command`` key as well +as an ``extra`` key:: + + // Using a command string + $this->dispatchShell([ + 'command' => 'schema create Blog --plugin Blog' + 'extra' => [ + 'foo' => 'bar' + ] + ]); + + // Using a command array + $this->dispatchShell([ + 'command' => ['schema', 'create', 'Blog', '--plugin', 'Blog'] + 'extra' => [ + 'foo' => 'bar' + ] + ]); + +Parameters passed through ``extra`` will be merged in the ``Shell::$params`` +property and are accessible with the ``Shell::param()`` method. +By default, a ``requested`` extra param is automatically added when a Shell +is dispatched using ``dispatchShell()``. This ``requested`` parameter prevents +the CakePHP console welcome message from being displayed on dispatched shells. + Getting User Input ================== @@ -409,7 +472,7 @@ ConsoleOutput will replace these tags with the correct ansi code sequence, or remove the tags if you are on a console that doesn't support ansi codes. There are several built-in styles, and you can create more. The built-in ones are -* ``error`` Error messages. Red underlined text. +* ``error`` Error messages. Red text. * ``warning`` Warning messages. Yellow text. * ``info`` Informational messages. Cyan text. * ``comment`` Additional text. Blue text. @@ -464,7 +527,7 @@ no styling is done at all. There are three modes you can use. * ``ConsoleOutput::COLOR`` - Output with color escape codes in place. By default on \*nix systems ConsoleOutput objects default to colour output. -On windows systems, plain output is the default unless the ``ANSICON`` environment +On Windows systems, plain output is the default unless the ``ANSICON`` environment variable is present. Hook Methods @@ -846,7 +909,7 @@ Getting Help as XML ------------------- When building automated tools or development tools that need to interact -with CakePHP shells, its nice to have help available in a machine parse-able +with CakePHP shells, it's nice to have help available in a machine parse-able format. The ConsoleOptionParser can provide help in xml by setting an additional argument:: @@ -933,12 +996,14 @@ More Topics .. toctree:: :maxdepth: 1 + console-and-shells/helpers console-and-shells/repl console-and-shells/cron-jobs console-and-shells/i18n-shell console-and-shells/completion-shell + console-and-shells/plugin-shell + console-and-shells/routes-shell console-and-shells/upgrade-shell - console-and-shells/plugin-assets .. meta:: :title lang=en: Console and Shells diff --git a/en/console-and-shells/completion-shell.rst b/en/console-and-shells/completion-shell.rst index c511b087a38fc0ff5945822d6a52a4f0fb394544..13352a8c58645d9e500404189b30610116372f5a 100644 --- a/en/console-and-shells/completion-shell.rst +++ b/en/console-and-shells/completion-shell.rst @@ -11,7 +11,7 @@ Sub Commands ============ The Completion Shell consists of a number of sub commands to assist the -developer creating it's completion script. Each for a different step in the +developer creating its completion script. Each for a different step in the autocompletion process. Commands @@ -44,7 +44,7 @@ Returns:: controller db_config fixture model plugin project test view options --------- +------- As the third and final options outputs options for the given (sub) command as set in getOptionParser. (Including the default options inherited from Shell.) diff --git a/en/console-and-shells/helpers.rst b/en/console-and-shells/helpers.rst new file mode 100644 index 0000000000000000000000000000000000000000..b4fb5682ee448779da5a8f9821241ed246fecefa --- /dev/null +++ b/en/console-and-shells/helpers.rst @@ -0,0 +1,117 @@ +Shell Helpers +############# + +.. versionadded:: 3.1 + Shell Helpers were added in 3.1.0 + +Shell Helpers let you easily package up complex output generation code. Shell +Helpers can be accessed and used from any shell or task:: + + // Output some data as a table. + $this->helper('table')->output($data); + + // Get a helper from a plugin. + $this->helper('Plugin.HelperName')->output($data); + +You can also get instances of helpers and call any public methods on them:: + + // Get and use the Progress Helper. + $progress = $this->helper('Progress'); + $progress->increment(10); + $progress->draw(); + +Creating Helpers +================ + +While CakePHP comes with a few shell helpers you can create more in your +application or plugins. As an example, we'll create a simple helper to generate +fancy headings. First create the **src/Shell/Helper/HeadingHelper.php** and put +the following in it:: + + _io->out($marker . ' ' . $args[0] . ' ' . $marker); + } + } + +We can then use this new helper in one of our shell commands by calling it:: + + // With ### on either side + $this->helper('heading')->output('It works!'); + + // With ~~~~ on either side + $this->helper('heading')->output('It works!', '~', 4); + +Built-In Helpers +================ + +Table Helper +------------ + +The TableHelper assists in making well formatted ASCII art tables. Using it is +pretty simple:: + + $data = [ + ['Header 1', 'Header', 'Long Header'], + ['short', 'Longish thing', 'short'], + ['Longer thing', 'short', 'Longest Value'], + ]; + $this->helper('table')->output($data); + + // Outputs + +--------------+---------------+---------------+ + | Header 1 | Header | Long Header | + +--------------+---------------+---------------+ + | short | Longish thing | short | + | Longer thing | short | Longest Value | + +--------------+---------------+---------------+ + +Progress Helper +--------------- + +The ProgressHelper can be used in two different ways. The simple mode lets you +provide a callback that is invoked until the progress is complete:: + + $this->helper('progress')->output(function ($progress) { + // Do work here. + $progress->increment(20); + }); + +You can control the progress bar more by providing additional options: + +- ``total`` The total number of items in the progress bar. Defaults + to 100. +- ``width`` The width of the progress bar. Defaults to 80. +- ``callback`` The callback that will be called in a loop to advance the + progress bar. + +An example of all the options in use would be:: + + $this->helper('progress')->output([ + 'total' => 10, + 'width' => 20, + 'callback' => function ($progress) { + $progress->increment(2); + } + ]); + +The progress helper can also be used manually to increment and re-render the +progress bar as necessary:: + + $progress = $this->helper('Progress'); + $progress->init([ + 'total' => 10, + 'width' => 20, + ]); + + $this->helper->increment(4); + $this->helper->draw(); diff --git a/en/console-and-shells/i18n-shell.rst b/en/console-and-shells/i18n-shell.rst index 41dc46c3af1b15df5a208eff8ca8501c3001996c..7d895affc7920ad2c14483afebe7c209e5eaa353 100644 --- a/en/console-and-shells/i18n-shell.rst +++ b/en/console-and-shells/i18n-shell.rst @@ -21,7 +21,7 @@ application will be combined into a single POT file:: bin/cake i18n extract The above will run the extraction shell. The result of this command will be the -file ``src/Locale/default.pot``. You use the pot file as a template for creating +file **src/Locale/default.pot**. You use the pot file as a template for creating po files. If you are manually creating po files from the pot file, be sure to correctly set the ``Plural-Forms`` header line. @@ -59,22 +59,10 @@ no to set the default behavior:: bin/cake i18n extract --extract-core yes - or + // or bin/cake i18n extract --extract-core no - -Create the Tables used by TranslateBehavior -=========================================== - -The i18n shell can also be used to initialize the default tables used by the -:php:class:`TranslateBehavior`:: - - bin/cake i18n initdb - -This will create the ``i18n`` table used by translate behavior. - - .. meta:: :title lang=en: I18N shell :keywords lang=en: pot files,locale default,translation tools,message string,app locale,php class,validation,i18n,translations,shell,models diff --git a/en/console-and-shells/plugin-assets.rst b/en/console-and-shells/plugin-assets.rst deleted file mode 100644 index 9977156beae0ff9f13f9d6a60db93b80ce4ff0e8..0000000000000000000000000000000000000000 --- a/en/console-and-shells/plugin-assets.rst +++ /dev/null @@ -1,21 +0,0 @@ -Plugin Assets Shell -################### - -CakePHP by default serves plugins assets using the ``AssetFilter`` dispatcher -filter. While this is a good convenience, it is recommended to symlink / copy -the plugin assets under app's webroot so that they can be directly served by the -web server without invoking PHP. You can do this by running:: - - bin/cake plugin_assets symlink - -Running the above command will symlink all plugins assets under app's webroot. -On Windows, which doesn't support symlinks, the assets will be copied in -respective folders instead of being symlinked. - -You can symlink assets of one particular plugin by specifying it's name:: - - bin/cake plugin_assets symlink MyPlugin - -.. meta:: - :title lang=en: Plugin Assets Shell - :keywords lang=en: plugin,assets diff --git a/en/console-and-shells/plugin-shell.rst b/en/console-and-shells/plugin-shell.rst new file mode 100644 index 0000000000000000000000000000000000000000..d56fd8e73ef520344b9b66e47bed95ea092e1c7d --- /dev/null +++ b/en/console-and-shells/plugin-shell.rst @@ -0,0 +1,66 @@ +.. _plugin-shell: + +Plugin Shell +############ + +The plugin shell allows you to load and unload plugins via the command prompt. +If you need help, run:: + + bin/cake plugin --help + +Loading Plugins +--------------- + +Via the `Load` task you are able to load plugins in your +``config/bootstrap.php``. You can do this by running:: + + bin/cake plugin load MyPlugin + +This will add the following to your ``config/bootstrap.php``:: + + Plugin::load('MyPlugin', []); + +By adding `-r` or `-b` to your command you can enable to `bootstrap` and +`routes` value:: + + bin/cake plugin load -b MyPlugin + + // will return + Plugin::load('MyPlugin', ['bootstrap' => true]); + + bin/cake plugin load -r MyPlugin + + // will return + Plugin::load('MyPlugin', ['routes' => true]); + +Unloading Plugins +----------------- + +You can unload a plugin by specifying its name:: + + bin/cake plugin unload MyPlugin + +This will remove the line ``Plugin::load('MyPlugin',...`` from your +``config/bootstrap.php``. + +Plugin Assets +------------- + +CakePHP by default serves plugins assets using the ``AssetFilter`` dispatcher +filter. While this is a good convenience, it is recommended to symlink / copy +the plugin assets under app's webroot so that they can be directly served by the +web server without invoking PHP. You can do this by running:: + + bin/cake plugin assets symlink + +Running the above command will symlink all plugins assets under app's webroot. +On Windows, which doesn't support symlinks, the assets will be copied in +respective folders instead of being symlinked. + +You can symlink assets of one particular plugin by specifying its name:: + + bin/cake plugin assets symlink MyPlugin + +.. meta:: + :title lang=en: Plugin Shell + :keywords lang=en: plugin,assets,shell,load,unload diff --git a/en/console-and-shells/repl.rst b/en/console-and-shells/repl.rst index 7cde45f8ab86002cadaccb395e5e81c64b208863..ab96429c854e1fb76de125f3afc010295b74cfcd 100644 --- a/en/console-and-shells/repl.rst +++ b/en/console-and-shells/repl.rst @@ -18,16 +18,16 @@ application's models:: App : App Path: /Users/mark/projects/cakephp-app/src/ --------------------------------------------------------------- - [1] app > $articles = Cake\ORM\TableRegistry::get('Articles'); + >>> $articles = Cake\ORM\TableRegistry::get('Articles'); // object(Cake\ORM\Table)( // // ) - [2] app > $articles->find(); + >>> $articles->find(); Since your application has been bootstrapped you can also test routing using the REPL:: - [1] app > Cake\Routing\Router::parse('/articles/view/1'); + >>> Cake\Routing\Router::parse('/articles/view/1'); // [ // 'controller' => 'Articles', // 'action' => 'view', @@ -39,12 +39,7 @@ REPL:: You can also test generating URL's:: - [1] app > Cake\Routing\Router::url(['controller' => 'Articles', 'action' => 'edit', 99]); + >>> Cake\Routing\Router::url(['controller' => 'Articles', 'action' => 'edit', 99]); // '/articles/edit/99' -To quit the REPL you can use ``CTRL-D``. - -.. warning:: - - The REPL does not work properly on windows systems due to issues with - readline and POSIX extensions. +To quit the REPL you can use ``CTRL-C`` or by typing ``exit``. diff --git a/en/console-and-shells/routes-shell.rst b/en/console-and-shells/routes-shell.rst new file mode 100644 index 0000000000000000000000000000000000000000..d5e6778dda86c7b871d0f8bf9d0b6bab08a1daae --- /dev/null +++ b/en/console-and-shells/routes-shell.rst @@ -0,0 +1,37 @@ +Routes Shell +############ + +.. versionadded:: 3.1 + The RoutesShell was added in 3.1 + +The RoutesShell provides a simple to use CLI interface for testing and debugging +routes. You can use it to test how routes are parsed, and what URLs routing +parameters will generate. + +Getting a List of all Routes +---------------------------- + +:: + bin/cake routes + +Testing URL parsing +------------------- + +You can quickly see how a URL will be parsed using the ``check`` method:: + + bin/cake routes check /bookmarks/edit/1 + +If your route contains any query string parameters remember to surround the URL +in quotes:: + + bin/cake routes check "/bookmarks/?page=1&sort=title&direction=desc" + + +Testing URL Generation +---------------------- + +You can see how which URL a :term:`routing array` will generate using the +``generate`` method:: + + bin/cake routes generate controller:Bookmarks action:edit 1 + diff --git a/en/contents.rst b/en/contents.rst index 60b96277e914d22ff8143ab92cd5dcfc0385ec27..492dbee032e592e923c2d160bf6e225ba33158ac 100644 --- a/en/contents.rst +++ b/en/contents.rst @@ -23,20 +23,20 @@ Contents controllers views orm - development/errors + controllers/components/authentication + bake core-libraries/caching console-and-shells - bake development/debugging deployment core-libraries/email + development/errors core-libraries/events core-libraries/internationalization-and-localization core-libraries/logging - controllers/components/authentication - controllers/components/pagination core-libraries/form + controllers/components/pagination plugins development/rest security @@ -58,6 +58,9 @@ Contents core-libraries/global-constants-and-functions debug-kit + migrations + elasticsearch + upgrade-tool appendices .. todolist:: diff --git a/en/contributing/cakephp-coding-conventions.rst b/en/contributing/cakephp-coding-conventions.rst index 03c661c9e2ab9a6a7cd463a36be9d8ec1bd9a9af..00cf094ddd555fda69e2d8b2d3636047799e88fa 100644 --- a/en/contributing/cakephp-coding-conventions.rst +++ b/en/contributing/cakephp-coding-conventions.rst @@ -434,15 +434,15 @@ Variables --------- Variable names should be as descriptive as possible, but also as short -as possible. Normal variables should start with a lowercase letter, and +as possible. All variables should start with a lowercase letter, and should be written in camelBack in case of multiple words. Variables -referencing objects should start with a capital letter, and in some way -associate to the class the variable is an object of. Example:: +referencing objects should in some way associate to the class the +variable is an object of. Example:: $user = 'John'; $users = ['John', 'Hans', 'Arne']; - $Dispatcher = new Dispatcher(); + $dispatcher = new Dispatcher(); Member Visibility ----------------- diff --git a/en/contributing/documentation.rst b/en/contributing/documentation.rst index c5a760bb12078d776120135fdb47378a6b4f1253..0944b755fdab316e0c6e543c751eb334cbb0cbb9 100644 --- a/en/contributing/documentation.rst +++ b/en/contributing/documentation.rst @@ -8,6 +8,11 @@ You can even edit the docs online with GitHub, without ever downloading the files -- the "Improve this Doc" button on any given page will direct you to GitHub's online editor for that page. +CakePHP documentation is +`continuously integrated `_, +so you can check the status of the `various builds `_ +on the Jenkins server at any time. + Translations ============ @@ -15,7 +20,67 @@ Email the docs team (docs at cakephp dot org) or hop on IRC (#cakephp on freenode) to discuss any translation efforts you would like to participate in. -Translator tips: +New Translation Language +------------------------ + +We want to provide translations that are as complete as possible. However, there +may be times where a translation file is not up-to-date. You should always +consider the English version as the authoritative version. + +If your language is not in the current languages, please contact us through +Github and we will consider creating a skeleton folder for it. The following +sections are the first one you should consider translating as these +files don't change often: + +- index.rst +- intro.rst +- quickstart.rst +- installation.rst +- /intro folder +- /tutorials-and-examples folder + +Reminder for Docs Administrators +-------------------------------- + +The structure of all language folders should mirror the English folder +structure. If the structure changes for the English version, we should apply +those changes in the other languages. + +For example, if a new English file is created in **en/file.rst**, we should: + +- Add the file in all other languages : **fr/file.rst**, **zh/file.rst**, ... +- Delete the content, but keeping the ``title``, ``meta`` information and + eventual ``toc-tree`` elements. The following note will be added while nobody + has translated the file:: + + File Title + ########## + + .. note:: + The documentation is not currently supported in XX language for this + page. + + Please feel free to send us a pull request on + `Github `_ or use the **Improve This Doc** + button to directly propose your changes. + + You can refer to the English version in the select top menu to have + information about this page's topic. + + // If toc-tree elements are in the English version + .. toctree:: + :maxdepth: 1 + + one-toc-file + other-toc-file + + .. meta:: + :title lang=xx: File Title + :keywords lang=xx: title, description,... + + +Translator tips +--------------- - Browse and edit in the language you want the content to be translated to - otherwise you won't see what has already been @@ -33,7 +98,7 @@ Translator tips: - Do not submit partial translations. - Do not edit a section with a pending change. - Do not use - `html entities `_ + `HTML entities `_ for accented characters, the book uses UTF-8. - Do not significantly change the markup (HTML) or add new content - If the original content is missing some info, submit an edit for @@ -42,7 +107,8 @@ Translator tips: Documentation Formatting Guide ============================== -The new CakePHP documentation is written with `ReST formatted text `_. ReST +The new CakePHP documentation is written with +`ReST formatted text `_. ReST (Re Structured Text) is a plain text markup syntax similar to markdown, or textile. To maintain consistency it is recommended that when adding to the CakePHP documentation you follow the guidelines here on how to format and @@ -72,26 +138,33 @@ preceded and followed by a blank line. Paragraphs ---------- -Paragraphs are simply blocks of text, with all the lines at the same level of indentation. -Paragraphs should be separated by more than one empty line. +Paragraphs are simply blocks of text, with all the lines at the same level of +indentation. Paragraphs should be separated by more than one empty line. Inline Markup ------------- * One asterisk: *text* for emphasis (italics) + We'll use it for general highlighting/emphasis. - * ``*text*`` + * ``*text*``. * Two asterisks: **text** for strong emphasis (boldface) + We'll use it for working directories, bullet list subject, table names and + excluding the following word "table". - * ``**text**`` + * ``**/config/Migrations**``, ``**articles**``, etc. * Two backquotes: ``text`` for code samples + We'll use it for names of method options, names of table columns, object + names, excluding the following word "object" and for method/function + names -- include "()". - * ````text```` + * ````cascadeCallbacks````, ````true````, ````id````, + ````PagesController````, ````config()````, etc. -If asterisks or backquotes appear in running text and could be confused with inline markup -delimiters, they have to be escaped with a backslash. +If asterisks or backquotes appear in running text and could be confused with +inline markup delimiters, they have to be escaped with a backslash. Inline markup has a few restrictions: @@ -285,8 +358,8 @@ matching directive is found: .. rst:role:: php:const - Reference either a global constant, or a class constant. Class constants should - be preceded by the owning class:: + Reference either a global constant, or a class constant. Class constants + should be preceded by the owning class:: DateTime has an :php:const:`DateTime::ATOM` constant. @@ -328,7 +401,8 @@ block must be indented, and like all paragraphs be separated by single lines:: This is regular text again. -Literal text is not modified or formatted, save that one level of indentation is removed. +Literal text is not modified or formatted, save that one level of indentation +is removed. Notes and Warnings @@ -336,7 +410,7 @@ Notes and Warnings There are often times when you want to inform the reader of an important tip, special note or a potential hazard. Admonitions in sphinx are used for just -that. There are three kinds of admonitions. +that. There are fives kinds of admonitions. * ``.. tip::`` Tips are used to document or re-iterate interesting or important information. The content of the directive should be written in complete @@ -347,12 +421,19 @@ that. There are three kinds of admonitions. * ``.. warning::`` Warnings are used to document potential stumbling blocks, or information pertaining to security. The content of the directive should be written in complete sentences and include all appropriate punctuation. +* ``.. versionadded:: X.Y.Z`` "Version added" admonitions are used to display notes + specific to new features added at a specific version, ``X.Y.Z`` being the version on + which the said feature was added. +* ``.. deprecated:: X.Y.Z`` As opposed to "version added" admonitions, "deprecated" + admonition are used to notify of a deprecated feature, ``X.Y.Z`` being the version on + which the said feature was deprecated. All admonitions are made the same:: .. note:: - Indented and preceded and followed by a blank line. Just like a paragraph. + Indented and preceded and followed by a blank line. Just like a + paragraph. This text is not part of the note. @@ -371,6 +452,14 @@ Samples It could be dangerous. +.. versionadded:: 2.6.3 + + This awesome feature was added on version 2.6.3 + +.. deprecated:: 2.6.3 + + This old feature was deprecated on version 2.6.3 + .. meta:: :title lang=en: Documentation diff --git a/en/controllers.rst b/en/controllers.rst index 0d0ebff95bf7b9de22cb03c5611586171130511e..dcf1af046cef3ef4c4db39af36a3b04dcf73bc9e 100644 --- a/en/controllers.rst +++ b/en/controllers.rst @@ -22,7 +22,7 @@ handles. Your application's controllers extend the ``AppController`` class, which in turn extends the core :php:class:`Controller` class. The ``AppController`` -class can be defined in ``src/Controller/AppController.php`` and it should +class can be defined in **src/Controller/AppController.php** and it should contain methods that are shared between all of your application's controllers. Controllers provide a number of methods that handle requests. These are called @@ -40,7 +40,7 @@ The App Controller As stated in the introduction, the ``AppController`` class is the parent class to all of your application's controllers. ``AppController`` itself extends the :php:class:`Cake\\Controller\\Controller` class included in CakePHP. -``AppController`` is defined in ``src/Controller/AppController.php`` as +``AppController`` is defined in **src/Controller/AppController.php** as follows:: namespace App\Controller; @@ -104,7 +104,7 @@ to write. By convention, CakePHP renders a view with an inflected version of the action name. Returning to our online bakery example, our RecipesController might contain the ``view()``, ``share()``, and ``search()`` actions. The controller would be found -in ``src/Controller/RecipesController.php`` and contain:: +in **src/Controller/RecipesController.php** and contain:: // src/Controller/RecipesController.php @@ -126,8 +126,8 @@ in ``src/Controller/RecipesController.php`` and contain:: } } -The template files for these actions would be ``src/Template/Recipes/view.ctp``, -``src/Template/Recipes/share.ctp``, and ``src/Template/Recipes/search.ctp``. The +The template files for these actions would be **src/Template/Recipes/view.ctp**, +**src/Template/Recipes/share.ctp**, and **src/Template/Recipes/search.ctp**. The conventional view file name is the lowercased and underscored version of the action name. @@ -213,6 +213,25 @@ assign a set of information to the view:: $this->set($data); +Setting View Options +-------------------- + +If you want to customize the view class, layout/template paths, helpers or the +theme that will be used when rendering the view, you can use the +``viewBuilder()`` method to get a builder. This builder can be used to define +properties of the view before it is created:: + + $this->viewBuilder() + ->helpers(['MyCustom']) + ->theme('Modern') + ->className('Modern.Admin'); + +The above shows how you can load custom helpers, set the theme and use a custom +view class. + +.. versionadded:: 3.1 + ViewBuilder was added in 3.1 + Rendering a View ---------------- @@ -225,7 +244,7 @@ you've submitted using the ``Controller::set()`` method), places the view inside The default view file used by render is determined by convention. If the ``search()`` action of the RecipesController is requested, -the view file in ``src/Template/Recipes/search.ctp`` will be rendered:: +the view file in **src/Template/Recipes/search.ctp** will be rendered:: namespace App\Controller; @@ -246,7 +265,7 @@ an alternate view file by specifying a view file name as first argument of ``Controller::render()`` method. If ``$view`` starts with '/', it is assumed to be a view or -element file relative to the ``src/Template`` folder. This allows +element file relative to the **src/Template** folder. This allows direct rendering of elements, very useful in AJAX calls:: // Render the element in src/Template/Element/ajaxreturn.ctp @@ -272,8 +291,8 @@ have called ``Controller::render()``, CakePHP will not try to re-render the view } } -This would render ``src/Template/Posts/custom_file.ctp`` instead of -``src/Template/Posts/my_action.ctp``. +This would render **src/Template/Posts/custom_file.ctp** instead of +**src/Template/Posts/my_action.ctp**. You can also render views inside plugins using the following syntax: ``$this->render('PluginName.PluginController/custom_file')``. @@ -289,7 +308,7 @@ For example:: } }      -This would render ``plugins/Users/src/Template/UserDetails/custom_file.ctp`` +This would render **plugins/Users/src/Template/UserDetails/custom_file.ctp** Redirecting to Other Pages ========================== @@ -371,7 +390,7 @@ Loading Additional Models .. php:method:: loadModel(string $modelClass, string $type) -The ``loadModel`` function comes handy when you need to use a model +The ``loadModel()`` function comes handy when you need to use a model table/collection that is not the controller's default one:: // In a controller method. @@ -436,7 +455,7 @@ want loaded, and any configuration data for them:: { parent::initialize(); $this->loadComponent('Csrf'); - $this->loadComponent('Comments', Configure:read('Comments')); + $this->loadComponent('Comments', Configure::read('Comments')); } .. php:attr:: components @@ -464,6 +483,10 @@ Each of these variables are merged with their inherited values, therefore it is not necessary (for example) to redeclare the ``FormHelper``, or anything that is declared in your ``AppController``. +.. deprecated:: 3.0 + Loading Helpers from the controller is provided for backwards compatibility + reasons. You should see :ref:`configuring-helpers` for how to load helpers. + .. _controller-life-cycle: Request Life-cycle Callbacks diff --git a/en/controllers/components.rst b/en/controllers/components.rst index dd2ad0828e207a6b4d3a75620a907ec638c300ba..f613f7abd91d48780ad19526e5123c4bd0d0a996 100644 --- a/en/controllers/components.rst +++ b/en/controllers/components.rst @@ -39,7 +39,7 @@ Controller's ``initialize()`` method or via the ``$components`` array:: { parent::initialize(); $this->loadComponent('Auth', [ - 'authorize' => ['controller'], + 'authorize' => 'Controller', 'loginAction' => ['controller' => 'Users', 'action' => 'login'] ]); $this->loadComponent('Cookie', ['expiry' => '1 day']); @@ -167,7 +167,7 @@ many different parts of the application. We could create a component to house this shared logic for use in many different controllers. The first step is to create a new component file and class. Create the file in -``src/Controller/Component/MathComponent.php``. The basic structure for the +**src/Controller/Component/MathComponent.php**. The basic structure for the component would look something like this:: namespace App\Controller\Component; @@ -318,7 +318,7 @@ augment the request cycle. Is invoked when the controller's redirect method is called but before any further action. If this method returns ``false`` the controller will not continue on to redirect the - request. The $url, and $response paramaters allow you to inspect and modify + request. The $url, and $response parameters allow you to inspect and modify the location or any other headers in the response. .. meta:: diff --git a/en/controllers/components/authentication.rst b/en/controllers/components/authentication.rst index e85c5c699f1b8b382854826edd0f5f331a7ecc97..4ad3894e07fd374972f239e88b9d0882a1d1ccb9 100644 --- a/en/controllers/components/authentication.rst +++ b/en/controllers/components/authentication.rst @@ -3,10 +3,10 @@ Authentication .. php:class:: AuthComponent(ComponentCollection $collection, array $config = []) -Identifying, authenticating and authorizing users is a common part of +Identifying, authenticating, and authorizing users is a common part of almost every web application. In CakePHP AuthComponent provides a pluggable way to do these tasks. AuthComponent allows you to combine -authentication objects, and authorization objects to create flexible +authentication objects and authorization objects to create flexible ways of identifying and checking user authorization. .. _authentication-objects: @@ -53,7 +53,7 @@ passwords. Digest authentication uses a digest hash of the username, password, and a few other details. This makes digest authentication more appropriate for applications without SSL encryption. -You can also use authentication systems like openid as well, however openid is +You can also use authentication systems like openid as well; however, openid is not part of CakePHP core. Configuring Authentication Handlers @@ -66,11 +66,11 @@ in. When logging users in, authentication handlers are checked in the order they are declared. Once one handler is able to identify the user, no other handlers will be checked. Conversely you can halt all authentication by throwing an exception. You will need to catch any -thrown exceptions, and handle them as needed. +thrown exceptions and handle them as needed. You can configure authentication handlers in your controller's ``beforeFilter()`` or ``initialize()`` methods. You can pass -configuration information into each authentication object, using an +configuration information into each authentication object using an array:: // Basic setup @@ -104,11 +104,11 @@ keys. - ``fields`` The fields to use to identify a user by. You can use keys ``username`` and ``password`` to specify your username and password fields respectively. -- ``userModel`` The model name of the users table, defaults to Users. -- ``scope`` Additional conditions to use when looking up and - authenticating users, i.e. ``['Users.is_active' => true]``. -- ``contain`` Extra models to contain and return with identified user's info. -- ``passwordHasher`` Password hasher class. Defaults to ``Default``. +- ``userModel`` The model name of the users table; defaults to Users. +- ``finder`` The finder method to use to fetch a user record. Defaults to 'all'. +- ``passwordHasher`` Password hasher class; Defaults to ``Default``. +- The ``scope`` and ``contain`` options have been deprecated as of 3.1. Use + a custom finder instead to modify the query to fetch a user record. To configure different fields for user in your ``initialize()`` method:: @@ -124,7 +124,7 @@ To configure different fields for user in your ``initialize()`` method:: ]); } -Do not put other ``Auth`` configuration keys (like ``authError``, ``loginAction`` etc) +Do not put other ``Auth`` configuration keys, such as ``authError``, ``loginAction``, etc., within the ``authenticate`` or ``Form`` element. They should be at the same level as the authenticate key. The setup above with other Auth configuration should look like:: @@ -143,7 +143,8 @@ should look like:: 'Form' => [ 'fields' => ['username' => 'email'] ] - ] + ], + 'storage' => 'Session' ]); } @@ -155,11 +156,46 @@ the following keys: In addition to the common configuration Digest authentication supports the following keys: -- ``realm`` The realm authentication is for, Defaults to the servername. +- ``realm`` The realm authentication is for. Defaults to the servername. - ``nonce`` A nonce used for authentication. Defaults to ``uniqid()``. -- ``qop`` Defaults to auth, no other values are supported at this time. +- ``qop`` Defaults to auth; no other values are supported at this time. - ``opaque`` A string that must be returned unchanged by clients. Defaults - to ``md5($config['realm'])`` + to ``md5($config['realm'])``. + +Customizing find query +---------------------- + +You can customize the query used to fetch the user record using the ``finder`` +option in authenticate class config:: + + public function initialize() + { + parent::initialize(); + $this->loadComponent('Auth', [ + 'authenticate' => [ + 'Form' => [ + 'finder' => 'auth' + ] + ], + ]); + } + +This will require your ``UsersTable`` to have finder method ``findAuth()``. +In the example shown below the query is modified to fetch only required fields +and add condition:: + + public function findAuth(\Cake\ORM\Query $query, array $option) + { + $query + ->select(['id', 'username', 'password']) + ->where(['Users.active' => 1]); + + return $query; + } + +.. note:: + ``finder`` option is available since 3.1. Prior to that you can use ``scope`` + and ``contain`` options to modify query. Identifying Users and Logging Them In ------------------------------------- @@ -168,7 +204,7 @@ Identifying Users and Logging Them In You need to manually call ``$this->Auth->identify()`` to identify the user using credentials provided in request. Then use ``$this->Auth->setUser()`` -to log the user in i.e. save user info to session. +to log the user in, i.e., save user info to session. When authenticating users, attached authentication objects are checked in the order they are attached. Once one of the objects can identify @@ -193,9 +229,9 @@ working with a login form could look like:: } } -The above code will attempt to first identify a user in using the POST data. -If successful we set the user info to session so that it persists across requests -and redirect to either the last page they were visiting or a URL specified in the +The above code will attempt to first identify a user by using the POST data. +If successful we set the user info to the session so that it persists across requests +and then redirect to either the last page they were visiting or a URL specified in the ``loginRedirect`` config. If the login is unsuccessful, a flash message is set. .. warning:: @@ -213,7 +249,7 @@ After logging a user in, you'll generally want to redirect them back to where they came from. Pass a URL in to set the destination a user should be redirected to upon logging in. -If no parameter is passed, gets the authentication redirect URL. The URL +If no parameter is passed, it gets the authentication redirect URL. The URL returned is as per following rules: - Returns the normalized URL from session Auth.redirect value if it is @@ -222,19 +258,179 @@ returned is as per following rules: ``loginRedirect`` value is returned. - If there is no session and no ``loginRedirect``, / is returned. -Using Digest and Basic Authentication for Logging In -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Creating Stateless Authentication Systems +----------------------------------------- Basic and digest are stateless authentication schemes and don't require an initial POST or a form. If using only basic / digest authenticators you don't -require a login action in your controller. Also you can set -``$this->Auth->sessionKey`` to ``false`` to ensure AuthComponent doesn't try to -read user info from session. You may also want to set config -``unauthorizedRedirect`` to ``false`` which will cause AuthComponent to throw -a ``ForbiddenException`` instead of default behavior of redirecting to referer. -Stateless authentication will re-verify the user's credentials on each request, -this creates a small amount of additional overhead, but allows clients to -login in without using cookies and makes is suitable for APIs. +require a login action in your controller. Stateless authentication will +re-verify the user's credentials on each request, this creates a small amount of +additional overhead, but allows clients to login without using cookies and +makes AuthComponent more suitable for building APIs. + +For stateless authenticators the ``storage`` config should be set to ``Memory`` +so that AuthComponent does not use session to storage user record. You may also +want to set config ``unauthorizedRedirect`` to ``false`` so that AuthComponent +throws a ``ForbiddenException`` instead of default behavior of redirecting to +referrer. + +Authentication objects can implement a ``getUser()`` method that can be used to +support user login systems that don't rely on cookies. A typical getUser method +looks at the request/environment and uses the information there to confirm the +identity of the user. HTTP Basic authentication for example uses +``$_SERVER['PHP_AUTH_USER']`` and ``$_SERVER['PHP_AUTH_PW']`` for the username +and password fields. + +.. note:: + + In case authentication does not work like expected, check if queries + are executed at all (see ``BaseAuthenticate::_query($username)``). + In case no queries are executed check if ``$_SERVER['PHP_AUTH_USER']`` + and ``$_SERVER['PHP_AUTH_PW']`` do get populated by the webserver. + If you are using Apache with FastCGI-PHP you might need to add this line + to your **.htaccess** file in webroot:: + + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] + +On each request, these values, ``PHP_AUTH_USER`` and ``PHP_AUTH_PW``, are used to +re-identify the user and ensure they are valid user. As with authentication +object's ``authenticate()`` method, the ``getUser()`` method should return +an array of user information on success or ``false`` on failure. :: + + public function getUser(Request $request) + { + $username = env('PHP_AUTH_USER'); + $pass = env('PHP_AUTH_PW'); + + if (empty($username) || empty($pass)) { + return false; + } + return $this->_findUser($username, $pass); + } + +The above is how you could implement getUser method for HTTP basic +authentication. The ``_findUser()`` method is part of ``BaseAuthenticate`` +and identifies a user based on a username and password. + +Using Basic Authentication +-------------------------- + +Basic authentication allows you to create a stateless authentication that can be +used in intranet applications or for simple API scenarios. Basic authentication +credentials will be rechecked on each request. + +.. warning:: + Basic authentication transmits credentials in plain-text. You should use + HTTPS when using Basic authentication. + + +To use basic authentication, you'll need to configure AuthComponent:: + + $this->Auth->config('authenticate', [ + 'Basic' => [ + 'fields' => ['username' => 'username', 'password' => 'api_key'] + 'userModel' => 'Users' + ], + ]); + +Here we're using username + API key as our fields, and use the Users model. + +Creating API Keys for Basic Authentication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Because basic HTTP sends credentials in plain-text, it is unwise to have user's +send their login password. Instead an opaque API key is generally used. You can +generate these API tokens randomly using libraries from CakePHP:: + + namespace App\Model\Table; + + use Cake\Utility\Text; + use Cake\Utility\Security; + use Cake\Event\Event; + use Cake\ORM\Table; + + class UsersTable extends Table + { + public function beforeSave(Event $event) + { + $entity = $event->data['entity']; + + if ($entity->isNew()) { + $entity->api_key = Security::hash(Text::uuid()); + } + return true; + } + } + +The above generates a random hash for each user as they are saved. Using this +key instead of a password, means that even over plain HTTP, your user's don't +have to send their password in API requests. You can also write additional logic +to regenerate the API key at the user's request. + +Using Digest Authentication +--------------------------- + +Digest authentication offers an improved security model over basic +authentication, as the user's credentials are never sent in the request header. +Instead a hash is sent. + +To use digest authentication, you'll need to configure AuthComponent:: + + $this->Auth->config('authenticate', [ + 'Digest' => [ + 'fields' => ['username' => 'username', 'password' => 'digest_hash'] + 'userModel' => 'Users' + ], + ]); + +Here we're using username + digest_hash as our fields, and use the Users model. + + +Hashing Passwords For Digest Authentication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Because Digest authentication requires a password hashed in the format +defined by the RFC, in order to correctly hash a password for use with +Digest authentication you should use the special password hashing +function on ``DigestAuthenticate``. If you are going to be combining +digest authentication with any other authentication strategies, it's also +recommended that you store the digest password in a separate column, +from the normal password hash:: + + namespace App\Model\Table; + + use Cake\Auth\DigestAuthenticate; + use Cake\Event\Event; + use Cake\ORM\Table; + + class UsersTable extends Table + { + public function beforeSave(Event $event) + { + $entity = $event->data['entity']; + + // Make a password for digest auth. + $entity->digest_hash = DigestAuthenticate::password( + $entity->username, + $entity->plain_password, + env('SERVER_NAME') + ); + return true; + } + } + +Passwords for digest authentication need a bit more information than +other password hashes, based on the RFC for digest authentication. + +.. note:: + + The third parameter of DigestAuthenticate::password() must match the + 'realm' config value defined when DigestAuthentication was + configured in AuthComponent::$authenticate. This defaults to + ``env('SCRIPT_NAME')``. You may wish to use a static string if you + want consistent hashes in multiple environments. + Creating Custom Authentication Objects -------------------------------------- @@ -242,9 +438,13 @@ Creating Custom Authentication Objects Because authentication objects are pluggable, you can create custom authentication objects in your application or plugins. If for example you wanted to create an OpenID authentication object. In -``src/Auth/OpenidAuthenticate.php`` you could put the following:: +**src/Auth/OpenidAuthenticate.php** you could put the following:: + + namespace App\Auth; use Cake\Auth\BaseAuthenticate; + use Cake\Network\Request; + use Cake\Network\Response; class OpenidAuthenticate extends BaseAuthenticate { @@ -259,13 +459,13 @@ you wanted to create an OpenID authentication object. In Authentication objects should return ``false`` if they cannot identify the user and an array of user information if they can. It's not required that you extend ``BaseAuthenticate``, only that your authentication object -implements an ``authenticate()`` method. The ``BaseAuthenticate`` class +implements ``Cake\Event\EventListenerInterface``. The ``BaseAuthenticate`` class provides a number of helpful methods that are commonly used. You can also implement a ``getUser()`` method if your authentication object needs to support stateless or cookie-less authentication. See the sections on basic and digest authentication below for more information. -``AuthComponent`` triggers two events ``Auth.afterIdentify`` and ``Auth.logout`` +``AuthComponent`` triggers two events, ``Auth.afterIdentify`` and ``Auth.logout``, after a user has been identified and before a user is logged out respectively. You can set callback functions for these events by returning a mapping array from ``implementedEvents()`` method of your authenticate class:: @@ -287,37 +487,13 @@ by including them in AuthComponents authenticate array:: $this->Auth->config('authenticate', [ 'Openid', // app authentication object. - 'AuthBag.Combo', // plugin authentication object. + 'AuthBag.Openid', // plugin authentication object. ]); -Creating Stateless Authentication Systems ------------------------------------------ - -Authentication objects can implement a ``getUser()`` method that can be -used to support user login systems that don't rely on cookies. A -typical getUser method looks at the request/environment and uses the -information there to confirm the identity of the user. HTTP Basic -authentication for example uses ``$_SERVER['PHP_AUTH_USER']`` and -``$_SERVER['PHP_AUTH_PW']`` for the username and password fields. On each -request, these values are used to re-identify the user and ensure they are -valid user. As with authentication object's ``authenticate()`` method the -``getUser()`` method should return an array of user information on success or -``false`` on failure. :: - - public function getUser($request) - { - $username = env('PHP_AUTH_USER'); - $pass = env('PHP_AUTH_PW'); - - if (empty($username) || empty($pass)) { - return false; - } - return $this->_findUser($username, $pass); - } - -The above is how you could implement getUser method for HTTP basic -authentication. The ``_findUser()`` method is part of ``BaseAuthenticate`` -and identifies a user based on a username and password. +.. note:: + Note that when using simple notation there's no 'Authenticate' word when + initiating the authentication object. Instead, if using namespaces, you'll need + to set the full namespace of the class, including the 'Authenticate' word. Handling Unauthenticated Requests --------------------------------- @@ -325,7 +501,7 @@ Handling Unauthenticated Requests When an unauthenticated user tries to access a protected page first the ``unauthenticated()`` method of the last authenticator in the chain is called. The authenticate object can handle sending response or redirection by returning -a response object, to indicate no further action is necessary. Due to this, the +a response object to indicate no further action is necessary. Due to this, the order in which you specify the authentication provider in ``authenticate`` config matters. @@ -338,12 +514,12 @@ Displaying Auth Related Flash Messages In order to display the session error messages that Auth generates, you need to add the following code to your layout. Add the following two -lines to the ``src/Template/Layout/default.ctp`` file in the body section:: +lines to the **src/Template/Layout/default.ctp** file in the body section:: echo $this->Flash->render(); echo $this->Flash->render('auth'); -You can customize the error messages, and flash settings AuthComponent +You can customize the error messages and flash settings AuthComponent uses. Using ``flash`` config you can configure the parameters AuthComponent uses for setting flash messages. The available keys are @@ -361,7 +537,7 @@ Sometimes, you want to display the authorization error only after the user has already logged-in. You can suppress this message by setting its value to boolean ``false``. -In your controller's beforeFilter(), or component settings:: +In your controller's beforeFilter() or component settings:: if (!$this->Auth->user()) { $this->Auth->config('authError', false); @@ -406,8 +582,8 @@ Creating Custom Password Hasher Classes --------------------------------------- In order to use a different password hasher, you need to create the class in -``src/Auth/LegacyPasswordHasher.php`` and implement the -``hash`` and ``check`` methods. This class needs to extend the +**src/Auth/LegacyPasswordHasher.php** and implement the +``hash()`` and ``check()`` methods. This class needs to extend the ``AbstractPasswordHasher`` class:: namespace App\Auth; @@ -454,7 +630,7 @@ Changing Hashing Algorithms CakePHP provides a clean way to migrate your users' passwords from one algorithm to another, this is achieved through the ``FallbackPasswordHasher`` class. -Assuming you are using ``LegacyPasswordHasher`` from the previous example, you +Assuming you are migrating your app from CakePHP 2.x which uses ``sha1`` password hashes, you can configure the AuthComponent as follows:: public function initialize() @@ -465,7 +641,10 @@ can configure the AuthComponent as follows:: 'Form' => [ 'passwordHasher' => [ 'className' => 'Fallback', - 'hashers' => ['Default', 'Legacy'] + 'hashers' => [ + 'Default', + 'Weak' => ['hashType' => 'sha1'] + ] ] ] ] @@ -503,51 +682,6 @@ As you can see we are just setting the plain password again so the setter function in the entity will hash the password as shown in the previous example and then save the entity. -Hashing Passwords For Digest Authentication -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Because Digest authentication requires a password hashed in the format -defined by the RFC, in order to correctly hash a password for use with -Digest authentication you should use the special password hashing -function on ``DigestAuthenticate``. If you are going to be combining -digest authentication with any other authentication strategies, it's also -recommended that you store the digest password in a separate column, -from the normal password hash:: - - namespace App\Model\Table; - - use Cake\Auth\DigestAuthenticate; - use Cake\Event\Event; - use Cake\ORM\Table; - - class UsersTable extends Table - { - - public function beforeSave(Event $event) - { - $entity = $event->data['entity']; - - // Make a password for digest auth. - $entity->digest_hash = DigestAuthenticate::password( - $entity->username, - $entity->plain_password, - env('SERVER_NAME') - ); - return true; - } - } - -Passwords for digest authentication need a bit more information than -other password hashes, based on the RFC for digest authentication. - -.. note:: - - The third parameter of DigestAuthenticate::password() must match the - 'realm' config value defined when DigestAuthentication was - configured in AuthComponent::$authenticate. This defaults to - ``env('SCRIPT_NAME')``. You may wish to use a static string if you - want consistent hashes in multiple environments. - Manually Logging Users In ------------------------- @@ -595,7 +729,7 @@ Logging Users Out .. php:method:: logout() -Eventually you'll want a quick way to de-authenticate someone, and +Eventually you'll want a quick way to de-authenticate someone and redirect them to where they need to go. This method is also useful if you want to provide a 'Log me out' link inside a members' area of your application:: @@ -621,8 +755,8 @@ identified/authenticated user is allowed to access the resources they are requesting. If enabled ``AuthComponent`` can automatically check authorization handlers and ensure that logged in users are allowed to access the resources they are requesting. There are several built-in -authorization handlers, and you can create custom ones for your -application, or as part of a plugin. +authorization handlers and you can create custom ones for your +application or as part of a plugin. - ``ControllerAuthorize`` Calls ``isAuthorized()`` on the active controller, and uses the return of that to authorize a user. This is often the @@ -647,7 +781,7 @@ Handlers should return ``true`` if they were able to check authorization successfully. Handlers will be called in sequence until one passes. If all checks fail, the user will be redirected to the page they came from. Additionally you can halt all authorization by throwing an exception. -You will need to catch any thrown exceptions, and handle them. +You will need to catch any thrown exceptions and handle them. You can configure authorization handlers in your controller's ``beforeFilter()`` or ``initialize()`` methods. You can pass @@ -691,7 +825,7 @@ Creating Custom Authorize Objects Because authorize objects are pluggable, you can create custom authorize objects in your application or plugins. If for example you wanted to create an LDAP authorize object. In -``src/Auth/LdapAuthorize.php`` you could put the +**src/Auth/LdapAuthorize.php** you could put the following:: namespace App\Auth; @@ -728,12 +862,12 @@ including them in your AuthComponent's authorize array:: Using No Authorization ---------------------- -If you'd like to not use any of the built-in authorization objects, and -want to handle things entirely outside of AuthComponent you can set +If you'd like to not use any of the built-in authorization objects and +want to handle things entirely outside of AuthComponent, you can set ``$this->Auth->config('authorize', false);``. By default AuthComponent starts off with ``authorize`` set to ``false``. If you don't use an authorization scheme, make sure to check authorization yourself in your controller's -beforeFilter, or with another component. +beforeFilter or with another component. Making Actions Public @@ -742,11 +876,11 @@ Making Actions Public .. php:method:: allow($actions = null) There are often times controller actions that you wish to remain -entirely public, or that don't require users to be logged in. -AuthComponent is pessimistic, and defaults to denying access. You can +entirely public or that don't require users to be logged in. +AuthComponent is pessimistic and defaults to denying access. You can mark actions as public actions by using ``AuthComponent::allow()``. By -marking actions as public, AuthComponent, will not check for a logged in -user, nor will authorize objects be checked:: +marking actions as public, AuthComponent will not check for a logged in +user nor will authorize objects be checked:: // Allow all actions $this->Auth->allow(); @@ -772,7 +906,7 @@ Making Actions Require Authorization .. php:method:: deny($actions = null) By default all actions require authorization. However, after making actions -public, you want to revoke the public access. You can do so using +public you want to revoke the public access. You can do so using ``AuthComponent::deny()``:: // Deny all actions. @@ -793,13 +927,13 @@ Using ControllerAuthorize ControllerAuthorize allows you to handle authorization checks in a controller callback. This is ideal when you have very simple -authorization, or you need to use a combination of models + components -to do your authorization, and don't want to create a custom authorize +authorization or you need to use a combination of models and components +to do your authorization and don't want to create a custom authorize object. The callback is always called ``isAuthorized()`` and it should return a boolean as to whether or not the user is allowed to access resources in -the request. The callback is passed the active user, so it can be +the request. The callback is passed the active user so it can be checked:: class AppController extends Controller @@ -830,7 +964,7 @@ checked:: } The above callback would provide a very simple authorization system -where, only users with role = admin could access actions that were in +where only users with role = admin could access actions that were in the admin prefix. Configuration options @@ -846,7 +980,7 @@ allowedActions Controller actions for which user validation is not required. authenticate Set to an array of Authentication objects you want to use when - logging users in. There are several core authentication objects, + logging users in. There are several core authentication objects; see the section on :ref:`authentication-objects`. authError Error to display when user attempts to access an object or action to which @@ -856,16 +990,16 @@ authError value to boolean ``false``. authorize Set to an array of Authorization objects you want to use when - authorizing users on each request, see the section on + authorizing users on each request; see the section on :ref:`authorization-objects`. flash Settings to use when Auth needs to do a flash message with ``FlashComponent::set()``. Available keys are: - - ``element`` - The element to use, defaults to 'default'. - - ``key`` - The key to use, defaults to 'auth' - - ``params`` - The array of additional params to use, defaults to [] + - ``element`` - The element to use; defaults to 'default'. + - ``key`` - The key to use; defaults to 'auth'. + - ``params`` - The array of additional params to use; defaults to []. loginAction A URL (defined as a string or array) to the controller action that handles @@ -882,7 +1016,7 @@ logoutRedirect unauthorizedRedirect Controls handling of unauthorized access. By default unauthorized user is redirected to the referrer URL or ``loginAction`` or '/'. - If set to ``false`` a ForbiddenException exception is thrown instead of + If set to ``false``, a ForbiddenException exception is thrown instead of redirecting. Testing Actions Protected By AuthComponent diff --git a/en/controllers/components/cookie.rst b/en/controllers/components/cookie.rst index 169f0e4a97589699505d2b05c92da9227a3ec63e..a7f535e36d182e3353c6e996f82aae8164371c7a 100644 --- a/en/controllers/components/cookie.rst +++ b/en/controllers/components/cookie.rst @@ -1,11 +1,11 @@ -CookieComponent -############### +Cookie +###### .. php:namespace:: Cake\Controller\Component .. php:class:: CookieComponent(ComponentRegistry $collection, array $config = []) -The CookieComponent is a wrapper around the native PHP ``setcookie`` method. It +The CookieComponent is a wrapper around the native PHP ``setcookie()`` method. It makes it easier to manipulate cookies, and automatically encrypt cookie data. Configuring Cookies diff --git a/en/controllers/components/csrf.rst b/en/controllers/components/csrf.rst index 4f73eb5f5dc515486e0d8c39aa97eab8d7a82e1a..b4fbf42e61e87db3ec0fb8f83074eba9b25996be 100644 --- a/en/controllers/components/csrf.rst +++ b/en/controllers/components/csrf.rst @@ -1,5 +1,5 @@ -Cross Site Request Forgery Component -#################################### +Cross Site Request Forgery +########################## By enabling the CSRF Component you get protection against attacks. `CSRF `_ or Cross Site @@ -12,7 +12,14 @@ are created with the :php:class:`Cake\\View\\Helper\\FormHelper`, a hidden field is added containing the CSRF token. During the ``Controller.startup`` event, if the request is a POST, PUT, DELETE, PATCH request the component will compare the request data & cookie value. If either is missing or the two values mismatch the -component will throw a :php:class:`Cake\Network\Exception\ForbiddenException`. +component will throw a +:php:class:`Cake\\Network\\Exception\\InvalidCsrfTokenException`. + +.. versionadded:: 3.1 + + The exception type changed from + :php:class:`Cake\\Network\\Exception\\ForbiddenException` to + :php:class:`Cake\\Network\\Exception\\InvalidCsrfTokenException`. Using the CsrfComponent ======================= @@ -23,9 +30,7 @@ you can benefit from the CSRF protection it provides:: public function initialize() { parent::initialize(); - $this->loadComponent('Csrf', [ - 'secure' => true - ]); + $this->loadComponent('Csrf'); } Settings can be passed into the component through your component's settings. @@ -33,8 +38,10 @@ The available configuration options are: - ``cookieName`` The name of the cookie to send. Defaults to ``csrfToken``. - ``expiry`` How long the CSRF token should last. Defaults to browser session. -- ``secure`` Whether or not the cookie will be set with the Secure flag. - Defaults to ``false``. + Accepts ``strtotime`` values as of 3.1 +- ``secure`` Whether or not the cookie will be set with the Secure flag. That is, + the cookie will only be set on a HTTPS connection and any attempt over normal HTTP + will fail. Defaults to ``false``. - ``field`` The form field to check. Defaults to ``_csrfToken``. Changing this will also require configuring FormHelper. @@ -68,7 +75,7 @@ Disabling the CSRF Component for Specific Actions While not recommended, you may want to disable the CsrfComponent on certain requests. You can do this using the controller's event dispatcher, during the -``beforeFilter`` method:: +``beforeFilter()`` method:: public function beforeFilter(Event $event) { diff --git a/en/controllers/components/flash.rst b/en/controllers/components/flash.rst index b8d653d56a68e796d86aba1a26890eed08a77688..95e6898398da9ece3cd257c9b94e87d27738851b 100644 --- a/en/controllers/components/flash.rst +++ b/en/controllers/components/flash.rst @@ -1,5 +1,5 @@ -FlashComponent -############## +Flash +##### .. php:namespace:: Cake\Controller\Component @@ -14,10 +14,10 @@ messages as "flash messages". FlashComponent writes flash messages to Setting Flash Messages ====================== -FlashComponent provides two ways to set flash messages: its ``__call`` magic +FlashComponent provides two ways to set flash messages: its ``__call()`` magic method and its ``set()`` method. To furnish your application with verbosity, -FlashComponent's ``__call`` magic method allows you use a method name that maps -to an element located under the ``src/Template/Element/Flash`` directory. By +FlashComponent's ``__call()`` magic method allows you use a method name that maps +to an element located under the **src/Template/Element/Flash** directory. By convention, camelcased methods will map to the lowercased and underscored element name:: @@ -32,7 +32,15 @@ use the ``set()`` method:: $this->Flash->set('This is a message'); -FlashComponent's ``__call`` and ``set()`` methods optionally take a second + +.. versionadded:: 3.1 + + Flash messages now stack. Successive calls to ``set()`` or ``__call()`` with + the same key will append the messages in the ``$_SESSION``. If you want to keep + the old behavior (one message even after consecutive calls), set the ``clear`` + parameter to ``true`` when configuring the Component. + +FlashComponent's ``__call()`` and ``set()`` methods optionally take a second parameter, an array of options: * ``key`` Defaults to 'flash'. The array key found under the 'Flash' key in @@ -42,6 +50,11 @@ parameter, an array of options: * ``params`` An optional array of keys/values to make available as variables within an element. +.. versionadded:: 3.1 + + A new key ``clear`` was added. This key expects a ``bool`` and allows you + to delete all messages in the current stack and start a new one. + An example of using these options:: // In your Controller @@ -61,10 +74,21 @@ An example of using these options:: : , . +Note that the parameter ``element`` will be always overridden while using ``__call()``. +In order to retrieve a specific element from a plugin, you should set the ``plugin`` parameter. +For example:: + + // In your Controller + $this->Flash->warning('My message', ['plugin' => 'PluginName']); + +The code above will use the warning.ctp element under **plugins/PluginName/src/Template/Element/Flash** +for rendering the flash message. + .. note:: + By default, CakePHP does not escape the HTML in flash messages. If you are using any request or user data in your flash messages, you should escape it with :php:func:`h` when formatting your messages. For more information about rendering your flash messages, please refer to the -:doc:`FlashHelper ` section. +:doc:`FlashHelper ` section. \ No newline at end of file diff --git a/en/controllers/components/request-handling.rst b/en/controllers/components/request-handling.rst index 6427931f2a3312b4f0d487b2b610e45681a332c1..14cd822a0f224d053855a25379f978bc05645a9e 100644 --- a/en/controllers/components/request-handling.rst +++ b/en/controllers/components/request-handling.rst @@ -253,7 +253,7 @@ automatically by using the ``viewClassMap`` setting:: public function initialize() { parent::initialize(); - $this->loadComponent(''RequestHandler', [ + $this->loadComponent('RequestHandler', [ 'viewClassMap' => [ 'json' => 'ApiKit.MyJson', 'xml' => 'ApiKit.MyXml', diff --git a/en/controllers/components/security.rst b/en/controllers/components/security.rst index 43124b3d815b11a60f07825c3611811e5532670b..d3080063f5ef97f454d073aad167549627e58433 100644 --- a/en/controllers/components/security.rst +++ b/en/controllers/components/security.rst @@ -1,5 +1,5 @@ -SecurityComponent -################## +Security +######## .. php:class:: SecurityComponent(ComponentCollection $collection, array $config = []) @@ -214,7 +214,7 @@ Disabling Security Component for Specific Actions There may be cases where you want to disable all security checks for an action (ex. AJAX requests). You may "unlock" these actions by listing them in -``$this->Security->unlockedActions`` in your ``beforeFilter``. The +``$this->Security->unlockedActions`` in your ``beforeFilter()``. The ``unlockedActions`` property will **not** affect other features of ``SecurityComponent``:: diff --git a/en/controllers/pages-controller.rst b/en/controllers/pages-controller.rst index 0466d0cc4866f217a4981f632436b652ffc3bb8b..f937c0a43179cc5866918cc8f03f3565f28fbf3c 100644 --- a/en/controllers/pages-controller.rst +++ b/en/controllers/pages-controller.rst @@ -1,16 +1,17 @@ The Pages Controller #################### -CakePHP ships with a default controller ``PagesController.php``. This is a +CakePHP ships with a default controller **PagesController.php**. This is a simple and optional controller for serving up static content. The home page -you see after installation is generated using this controller. If you make the -view file ``src/Template/Pages/about_us.ctp`` you can access it using the URL -``http://example.com/pages/about_us``. You are free to modify the Pages +you see after installation is generated using this controller and the view +file **src/Template/Pages/home.ctp**. If you make the view file +**src/Template/Pages/about_us.ctp** you can access it using the URL +**http://example.com/pages/about_us**. You are free to modify the Pages Controller to meet your needs. When you "bake" an app using Composer the Pages Controller is created in your -``src/Controller/`` folder. +**src/Controller/** folder. .. meta:: :title lang=en: The Pages Controller - :keywords lang=en: pages controller,default controller,cakephp,ships,php,file folder + :keywords lang=en: pages controller,default controller,cakephp,ships,php,file folder,home page diff --git a/en/controllers/request-response.rst b/en/controllers/request-response.rst index 9184a76ebd8446738514ae6a195b4099991cc048..da4e3abe093985c316ff322e2ab17beb28b6c45a 100644 --- a/en/controllers/request-response.rst +++ b/en/controllers/request-response.rst @@ -152,7 +152,7 @@ into a DOMDocument object, :php:meth:`~Cake\\Network\\Request::input()` supports in additional parameters as well:: // Get Xml encoded data submitted to a PUT/POST action - $data = $this->request->input('Xml::build', ['return' => 'domdocument']); + $data = $this->request->input('Cake\Utility\Xml::build', ['return' => 'domdocument']); Path Information ---------------- @@ -242,16 +242,21 @@ There are several built-in detectors that you can use: * ``is('get')`` Check to see whether the current request is a GET. * ``is('put')`` Check to see whether the current request is a PUT. +* ``is('patch')`` Check to see whether the current request is a PATCH. * ``is('post')`` Check to see whether the current request is a POST. * ``is('delete')`` Check to see whether the current request is a DELETE. * ``is('head')`` Check to see whether the current request is HEAD. * ``is('options')`` Check to see whether the current request is OPTIONS. * ``is('ajax')`` Check to see whether the current request came with X-Requested-With = XMLHttpRequest. -* ``is('ssl')`` Check to see whether the request is via SSL -* ``is('flash')`` Check to see whether the request has a User-Agent of Flash -* ``is('mobile')`` Check to see whether the request came from a common list - of mobile agents. +* ``is('ssl')`` Check to see whether the request is via SSL. +* ``is('flash')`` Check to see whether the request has a User-Agent of Flash. +* ``is('requested')`` Check to see whether the request has a query param + 'requested' with value 1. +* ``is('json')`` Check to see whether the request has 'json' extension and + accept 'application/json' mimetype. +* ``is('xml')`` Check to see whether the request has 'xml' extension and accept + 'application/xml' or 'text/xml' mimetype. Session Data @@ -259,7 +264,7 @@ Session Data To access the session for a given request use the ``session()`` method:: - $this->request->session()->read('User.name'); + $this->request->session()->read('Auth.User.name'); For more information, see the :doc:`/development/sessions` documentation for how to use the session object. @@ -396,14 +401,13 @@ Changing the Response Class CakePHP uses ``Response`` by default. ``Response`` is a flexible and transparent class. If you need to override it with your own application-specific class, -you can replace ``Response`` in ``webroot/index.php``. +you can replace ``Response`` in **webroot/index.php**. This will make all the controllers in your application use ``CustomResponse`` instead of :php:class:`Cake\\Network\\Response`. You can also replace the response instance by setting ``$this->response`` in your controllers. Overriding the response object is handy during testing, as it allows you to stub -out the methods that interact with :php:meth:`~CakeResponse::header()`. See the section on -:ref:`cakeresponse-testing` for more information. +out the methods that interact with :php:meth:`Cake\\Network\\Response::header()`. Dealing with Content Types -------------------------- @@ -446,7 +450,7 @@ You can accomplish that by using :php:meth:`Cake\\Network\\Response::file()`:: public function sendFile($id) { - $file = $this->Attachment->getFile($id); + $file = $this->Attachments->getFile($id); $this->response->file($file['path']); // Return response object to prevent controller from trying to render // a view. @@ -484,7 +488,7 @@ a pdf or an ics generated on the fly from a string:: public function sendIcs() { - $icsString = $this->Calendar->generateIcs(); + $icsString = $this->Calendars->generateIcs(); $this->response->body($icsString); $this->response->type('ics'); @@ -496,6 +500,27 @@ a pdf or an ics generated on the fly from a string:: return $this->response; } +Streaming Resources +------------------- + +You can use a callable with ``body()`` to easily convert resource streams into +responses:: + + $file = fopen('/some/file.png', 'r'); + $this->response->body(function () use ($file) { + rewind($file); + fpassthru($file); + fclose($file); + }); + +Callbacks can also return the body as a string:: + + $path = '/some/file.png'; + $this->response->body(function () use ($path) { + return file_get_contents($path); + }); + + Setting Headers --------------- @@ -660,8 +685,8 @@ To take advantage of this header, you must either call the public function index() { - $articles = $this->Article->find('all'); - $this->response->etag($this->Article->generateHash($articles)); + $articles = $this->Articles->find('all'); + $this->response->etag($this->Articles->generateHash($articles)); if ($this->response->checkNotModified($this->request)) { return $this->response; } @@ -684,8 +709,8 @@ To take advantage of this header, you must either call the public function view() { - $article = $this->Article->find('first'); - $this->response->modified($article['Article']['modified']); + $article = $this->Articles->find()->first(); + $this->response->modified($article->modified); if ($this->response->checkNotModified($this->request)) { return $this->response; } @@ -728,27 +753,6 @@ Once you are done creating a response, calling ``send()`` will send all the set headers as well as the body. This is done automatically at the end of each request by ``Dispatcher``. - -.. _cakeresponse-testing: - -Response and Testing --------------------- - -The ``Response`` class helps make testing controllers and components easier. -By having a single place to mock/stub headers you can more easily test -controllers and components:: - - public function testSomething() - { - $this->controller->response = $this->getMock('Cake\Network\Response'); - $this->controller->response->expects($this->once())->method('header'); - // ... - } - -Additionally, you can run tests from the command line more easily, as you can use -mocks to avoid the 'headers sent' errors that can occur when trying to set -headers in CLI. - .. meta:: :title lang=en: Request and Response objects :keywords lang=en: request controller,request parameters,array indexes,purpose index,response objects,domain information,request object,request data,interrogating,params,previous versions,introspection,dispatcher,rout,data structures,arrays,ip address,migration,indexes,cakephp diff --git a/en/core-libraries/app.rst b/en/core-libraries/app.rst index 5e481cbc8e9191dd941f5646790f7570948ecc43..71f244d56756e0e82e9f98fda70c2b61ea0befdd 100644 --- a/en/core-libraries/app.rst +++ b/en/core-libraries/app.rst @@ -62,12 +62,12 @@ Used for finding the path to a package inside CakePHP:: Locating Plugins ================ -.. php:staticmethod:: pluginPath(string $plugin) +.. php:staticmethod:: Plugin::path(string $plugin) -Plugins can be located with App as well. Using ``App::pluginPath('DebugKit');`` +Plugins can be located with Plugin. Using ``Plugin::path('DebugKit');`` for example, will give you the full path to the DebugKit plugin:: - $path = App::pluginPath('DebugKit'); + $path = Plugin::path('DebugKit'); Locating Themes =============== diff --git a/en/core-libraries/caching.rst b/en/core-libraries/caching.rst index 34719fdef9a27a3ddf4ce2224bcb9dc9edf2fd26..a2b533091f448f2f186838bf5cd740f64bc42472 100644 --- a/en/core-libraries/caching.rst +++ b/en/core-libraries/caching.rst @@ -49,7 +49,7 @@ Configuring Cache Class .. php:staticmethod:: config($key, $config = null) Configuring the Cache class can be done anywhere, but generally you will want to -configure Cache during bootstrapping. The ``config/app.php`` file is the +configure Cache during bootstrapping. The **config/app.php** file is the conventional location to do this. You can configure as many cache configurations as you need, and use any mixture of cache engines. CakePHP uses two cache configurations internally. ``_cake_core_`` is used for storing file @@ -61,7 +61,7 @@ for the core caches. This will prevent multiple applications from overwriting each other's cached data. Using multiple configurations also lets you incrementally change the storage as -needed. For example in your ``config/app.php`` you could put the following:: +needed. For example in your **config/app.php** you could put the following:: // ... 'Cache' => [ @@ -290,8 +290,8 @@ Clearing Cached Data .. php:staticmethod:: clear($check, $config = 'default') -Destroy all cached values for a cache configuration. In engines like Apc, -Memcached and Wincache, the cache configuration's prefix is used to remove +Destroy all cached values for a cache configuration. In engines like: Apc, +Memcached, and Wincache, the cache configuration's prefix is used to remove cache entries. Make sure that different cache configurations have different prefixes:: @@ -346,7 +346,7 @@ You can greatly improve the performance of your application by putting results that infrequently change, or that are subject to heavy reads into the cache. A perfect example of this are the results from :php:meth:`Cake\\ORM\\Table::find()`. The Query object allows you to cache -results using the ``cache`` method. See the :ref:`caching-query-results` section +results using the ``cache()`` method. See the :ref:`caching-query-results` section for more information. Using Groups @@ -440,7 +440,7 @@ You can provide custom ``Cache`` adapters in ``App\Cache\Engine`` as well as in plugins using ``$plugin\Cache\Engine``. src/plugin cache engines can also override the core engines. Cache adapters must be in a cache directory. If you had a cache engine named ``MyCustomCacheEngine`` -it would be placed in either ``src/Cache/Engine/MyCustomCacheEngine.php`` +it would be placed in either **src/Cache/Engine/MyCustomCacheEngine.php** as an app/libs. Or in ``$plugin/Cache/Engine/MyCustomCacheEngine.php`` as part of a plugin. Cache configs from plugins need to use the plugin dot syntax. :: diff --git a/en/core-libraries/collections.rst b/en/core-libraries/collections.rst index d7e2f5b766b0acb44b2e14e648ddb8ead4837480..7db4d7e574ea16a2c70384f799cfe5ad05127bc4 100644 --- a/en/core-libraries/collections.rst +++ b/en/core-libraries/collections.rst @@ -11,7 +11,7 @@ The collection classes provide a set of tools to manipulate arrays or ``Traversable`` objects. If you have ever used underscore.js, you have an idea of what you can expect from the collection classes. -Collection instances are immutable, modifying a collection will instead generate +Collection instances are immutable; modifying a collection will instead generate a new collection. This makes working with collection objects more predictable as operations are side-effect free. @@ -40,34 +40,40 @@ application as well. List of Methods =============== +* :php:meth:`append` +* :php:meth:`buffered` +* :php:meth:`combine` +* :php:meth:`compile` +* :php:meth:`contains` +* :php:meth:`countBy` * :php:meth:`each` -* :php:meth:`map` +* :php:meth:`every` * :php:meth:`extract` -* :php:meth:`combine` -* :php:meth:`stopWhen` -* :php:meth:`unfold` * :php:meth:`filter` -* :php:meth:`reject` -* :php:meth:`every` -* :php:meth:`some` -* :php:meth:`match` -* :php:meth:`reduce` -* :php:meth:`min` -* :php:meth:`max` +* :php:meth:`first` * :php:meth:`groupBy` -* :php:meth:`countBy` * :php:meth:`indexBy` -* :php:meth:`sortBy` -* :php:meth:`nest` +* :php:meth:`insert` +* :php:meth:`isEmpty` +* :php:meth:`last` * :php:meth:`listNested` -* :php:meth:`contains` -* :php:meth:`shuffle` +* :php:meth:`map` +* :php:meth:`match` +* :php:meth:`max` +* :php:meth:`min` +* :php:meth:`nest` +* :php:meth:`reduce` +* :php:meth:`reject` * :php:meth:`sample` +* :php:meth:`shuffle` +* :php:meth:`skip` +* :php:meth:`some` +* :php:meth:`sortBy` +* :php:meth:`stopWhen` * :php:meth:`take` -* :php:meth:`append` -* :php:meth:`insert` -* :php:meth:`buffered` -* :php:meth:`compile` +* :php:meth:`through` +* :php:meth:`unfold` +* :php:meth:`zip` Iterating ========= @@ -99,7 +105,7 @@ callback being applied to each object in the original collection:: return $value * 2; }); - // $result contains [2, 4, 6]; + // $result contains ['a' => 2, 'b' => 4, 'c' => 6]; $result = $new->toArray(); The ``map()`` method will create a new iterator which lazily creates @@ -136,6 +142,32 @@ you can use a callback function to return it:: return $article->author->name . ', ' . $article->author->last_name; }); +Often, the properties you need to extract a common key present in multiple +arrays or objects that are deeply nested inside other structures. For those +cases you can use the ``{*}`` matcher in the path key:: + + $data = [ + [ + 'name' => 'James', + 'phone_numbers' => [ + ['number' => 'number-1'], + ['number' => 'number-2'], + ['number' => 'number-3'], + ] + ], + [ + 'name' => 'James', + 'phone_numbers' => [ + ['number' => 'number-4'], + ['number' => 'number-5'], + ] + ] + ]; + + $numbers = (new Collection($data))->extract('phone_numbers.{*}.number'); + $numbers->toList(); + // Returns ['number-1', 'number-2', 'number-3', 'number-4', 'number-5'] + .. php:method:: combine($keyPath, $valuePath, $groupPath = null) Collections allow you to create a new collection made from keys and values in @@ -166,6 +198,22 @@ You can also optionally use a ``groupPath`` to group results based on a path:: 'b' => [2 => 'bar'] ]; +Finally you can use *closures* to build keys/values/groups paths dynamically, +for example when working with entities and dates (converted to ``Cake/Time`` +instances by the ORM) you may want to group results by date:: + + $combined = (new Collection($entities))->combine( + 'id', + function ($entity) { return $entity; }, + function ($entity) { return $entity->date->toDateString(); } + ); + + // Result will look like this when converted to array + [ + 'date string like 2015-05-01' => ['entity1->id' => entity1, 'entity2->id' => entity2, ..., 'entityN->id' => entityN] + 'date string like 2015-06-01' => ['entity1->id' => entity1, 'entity2->id' => entity2, ..., 'entityN->id' => entityN] + ] + .. php:method:: stopWhen(callable $c) You can stop the iteration at any point using the ``stopWhen()`` method. Calling @@ -188,14 +236,14 @@ passed callable returns false for one of the elements:: Sometimes the internal items of a collection will contain arrays or iterators with more items. If you wish to flatten the internal structure to iterate once over all elements you can use the ``unfold()`` method. It will create a new -collection that will yield the every single element nested in the collection:: +collection that will yield every single element nested in the collection:: $items = [[1, 2, 3], [4, 5]]; $collection = new Collection($items); - $allElements = $collection->unfold(); + $new = $collection->unfold(); // $result contains [1, 2, 3, 4, 5]; - $result = $new->toArray(false); + $result = $new->toList(); When passing a callable to ``unfold()`` you can control what elements will be unfolded from each item in the original collection. This is useful for returning @@ -208,7 +256,20 @@ data from paginated services:: return MyService::fetchPage($page)->toArray(); }); - $allPagesItems = $items->toArray(false); + $allPagesItems = $items->toList(); + +If you are using PHP 5.5+, you can use the ``yield`` keyword inside ``unfold()`` +to return as many elements for each item in the collection as you may need:: + + $oddNumbers = [1, 3, 5, 7]; + $collection = new Collection($oddNumbers); + $new = $collection->unfold(function ($oddNumber) { + yield $oddNumber; + yield $oddNumber + 1; + }); + + // $result contains [1, 2, 3, 4, 5, 6, 7, 8]; + $result = $new->toList(); Filtering ========= @@ -297,7 +358,7 @@ collection:: In the above example, ``$totalPrice`` will be the sum of all single prices contained in the collection. Note the second argument for the ``reduce()`` -function, it takes the initial value for the reduce operation you are +function takes the initial value for the reduce operation you are performing:: $allTags = $collection->reduce(function ($accumulated, $article) { @@ -313,13 +374,13 @@ not just the smallest value found:: $collection = new Collection($people); $youngest = $collection->min('age'); - echo $yougest->name; + echo $youngest->name; You are also able to express the property to compare by providing a path or a callback function:: $collection = new Collection($people); - $personYougestChild = $collection->min(function ($person) { + $personYoungestChild = $collection->min(function ($person) { return $person->child->age; }); @@ -341,7 +402,7 @@ element from the collection having the highest property value:: .. php:method:: sumOf(string|callable $callback) -Finally, the ``sumOf`` method will return the sum of a property of all +Finally, the ``sumOf()`` method will return the sum of a property of all elements:: $collection = new Collection($people); @@ -428,6 +489,53 @@ a callback:: return md5($file); }); +.. php:method:: zip($elements) + +The elements of different collections can be grouped together using the +``zip()`` method. It will return a new collection containing an array grouping +the elements from each collection that are placed at the same position:: + + $odds = new Collection([1, 3, 5]); + $pairs = new Collection([2, 4, 6]); + $combined = $odds->zip($pairs)->toList(); // [[1, 2], [3, 4], [5, 6]] + +You can also zip multiple collections at once:: + + $years = new Collection([2013, 2014, 2015, 2016]); + $salaries = [1000, 1500, 2000, 2300]; + $increments = [0, 500, 500, 300]; + + $rows = $years->zip($salaries, $increments)->toList(); + // Returns: + [ + [2013, 1000, 0], + [2014, 1500, 500], + [2015, 2000, 500], + [2016, 2300, 300] + ] + +As you can already see, the ``zip()`` method is very useful for transposing +multidimensional arrays:: + + $data = [ + 2014 => ['jan' => 100, 'feb' => 200], + 2015 => ['jan' => 300, 'feb' => 500], + 2016 => ['jan' => 400, 'feb' => 600], + ] + + // Getting jan and feb data together + + $firstYear = new Collection(array_shift($data)); + $firstYear->zip($data[0], $data[1])->toList(); + + // Or $firstYear->zip(...$data) in PHP >= 5.6 + + // Returns + [ + [100, 300, 400], + [200, 500, 600] + ] + Sorting ======= @@ -539,7 +647,7 @@ rendering menus or traversing elements up to certain level in the tree. .. php:method:: listNested($dir = 'desc', $nestingKey = 'children') The inverse of ``nest()`` is ``listNested()``. This method allows you to flatten -a tree structure back into a linear structure. It takes two parameters, the +a tree structure back into a linear structure. It takes two parameters; the first one is the traversing mode (asc, desc or leaves), and the second one is the name of the property containing the children for each element in the collection. @@ -571,9 +679,45 @@ instruct it to only return the leaf elements in the tree:: ['id' => 5, 'parent_id' => 6, 'name' => 'Clown Fish'] ] +Once you have converted a tree into a nested list, you can use the ``printer()`` +method to configure how the list output should be formatted:: + + $nested->listNested()->printer('name', 'id', '--')->toArray(); + + // Returns + [ + 3 => 'Eagle', + 4 => 'Seagull', + 5 -> '--Clown Fish', + ] + +The ``printer()`` method also lets you use a callback to generate the keys and +or values:: + + $nested->listNested()->printer( + function ($el) { + return $el->name; + }, + function ($el) { + return $el->id; + } + ); + Other Methods ============= +.. php:method:: isEmpty() + +Allows you to see if a collection contains any elements:: + + $collection = new Collection([]); + // Returns true + $collection->isEmpty(); + + $collection = new Collection([1]); + // Returns false + $collection->isEmpty(); + .. php:method:: contains($value) Collections allow you to quickly check if they contain one particular @@ -594,7 +738,7 @@ position, use the ``shuffle``:: $collection = new Collection(['a' => 1, 'b' => 2, 'c' => 3]); - // This could return ['b' => 2, 'c' => 3, 'a' => 1] + // This could return [2, 3, 1] $collection->shuffle()->toArray(); Withdrawing Elements @@ -630,6 +774,32 @@ the first argument, starting from the position passed in the second argument:: Positions are zero-based, therefore the first position number is ``0``. +.. php:method:: skip(int $positions) + +While the second argument of ``take()`` can help you skip some elements before +getting them from the collection, you can also use ``skip()`` for the same +purpose as a way to take the rest of the elements after a certain position:: + + $collection = new Collection([1, 2, 3, 4]); + $allExceptFirstTwo = $collection->skip(2)->toList(); // [3, 4] + +.. php:method:: first() + +One of the most common uses of ``take()`` is getting the first element in the +collection. A shortcut method for achieving the same goal is using the +``first()`` method:: + + $collection = new Collection([5, 4, 3, 2]); + $collection->first(); // Returns 5 + +.. php:method:: last() + +Similarly, you can get the last element of a collection using the ``last()`` +method:: + + $collection = new Collection([5, 4, 3, 2]); + $collection->last(); // Returns 2 + Expanding Collections --------------------- @@ -655,7 +825,7 @@ collection containing the values from both sources:: This can present a problem when converting a collection to an array using ``toArray()``. If you do not want values from one collection to override others in the previous one based on their key, make sure that you call - ``toArray(false)`` in order to drop the keys and preserve all values. + ``toList()`` in order to drop the keys and preserve all values. Modifiying Elements ------------------- @@ -721,6 +891,94 @@ first one, then the target property will be filled with ``null`` values:: The ``insert()`` method can operate array elements or objects implementing the ``ArrayAccess`` interface. +Making Collection Methods Reusable +---------------------------------- + +Using closures for collection methods is great when the work to be done is small +and focused, but it can get messy very quickly. This becomes more obvious when +a lot of different methods need to be called or when the length of the closure +methods is more than just a few lines. + +There are also cases when the logic used for the collection methods can be +reused in multiple parts of your application. It is recommended that you +consider extracting complex collection logic to separate classes. For example, +imagine a lengthy closure like this one:: + + $collection + ->map(function ($row, $key) { + if (!empty($row['items'])) { + $row['total'] = collection($row['items'])->sumOf('price'); + } + + if (!empty($row['total'])) { + $row['tax_amount'] = $row['total'] * 0.25; + } + + // More code here... + + return $modifiedRow; + }); + +This can be refactored by creating another class:: + + class TotalOrderCalculator + { + + public function __invoke($row, $key) + { + if (!empty($row['items'])) { + $row['total'] = collection($row['items'])->sumOf('price'); + } + + if (!empty($row['total'])) { + $row['tax_amount'] = $row['total'] * 0.25; + } + + // More code here... + + return $modifiedRow; + } + } + + // Use the logic in your map() call + $collection->map(new TotalOrderCalculator) + + +.. php:method:: through(callable $c) + +Sometimes a chain of collection method calls can become reusable in other parts +of your application, but only if they are called in that specific order. In +those cases you can use ``through()`` in combination with a class implementing +``__invoke`` to distribute your handy data processing calls:: + + $collection + ->map(new ShippingCostCalculator) + ->map(new TotalOrderCalculator) + ->map(new GiftCardPriceReducer) + ->buffered() + ... + +The above method calls can be extracted into a new class so they don't need to +be repeated every time:: + + class FinalCheckOutRowProcessor + { + + public function __invoke($collection) + { + return $collection + ->map(new ShippingCostCalculator) + ->map(new TotalOrderCalculator) + ->map(new GiftCardPriceReducer) + ->buffered() + ... + } + } + + + // Now you can use the through() method to call all methods at once + $collection->through(new FinalCheckOutRowProcessor); + Optimizing Collections ---------------------- @@ -816,4 +1074,4 @@ places at the same time. In order to clone a collection out of another use the .. meta:: :title lang=en: Collections - :keywords lang=en: collections, cakephp, append, sort, compile, contains, countBy, each, every, extract, filter, first, firstMatch, groupBy, indexBy, jsonSerialize, map, match, max, min, reduce, reject, sample, shuffle, some, random, sortBy, take, toArray, insert, sumOf, stopWhen, unfold + :keywords lang=en: collections, cakephp, append, sort, compile, contains, countBy, each, every, extract, filter, first, firstMatch, groupBy, indexBy, jsonSerialize, map, match, max, min, reduce, reject, sample, shuffle, some, random, sortBy, take, toArray, insert, sumOf, stopWhen, unfold, through diff --git a/en/core-libraries/email.rst b/en/core-libraries/email.rst index 7e88c601bff9c1518df7a18fa855c17412f8cd6e..6375e3314fa3cb1bdba36d0d41533b04111cfb07 100644 --- a/en/core-libraries/email.rst +++ b/en/core-libraries/email.rst @@ -1,7 +1,12 @@ Email ##### -.. php:namespace:: Cake\Network\Email +.. php:namespace:: Cake\Mailer + +.. warning:: + Before version 3.1, the ``Email`` and ``Transport`` classes were under + the ``Cake\Network\Email`` namespace instead of the ``Cake\Mailer`` + namespace. .. php:class:: Email(mixed $profile = null) @@ -13,7 +18,7 @@ Basic Usage First of all, you should ensure the class is loaded:: - use Cake\Network\Email\Email; + use Cake\Mailer\Email; After you've loaded ``Email``, you can send an email with the following:: @@ -48,9 +53,9 @@ Configuration Configuration for ``Email`` defaults is created using ``config()`` and ``configTransport()``. You should put your email presets in the -``config/app.php`` file. The ``config/app.php.default`` file is an +**config/app.php** file. The ``config/app.php.default`` file is an example of this file. It is not required to define email configuration in -``config/app.php``. ``Email`` can be used without it and use the respective +**config/app.php**. ``Email`` can be used without it and use the respective methods to set all configurations separately or load an array of configs. By defining profiles and transports, you can keep your application code free of @@ -86,7 +91,7 @@ is useful for debugging. Configuring transports allows you to keep configuration data out of your application code and makes deployment simpler as you can simply change the configuration data. An example transport configuration looks like:: - use Cake\Network\Email\Email; + use Cake\Mailer\Email; // Sample Mail configuration Email::configTransport('default', [ @@ -106,11 +111,11 @@ You can configure SSL SMTP servers, like Gmail. To do so, put the ``ssl://`` prefix in the host and configure the port value accordingly. You can also enable TLS SMTP using the ``tls`` option:: - use Cake\Network\Email\Email; + use Cake\Mailer\Email; Email::configTransport('gmail', [ 'host' => 'smtp.gmail.com', - 'port' => 465, + 'port' => 587, 'username' => 'my@gmail.com', 'password' => 'secret', 'className' => 'Smtp', @@ -175,7 +180,7 @@ following configuration keys are used: - ``'attachments'``: List of files to attach. See ``Email::attachments()``. - ``'emailFormat'``: Format of email (html, text or both). See ``Email::emailFormat()``. - ``'transport'``: Transport configuration name. See - :php:meth:`~Cake\\Network\\Email\\Email::configTransport()`. + :php:meth:`~Cake\\Mailer\\Email::configTransport()`. - ``'log'``: Log level to log the email headers and message. ``true`` will use LOG_DEBUG. See also ``CakeLog::write()`` - ``'helpers'``: Array of helpers used in the email template. @@ -215,8 +220,8 @@ and elements just like normal views:: ->from('app@domain.com') ->send(); -The above would use ``src/Template/Email/html/welcome.ctp`` for the view -and ``src/Template/Layout/Email/html/fancy.ctp`` for the layout. You can +The above would use **src/Template/Email/html/welcome.ctp** for the view +and **src/Template/Layout/Email/html/fancy.ctp** for the layout. You can send multipart templated email messages as well:: $email = new Email(); @@ -228,10 +233,10 @@ send multipart templated email messages as well:: This would use the following template files: -* ``src/Template/Email/text/welcome.ctp`` -* ``src/Template/Layout/Email/text/fancy.ctp`` -* ``src/Template/Email/html/welcome.ctp`` -* ``src/Template/Layout/Email/html/fancy.ctp`` +* **src/Template/Email/text/welcome.ctp** +* **src/Template/Layout/Email/text/fancy.ctp** +* **src/Template/Email/html/welcome.ctp** +* **src/Template/Layout/Email/html/fancy.ctp** When sending templated emails you have the option of sending either ``text``, ``html`` or ``both``. @@ -249,7 +254,7 @@ You can use helpers in emails as well, much like you can in normal template file By default only the ``HtmlHelper`` is loaded. You can load additional helpers using the ``helpers()`` method:: - $Email->helpers(['Html', 'Custom', 'Text']); + $email->helpers(['Html', 'Custom', 'Text']); When setting helpers be sure to include 'Html' or it will be removed from the helpers loaded in your email template. @@ -273,7 +278,7 @@ You can do this using themes by telling Email to use appropriate theme using This allows you to override the ``new_comment`` template in your theme without modifying the Blog plugin. The template file needs to be created in the following path: -``src/Template/Plugin/TestTheme/Blog/Email/text/new_comment.ctp``. +**src/Template/Plugin/TestTheme/Blog/Email/text/new_comment.ctp**. Sending Attachments =================== @@ -284,17 +289,17 @@ You can attach files to email messages as well. There are a few different formats depending on what kind of files you have, and how you want the filenames to appear in the recipient's mail client: -1. String: ``$Email->attachments('/full/file/path/file.png')`` will attach this +1. String: ``$email->attachments('/full/file/path/file.png')`` will attach this file with the name file.png. -2. Array: ``$Email->attachments(['/full/file/path/file.png'])`` will have +2. Array: ``$email->attachments(['/full/file/path/file.png'])`` will have the same behavior as using a string. 3. Array with key: - ``$Email->attachments(['photo.png' => '/full/some_hash.png'])`` will + ``$email->attachments(['photo.png' => '/full/some_hash.png'])`` will attach some_hash.png with the name photo.png. The recipient will see photo.png, not some_hash.png. 4. Nested arrays:: - $Email->attachments([ + $email->attachments([ 'photo.png' => [ 'file' => '/full/some_hash.png', 'mimetype' => 'image/png', @@ -323,7 +328,7 @@ Using Transports Transports are classes designed to send the e-mail over some protocol or method. CakePHP supports the Mail (default), Debug and SMTP transports. -To configure your method, you must use the :php:meth:`Cake\\Network\Email\\Email::transport()` +To configure your method, you must use the :php:meth:`Cake\\Mailer\\Email::transport()` method or have the transport in your configuration:: $email = new Email(); @@ -340,19 +345,20 @@ Creating Custom Transports You are able to create your custom transports to integrate with others email systems (like SwiftMailer). To create your transport, first create the file -``src/Network/Email/ExampleTransport.php`` (where Example is the name of your +**src/Network/Email/ExampleTransport.php** (where Example is the name of your transport). To start off your file should look like:: - use Cake\Network\Email\AbstractTransport; + namespace App\Network\Email; + + use Cake\Mailer\AbstractTransport; + use Cake\Mailer\Email; class ExampleTransport extends AbstractTransport { - public function send(Email $email) { // Magic inside! } - } You must implement the method ``send(Email $email)`` with your custom logic. @@ -361,12 +367,12 @@ called before send() and allows you to accept user configurations. By default, this method puts the configuration in protected attribute ``$_config``. If you need to call additional methods on the transport before send, you can use -:php:meth:`Cake\\Network\\Email\\Email::transportClass()` to get an instance of the transport. +:php:meth:`Cake\\Mailer\\Email::transportClass()` to get an instance of the transport. Example:: - $yourInstance = $Email->transport('your')->transportClass(); + $yourInstance = $email->transport('your')->transportClass(); $yourInstance->myCustomMethod(); - $Email->send(); + $email->send(); Relaxing Address Validation Rules --------------------------------- @@ -389,10 +395,10 @@ Sending Messages Quickly Sometimes you need a quick way to fire off an email, and you don't necessarily want do setup a bunch of configuration ahead of time. -:php:meth:`Cake\\Network\Email\\Email::deliver()` is intended for that purpose. +:php:meth:`Cake\\Mailer\\Email::deliver()` is intended for that purpose. You can create your configuration using -:php:meth:`Cake\\Network\\Email\\Email::config()`, or use an array with all +:php:meth:`Cake\\Mailer\\Email::config()`, or use an array with all options that you need and use the static method ``Email::deliver()``. Example:: @@ -401,7 +407,7 @@ Example:: This method will send an email to "you@example.com", from "me@example.com" with subject "Subject" and content "Message". -The return of ``deliver()`` is a :php:class:`Cake\\Email\\Email` instance with all +The return of ``deliver()`` is a :php:class:`Cake\\Mailer\\Email` instance with all configurations set. If you do not want to send the email right away, and wish to configure a few things before sending, you can pass the 5th parameter as ``false``. @@ -424,12 +430,100 @@ When sending emails within a CLI script (Shells, Tasks, ...) you should manually set the domain name for CakeEmail to use. It will serve as the host name for the message id (since there is no host name in a CLI environment):: - $Email->domain('www.example.org'); + $email->domain('www.example.org'); // Results in message ids like ```` (valid) // Instead of ``` (invalid) A valid message id can help to prevent emails ending up in spam folders. + +Creating Reusable Emails +======================== + +.. versionadded:: 3.1.0 + +Mailers allow you to create reusable emails throughout your application. They +can also be used to contain multiple email configurations in one location. This +helps keep your code DRYer and keeps email configuration noise out of other +areas in your application. + +In this example we will be creating a ``Mailer`` that contains user-related +emails. To create our ``UserMailer``, create the file +**src/Mailer/UserMailer.php**. The contents of the file should look like the +following:: + + namespace App\Mailer; + + use Cake\Mailer\Mailer; + + class UserMailer extends Mailer + { + public function welcome($user) + { + $this->_email->profile('default'); + $this->_email->to($user->email); + $this->_email->subject(sprintf('Welcome %s', $user->name)); + } + + public function resetPassword($user) + { + $this->_email->profile('default'); + $this->_email->to($user->email); + $this->_email->subject('Reset password'); + $this->set(['token' => $user->token]); + } + } + +In our example we have created two methods, one for sending a welcome email, and +another for sending a password reset email. Each of these methods expect a user +``Entity`` and utilizes its properties for configuring each email. + +We are now able to use our ``UserMailer`` to send out our user-related emails +from anywhere in our application. For example, if we wanted to send our welcome +email we could do the following:: + + namespace App\Controller; + + use Cake\Mailer\MailerAwareTrait; + + class UsersController extends AppController + { + use MailerAwareTrait; + + public function register() + { + $user = $this->Users->newEntity(); + if ($this->request->is('post')) { + $user = $this->Users->patchEntitiy($user, $this->request->data()) + if ($this->Users->save($user)) { + $this->getMailer('User')->send('welcome', [$user]); + } + } + $this->set('user', $user); + } + } + +If we wanted to completely separate sending a user their welcome email from our +application's code, we can have our ``UserMailer`` subscribe to the +``Model.afterSave`` event. By subscribing to an event, we can keep our +application's user-related classes completely free of email-related logic and +instructions. For example, we could add the following to our ``UserMailer``:: + + public function implementedEvents() + { + return [ + 'Model.afterSave' => 'onRegistration', + ; + } + + public function onRegistration(Event $event, Entity $entity, ArrayObject $options) + { + if ($entity->isNew()) { + $this->send('welcome', [$entity]); + } + } + + .. meta:: :title lang=en: Email :keywords lang=en: sending mail,email sender,envelope sender,php class,database configuration,sending emails,meth,shells,smtp,transports,attributes,array,config,flexibility,php email,new email,sending email,models diff --git a/en/core-libraries/events.rst b/en/core-libraries/events.rst index a5d46f3ae4d44fd884e794e8f5532b2ff9002a25..04114f5f0399bf0e5c4ead50bf9c3f10f9ce44fc 100644 --- a/en/core-libraries/events.rst +++ b/en/core-libraries/events.rst @@ -121,41 +121,6 @@ along. The listeners will handle all the extra logic around the possibly in separate objects and even delegating it to offline tasks if you have the need. -Dispatching Events -================== - -Once you have obtained an instance of an event manager you can dispatch events -using :php:meth:`~Cake\\Event\\EventManager::dispatch()`. This method takes an instance -of the :php:class:`Cake\\Event\\Event` class. Let's look at dispatching an event:: - - // Create a new event and dispatch it. - $event = new Event('Model.Order.afterPlace', $this, [ - 'order' => $order - ]); - $this->eventManager()->dispatch($event); - -:php:class:`Cake\\Event\\Event` accepts 3 arguments in its constructor. The first one is -the event name, you should try to keep this name as unique as possible, while -making it readable. We suggest a convention as follows: ``Layer.eventName`` for -general events happening at a layer level (e.g. ``Controller.startup``, -``View.beforeRender``) and ``Layer.Class.eventName`` for events happening in -specific classes on a layer, for example ``Model.User.afterRegister`` or -``Controller.Courses.invalidAccess``. - -The second argument is the ``subject``, meaning the object associated to the event, -usually when it is the same class triggering events about itself, using ``$this`` -will be the most common case. Although a Component could trigger -controller events too. The subject class is important because listeners will get -immediate access to the object properties and have the chance to inspect or -change them on the fly. - -Finally, the third argument is any additional event data.This can be any data you consider -useful to pass around so listeners can act upon it. While this can be an argument -of any type, we recommend passing an associative array. - -The :php:meth:`~Cake\\Event\\EventManager::dispatch()` method accepts an event -object as an argument and notifies all subscribed listeners. - Registering Listeners ===================== @@ -193,9 +158,9 @@ necessary. Our ``UserStatistics`` listener might start out like:: $statistics = new UserStatistic(); $this->Orders->eventManager()->on($statistics); -As you can see in the above code, the ``on`` function will accept instances +As you can see in the above code, the ``on()`` function will accept instances of the ``EventListener`` interface. Internally, the event manager will use -``implementedEvents`` to attach the correct callbacks. +``implementedEvents()`` to attach the correct callbacks. Registering Anonymous Listeners ------------------------------- @@ -245,8 +210,8 @@ below this default will work. On the other hand if you desire to run the callback after the others, using a number above ``10`` will do. If two callbacks happen to have the same priority value, they will be executed -with a the order they were attached. You set priorities using the ``attach`` -method for callbacks, and declaring it in the ``implementedEvents`` function for +with a the order they were attached. You set priorities using the ``attach()`` +method for callbacks, and declaring it in the ``implementedEvents()`` function for event listeners:: // Setting priority for a callback @@ -301,6 +266,41 @@ order. Unlike in 2.x, converting event data to listener arguments is the default behavior and cannot be disabled. +Dispatching Events +================== + +Once you have obtained an instance of an event manager you can dispatch events +using :php:meth:`~Cake\\Event\\EventManager::dispatch()`. This method takes an instance +of the :php:class:`Cake\\Event\\Event` class. Let's look at dispatching an event:: + + // An event listener has to be instantiated before dispatching an event. + // Create a new event and dispatch it. + $event = new Event('Model.Order.afterPlace', $this, [ + 'order' => $order + ]); + $this->eventManager()->dispatch($event); + +:php:class:`Cake\\Event\\Event` accepts 3 arguments in its constructor. The first one is +the event name, you should try to keep this name as unique as possible, while +making it readable. We suggest a convention as follows: ``Layer.eventName`` for +general events happening at a layer level (e.g. ``Controller.startup``, +``View.beforeRender``) and ``Layer.Class.eventName`` for events happening in +specific classes on a layer, for example ``Model.User.afterRegister`` or +``Controller.Courses.invalidAccess``. + +The second argument is the ``subject``, meaning the object associated to the event, +usually when it is the same class triggering events about itself, using ``$this`` +will be the most common case. Although a Component could trigger +controller events too. The subject class is important because listeners will get +immediate access to the object properties and have the chance to inspect or +change them on the fly. + +Finally, the third argument is any additional event data.This can be any data you consider +useful to pass around so listeners can act upon it. While this can be an argument +of any type, we recommend passing an associative array. + +The :php:meth:`~Cake\\Event\\EventManager::dispatch()` method accepts an event +object as an argument and notifies all subscribed listeners. Stopping Events --------------- @@ -311,7 +311,7 @@ listeners from being notified. You can see this in action during model callbacks the code detects it cannot proceed any further. In order to stop events you can either return ``false`` in your callbacks or call -the ``stopPropagation`` method on the event object:: +the ``stopPropagation()`` method on the event object:: public function doSomething($event) { diff --git a/en/core-libraries/file-folder.rst b/en/core-libraries/file-folder.rst index 77c5085efa89afdd106e1bddce3f2f12bf46aad5..778f71e8ecd152c20b9c07ee242a7ccb96b8edf1 100644 --- a/en/core-libraries/file-folder.rst +++ b/en/core-libraries/file-folder.rst @@ -57,7 +57,7 @@ Folder API .. php:attr:: mode Mode to be used when creating folders. Defaults to ``0755``. Does nothing on - windows machines. + Windows machines. .. php:staticmethod:: addPathElement(string $path, string $element) diff --git a/en/core-libraries/form.rst b/en/core-libraries/form.rst index f1fcd8ada351adae1a4a573bfff5f8df6554eeab..aa91b2912cadd9b02f3e26141b0bd52ed0d4f81d 100644 --- a/en/core-libraries/form.rst +++ b/en/core-libraries/form.rst @@ -15,7 +15,7 @@ Creating a Form Generally when using the Form class you'll want to use a subclass to define your form. This makes testing easier, and lets you re-use your form. Forms are put -into ``src/Form`` and usually have ``Form`` as a class suffix. For example, +into **src/Form** and usually have ``Form`` as a class suffix. For example, a simple contact form would look like:: // in src/Form/ContactForm.php @@ -57,7 +57,7 @@ In the above example we see the 3 hook methods that forms provide: * ``_buildSchema`` is used to define the schema data that is used by FormHelper to create an HTML form. You can define field type, length, and precision. -* ``_buildValidator`` Gets a :php:class:`Cake\Validation\Validator` instance +* ``_buildValidator`` Gets a :php:class:`Cake\\Validation\\Validator` instance that you can attach validators to. * ``_execute`` lets you define the behavior you want to happen when ``execute()`` is called and the data is valid. @@ -98,6 +98,45 @@ accordingly. We could have also used the ``validate()`` method to only validate the request data:: $isValid = $form->validate($this->request->data); + +Setting Form Values +=================== + +In order to set the values for the fields of a modelless form, one can define +the values using ``$this->request->data``, like in all other forms created by the FormHelper:: + + // In a controller + namespace App\Controller; + + use App\Controller\AppController; + use App\Form\ContactForm; + + class ContactController extends AppController + { + public function index() + { + $contact = new ContactForm(); + if ($this->request->is('post')) { + if ($contact->execute($this->request->data)) { + $this->Flash->success('We will get back to you soon.'); + } else { + $this->Flash->error('There was a problem submitting your form.'); + } + } + + if ($this->request->is('get')) { + //Values from the User Model e.g. + $this->request->data['name'] = 'John Doe'; + $this->request->data['email'] = 'john.doe@example.com'; + } + + $this->set('contact', $contact); + } + } + +Values should only be defined if the request method is GET, otherwise +you will overwrite your previous POST Data which might have been incorrect +and not been saved. Getting Form Errors =================== @@ -111,6 +150,34 @@ Once a form has been validated you can retreive the errors from it:: ] */ +Invalidating Individual Form Fields from Controller +=================================================== + +It is possible to invalidate individual fields from the controller without the +use of the Validator class. The most common use case for this is when the +validation is done on a remote server. In such case, you must manually +invalidate the fields accordingly to the feedback from the remote server:: + + // in src/Form/ContactForm.php + public function setErrors($errors) + { + $this->_errors = $errors; + } + +According to how the validator class would have returned the errors, ``$errors`` +must be in this format:: + + ["fieldName" => ["validatorName" => "The error message to display"]] + +Now you will be able to invalidate form fields by setting the fieldName, then +set the error messages:: + + // In a controller + $contact = new ContactForm(); + $contact->setErrors(["email" => ["_required" => "Your email is required"]]); + +Proceed to Creating HTML with FormHelper to see the results. + Creating HTML with FormHelper ============================= diff --git a/en/core-libraries/global-constants-and-functions.rst b/en/core-libraries/global-constants-and-functions.rst index c1b34a66ea851987acd1378a41c7a798a00ecba2..4fbcd5f80e0c2eda888d364c12b87b31bfb37ca1 100644 --- a/en/core-libraries/global-constants-and-functions.rst +++ b/en/core-libraries/global-constants-and-functions.rst @@ -36,19 +36,6 @@ such as debugging and translating content. :doc:`/core-libraries/internationalization-and-localization` section for more information. -.. php:function:: __c(string $msg, integer $category, mixed $args = null) - - Note that the category must be specified with an I18n class constant, instead of - only the constant name. The values are: - - - I18n::LC_ALL - LC_ALL - - I18n::LC_COLLATE - LC_COLLATE - - I18n::LC_CTYPE - LC_CTYPE - - I18n::LC_MONETARY - LC_MONETARY - - I18n::LC_NUMERIC - LC_NUMERIC - - I18n::LC_TIME - LC_TIME - - I18n::LC_MESSAGES - LC_MESSAGES - .. php:function:: __d(string $domain, string $msg, mixed $args = null) Allows you to override the current domain for a single message lookup. @@ -56,52 +43,52 @@ such as debugging and translating content. Useful when internationalizing a plugin: ``echo __d('PluginName', 'This is my plugin');`` -.. php:function:: __dc(string $domain, string $msg, integer $category, mixed $args = null) +.. php:function:: __dn(string $domain, string $singular, string $plural, integer $count, mixed $args = null) + + Allows you to override the current domain for a single plural message + lookup. Returns correct plural form of message identified by ``$singular`` + and ``$plural`` for count ``$count`` from domain ``$domain``. + +.. php:function:: __dx(string $domain, string $context, string $msg, mixed $args = null) Allows you to override the current domain for a single message lookup. It - also allows you to specify a category. - - Note that the category must be specified with an I18n class constant, instead of - only the constant name. The values are: + also allows you to specify a context. - - I18n::LC_ALL - LC_ALL - - I18n::LC_COLLATE - LC_COLLATE - - I18n::LC_CTYPE - LC_CTYPE - - I18n::LC_MONETARY - LC_MONETARY - - I18n::LC_NUMERIC - LC_NUMERIC - - I18n::LC_TIME - LC_TIME - - I18n::LC_MESSAGES - LC_MESSAGES + The context is a unique identifier for the translations string that makes it + unique within the same domain. -.. php:function:: __dcn(string $domain, string $singular, string $plural, integer $count, integer $category, mixed $args = null) +.. php:function:: __dxn(string $domain, string $context, string $singular, string $plural, integer $count, mixed $args = null) Allows you to override the current domain for a single plural message - lookup. It also allows you to specify a category. Returns correct plural - form of message identified by $singular and $plural for count $count from - domain $domain. + lookup. It also allows you to specify a context. Returns correct plural + form of message identified by ``$singular`` and ``$plural`` for count + ``$count`` from domain ``$domain``. Some languages have more than one form + for plural messages dependent on the count. - Note that the category must be specified with an I18n class constant, instead of - only the constant name. The values are: + The context is a unique identifier for the translations string that makes it + unique within the same domain. - - I18n::LC_ALL - LC_ALL - - I18n::LC_COLLATE - LC_COLLATE - - I18n::LC_CTYPE - LC_CTYPE - - I18n::LC_MONETARY - LC_MONETARY - - I18n::LC_NUMERIC - LC_NUMERIC - - I18n::LC_TIME - LC_TIME - - I18n::LC_MESSAGES - LC_MESSAGES +.. php:function:: __n(string $singular, string $plural, integer $count, mixed $args = null) -.. php:function:: __dn(string $domain, string $singular, string $plural, integer $count, mixed $args = null) + Returns correct plural form of message identified by ``$singular`` and ``$plural`` + for count ``$count``. Some languages have more than one form for plural + messages dependent on the count. - Allows you to override the current domain for a single plural message - lookup. Returns correct plural form of message identified by $singular and - $plural for count $count from domain $domain. +.. php:function:: __x(string $context, string $msg, mixed $args = null) -.. php:function:: __n(string $singular, string $plural, integer $count, mixed $args = null) + The context is a unique identifier for the translations string that makes it + unique within the same domain. + +.. php:function:: __xn(string $context, string $singular, string $plural, integer $count, mixed $args = null) - Returns correct plural form of message identified by $singular and $plural - for count $count. Some languages have more than one form for plural + Returns correct plural form of message identified by ``$singular`` and + ``$plural`` for count ``$count`` from domain ``$domain``. It also allows you + to specify a context. Some languages have more than one form for plural messages dependent on the count. + The context is a unique identifier for the translations string that makes it + unique within the same domain. + .. php:function:: collection(mixed $items) Convenience wrapper for instantiating a new :php:class:`Cake\Collection\Collection` @@ -110,7 +97,7 @@ such as debugging and translating content. .. php:function:: debug(mixed $var, boolean $showHtml = null, $showFrom = true) - If the core ``$debug`` variable is ``true``, $var is printed out. + If the core ``$debug`` variable is ``true``, ``$var`` is printed out. If ``$showHTML`` is ``true`` or left as ``null``, the data is rendered to be browser-friendly. If ``$showFrom`` is not set to ``false``, the debug output will start with the line from @@ -122,7 +109,7 @@ such as debugging and translating content. Gets an environment variable from available sources. Used as a backup if ``$_SERVER`` or ``$_ENV`` are disabled. - This function also emulates PHP\_SELF and DOCUMENT\_ROOT on + This function also emulates ``PHP_SELF`` and ``DOCUMENT_ROOT`` on unsupporting servers. In fact, it's a good idea to always use ``env()`` instead of ``$_SERVER`` or ``getenv()`` (especially if you plan to distribute the code), since it's a full emulation @@ -134,15 +121,28 @@ such as debugging and translating content. .. php:function:: pluginSplit(string $name, boolean $dotAppend = false, string $plugin = null) - Splits a dot syntax plugin name into its plugin and class name. If $name - does not have a dot, then index 0 will be null. + Splits a dot syntax plugin name into its plugin and class name. If ``$name`` + does not have a dot, then index 0 will be ``null``. Commonly used like ``list($plugin, $name) = pluginSplit('Users.User');`` + +.. php:function:: namespaceSplit(string $class) + Split the namespace from the classname. + + Commonly used like ``list($namespace, $className) = namespaceSplit('Cake\Core\App');`` + .. php:function:: pr(mixed $var) Convenience wrapper for ``print_r()``, with the addition of - wrapping
 tags around the output.
+    wrapping ``
`` tags around the output.
+    
+.. php:function:: pj(mixed $var)
+
+    JSON pretty print convenience function, with the addition of
+    wrapping ``
`` tags around the output.
+    
+    It is meant for debugging the JSON representation of objects and arrays.
 
 Core Definition Constants
 =========================
@@ -176,7 +176,8 @@ Most of the following constants refer to paths in your application.
 
 .. php:const:: DS
 
-    Short for PHP's DIRECTORY\_SEPARATOR, which is / on Linux and \\ on windows.
+    Short for PHP's ``DIRECTORY_SEPARATOR``, which is ``/`` on Linux and ``\\``
+    on Windows.
 
 .. php:const:: LOGS
 
diff --git a/en/core-libraries/hash.rst b/en/core-libraries/hash.rst
index 3b7a6eca5a615afd2beb8fb41ecb99b80ecb3c01..4d9885ba472e9bb565f80adb9e8ed09bf2c62ffb 100644
--- a/en/core-libraries/hash.rst
+++ b/en/core-libraries/hash.rst
@@ -86,14 +86,19 @@ Attribute Matching Types
     want returned ::
 
         // Common Usage:
-        $users = $this->User->find("all");
-        $results = Hash::extract($users, '{n}.User.id');
+        $users = [
+            ['id' => 1, 'name' => 'mark'],
+            ['id' => 2, 'name' => 'jane'],
+            ['id' => 3, 'name' => 'sally'],
+            ['id' => 4, 'name' => 'jose'],
+        ];
+        $results = Hash::extract($users, '{n}.id');
         // $results equals:
-        // [1,2,3,4,5,...];
+        // [1,2,3,4];
 
 .. php:staticmethod:: Hash::insert(array $data, $path, $values = null)
 
-    Inserts $data into an array as defined by ``$path``::
+    Inserts ``$data`` into an array as defined by ``$path``::
 
         $a = [
             'pages' => ['name' => 'page']
@@ -112,12 +117,31 @@ Attribute Matching Types
     You can use paths using ``{n}`` and ``{s}`` to insert data into multiple
     points::
 
-        $users = $this->User->find('all');
-        $users = Hash::insert($users, '{n}.User.new', 'value');
+        $users = Hash::insert($users, '{n}.new', 'value');
+
+    Attribute matchers work with ``insert()`` as well::
+
+        $data = [
+            0 => ['up' => true, 'Item' => ['id' => 1, 'title' => 'first']],
+            1 => ['Item' => ['id' => 2, 'title' => 'second']],
+            2 => ['Item' => ['id' => 3, 'title' => 'third']],
+            3 => ['up' => true, 'Item' => ['id' => 4, 'title' => 'fourth']],
+            4 => ['Item' => ['id' => 5, 'title' => 'fifth']],
+        ];
+        $result = Hash::insert($data, '{n}[up].Item[id=4].new', 9);
+        /* $result now looks like:
+            [
+                ['up' => true, 'Item' => ['id' => 1, 'title' => 'first']],
+                ['Item' => ['id' => 2, 'title' => 'second']],
+                ['Item' => ['id' => 3, 'title' => 'third']],
+                ['up' => true, 'Item' => ['id' => 4, 'title' => 'fourth', 'new' => 9]],
+                ['Item' => ['id' => 5, 'title' => 'fifth']],
+            ]
+        */
 
 .. php:staticmethod:: remove(array $data, $path = null)
 
-    Removes all elements from an array that match $path. ::
+    Removes all elements from an array that match ``$path``. ::
 
         $a = [
             'pages' => ['name' => 'page'],
@@ -134,15 +158,32 @@ Attribute Matching Types
         */
 
     Using ``{n}`` and ``{s}`` will allow you to remove multiple values at once.
+    You can also use attribute matchers with ``remove()``::
 
+        $data = [
+            0 => ['clear' => true, 'Item' => ['id' => 1, 'title' => 'first']],
+            1 => ['Item' => ['id' => 2, 'title' => 'second']],
+            2 => ['Item' => ['id' => 3, 'title' => 'third']],
+            3 => ['clear' => true, 'Item' => ['id' => 4, 'title' => 'fourth']],
+            4 => ['Item' => ['id' => 5, 'title' => 'fifth']],
+        ];
+        $result = Hash::remove($data, '{n}[clear].Item[id=4]');
+        /* $result now looks like:
+            [
+                ['clear' => true, 'Item' => ['id' => 1, 'title' => 'first']],
+                ['Item' => ['id' => 2, 'title' => 'second']],
+                ['Item' => ['id' => 3, 'title' => 'third']],
+                ['Item' => ['id' => 5, 'title' => 'fifth']],
+            ]
+        */
 
 .. php:staticmethod:: combine(array $data, $keyPath = null, $valuePath = null, $groupPath = null)
 
-    Creates an associative array using a $keyPath as the path to build its keys,
-    and optionally $valuePath as path to get the values. If $valuePath is not
+    Creates an associative array using a ``$keyPath`` as the path to build its keys,
+    and optionally ``$valuePath`` as path to get the values. If ``$valuePath`` is not
     specified, or doesn't match anything, values will be initialized to null.
     You can optionally group the values by what is obtained when following the
-    path specified in $groupPath. ::
+    path specified in ``$groupPath``. ::
 
         $a = [
             [
@@ -227,7 +268,7 @@ Attribute Matching Types
             ]
         */
 
-    You can provide array's for both $keyPath and $valuePath. If you do this,
+    You can provide array's for both ``$keyPath`` and ``$valuePath``. If you do this,
     the first value will be used as a format string, for values extracted by the
     other paths::
 
@@ -375,8 +416,8 @@ Attribute Matching Types
 .. php:staticmethod:: filter(array $data, $callback = ['Hash', 'filter'])
 
     Filters empty elements out of array, excluding '0'. You can also supply a
-    custom $callback to filter the array elements. You callback should return
-    ``false`` to remove elements from the resulting array::
+    custom ``$callback`` to filter the array elements. You callback should
+    return ``false`` to remove elements from the resulting array::
 
         $data = [
             '0',
@@ -552,16 +593,16 @@ Attribute Matching Types
     the deepest number of dimensions of any element in the array::
 
         $data = ['1' => '1.1', '2', '3' => ['3.1' => '3.1.1']];
-        $result = Hash::maxDimensions($data, true);
+        $result = Hash::maxDimensions($data);
         // $result == 2
 
         $data = ['1' => ['1.1' => '1.1.1'], '2', '3' => ['3.1' => ['3.1.1' => '3.1.1.1']]];
-        $result = Hash::maxDimensions($data, true);
+        $result = Hash::maxDimensions($data);
         // $result == 3
 
 .. php:staticmethod:: map(array $data, $path, $function)
 
-    Creates a new array, by extracting $path, and mapping $function
+    Creates a new array, by extracting ``$path``, and mapping ``$function``
     across the results. You can use both expression and matching elements with
     this method::
 
@@ -576,13 +617,13 @@ Attribute Matching Types
 
 .. php:staticmethod:: reduce(array $data, $path, $function)
 
-    Creates a single value, by extracting $path, and reducing the extracted
-    results with $function. You can use both expression and matching elements
+    Creates a single value, by extracting ``$path``, and reducing the extracted
+    results with ``$function``. You can use both expression and matching elements
     with this method.
 
 .. php:staticmethod:: apply(array $data, $path, $function)
 
-    Apply a callback to a set of extracted values using $function. The function
+    Apply a callback to a set of extracted values using ``$function``. The function
     will get the extracted values as the first argument.
 
 .. php:staticmethod:: sort(array $data, $path, $dir, $type = 'regular')
@@ -737,7 +778,6 @@ Attribute Matching Types
 .. php:staticmethod:: nest(array $data, array $options = [])
 
     Takes a flat array set, and creates a nested, or threaded data structure.
-    Used by methods like ``Table::find('threaded')``.
 
     **Options:**
 
@@ -749,53 +789,53 @@ Attribute Matching Types
       Should be compatible with :php:meth:`Hash::extract()`. Defaults to ``{n}.$alias.parent_id``
     - ``root`` The id of the desired top-most result.
 
-    Example::
+    For example, if you had the following array of data::
 
         $data = [
-            ['ModelName' => ['id' => 1, 'parent_id' => null]],
-            ['ModelName' => ['id' => 2, 'parent_id' => 1]],
-            ['ModelName' => ['id' => 3, 'parent_id' => 1]],
-            ['ModelName' => ['id' => 4, 'parent_id' => 1]],
-            ['ModelName' => ['id' => 5, 'parent_id' => 1]],
-            ['ModelName' => ['id' => 6, 'parent_id' => null]],
-            ['ModelName' => ['id' => 7, 'parent_id' => 6]],
-            ['ModelName' => ['id' => 8, 'parent_id' => 6]],
-            ['ModelName' => ['id' => 9, 'parent_id' => 6]],
-            ['ModelName' => ['id' => 10, 'parent_id' => 6]]
+            ['ThreadPost' => ['id' => 1, 'parent_id' => null]],
+            ['ThreadPost' => ['id' => 2, 'parent_id' => 1]],
+            ['ThreadPost' => ['id' => 3, 'parent_id' => 1]],
+            ['ThreadPost' => ['id' => 4, 'parent_id' => 1]],
+            ['ThreadPost' => ['id' => 5, 'parent_id' => 1]],
+            ['ThreadPost' => ['id' => 6, 'parent_id' => null]],
+            ['ThreadPost' => ['id' => 7, 'parent_id' => 6]],
+            ['ThreadPost' => ['id' => 8, 'parent_id' => 6]],
+            ['ThreadPost' => ['id' => 9, 'parent_id' => 6]],
+            ['ThreadPost' => ['id' => 10, 'parent_id' => 6]]
         ];
 
         $result = Hash::nest($data, ['root' => 6]);
         /* $result now looks like:
             [
                 (int) 0 => [
-                    'ModelName' => [
+                    'ThreadPost' => [
                         'id' => (int) 6,
                         'parent_id' => null
                     ],
                     'children' => [
                         (int) 0 => [
-                            'ModelName' => [
+                            'ThreadPost' => [
                                 'id' => (int) 7,
                                 'parent_id' => (int) 6
                             ],
                             'children' => []
                         ],
                         (int) 1 => [
-                            'ModelName' => [
+                            'ThreadPost' => [
                                 'id' => (int) 8,
                                 'parent_id' => (int) 6
                             ],
                             'children' => []
                         ],
                         (int) 2 => [
-                            'ModelName' => [
+                            'ThreadPost' => [
                                 'id' => (int) 9,
                                 'parent_id' => (int) 6
                             ],
                             'children' => []
                         ],
                         (int) 3 => [
-                            'ModelName' => [
+                            'ThreadPost' => [
                                 'id' => (int) 10,
                                 'parent_id' => (int) 6
                             ],
diff --git a/en/core-libraries/httpclient.rst b/en/core-libraries/httpclient.rst
index 86bf622ff9a2f4e71569fa523c7f6b5b7f4c8333..4cf0950ba361be64b4db2ccdd05c452bcc216459 100644
--- a/en/core-libraries/httpclient.rst
+++ b/en/core-libraries/httpclient.rst
@@ -52,17 +52,64 @@ Doing post and put requests is equally simple::
 Creating Multipart Requests with Files
 ======================================
 
-You can include files in request bodies by including them in the data array::
+You can include files in request bodies by including a filehandle in the array::
 
     $http = new Client();
     $response = $http->post('http://example.com/api', [
-      'image' => '@/path/to/a/file',
-      'logo' => $fileHandle
+      'image' => fopen('/path/to/a/file', 'r'),
     ]);
 
-By prefixing data values with ``@`` or including a filehandle in the data.  If
-a filehandle is used, the filehandle will be read until its end, it will not be
-rewound before being read.
+The filehandle will be read until its end; it will not be rewound before being read.
+
+.. warning::
+
+    For compatibility reasons, strings beginning with ``@`` will be evaluated
+    as local or remote file paths.
+
+This functionality is deprecated as of CakePHP 3.0.5
+and will be removed in a future version. Until that happens, user data being passed
+to the Http Client must be sanitized as follows::
+
+    $response = $http->post('http://example.com/api', [
+        'search' => ltrim($this->request->data('search'), '@'),
+    ]);
+
+If it is necessary to preserve leading ``@`` characters in query strings, you can pass
+a pre-encoded query string from ``http_build_query()``::
+
+    $response = $http->post('http://example.com/api', http_build_query([
+        'search' => $this->request->data('search'),
+    ]));
+
+Building Multipart Request Bodies by Hand
+-----------------------------------------
+
+There may be times when you need to build a request body in a very specific way.
+In these situations you can often use ``Cake\Network\Http\FormData`` to craft
+the specific multipart HTTP request you want::
+
+    use Cake\Network\Http\FormData;
+
+    $data = new FormData();
+
+    // Create an XML part
+    $xml = $data->newPart('xml', $xmlString);
+    // Set the content type.
+    $xml->type('application/xml');
+    $data->add($xml);
+
+    // Create a file upload with addFile()
+    // This will append the file to the form data as well.
+    $file = $data->addFile('upload', fopen('/some/file.txt', 'r'));
+    $file->contentId('abc123');
+    $file->disposition('attachment');
+
+    // Send the request.
+    $response = $http->post(
+        'http://example.com/api',
+        (string)$data,
+        ['headers' => ['Content-Type' => 'multipart/related']]
+    );
 
 Sending Request Bodies
 ======================
@@ -180,6 +227,17 @@ key and consumer secret::
       ]
     ]);
 
+OAuth 2 Authentication
+----------------------
+
+Because OAuth2 is often just a simple header, there is not a specialized
+authentication adapter. Instead you can create a client with the access token::
+
+    $http = new Client([
+        'headers' => ['Authorization' => 'Bearer ' . $accessToken]
+    ]);
+    $response = $http->get('https://example.com/api/profile/1');
+
 Proxy Authentication
 --------------------
 
diff --git a/en/core-libraries/inflector.rst b/en/core-libraries/inflector.rst
index 1d5b47073c08e8024773f179a4421ae0330ea2fe..301348b3efb19bbac8577e449c5c8eec18521bd7 100644
--- a/en/core-libraries/inflector.rst
+++ b/en/core-libraries/inflector.rst
@@ -26,8 +26,18 @@ customize the rules used::
     // Apples
     echo Inflector::pluralize('Apple');
 
+.. note::
+
+    ``pluralize()`` may not always correctly convert a noun that is already in its plural form.
+
+.. code-block:: php
+
     // Person
     echo Inflector::singularize('People');
+    
+.. note::
+
+    ``singularize()`` may not always correctly convert a noun that is already in its singular form.
 
 Creating CamelCase and under_scored Forms
 =========================================
@@ -41,7 +51,7 @@ These methods are useful when creating class names, or property names::
     Inflector::camelize('Apple_pie')
 
     // apple_pie
-    Inflector::undescore('ApplePie');
+    Inflector::underscore('ApplePie');
 
 It should be noted that underscore will only convert camelCase
 formatted words. Words that contains spaces will be lower-cased,
@@ -121,7 +131,7 @@ Loading Custom Inflections
 .. php:staticmethod:: rules($type, $rules, $reset = false)
 
 Define new inflection and transliteration rules for Inflector to use.  Often,
-this method is used in your ``config/bootstrap.php``::
+this method is used in your **config/bootstrap.php**::
 
     Inflector::rules('singular', ['/^(bil)er$/i' => '\1', '/^(inflec|contribu)tors$/i' => '\1ta']);
     Inflector::rules('uninflected', ['singulars']);
diff --git a/en/core-libraries/internationalization-and-localization.rst b/en/core-libraries/internationalization-and-localization.rst
index f70b39e0852c988e090595f10a6c81e90665d6ab..a1e77c435df6b4830954001ac999744b54c6cc83 100644
--- a/en/core-libraries/internationalization-and-localization.rst
+++ b/en/core-libraries/internationalization-and-localization.rst
@@ -40,7 +40,7 @@ Language Files
 Translations can be made available by using language files stored in your
 application. The default format for CakePHP translation files is the
 `Gettext `_ format. Files need to be
-placed under ``src/Locale/`` and within this directory, there should be
+placed under **src/Locale/** and within this directory, there should be
 a subfolder for each language the application needs to support::
 
     /src
@@ -94,7 +94,7 @@ the :doc:`following chapter ` to learn more.
 Setting the Default Locale
 --------------------------
 
-The default locale can be set in your ``config/bootstrap.php`` folder by using
+The default locale can be set in your **config/bootstrap.php** folder by using
 the following line::
 
     ini_set('intl.default_locale', 'fr_FR');
@@ -162,6 +162,16 @@ All translation functions support placeholder replacements::
 
     __x('alphabet', 'He read the letter {0}', 'Z');
 
+The ``'`` (single quote) character acts as an escape code in translation
+messages. Any variables between single quotes will not be replaced and is
+treated as literal text. For example::
+
+    __("This variable '{0}' be replaced.", 'will not');
+
+By using two adjacent quotes your variables will be replaced properly::
+
+    __("This variable ''{0}'' be replaced.", 'will');
+
 These functions take advantage of the
 `ICU MessageFormatter `_
 so you can translate messages and localize dates, numbers and
@@ -175,7 +185,6 @@ currency at the same time::
     // Returns
     Hi Charles, your balance on the Jan 13, 2014, 11:12 AM is $ 1,354.37
 
-
 Numbers in placeholders can be formatted as well with fine grain control of the
 output::
 
@@ -217,6 +226,10 @@ understands the same options as ``date``.
     names like ``['name' => 'Sara', 'age' => 12]``. This feature is not available
     in PHP 5.4.
 
+    If you are planning on making use of the internationalization features it is
+    a good idea to ensure you are running PHP5.5, and have a version of ICU
+    above 48.x.y. Older versions of PHP and ICU have a number of problems.
+
 Plurals
 -------
 
@@ -233,23 +246,27 @@ the following strings
 
 .. code-block:: pot
 
-     msgid "{0,plural,=0{No records found} =1{Found 1 record} other{Found {1} records}}"
-     msgstr "{0,plural,=0{Ningún resultado} =1{1 resultado} other{{1} resultados}}"
+     msgid "{0,plural,=0{No records found} =1{Found 1 record} other{Found # records}}"
+     msgstr "{0,plural,=0{Ningún resultado} =1{1 resultado} other{# resultados}}"
+
+     msgid "{placeholder,plural,=0{No records found} =1{Found 1 record} other{Found {1} records}}"
+     msgstr "{placeholder,plural,=0{Ningún resultado} =1{1 resultado} other{{1} resultados}}"
 
 And in your application use the following code to output either of the
 translations for such string::
 
-    __('{0,plural,=0{No records found }=1{Found 1 record} other{Found {1} records}}', [0]);
+    __('{0,plural,=0{No records found }=1{Found 1 record} other{Found # records}}', [0]);
 
     // Returns "Ningún resultado" as the argument {0} is 0
 
-    __('{0,plural,=0{No records found} =1{Found 1 record} other{Found {1} records}}', [1]);
+    __('{0,plural,=0{No records found} =1{Found 1 record} other{Found # records}}', [1]);
 
     // Returns "1 resultado" because the argument {0} is 1
 
-    __('{0,plural,=0{No records found} =1{Found 1 record} other{Found {1} records}}', [2, 2]);
+    __('{placeholder,plural,=0{No records found} =1{Found 1 record} other{Found {1} records}}', [0, 'many', 'placeholder' => 2])
 
-    // Returns "2 resultados" because the argument {0} is 2
+    // Returns "many resultados" because the argument {placeholder} is 2 and
+    // argument {1} is 'many'
 
 A closer look to the format we just used will make it evident how messages are
 built::
@@ -260,6 +277,9 @@ The ``[count placeholder]`` can be the array key number of any of the variables
 you pass to the translation function. It will be used for selecting the correct
 plural form.
 
+Note that to reference ``[count placeholder]`` within ``{message}`` you have to
+use ``#``.
+
 You can of course use simpler message ids if you don't want to type the full
 plural selection sequence in your code
 
@@ -346,7 +366,7 @@ for a single domain and locale::
     I18n::translator('animals', 'fr_FR', function () {
         $package = new Package(
             'default', // The formatting strategy (ICU)
-            'default', // The fallback domain
+            'default'  // The fallback domain
         );
         $package->setMessages([
             'Dog' => 'Chien',
@@ -358,7 +378,7 @@ for a single domain and locale::
         return $package;
     });
 
-The above code can be added to your ``config/bootstrap.php`` so that
+The above code can be added to your **config/bootstrap.php** so that
 translations can be found before any translation function is used. The absolute
 minimum that is required for creating a translator is that the loader function
 should return a ``Aura\Intl\Package`` object. Once the code is in place you can
@@ -402,9 +422,9 @@ class::
         }
     }
 
-The file should be created in the ``src/I18n/Parser`` directory of your
+The file should be created in the **src/I18n/Parser** directory of your
 application. Next, create the translations file under
-``src/Locale/fr_FR/animals.yaml``
+**src/Locale/fr_FR/animals.yaml**
 
 .. code-block:: yaml
 
@@ -447,7 +467,7 @@ any language from an external service::
         )
     });
 
-The above example calls an example external service to load a json file with the
+The above example calls an example external service to load a JSON file with the
 translations and then just build a ``Package`` object for any locale that is
 requested in the application.
 
@@ -482,7 +502,7 @@ Using Different Formatters
 
 In previous examples we have seen that Packages are built using ``default`` as
 first argument, and it was indicated with a comment that it corresponded to the
-formatter to be used. Formatters are  classes responsible for interpolating
+formatter to be used. Formatters are classes responsible for interpolating
 variables in translation messages and selecting the correct plural form.
 
 If you're dealing with a legacy application, or you don't need the power offered
@@ -490,7 +510,7 @@ by the ICU message formatting, CakePHP also provides the ``sprintf`` formatter::
 
     return Package('sprintf', 'fallback_domain', $messages);
 
-The messages to be translated will be passed to the ``sprintf`` function for
+The messages to be translated will be passed to the ``sprintf()`` function for
 interpolating the variables::
 
     __('Hello, my name is %s and I am %d years old', 'José', 29);
@@ -501,6 +521,75 @@ created translators using the ``translator()`` and ``config()`` methods::
 
     I18n::defaultFormatter('sprintf');
 
+Localizing Dates and Numbers
+============================
+
+When outputting Dates and Numbers in your application, you will often need that
+they are formatted according to the preferred format for the country or region
+that you wish your page to be displayed.
+
+In order to change how dates and numbers are displayed you just need to change
+the current locale setting and use the right classes::
+
+    use Cake\I18n\I18n;
+    use Cake\I18n\Time;
+    use Cake\I18n\Number;
+
+    I18n::locale('fr-FR');
+
+    $date = new Time('2015-04-05 23:00:00');
+
+    echo $date; // Displays 05/04/2015 23:00
+
+    echo Number::format(524.23); // Displays 524,23
+
+Make sure you read the :doc:`/core-libraries/time` and :doc:`/core-libraries/number`
+sections to learn more about formatting options.
+
+By default dates returned for the ORM results use the ``Cake\I18n\Time`` class,
+so displaying them directly in you application will be affected by changing the
+current locale.
+
+.. _parsing-localized-dates:
+
+Parsing Localized Datetime Data
+-------------------------------
+
+When accepting localized data from the request, it is nice to accept datetime
+information in a user's localized format. In a controller, or
+:doc:`/development/dispatch-filters` you can configure the Date, Time, and
+DateTime types to parse localized formats::
+
+    use Cake\Database\Type;
+
+    // Enable default locale format parsing.
+    Type::build('datetime')->useLocaleParser();
+
+    // Configure a custom datetime format parser format.
+    Type::build('datetime')->useLocaleParser()->setLocaleFormat('dd-M-y');
+
+    // You can also use IntlDateFormatter constants.
+    Type::build('datetime')->useLocaleParser()
+        ->setLocaleFormat([IntlDateFormatter::SHORT, -1]);
+
+The default parsing format is the same as the default string format.
+
+Automatically Choosing the Locale Based on Request Data
+=======================================================
+
+By using the ``LocaleSelectorFilter`` in your application, CakePHP will
+automatically set the locale based on the current user::
+
+    // in config/bootstrap.php
+    DispatcherFactory::add('LocaleSelector');
+
+    // Restrict the locales to only en-US, fr-FR
+    DispatcherFactory::add('LocaleSelector', ['locales' => ['en-US', 'fr-FR']]);
+
+The ``LocaleSelectorFilter`` will use the ``Accept-Language`` header to
+automatically set the user's preferred locale. You can use the locale list
+option to restrict which locales will automatically be used.
+
 .. meta::
     :title lang=en: Internationalization & Localization
     :keywords lang=en: internationalization localization,internationalization and localization,language application,gettext,l10n,pot,i18n,translation,languages
diff --git a/en/core-libraries/logging.rst b/en/core-libraries/logging.rst
index 04b1c3479bda2f293c9e522dc0f29110ab492cfa..5c8da27cd1b5b4fc5eaa9cf4eaf83d742be3ffdd 100644
--- a/en/core-libraries/logging.rst
+++ b/en/core-libraries/logging.rst
@@ -24,7 +24,7 @@ Logging Configuration
 =====================
 
 Configuring ``Log`` should be done during your application's bootstrap phase.
-The ``config/app.php`` file is intended for just this.  You can define
+The **config/app.php** file is intended for just this.  You can define
 as many or as few loggers as your application needs.  Loggers should be
 configured using :php:class:`Cake\\Core\\Log`. An example would be::
 
@@ -48,7 +48,7 @@ configured using :php:class:`Cake\\Core\\Log`. An example would be::
 
 The above creates two loggers.  One named ``debug`` the other named ``error``.
 Each is configured to handle different levels of messages. They also store their
-log messages in separate files, so its easy to separate debug/notice/info logs
+log messages in separate files, so it's easy to separate debug/notice/info logs
 from more serious errors. See the section on :ref:`logging-levels` for more
 information on the different levels and what they mean.
 
@@ -81,8 +81,8 @@ Creating Log Adapters
 Log adapters can be part of your application, or part of
 plugins. If for example you had a database logger called
 ``DatabaseLog``. As part of your application it would be placed in
-``src/Log/Engine/DatabaseLog.php``. As part of a plugin it would be placed in
-``plugins/LoggingPack/src/Log/Engine/DatabaseLog.php``. To configure log
+**src/Log/Engine/DatabaseLog.php**. As part of a plugin it would be placed in
+**plugins/LoggingPack/src/Log/Engine/DatabaseLog.php**. To configure log
 adapters you should use :php:meth:`Cake\\Log\\Log::config()`.  For example
 configuring our DatabaseLog would look like::
 
@@ -144,7 +144,7 @@ interface as it only requires you to implement the ``log()`` method.
 
 .. note::
 
-    You should configure loggers during bootstrapping. ``config/app.php`` is the
+    You should configure loggers during bootstrapping. **config/app.php** is the
     conventional place to configure log adapters.
 
     In debug mode missing directories will be automatically created to avoid unnecessary
@@ -155,7 +155,7 @@ Error and Exception Logging
 
 Errors and Exceptions can also be logged. By configuring the co-responding
 values in your app.php file.  Errors will be displayed when debug > 0 and logged
-when debug is ``false``. To log uncaugh exceptions, set the ``log`` option to
+when debug is ``false``. To log uncaught exceptions, set the ``log`` option to
 ``true``. See :doc:`/development/configuration` for more information.
 
 Interacting with Log Streams
diff --git a/en/core-libraries/number.rst b/en/core-libraries/number.rst
index b71908e64ff3d0a9498c774f3cf75c08a911dcf8..48dec7f698d1b55cfb42640e5687fba1138241a2 100644
--- a/en/core-libraries/number.rst
+++ b/en/core-libraries/number.rst
@@ -33,7 +33,7 @@ use the ``Number`` class::
 
 .. start-cakenumber
 
-All of these functions return the formatted number; They do not
+All of these functions return the formatted number; they do not
 automatically echo the output into the view.
 
 Formatting Currency Values
@@ -75,7 +75,7 @@ output. The following options are available:
 +---------------------+----------------------------------------------------+
 | after               | Text to display before the rendered number.        |
 +---------------------+----------------------------------------------------+
-| zero                | The text to use for zero values, can be a string   |
+| zero                | The text to use for zero values; can be a string   |
 |                     | or a number. ie. 0, 'Free!'.                       |
 +---------------------+----------------------------------------------------+
 | places              | Number of decimal places to use, ie. 2             |
@@ -97,7 +97,7 @@ output. The following options are available:
 |                     | with the international currency code.              |
 +---------------------+----------------------------------------------------+
 
-If $currency value is ``null``, the default currency will be retrieved form
+If $currency value is ``null``, the default currency will be retrieved from
 :php:meth:`Cake\\I18n\\Number::defaultCurrency()`
 
 
@@ -216,17 +216,17 @@ resides.
 +=====================+====================================================+
 | places              | Number of decimal places to use, ie. 2             |
 +---------------------+----------------------------------------------------+
-| precision           | Maximal number of decimal places to use, ie. 2     |
+| precision           | Maximum number of decimal places to use, ie. 2     |
 +---------------------+----------------------------------------------------+
 | pattern             | An ICU number pattern to use for formatting the    |
 |                     | number ie. #,###.00                                |
 +---------------------+----------------------------------------------------+
-| locale              | The locale name to use for formating number,       |
+| locale              | The locale name to use for formatting number,      |
 |                     | ie. "fr_FR".                                       |
 +---------------------+----------------------------------------------------+
 | before              | Text to display before the rendered number.        |
 +---------------------+----------------------------------------------------+
-| after               | Text to display before the rendered number.        |
+| after               | Text to display after the rendered number.         |
 +---------------------+----------------------------------------------------+
 
 Example::
@@ -283,14 +283,14 @@ The ``$options`` parameter takes the same keys as :php:meth:`Number::format()` i
 +=====================+====================================================+
 | places              | Number of decimal places to use, ie. 2             |
 +---------------------+----------------------------------------------------+
-| precision           | Maximal number of decimal places to use, ie. 2     |
+| precision           | Maximum number of decimal places to use, ie. 2     |
 +---------------------+----------------------------------------------------+
-| locale              | The locale name to use for formating number,       |
+| locale              | The locale name to use for formatting number,      |
 |                     | ie. "fr_FR".                                       |
 +---------------------+----------------------------------------------------+
 | before              | Text to display before the rendered number.        |
 +---------------------+----------------------------------------------------+
-| after               | Text to display before the rendered number.        |
+| after               | Text to display after the rendered number.         |
 +---------------------+----------------------------------------------------+
 
 Example::
diff --git a/en/core-libraries/registry-objects.rst b/en/core-libraries/registry-objects.rst
index aeeaa16df738436b9e7be9052929abf332873f2e..c06b2532ffffd706605194f1eb54901da1d15c41 100644
--- a/en/core-libraries/registry-objects.rst
+++ b/en/core-libraries/registry-objects.rst
@@ -5,7 +5,7 @@ The registry classes provide a simple way to create and retrieve loaded
 instances of a given object type. There are registry classes for Components,
 Helpers, Tasks, and Behaviors.
 
-While the examples below, will use Components, the same behavior can be expected
+While the examples below will use Components, the same behavior can be expected
 for Helpers, Behaviors, and Tasks in addition to Components.
 
 Loading Objects
@@ -17,12 +17,12 @@ Example::
     $this->loadComponent('Acl.Acl');
     $this->addHelper('Flash')
 
-Will result in the ``Toolbar`` property and ``Flash`` helper being loaded.
+This will result in the ``Toolbar`` property and ``Flash`` helper being loaded.
 Configuration can also be set on-the-fly. Example::
 
     $this->loadComponent('Cookie', ['name' => 'sweet']);
 
-Any keys & values provided will be passed to the Component's constructor.  The
+Any keys and values provided will be passed to the Component's constructor.  The
 one exception to this rule is ``className``.  Classname is a special key that is
 used to alias objects in a registry.  This allows you to have component names
 that do not reflect the classnames, which can be helpful when extending core
@@ -41,9 +41,9 @@ for your application.
 Disabling Callbacks
 ===================
 
-In previous versions collection objects provided a ``disable`` method to disable
-objects from recieving callbacks. To do this now, you should use the features in
-the events system. For example you could disable component callbacks in the
+In previous versions, collection objects provided a ``disable()`` method to disable
+objects from receiving callbacks. You should use the features in the events system to
+accomplish this now. For example, you could disable component callbacks in the 
 following way::
 
     // Remove Auth from callbacks.
diff --git a/en/core-libraries/security.rst b/en/core-libraries/security.rst
index 508155608f022c04b0b08550fa5496f629c9914b..28b30d0b6accd2a9e12113ca20bb55d1ac41683c 100644
--- a/en/core-libraries/security.rst
+++ b/en/core-libraries/security.rst
@@ -5,7 +5,8 @@ Security
 
 .. php:class:: Security
 
-The `security library `_
+The `security library
+`_
 handles basic security measures such as providing methods for
 hashing and encrypting data.
 
@@ -25,7 +26,7 @@ encrypted in one implementation is portable to the other.
 
 This method should **never** be used to store passwords.  Instead you should use
 the one way hashing methods provided by
-:php:meth:`~Cake\Utility\Security::hash()`. An example use would be::
+:php:meth:`~Cake\\Utility\\Security::hash()`. An example use would be::
 
     // Assuming key is stored somewhere it can be re-used for
     // decryption later.
@@ -86,7 +87,7 @@ value will be used::
     // Using the default hash algorithm
     $hash = Security::hash('CakePHP Framework');
 
-The ``hash`` method supports the following hashing strategies:
+The ``hash()`` method supports the following hashing strategies:
 
 - md5
 - sha1
@@ -97,7 +98,7 @@ And any other hash algorithmn that PHP's ``hash()`` function supports.
 .. warning::
 
     You should not be using ``hash()`` for passwords in new applications.
-    Instead you should use the ``DefaultPasswordHasher`` class which uses bcrpyt
+    Instead you should use the ``DefaultPasswordHasher`` class which uses bcrypt
     by default.
 
 .. meta::
diff --git a/en/core-libraries/text.rst b/en/core-libraries/text.rst
index 432eecc755ac752e70e9c78ca32224308a4f055e..7867f8ef1179bc1de6af239ae40f0df7e324ae91 100644
--- a/en/core-libraries/text.rst
+++ b/en/core-libraries/text.rst
@@ -44,7 +44,7 @@ Generating UUIDs
 .. php:staticmethod:: uuid()
 
 The UUID method is used to generate unique identifiers as per :rfc:`4122`. The
-UUID is a 128bit string in the format of 485fc381-e790-47a3-9794-1337c0a8fe68. ::
+UUID is a 128-bit string in the format of ``485fc381-e790-47a3-9794-1337c0a8fe68``. ::
 
     Text::uuid(); // 485fc381-e790-47a3-9794-1337c0a8fe68
 
@@ -57,7 +57,7 @@ Simple String Parsing
 Tokenizes a string using ``$separator``, ignoring any instance of
 ``$separator`` that appears between ``$leftBound`` and ``$rightBound``.
 
-This method can be useful when splitting up data in that has regular
+This method can be useful when splitting up data that has regular
 formatting such as tag lists::
 
     $data = "cakephp 'great framework' php";
@@ -67,7 +67,7 @@ formatting such as tag lists::
 
 .. php:method:: parseFileSize(string $size, $default)
 
-This method unformats a number from a human readable byte size
+This method unformats a number from a human-readable byte size
 to an integer number of bytes::
 
     $int = Text::parseFileSize('2GB');
@@ -88,8 +88,8 @@ for key/value replacements::
 
 .. php:staticmethod:: cleanInsert($string, $options = [])
 
-Cleans up a ``Text::insert`` formatted string with given $options
-depending on the 'clean' key in $options. The default method used
+Cleans up a ``Text::insert`` formatted string with given ``$options``
+depending on the 'clean' key in ``$options``. The default method used
 is text but html is also available. The goal of this function is to
 replace all whitespace and unneeded markup around placeholders that
 did not get replaced by ``Text::insert``.
@@ -109,15 +109,15 @@ Wrapping Text
 
 .. php:staticmethod:: wrap($text, $options = [])
 
-Wraps a block of text to a set width, and indent blocks as well.
+Wraps a block of text to a set width and indents blocks as well.
 Can intelligently wrap text so words are not sliced across lines::
 
     $text = 'This is the song that never ends.';
     $result = Text::wrap($text, 22);
 
     // Returns
-    This is the song
-    that never ends.
+    This is the song that
+    never ends.
 
 You can provide an array of options that control how wrapping is done. The
 supported options are:
@@ -127,6 +127,26 @@ supported options are:
 * ``indent`` The character to indent lines with. Defaults to ''.
 * ``indentAt`` The line number to start indenting text. Defaults to 0.
 
+.. php:staticmethod:: wrapBlock($text, $options = [])    
+
+If you need to ensure that the total width of the generated block won't
+exceed a certain length even with internal identation, you need to use
+``wrapBlock()`` instead of ``wrap()``. This is particulary useful to generate
+text for the console for example. It accepts the same options than ``wrap()``::
+
+    $text = 'This is the song that never ends. This is the song that never ends.';
+    $result = Text::wrapBlock($text, [
+        'width' => 22,
+        'indent' => ' → ',
+        'indentAt' => 1
+    ]);
+
+    // Returns
+    This is the song that
+     → never ends. This
+     → is the song that
+     → never ends.
+
 .. start-text
 
 Highlighting Substrings
@@ -139,9 +159,9 @@ specified or a default string.
 
 Options:
 
--  'format' - string The piece of HTML with that the phrase will be
+-  ``format`` string - The piece of HTML with the phrase that will be
    highlighted
--  'html' - bool If ``true``, will ignore any HTML tags, ensuring that
+-  ``html`` bool - If ``true``, will ignore any HTML tags, ensuring that
    only the correct text is highlighted
 
 Example::
diff --git a/en/core-libraries/time.rst b/en/core-libraries/time.rst
index f91a799d6fe78fe6a54c6a15a515159769761b31..71df39e13f688dc545e567628d17d2ab6b70f548 100644
--- a/en/core-libraries/time.rst
+++ b/en/core-libraries/time.rst
@@ -31,9 +31,11 @@ use the ``Time`` class::
 
 
 Under the hood, CakePHP uses `Carbon `_
-to power its Time utility. Anything you can do with ``Carbon`` and
+to power its ``Time`` utility. Anything you can do with ``Carbon`` and
 ``DateTime``, you can do with ``Time``.
 
+For details on Carbon please see `their documentation `_.
+
 .. start-time
 
 Creating Time Instances
@@ -61,11 +63,11 @@ There are a few ways to create ``Time`` instances::
 
     $time = new Time('2 hours ago');
 
-The ``Time`` class constructor can take any paramenter the internal ``DateTime``
+The ``Time`` class constructor can take any parameter that the internal ``DateTime``
 PHP class can. When passing a number or numeric string, it will be interpreted
 as a UNIX timestamp.
 
-In test cases, you can easily mock out ``now()`` using ``setTestNow()``::
+In test cases you can easily mock out ``now()`` using ``setTestNow()``::
 
     // Fixate time.
     $now = new Time('2014-04-12 12:22:30');
@@ -126,7 +128,7 @@ dates. CakePHP makes this a snap::
     // Prints a localized datetime stamp.
     echo $now;
 
-    // Outputs '4/20/14, 10:10 PM' for the en-US locale
+    // Outputs '10/31/14, 12:00 AM' for the en-US locale
     $now->i18nFormat();
 
     // Use the full date and time format
@@ -135,16 +137,43 @@ dates. CakePHP makes this a snap::
     // Use full date but short time format
     $now->i18nFormat([\IntlDateFormatter::FULL, \IntlDateFormatter::SHORT]);
 
-    // Outputs '2014-04-20 22:10'
+    // Outputs '2014-10-31 00:00:00'
     $now->i18nFormat('YYYY-MM-dd HH:mm:ss');
 
+It is possible to specify the desired format for the string to be displayed.
+You can either pass `IntlDateFormatter constants
+`_ as the first
+argument of this function, or pass a full ICU date formatting string as
+specified in the following resource:
+http://www.icu-project.org/apiref/icu4c/classSimpleDateFormat.html#details.
+
+You can also format dates with non-gregorian calendars::
+
+    // Outputs 'Friday, Aban 9, 1393 AP at 12:00:00 AM GMT'
+    $result = $now->i18nFormat(\IntlDateFormatter::FULL, null, 'en-IR@calendar=persian');
+
+The following calendar types are supported:
+
+* japanese
+* buddhist
+* chinese
+* persian
+* indian
+* islamic
+* hebrew
+* coptic
+* ethiopic
+
+.. versionadded:: 3.1
+    Non-gregorian calendar support was added in 3.1
+
 .. php:method:: nice()
 
 Print out a predefined 'nice' format::
 
     $now = Time::parse('2014-10-31');
 
-    // Outputs 'Oct 31, 2014 12:32pm' in en-US
+    // Outputs 'Oct 31, 2014 12:00 AM' in en-US
     echo $now->nice();
 
 You can alter the timezone in which the date is displayed without altering the
@@ -153,7 +182,7 @@ want to display them in a user's own timezone::
 
     $now->i18nFormat(\IntlDateFormatter::FULL, 'Europe/Paris');
 
-Leaving the first parameter as null will use the default formatting string::
+Leaving the first parameter as ``null`` will use the default formatting string::
 
     $now->i18nFormat(null, 'Europe/Paris');
 
@@ -167,13 +196,13 @@ Setting the Default Locale and Format String
 --------------------------------------------
 
 The default locale in which dates are displayed when using ``nice``
-``18nFormat`` is taken from the directive
+``i18nFormat`` is taken from the directive
 `intl.default_locale `_.
 You can, however, modify this default at runtime::
 
     Time::$defaultLocale = 'es-ES';
 
-From now on, dates will be displayed in the Spanish preferred format, unless
+From now on, dates will be displayed in the Spanish preferred format unless
 a different locale is specified directly in the formatting method.
 
 Likewise, it is possible to alter the default formatting string to be used for
@@ -197,7 +226,7 @@ Often it is useful to print times relative to the present::
 
     $now = new Time('Aug 22, 2011');
     echo $now->timeAgoInWords(
-        ['format' => 'F jS, Y', 'end' => '+1 year']
+        ['format' => 'MMM d, YYY', 'end' => '+1 year']
     );
     // On Nov 10th, 2011 this would display: 2 months, 2 weeks, 6 days ago
 
diff --git a/en/core-libraries/validation.rst b/en/core-libraries/validation.rst
index 9a7802dce0905546f89220c06d044f158fabfa24..f2d62648e6290fd85d012645c242c07015963b99 100644
--- a/en/core-libraries/validation.rst
+++ b/en/core-libraries/validation.rst
@@ -6,6 +6,8 @@ Validation
 The validation package in CakePHP provides features to build validators that can
 validate arbitrary arrays of data with ease.
 
+.. _creating-validators:
+
 Creating Validators
 ===================
 
@@ -96,31 +98,6 @@ An example of these methods in action is::
         ->notEmpty('body', 'A body is required', 'create')
         ->allowEmpty('header_image', 'update');
 
-Unique Fields
--------------
-
-The ``Table`` class provides a validation rule to ensure that a given field
-is unique within a table. For example, if you wanted to make sure that an e-mail
-address is unique, you could do the following::
-
-    $validator->add('email', [
-        'unique' => ['rule' => 'validateUnique', 'provider' => 'table']
-    ]);
-
-If you wish to only ensure uniqueness of a field based on an another field in
-your table, such as a foreign key of an associated table, you can scope it with
-the following::
-
-    $validator->add('email', [
-        'unique' => [
-            'rule' => ['validateUnique', ['scope' => 'site_id']],
-            'provider' => 'table'
-        ]
-    ]);
-
-This will ensure that the provided e-mail address is only unique to other
-records with the same ``site_id``.
-
 Notice that these examples take a ``provider`` key.  Adding ``Validator``
 providers is further explained in the following sections.
 
@@ -159,7 +136,7 @@ Validator instances come with a 'default' provider setup automatically. The
 default provider is mapped to the :php:class:`~Cake\\Validation\\Validation`
 class. This makes it simple to use the methods on that class as validation
 rules. When using Validators and the ORM together, additional providers are
-configured for the table and entity objects. You can use the ``provider`` method
+configured for the table and entity objects. You can use the ``provider()`` method
 to add any additional providers your application needs::
 
     $validator = new Validator();
@@ -239,6 +216,8 @@ not a particular rule should be applied::
         }
     ]);
 
+You can access the other submitted fields values using the ``$context['data']``
+array.
 The above example will make the rule for 'picture' optional depending on whether
 the value for ``show_profile_picture`` is empty. You could also use the
 ``uploadedFile`` validation rule to create optional file upload inputs::
@@ -266,6 +245,42 @@ met::
 In the above example, the ``email_frequency`` field cannot be left empty if the
 the user wants to receive the newsletter.
 
+Nesting Validators
+------------------
+
+.. versionadded:: 3.0.5
+
+When validating :doc:`/core-libraries/form` with nested data, or when working
+with models that contain array data types, it is necessary to validate the
+nested data you have. CakePHP makes it simple to add validators to specific
+attributes. For example, assume you are working with a non-relational database
+and need to store an article and its comments::
+
+    $data = [
+        'title' => 'Best article',
+        'comments' => [
+            ['comment' => '']
+        ]
+    ];
+
+To validate the comments you would use a nested validator::
+
+    $validator = new Validator();
+    $validator->add('title', 'not-blank', ['rule' => 'notBlank']);
+
+    $commentValidator = new Validator();
+    $commentValidator->add('comment', 'not-blank', ['rule' => 'notBlank']);
+
+    // Connect the nested validators.
+    $validator->addNestedMany('comments', $commentValidator);
+
+    // Get all errors including those from nested validators.
+    $validator->errors($data);
+
+You can create 1:1 'relationships' with ``addNested()`` and 1:N 'relationships'
+with ``addNestedMany()``. With both methods, the nested validator's errors will
+contribute to the parent validator's errors and influence the final result.
+
 .. _reusable-validators:
 
 Creating Reusable Validators
diff --git a/en/core-libraries/xml.rst b/en/core-libraries/xml.rst
index c563d92b6d682b4f89ac7a7593074622582ed794..2f85cd3fd794e4009429c5e0b55d255d1504aff2 100644
--- a/en/core-libraries/xml.rst
+++ b/en/core-libraries/xml.rst
@@ -12,9 +12,9 @@ DOMDocument objects, and back into arrays again.
 Importing Data to Xml Class
 ===========================
 
-.. php:staticmethod:: build($input, $options = [])
+.. php:staticmethod:: build($input, array $options = [])
 
-You can load XML-ish data do it using ``Xml::build()``. Depending on your
+You can load XML-ish data using ``Xml::build()``. Depending on your
 ``$options`` parameter, this method will return a SimpleXMLElement (default)
 or DOMDocument object. You can use ``Xml::build()`` to build XML
 objects from a variety of sources.  For example, you can load XML from
@@ -44,11 +44,11 @@ You can also build Xml objects using an array::
     ];
     $xml = Xml::build($data);
 
-If your input is invalid the Xml class will throw an Exception::
+If your input is invalid, the Xml class will throw an exception::
 
     $xmlString = 'What is XML?'
     try {
-        $xmlObject = Xml::build($xmlString); // Here will throw a Exception
+        $xmlObject = Xml::build($xmlString); // Here will throw an exception
     } catch (\Cake\Utility\Exception\XmlException $e) {
         throw new InternalErrorException();
     }
@@ -63,7 +63,7 @@ If your input is invalid the Xml class will throw an Exception::
 Transforming a XML String in Array
 ==================================
 
-.. php:staticmethod:: toArray($xml);
+.. php:staticmethod:: toArray($obj);
 
 Converting XML strings into arrays is simple with the Xml class as well. By
 default you'll get a SimpleXml object back::
@@ -84,7 +84,7 @@ Transforming an Array into a String of XML
     $xmlString = $xmlObject->asXML();
 
 Your array must have only one element in the "top level" and it can not be
-numeric. If the array is not in this format, Xml will throw a Exception.
+numeric. If the array is not in this format, Xml will throw an exception.
 Examples of invalid arrays::
 
     // Top level with numeric key
@@ -99,8 +99,8 @@ Examples of invalid arrays::
     ];
 
 
-By default array values will be output as XML tags, if you want to define
-attributes or text values you can should prefix the keys that are supposed to be
+By default array values will be output as XML tags. If you want to define
+attributes or text values you can prefix the keys that are supposed to be
 attributes with ``@``. For value text, use ``@`` as the key::
 
     $xmlArray = [
@@ -122,8 +122,8 @@ The content of ``$xmlString`` will be::
 Using Namespaces
 ----------------
 
-To use XML Namespaces, in your array you must create a key with name ``xmlns:``
-to generic namespace or input the prefix ``xmlns:`` in a custom namespace. See
+To use XML Namespaces, create a key in your array with the name ``xmlns:``
+in a generic namespace or input the prefix ``xmlns:`` in a custom namespace. See
 the samples::
 
     $xmlArray = [
@@ -175,7 +175,7 @@ your document type to add, remove, or manipulate child nodes::
 
 .. tip::
 
-    After manipulate your XML using SimpleXMLElement or DomDocument you can use
+    After manipulating your XML using SimpleXMLElement or DomDocument you can use
     ``Xml::toArray()`` without a problem.
 
 .. meta::
diff --git a/en/debug-kit.rst b/en/debug-kit.rst
index 6b9bfb7cd3f2c6b0f08118b45197c12cabc31a2f..8a62f5a7908fb6210033b6acab5372b1bf24f828 100644
--- a/en/debug-kit.rst
+++ b/en/debug-kit.rst
@@ -12,7 +12,7 @@ you've removed it and want to re-install it, you can do so by running the
 following from your application's ROOT directory (where composer.json file is
 located)::
 
-    php composer.phar require cakephp/debug_kit "3.0.*-dev"
+    php composer.phar require --dev cakephp/debug_kit "~3.0"
 
 DebugKit Storage
 ================
@@ -27,7 +27,7 @@ Database Configuration
 By default DebugKit will store panel data into a SQLite database in your
 application's ``tmp`` directory. If you cannot install pdo_sqlite, you can
 configure DebugKit to use a different database by defining a ``debug_kit``
-connection in your ``config/app.php`` file.
+connection in your **config/app.php** file.
 
 Toolbar Usage
 =============
@@ -87,9 +87,9 @@ applications.
 Creating a Panel Class
 ----------------------
 
-Panel Classes simply need to be placed in the ``src/Panel`` directory. The
+Panel Classes simply need to be placed in the **src/Panel** directory. The
 filename should match the classname, so the class ``MyCustomPanel`` would be
-expected to have a filename of ``src/Panel/MyCustomPanel.php``::
+expected to have a filename of **src/Panel/MyCustomPanel.php**::
 
     namespace App\Panel;
 
@@ -111,7 +111,7 @@ Callbacks
 By default Panel objects have two callbacks, allowing them to hook into the
 current request. Panels subscribe to the ``Controller.initialize`` and
 ``Controller.shutdown`` events. If your panel needs to subscribe to additional
-events, you can use the ``implementedEvents`` method to define all of the events
+events, you can use the ``implementedEvents()`` method to define all of the events
 your panel is interested in.
 
 You should refer to the built-in panels for some examples on how you can build
@@ -124,7 +124,7 @@ Each Panel is expected to have a view element that renders the content from the
 panel. The element name must be the underscored inflection of the class name.
 For example ``SessionPanel`` has an element named ``session_panel.ctp``, and
 SqllogPanel has an element named ``sqllog_panel.ctp``. These elements should be
-located in the root of your ``src/Template/Element`` directory.
+located in the root of your **src/Template/Element** directory.
 
 Custom Titles and Elements
 --------------------------
@@ -136,6 +136,21 @@ customize your panel's behavior:
 - ``title()`` - Configure the title that is displayed in the toolbar.
 - ``elementName()`` - Configure which element should be used for a given panel.
 
+Panel Hook Methods
+------------------
+
+You can also implement the following hook methods to customize how your panel
+behaves and appears:
+
+* ``shutdown(Event $event)`` This method typically collects and prepares the
+  data for the panel. Data is generally stored in ``$this->_data``.
+* ``summary()`` Can return a string of summary data to be displayed in the
+  toolbar even when a panel is collapsed. Often this is a counter, or short
+  summary information.
+* ``data()`` Returns the panel's data to be used as element context. This hook
+  method lets you further manipulate the data collected in the ``shutdown()``
+  method. This method **must** return data that can be serialized.
+
 Panels in Other Plugins
 -----------------------
 
@@ -157,10 +172,9 @@ render time::
 To use a plugin or app panel, update your application's DebugKit configuration
 to include the panel::
 
-    Configure::write(
-        'DebugKit.panels',
-        array_merge(Configure::read('DebugKit.panels'), ['MyCustomPanel'])
-    );
+    // in config/bootstrap.php
+    Configure::write('DebugKit.panels', ['App', 'MyPlugin.MyCustom']);
+    Plugin::load('DebugKit', ['bootstrap' => true]);
 
-The above would load all the default panels as well as the custom panel from
-``MyPlugin``.
+The above would load all the default panels as well as the ``AppPanel``, and
+``MyCustomPanel`` panel from ``MyPlugin``.
diff --git a/en/deployment.rst b/en/deployment.rst
index 83d200ab4b94aa69bd258970d85fbfe8daf6b735..7c481eb95aba9008340772cc4ad4273e57c1ed5a 100644
--- a/en/deployment.rst
+++ b/en/deployment.rst
@@ -85,9 +85,18 @@ your production server once the application is deployed::
 
 Since handling static assets, such as images, JavaScript and CSS files of
 plugins, through the ``Dispatcher`` is incredibly inefficient, it is strongly
-recommended to symlink them for production. For example like this::
+recommended to symlink them for production. This can be done easily using 
+the ``plugin`` shell::
 
-    ln -s Plugin/YourPlugin/webroot/css/yourplugin.css webroot/css/yourplugin.css
+    bin/cake plugin assets symlink
+    
+The above command will symlink the ``webroot`` directory of all loaded plugins to
+appropriate path in the app's ``webroot`` directory.
+
+If your filesystem doesn't allow creating symlinks the directories will be copied
+instead of being symlinked. You can also explicitly copy the directories using::
+
+    bin/cake plugin assets copy
 
 .. meta::
     :title lang=en: Deployment
diff --git a/en/development/configuration.rst b/en/development/configuration.rst
index c188fd4ac29a9d46393f82a39b8f36bf76e03712..b894bc1db5d7e885a20dda58a11aa2c9e11bb651 100644
--- a/en/development/configuration.rst
+++ b/en/development/configuration.rst
@@ -17,7 +17,7 @@ Configuring your Application
 Configuration is generally stored in either PHP or INI files, and loaded during
 the application bootstrap. CakePHP comes with one configuration file by default,
 but if required you can add additional configuration files and load them in
-``config/bootstrap.php``. :php:class:`Cake\\Core\\Configure` is used for
+**config/bootstrap.php**. :php:class:`Cake\\Core\\Configure` is used for
 general configuration, and the adapter based classes provide ``config()``
 methods to make configuration simple and transparent.
 
@@ -26,7 +26,7 @@ Loading Additional Configuration Files
 
 If your application has many configuration options it can be helpful to split
 configuration into multiple files. After creating each of the files in your
-``config/`` directory you can load them in ``bootstrap.php``::
+**config/** directory you can load them in **bootstrap.php**::
 
     use Cake\Core\Configure;
     use Cake\Core\Configure\Engine\PhpConfig;
@@ -36,7 +36,7 @@ configuration into multiple files. After creating each of the files in your
     Configure::load('other_config', 'default');
 
 You can also use additional configuration files to provide environment specific
-overrides. Each file loaded after ``app.php`` can redefine previously declared
+overrides. Each file loaded after **app.php** can redefine previously declared
 values allowing you to customize configuration for development or staging
 environments.
 
@@ -55,7 +55,7 @@ App.namespace
     .. note::
 
         When changing the namespace in your configuration, you will also
-        need to update your ``composer.json`` file to use this namespace
+        need to update your **composer.json** file to use this namespace
         as well. Additionally, create a new autoloader by running
         ``php composer.phar dumpautoload``.
 
@@ -179,25 +179,33 @@ to multiple directories with the following::
         }
     }
 
-View and Plugin Paths
----------------------
+Plugin, View Template and Locale Paths
+--------------------------------------
 
-Since views and plugins are not classes, they cannot have an autoloader
-configured. CakePHP provides two Configure variables to setup additional paths
-for these resources. In your ``config/app.php`` you can set these
-variables::
+Since plugins, view templates and locales are not classes, they cannot have an
+autoloader configured. CakePHP provides three Configure variables to setup additional
+paths for these resources. In your **config/app.php** you can set these variables::
 
     return [
         // More configuration
         'App' => [
             'paths' => [
-                'views' => [APP . 'View/', APP . 'View2/'],
-                'plugins' => [ROOT . '/Plugin/', '/path/to/other/plugins/']
+                'plugins' => [
+                    ROOT . DS . 'plugins' . DS,
+                    '/path/to/other/plugins/'
+                ],
+                'templates' => [
+                    APP . 'Template' . DS,
+                    APP . 'Template2' . DS
+                ],
+                'locales' => [
+                    APP . 'Locale' . DS
+                ]
             ]
         ]
     ];
 
-Paths should end in ``/``, or they will not work properly.
+Paths should end with a directory separator, or they will not work properly.
 
 Inflection Configuration
 ========================
@@ -276,7 +284,7 @@ Checking to see if Configuration Data is Defined
 
 .. php:staticmethod:: check($key)
 
-Used to check if a key/path exists and has not-null value::
+Used to check if a key/path exists and has non-null value::
 
     $exists = Configure::check('Company.name');
 
@@ -322,7 +330,7 @@ need to attach it to Configure using :php:meth:`Configure::config()`::
 
 You can have multiple engines attached to Configure, each reading different
 kinds or sources of configuration files. You can interact with attached engines
-using a few other methods on Configure. To see check which engine aliases are
+using a few other methods on Configure. To check which engine aliases are
 attached you can use :php:meth:`Configure::configured()`::
 
     // Get the array of aliases for attached engines.
@@ -365,9 +373,9 @@ Creating or Modifying Configuration Files
 Dumps all or some of the data in Configure into a file or storage system
 supported by a config engine. The serialization format is decided by the config
 engine attached as $config. For example, if the 'default' engine is
-a :php:class:`Cake\\Configure\\Engine\\PhpConfig`, the generated file will be
+a :php:class:`Cake\\Core\\Configure\\Engine\\PhpConfig`, the generated file will be
 a PHP configuration file loadable by the
-:php:class:`Cake\\Configure\\Engine\\PhpConfig`
+:php:class:`Cake\\Core\\Configure\\Engine\\PhpConfig`
 
 Given that the 'default' engine is an instance of PhpConfig.
 Save all data in Configure to the file `my_config.php`::
@@ -446,13 +454,13 @@ files, you could create a simple Xml config engine for you application::
             return Xml::toArray($xml);
         }
 
-        public function dump($key, $data)
+        public function dump($key, array $data)
         {
             // Code to dump data to file
         }
     }
 
-In your ``config/bootstrap.php`` you could attach this engine and use it::
+In your **config/bootstrap.php** you could attach this engine and use it::
 
     use App\Configure\Engine\XmlConfig;
 
@@ -488,14 +496,16 @@ configuration information that the resource named ``$key`` contains.
 Built-in Configuration Engines
 ==============================
 
+.. php:namespace:: Cake\Core\Configure\Engine
+
 PHP Configuration Files
 -----------------------
 
 .. php:class:: PhpConfig
 
 Allows you to read configuration files that are stored as plain PHP files.
-You can read either files from your app's ``config`` or from plugin configs
-directories by using :term:`plugin syntax`. Files **must** return an array.
+You can read either files from your app's config or from plugin configs
+directories by using :term:`plugin syntax`. Files *must* return an array.
 An example configuration file would look like::
 
     return [
@@ -509,7 +519,7 @@ An example configuration file would look like::
     ];
 
 Load your custom configuration file by inserting the following in
-``config/bootstrap.php``::
+**config/bootstrap.php**::
 
     Configure::load('customConfig');
 
@@ -519,7 +529,7 @@ Ini Configuration Files
 .. php:class:: IniConfig
 
 Allows you to read configuration files that are stored as plain .ini files.
-The ini files must be compatible with php's ``parse_ini_file`` function, and
+The ini files must be compatible with php's ``parse_ini_file()`` function, and
 benefit from the following improvements
 
 * dot separated values are expanded into arrays.
@@ -566,7 +576,7 @@ Bootstrapping CakePHP
 =====================
 
 If you have any additional configuration needs, you should add them to your
-application's ``config/bootstrap.php`` file. This file is included before each
+application's **config/bootstrap.php** file. This file is included before each
 request, and CLI command.
 
 This file is ideal for a number of common bootstrapping tasks:
diff --git a/en/development/debugging.rst b/en/development/debugging.rst
index d3cf81026aafd567e19433f10288d53cb9fe8a0f..160956913a2b1ef949bd7fa1e1edfd6db70cfbbb 100644
--- a/en/development/debugging.rst
+++ b/en/development/debugging.rst
@@ -13,7 +13,7 @@ Basic Debugging
 .. php:function:: debug(mixed $var, boolean $showHtml = null, $showFrom = true)
 
 The ``debug()`` function is a globally available function that works
-similarly to the PHP function ``print\_r()``. The ``debug()`` function
+similarly to the PHP function ``print_r()``. The ``debug()`` function
 allows you to show the contents of a variable in a number of
 different ways. First, if you'd like data to be shown in an
 HTML-friendly way, set the second parameter to ``true``. The function
@@ -23,10 +23,25 @@ default.
 Output from this function is only shown if the core ``$debug`` variable
 has been set to ``true``.
 
-.. php:function stackTrace()
+.. php:function:: stackTrace()
 
 The ``stackTrace()`` function is available globally, and allows you to output
-a stack trace whereever the function is called.
+a stack trace wherever the function is called.
+
+.. php:function:: breakpoint()
+
+.. versionadded:: 3.1
+
+If you have `Psysh `_ installed you can use this
+function in CLI enviroments to open an interactive console with the current
+local scope::
+
+    // Some code
+    eval(breakpoint());
+
+Will open an interactive console that can be used to check local variables
+and execute other code. You can exit the interactive debugger and resume the
+original execution by running ``quit`` or ``q`` in the interactive session.
 
 Using the Debugger Class
 ========================
@@ -78,7 +93,7 @@ Logging With Stack Traces
 Creates a detailed stack trace log at the time of invocation. The
 ``log()`` method prints out data similar to that done by
 ``Debugger::dump()``, but to the debug.log instead of the output
-buffer. Note your ``tmp`` directory (and its contents) must be
+buffer. Note your **tmp** directory (and its contents) must be
 writable by the web server for ``log()`` to work correctly.
 
 Generating Stack Traces
diff --git a/en/development/dispatch-filters.rst b/en/development/dispatch-filters.rst
index e004147b223ec0a79597a3e1590a6712fe942169..d279af2b40d3ef89ea7e443772ba12247f88811c 100644
--- a/en/development/dispatch-filters.rst
+++ b/en/development/dispatch-filters.rst
@@ -21,7 +21,12 @@ features that all applications are likely to need. The built-in filters are:
 * ``AssetFilter`` checks whether the request is referring to a theme
   or plugin asset file, such as a CSS, JavaScript or image file stored in either a
   plugin's webroot folder or the corresponding one for a Theme. It will serve the
-  file accordingly if found, stopping the rest of the dispatching cycle.
+  file accordingly if found, stopping the rest of the dispatching cycle::
+
+        // Use options to set cacheTime for your static assets
+        // If not set, this defaults to +1 hour
+        DispatcherFactory::add('Asset', ['cacheTime' => '+24 hours']);
+
 * ``RoutingFilter`` applies application routing rules to the request URL.
   Populates ``$request->params`` with the results of routing.
 * ``ControllerFactory`` uses ``$request->params`` to locate the controller that
@@ -32,7 +37,7 @@ features that all applications are likely to need. The built-in filters are:
 Using Filters
 =============
 
-Filters are usually enabled in your application's ``bootstrap.php`` file, but
+Filters are usually enabled in your application's **bootstrap.php** file, but
 you could easily load them any time before the request is dispatched.  Adding
 and removing filters is done through :php:class:`Cake\\Routing\\DispatcherFactory`. By
 default, the CakePHP application template comes with a couple filter classes
@@ -61,7 +66,7 @@ Configuring Filter Order
 
 When adding filters, you can control the order they are invoked in using
 event handler priorities. While filters can define a default priority using the
-``_priority`` property, you can set a specific priority when attaching the
+``$_priority`` property, you can set a specific priority when attaching the
 filter::
 
     DispatcherFactory::add('Asset', ['priority' => 1]);
@@ -93,7 +98,7 @@ The callable can expect to get the current request and response as arguments.
 Building a Filter
 =================
 
-To create a filter, define a class in ``src/Routing/Filter``. In this example,
+To create a filter, define a class in **src/Routing/Filter**. In this example,
 we'll be making a filter that adds a tracking cookie for the first landing
 page. First, create the file. Its contents should look like::
 
@@ -119,7 +124,7 @@ page. First, create the file. Its contents should look like::
         }
     }
 
-Save this file into ``src/Routing/Filter/TrackingCookieFilter.php``. As you can see, like other
+Save this file into **src/Routing/Filter/TrackingCookieFilter.php**. As you can see, like other
 classes in CakePHP, dispatcher filters have a few conventions:
 
 * Class names end in ``Filter``.
@@ -128,11 +133,11 @@ classes in CakePHP, dispatcher filters have a few conventions:
 * Generally filters extend ``Cake\Routing\DispatcherFilter``.
 
 ``DispatcherFilter`` exposes two methods that can be overridden in subclasses,
-they are ``beforeDispatch`` and ``afterDispatch``. These methods are executed
-before or after any controller is executed respectively. Both methods receive
-a :php:class:`Cake\\Event\\Event` object containing the ``request`` and
-``response`` objects (:php:class:`Cake\\Network\\Request` and
-:php:class:`Cake\\Network\\Response` instances) inside the ``data`` property.
+they are ``beforeDispatch()`` and ``afterDispatch()``. These methods are
+executed before or after any controller is executed respectively. Both methods
+receive a :php:class:`Cake\\Event\\Event` object containing the ``Request`` and
+``Response`` objects (:php:class:`Cake\\Network\\Request` and
+:php:class:`Cake\\Network\\Response` instances) inside the ``$data`` property.
 
 While our filter was pretty simple, there are a few other interesting things we
 can do in filter methods. By returning an ``Response`` object, you can
@@ -176,7 +181,7 @@ This filter will send a expiration header to 1 day in the future for
 all responses produced by the pages controller. You could of course do the same
 in the controller, this is just an example of what could be done with filters.
 For instance, instead of altering the response, you could cache it using
-:php:class:`Cake\\Cache\\Cache` and serve the response from the ``beforeDispatch``
+:php:class:`Cake\\Cache\\Cache` and serve the response from the ``beforeDispatch()``
 callback.
 
 While powerful, dispatcher filters have the potential to make your application
diff --git a/en/development/errors.rst b/en/development/errors.rst
index daef220e2ffb9912f1b1e6c285c08e2de4af9177..3b382d8992930895e4fcba11c5b264f16c1e9838 100644
--- a/en/development/errors.rst
+++ b/en/development/errors.rst
@@ -12,7 +12,7 @@ application.
 Error & Exception Configuration
 ================================
 
-Error configuration is done inside your application's ``config/app.php``
+Error configuration is done inside your application's **config/app.php**
 file. By default CakePHP uses the ``ErrorHandler`` or ``ConsoleErrorHandler``
 class to trap errors and print/log the errors. You can replace this behavior by
 changing out the default error handler. The default error handler also handles
@@ -29,7 +29,7 @@ your application:
   finding where/when errors are being raised.
 * ``exceptionRenderer`` - string - The class responsible for rendering uncaught
   exceptions. If you choose a custom class you should place the file for that
-  class in ``src/Error``. This class needs to implement a ``render()`` method.
+  class in **src/Error**. This class needs to implement a ``render()`` method.
 * ``log`` - boolean - When ``true``, exceptions + their stack traces will be
   logged to :php:class:`Cake\\Log\\Log`.
 * ``skipLog`` - array - An array of exception classnames that should not be
@@ -80,9 +80,9 @@ An example would be::
         }
     }
 
-The ``BaseErrorHandler`` defines two abstract methods. ``_displayError`` is used
-when errors are triggered. The ``_displayException`` method is called when there
-is an uncaught exception.
+The ``BaseErrorHandler`` defines two abstract methods. ``_displayError()`` is
+used when errors are triggered. The ``_displayException()`` method is called
+when there is an uncaught exception.
 
 
 Changing Fatal Error Behavior
@@ -103,7 +103,7 @@ standard error page, you can override it like::
 
     use Cake\Error\BaseErrorHandler;
 
-    class AppError
+    class AppError extends BaseErrorHandler
     {
         // Other methods.
 
@@ -138,12 +138,20 @@ exceptions for HTTP methods
 
 .. php:exception:: UnauthorizedException
 
-    Used for doing a 401 Not found error.
+    Used for doing a 401 Unauthorized error.
 
 .. php:exception:: ForbiddenException
 
     Used for doing a 403 Forbidden error.
 
+.. versionadded:: 3.1
+
+    InvalidCsrfTokenException has been added.
+
+.. php:exception:: InvalidCsrfTokenException
+
+    Used for doing a 403 error caused by an invalid CSRF token.
+
 .. php:exception:: NotFoundException
 
     Used for doing a 404 Not found error.
@@ -317,7 +325,7 @@ to indicate failure states. For example::
 
     public function view($id)
     {
-        $post = $this->Post->read(null, $id);
+        $post = $this->Post->findById($id)->first();
         if (!$post) {
             throw new NotFoundException();
         }
@@ -338,13 +346,13 @@ Exception Renderer
 The ExceptionRenderer class with the help of ``ErrorController`` takes care of
 rendering the error pages for all the exceptions thrown by you application.
 
-The error page views are located at ``src/Template/Error/``. For all 4xx and
-5xx errors the template files ``error400.ctp`` and ``error500.ctp`` are used
+The error page views are located at **src/Template/Error/**. For all 4xx and
+5xx errors the template files **error400.ctp** and **error500.ctp** are used
 respectively. You can customize them as per your needs. By default your
-``src/Template/Layout/default.ctp`` is used for error pages too. If for
-example, you want to use another layout ``src/Template/Layout/my_error.ctp``
+**src/Template/Layout/default.ctp** is used for error pages too. If for
+example, you want to use another layout **src/Template/Layout/my_error.ctp**
 for your error pages, simply edit the error views and add the statement
-``$this->layout = 'my_error';`` to the ``error400.ctp`` and ``error500.ctp``.
+``$this->layout = 'my_error';`` to the **error400.ctp** and **error500.ctp**.
 
 Each framework layer exception has its own view file located in the core
 templates but you really don't need to bother customizing them as they are used
@@ -367,7 +375,7 @@ If your application contained the following exception::
     {};
 
 You could provide nice development errors, by creating
-``src/Template/Error/missing_widget.ctp``. When in production mode, the above
+**src/Template/Error/missing_widget.ctp**. When in production mode, the above
 error would be treated as a 500 error. The constructor for
 :php:exc:`Cake\\Core\\Exception\\Exception` has been extended, allowing you to
 pass in hashes of data. These hashes are interpolated into the the
@@ -401,11 +409,11 @@ creating an exception::
 
     throw new MissingWidgetHelperException('Its not here', 501);
 
-Will create a ``501`` response code, you can use any HTTP status code
+Will create a 501 response code, you can use any HTTP status code
 you want. In development, if your exception doesn't have a specific
-template, and you use a code equal to or greater than ``500`` you will
-see the ``error500`` template. For any other error code you'll get the
-``error400`` template. If you have defined an error template for your
+template, and you use a code equal to or greater than 500 you will
+see the **error500.ctp** template. For any other error code you'll get the
+**error400.ctp** template. If you have defined an error template for your
 custom exception, that template will be used in development mode.
 If you'd like your own exception handling logic even in production,
 see the next section.
@@ -442,9 +450,9 @@ Using the exceptionRenderer Option of the Default Handler
 
 If you don't want to take control of the exception handling, but want to change
 how exceptions are rendered you can use the ``exceptionRenderer`` option in
-``config/app.php`` to choose a class that will render exception pages. By
+**config/app.php** to choose a class that will render exception pages. By
 default :php:class:`Cake\\Core\\Exception\\ExceptionRenderer` is used. Your
-custom exception renderer class should be placed in ``src/Error``. In a custom
+custom exception renderer class should be placed in **src/Error**. In a custom
 exception rendering class you can provide specialized handling for application
 specific errors::
 
@@ -491,9 +499,10 @@ By convention CakePHP will use ``App\Controller\ErrorController`` if it exists.
 Implementing this class can give you a configuration free way of customizing
 error page output.
 
-If you are using custom exception renderer, you can use the ``_getController``
-method to return a customize the controller.  By implementing ``_getController``
-in your exception renderer you can use any controller you want::
+If you are using custom exception renderer, you can use the ``_getController()``
+method to return a customize the controller.  By implementing
+``_getController()`` in your exception renderer you can use any controller you
+want::
 
     // in src/Error/AppExceptionRenderer
     namespace App\Error;
@@ -524,7 +533,7 @@ Logging Exceptions
 
 Using the built-in exception handling, you can log all the exceptions that are
 dealt with by ErrorHandler by setting the ``log`` option to ``true`` in your
-``config/app.php``. Enabling this will log every exception to
+**config/app.php**. Enabling this will log every exception to
 :php:class:`Cake\\Log\\Log` and the configured loggers.
 
 .. note::
diff --git a/en/development/rest.rst b/en/development/rest.rst
index eb9e5c9b80abd98bab47d4e264d83a189c593790..2060ea15aa665ff60a0bc012afabda656baaaf5e 100644
--- a/en/development/rest.rst
+++ b/en/development/rest.rst
@@ -108,11 +108,11 @@ serialize into XML.
 
 If we wanted to modify the data before it is converted into XML we should not
 define the ``_serialize`` view variable, and instead use template files. We place
-the REST views for our RecipesController inside ``src/Template/recipes/xml``. We can also use
+the REST views for our RecipesController inside **src/Template/Recipes/xml**. We can also use
 the :php:class:`Xml` for quick-and-easy XML output in those views. Here's what
 our index view might look like::
 
-    // app/View/Recipes/xml/index.ctp
+    // src/Template/Recipes/xml/index.ctp
     // Do some formatting and manipulation on
     // the $recipes array.
     $xml = Xml::fromArray(['response' => $recipes]);
@@ -166,6 +166,12 @@ and supply the array version of that data in ``$this->request->data``.
 You can also wire in additional deserializers for alternate formats if you
 need them, using :php:meth:`RequestHandler::addInputType()`.
 
+RESTful Routing
+===============
+
+CakePHP's Router makes connecting RESTful resource routes easy. See the section
+on :ref:`resource-routes` for more information.
+
 .. meta::
     :title lang=en: REST
     :keywords lang=en: application programmers,default routes,core functionality,result format,mashups,recipe database,request method,easy access,config,soap,recipes,logic,audience,cakephp,running,api
diff --git a/en/development/routing.rst b/en/development/routing.rst
index 2e0c3240edb61aa1db31e0411634cc73e505e2c9..54a23d2e58a4ad3a97bbd638e2b83380c4016320 100644
--- a/en/development/routing.rst
+++ b/en/development/routing.rst
@@ -25,8 +25,18 @@ this to your **routes.php** file::
 
     use Cake\Routing\Router;
 
+    // Using the scoped route builder.
+    Router::scope('/', function ($routes) {
+        $routes->connect('/', ['controller' => 'Articles', 'action' => 'index']);
+    });
+
+    // Using the static method.
     Router::connect('/', ['controller' => 'Articles', 'action' => 'index']);
 
+``Router`` provides two interfaces for connecting routes. The static method is
+a backwards compatible interface, while the scoped builders offer more terse
+syntax when building multiple routes, and better performance.
+
 This will execute the index method in the ``ArticlesController`` when the homepage
 of your site is visited. Sometimes you need dynamic routes that will accept
 multiple parameters, this would be the case, for example of a route for viewing
@@ -34,7 +44,7 @@ an article's content::
 
     Router::connect('/articles/*', ['controller' => 'Articles', 'action' => 'view']);
 
-The above route will accept any url looking like ``/articles/15`` and invoke the
+The above route will accept any URL looking like ``/articles/15`` and invoke the
 method ``view(15)`` in the ``ArticlesController``. This will not, though,
 prevent people from trying to access URLs looking like ``/articles/foobar``. If
 you wish, you can restring some parameters to conform to a regular expression::
@@ -46,14 +56,14 @@ you wish, you can restring some parameters to conform to a regular expression::
     );
 
 The previous example changed the star matcher by a new placeholder ``:id``.
-Using placeholders allows us to validate parts of the url, in this case we used
+Using placeholders allows us to validate parts of the URL, in this case we used
 the ``\d+`` regular expression so that only digits are matched. Finally, we told
 the Router to treat the ``id`` placeholder as a function argument to the
 ``view()`` function by specifying the ``pass`` option. More on using this
 options later.
 
-The CakePHP Router can also match routes in reverse. That means that from an
-array containing similar parameters, it is capable of generation a URL string::
+The CakePHP Router can also reverse match routes. That means that from an
+array containing matching parameters, it is capable of generation a URL string::
 
     use Cake\Routing\Router;
 
@@ -110,7 +120,7 @@ some routes we'll use the ``scope()`` method::
 
     // In config/routes.php
     Router::scope('/', function ($routes) {
-        $routes->fallbacks('InflectedRoute');
+        $routes->fallbacks('DashedRoute');
     });
 
 The ``connect()`` method takes up to three parameters: the URL template you wish
@@ -195,7 +205,7 @@ made available in the :ref:`passed-arguments` array.
 
 When generating URLs, routes are used too. Using
 ``['controller' => 'Users', 'action' => 'some_action', 5]`` as
-a url will output ``/cooks/some_action/5`` if the above route is the
+a URL will output ``/cooks/some_action/5`` if the above route is the
 first match found.
 
 .. _route-elements:
@@ -209,8 +219,8 @@ actions should lie. When a request is made, the values for these
 route elements are found in ``$this->request->params`` in the controller.
 When you define a custom route element, you can optionally specify a regular
 expression - this tells CakePHP how to know if the URL is correctly formed or
-not. If you choose to not provide a regular expression, any non ``/`` character will be
-treated as part of the parameter::
+not. If you choose to not provide a regular expression, any non ``/`` character
+will be treated as part of the parameter::
 
     $routes->connect(
         '/:controller/:id',
@@ -227,18 +237,21 @@ identify controller names in URLs. The ``:id`` element is a custom
 route element, and must be further clarified by specifying a
 matching regular expression in the third parameter of connect().
 
-CakePHP does not automatically produce lowercased urls when using the
+CakePHP does not automatically produce lowercased and dashed URLs when using the
 ``:controller`` parameter. If you need this, the above example could be
 rewritten like so::
 
     $routes->connect(
         '/:controller/:id',
         ['action' => 'view'],
-        ['id' => '[0-9]+', 'routeClass' => 'InflectedRoute']
+        ['id' => '[0-9]+', 'routeClass' => 'DashedRoute']
     );
 
-The special ``InflectedRoute`` class will make sure that the ``:controller`` and
-``:plugin`` parameters are correctly lowercased.
+The ``DashedRoute`` class will make sure that the ``:controller`` and
+``:plugin`` parameters are correctly lowercased and dashed.
+
+If you need lowercased and underscored URLs while migrating from a CakePHP
+2.x application, you can instead use the ``InflectedRoute`` class.
 
 .. note::
 
@@ -302,15 +315,17 @@ CakePHP, and should not be used unless you want the special meaning
 * ``action`` Used to name the controller action for a route.
 * ``plugin`` Used to name the plugin a controller is located in.
 * ``prefix`` Used for :ref:`prefix-routing`
-* ``_ext`` Used for :ref:`file-extensions` routing.
-* ``_base`` Set to ``false`` to remove the base path from the generated URL. If your application
-  is not in the root directory, this can be used to generate URLs that are 'cake relative'.
-  cake relative URLs are required when using requestAction.
-* ``_scheme``  Set to create links on different schemes like `webcal` or `ftp`. Defaults
-  to the current scheme.
+* ``_ext`` Used for :ref:`File extentions routing `.
+* ``_base`` Set to ``false`` to remove the base path from the generated URL. If
+  your application is not in the root directory, this can be used to generate
+  URLs that are 'cake relative'. cake relative URLs are required when using
+  requestAction.
+* ``_scheme``  Set to create links on different schemes like `webcal` or `ftp`.
+  Defaults to the current scheme.
 * ``_host`` Set the host to use for the link.  Defaults to the current host.
 * ``_port`` Set the port if you need to create links on non-standard ports.
-* ``_full``  If ``true`` the `FULL_BASE_URL` constant will be prepended to generated URLs.
+* ``_full``  If ``true`` the `FULL_BASE_URL` constant will be prepended to
+  generated URLs.
 * ``#`` Allows you to set URL hash fragments.
 * ``_ssl`` Set to ``true`` to convert the generated URL to https or ``false``
   to force http.
@@ -322,29 +337,34 @@ CakePHP, and should not be used unless you want the special meaning
 Passing Parameters to Action
 ----------------------------
 
-When connecting routes using :ref:`route-elements` you may want
-to have routed elements be passed arguments instead. By using the 3rd
-argument of :php:meth:`Cake\\Routing\\Router::connect()` you can define which route
-elements should also be made available as passed arguments::
+When connecting routes using :ref:`route-elements` you may want to have routed
+elements be passed arguments instead. The ``pass`` option whitelists which route
+elements should also be made available as arguments passed into the controller
+functions::
 
-    // SomeController.php
+    // src/Controller/BlogsController.php
     public function view($articleId = null, $slug = null)
     {
         // Some code here...
     }
 
     // routes.php
-    Router::connect(
-        '/blog/:id-:slug', // E.g. /blog/3-CakePHP_Rocks
-        ['controller' => 'Blog', 'action' => 'view'],
-        [
-            // order matters since this will simply map ":id" to $articleId in your action
-            'pass' => ['id', 'slug'],
-            'id' => '[0-9]+'
-        ]
-    );
+    Router::scope('/', function ($routes) {
+        $routes->connect(
+            '/blog/:id-:slug', // E.g. /blog/3-CakePHP_Rocks
+            ['controller' => 'Blogs', 'action' => 'view'],
+            [
+                // Define the route elements in the route template
+                // to pass as function arguments. Order matters since this
+                // will simply map ":id" to $articleId in your action
+                'pass' => ['id', 'slug'],
+                // Define a pattern that `id` must match.
+                'id' => '[0-9]+'
+            ]
+        );
+    });
 
-And now, thanks to the reverse routing capabilities, you can pass
+Now thanks to the reverse routing capabilities, you can pass
 in the URL array like below and CakePHP will know how to form the URL
 as defined in the routes::
 
@@ -392,6 +412,52 @@ can be used in reverse routing to identify the route you want to use::
 If your route template contains any route elements like ``:controller`` you'll
 need to supply those as part of the options to ``Router::url()``.
 
+.. note::
+
+    Route names must be unique across your entire application. The same
+    ``_name`` cannot be used twice, even if the names occur inside a different
+    routing scope.
+
+When building named routes, you will probably want to stick to some conventions
+for the route names. CakePHP makes building up route names easier by allowing
+you to define name prefixes in each scope::
+
+    Router::scope('/api', ['_namePrefix' => 'api:'], function ($routes) {
+        // This route's name will be `api:ping`
+        $routes->connect('/ping', ['controller' => 'Pings'], ['_name' => 'ping']);
+    });
+    // Generate a URL for the ping route
+    Router::url(['_name' => 'api:ping']);
+
+    // Use namePrefix with plugin()
+    Router::plugin('Contacts', ['_namePrefix' => 'contacts:'], function ($routes) {
+        // Connect routes.
+    });
+
+    // Or with prefix()
+    Router::prefix('Admin', ['_namePrefix' => 'admin:'], function ($routes) {
+        // Connect routes.
+    });
+
+You can also use the ``_namePrefix`` option inside nested scopes and it works as
+you'd expect::
+
+    Router::plugin('Contacts', ['_namePrefix' => 'contacts:', function ($routes) {
+        $routes->scope('/api', ['_namePrefix' => 'api:'], function ($routes) {
+            // This route's name will be `contacts:api:ping`
+            $routes->connect('/ping', ['controller' => 'Pings'], ['_name' => 'ping']);
+        });
+    });
+
+    // Generate a URL for the ping route
+    Router::url(['_name' => 'contacts:api:ping']);
+
+Routes connected in named scopes will only have names added if the route is also
+named. Nameless routes will not have the ``_namePrefix`` applied to them.
+
+.. versionadded:: 3.1
+    The ``_namePrefix`` option was added in 3.1
+
 .. index:: admin routing, prefix routing
 .. _prefix-routing:
 
@@ -408,7 +474,7 @@ can be enabled by using the ``prefix`` scope method::
     Router::prefix('admin', function ($routes) {
         // All routes here will be prefixed with `/admin`
         // And have the prefix => admin route element added.
-        $routes->fallbacks('InflectedRoute');
+        $routes->fallbacks('DashedRoute');
     });
 
 Prefixes are mapped to sub-namespaces in your application's ``Controller``
@@ -416,11 +482,11 @@ namespace. By having prefixes as separate controllers you can create smaller and
 simpler controllers. Behavior that is common to the prefixed and non-prefixed
 controllers can be encapsulated using inheritance,
 :doc:`/controllers/components`, or traits.  Using our users example, accessing
-the URL ``/admin/users/edit/5`` would call the ``edit`` method of our
-``src/Controller/Admin/UsersController.php`` passing 5 as the first parameter. The
-view file used would be ``src/Template/Admin/Users/edit.ctp``
+the URL ``/admin/users/edit/5`` would call the ``edit()`` method of our
+**src/Controller/Admin/UsersController.php** passing 5 as the first parameter.
+The view file used would be **src/Template/Admin/Users/edit.ctp**
 
-You can map the URL /admin to your ``index`` action of pages controller using
+You can map the URL /admin to your ``index()`` action of pages controller using
 following route::
 
     Router::prefix('admin', function ($routes) {
@@ -430,6 +496,15 @@ following route::
         $routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
     });
 
+When creating prefix routes, you can set additional route parameters using
+the ``$options`` argument::
+
+    Router::prefix('admin', ['param' => 'value'], function ($routes) {
+        // Routes connected here are prefixed with '/admin' and
+        // have the 'param' routing key set.
+        $routes->connect('/:controller');
+    });
+
 You can define prefixes inside plugin scopes as well::
 
     Router::plugin('DebugKit', function ($routes) {
@@ -482,8 +557,8 @@ Plugin Routing
 
 .. php:staticmethod:: plugin($name, $options = [], $callback)
 
-Plugin routes are most easily created using the ``plugin()`` method. This method
-creates a new routing scope for the plugin's routes::
+Routes for :doc:`/plugins` are most easily created using the ``plugin()``
+method. This method creates a new routing scope for the plugin's routes::
 
     Router::plugin('DebugKit', function ($routes) {
         // Routes connected here are prefixed with '/debug_kit' and
@@ -539,7 +614,7 @@ application with the ability to route plugin, controller, and camelized action
 names to a dashed URL.
 
 For example, if we had a ``ToDo`` plugin, with a ``TodoItems`` controller, and a
-``showItems`` action, it could be accessed at ``/to-do/todo-items/show-items``
+``showItems()`` action, it could be accessed at ``/to-do/todo-items/show-items``
 with the following router connection::
 
     Router::plugin('ToDo', ['path' => 'to-do'], function ($routes) {
@@ -561,10 +636,10 @@ extra line in your routes config file::
 
 This will enable the named extensions for all routes connected **after** this
 method call. Any routes connected prior to it will not inherit the extensions.
-By default the extensions you passed will be merged with existing list of extensions.
-You can pass ``false`` for the second argument to override existing list.
-Calling the method without arguments will return existing list of extensions.
-You can set extensions per scope as well::
+By default the extensions you passed will be merged with existing list of
+extensions. You can pass ``false`` for the second argument to override existing
+list. Calling the method without arguments will return existing list of
+extensions. You can set extensions per scope as well::
 
     Router::scope('/api', function ($routes) {
         $routes->extensions(['json', 'xml']);
@@ -580,10 +655,10 @@ By using extensions, you tell the router to remove any matching file extensions,
 and then parse what remains. If you want to create a URL such as
 /page/title-of-page.html you would create your route using::
 
-    Router::scope('/api', function ($routes) {
-        $routes->extensions(['json', 'xml']);
+    Router::scope('/page', function ($routes) {
+        $routes->extensions(['json', 'xml', 'html']);
         $routes->connect(
-            '/page/:title',
+            '/:title',
             ['controller' => 'Pages', 'action' => 'view'],
             [
                 'pass' => ['title']
@@ -608,9 +683,10 @@ Creating RESTful Routes
 
 .. php:staticmethod:: mapResources($controller, $options)
 
-Router makes it easy to generate RESTful routes for your controllers.
-If we wanted to allow REST access to a recipe database, we'd do
-something like this::
+Router makes it easy to generate RESTful routes for your controllers. RESTful
+routes are helpful when you are creating API endpoints for your application.  If
+we wanted to allow REST access to a recipe controller, we'd do something like
+this::
 
     // In config/routes.php...
 
@@ -652,8 +728,8 @@ REST client (or anything else that can do POST easily). Just set
 the value of \_method to the name of the HTTP request method you
 wish to emulate.
 
-Creating Nested Resources
--------------------------
+Creating Nested Resource Routes
+-------------------------------
 
 Once you have connected resources in a scope, you can connect routes for
 sub-resources as well. Sub-resource routes will be prepended by the original
@@ -677,8 +753,8 @@ You can get the ``article_id`` in ``CommentsController`` by::
 
 .. note::
 
-    While you can nest resources as deeply as you require, it is not recommended to
-    nest more than 2 resources together.
+    While you can nest resources as deeply as you require, it is not recommended
+    to nest more than 2 resources together.
 
 Limiting the Routes Created
 ---------------------------
@@ -697,15 +773,50 @@ Changing the Controller Actions Used
 ------------------------------------
 
 You may need to change the controller action names that are used when connecting
-routes. For example, if your ``edit`` action is called ``update`` you can use
-the ``actions`` key to rename the actions used::
+routes. For example, if your ``edit()`` action is called ``update()`` you can
+use the ``actions`` key to rename the actions used::
 
     $routes->resources('Articles', [
-        'actions' => ['update' => 'update', 'add' => 'create']
+        'actions' => ['edit' => 'update', 'add' => 'create']
     ]);
 
-The above would use ``update`` for the update action, and ``create`` instead of
-``add``.
+The above would use ``update()`` for the ``edit()`` action, and ``create()``
+instead of ``add()``.
+
+Mapping Additional Resource Routes
+----------------------------------
+
+You can map additional resource methods using the ``map`` option::
+
+     $routes->resources('Articles', [
+        'map' => [
+            'deleteAll' => [
+                'action' => 'deleteAll',
+                'method' => 'DELETE'
+            ]
+        ]
+     ]);
+     // This would connect /articles/deleteAll
+
+In addition to the default routes, this would also connect a route for
+`/articles/delete_all`. By default the path segment will match the key name. You
+can use the 'path' key inside the resource definition to customize the path
+name::
+
+
+    $routes->resources('Articles', [
+        'map' => [
+            'updateAll' => [
+                'action' => 'updateAll',
+                'method' => 'DELETE',
+                'path' => '/update_many'
+            ],
+        ]
+    ]);
+    // This would connect /articles/update_many
+
+If you define 'only' and 'map', make sure that your mapped methods are also in
+the 'only' list.
 
 .. _custom-rest-routing:
 
@@ -788,10 +899,10 @@ Generating URLs
 
 .. php:staticmethod:: url($url = null, $full = false)
 
-Generating URLs or Reverse routing is a feature in CakePHP that is used to allow you to
-easily change your URL structure without having to modify all your code.
-By using :term:`routing arrays ` to define your URLs, you can
-later configure routes and the generated URLs will automatically update.
+Generating URLs or Reverse routing is a feature in CakePHP that is used to
+allow you to easily change your URL structure without having to modify all your
+code. By using :term:`routing arrays ` to define your URLs, you
+can later configure routes and the generated URLs will automatically update.
 
 If you create URLs using strings like::
 
@@ -830,14 +941,16 @@ older versions of CakePHP.
 You can also use any of the special route elements when generating URLs:
 
 * ``_ext`` Used for :ref:`file-extensions` routing.
-* ``_base`` Set to ``false`` to remove the base path from the generated URL. If your application
-  is not in the root directory, this can be used to generate URLs that are 'cake relative'.
-  cake relative URLs are required when using requestAction.
-* ``_scheme``  Set to create links on different schemes like `webcal` or `ftp`. Defaults
-  to the current scheme.
+* ``_base`` Set to ``false`` to remove the base path from the generated URL. If
+  your application is not in the root directory, this can be used to generate
+  URLs that are 'cake relative'.  cake relative URLs are required when using
+  requestAction.
+* ``_scheme``  Set to create links on different schemes like ``webcal`` or
+  ``ftp``. Defaults to the current scheme.
 * ``_host`` Set the host to use for the link.  Defaults to the current host.
 * ``_port`` Set the port if you need to create links on non-standard ports.
-* ``_full``  If ``true`` the `FULL_BASE_URL` constant will be prepended to generated URLs.
+* ``_full``  If ``true`` the ``FULL_BASE_URL`` constant will be prepended to
+  generated URLs.
 * ``_ssl`` Set to ``true`` to convert the generated URL to https or ``false``
   to force http.
 * ``_name`` Name of route. If you have setup named routes, you can use this key
@@ -853,7 +966,7 @@ Redirect Routing
 Redirect routing allows you to issue HTTP status 30x redirects for
 incoming routes, and point them at different URLs. This is useful
 when you want to inform client applications that a resource has moved
-and you don't want to expose two URLs for the same content
+and you don't want to expose two URLs for the same content.
 
 Redirection routes are different from normal routes as they perform an actual
 header redirection if a match is found. The redirection can occur to
@@ -886,7 +999,8 @@ Custom Route Classes
 Custom route classes allow you to extend and change how individual routes parse
 requests and handle reverse routing. Route classes have a few conventions:
 
-* Route classes are expected to be found in the ``Routing\\Route`` namespace of your application or plugin.
+* Route classes are expected to be found in the ``Routing\\Route`` namespace of
+  your application or plugin.
 * Route classes should extend :php:class:`Cake\\Routing\\Route`.
 * Route classes should implement one or both of ``match()`` and/or ``parse()``.
 
@@ -894,13 +1008,14 @@ The ``parse()`` method is used to parse an incoming URL. It should generate an
 array of request parameters that can be resolved into a controller & action.
 Return ``false`` from this method to indicate a match failure.
 
-The ``match()`` method is used to match an array of URL parameters and create a string URL.
-If the URL parameters do not match the route ``false`` should be returned.
+The ``match()`` method is used to match an array of URL parameters and create a
+string URL. If the URL parameters do not match the route ``false`` should be
+returned.
 
 You can use a custom route class when making a route by using the ``routeClass``
 option::
 
-    Router::connect(
+    $routes->connect(
          '/:slug',
          ['controller' => 'Articles', 'action' => 'view'],
          ['routeClass' => 'SlugRoute']
@@ -915,33 +1030,33 @@ Default Route Class
 
 .. php:staticmethod:: defaultRouteClass($routeClass = null)
 
-If you want to use an alterate route class for all your routes besides the
+If you want to use an alternate route class for all your routes besides the
 default ``Route``, you can do so by calling ``Router::defaultRouteClass()``
 before setting up any routes and avoid having to specify the ``routeClass``
 option for each route. For example using::
 
-    Router::defaultRouteClass('DashedRoute');
+    Router::defaultRouteClass('InflectedRoute');
 
 will cause all routes connected after this to use the ``DashedRoute`` route class.
 Calling the method without an argument will return current default route class.
 
-Fallbacks method
+Fallbacks Method
 ----------------
 
 .. php:method:: fallbacks($routeClass = null)
 
-The fallbacks method is a simple shortcut for defining default routes. The method
-uses the passed routing class for the defined rules or if no class is provided the
-class returned by ``Router::defaultRouteClass()`` is used.
+The fallbacks method is a simple shortcut for defining default routes. The
+method uses the passed routing class for the defined rules or if no class is
+provided the class returned by ``Router::defaultRouteClass()`` is used.
 
 Calling fallbacks like so::
 
-    $routes->fallbacks('InflectedRoute');
+    $routes->fallbacks('DashedRoute');
 
 Is equivalent to the following explicit calls::
 
-    $routes->connect('/:controller', ['action' => 'index'], ['routeClass' => 'InflectedRoute']);
-    $routes->connect('/:controller/:action/*', [], , ['routeClass' => 'InflectedRoute']);
+    $routes->connect('/:controller', ['action' => 'index'], ['routeClass' => 'DashedRoute']);
+    $routes->connect('/:controller/:action/*', [], , ['routeClass' => 'DashedRoute']);
 
 .. note::
 
@@ -949,6 +1064,31 @@ Is equivalent to the following explicit calls::
     with ``:plugin`` and/or ``:controller`` route elements will result in
     inconsistent URL case.
 
+Creating Persistent URL Parameters
+==================================
+
+You can hook into the URL generation process using URL filter functions. Filter
+functions are called *before* the URLs are matched against the routes, this
+allows you to prepare URLs before routing.
+
+Callback filter functions should expect the following parameters:
+
+- ``$params`` The URL params being processed.
+- ``$request`` The current request.
+
+The URL filter function should *always* return the params even if unmodified.
+
+URL filters allow you to easily implement features like persistent parameters::
+
+    Router::addUrlFilter(function ($params, $request) {
+        if (isset($request->params['lang']) && !isset($params['lang'])) {
+            $params['lang'] = $request->params['lang'];
+        }
+        return $params;
+    });
+
+Filter functions are applied in the order they are connected.
+
 Handling Named Parameters in URLs
 =================================
 
@@ -983,96 +1123,75 @@ RequestActionTrait
 .. php:method:: requestAction(string $url, array $options)
 
     This function calls a controller's action from any location and
-    returns data from the action. The ``$url`` passed is a
+    returns the response body from the action. The ``$url`` passed is a
     CakePHP-relative URL (/controllername/actionname/params). To pass
     extra data to the receiving controller action add to the $options
     array.
 
     .. note::
 
-        You can use ``requestAction()`` to retrieve a fully rendered view
-        by passing 'return' in the options:
-        ``requestAction($url, ['return']);``. It is important to note
-        that making a requestAction using 'return' from a controller method
-        can cause script and css tags to not work correctly.
-
-    .. warning::
-
-        If used without caching ``requestAction`` can lead to poor
-        performance. It is seldom appropriate to use in a controller.
+        You can use ``requestAction()`` to retrieve a rendered view by passing
+        'return' in the options: ``requestAction($url, ['return']);``. It is
+        important to note that making a requestAction using 'return' from
+        a controller method may cause script and css tags to not work correctly.
 
-    ``requestAction`` is best used in conjunction with (cached)
-    elements – as a way to fetch data for an element before rendering.
-    Let's use the example of putting a "latest comments" element in the
-    layout. First we need to create a controller function that will
-    return the data::
-
-        // Controller/CommentsController.php
-        class CommentsController extends AppController
-        {
-            public function latest()
-            {
-                if (!$this->request->is('requested')) {
-                    throw new ForbiddenException();
-                }
-                return $this->Comments->find('all', [
-                    'order' => 'Comment.created DESC',
-                    'limit' => 10
-               ]);
-            }
-        }
+    Generally you can avoid dispatching sub-requests by using
+    :doc:`/views/cells`. Cells give you a lightweight way to create re-usable
+    view components when compared to ``requestAction()``.
 
     You should always include checks to make sure your requestAction methods are
-    actually originating from ``requestAction``.  Failing to do so will allow
+    actually originating from ``requestAction()``.  Failing to do so will allow
     requestAction methods to be directly accessible from a URL, which is
     generally undesirable.
 
     If we now create a simple element to call that function::
 
-        // View/Element/latest_comments.ctp
-
-        $comments = $this->requestAction('/comments/latest');
-        foreach ($comments as $comment) {
-            echo $comment->title;
-        }
+        // src/View/Element/latest_comments.ctp
+        echo $this->requestAction('/comments/latest');
 
     We can then place that element anywhere to get the output
     using::
 
         echo $this->element('latest_comments');
 
-    Written in this way, whenever the element is rendered, a request
-    will be made to the controller to get the data, the data will be
-    processed, and returned. However in accordance with the warning
-    above it's best to make use of element caching to prevent needless
-    processing. By modifying the call to element to look like this::
+    Written in this way, whenever the element is rendered, a request will be
+    made to the controller to get the data, the data will be processed, rendered
+    and returned. However in accordance with the warning above it's best to make
+    use of element caching to prevent needless processing. By modifying the call
+    to element to look like this::
 
         echo $this->element('latest_comments', [], ['cache' => '+1 hour']);
 
     The ``requestAction`` call will not be made while the cached
     element view file exists and is valid.
 
-    In addition, requestAction now takes array based cake style URLs::
+    In addition, requestAction takes routing array URLs::
 
         echo $this->requestAction(
-            ['controller' => 'Articles', 'action' => 'featured'],
-            ['return']
+            ['controller' => 'Articles', 'action' => 'featured']
         );
 
-    The URL based array are the same as the ones that :php:meth:`HtmlHelper::link()`
-    uses with one difference - if you are using passed parameters, you must put them
-    in a second array and wrap them with the correct key. This is because
-    requestAction merges the extra parameters (requestAction's 2nd parameter)
-    with the ``request->params`` member array and does not explicitly place them
-    under the ``pass`` key. Any additional keys in the ``$option`` array will
-    be made available in the requested action's ``request->params`` property::
+    .. note::
+
+        Unlike other places where array URLs are analogous to string URLs,
+        requestAction treats them differently.
+
+    The URL based array are the same as the ones that
+    :php:meth:`Cake\\Routing\\Router::url()` uses with one difference - if you
+    are using passed parameters, you must put them in a second array and wrap
+    them with the correct key. This is because requestAction merges the extra
+    parameters (requestAction's 2nd parameter) with the ``request->params``
+    member array and does not explicitly place them under the ``pass`` key. Any
+    additional keys in the ``$option`` array will be made available in the
+    requested action's ``request->params`` property::
 
         echo $this->requestAction('/articles/view/5');
 
     As an array in the requestAction would then be::
 
         echo $this->requestAction(
-            ['controller' => 'Articles', 'action' => 'view', 5],
+            ['controller' => 'Articles', 'action' => 'view'],
+            ['pass' => [5]]
         );
 
     You can also pass querystring arguments, post data or cookies using the
@@ -1085,11 +1204,6 @@ RequestActionTrait
           'cookies' => ['remember_me' => 1],
         ]);
 
-    .. note::
-
-        Unlike other places where array URLs are analogous to string URLs,
-        requestAction treats them differently.
-
     When using an array URL in conjunction with requestAction() you
     must specify **all** parameters that you will need in the requested
     action. This includes parameters like ``$this->request->data``.  In addition
diff --git a/en/development/sessions.rst b/en/development/sessions.rst
index ba7e6f2d4c46ce1acc2ef8fffb5617875cee9d6c..997fb54baa46c05f7a0ee89459d72e932dfe8ae8 100644
--- a/en/development/sessions.rst
+++ b/en/development/sessions.rst
@@ -114,10 +114,10 @@ configuration. The built-in configurations are:
 
 The accepted values are:
 
-* - defaults: either 'php', 'database', 'cache' or 'cake' as explained above.
-* - handler: An array containing the handler configuration
-* - ini: A list of php.ini directives to set before the session starts.
-* - timeout: The time in minutes the session should stay active
+* defaults - either 'php', 'database', 'cache' or 'cake' as explained above.
+* handler - An array containing the handler configuration
+* ini - A list of php.ini directives to set before the session starts.
+* timeout - The time in minutes the session should stay active
 
 Session Handlers
 ----------------
@@ -142,41 +142,25 @@ The above shows how you could setup the Database session handler with an
 application model. When using class names as your handler.engine, CakePHP will
 expect to find your class in the ``Network\Session`` namespace. For example, if
 you had a ``AppSessionHandler`` class,  the file should be
-``src/Network/Session/AppSessionHandler.php``, and the class name should be
+**src/Network/Session/AppSessionHandler.php**, and the class name should be
 ``App\\Network\\Session\\AppSessionHandler``. You can also use session handlers
 from inside plugins. By setting the engine to ``MyPlugin.PluginSessionHandler``.
 
 Database Sessions
 -----------------
 
-The changes in session configuration change how you define database sessions.
-Most of the time you will only need to set ``Session.handler.model`` in your
-configuration as well as choose the database defaults::
+If you you need to use a database to store your session data, configure as follows::
 
-    Configure::write('Session', [
-        'defaults' => 'database',
-        'handler' => [
-            'model' => 'CustomSessions'
-        ]
-    ]);
-
-The above will tell Session to use the built-in 'database' defaults, and
-specify that a model called ``CustomSessions`` will be the delegate for saving
-session information to the database.
-
-If you do not need a fully custom session handler, but still require
-database-backed session storage, you can simplify the above code to::
-
-    Configure::write('Session', [
+    'Session' => [
         'defaults' => 'database'
-    ]);
+    ]
 
 This configuration will require a database table to be added with
 at least these fields::
 
     CREATE TABLE `sessions` (
       `id` varchar(255) NOT NULL DEFAULT '',
-      `data` text,
+      `data` VARBINARY, -- or BYTEA for PostgreSQL
       `expires` int(11) DEFAULT NULL,
       PRIMARY KEY (`id`)
     );
@@ -184,6 +168,20 @@ at least these fields::
 You can find a copy of the schema for the sessions table in the application
 skeleton.
 
+You can also use your own ``Table`` class to handle the saving of the sessions::
+
+    'Session' => [
+        'defaults' => 'database',
+        'handler' => [
+            'engine' => 'Database',
+            'model' => 'CustomSessions'
+        ]
+    ]
+
+The above will tell Session to use the built-in 'database' defaults, and
+specify that a Table called ``CustomSessions`` will be the delegate for saving
+session information to the database.
+
 Cache Sessions
 --------------
 
@@ -235,7 +233,7 @@ example we'll create a session handler that stores sessions both in the Cache
 without having to worry about sessions evaporating when the cache fills up.
 
 First we'll need to create our custom class and put it in
-``src/Network/Session/ComboSession.php``. The class should look
+**src/Network/Session/ComboSession.php**. The class should look
 something like::
 
     namespace App\Network\Session;
diff --git a/en/development/testing.rst b/en/development/testing.rst
index 3b5b7cb46bab265b56ab450ae322119ade6f8b2f..b612b5b27dbc44e3660539e4841fe2ff497f15b7 100644
--- a/en/development/testing.rst
+++ b/en/development/testing.rst
@@ -45,9 +45,9 @@ tests::
 Test Database Setup
 ===================
 
-Remember to have debug enabled in your ``config/app.php`` file before running
+Remember to have debug enabled in your **config/app.php** file before running
 any tests.  Before running any tests you should be sure to add a ``test``
-datasource configuration to ``config/app.php``. This configuration is used by
+datasource configuration to **config/app.php**. This configuration is used by
 CakePHP for fixture tables and data::
 
     'Datasources' => [
@@ -73,9 +73,6 @@ After installing PHPUnit and setting up your ``test`` datasource configuration
 you can make sure you're ready to write and run your own tests by running your
 application's tests::
 
-    // For system wide PHPUnit
-    $ phpunit
-
     // For phpunit.phar
     $ php phpunit.phar
 
@@ -87,14 +84,14 @@ To run a specific test you can supply the path to the test as a parameter to
 PHPUnit. For example, if you had a test case for ArticlesTable class you could
 run it with::
 
-    $ phpunit tests/TestCase/Model/Table/ArticlesTableTest
+    $ vendor/bin/phpunit tests/TestCase/Model/Table/ArticlesTableTest
 
 You should see a green bar with some additional information about the tests run,
 and number passed.
 
 .. note::
 
-    If you are on a windows system you probably won't see any colours.
+    If you are on a Windows system you probably won't see any colours.
 
 Test Case Conventions
 =====================
@@ -123,7 +120,9 @@ Our helper looks like::
 
     namespace App\View\Helper;
 
-    class ProgressHelper extends AppHelper
+    use Cake\View\Helper;
+
+    class ProgressHelper extends Helper
     {
         public function bar($value)
         {
@@ -137,7 +136,7 @@ Our helper looks like::
 
 This is a very simple example, but it will be useful to show how you can create
 a simple test case. After creating and saving our helper, we'll create the test
-case file in ``tests/TestCase/View/Helper/ProgressHelperTest.php``. In that file
+case file in **tests/TestCase/View/Helper/ProgressHelperTest.php**. In that file
 we'll start with the following::
 
     namespace App\Test\TestCase\View\Helper;
@@ -211,13 +210,34 @@ Once you have PHPUnit installed and some test cases written, you'll want to run
 the test cases very frequently. It's a good idea to run tests before committing
 any changes to help ensure you haven't broken anything.
 
-By using ``phpunit`` you can run your application and plugin tests. To run your
+By using ``phpunit`` you can run your application tests. To run your
 application's tests you can simply run::
 
-    $ phpunit
+    // composer installs
+    $ vendor/bin/phpunit
+
+    // phar file
+    php phpunit.phar
+
+From your application's root directory. To run tests for a plugin that is part
+of your application source, first ``cd`` into the plugin directory, then use
+``phpunit`` command that matches how you installed phpunit::
 
-From your application's root directory. To run a plugin's tests, first ``cd``
-into the plugin directory, then use ``phpunit`` to run the tests.
+    cd plugins
+
+    // Using composer installed phpunit
+    ../vendor/bin/phpunit
+
+    // Using phar file
+    php ../phpunit.phar
+
+To run tests on a standalone plugin, you should first install the project in
+a separate directory and install its dependencies::
+
+    git clone git://github.com/cakephp/debug_kit.git
+    cd debug_kit
+    php ~/composer.phar install
+    php ~/phpunit.phar
 
 Filtering Test Cases
 --------------------
@@ -293,7 +313,7 @@ that can be used by the test. The benefit of using fixtures is that your test
 has no chance of disrupting live application data. In addition, you can begin
 testing your code prior to actually developing live content for an application.
 
-CakePHP uses the connection named ``test`` in your ``config/datasources.php``
+CakePHP uses the connection named ``test`` in your **config/datasources.php**
 configuration file. If this connection is not usable, an exception will be
 raised and you will not be able to use database fixtures.
 
@@ -325,7 +345,7 @@ When creating a fixture you will mainly define two things: how the table is
 created (which fields are part of the table), and which records will be
 initially populated to the table. Let's create our first fixture, that will be
 used to test our own Article model. Create a file named ``ArticlesFixture.php``
-in your ``tests/Fixture`` directory, with the following content::
+in your **tests/Fixture** directory, with the following content::
 
     namespace App\Test\Fixture;
 
@@ -343,39 +363,41 @@ in your ``tests/Fixture`` directory, with the following content::
               'body' => 'text',
               'published' => ['type' => 'integer', 'default' => '0', 'null' => false],
               'created' => 'datetime',
-              'updated' => 'datetime',
+              'modified' => 'datetime',
               '_constraints' => [
                 'primary' => ['type' => 'primary', 'columns' => ['id']]
               ]
           ];
           public $records = [
               [
-                  'id' => 1,
                   'title' => 'First Article',
                   'body' => 'First Article Body',
                   'published' => '1',
                   'created' => '2007-03-18 10:39:23',
-                  'updated' => '2007-03-18 10:41:31'
+                  'modified' => '2007-03-18 10:41:31'
               ],
               [
-                  'id' => 2,
                   'title' => 'Second Article',
                   'body' => 'Second Article Body',
                   'published' => '1',
                   'created' => '2007-03-18 10:41:23',
-                  'updated' => '2007-03-18 10:43:31'
+                  'modified' => '2007-03-18 10:43:31'
               ],
               [
-                  'id' => 3,
                   'title' => 'Third Article',
                   'body' => 'Third Article Body',
                   'published' => '1',
                   'created' => '2007-03-18 10:43:23',
-                  'updated' => '2007-03-18 10:45:31'
+                  'modified' => '2007-03-18 10:45:31'
               ]
           ];
      }
 
+.. note::
+
+    It is recommended to not manually add values to auto incremental columns,
+    as it interferes with the sequence generation in PostgreSQL and SQLServer.
+
 The ``$connection`` property defines the datasource of which the fixture will
 use.  If your application uses multiple datasources, you should make the
 fixtures match the model's datasources but prefixed with ``test_``.
@@ -431,7 +453,7 @@ Dynamic Data and Fixtures
 Since records for a fixture are declared as a class property, you cannot easily
 use functions or other dynamic data to define fixtures. To solve this problem,
 you can define ``$records`` in the init() function of your fixture. For example
-if you wanted all the created and updated timestamps to reflect today's date you
+if you wanted all the created and modified timestamps to reflect today's date you
 could do the following::
 
     namespace App\Test\Fixture;
@@ -447,7 +469,7 @@ could do the following::
             'body' => 'text',
             'published' => ['type' => 'integer', 'default' => '0', 'null' => false],
             'created' => 'datetime',
-            'updated' => 'datetime',
+            'modified' => 'datetime',
             '_constraints' => [
                 'primary' => ['type' => 'primary', 'columns' => ['id']],
             ]
@@ -457,12 +479,11 @@ could do the following::
         {
             $this->records = [
                 [
-                    'id' => 1,
                     'title' => 'First Article',
                     'body' => 'First Article Body',
                     'published' => '1',
                     'created' => date('Y-m-d H:i:s'),
-                    'updated' => date('Y-m-d H:i:s'),
+                    'modified' => date('Y-m-d H:i:s'),
                 ],
             ];
             parent::init();
@@ -483,7 +504,7 @@ create the table definition used in the test suite.
 
 Let's start with an example. Assuming you have a table named articles available
 in your application, change the example fixture given in the previous section
-(``tests/Fixture/ArticlesFixture.php``) to::
+(**tests/Fixture/ArticlesFixture.php**) to::
 
 
     class ArticlesFixture extends TestFixture
@@ -508,28 +529,25 @@ as it was shown on previous section. For example::
         public $import = ['table' => 'articles'];
         public $records = [
             [
-              'id' => 1,
               'title' => 'First Article',
               'body' => 'First Article Body',
               'published' => '1',
               'created' => '2007-03-18 10:39:23',
-              'updated' => '2007-03-18 10:41:31'
+              'modified' => '2007-03-18 10:41:31'
             ],
             [
-              'id' => 2,
               'title' => 'Second Article',
               'body' => 'Second Article Body',
               'published' => '1',
               'created' => '2007-03-18 10:41:23',
-              'updated' => '2007-03-18 10:43:31'
+              'modified' => '2007-03-18 10:43:31'
             ],
             [
-              'id' => 3,
               'title' => 'Third Article',
               'body' => 'Third Article Body',
               'published' => '1',
               'created' => '2007-03-18 10:43:23',
-              'updated' => '2007-03-18 10:45:31'
+              'modified' => '2007-03-18 10:45:31'
             ]
         ];
     }
@@ -595,7 +613,7 @@ Testing Table Classes
 =====================
 
 Let's say we already have our Articles Table class defined in
-``src/Model/Table/ArticlesTable.php``, and it looks like::
+**src/Model/Table/ArticlesTable.php**, and it looks like::
 
     namespace App\Model\Table;
 
@@ -615,11 +633,11 @@ Let's say we already have our Articles Table class defined in
     }
 
 We now want to set up a test that will test this table class. Let's now create
-a file named ``ArticlesTableTest.php`` in your ``tests/TestCase/Model/Table`` directory,
+a file named ``ArticlesTableTest.php`` in your **tests/TestCase/Model/Table** directory,
 with the following contents::
 
     namespace App\Test\TestCase\Model\Table;
-    
+
     use App\Model\Table\ArticlesTable;
     use Cake\ORM\TableRegistry;
     use Cake\TestSuite\TestCase;
@@ -637,7 +655,7 @@ Creating a Test Method
 ----------------------
 
 Let's now add a method to test the function published() in the Article model.
-Edit the file ``tests/TestCase/Model/Table/ArticlesTableTest.php`` so it now
+Edit the file **tests/TestCase/Model/Table/ArticlesTableTest.php** so it now
 looks like this::
 
     namespace App\Test\TestCase\Model\Table;
@@ -676,7 +694,7 @@ creating an instance of our ``ArticlesTable`` class, and then run our
 ``find('published')`` method. In ``$expected`` we set what we expect should be
 the proper result (that we know since we have defined which records are
 initially populated to the article table.) We test that the result equals our
-expectation by using the ``assertEquals`` method. See the :ref:`running-tests`
+expectation by using the ``assertEquals()`` method. See the :ref:`running-tests`
 section for more information on how to run your test case.
 
 
@@ -697,6 +715,10 @@ with reflected properties that normal mocks have::
         $model->verifyEmail('test@example.com');
     }
 
+In your ``tearDown()`` method be sure to remove the mock with::
+
+    TableRegistry::clear();
+
 .. _integration-testing:
 
 Controller Integration Testing
@@ -727,9 +749,12 @@ model. The controller code looks like::
 
         public function index($short = null)
         {
-            if (!empty($this->request->data)) {
+            if ($this->request->is('post')) {
                 $article = $this->Articles->newEntity($this->request->data);
-                $this->Articles->save($article);
+                if ($this->Articles->save($article)) {
+                    // Redirect as per PRG pattern
+                    return $this->redirect(['action' => 'index']);
+                }
             }
             if (!empty($short)) {
                 $result = $this->Article->find('all', [
@@ -747,7 +772,7 @@ model. The controller code looks like::
     }
 
 Create a file named ``ArticlesControllerTest.php`` in your
-``tests/TestCase/Controller`` directory and put the following inside::
+**tests/TestCase/Controller** directory and put the following inside::
 
     namespace App\Test\TestCase\Controller;
 
@@ -792,9 +817,9 @@ Create a file named ``ArticlesControllerTest.php`` in your
                 'title' => 'New Article',
                 'body' => 'New Body'
             ];
-            $this->post('/articles/add', $data);
+            $this->post('/articles', $data);
 
-            $this->assertResponseOk();
+            $this->assertResponseSuccess();
             $articles = TableRegistry::get('Articles');
             $query = $articles->find()->where(['title' => $data['title']]);
             $this->assertEquals(1, $query->count());
@@ -834,7 +859,7 @@ to configure the requests you will send to your application under test::
         'headers' => ['Accept' => 'application/json']
     ]);
 
-The state set by these helper methods is reset in the ``tearDown`` method.
+The state set by these helper methods is reset in the ``tearDown()`` method.
 
 .. _testing-authentication:
 
@@ -882,6 +907,9 @@ make testing responses much simpler. Some examples are::
     // Check for a 2xx response code
     $this->assertResponseOk();
 
+    // Check for a 2xx/3xx response code
+    $this->assertResponseSuccess();
+
     // Check for a 4xx response code
     $this->assertResponseError();
 
@@ -897,6 +925,9 @@ make testing responses much simpler. Some examples are::
     // Check that no Location header has been set
     $this->assertNoRedirect();
 
+    // Check a part of the Location header
+    $this->assertRedirectContains('/articles/edit/');
+
     // Assert not empty response content
     $this->assertResponseNotEmpty();
 
@@ -908,6 +939,7 @@ make testing responses much simpler. Some examples are::
 
     // Assert partial response content
     $this->assertResponseContains('You won!');
+    $this->assertResponseNotContains('You lost!');
 
     // Assert layout
     $this->assertLayout('default');
@@ -925,7 +957,16 @@ make testing responses much simpler. Some examples are::
     $this->assertEquals('jose', $this->viewVariable('user.username'));
 
     // Assert cookies in the response
-    $this->assertEquals('1', $this->cookies());
+    $this->assertCookie('1', 'thingid');
+
+    // Check the content type
+    $this->assertContentType('application/json');
+
+In addition to the above assertion methods, you can also use all of the
+assertions in `TestSuite
+`_ and those
+found in `PHPUnit
+`_
 
 
 Testing a JSON Responding Controller
@@ -953,7 +994,7 @@ begin with a simple example controller that responds in JSON::
         }
     }
 
-Now we create the file ``tests/TestCase/Controller/MarkersControllerTest.php``
+Now we create the file **tests/TestCase/Controller/MarkersControllerTest.php**
 and make sure our web service is returning the proper response::
 
     class MarkersControllerTest extends IntegrationTestCase
@@ -988,8 +1029,8 @@ often results in fragile, difficult to maintain test suites that are prone to
 breaking. When writing functional tests using :php:class:`IntegrationTestCase`
 you can inspect the rendered view content by setting the ``return`` option to
 'view'. While it is possible to test view content using IntegrationTestCase,
-a more robust and maintable integration/view testing can be accomplished using
-tools like `Selenium webdriver `_.
+a more robust and maintainable integration/view testing can be accomplished
+using tools like `Selenium webdriver `_.
 
 
 Testing Components
@@ -998,7 +1039,7 @@ Testing Components
 Let's pretend we have a component called PagematronComponent in our application.
 This component helps us set the pagination limit value across all the
 controllers that use it. Here is our example component located in
-``app/Controller/Component/PagematronComponent.php``::
+**src/Controller/Component/PagematronComponent.php**::
 
     class PagematronComponent extends Component
     {
@@ -1035,16 +1076,17 @@ controllers that use it. Here is our example component located in
     }
 
 Now we can write tests to ensure our paginate ``limit`` parameter is being
-set correctly by the ``adjust`` method in our component. We create the file
-``tests/TestCase/Controller/Component/PagematronComponentTest.php``::
+set correctly by the ``adjust()`` method in our component. We create the file
+**tests/TestCase/Controller/Component/PagematronComponentTest.php**::
 
     namespace App\Test\TestCase\Controller\Component;
 
     use App\Controller\Component\PagematronComponent;
     use Cake\Controller\Controller;
-    use Cake\Controller\ComponentCollection;
+    use Cake\Controller\ComponentRegistry;
     use Cake\Network\Request;
     use Cake\Network\Response;
+    use Cake\TestSuite\TestCase;
 
     class PagematronComponentTest extends TestCase
     {
@@ -1056,9 +1098,6 @@ set correctly by the ``adjust`` method in our component. We create the file
         {
             parent::setUp();
             // Setup our component and fake test controller
-            $collection = new ComponentCollection();
-            $this->component = new PagematronComponent($collection);
-
             $request = new Request();
             $response = new Response();
             $this->controller = $this->getMock(
@@ -1066,7 +1105,8 @@ set correctly by the ``adjust`` method in our component. We create the file
                 [],
                 [$request, $response]
             );
-            $this->component->setController($this->controller);
+            $registry = new ComponentRegistry($this->controller);
+            $this->component = new PagematronComponent($registry);
         }
 
         public function testAdjust()
@@ -1135,8 +1175,8 @@ Now we create our tests::
         public function setUp()
         {
             parent::setUp();
-            $view = new View();
-            $this->helper = new CurrencyRendererHelper($view);
+            $View = new View();
+            $this->helper = new CurrencyRendererHelper($View);
         }
 
         // Testing the usd() function
@@ -1162,6 +1202,9 @@ check if the returned values are equal to what is expected.
 Save this and execute the test. You should see a green bar and messaging
 indicating 1 pass and 4 assertions.
 
+When you are testing a Helper which uses other helpers, be sure to mock the
+View clases ``loadHelpers`` method.
+
 Creating Test Suites
 ====================
 
@@ -1185,7 +1228,7 @@ would be
 ``CakeTestSuite`` offers several methods for easily creating test suites based
 on the file system. It allows you to run any code you want to prepare your test
 suite. If we wanted to create a test suite for all our model tests we could
-would create ``tests/TestCase/AllModelTest.php``. Put the following in it::
+would create **tests/TestCase/AllModelTest.php**. Put the following in it::
 
     class AllModelTest extends TestSuite
     {
@@ -1197,13 +1240,13 @@ would create ``tests/TestCase/AllModelTest.php``. Put the following in it::
     }
 
 The code above will group all test cases found in the
-``tests/TestCase/Model/`` folder. To add an individual file, use
+**tests/TestCase/Model/** folder. To add an individual file, use
 ``$suite->addTestFile($filename);``. You can recursively add a directory
 for all tests using::
 
     $suite->addTestDirectoryRecursive(TESTS . 'TestCase');
 
-Would recursively add all test cases in the ``tests/TestCase/``
+Would recursively add all test cases in the **tests/TestCase/**
 directory.
 
 Creating Tests for Plugins
@@ -1266,8 +1309,7 @@ present in your ``composer.json`` file::
 
     "autoload-dev": {
         "psr-4": {
-            "MyPlugin\\Test\\": "tests",
-            "MyPlugin\\Test\\Fixture\\": "tests/Fixture"
+            "MyPlugin\\Test\\": "./plugins/MyPlugin/tests"
         }
     }
 
@@ -1346,7 +1388,7 @@ a *shell script step* to the build that contains the following:
     ];
     CONFIG
 
-Then uncomment the following line in your ``config/bootstrap.php`` file::
+Then uncomment the following line in your **config/bootstrap.php** file::
 
     //Configure::load('app_local', 'default');
 
diff --git a/en/elasticsearch.rst b/en/elasticsearch.rst
new file mode 100644
index 0000000000000000000000000000000000000000..83770e9c7d4e2a1912a38e2b114aaed9841ba619
--- /dev/null
+++ b/en/elasticsearch.rst
@@ -0,0 +1,319 @@
+ElasticSearch
+#############
+
+The ElasticSearch plugin provides an ORM-like abstraction on top of
+`elasticsearch `_. The plugin
+provides features that make testing, indexing documents and searching your
+indexes easier.
+
+Installation
+============
+
+To install the elasticsearch plugin, you can use ``composer``. From your
+application's ROOT directory (where composer.json file is located) run the
+following::
+
+    php composer.phar require cakephp/elastic-search "@stable"
+
+You will need to add the following line to your application's
+**config/bootstrap.php** file::
+
+    Plugin::load('ElasticSearch', ['bootstrap' => true]);
+
+Additionally, you will need to configure the 'elastic' datasource connection in
+your **config/app.php** file. An example configuration would be::
+
+    // in config/app.php
+    'Datasources' => [
+        // other datasources
+        'elastic' => [
+            'className' => 'Cake\ElasticSearch\Datasource\Connection',
+            'driver' => 'Cake\ElasticSearch\Datasource\Connection',
+            'host' => '127.0.0.1',
+            'port' => 9200,
+            'index' => 'my_apps_index',
+        ],
+    ]
+
+Overview
+========
+
+The elasticsearch plugin makes it easier to interact with an elasticsearch index
+and provides an interface similar to the :doc:`/orm`. To get started you should
+create a ``Type`` object. ``Type`` objects are the "Repository" or table-like
+class in elasticsearch::
+
+    // in src/Model/Type/ArticlesType.php
+    namespace App\Model\Type;
+
+    use Cake\ElasticSearch\Type;
+
+    class ArticlesType extends Type
+    {
+    }
+
+You can then use your type class in your controllers::
+
+    public function beforeFilter(Event $event)
+    {
+        parent::beforeFilter($event);
+        // Load the Type using the 'Elastic' provider.
+        $this->loadModel('Articles', 'Elastic');
+    }
+
+    public function add()
+    {
+        $article = $this->Articles->newEntity();
+        if ($this->request->is('post')) {
+            $article = $this->Articles->patchEntity($article, $this->request->data);
+            if ($this->Articles->save($article)) {
+                $this->Flash->success('It saved');
+            }
+        }
+        $this->set(compact('article'));
+    }
+
+We would also need to create a basic view for our indexed articles::
+
+    // in src/Template/Articles/add.ctp
+    Form->create($article) ?>
+    Form->input('title') ?>
+    Form->input('body') ?>
+    Form->button('Save') ?>
+    Form->end() ?>
+
+You should now be able to submit the form and have a new document added to
+elasticsearch.
+
+Document Objects
+================
+
+Like the ORM, the Elasticsearch ODM uses :doc:`/orm/entities`-like classes. The
+base class you should inherit from is ``Cake\ElasticSearch\Document``. Document
+classes are found in the ``Model\Document`` namespace in your application or
+plugin::
+
+    namespace App\Model\Document;
+
+    class Article extends Document
+    {
+    }
+
+Outside of constructor logic that makes Documents work with data from
+elasticsearch, the interface and functionality provided by ``Document`` are the
+same as those in :doc:`/orm/entities`
+
+Searching Indexed Documents
+===========================
+
+After you've indexed some documents you will want to search through them. The
+elasticsearch plugin provides a query builder that allows you to build search
+queries::
+
+    $query = $this->Articles->find()
+        ->where([
+            'title' => 'special',
+            'or' => [
+                'tags in' => ['cake', 'php'],
+                'tags not in' => ['c#', 'java']
+            ]
+        ]);
+
+    foreach ($query as $article) {
+        echo $article->title;
+    }
+
+You can use the ``FilterBuilder`` to add filtering conditions::
+
+    $query->where(function ($builder) {
+        return $builder->and(
+            $builder->gt('views', 99),
+            $builder->term('author.name', 'sally')
+        );
+    });
+
+The `FilterBuilder source
+`_
+has the complete list of methods with examples for many commonly used methods.
+
+Validating Data & Using Application Rules
+=========================================
+
+Like the ORM, the ElasticSearch plugin lets you validate data when marshalling
+documents. Validating request data, and applying application rules works the
+same as it does with the relational ORM. See the :ref:`validating-request-data`
+and :ref:`application-rules` sections for more information.
+
+.. comment::
+    Need information on nested validators.
+
+Saving New Documents
+====================
+
+When you're ready to index some data into elasticsearch, you'll first need to
+convert your data into a ``Document`` that can be indexed::
+
+    $article = $this->Articles->newEntity($data);
+    if ($this->Articles->save($article)) {
+        // Document was indexed
+    }
+
+When marshalling a document, you can specify which embedded documents you wish
+to marshall using the ``associated`` key::
+
+    $article = $this->Articles->newEntity($data, ['associated' => ['Comments']]);
+
+Saving a document will trigger the following events:
+
+* ``Model.beforeSave`` - Fired before the document is saved. You can prevent the
+  save operation from happening by stopping this event.
+* ``Model.buildRules`` - Fired when the rules checker is built for the first
+  time.
+* ``Model.afterSave`` - Fired after the document is saved.
+
+.. note::
+    There are no events for embedded documents, as the parent document and all
+    of its embedded documents are saved as one operation.
+
+
+Updating Existing Documents
+===========================
+
+When you need to re-index data, you can patch existing entities and re-save
+them::
+
+    $query = $this->Articles->find()->where(['user.name' => 'jill']);
+    foreach ($query as $doc) {
+        $doc->set($newProperties);
+        $this->Articles->save($doc);
+    }
+
+Deleting Documents
+==================
+
+After retrieving a document you can delete it::
+
+    $doc = $this->Articles->get($id);
+    $this->Articles->delete($doc);
+
+You can also delete documents matching specific conditions::
+
+    $this->Articles->deleteAll(['user.name' => 'bob']);
+
+Embedding Documents
+===================
+
+By defining embedded documents, you can attach entity classes to specific
+property paths in your documents. This allows you to provide custom behavior to
+the documents within a parent document. For example, you may want the comments
+embedded in an article to have specific application specific methods. You can
+use ``embedOne`` and ``embedMany`` to define embedded documents::
+
+    // in src/Model/Type/ArticlesType.php
+    namespace App\Model\Type;
+
+    use Cake\ElasticSearch\Type;
+
+    class ArticlesType extends Type
+    {
+        public function initialize()
+        {
+            $this->embedOne('User');
+            $this->embedMany('Comments', [
+                'entityClass' => 'MyComment'
+            ]);
+        }
+    }
+
+The above would create two embedded documents on the ``Article`` document. The
+``User`` embed will convert the ``user`` property to instances of
+``App\\Model\\Document\\User``. To get the Comments embed to use a class name
+that does not match the property name, we can use the ``entityClass`` option to
+configure a custom class name.
+
+Once we've setup our embedded documents, the results of ``find()`` and ``get()``
+will return objects with the correct embedded document classes::
+
+    $article = $this->Articles->get($id);
+    // Instance of App\Model\Document\User
+    $article->user;
+
+    // Array of App\Model\Document\Comment instances
+    $article->comments;
+
+Getting Type Instances
+======================
+
+Like the ORM, the elasticsearch plugin provides a factory/registry for getting
+``Type`` instances::
+
+    use Cake\ElasticSearch\TypeRegistry;
+
+    $articles = TypeRegistry::get('Articles');
+
+Flushing the Registry
+---------------------
+
+During test cases you may want to flush the registry. Doing so is often useful
+when you are using mock objects, or modifying a type's dependencies::
+
+    TypeRegistry::flush();
+
+Test Fixtures
+=============
+
+The elasticsearch plugin provides seamless test suite integration. Just like
+database fixtures, you can create test fixtures for elasticsearch. We could
+define a test fixture for our Articles type with the following::
+
+    namespace App\Test\Fixture;
+
+    use Cake\ElasticSearch\TestSuite\TestFixture;
+
+    /**
+     * Articles fixture
+     */
+    class ArticlesFixture extends TestFixture
+    {
+        /**
+         * The table/type for this fixture.
+         *
+         * @var string
+         */
+        public $table = 'articles';
+
+        /**
+         * The mapping data.
+         *
+         * @var array
+         */
+        public $schema = [
+            'id' => ['type' => 'integer'],
+            'user' => [
+                'type' => 'nested',
+                'properties' => [
+                    'username' => ['type' => 'string'],
+                ]
+            ]
+            'title' => ['type' => 'string'],
+            'body' => ['type' => 'string'],
+        ];
+
+        public $records = [
+            [
+                'user' => [
+                    'username' => 'billy'
+                ],
+                'title' => 'First Post',
+                'body' => 'Some content'
+            ]
+        ];
+    }
+
+The ``schema`` property uses the `native elasticsearch mapping format
+`_.
+You can safely omit the type name and top level ``properties`` key. Once your
+fixtures are created you can use them in your test cases by including them in
+your test's ``fixtures`` properties::
+
+    public $fixtures = ['app.articles'];
diff --git a/en/epub-contents.rst b/en/epub-contents.rst
index ba3a86d5f7ae84b6dc3460cdff94a001c8e8d436..7889ba1f3f54606b345233f0c23654905853806f 100644
--- a/en/epub-contents.rst
+++ b/en/epub-contents.rst
@@ -17,19 +17,20 @@ Contents
     controllers
     views
     orm
-    development/errors
 
+    controllers/components/authentication
+    bake
     core-libraries/caching
     console-and-shells
-    bake
     development/debugging
     deployment
     core-libraries/email
+    development/errors
     core-libraries/events
     core-libraries/internationalization-and-localization
     core-libraries/logging
-    controllers/components/pagination
     core-libraries/form
+    controllers/components/pagination
     plugins
     development/rest
     security
@@ -51,6 +52,7 @@ Contents
 
     core-libraries/global-constants-and-functions
     debug-kit
+    migrations
     appendices
 
 .. todolist::
diff --git a/en/index.rst b/en/index.rst
index 4e771da90f323eeab72074506c5fe3e54ab0a0a3..7003756577aa80f068525b0418d38901e6398d9c 100644
--- a/en/index.rst
+++ b/en/index.rst
@@ -1,11 +1,10 @@
-.. CakePHP Cookbook documentation master file, created by
-   sphinx-quickstart on Tue Jan 18 12:54:14 2011.
-   You can adapt this file completely to your liking, but it should at least
-   contain the root `toctree` directive.
-
 Welcome
 #######
 
+.. warning::
+    This version of the documentation is for CakePHP 3.0. Go `here for the
+    CakePHP 2.x documentation `_.
+
 The CakePHP cookbook is an openly developed and community editable documentation
 project. Notice the "Improve this Doc" button in the upper right-hand
 corner; it will direct you to the GitHub online editor of the active page,
@@ -33,7 +32,7 @@ First Steps
 ===========
 
 Learning a new framework can be intimidating and exciting at the same time. To
-help you along, we have created a cookbook packed with examples and recipies to
+help you along, we have created a cookbook packed with examples and recipes to
 get the common tasks completed. If you are new, you should start off with the
 :doc:`/quickstart` as it will give you a quick tour of what
 CakePHP has to offer and how it works.
diff --git a/en/installation.rst b/en/installation.rst
old mode 100755
new mode 100644
index ac69bfeca6e17d7cf177955c37f5a78c88df4ca8..c63d2de21669da018ac315cd39c692befb53adca
--- a/en/installation.rst
+++ b/en/installation.rst
@@ -22,15 +22,15 @@ Requirements
     default.
 
     In XAMPP, intl extension is included but you have to uncomment
-    ``extension=php_intl.dll`` in ``php.ini`` and restart the server through
+    ``extension=php_intl.dll`` in **php.ini** and restart the server through
     the XAMPP Control Panel.
 
     In WAMP, the intl extension is "activated" by default but not working.
     To make it work you have to go to php folder (by default)
-    ``C:\wamp\bin\php\php{version}``, copy all the files that looks like
-    ``icu***.dll`` and paste them into the apache bin directory
-    ``C:\wamp\bin\apache\apache{version}\bin``. Then restart all services and
-    it should be OK.
+    **C:\\wamp\\bin\\php\\php{version}**, copy all the files that looks like
+    **icu*.dll** and paste them into the apache bin directory
+    **C:\\wamp\\bin\\apache\\apache{version}\\bin**. Then restart all services
+    and it should be OK.
 
 While a database engine isn't required, we imagine that most applications will
 utilize one. CakePHP supports a variety of database storage engines:
@@ -68,11 +68,11 @@ instructions for Composer's Windows installer can be found within the README
 Now that you've downloaded and installed Composer, you can get a new CakePHP
 application by running::
 
-    php composer.phar create-project --prefer-dist -s dev cakephp/app [app_name]
+    php composer.phar create-project --prefer-dist cakephp/app [app_name]
 
 Or if Composer is installed globally::
 
-    composer create-project --prefer-dist -s dev cakephp/app [app_name]
+    composer create-project --prefer-dist cakephp/app [app_name]
 
 Once Composer finishes downloading the application skeleton and the core
 CakePHP library, you should have a functioning CakePHP application
@@ -82,34 +82,52 @@ files with the rest of your source code.
 You can now visit the path to where you installed your CakePHP application and
 see the setup traffic lights.
 
+Although composer is the recommended installation method, there are
+pre-installed downloads available on
+`Github `_.
+Those downloads contain the app skeleton with all vendor packages installed.
+Also it includes the ``composer.phar`` so you have everything you need for
+further use.
+
 Keeping Up To Date with the Latest CakePHP Changes
 --------------------------------------------------
 
-If you want to keep current with the latest changes in CakePHP you can
-add the following to your application's ``composer.json``::
+By default this is what your application **composer.json** looks like::
+
+    "require": {
+        "cakephp/cakephp": "~3.0"
+    }
+
+Each time you run
+``php composer.phar update`` you will receive the latest stable releases when
+using the default version constraint ``~3.0``. Only bugfix and minor version
+releases of 3.x will be used when updating.
+
+If you want to keep current with the latest unreleased changes in CakePHP you
+can add the change your application's **composer.json**::
 
     "require": {
-        "cakephp/cakephp": "3.0.*-dev"
+        "cakephp/cakephp": "dev-master"
     }
 
-Where ```` is the branch name you want to follow. Each time you run
-``php composer.phar update`` you will receive the latest changes in the chosen
-branch.
+Be aware that is not recommended, as your application can break when next major
+version is being released. Additionally composer does not cache development
+branches, so it slows down consecutive composer installs/updates.
 
 Permissions
 ===========
 
-CakePHP uses the ``tmp`` directory for a number of different operations.
+CakePHP uses the **tmp** directory for a number of different operations.
 Model descriptions, cached views, and session information are just a few examples.
-The ``logs`` directory is used to write log files by the default ``FileLog`` engine.
+The **logs** directory is used to write log files by the default ``FileLog`` engine.
 
-As such, make sure the directories ``logs``, ``tmp`` and all its subdirectories
+As such, make sure the directories **logs**, **tmp** and all its subdirectories
 in your CakePHP installation are writable by the web server user. Composer's
-installation process makes ``tmp`` and it's subfolders globally writeable to get
+installation process makes **tmp** and its subfolders globally writeable to get
 things up and running quickly but you can update the permissions for better
 security and keep them writable only for the webserver user.
 
-One common issue is that ``logs`` and ``tmp`` directories and subdirectories must be
+One common issue is that **logs** and **tmp** directories and subdirectories must be
 writable both by the web server and the command line user. On a UNIX system, if
 your web server user is different from your command line user, you can run the
 following commands from your application directory just once in your project to
@@ -126,21 +144,21 @@ Development Server
 
 A development installation is the fastest method to setup CakePHP.  In this
 example, we will be using CakePHP's console to run PHP's built-in web server
-which will make your application available at ``http://host:port``. From the app
+which will make your application available at **http://host:port**. From the app
 directory, execute::
 
     bin/cake server
 
 By default, without any arguments provided, this will serve your application at
-``http://localhost:8765/``.
+**http://localhost:8765/**.
 
-If you have something conflicting with ``localhost`` or port ``8765``, you can
+If you have something conflicting with **localhost** or port 8765, you can
 tell the CakePHP console to run the web server on a specific host and/or port
 utilizing the following arguments::
 
     bin/cake server -H 192.168.13.37 -p 5673
 
-This will serve your application at ``http://192.168.13.37:5673/``.
+This will serve your application at **http://192.168.13.37:5673/**.
 
 That's it! Your CakePHP application is up and running without having to
 configure a web server.
@@ -283,7 +301,7 @@ further information.
 
    If your CakePHP site still has problems with mod\_rewrite, you might
    want to try modifying settings for Virtual Hosts. On Ubuntu,
-   edit the file /etc/apache2/sites-available/default (location is
+   edit the file **/etc/apache2/sites-available/default** (location is
    distribution-dependent). In this file, ensure that
    ``AllowOverride None`` is changed to ``AllowOverride All``, so you have::
 
@@ -349,9 +367,10 @@ nginx
 -----
 
 nginx does not make use of .htaccess files like Apache, so it is necessary to
-create those rewritten URLs in the site-available configuration. Depending upon
-your setup, you will have to modify this, but at the very least,
-you will need PHP running as a FastCGI instance::
+create those rewritten URLs in the site-available configuration. This is usually
+found in ``/etc/nginx/sites-available/your_virtual_host_conf_file``. Depending
+upon your setup, you will have to modify this, but at the very least, you will
+need PHP running as a FastCGI instance::
 
     server {
         listen   80;
@@ -383,6 +402,39 @@ you will need PHP running as a FastCGI instance::
         }
     }
 
+On some servers (Like Ubuntu 14.04) the above configuration won't work out of
+the box, and the nginx docs recommend a different approach anyway
+(http://nginx.org/en/docs/http/converting_rewrite_rules.html). You might try the
+following (you'll notice this is also just one server {} block, rather than two,
+although if you want example.com to resolve to your CakePHP application in
+addition to www.example.com consult the nginx link above)::
+
+    server {
+        listen   80;
+        server_name www.example.com;
+        rewrite 301 http://www.example.com$request_uri permanent;
+
+        # root directive should be global
+        root   /var/www/example.com/public/webroot/;
+        index  index.php;
+
+        access_log /var/www/example.com/log/access.log;
+        error_log /var/www/example.com/log/error.log;
+
+        location / {
+            try_files $uri /index.php?$args;
+        }
+
+        location ~ \.php$ {
+            try_files $uri =404;
+            include /etc/nginx/fastcgi_params;
+            fastcgi_pass    127.0.0.1:9000;
+            fastcgi_index   index.php;
+            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+        }
+    }
+
+
 IIS7 (Windows hosts)
 --------------------
 
@@ -392,8 +444,10 @@ rules into IIS to use CakePHP's native rewrites. To do this, follow
 these steps:
 
 
-#. Use `Microsoft's Web Platform Installer `_ to install the URL
-   `Rewrite Module 2.0 `_ or download it directly (`32-bit `_ / `64-bit `_).
+#. Use `Microsoft's Web Platform Installer `_
+   to install the URL `Rewrite Module 2.0 `_
+   or download it directly (`32-bit `_ /
+   `64-bit `_).
 #. Create a new file called web.config in your CakePHP root folder.
 #. Using Notepad or any XML-safe editor, copy the following
    code into your new web.config file::
@@ -434,7 +488,7 @@ I Can't Use URL Rewriting
 
 If you don't want or can't get mod\_rewrite (or some other
 compatible module) up and running on your server, you'll need to
-use CakePHP's built in pretty URLs. In ``config/app.php``,
+use CakePHP's built in pretty URLs. In **config/app.php**,
 uncomment the line that looks like::
 
     'App' => [
diff --git a/en/intro.rst b/en/intro.rst
index cc95dd3b9bcb40dfc0e60731d523c89ed7de597f..d19cce86b452033546d85d6a6d541fb9e5cbf9b6 100644
--- a/en/intro.rst
+++ b/en/intro.rst
@@ -18,7 +18,7 @@ CakePHP provides a basic organizational structure that covers class names,
 filenames, database table names, and other conventions. While the conventions
 take some time to learn, by following the conventions CakePHP provides you can
 avoid needless configuration and make a uniform application structure that makes
-working with various projects a breeze. The :doc:`conventions chapter
+working with various projects simple. The :doc:`conventions chapter
 ` covers the various conventions that CakePHP uses.
 
 
@@ -129,13 +129,17 @@ The typical CakePHP request cycle starts with a user requesting a page or
 resource in your application. At a high level each request goes through the
 following steps:
 
-#. The request is first processed by your routes.
-#. After the request has been routed, the dispatcher will select the
-   correct controller object to handle it.
+#. The webserver rewrite rules direct the request to ``webroot/index.php``.
+#. Your application's autoloader and bootstrap files are executed.
+#. Any :doc:`dispatch filters ` that are
+   configured can handle the request, and optionally generate a response.
+#. The dispatcher selects the appropriate controller & action based on routing rules.
 #. The controller's action is called and the controller interacts with the
    required Models and Components.
 #. The controller delegates response creation to the View to generate the output
    resulting from the model data.
+#. The view uses Helpers and Cells to generate the response body and headers.
+#. The response is sent back to the client.
 
 Just the Start
 ==============
@@ -146,8 +150,7 @@ features in CakePHP are:
 * A :doc:`caching ` framework that integrates with
   Memcache, Redis and other backends.
 * Powerful :doc:`code generation tools
-  ` so you can hit the ground
-  running.
+  ` so you can start immediately.
 * :doc:`Integrated testing framework ` so you can ensure
   your code works perfectly.
 
diff --git a/en/intro/conventions.rst b/en/intro/conventions.rst
index 2affc800c33bad1c8906cc85423e6fe243ac0240..add64190ebae30a36793775ead27a9374df7276f 100644
--- a/en/intro/conventions.rst
+++ b/en/intro/conventions.rst
@@ -98,16 +98,20 @@ Join tables, used in BelongsToMany relationships between models, should be named
 after the model tables they will join, arranged in alphabetical order
 (apples\_zebras rather than zebras\_apples).
 
+Rather than using an auto-increment key as the primary key, you may also use
+char(36). CakePHP will then use a unique 36 character UUID (Text::uuid) whenever
+you save a new record using the ``Table::save()`` method.
+
 View Conventions
 ================
 
 View template files are named after the controller functions they
 display, in an underscored form. The getReady() function of the
 PeopleController class will look for a view template in
-``src/Template/People/get_ready.ctp``.
+**src/Template/People/get_ready.ctp**.
 
 The basic pattern is
-``src/Template/Controller/underscored_function_name.ctp``.
+**src/Template/Controller/underscored_function_name.ctp**.
 
 By naming the pieces of your application using CakePHP conventions,
 you gain functionality without the hassle and maintenance tethers
@@ -115,11 +119,11 @@ of configuration. Here's a final example that ties the conventions
 together:
 
 -  Database table: "people"
--  Table class: "PeopleTable", found at ``src/Model/Table/PeopleTable.php``
--  Entity class: "Person", found at ``src/Model/Entity/Person.php``
+-  Table class: "PeopleTable", found at **src/Model/Table/PeopleTable.php**
+-  Entity class: "Person", found at **src/Model/Entity/Person.php**
 -  Controller class: "PeopleController", found at
-   ``src/Controller/PeopleController.php``
--  View template, found at ``src/Template/People/index.ctp``
+   **src/Controller/PeopleController.php**
+-  View template, found at **src/Template/People/index.ctp**
 
 Using these conventions, CakePHP knows that a request to
 http://example.com/people/ maps to a call on the ``index()`` function
diff --git a/en/intro/where-to-get-help.rst b/en/intro/where-to-get-help.rst
index 940ad0ff31a9ace6ee11cccb968668b87d77ea22..bb4653a9521f6abccf3695cb01b9e5575024a0ef 100644
--- a/en/intro/where-to-get-help.rst
+++ b/en/intro/where-to-get-help.rst
@@ -103,6 +103,10 @@ French
 ------
 - `French CakePHP Community `_
 
+Brazilian Portuguese
+--------------------
+- `Brazilian CakePHP Community `_
+
 
 .. meta::
     :title lang=en: Where to Get Help
diff --git a/en/migrations.rst b/en/migrations.rst
new file mode 100644
index 0000000000000000000000000000000000000000..90e30ef72d595120902f7de5d6785c12d67846b9
--- /dev/null
+++ b/en/migrations.rst
@@ -0,0 +1,392 @@
+Migrations
+##########
+
+Migrations is another plugin supported by the core team that helps you
+do schema changes in your database by writing PHP files that can be tracked
+using your version control system.
+
+It allows you to evolve your database tables over time. Instead of writing
+schema modifications in SQL, this plugin allows you to use an intuitive set
+of methods to implement your database changes.
+
+This plugin is a wrapper for the database migrations library `Phinx `_
+
+Installation
+============
+
+By default Migrations is installed with the default application skeleton. If
+you've removed it and want to re-install it, you can do so by running the
+following from your application's ROOT directory (where composer.json file is
+located)::
+
+        php composer.phar require cakephp/migrations "@stable"
+
+You will need to add the following line to your application's bootstrap.php file::
+
+        Plugin::load('Migrations');
+
+Additionally, you will need to configure the default database configuration in your
+config/app.php file as explained in the :ref:`Database Configuration section `.
+
+Overview
+========
+
+A migration is basically a single PHP file that describes a new 'version' of
+the database. A migration file can create tables, add or remove columns, create
+indexes and even insert data into the database.
+
+Here's an example of a migration::
+
+        class CreateProductsTable extends AbstractMigration
+        {
+            /**
+             * This method gets executed when applying the changes to
+             * the database.
+             *
+             * Changes to the database can also be reverted without any
+             * additional code for non-destructive operations.
+             */
+            public function change()
+            {
+                // create the table
+                $table = $this->table('products');
+                $table->addColumn('name', 'string')
+                      ->addColumn('description', 'text')
+                      ->addColumn('created', 'datetime')
+                      ->create();
+            }
+
+
+This migration adds a table called products with a string column called ``name``, a text
+``description`` column and a column called ``created`` with a datetime type.
+A primary key column called ``id`` will also be added implicitly.
+
+Note that this file describes how the database should look like after applying
+the change, at this point no ``products`` table exist, but we have created
+a file that is both able to create the table with the right column as well as
+to drop it if we rollback the migration.
+
+Once the file has been created in the **config/Migrations** folder, you will be
+able to execute the following command to create the table in your database::
+
+        bin/cake migrations migrate
+
+Creating Migrations
+===================
+
+Migration files are stored in the **config/Migration** directory of your
+application. The name of the migration files are prefixed with the date in
+which they were created, in the format **YYYYMMDDHHMMSS_my_new_migration.php**.
+
+The easiest way of creating a migrations file is by using the command line.
+Let's imagine that you'd like to add a new ``products`` table::
+
+        bin/cake bake migration CreateProducts name:string description:text created modified
+
+The above line will create a migration file looking like this::
+
+        class CreateProductsTable extends AbstractMigration
+        {
+            public function change()
+            {
+                $table = $this->table('products');
+                $table->addColumn('name', 'string')
+                      ->addColumn('description', 'text')
+                      ->addColumn('created', 'datetime')
+                      ->addColumn('modified', 'datetime')
+                      ->create();
+            }
+
+If the migration name in the command line is of the form "AddXXXToYYY" or "RemoveXXXFromYYY"
+and is followed by a list of column names and types then a migration file
+containing the code for creating or dropping the columns will be generated::
+
+        bin/cake bake migration AddPriceToProducts price:decimal
+
+Executing the command line above will generate::
+
+        class AddPriceToProducts extends AbstractMigration
+        {
+            public function change()
+            {
+                $table = $this->table('products');
+                $table->addColumn('price', 'decimal')
+                      ->update();
+            }
+
+It is also possible to add indexes to columns::
+
+        bin/cake bake migration AddNameIndexToProducts name:string:index
+
+will generate::
+
+        class AddNameIndexToProducts extends AbstractMigration
+        {
+            public function change()
+            {
+                $table = $this->table('products');
+                $table->addColumn('name', 'string')
+                      ->addIndex(['name'])
+                      ->update();
+            }
+
+
+When using fields in the command line it may be handy to remember that they
+follow the following pattern::
+
+        field:fieldType:indexType:indexName
+
+For instance, the following are all valid ways of specifying an email field:
+
+* ``email:string:unique``
+* ``email:string:unique:EMAIL_INDEX``
+
+Fields named ``created`` and ``modified`` will automatically be set to the type
+``datetime``.
+
+In the same way, you can generate a migration to remove a column by using the
+command line::
+
+         bin/cake bake migration RemovePriceFromProducts price
+
+creates the file::
+
+        class RemovePriceFromProducts extends AbstractMigration
+        {
+            public function change()
+            {
+                $table = $this->table('products');
+                $table->removeColumn('price');
+            }
+
+Migration Names can follow any of the following patterns:
+
+* Create a table: (``/^(Create)(.*)/``) Creates the specified table.
+* Drop a table: (``/^(Drop)(.*)/``) Drops the specified table. Ignores specified field arguments.
+* Add a field: (``/^(Add).*(?:To)(.*)/``) Adds fields to the specified table.
+* Remove a field: (``/^(Remove).*(?:From)(.*)/``) Removes fields from the specified table.
+* Alter a table:  (``/^(Alter)(.*)/``) Alters the specified table. An alias for CreateTable and AddField.
+
+Field types a those generically made available by the ``Phinx`` library. Those
+can be:
+
+* string
+* text
+* integer
+* biginteger
+* float
+* decimal
+* datetime
+* timestamp
+* time
+* date
+* binary
+* boolean
+* uuid
+
+Additionally you can create an empty migrations file if you want full control
+over what needs to be executed::
+
+        bin/cake migrations create MyCustomMigration
+
+Please make sure you read the official `Phinx documentation `_
+in order to know the complete list of methods you can use for writing migration files.
+
+Generating Migrations From Existing Databases
+---------------------------------------------
+
+If you are dealing with a pre-existing database and want to start using
+migrations, or to version control the initial schema of your application's
+database, you can run the ``migration_snapshot`` command::
+
+        bin/cake bake migration_snapshot Initial
+
+It will generate a migration file called **Initial** containing all the create
+statements for all tables in your database.
+
+Creating Custom Primary Keys
+----------------------------
+
+If you need to avoid the automatic creation of the ``id`` primary key when
+adding new tables to the database, you can use the second argument of the
+``table()`` method::
+
+        class CreateProductsTable extends AbstractMigration
+        {
+            public function change()
+            {
+                $table = $this->table('products', ['id' => false, 'primary_key' => ['id']]);
+                $table
+                      ->addColumn('id', 'uuid')
+                      ->addColumn('name', 'string')
+                      ->addColumn('description', 'text')
+                      ->create();
+            }
+
+The above will create a ``CHAR(36)`` ``id`` column that is also the primary key.
+
+Collations
+----------
+
+If you need to create a table with a different collation than the database
+default one, you can define it with the ``table()`` method, as an option::
+
+        class CreateCategoriesTable extends AbstractMigration
+        {
+            public function change()
+            {
+                $table = $this
+                    ->table('categories', [
+                        'collation' => 'latin1_german1_ci'
+                    ])
+                    ->addColumn('title', 'string', [
+                        'default' => null,
+                        'limit' => 255,
+                        'null' => false,
+                    ])
+                    ->create();
+            }
+
+Note however this can only be done on table creation : there is currently
+no way of adding a column to an existing table with a different collation than
+the table or the database.
+Only ``MySQL`` and ``SqlServer`` supports this configuration key for the time being.
+
+Applying Migrations
+===================
+
+Once you have generated or written your migration file, you need to execute the
+following command to apply the changes to your database::
+
+        bin/cake migrations migrate
+
+To migrate to a specific version then use the --target parameter or -t for short::
+
+        bin/cake migrations migrate -t 20150103081132
+
+That corresponds to the timestamp that is prefixed to the migrations file name.
+
+Reverting Migrations
+====================
+
+The Rollback command is used to undo previous migrations executed by this
+plugin. It is the reverse action of the ``migrate`` command.
+
+You can rollback to the previous migration by using the ``rollback`` command::
+
+        bin/cake migrations rollback
+
+You can also pass a migration version number to rollback to a specific version::
+
+         bin/cake migrations rollback -t 20150103081132
+
+Migrations Status
+=================
+
+The Status command prints a list of all migrations, along with their current status.
+You can use this command to determine which migrations have been run::
+
+        bin/cake migrations status
+
+Marking a migration as migrated
+===============================
+
+.. versionadded:: cakephp/migrations 1.1.0
+
+It can sometimes be useful to mark a migration as migrated without actually running it.
+In order to do this, you can use the ``mark_migrated`` command. This command
+expects the migration version number as argument::
+
+    bin/cake migrations mark_migrated 20150420082532
+
+Note that when you bake a snapshot with the ``cake bake migration_snapshot``
+command, the created migration will automatically be marked as migrated.
+
+Using Migrations In Plugins
+===========================
+
+Plugins can also provide migration files. This makes plugins that are intended
+to be distributed much more portable and easy to install. All commands in the
+Migrations plugin support the ``--plugin`` or ``-p`` option that will scope the
+execution to the migrations relative to that plugin::
+
+        bin/cake migrations status -p PluginName
+
+        bin/cake migrations migrate -p PluginName
+
+
+Running Migrations in a non-shell environment
+=============================================
+
+.. versionadded:: cakephp/migrations 1.2.0
+
+Since the release of version 1.2 of the migrations plugin, you can run
+migrations from a non-shell environment, directly from an app, by using the new
+``Migrations`` class. This can be handy in case you are developing a plugin
+installer for a CMS for instance.
+The ``Migrations`` class allows you to run the following commands from the
+migrations shell :
+
+* migrate
+* rollback
+* markMigrated
+* status
+
+Each of these commands has a method defined in the ``Migrations`` class.
+
+Here is how to use it::
+
+    use Migrations\Migrations;
+
+    $migrations = new Migrations();
+
+    // Will return an array of all migrations and their status
+    $status = $migrations->status();
+
+    // Will return true if success. If an error occurred, an exception will be thrown
+    $migrate = $migrations->migrate();
+
+    // Will return true if success. If an error occurred, an exception will be thrown
+    $rollback = $migrations->rollback();
+
+    // Will return true if success. If an error occurred, an exception will be thrown
+    $markMigrated = $migrations->markMigrated(20150804222900);
+
+The methods can accept an array of parameters that should match options from
+the commands::
+
+    use Migrations\Migrations;
+
+    $migrations = new Migrations();
+
+    // Will return an array of all migrations and their status
+    $status = $migrations->status(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+You can pass any options the shell commands would take.
+The only exception is the ``markMigrated`` command which is expecting the
+version number of the migrations to mark as migrated as first argument. Pass
+the array of parameters as the second argument for this method.
+
+Optionally, you can pass these parameters in the constructor of the class.
+They will be used as default and this will prevent you from having to pass
+them on each method call::
+
+    use Migrations\Migrations;
+
+    $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+    // All the following calls will be done with the parameters passed to the Migrations class constructor
+    $status = $migrations->status();
+    $migrate = $migrations->migrate();
+
+If you need to override one or more default parameters for one call, you can
+pass them to the method::
+
+    use Migrations\Migrations;
+
+    $migrations = new Migrations(['connection' => 'custom', 'source' => 'MyMigrationsFolder']);
+
+    // This call will be made with the "custom" connection
+    $status = $migrations->status();
+    // This one with the "default" connection
+    $migrate = $migrations->migrate(['connection' => 'default']);
diff --git a/en/orm.rst b/en/orm.rst
index 15141a6503f29dbce3c6423b76dd8946e3c31fcf..c595f293fd31649e02ed46be8ad5fe8d043eaf41 100644
--- a/en/orm.rst
+++ b/en/orm.rst
@@ -1,18 +1,17 @@
-Models
-######
+Database Access & ORM
+#####################
 
-Models are the classes that sit as the business layer in your application.
-This means that they should be responsible for managing almost everything
-that happens regarding your data, its validity, interactions and evolution
-of the information workflow in your domain of work.
-
-In CakePHP your application's domain model gets split into 2 primary object
+In CakePHP working with data through the database is done with two primary object
 types. The first are **repositories** or **table objects**. These objects
 provide access to collections of data. They allow you to save new records,
 modify/delete existing ones, define relations, and perform bulk operations. The
 second type of objects are **entities**. Entities represent individual records
 and allow you to define row/record level behavior & functionality.
 
+These two classes are usually responsible for managing almost everything
+that happens regarding your data, its validity, interactions and evolution
+of the information workflow in your domain of work.
+
 CakePHP's built-in ORM specializes in relational databases, but can be extended
 to support alternative datasources.
 
@@ -44,11 +43,11 @@ example if we wanted to load some data from our ``articles`` table we could do::
     }
 
 Note that we didn't have to create any code or wire any configuration up.
-The conventions in CakePHP allow us to skip some boilerplate code, and allow the
+The conventions in CakePHP allow us to skip some boilerplate code and allow the
 framework to insert base classes when your application has not created
 a concrete class. If we wanted to customize our ArticlesTable class adding some
 associations or defining some additional methods we would add the following to
-``src/Model/Table/ArticlesTable.php`` after the `` true]``
 - **joinType**: the type of the join to use in the SQL query, default
-  is INNER. You may want to use LEFT if your hasOne association is optional.
+  is LEFT. You can use INNER if your hasOne association is always present.
 - **dependent**: When the dependent key is set to ``true``, and an
   entity is deleted, the associated model records are also deleted. In this
   case we set it to ``true`` so that deleting a User will also delete her associated
@@ -272,10 +275,13 @@ Possible keys for belongsTo association arrays include:
 - **className**: the class name of the model being associated to
   the current model. If you're defining a 'Profile belongsTo User'
   relationship, the className key should equal 'Users'.
-- **foreignKey**: the name of the foreign key found in the current model. This
+- **foreignKey**: the name of the foreign key found in the current table. This
   is especially handy if you need to define multiple belongsTo relationships to
   the same model. The default value for this key is the underscored, singular
   name of the other model, suffixed with ``_id``.
+- **bindingKey**: The name of the column in the other table, that will be used
+  for matching the ``foreignKey``. If not specified, the primary key (for example
+  the id column of the ``Users`` table) will be used.
 - **conditions**: an array of find() compatible conditions or SQL
   strings such as ``['Users.active' => true]``
 - **joinType**: the type of the join to use in the SQL query, default
@@ -355,10 +361,13 @@ Possible keys for hasMany association arrays include:
   the current model. If you're defining a 'User hasMany Comment'
   relationship, the className key should equal 'Comment'.
 - **foreignKey**: the name of the foreign key found in the other
-  model. This is especially handy if you need to define multiple
+  table. This is especially handy if you need to define multiple
   hasMany relationships. The default value for this key is the
   underscored, singular name of the actual model, suffixed with
   '\_id'.
+- **bindingKey**: The name of the column in the current table, that will be used
+  for matching the ``foreignKey``. If not specified, the primary key (for example
+  the id column of the ``Articles`` table) will be used.
 - **conditions**: an array of find() compatible conditions or SQL
   strings such as ``['Comments.visible' => true]``
 - **sort**  an array of find() compatible order clauses or SQL
@@ -373,7 +382,7 @@ Possible keys for hasMany association arrays include:
 - **propertyName**: The property name that should be filled with data from the
   associated table into the source table results. By default this is the
   underscored & plural name of the association so ``comments`` in our example.
-- **strategy**: Defines the query strategy to use. Defaults to 'SELECT'. The other
+- **strategy**: Defines the query strategy to use. Defaults to 'select'. The other
   valid value is 'subquery', which replaces the ``IN`` list with an equivalent
   subquery.
 - **finder**: The finder method to use when loading associated records.
@@ -405,6 +414,11 @@ given article is often cached to make generating lists of articles more
 efficient. You can use the :doc:`CounterCacheBehavior
 ` to cache counts of associated records.
 
+You should make sure that your database tables do not contain columns that match
+association property names. If for example you have counter fields that conflict
+with association properties, you must either rename the association property, or
+the column name.
+
 BelongsToMany Associations
 ==========================
 
@@ -483,6 +497,8 @@ Possible keys for belongsToMany association arrays include:
   conditions on an associated table, you should use a 'through' model, and
   define the necessary belongsTo associations on it.
 - **sort** an array of find() compatible order clauses.
+- **dependent**: When the dependent key is set to ``false``, and an entity is
+  deleted, the data of the join table will not be deleted.
 - **through** Allows you to provide a either the name of the Table instance you
   want used on the join table, or the instance itself. This makes customizing
   the join table keys possible, and allows you to customize the behavior of the
@@ -495,7 +511,7 @@ Possible keys for belongsToMany association arrays include:
 - **propertyName**: The property name that should be filled with data from the
   associated table into the source table results. By default this is the
   underscored & plural name of the association, so ``tags`` in our example.
-- **strategy**: Defines the query strategy to use. Defaults to 'SELECT'. The
+- **strategy**: Defines the query strategy to use. Defaults to 'select'. The
   other valid value is 'subquery', which replaces the ``IN`` list with an
   equivalent subquery.
 - **saveStrategy**: Either 'append' or 'replace'. Indicates the mode to be used
@@ -533,6 +549,8 @@ generated::
       AND article_id IN (SELECT id FROM articles)
     );
 
+.. _using-the-through-option:
+
 Using the 'through' Option
 --------------------------
 
@@ -602,17 +620,15 @@ Default Association Conditions
 The ``finder`` option allows you to use a :ref:`custom finder
 ` to load associated record data. This lets you encapsulate
 your queries better and keep your code DRY'er. There are some limitations when
-using finders to load associated records for associations that are loaded using
+using finders to load data in associations that are loaded using
 joins (belongsTo/hasOne). Only the following aspects of the query will be
 applied to the root query:
 
-- WHERE conditions
-- Additional joins
-- Contained associations
-- Map/Reduce functions
-- Result formatters
+- WHERE conditions.
+- Additional joins.
+- Contained associations.
 
 Other aspects of the query, such as selected columns, order, group by, having and
 other sub-statements, will not be applied to the root query. Associations that
 are *not* loaded through joins (hasMany/belongsToMany), do not have the above
-restrictions.
+restrictions and can also use result formatters or map/reduce functions.
diff --git a/en/orm/behaviors.rst b/en/orm/behaviors.rst
index c23278eed63a599803188a374746f0ba28871323..379bee58437b411f76ff86ecd5d005b814255cc5 100644
--- a/en/orm/behaviors.rst
+++ b/en/orm/behaviors.rst
@@ -41,7 +41,7 @@ This behavior will allow us to populate a slug field with the results of
 Before we create our behavior we should understand the conventions for
 behaviors:
 
-- Behavior files are located in ``src/Model/Behavior``, or
+- Behavior files are located in **src/Model/Behavior**, or
   ``MyPlugin\Model\Behavior``.
 - Behavior classes should be in the ``App\Model\Behavior`` namespace, or
   ``MyPlugin\Model\Behavior`` namespace.
@@ -49,7 +49,7 @@ behaviors:
 - Behaviors extend ``Cake\ORM\Behavior``.
 
 To create our sluggable behavior. Put the following into
-``src/Model/Behavior/SluggableBehavior.php``::
+**src/Model/Behavior/SluggableBehavior.php**::
 
     namespace App\Model\Behavior;
 
@@ -117,9 +117,9 @@ public methods as mixin methods. In these cases you can use the
 ``implementedMethods`` configuration key to rename or exclude mixin methods. For
 example if we wanted to prefix our slug() method we could do the following::
 
-    public $_defaultConfig = [
+    protected $_defaultConfig = [
         'implementedMethods' => [
-            'slug' => 'superSlug',
+            'superSlug' => 'slug',
         ]
     ];
 
@@ -134,7 +134,7 @@ rename/remove mixin methods when adding a behavior to a table. For example::
     // In a table's initialize() method.
     $this->addBehavior('Sluggable', [
         'implementedMethods' => [
-            'slug' => 'superSlug',
+            'superSlug' => 'slug',
         ]
     ]);
 
@@ -220,7 +220,7 @@ these cases you can use the ``implementedFinders`` configuration key to rename
 or exclude finder methods. For example if we wanted to rename our ``find(slug)``
 method we could do the following::
 
-    public $_defaultConfig = [
+    protected $_defaultConfig = [
         'implementedFinders' => [
             'slugged' => 'findSlug',
         ]
@@ -241,6 +241,13 @@ rename/remove finder methods when adding a behavior to a table. For example::
         ]
     ]);
 
+Removing Loaded Behaviors
+=========================
+
+To remove a behavior from your table you can call the ``removeBehavior()`` method::
+
+    // Remove the loaded behavior
+    $this->removeBehavior('Sluggable');
 
 Accessing Loaded Behaviors
 ==========================
diff --git a/en/orm/behaviors/counter-cache.rst b/en/orm/behaviors/counter-cache.rst
index 53897c4298a71620938c7316ac241256f7cbef1c..55b1dfd2c70d4b2ce2c80c757239604e9bd32914 100644
--- a/en/orm/behaviors/counter-cache.rst
+++ b/en/orm/behaviors/counter-cache.rst
@@ -1,5 +1,5 @@
-CounterCache Behavior
-#####################
+CounterCache
+############
 
 .. php:namespace:: Cake\ORM\Behavior
 
@@ -9,7 +9,9 @@ Often times web applications need to display counts of related objects. For
 example, when showing a list of articles you may want to display how many
 comments it has. Or when showing a user you might want to show how many
 friends/followers she has. The CounterCache behavior is intended for these
-situations.
+situations. CounterCache will update a field in the associated models assigned
+in the options when it is invoked. The fields should exist in the database and
+be of the type INT.
 
 Basic Usage
 ===========
@@ -48,7 +50,7 @@ counter value::
     $this->addBehavior('CounterCache', [
         'Articles' => [
             'comment_count' => [
-                'findType' => 'published'
+                'finder' => 'published'
             ]
         ]
     ]);
@@ -64,6 +66,17 @@ to find records instead::
         ]
     ]);
 
+If you want CounterCache to update multiple fields, for example both showing a
+conditional count and a basic count you can add these fields in the array::
+
+    $this->addBehavior('CounterCache', [
+        'Articles' => ['comment_count',
+            'published_comment_count' => [
+                'finder' => 'published'
+            ]
+        ]
+    ]);
+
 Lastly, if a custom finder and conditions are not suitable you can provide
 a callback method. This callable must return the count value to be stored::
 
@@ -74,3 +87,16 @@ a callback method. This callable must return the count value to be stored::
             }
         ]
     ]);
+
+
+.. note::
+
+    The CounterCache behavior works for ``belongsTo`` associations only. For
+    example for "Comments belongsTo Articles", you need to add the CounterCache
+    behavior to the ``CommentsTable`` in order to generate ``comment_count`` for
+    Articles table.
+    
+    It is possible though to make this work for ``belongsToMany`` associations.
+    You need to enable the CounterCache behavior in a custom ``through`` table
+    configured in association options. See how to configure a custom join table
+    :ref:`using-the-through-option`.
diff --git a/en/orm/behaviors/timestamp.rst b/en/orm/behaviors/timestamp.rst
index 34497cdb718a9e5920f21dd63632bea99b287207..96091340fc0794cef628472e19528aa87e5e7e56 100644
--- a/en/orm/behaviors/timestamp.rst
+++ b/en/orm/behaviors/timestamp.rst
@@ -1,5 +1,5 @@
-Timestamp Behavior
-##################
+Timestamp
+#########
 
 .. php:namespace:: Cake\ORM\Behavior
 
diff --git a/en/orm/behaviors/translate.rst b/en/orm/behaviors/translate.rst
index 4f373111db687561005f554136adc138d752dd2e..5209169fc8245b324015e4de37ca243b2473f03b 100644
--- a/en/orm/behaviors/translate.rst
+++ b/en/orm/behaviors/translate.rst
@@ -103,7 +103,7 @@ manually running the following SQL script in your database:
 Attaching the Translate Behavior to Your Tables
 ===============================================
 
-Attaching the behavior can be done in the ``initialize`` method in your Table
+Attaching the behavior can be done in the ``initialize()`` method in your Table
 class::
 
     class ArticlesTable extends Table
@@ -127,7 +127,6 @@ repository, you can specify it in the behavior's configuration. This is common
 when you have multiple tables to translate and you want a cleaner separation
 of the data that is stored for each different table::
 
-
     class Articles extends Table
     {
 
@@ -146,7 +145,7 @@ You need to make sure that any custom table you use has the columns ``field``,
 Reading Translated Content
 ==========================
 
-As shown above you can use the ``locale`` method to choose the active
+As shown above you can use the ``locale()`` method to choose the active
 translation for entities that are loaded::
 
     I18n::locale('spa');
@@ -218,6 +217,30 @@ set of records::
     $spanishTranslation = $article->translation('spa');
     $englishTranslation = $article->translation('eng');
 
+Preventing Retrieval of Empty Translations
+------------------------------------------
+
+Translation records can contain any string, if a record has been translated
+and stored as an empty string ('') the translate behavior will take and use
+this to overwrite the original field value.
+
+If this is undesired, you can ignore translations which are empty using the
+``allowEmptyTranslations`` config key::
+
+    class Articles extends Table
+    {
+
+        public function initialize(array $config)
+        {
+            $this->addBehavior('Translate', [
+                'fields' => ['title', 'body'],
+                'allowEmptyTranslations' => false
+            ]);
+        }
+    }
+
+The above would only load translated data that had content.
+
 Retrieving All Translations For Associations
 --------------------------------------------
 
@@ -242,7 +265,7 @@ Retrieving one language without using I18n::locale
 
 calling ``I18n::locale('spa');`` changes the default locale for all translated
 finds, there may be times you wish to retrieve translated content without modifying
-the application's state. For these scenarios use the behavior ``locale`` method::
+the application's state. For these scenarios use the behavior ``locale()`` method::
 
     I18n::locale('eng'); // reset for illustration
     $articles = TableRegistry::get('Articles');
diff --git a/en/orm/behaviors/tree.rst b/en/orm/behaviors/tree.rst
index dcc1b721c5539b54a21dc5b905e6381833a2a77a..c1bd84de261799345e507e6ec2d6808ccb8b7ba0 100644
--- a/en/orm/behaviors/tree.rst
+++ b/en/orm/behaviors/tree.rst
@@ -1,5 +1,5 @@
-TreeBehavior
-############
+Tree
+####
 
 .. php:namespace:: Cake\ORM\Behavior
 
@@ -24,8 +24,8 @@ Requirements
 This behavior requires the following columns in your table:
 
 - ``parent_id`` (nullable) The column holding the ID of the parent row
-- ``lft`` (integer) Used to maintain the tree structure
-- ``rght`` (integer) Used to maintain the tree structure
+- ``lft`` (integer, signed) Used to maintain the tree structure
+- ``rght`` (integer, signed) Used to maintain the tree structure
 
 You can configure the name of those fields should you need to customize them.
 More information on the meaning of the fields and how they are used can be found
@@ -108,6 +108,23 @@ The output will be similar to::
     __National
     __International
 
+The ``treeList`` finder takes a number of options:
+
+* ``keyPath``: A dot separated path to fetch the field to use for the array key,
+  or a closure to return the key out of the provided row.
+* ``valuePath``: A dot separated path to fetch the field to use for the array
+  value, or a closure to return the value out of the provided row.
+* ``spacer``: A string to be used as prefix for denoting the depth in the tree
+  for each item
+
+An example of all options in use is::
+
+    $query = $categories->find('treeList', [
+        'keyPath' => 'url',
+        'valuePath' => 'id',
+        'spacer' => ' '
+    ]);
+
 One very common task is to find the tree path from a particular node to the root
 of the tree. This is useful, for example, for adding the breadcrumbs list for
 a menu structure::
@@ -144,12 +161,26 @@ schema, you can provide aliases for them::
     public function initialize(array $config)
     {
         $this->addBehavior('Tree', [
-            'parent' => 'ancestor_id', // Use this instead of parent_id,
+            'parent' => 'ancestor_id', // Use this instead of parent_id
             'left' => 'tree_left', // Use this instead of lft
             'right' => 'tree_right' // Use this instead of rght
         ]);
     }
 
+Node Level (Depth)
+==================
+
+Knowing the depth of tree nodes can be useful when you want to retrieve nodes
+only upto a certain level for e.g. when generating menus. You can use the
+``level`` option to specify the field that will save level of each node::
+
+    $this->addBehavior('Tree', [
+        'level' => 'level', // Defaults to null, i.e. no level saving
+    ]);
+
+If you don't want to cache the level using a db field you can use
+``TreeBehavior::getLevel()`` method to get level of a node.
+
 Scoping and Multi Trees
 =======================
 
@@ -217,7 +248,7 @@ the tree) is trivial::
     $categoriesTable->delete($aCategory);
 
 The TreeBehavior will take care of all internal deleting operations for you. It
-is also possible to Only delete one node and re-assign all children to the
+is also possible to only delete one node and re-assign all children to the
 immediately superior parent node in the tree::
 
     $aCategory = $categoriesTable->get(10);
@@ -225,3 +256,21 @@ immediately superior parent node in the tree::
     $categoriesTable->delete($aCategory);
 
 All children nodes will be kept and a new parent will be assigned to them.
+
+The deletion of a node is based off of the lft and rght values of the entity. This
+is important to note when looping through the various children of a node for
+conditional deletes::
+
+    $descendants = $teams->find('children', ['for' => 1]);
+    
+    foreach ($descendants as $descendant) {
+        $team = $teams->get($descendant->id); // search for the up-to-date entity object
+        if ($team->expired) {
+            $teams->delete($team); // deletion reorders the lft and rght of database entries
+        }
+    }
+    
+The TreeBehavior reorders the lft and rght values of records in the table when a node
+is deleted. As such, the lft and rght values of the entities inside ``$descendants``
+(saved before the delete operation) will be inaccurate. Entities will have to be loaded
+and modified on the fly to prevent inconsistencies in the table.
diff --git a/en/orm/database-basics.rst b/en/orm/database-basics.rst
index d33dc337bc88a30471e12c0e59b7e82347fd09b2..9d5f9c671ef679ef2a5c34f144036e3d77cf3e25 100644
--- a/en/orm/database-basics.rst
+++ b/en/orm/database-basics.rst
@@ -1,20 +1,125 @@
 Database Basics
 ###############
 
-The ORM and database access in CakePHP has been totally rebuilt for 3.0.
-It features a new fluent API for building queries, improved schema
-reflection/generation, a flexible type system and more.
+The CakePHP database access layer abstracts and provides help with most aspects
+of dealing with relational databases such as, keeping connections to the server,
+building queries, preventing SQL injections, inspecting and altering schemas,
+and with debugging and profiling queries sent to the database.
+
+Quick Tour
+==========
+
+The functions described in this chapter illustrate what is possible to do with
+the lower-level database access API. If instead you want to learn more about the
+complete ORM, you can read the :doc:`/orm/query-builder` and
+:doc:`/orm/table-objects` sections.
+
+The easiest way to create a database connection is using a ``DSN`` string::
+
+    use Cake\Datasource\ConnectionManager;
+
+    $dsn = 'mysql://root:password@localhost/my_database';
+    ConnectionManager::config('default', ['url' => $dsn]);
+
+Once created, you can access the connection object to start using it::
+
+    $connection = ConnectionManager::get('default');
+
+Supported Databases
+-------------------
+
+CakePHP supports the following relational database servers:
+
+* MySQL 5.1+
+* SQLite 3
+* PostgreSQL 8+
+* SQLServer 2008+
+
+You will need the correct PDO extension installed for each of the above database
+drivers. Procedural API's are not supported.
+
+.. _running-select-statements:
+
+Running Select Statements
+-------------------------
+
+Running raw SQL queries is a breeze::
+
+    use Cake\Datasource\ConnectionManager;
+
+    $connection = ConnectionManager::get('default');
+    $results = $connection->execute('SELECT * FROM articles')->fetchAll('assoc');
+
+You can use prepared statements to insert parameters::
+
+    $results = $connection
+        ->execute('SELECT * FROM articles WHERE id = :id', ['id' => 1])
+        ->fetchAll('assoc');
+
+It is also possible to use complex data types as arguments::
+
+    $results = $connection
+        ->execute(
+            'SELECT * FROM articles WHERE created >= :created',
+            ['created' => DateTime('1 day ago')],
+            ['created' => 'datetime']
+        )
+        ->fetchAll('assoc');
+
+Instead of writing the SQL manually, you can use the query builder::
+
+    $results = $connection
+        ->newQuery()
+        ->select('*')
+        ->from('articles')
+        ->where(['created >' => new DateTime('1 day ago'), ['created' => 'datetime']])
+        ->order(['title' => 'DESC'])
+        ->execute()
+        ->fetchAll('assoc');
+
+Running Insert Statements
+-------------------------
+
+Inserting rows in the database is usually a matter of a couple lines::
+
+    use Cake\Datasource\ConnectionManager;
+
+    $connection = ConnectionManager::get('default');
+    $connection->insert('articles', [
+        'title' => 'A New Article',
+        'created' => new DateTime('now')
+    ], ['created' => 'datetime']);
+
+Running Update Statements
+-------------------------
+
+Updating rows in the database is equally intuitive, the following example will
+update the article with **id** 10::
+
+    use Cake\Datasource\ConnectionManager;
+    $connection = ConnectionManager::get('default');
+    $connection->update('articles', ['title' => 'New title'], ['id' => 10]);
+
+Running Delete Statements
+-------------------------
+
+Similarly, the ``delete()`` method is used to delete rows from the database, the
+following example deletes the article with **id** 10::
+
+    use Cake\Datasource\ConnectionManager;
+    $connection = ConnectionManager::get('default');
+    $connection->delete('articles', ['id' => 10]);
 
 .. _database-configuration:
 
 Configuration
 =============
 
-By convention database connections are configured in ``config/app.php``. The
+By convention database connections are configured in **config/app.php**. The
 connection information defined in this file is fed into
 :php:class:`Cake\\Datasource\\ConnectionManager` creating the connection configuration
 your application will be using. Sample connection information can be found in
-``config/app.default.php``. A sample connection configuration would look
+**config/app.default.php**. A sample connection configuration would look
 like::
 
     'Datasources' => [
@@ -112,8 +217,7 @@ ssl_ca
     The file path to the SSL certificate authority. (Only supported by MySQL).
 init
     A list of queries that should be sent to the database server as
-    when the connection is created. This option is only
-    supported by MySQL, PostgreSQL, and SQL Server at this time.
+    when the connection is created.
 log
     Set to ``true`` to enable query logging. When enabled queries will be logged
     at a ``debug`` level with the ``queriesLog`` scope.
@@ -254,9 +358,10 @@ implement the following methods:
 * toPHP
 * toDatabase
 * toStatement
+* marshal
 
 An easy way to fulfill the basic interface is to extend
-:php:class:`Cake\Database\Type`. For example if we wanted to add a JSON type,
+:php:class:`Cake\\Database\\Type`. For example if we wanted to add a JSON type,
 we could make the following type class::
 
     // in src/Database/Type/JsonType.php
@@ -278,6 +383,14 @@ we could make the following type class::
             return json_decode($value, true);
         }
 
+        public function marshal($value)
+        {
+            if (is_array($value) || $value === null) {
+                return $value;
+            }
+            return json_decode($value, true);
+        }
+
         public function toDatabase($value, Driver $driver)
         {
             return json_encode($value);
@@ -293,7 +406,7 @@ we could make the following type class::
 
     }
 
-By default the ``toStatement`` method will treat values as strings which will
+By default the ``toStatement()`` method will treat values as strings which will
 work for our new type. Once we've created our new type, we need to add it into
 the type mapping. During our application bootstrap we should do the following::
 
@@ -304,32 +417,20 @@ the type mapping. During our application bootstrap we should do the following::
 We can then overload the reflected schema data to use our new type, and
 CakePHP's database layer will automatically convert our JSON data when creating
 queries. You can use the custom types you've created by mapping the types in
-your Table's :ref:`_initializeSchema() method `.
-
-.. _parsing-localized-dates:
-
-Parsing Localized Datetime Data
--------------------------------
-
-When accepting localized data, it is nice to accept datetime information in
-a user's localized format. In a controller, or
-:doc:`/development/dispatch-filters` you can configure the Date, Time, and
-DateTime types to parse localized formats::
-
-    use Cake\Database\Type;
-
-    // Enable default locale format parsing.
-    Type::build('datetime')->useLocaleParser();
-
-    // Configure a custom datetime format parser format.
-    Type::build('datetime')->useLocaleParser()->setLocaleFormat('dd-M-y');
-
-    // You can also use IntlDateFormatter constants.
-    Type::build('datetime')->useLocaleParser()
-        ->setLocaleFormat([IntlDateFormatter::SHORT, -1]);
-
-The default parsing format is the same as the default string format.
+your Table's :ref:`_initializeSchema() method `::
+    
+    use Cake\Database\Schema\Table as Schema;
 
+    class WidgetsTable extends Table
+    {
+    
+        protected function _initializeSchema(Schema $schema)
+        {
+            $schema->columnType('widget_prefs', 'json');
+            return $schema;
+        }
+    
+    }
 
 Connection Classes
 ==================
@@ -359,7 +460,7 @@ method is ``query()`` which allows you to run already completed SQL queries::
 
 .. php:method:: execute($sql, $params, $types)
 
-The ``query`` method does not allow for additional parameters. If you need
+The ``query()`` method does not allow for additional parameters. If you need
 additional parameters you should use the ``execute()`` method, which allows for
 placeholders to be used::
 
@@ -382,7 +483,7 @@ abstract type names when creating a query::
 
 This allows you to use rich data types in your applications and properly convert
 them into SQL statements. The last and most flexible way of creating queries is
-to use the :doc:`/orm/query-builder`. This apporach allows you to build complex and
+to use the :doc:`/orm/query-builder`. This approach allows you to build complex and
 expressive queries without having to use platform specific SQL::
 
     $query = $conn->newQuery();
@@ -413,8 +514,8 @@ Using Transactions
 -------------------
 
 The connection objects provide you a few simple ways you do database
-transactions. The most basic way of doing transactions is through the ``begin``,
-``commit`` and ``rollback`` methods, which map to their SQL equivalents::
+transactions. The most basic way of doing transactions is through the ``begin()``,
+``commit()`` and ``rollback()`` methods, which map to their SQL equivalents::
 
     $conn->begin();
     $conn->execute('UPDATE posts SET published = ? WHERE id = ?', [true, 2]);
@@ -424,7 +525,7 @@ transactions. The most basic way of doing transactions is through the ``begin``,
 .. php:method:: transactional(callable $callback)
 
 In addition to this interface connection instances also provide the
-``transactional`` method which makes handling the begin/commit/rollback calls
+``transactional()`` method which makes handling the begin/commit/rollback calls
 much simpler::
 
     $conn->transactional(function ($conn) {
@@ -475,7 +576,7 @@ Binding Values
 --------------
 
 Once you've created a prepared statement, you may need to bind additional data.
-You can bind multiple values at once using the ``bind`` method, or bind
+You can bind multiple values at once using the ``bind()`` method, or bind
 individual elements using ``bindValue``::
 
     $stmt = $conn->prepare(
@@ -666,3 +767,8 @@ You can also configure the metadata caching at runtime with the
 
 CakePHP also includes a CLI tool for managing metadata caches. See the
 :doc:`/console-and-shells/orm-cache` chapter for more information.
+
+
+.. meta::
+    :title lang=en: Database Basics
+    :keywords lang=en: SQL,MySQL,MariaDB,PostGres,Postgres,postgres,PostgreSQL,PostGreSQL,postGreSql,select,insert,update,delete,statement,configuration,connection,database,data,types,custom,,executing,queries,transactions,prepared,statements,binding,fetching,row,count,error,codes,query,logging,identifier,quoting,metadata,caching
diff --git a/en/orm/deleting-data.rst b/en/orm/deleting-data.rst
index 47b89263e9aadd3898e43e38e0d986e2d289458f..da3e96224d53972358bcc38848dd9d92b1a5431c 100644
--- a/en/orm/deleting-data.rst
+++ b/en/orm/deleting-data.rst
@@ -11,8 +11,8 @@ Once you've loaded an entity you can delete it by calling the originating
 table's delete method::
 
     // In a controller.
-    $entity = $articles->get(2);
-    $result = $articles->delete($entity);
+    $entity = $this->Articles->get(2);
+    $result = $this->Articles->delete($entity);
 
 When deleting entities a few things happen:
 
@@ -29,7 +29,7 @@ When deleting entities a few things happen:
 By default all deletes happen within a transaction. You can disable the
 transaction with the atomic option::
 
-    $result = $articles->delete($entity, ['atomic' => false]);
+    $result = $this->Articles->delete($entity, ['atomic' => false]);
 
 Cascading Deletes
 -----------------
diff --git a/en/orm/entities.rst b/en/orm/entities.rst
index aeacd6abc29afd14ae31d3182fd0945d6988dfad..8153e5d321f0e16e460d6a73f11368bf718780e2 100644
--- a/en/orm/entities.rst
+++ b/en/orm/entities.rst
@@ -18,7 +18,7 @@ Creating Entity Classes
 
 You don't need to create entity classes to get started with the ORM in CakePHP.
 However, if you want to have custom logic in your entities you will need to
-create classes. By convention entity classes live in ``src/Model/Entity/``. If
+create classes. By convention entity classes live in **src/Model/Entity/**. If
 our application had an ``articles`` table we could create the following entity::
 
     // src/Model/Entity/Article.php
@@ -37,12 +37,47 @@ articles table, we'll get instances of this class.
 
     If you don't define an entity class CakePHP will use the basic Entity class.
 
+Creating Entities
+=================
+
+Entities can be directly instantiated::
+
+    use App\Model\Entity\Article;
+
+    $article = new Article();
+
+When instantiating an entity you can pass the properties with the data you want
+to store in them::
+
+    use App\Model\Entity\Article;
+
+    $article = new Article([
+        'id' => 1,
+        'title' => 'New Article',
+        'created' => new DateTime('now')
+    ]);
+
+Another way of getting new entities is using the ``newEntity()`` method from the
+``Table`` objects::
+
+    use Cake\ORM\TableRegistry;
+
+    $article = TableRegistry::get('Articles')->newEntity();
+    $article = TableRegistry::get('Articles')->newEntity([
+        'id' => 1,
+        'title' => 'New Article',
+        'created' => new DateTime('now')
+    ]);
+
 Accessing Entity Data
 =====================
 
 Entities provide a few ways to access the data they contain. Most commonly you
 will access the data in an entity using object notation::
 
+    use App\Model\Entity\Article;
+
+    $article = new Article;
     $article->title = 'This is my first post';
     echo $article->title;
 
@@ -86,8 +121,9 @@ are read or set. For example::
 
 Accessors use the convention of ``_get`` followed by the CamelCased version of
 the field name. They receive the basic value stored in the ``_properties`` array
-as their only argument. You can customize how properties get set by defining
-a mutator::
+as their only argument. Accessors will be used when saving entities, so be
+careful when defining methods that format data, as the formatted data will be
+persisted. You can customize how properties get set by defining a mutator::
 
     namespace App\Model\Entity;
 
@@ -113,6 +149,8 @@ you easily convert properties as they are set, or create calculated data.
 Mutators and accessors are applied when properties are read using object
 notation, or using get() and set().
 
+.. _entities-virtual-properties:
+
 Creating Virtual Properties
 ---------------------------
 
@@ -171,6 +209,16 @@ You can also check for changes to any property in the entity::
     // See if the entity has changed
     $article->dirty();
 
+To remove the dirty mark from fields in an entity, you can use the ``clean()``
+method::
+
+    $article->clean();
+
+When creating a new entity, you can avoid the fields from being marked as dirty
+by passing an extra option::
+
+    $article = new Article(['title' => 'New Article'], ['markClean' => true]);
+
 Validation Errors
 =================
 
@@ -199,9 +247,8 @@ Mass Assignment
 While setting properties to entities in bulk is simple and convenient, it can
 create significant security issues. Bulk assigning user data from the request
 into an entity allows the user to modify any and all columns. When using
-anonymous entity classes CakePHP does not protect against mass-assignment. You
-can easily protect against mass-assignment by using :doc:`/bake` to generate your
-entities.
+anonymous entity classes or creating the entity class with the :doc:`/bake`
+CakePHP does not protect against mass-assignment. 
 
 The ``_accessible`` property allows you to provide a map of properties and
 whether or not they can be mass-assigned. The values ``true`` and ``false``
@@ -237,6 +284,16 @@ fallback behavior if a field is not specifically named::
 
 If the ``*`` property is not defined it will default to ``false``.
 
+Avoiding Mass Assignment Protection
+-----------------------------------
+
+When creating a new entity using the ``new`` keyword you can tell it to not
+protect itself against mass assignment::
+
+    use App\Model\Entity\Article;
+
+    $article = new Article(['id' => 1, 'title' => 'Foo'], ['guard' => false]);
+
 Modifying the Guarded Fields at Runtime
 ---------------------------------------
 
@@ -254,6 +311,9 @@ method::
     Modifying accessible fields effects only the instance the method is called
     on.
 
+When using the ``newEntity()`` and ``patchEntity()`` methods in the ``Table``
+objects you can customize mass assignment protection with options. Please refer
+to the :ref:`changing-accessible-fields` section for more information.
 
 Bypassing Field Guarding
 ------------------------
@@ -267,6 +327,23 @@ By setting the ``guard`` option to ``false``, you can ignore the accessible fiel
 list for a single call to ``set()``.
 
 
+Checking if an Entity was Persisted
+-----------------------------------
+
+It is often necessary to know if an entity represents a row that is already
+in the database. In those situations use the ``isNew()`` method::
+
+    if (!$article->isNew()) {
+        echo 'This article was saved already!';
+    }
+
+If you are certain that an entity has already been persisted, you can use
+``isNew()`` as a setter::
+
+    $article->isNew(false);
+
+    $article->isNew(true);
+
 .. _lazy-load-associations:
 
 Lazy Loading Associations
@@ -307,7 +384,7 @@ can lazily load associated data::
             $comments = TableRegistry::get('Comments');
             return $comments->find('all')
                 ->where(['article_id' => $this->id])
-                ->all();
+                ->toArray();
         }
 
     }
@@ -324,7 +401,7 @@ Creating Re-usable Code with Traits
 
 You may find yourself needing the same logic in multiple entity classes. PHP's
 traits are a great fit for this. You can put your application's traits in
-``src/Model/Entity``. By convention traits in CakePHP are suffixed with
+**src/Model/Entity**. By convention traits in CakePHP are suffixed with
 ``Trait`` so they are easily discernible from classes or interfaces. Traits are
 often a good compliment to behaviors, allowing you to provide functionality for
 the table and entity objects.
@@ -382,7 +459,7 @@ Exposing Virtual Properties
 By default virtual properties are not exported when converting entities to
 arrays or JSON. In order to expose virtual properties you need to make them
 visible. When defining your entity class you can provide a list of virtual
-fields that should be exposed::
+properties that should be exposed::
 
     namespace App\Model\Entity;
 
@@ -425,7 +502,11 @@ This list can be modified at runtime using ``hiddenProperties``::
 Storing Complex Types
 =====================
 
-Entities are not intended to contain the logic for serializing and
-unserializing complex data coming from the database. Refer to the
-:ref:`saving-complex-types` section to understand how your application can store
-more complex data types like arrays and objects.
+Accessor & Mutator methods on entities are not intended to contain the logic for
+serializing and unserializing complex data coming from the database. Refer to
+the :ref:`saving-complex-types` section to understand how your application can
+store more complex data types like arrays and objects.
+
+.. meta::
+    :title lang=en: Entities
+    :keywords lang=en: entity, entities, single row, individual record
diff --git a/en/orm/query-builder.rst b/en/orm/query-builder.rst
index 2514911d57c46832c057f467c654ca97dbffe388..886316888eae9b7a3276618ab58781b740e9c527 100644
--- a/en/orm/query-builder.rst
+++ b/en/orm/query-builder.rst
@@ -12,26 +12,6 @@ queries using unions and subqueries with ease.
 Underneath the covers, the query builder uses PDO prepared statements which
 protect against SQL injection attacks.
 
-Query objects are lazily evaluated. This means a query is not executed until one
-of the following things occur:
-
-- The query is iterated with ``foreach()``.
-- The query's ``execute()`` method is called. This will return the underlying
-  statement object, and is to be used with insert/update/delete queries.
-- The query's ``first()`` method is called. This will return the first result in the set
-  built by ``SELECT`` (it adds ``LIMIT 1`` to the query).
-- The query's ``all()`` method is called. This will return the result set and
-  can only be used with ``SELECT`` statements.
-- The query's ``toArray()`` method is called.
-
-Until one of these conditions are met, the query can be modified with additional
-SQL being sent to the database. It also means that if a Query hasn't been
-evaluated, no SQL is ever sent to the database. Once executed, modifying and
-re-evaluating a query will result in additional SQL being run.
-
-If you want to take a look at what SQL CakePHP is generating, you can turn
-database :ref:`query logging ` on.
-
 The Query Object
 ================
 
@@ -39,12 +19,38 @@ The easiest way to create a ``Query`` object is to use ``find()`` from a
 ``Table`` object. This method will return an incomplete query ready to be
 modified. You can also use a table's connection object to access the lower level
 Query builder that does not include ORM features, if necessary. See the
-:ref:`database-queries` section for more information. For the remaining
-examples, assume that ``$articles`` is a :php:class:`~Cake\\ORM\\Table`::
+:ref:`database-queries` section for more information::
+
+    use Cake\ORM\TableRegistry;
+    $articles = TableRegistry::get('Articles');
 
     // Start a new query.
     $query = $articles->find();
 
+When inside a controller, you can use the automatic table variable that is
+created using the conventions system::
+
+    // Inside ArticlesController.php
+
+    $query = $this->Articles->find();
+
+Selecting Rows From A Table
+---------------------------
+
+::
+
+    use Cake\ORM\TableRegistry;
+
+    $query = TableRegistry::get('Articles')->find();
+
+    foreach ($query as $article) {
+        debug($article->title);
+    }
+
+For the remaining examples, assume that ``$articles`` is a
+:php:class:`~Cake\\ORM\\Table`. When inside controllers, you can use
+``$this->Articles`` instead of ``$articles``.
+
 Almost every method in a ``Query`` object will return the same query, this means
 that ``Query`` objects are lazy, and will not be executed unless you tell them
 to::
@@ -60,6 +66,10 @@ You can of course chain the methods you call on Query objects::
         ->where(['id !=' => 1])
         ->order(['created' => 'DESC']);
 
+    foreach ($query as $article) {
+        debug($article->created);
+    }
+
 If you try to call ``debug()`` on a Query object, you will see its internal
 state and the SQL that will be executed in the database::
 
@@ -70,54 +80,84 @@ state and the SQL that will be executed in the database::
     // 'sql' => 'SELECT * FROM articles where id = ?'
     // ...
 
-Once you're happy with the Query, you can execute it. The easiest way is to
-either call the ``first()`` or the ``all()`` methods::
+You can execute a query directly without having to use ``foreach`` on it.
+The easiest way is to either call the ``all()`` or ``toArray()`` methods::
 
-    $firstArticle = $articles
+    $resultsIteratorObject = $articles
         ->find()
-        ->where(['id' => 1])
-        ->first();
+        ->where(['id >' => 1])
+        ->all();
 
-    $allResults = $articles
+    foreach ($resultsIteratorObject as $article) {
+        debug($article->id);
+    }
+
+    $resultsArray = $articles
         ->find()
         ->where(['id >' => 1])
-        ->all();
+        ->toArray();
+
+    foreach ($resultsArray as $article) {
+        debug($article->id);
+    }
+
+    debug($resultsArray[0]->title);
 
-In the above example, ``$allResults`` will be an instance of
+In the above example, ``$resultsIteratorObject`` will be an instance of
 ``Cake\ORM\ResultSet``, an object you can iterate and apply several extracting
-and traversing methods on. Often, there is no need to call ``all()``, you are
-allowed to just iterate the Query object to get its results::
+and traversing methods on.
 
-    // Iterate the results
-    foreach ($allResults as $result) {
-     ...
-    }
+Often, there is no need to call ``all()``, you can simply iterate the
+Query object to get its results. Query objects can also be used directly as the
+result object; trying to iterate the query, calling ``toArray()`` or some of the
+methods inherited from :ref:`Collection `, will result in the
+query being executed and results returned to you.
 
-    // That is equivalent to
-    $query = $articles->find()->where(['id' => 1]);
-    foreach ($query as $result) {
-     ...
-    }
+Selecting A Single Row From A Table
+-----------------------------------
 
-Query objects can also be used directly as the result object; trying to iterate the query,
-calling ``toArray`` or some of the methods inherited from :ref:`Collection`,
-will result in the query being executed and results returned to you::
+You can use the ``first()`` method to get the first result in the query::
+
+    $article = $articles
+        ->find()
+        ->where(['id' => 1])
+        ->first();
 
-    // This executes the query and returns an array of results
-    $resultsIntoAnArray = $articles->find()->where(['id >' => 1])->toArray();
+    debug($article->title);
 
-    // Use the combine() method from the collections library
-    // This executes the query
-    $keyValueList = $articles->find()->combine('id', 'title');
+Getting A List Of Values From A Column
+--------------------------------------
+
+::
 
     // Use the extract() method from the collections library
     // This executes the query as well
     $allTitles = $articles->find()->extract('title');
 
+    foreach ($allTitles as $title) {
+        echo $title;
+    }
+
+You can also get a key-value list out of a query result::
+
+    $list = $articles->find('list')->select(['id', 'title']);
+
+    foreach ($list as $id => $title) {
+        echo "$id : $title"
+    }
+
+Queries Are Collection Objects
+------------------------------
+
 Once you get familiar with the Query object methods, it is strongly encouraged
-that you visit the :ref:`Collection` section to improve your skills
-in efficiently traversing the data. In short, it is important to remember that
-anything you can call on a Collection object, you can also do in a Query object::
+that you visit the :ref:`Collection ` section to improve
+your skills in efficiently traversing the data. In short, it is important to
+remember that anything you can call on a Collection object, you can also do in
+a Query object::
+
+    // Use the combine() method from the collections library
+    // This is equivalent to find('list')
+    $keyValueList = $articles->find()->combine('id', 'title');
 
     // An advanced example
     $results = $articles->find()
@@ -130,6 +170,33 @@ anything you can call on a Collection object, you can also do in a Query object:
         ->combine('id', 'trimmedTitle') // combine() is another collection method
         ->toArray(); // Also a collections library method
 
+    foreach ($results as $id => $trimmedTitle) {
+        echo "$id : $trimmedTitle";
+    }
+
+How Are Queries Lazily Evaluated
+--------------------------------
+
+Query objects are lazily evaluated. This means a query is not executed until one
+of the following things occur:
+
+- The query is iterated with ``foreach()``.
+- The query's ``execute()`` method is called. This will return the underlying
+  statement object, and is to be used with insert/update/delete queries.
+- The query's ``first()`` method is called. This will return the first result in the set
+  built by ``SELECT`` (it adds ``LIMIT 1`` to the query).
+- The query's ``all()`` method is called. This will return the result set and
+  can only be used with ``SELECT`` statements.
+- The query's ``toArray()`` method is called.
+
+Until one of these conditions are met, the query can be modified without additional
+SQL being sent to the database. It also means that if a Query hasn't been
+evaluated, no SQL is ever sent to the database. Once executed, modifying and
+re-evaluating a query will result in additional SQL being run.
+
+If you want to take a look at what SQL CakePHP is generating, you can turn
+database :ref:`query logging ` on.
+
 The following sections will show you everything there is to know about using and
 combining the Query object methods to construct SQL statements and extract data.
 
@@ -177,6 +244,17 @@ method::
     $query = $articles->find()
         ->order(['title' => 'ASC', 'id' => 'ASC']);
 
+In addition to ``order``, the ``orderAsc`` and ``orderDesc`` methods can be used
+when you need to sort on complex expressions::
+
+    // As of 3.0.12 orderAsc & orderDesc are available.
+    $query = $articles->find();
+    $concat = $query->newExpr()->func()->concat([
+        'title' => 'literal',
+        'synopsis' => 'literal'
+    ]);
+    $query->orderAsc($concat);
+
 To limit the number of rows or set the row offset you can use the ``limit()``
 and ``page()`` methods::
 
@@ -189,6 +267,31 @@ As you can see from the examples above, all the methods that modify the query
 provide a fluent interface, allowing you to build a query through chained method
 calls.
 
+Selecting All Fields From a Table
+---------------------------------
+
+By default a query will select all fields from a table, the exception is when you
+call the ``select()`` function yourself and pass certain fields::
+
+    // Only select id and title from the articles table
+    $articles->find()->select(['id', 'title']);
+
+If you wish to still select all fields from a table after having called
+``select($fields)``, you can pass the table instance to ``select()`` for this
+purpose::
+
+    // Only all fields from the articles table including
+    // a calculated slug field.
+    $query = $articlesTable->find();
+    $query
+        ->select(['slug' => $query->func()->concat(['title', '-', 'id'])])
+        ->select($articlesTable); // Select all fields from articles
+
+.. versionadded:: 3.1
+    Passing a table object to select() was added in 3.1.
+
+.. _using-sql-functions:
+
 Using SQL Functions
 -------------------
 
@@ -219,6 +322,14 @@ A number of commonly used functions can be created with the ``func()`` method:
   treated as bound parameters unless marked as literal.
 - ``now()`` Take either 'time' or 'date' as an argument allowing you to get
   either the current time, or current date.
+- ``extract()`` Returns the specified date part from the SQL expression.
+- ``dateAdd()`` Add the time unit to the date expression.
+- ``dayOfWeek()`` Returns a FunctionExpression representing a call to SQL
+  WEEKDAY function.
+
+.. versionadded:: 3.1
+
+    ``extract()``, ``dateAdd()`` and ``dayOfWeek()`` methods have been added.
 
 When providing arguments for SQL functions, there are two kinds of parameters
 you can use, literal arguments and bound parameters. Literal parameters allow
@@ -241,8 +352,9 @@ following SQL on MySQL::
 The ``:c0`` value will have the ``' NEW'`` text bound when the query is
 executed.
 
-In addition to the above functions, the ``func()`` method can be used to create any generic SQL function
-such as ``year``, ``date_format``, ``convert``, etc. For example::
+In addition to the above functions, the ``func()`` method can be used to create
+any generic SQL function such as ``year``, ``date_format``, ``convert``, etc.
+For example::
 
     $query = $articles->find();
     $year = $query->func()->year([
@@ -261,6 +373,19 @@ Would result in::
 
     SELECT YEAR(created) as yearCreated, DATE_FORMAT(created, '%H:%i') as timeCreated FROM articles;
 
+You should remember to use the function builder whenever you need to put
+untrusted data into SQL functions or stored procedures::
+
+    // Use a stored procedure
+    $query = $articles->find();
+    $lev = $query->func()->levenshtein([$search, 'LOWER(title)' => 'literal']);
+    $query->where(function ($exp) use ($lev) {
+        return $exp->between($lev, 0, $tolerance);
+    });
+
+    // Generated SQL would be
+    WHERE levenshtein(:c0, lower(street)) BETWEEN :c1 AND :c2
+
 Aggregates - Group and Having
 -----------------------------
 
@@ -275,20 +400,6 @@ When using aggregate functions like ``count`` and ``sum`` you may want to use
     ->group('published_date')
     ->having(['count >' => 3]);
 
-Disabling Hydration
--------------------
-
-While ORMs and object result sets are powerful, hydrating entities is sometimes
-unnecessary. For example, when accessing aggregated data, building an Entity may
-not make sense. In these situations you may want to disable entity hydration::
-
-    $query = $articles->find();
-    $query->hydrate(false);
-
-.. note::
-
-    When hydration is disabled results will be returned as basic arrays.
-
 Case statements
 ---------------
 
@@ -314,6 +425,58 @@ To do this with the query builder, we'd use the following code::
     ])
     ->group('published');
 
+The ``addCase`` function can also chain together multiple statements to create ``if .. then .. [elseif .. then .. ] [ .. else ]`` logic inside your SQL.
+
+If we wanted to classify cities into SMALL, MEDIUM, or LARGE based on population size, we could do the following::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->addCase(
+                [
+                    $q->newExpr()->lt('population', 100000),
+                    $q->newExpr()->between('population', 100000, 999000),
+                    $q->newExpr()->gte('population', 999001),
+                ],
+                ['SMALL',  'MEDIUM', 'LARGE'], # values matching conditions
+                ['string', 'string', 'string'] # type of each value
+            );
+        });
+    # WHERE CASE
+    #   WHEN population < 100000 THEN 'SMALL'
+    #   WHEN population BETWEEN 100000 AND 999000 THEN 'MEDIUM'
+    #   WHEN population >= 999001 THEN 'LARGE'
+    #   END
+
+Any time there are fewer case conditions than values, ``addCase`` will
+automatically produce an ``if .. then .. else`` statement::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->addCase(
+                [
+                    $q->newExpr()->eq('population', 0),
+                ],
+                ['DESERTED', 'INHABITED'], # values matching conditions
+                ['string', 'string'] # type of each value
+            );
+        });
+    # WHERE CASE
+    #   WHEN population = 0 THEN 'DESERTED' ELSE 'INHABITED' END
+
+Disabling Hydration
+-------------------
+
+While ORMs and object result sets are powerful, hydrating entities is sometimes
+unnecessary. For example, when accessing aggregated data, building an Entity may
+not make sense. In these situations you may want to disable entity hydration::
+
+    $query = $articles->find();
+    $query->hydrate(false);
+
+.. note::
+
+    When hydration is disabled results will be returned as basic arrays.
+
 .. _advanced-query-conditions:
 
 Advanced Conditions
@@ -500,18 +663,115 @@ Which will generate the following SQL looking like::
 When using the expression objects you can use the following methods to create
 conditions:
 
-- ``eq()`` Creates an equality condition.
-- ``notEq()`` Create an inequality condition
-- ``like()`` Create a condition using the ``LIKE`` operator.
-- ``notLike()`` Create a negated ``LIKE`` condition.
-- ``in()`` Create a condition using ``IN``.
-- ``notIn()`` Create a negated condition using ``IN``.
-- ``gt()`` Create a ``>`` condition.
-- ``gte()`` Create a ``>=`` condition.
-- ``lt()`` Create a ``<`` condition.
-- ``lte()`` Create a ``<=`` condition.
-- ``isNull()`` Create an ``IS NULL`` condition.
-- ``isNotNull()`` Create a negated ``IS NULL`` condition.
+- ``eq()`` Creates an equality condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->eq('population', '10000');
+        });
+    # WHERE population = 10000
+
+- ``notEq()`` Creates an inequality condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->notEq('population', '10000');
+        });
+    # WHERE population != 10000
+
+- ``like()`` Creates a condition using the ``LIKE`` operator::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->like('name', '%A%');
+        });
+    # WHERE name LIKE "%A%"
+
+- ``notLike()`` Creates a negated ``LIKE`` condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->notLike('name', '%A%');
+        });
+    # WHERE name NOT LIKE "%A%"
+
+- ``in()`` Create a condition using ``IN``::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->in('country_id', ['AFG', 'USA', 'EST']);
+        });
+    # WHERE country_id IN ('AFG', 'USA', 'EST')
+
+- ``notIn()`` Create a negated condition using ``IN``::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->notIn('country_id', ['AFG', 'USA', 'EST']);
+        });
+    # WHERE country_id NOT IN ('AFG', 'USA', 'EST')
+
+- ``gt()`` Create a ``>`` condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->gt('population', '10000');
+        });
+    # WHERE population > 10000
+
+- ``gte()`` Create a ``>=`` condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->gte('population', '10000');
+        });
+    # WHERE population >= 10000
+
+- ``lt()`` Create a ``<`` condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->lt('population', '10000');
+        });
+    # WHERE population < 10000
+
+- ``lte()`` Create a ``<=`` condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->lte('population', '10000');
+        });
+    # WHERE population <= 10000
+
+- ``isNull()`` Create an ``IS NULL`` condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->isNull('population');
+        });
+    # WHERE (population) IS NULL
+
+- ``isNotNull()`` Create a negated ``IS NULL`` condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->isNotNull('population');
+        });
+    # WHERE (population) IS NOT NULL
+
+- ``between()`` Create a ``BETWEEN`` condition::
+
+    $query = $cities->find()
+        ->where(function ($exp, $q) {
+            return $exp->between('population', 999, 5000000);
+        });
+    # WHERE population BETWEEN 999 AND 5000000,
+
+.. warning::
+
+    The field name used in expressions should **never** contain untrusted content.
+    See the :ref:`using-sql-functions` section for how to safely include
+    untrusted data into function calls.
 
 Automatically Creating IN Clauses
 ---------------------------------
@@ -551,7 +811,8 @@ the ``IS`` operator to automatically create the correct expression::
         ->where(['parent_id IS' => $parentId]);
 
 
-The above will create ``parent_id` = :c1`` or ``parent_id IS NULL`` depending on the type of ``$parentId``
+The above will create ``parent_id` = :c1`` or ``parent_id IS NULL`` depending on
+the type of ``$parentId``
 
 Automatic IS NOT NULL Creation
 ------------------------------
@@ -563,7 +824,8 @@ the ``IS NOT`` operator to automatically create the correct expression::
         ->where(['parent_id IS NOT' => $parentId]);
 
 
-The above will create ``parent_id` != :c1`` or ``parent_id IS NOT NULL`` depending on the type of ``$parentId``
+The above will create ``parent_id` != :c1`` or ``parent_id IS NOT NULL``
+depending on the type of ``$parentId``
 
 Raw Expressions
 ---------------
@@ -728,6 +990,8 @@ to fetch associated data from other tables is called **eager loading**.
     :start-after: start-contain
     :end-before: end-contain
 
+.. _adding-joins:
+
 Adding Joins
 ------------
 
@@ -801,6 +1065,23 @@ SQL. In addition to ``join()`` you can use ``rightJoin()``, ``leftJoin()`` and
         ],
         ['Authors.promoted' => 'boolean', 'Authors.created' => 'datetime']);
 
+It should be noted that if you set the ``quoteIdentifiers`` option to ``true`` when
+defining your ``Connection``, join conditions between table fields should be set as follow::
+
+    $query = $articles->find()
+        ->join([
+            'c' => [
+                'table' => 'comments',
+                'type' => 'LEFT',
+                'conditions' => [
+                    'c.article_id' => new \Cake\Database\Expression\IdentifierExpression('articles.id')
+                ]
+            ],
+        ]);
+
+This ensures that all of your identifiers will be quoted across the Query, avoiding errors with
+some database Drivers (PostgreSQL notably)
+
 Inserting Data
 ==============
 
@@ -858,6 +1139,34 @@ Instead, create new a query object using ``query()``::
 Generally, it is easier to delete data using entities and
 :php:meth:`~Cake\\ORM\\Table::delete()`.
 
+SQL Injection Prevention
+========================
+
+While the ORM and database abstraction layers prevent most SQL injections
+issues, it is still possible to leave yourself vulnerable through improper use.
+When using the expression builder, column names must not contain user data::
+
+    $query->where(function ($exp) use ($userData, $values) {
+        // Column names in all expressions are not safe.
+        return $exp->in($userData, $values);
+    });
+
+When building function expressions, function names should never contain user
+data::
+
+    // Not safe.
+    $query->func()->{$userData}($arg1);
+
+    // Also not safe to use an array of
+    // user data in a function expression
+    $query->func()->coalesce($userData);
+
+Raw expressions are never safe::
+
+    $expr = $query->newExpr()->add($userData);
+    $query->select(['two' => $expr]);
+
+
 More Complex Queries
 ====================
 
@@ -877,7 +1186,7 @@ Unions are created by composing one or more select queries together::
 
     $unpublished->union($inReview);
 
-You can create ``UNION ALL`` queries using the ``unionAll`` method::
+You can create ``UNION ALL`` queries using the ``unionAll()`` method::
 
     $inReview = $articles->find()
         ->where(['need_review' => true]);
@@ -905,6 +1214,17 @@ subqueries::
 Subqueries are accepted anywhere a query expression can be used. For example, in
 the ``select()`` and ``join()`` methods.
 
+Executing Complex Queries
+-------------------------
+
+While the query builder makes it easy to build most queries, very complex
+queries can be tedious and complicated to build. You may want to :ref:`execute
+the desired SQL directly `.
+
+Executing SQL directly allows you to fine tune the query that will be run.
+However, doing so doesn't let you use ``contain`` or other higher level ORM
+features.
+
 .. _format-results:
 
 Adding Calculated Fields
@@ -956,221 +1276,3 @@ expect::
 As seen above, the formatters attached to associated query builders are scoped
 to operate only on the data in the association. CakePHP will ensure that
 computed values are inserted into the correct entity.
-
-.. _map-reduce:
-
-Modifying Results with Map/Reduce
-==================================
-
-More often than not, find operations require post-processing the data that is
-found in the database. While entities' getter methods can take care of most of
-the virtual property generation or special data formatting, sometimes you
-need to change the data structure in a more fundamental way.
-
-For those cases, the ``Query`` object offers the ``mapReduce()`` method, which
-is a way of processing results once they are fetched from the database.
-
-A common example of changing the data structure is grouping results together
-based on certain conditions. For this task we can use the ``mapReduce()``
-function. We need two callable functions the ``$mapper`` and the ``$reducer``.
-The ``$mapper`` callable receives the current result from the database as first
-argument, the iteration key as second argument and finally it receives an
-instance of the ``MapReduce`` routine it is running::
-
-    $mapper = function ($article, $key, $mapReduce) {
-        $status = 'published';
-        if ($article->isDraft() || $article->isInReview()) {
-            $status = 'unpublished';
-        }
-        $mapReduce->emitIntermediate($article, $status);
-    };
-
-In the above example ``$mapper`` is calculating the status of an article, either
-published or unpublished, then it calls ``emitIntermediate()`` on the
-``MapReduce`` instance. The method stores the article in the list of articles
-labelled as either published or unpublished.
-
-The next step in the map-reduce process is to consolidate the final results. For
-each status created in the mapper, the ``$reducer`` function will be called so
-you can do any extra processing. This function will receive the list of articles
-in a particular ``bucket`` as the first parameter, the name of the ``bucket`` it
-needs to process as the second parameter, and again, as in the ``mapper()``
-function, the instance of the ``MapReduce`` routine as the third parameter. In
-our example, we did not have to do any extra processing, so we just ``emit()``
-the final results::
-
-    $reducer = function ($articles, $status, $mapReduce) {
-        $mapReduce->emit($articles, $status);
-    };
-
-Finally, we can put these two functions together to do the grouping::
-
-    $articlesByStatus = $articles->find()
-        ->where(['author_id' => 1])
-        ->mapReduce($mapper, $reducer);
-
-    foreach ($articlesByStatus as $status => $articles) {
-        echo sprintf("The are %d %s articles", count($articles), $status);
-    }
-
-The above will ouput the following lines::
-
-    There are 4 published articles
-    There are 5 unpublished articles
-
-Of course, this is a simplistic example that could actually be solved in another
-way without the help of a map-reduce process. Now, let's take a look at another
-example in which the reducer function will be needed to do something more than
-just emitting the results.
-
-Calculating the most commonly mentioned words, where the articles contain
-information about CakePHP, as usual we need a mapper function::
-
-    $mapper = function ($article, $key, $mapReduce) {
-        if (stripos('cakephp', $article['body']) === false) {
-            return;
-        }
-
-        $words = array_map('strtolower', explode(' ', $article['body']));
-        foreach ($words as $word) {
-            $mapReduce->emitIntermediate($article['id'], $word);
-        }
-    };
-
-It first checks for whether the "cakephp" word is in the article's body, and
-then breaks the body into individual words. Each word will create its own
-``bucket`` where each article id will be stored. Now let's reduce our results to
-only extract the count::
-
-    $reducer = function ($occurrences, $word, $mapReduce) {
-        $mapReduce->emit(count($occurrences), $word);
-    }
-
-Finally, we put everything together::
-
-    $articlesByStatus = $articles->find()
-        ->where(['published' => true])
-        ->andWhere(['published_date >=' => new DateTime('2014-01-01')])
-        ->hydrate(false)
-        ->mapReduce($mapper, $reducer);
-
-This could return a very large array if we don't clean stop words, but it could
-look something like this::
-
-    [
-        'cakephp' => 100,
-        'awesome' => 39,
-        'impressive' => 57,
-        'outstanding' => 10,
-        'mind-blowing' => 83
-    ]
-
-One last example and you will be a map-reduce expert. Imagine you have
-a ``friends`` table and you want to find "fake friends" in our database, or
-better said, people who do not follow each other. Let's start with our
-``mapper`` function::
-
-    $mapper = function ($rel, $key, $mr) {
-        $mr->emitIntermediate($rel['source_user_id'], $rel['target_user_id']);
-        $mr->emitIntermediate($rel['target_user_id'], $rel['source_target_id']);
-    };
-
-We just duplicated our data to have a list of users each other user follows.
-Now it's time to reduce it. For each call to the reducer, it will receive a list
-of followers per user::
-
-    // $friends list will look like
-    // repeated numbers mean that the relationship existed in both directions
-    [2, 5, 100, 2, 4]
-
-    $reducer = function ($friendsList, $user, $mr) {
-        $friends = array_count_values($friendsList);
-        foreach ($friends as $friend => $count) {
-            if ($count < 2) {
-                $mr->emit($friend, $user);
-            }
-        }
-    }
-
-And we supply our functions to a query::
-
-    $fakeFriends = $friends->find()
-        ->hydrate(false)
-        ->mapReduce($mapper, $reducer)
-        ->toArray();
-
-This would return an array similar to this::
-
-    [
-        1 => [2, 4],
-        3 => [6]
-        ...
-    ]
-
-The resulting array means, for example, that user with id ``1`` follows users
-``2`` and ``4``, but those do not follow ``1`` back.
-
-
-Stacking Multiple Operations
-----------------------------
-
-Using `mapReduce` in a query will not execute it immediately. The operation will
-be registered to be run as soon as the first result is attempted to be fetched.
-This allows you to keep chaining additional methods and filters to the query
-even after adding a map-reduce routine::
-
-   $query = $articles->find()
-        ->where(['published' => true])
-        ->mapReduce($mapper, $reducer);
-
-    // At a later point in your app:
-    $query->where(['created >=' => new DateTime('1 day ago')]);
-
-This is particularly useful for building custom finder methods as described in the
-:ref:`custom-find-methods` section::
-
-    public function findPublished(Query $query, array $options])
-    {
-        return $query->where(['published' => true]);
-    }
-
-    public function findRecent(Query $query, array $options)
-    {
-        return $query->where(['created >=' => new DateTime('1 day ago')]);
-    }
-
-    public function findCommonWords(Query $query, array $options)
-    {
-        // Same as in the common words example in the previous section
-        $mapper = ...;
-        $reducer = ...;
-        return $query->mapReduce($mapper, $reducer);
-    }
-
-    $commonWords = $articles
-        ->find('commonWords')
-        ->find('published')
-        ->find('recent');
-
-Moreover, it is also possible to stack more than one ``mapReduce`` operation for
-a single query. For example, if we wanted to have the most commonly used words
-for articles, but then filter it to only return words that were mentioned more
-than 20 times across all articles::
-
-    $mapper = function ($count, $word, $mr) {
-        if ($count > 20) {
-            $mr->emit($count, $word);
-        }
-    };
-
-    $articles->find('commonWords')->mapReduce($mapper);
-
-Removing All Stacked Map-reduce Operations
-------------------------------------------
-
-Under some circumstances you may want to modify a ``Query`` object so that no
-``mapReduce`` operations are executed at all. This can be easily done by
-calling the method with both parameters as null and the third parameter
-(overwrite) as ``true``::
-
-    $query->mapReduce(null, null, true);
diff --git a/en/orm/retrieving-data-and-resultsets.rst b/en/orm/retrieving-data-and-resultsets.rst
index f82b1fe5b77db51a77dcacaa6e09d9cf1b3bda69..8814ccecc81bc044fb799730cf86114bc42d1205 100644
--- a/en/orm/retrieving-data-and-resultsets.rst
+++ b/en/orm/retrieving-data-and-resultsets.rst
@@ -10,6 +10,20 @@ objects, when you query for individual records you get 'entity' objects. While
 this section discusses the different ways you can find and load entities, you
 should read the :doc:`/orm/entities` section for more information on entities.
 
+Debugging Queries and ResultSets
+================================
+
+Since the ORM now returns Collections and Entities, debugging these objects can
+be more complicated than in previous CakePHP versions. There are now various
+ways to inspect the data returned by the ORM.
+
+- ``debug($query)`` Shows the SQL and bound params, does not show results.
+- ``debug($query->all())`` Shows the ResultSet properties (not the results).
+- ``debug($query->toArray())`` An easy way to show each of the results.
+- ``debug(json_encode($query, JSON_PRETTY_PRINT))`` More human readable results.
+- ``debug($query->first())`` Show the properties of a single entity.
+- ``debug((string)$query->first())`` Show the properties of a single entity as JSON.
+
 Getting a Single Entity by Primary Key
 ======================================
 
@@ -30,7 +44,7 @@ view entities and their related data. You can do this easily by using
     ]);
 
 If the get operation does not find any results
-a ``Cake\ORM\Exception\RecordNotFoundException`` will be raised. You can either
+a ``Cake\Datasource\Exception\RecordNotFoundException`` will be raised. You can either
 catch this exception yourself, or allow CakePHP to convert it into a 404 error.
 
 Like ``find()`` get has caching integrated. You can use the ``cache`` option
@@ -53,6 +67,11 @@ when calling ``get()`` to perform read-through caching::
         'cache' => false
     ]);
 
+Optionally you can ``get()`` an entity using :ref:`custom-find-methods`. For example you may want to get all translations for an entity. You can achieve that by using the ``finder`` option::
+
+    $article = $articles->get($id, [
+        'finder' => 'translations',
+    ]);
 
 Using Finders to Load Data
 ==========================
@@ -60,7 +79,7 @@ Using Finders to Load Data
 .. php:method:: find($type, $options = [])
 
 Before you can work with entities, you'll need to load them. The easiest way to
-do this is using the ``find`` method. The find method provides an easy and
+do this is using the ``find()`` method. The find method provides an easy and
 extensible way to find the data you are interested in::
 
     // In a controller or table method.
@@ -68,7 +87,7 @@ extensible way to find the data you are interested in::
     // Find all the articles
     $query = $articles->find('all');
 
-The return value of any ``find`` method is always
+The return value of any ``find()`` method is always
 a :php:class:`Cake\\ORM\\Query` object. The Query class allows you to further
 refine a query after creating it. Query objects are evaluated lazily, and do not
 execute until you start fetching rows, convert it to an array, or when the
@@ -100,7 +119,7 @@ execute until you start fetching rows, convert it to an array, or when the
     to build more complex queries, adding additional conditions, limits, or include
     associations using the fluent interface.
 
-.. code-block:: php
+::
 
     // In a controller or table method.
     $query = $articles->find('all')
@@ -135,7 +154,7 @@ The list of options supported by find() are:
 
 Any options that are not in this list will be passed to beforeFind listeners
 where they can be used to modify the query object. You can use the
-``getOptions`` method on a query object to retrieve the options used. While you
+``getOptions()`` method on a query object to retrieve the options used. While you
 can very easily pass query objects to your controllers, we recommend that you
 package your queries up as :ref:`custom-find-methods` instead. Using custom
 finder methods will let you re-use your queries more easily and make testing
@@ -175,7 +194,7 @@ a result count of that query::
 
     // In a controller or table method.
     $query = $articles->find('all', [
-        'where' => ['Articles.title LIKE' => '%Ovens%']
+        'conditions' => ['Articles.title LIKE' => '%Ovens%']
     ]);
     $number = $query->count();
 
@@ -187,7 +206,7 @@ Finding Key/Value Pairs
 =======================
 
 It is often useful to generate an associative array of data from your application's
-data. For example, this is very useful when creating ``` elements. CakePHP
 provides a simple to use method for generating 'lists' of data::
 
     // In a controller or table method.
@@ -215,11 +234,12 @@ a table::
     }
 
 When calling ``list`` you can configure the fields used for the key and value with
-the ``idField`` and ``valueField`` options respectively::
+the ``keyField`` and ``valueField`` options respectively::
 
     // In a controller or table method.
     $query = $articles->find('list', [
-        'idField' => 'slug', 'valueField' => 'title'
+        'keyField' => 'slug',
+        'valueField' => 'title'
     ]);
     $data = $query->toArray();
 
@@ -234,7 +254,7 @@ bucketed sets, or want to build ```` elements with FormHelper::
 
     // In a controller or table method.
     $query = $articles->find('list', [
-        'idField' => 'slug',
+        'keyField' => 'slug',
         'valueField' => 'title',
         'groupField' => 'author_id'
     ]);
@@ -251,6 +271,13 @@ bucketed sets, or want to build ```` elements with FormHelper::
         ]
     ];
 
+You can also create list data from associations that can be reached with joins::
+
+    $query = $articles->find('list', [
+        'keyField' => 'id',
+        'valueField' => 'author.name'
+    ])->contain(['Authors']);
+
 Finding Threaded Data
 =====================
 
@@ -265,7 +292,7 @@ table. All entities matching a given ``parent_id`` are placed under the
 
     // Expanded default values
     $query = $comments->find('threaded', [
-        'idField' => $comments->primaryKey(),
+        'keyField' => $comments->primaryKey(),
         'parentField' => 'parent_id'
     ]);
     $results = $query->toArray();
@@ -273,7 +300,7 @@ table. All entities matching a given ``parent_id`` are placed under the
     echo count($results[0]->children);
     echo $results[0]->children[0]->comment;
 
-The ``parentField`` and ``idField`` keys can be used to define the fields that
+The ``parentField`` and ``keyField`` keys can be used to define the fields that
 threading will occur on.
 
 .. tip::
@@ -332,6 +359,8 @@ If you need to modify the results after they have been fetched you should use
 a :ref:`map-reduce` function to modify the results. The map reduce features
 replace the 'afterFind' callback found in previous versions of CakePHP.
 
+.. _dynamic-finders:
+
 Dynamic Finders
 ===============
 
@@ -339,6 +368,13 @@ CakePHP's ORM provides dynamically constructed finder methods which allow you to
 easily express simple queries with no additional code. For example if you wanted
 to find a user by username you could do::
 
+    // In a controller
+    // The following two calls are equal.
+    $query = $this->Users->findByUsername('joebob');
+    $query = $this->Users->findAllByUsername('joebob');
+
+    // In a table method
+    $users = TableRegistry::get('Users');
     // The following two calls are equal.
     $query = $users->findByUsername('joebob');
     $query = $users->findAllByUsername('joebob');
@@ -365,12 +401,40 @@ The above would translate into the following::
         'conditions' => ['username' => 'bro']
     ]);
 
+Once you have a query object from a dynamic finder, you'll need to call
+``first()`` if you want the first result.
+
 .. note::
 
     While dynamic finders make it simple to express queries, they come with some
     additional performance overhead.
 
 
+Retrieving Associated Data
+==========================
+
+When you want to grab associated data, or filter based on associated data, there
+are two ways:
+
+- use CakePHP ORM query functions like ``contain()`` and ``matching()``
+- use join functions like ``innerJoin()``, ``leftJoin()``, and ``rightJoin()``
+
+You should use ``contain()`` when you want to load the primary model, and its
+associated data. While ``contain()`` will let you apply additional conditions to
+the loaded associations, you cannot constrain the primary model based on the
+associations. For more details on the ``contain()``, look at
+:ref:`eager-loading-associations`.
+
+You should use ``matching()`` when you want to restrict the primary model based
+on associations. For example, you want to load all the articles that have
+a specific tag on them. For more details on the ``matching()``, look at
+:ref:`filtering-by-associated-data`.
+
+If you prefer to use join functions, you can look at
+:ref:`adding-joins` for more information.
+
+.. _eager-loading-associations:
+
 Eager Loading Associations
 ==========================
 
@@ -486,12 +550,30 @@ case you should use an array passing ``foreignKey`` and ``queryBuilder``::
     ]);
 
 If you have limited the fields you are loading with ``select()`` but also want to
-load fields off of contained associations, you can use ``autoFields()``::
+load fields off of contained associations, you can pass the association object
+to ``select()``::
 
     // Select id & title from articles, but all fields off of Users.
+    $articlesTable
+        ->select(['id', 'title'])
+        ->select($articlesTable->Users)
+        ->contain(['Users']);
+
+Alternatively, if you can multiple associations, you can use ``autoFields()``::
+
+    // Select id & title from articles, but all fields off of Users, Comments
+    // and Tags.
     $query->select(['id', 'title'])
-        ->contain(['Users'])
+        ->contain(['Comments', 'Tags'])
         ->autoFields(true);
+        ->contain(['Users' => function($q) {
+            return $q->autoFields(true);
+        }]);
+
+.. versionadded:: 3.1
+    Selecting columns via an association object was added in 3.1
+
+.. _filtering-by-associated-data:
 
 Filtering by Associated Data
 ----------------------------
@@ -545,21 +627,218 @@ The data from the association that is 'matched' will be available on the
 association, you can expect to get both the ``_matchingData`` and standard
 association properties in your results.
 
+Using innerJoinWith
+~~~~~~~~~~~~~~~~~~~
+
+Using the ``matching()`` function, as we saw already, will create an ``INNER
+JOIN`` with the specified association and will also load the fields into the
+result set.
+
+There may be cases where you want to use ``matching()`` but are not interested
+in loading the fields into the result set. For this purpose, you can use
+``innerJoinWith()``::
+
+    $query = $articles->find();
+    $query->innerJoinWith('Tags', function ($q) {
+        return $q->where(['Tags.name' => 'CakePHP']);
+    });
+
+The ``innerJoinWith()`` method works the same as ``matching()``, that
+means that you can use dot notation to join deeply nested
+associations::
+
+    $query = $products->find()->innerJoinWith(
+        'Shops.Cities.Countries', function ($q) {
+            return $q->where(['Countries.name' => 'Japan']);
+        }
+    );
+
+Again, the only difference is that no additional columns will be added to the
+result set, and no ``_matchingData`` property will be set.
+
+.. versionadded:: 3.1
+    Query::innerJoinWith() was added in 3.1
+
+Using notMatching
+~~~~~~~~~~~~~~~~~
+
+The opposite of ``matching()`` is ``notMatching()``. This function will change
+the query so that it filters results that have no relation to the specified
+association::
+
+    // In a controller or table method.
+
+    $query = $articlesTable
+        ->find()
+        ->notMatching('Tags', function ($q) {
+            return $q->where(['Tags.name' => 'boring']);
+        });
+
+The above example will find all articles that were not tagged with the word
+``boring``.  You can apply this method to HasMany associations as well. You could,
+for example, find all the authors with no published articles in the last 10
+days::
+
+    $query = $authorsTable
+        ->find()
+        ->notMatching('Articles', function ($q) {
+            return $q->where(['Articles.created >=' => new \DateTime('-10 days')]);
+        });
+
+It is also possible to use this method for filtering out records not matching
+deep associations. For example, you could find articles that have not been
+commented on by a certain user::
+
+    $query = $articlesTable
+        ->find()
+        ->notMatching('Comments.Users', function ($q) {
+            return $q->where(['username' => 'jose']);
+        });
+
+Since articles with no comments at all also satisfy the condition above, you may
+want to combine ``matching()`` and ``notMatching()`` in the same query. The
+following example will find articles having at least one comment, but not
+commented by a certain user::
+
+    $query = $articlesTable
+        ->find()
+        ->notMatching('Comments.Users', function ($q) {
+            return $q->where(['username' => 'jose']);
+        })
+        ->matching('Comments');
+
+.. note::
+
+    As ``notMatching()`` will create a ``LEFT JOIN``, you might want to consider
+    calling ``distinct`` on the find query as you can get duplicate rows
+    otherwise.
+
+Keep in mind that contrary to the ``matching()`` function, ``notMatching()``
+will not add any data to the ``_matchingData`` property in the results.
+
+.. versionadded:: 3.1
+    Query::notMatching() was added in 3.1
+
+Using leftJoinWith
+~~~~~~~~~~~~~~~~~~
+
+On certain occasions you may want to calculate a result based on an association,
+without having to load all the records for it. For example, if you wanted to
+load the total number of comments an article has along with all the article
+data, you can use the ``leftJoinWith()`` function::
+
+    $query = $articlesTable->find();
+    $query->select(['total_comments' => $query->func()->count('Comments.id')])
+        ->leftJoinWith('Comments')
+        ->group(['Articles.id'])
+        ->autoFields(true);
+
+The results for the above query will contain the article data and the
+``total_comments`` property for each of them.
+
+``leftJoinWith()`` can also be used with deeply nested associations. This is
+useful, for example, for bringing the count of articles tagged with a certain
+word, per author::
+
+    $query = $authorsTable->find();
+        ->find()
+        ->select(['total_articles' => $query->func()->count('Articles.id')])
+        ->leftJoinWith('Articles.Tags', function ($q) {
+            return $q->where(['Tags.name' => 'awesome']);
+        })
+        ->group(['Authors.id'])
+        ->autoFields(true);
+
+This function will not load any columns from the specified associations into the
+result set.
+
+.. versionadded:: 3.1
+    Query::leftJoinWith() was added in 3.1
+
 .. end-contain
 
+Changing Fetching Strategies
+----------------------------
+
+As you may know already, ``belongsTo`` and ``hasOne`` associations are loaded
+using a ``JOIN`` in the main finder query. While this improves query and
+fetching speed and allows for creating more expressive conditions when
+retrieving data, this may be a problem when you want to apply certain clauses to
+the finder query for the association, such as ``order()`` or ``limit()``.
+
+For example, if you wanted to get the first comment of an article as an
+association::
+
+   $articles->hasOne('FirstComment', [
+        'className' => 'Comments',
+        'foreignKey' => 'article_id'
+   ]);
+
+In order to correctly fetch the data from this association, we will need to tell
+the query to use the ``select`` strategy, since we want order by a particular
+column::
+
+    $query = $articles->find()->contain([
+        'FirstComment' => [
+                'strategy' => 'select',
+                'queryBuilder' => function ($q) {
+                    return $q->order(['FirstComment.created' =>'ASC'])->limit(1);
+                }
+        ]
+    ]);
+
+Dynamically changing the strategy in this way will only apply to a specific
+query. If you want to make the strategy change permanent you can do::
+
+    $articles->FirstComment->strategy('select');
+
+Using the ``select`` strategy is also a great way of making associations with
+tables in another database, since it would not be possible to fetch records
+using ``joins``.
+
+Fetching With The Subquery Strategy
+-----------------------------------
+
+As your tables grow in size, fetching associations from them can become
+slower, especially if you are querying big batches at once. A good way of
+optimizing association loading for ``hasMany`` and ``belongsToMany``
+associations is by using the ``subquery`` strategy::
+
+    $query = $articles->find()->contain([
+        'Comments' => [
+                'strategy' => 'subquery',
+                'queryBuilder' => function ($q) {
+                    return $q->where(['Comments.approved' => true]);
+                }
+        ]
+    ]);
+
+The result will remain the same as with using the default strategy, but this
+can greatly improve the query and fetching time in some databases, in
+particular it will allow to fetch big chunks of data at the same time in
+databases that limit the amount of bound parameters per query, such as
+**Microsoft SQL Server**.
+
+You can also make the strategy permanent for the association by doing::
+
+    $articles->Comments->strategy('subquery');
+
 Lazy Loading Associations
 -------------------------
 
 While CakePHP makes it easy to eager load your associations, there may be cases
 where you need to lazy-load associations. You should refer to the
-:ref:`lazy-load-associations` section for more information.
+:ref:`lazy-load-associations` and :ref:`loading-additional-associations`
+sections for more information.
 
 Working with Result Sets
 ========================
 
 Once a query is executed with ``all()``, you will get an instance of
-:php:class:`Cake\\ORM\ResultSet`. This object offers powerful ways to manipulate
-the resulting data from your queries.
+:php:class:`Cake\\ORM\\ResultSet`. This object offers powerful ways to manipulate
+the resulting data from your queries. Like Query objects, ResultSets are
+a :doc:`Collection ` and you can use any collection
+method on ResultSet objects.
 
 Result set objects will lazily load rows from the underlying prepared statement.
 By default results will be buffered in memory allowing you to iterate a result
@@ -621,5 +900,292 @@ articles quite easily::
         ->extract('tags.name')
         ->reduce($reducer, []);
 
+Some other examples of the collection methods being used with result sets are::
+
+    // Filter the rows by a calculated property
+    $filtered = $results->filter(function ($row) {
+        return $row->is_recent;
+    });
+
+    // Create an associative array from result properties
+    $articles = TableRegistry::get('Articles');
+    $results = $articles->find()->contain(['Authors'])->all();
+
+    $authorList = $results->combine('id', 'author.name');
+
 The :doc:`/core-libraries/collections` chapter has more detail on what can be
-done with result sets using the collections features.
+done with result sets using the collections features. The :ref:`format-results`
+section show how you can add calculated fields, or replace the result set.
+
+Getting the First & Last Record From a ResultSet
+------------------------------------------------
+
+You can use the ``first()`` and ``last()`` methods to get the respective records
+from a result set::
+
+    $result = $articles->find('all')->all();
+
+    // Get the first and/or last result.
+    $row = $result->first();
+    $row = $result->last();
+
+Getting an Arbitrary Index From a ResultSet
+-------------------------------------------
+
+You can use ``skip()`` and ``first()`` to get an arbitrary record from
+a ResultSet::
+
+    $result = $articles->find('all')->all();
+
+    // Get the 5th record
+    $row = $result->skip(4)->first();
+
+Checking if a Query or ResultSet is Empty
+-----------------------------------------
+
+You can use the ``isEmpty()`` method on a Query or ResultSet object to see if it
+has any rows in it. Calling ``isEmpty()`` on a Query object will evaluate the
+query::
+
+    // Check a query.
+    $query->isEmpty();
+
+    // Check results
+    $results = $query->all();
+    $results->isEmpty();
+
+.. _loading-additional-associations:
+
+Loading Additional Associations
+-------------------------------
+
+Once you've created a result set, you may need to load
+additional associations. This is the perfect time to lazily eager load data. You
+can load additional associations using ``loadInto()``::
+
+    $articles = $this->Articles->find()->all();
+    $withMore = $this->Articles->loadInto($articles, ['Comments', 'Users']);
+
+You can eager load additional data into a single entity, or a collection of
+entities.
+
+.. versionadded: 3.1
+    Table::loadInto() was added in 3.1
+
+.. _map-reduce:
+
+Modifying Results with Map/Reduce
+=================================
+
+More often than not, find operations require post-processing the data that is
+found in the database. While entities' getter methods can take care of most of
+the virtual property generation or special data formatting, sometimes you
+need to change the data structure in a more fundamental way.
+
+For those cases, the ``Query`` object offers the ``mapReduce()`` method, which
+is a way of processing results once they are fetched from the database.
+
+A common example of changing the data structure is grouping results together
+based on certain conditions. For this task we can use the ``mapReduce()``
+function. We need two callable functions the ``$mapper`` and the ``$reducer``.
+The ``$mapper`` callable receives the current result from the database as first
+argument, the iteration key as second argument and finally it receives an
+instance of the ``MapReduce`` routine it is running::
+
+    $mapper = function ($article, $key, $mapReduce) {
+        $status = 'published';
+        if ($article->isDraft() || $article->isInReview()) {
+            $status = 'unpublished';
+        }
+        $mapReduce->emitIntermediate($article, $status);
+    };
+
+In the above example ``$mapper`` is calculating the status of an article, either
+published or unpublished, then it calls ``emitIntermediate()`` on the
+``MapReduce`` instance. This method stores the article in the list of articles
+labelled as either published or unpublished.
+
+The next step in the map-reduce process is to consolidate the final results. For
+each status created in the mapper, the ``$reducer`` function will be called so
+you can do any extra processing. This function will receive the list of articles
+in a particular "bucket" as the first parameter, the name of the "bucket" it
+needs to process as the second parameter, and again, as in the ``mapper()``
+function, the instance of the ``MapReduce`` routine as the third parameter. In
+our example, we did not have to do any extra processing, so we just ``emit()``
+the final results::
+
+    $reducer = function ($articles, $status, $mapReduce) {
+        $mapReduce->emit($articles, $status);
+    };
+
+Finally, we can put these two functions together to do the grouping::
+
+    $articlesByStatus = $articles->find()
+        ->where(['author_id' => 1])
+        ->mapReduce($mapper, $reducer);
+
+    foreach ($articlesByStatus as $status => $articles) {
+        echo sprintf("The are %d %s articles", count($articles), $status);
+    }
+
+The above will ouput the following lines::
+
+    There are 4 published articles
+    There are 5 unpublished articles
+
+Of course, this is a simplistic example that could actually be solved in another
+way without the help of a map-reduce process. Now, let's take a look at another
+example in which the reducer function will be needed to do something more than
+just emitting the results.
+
+Calculating the most commonly mentioned words, where the articles contain
+information about CakePHP, as usual we need a mapper function::
+
+    $mapper = function ($article, $key, $mapReduce) {
+        if (stripos('cakephp', $article['body']) === false) {
+            return;
+        }
+
+        $words = array_map('strtolower', explode(' ', $article['body']));
+        foreach ($words as $word) {
+            $mapReduce->emitIntermediate($article['id'], $word);
+        }
+    };
+
+It first checks for whether the "cakephp" word is in the article's body, and
+then breaks the body into individual words. Each word will create its own
+``bucket`` where each article id will be stored. Now let's reduce our results to
+only extract the count::
+
+    $reducer = function ($occurrences, $word, $mapReduce) {
+        $mapReduce->emit(count($occurrences), $word);
+    }
+
+Finally, we put everything together::
+
+    $articlesByStatus = $articles->find()
+        ->where(['published' => true])
+        ->andWhere(['published_date >=' => new DateTime('2014-01-01')])
+        ->hydrate(false)
+        ->mapReduce($mapper, $reducer);
+
+This could return a very large array if we don't clean stop words, but it could
+look something like this::
+
+    [
+        'cakephp' => 100,
+        'awesome' => 39,
+        'impressive' => 57,
+        'outstanding' => 10,
+        'mind-blowing' => 83
+    ]
+
+One last example and you will be a map-reduce expert. Imagine you have
+a ``friends`` table and you want to find "fake friends" in our database, or
+better said, people who do not follow each other. Let's start with our
+``mapper()`` function::
+
+    $mapper = function ($rel, $key, $mr) {
+        $mr->emitIntermediate($rel['source_user_id'], $rel['target_user_id']);
+        $mr->emitIntermediate($rel['target_user_id'], $rel['source_target_id']);
+    };
+
+We just duplicated our data to have a list of users each other user follows.
+Now it's time to reduce it. For each call to the reducer, it will receive a list
+of followers per user::
+
+    // $friends list will look like
+    // repeated numbers mean that the relationship existed in both directions
+    [2, 5, 100, 2, 4]
+
+    $reducer = function ($friendsList, $user, $mr) {
+        $friends = array_count_values($friendsList);
+        foreach ($friends as $friend => $count) {
+            if ($count < 2) {
+                $mr->emit($friend, $user);
+            }
+        }
+    }
+
+And we supply our functions to a query::
+
+    $fakeFriends = $friends->find()
+        ->hydrate(false)
+        ->mapReduce($mapper, $reducer)
+        ->toArray();
+
+This would return an array similar to this::
+
+    [
+        1 => [2, 4],
+        3 => [6]
+        ...
+    ]
+
+The resulting array means, for example, that user with id ``1`` follows users
+``2`` and ``4``, but those do not follow ``1`` back.
+
+
+Stacking Multiple Operations
+----------------------------
+
+Using `mapReduce` in a query will not execute it immediately. The operation will
+be registered to be run as soon as the first result is attempted to be fetched.
+This allows you to keep chaining additional methods and filters to the query
+even after adding a map-reduce routine::
+
+   $query = $articles->find()
+        ->where(['published' => true])
+        ->mapReduce($mapper, $reducer);
+
+    // At a later point in your app:
+    $query->where(['created >=' => new DateTime('1 day ago')]);
+
+This is particularly useful for building custom finder methods as described in the
+:ref:`custom-find-methods` section::
+
+    public function findPublished(Query $query, array $options)
+    {
+        return $query->where(['published' => true]);
+    }
+
+    public function findRecent(Query $query, array $options)
+    {
+        return $query->where(['created >=' => new DateTime('1 day ago')]);
+    }
+
+    public function findCommonWords(Query $query, array $options)
+    {
+        // Same as in the common words example in the previous section
+        $mapper = ...;
+        $reducer = ...;
+        return $query->mapReduce($mapper, $reducer);
+    }
+
+    $commonWords = $articles
+        ->find('commonWords')
+        ->find('published')
+        ->find('recent');
+
+Moreover, it is also possible to stack more than one ``mapReduce`` operation for
+a single query. For example, if we wanted to have the most commonly used words
+for articles, but then filter it to only return words that were mentioned more
+than 20 times across all articles::
+
+    $mapper = function ($count, $word, $mr) {
+        if ($count > 20) {
+            $mr->emit($count, $word);
+        }
+    };
+
+    $articles->find('commonWords')->mapReduce($mapper);
+
+Removing All Stacked Map-reduce Operations
+------------------------------------------
+
+Under some circumstances you may want to modify a ``Query`` object so that no
+``mapReduce`` operations are executed at all. This can be easily done by
+calling the method with both parameters as null and the third parameter
+(overwrite) as ``true``::
+
+    $query->mapReduce(null, null, true);
diff --git a/en/orm/saving-data.rst b/en/orm/saving-data.rst
index f01d567134968c0a84a2ce2bcf46d57c5c2c5dc9..1784774a70dba08a42cefd33a94126744543388d 100644
--- a/en/orm/saving-data.rst
+++ b/en/orm/saving-data.rst
@@ -8,6 +8,129 @@ Saving Data
 After you have :doc:`loaded your data` you
 will probably want to update & save the changes.
 
+
+A Glance Over Saving Data
+=========================
+
+Applications will usually have a couple ways in which data is saved. The first
+one is obviously though web forms and the other is by directly generating or
+changing data in the code to be sent to the database.
+
+Inserting Data
+--------------
+
+The easiest way to insert data in the database is creating a new entity and
+passing it to the ``save()`` method in the ``Table`` class::
+
+    use Cake\ORM\TableRegistry;
+
+    $articlesTable = TableRegistry::get('Articles');
+    $article = $articlesTable->newEntity();
+
+    $article->title = 'A New Article';
+    $article->body = 'This is the body of the article';
+
+    if ($articlesTable->save($article)) {
+        // The $article entity contain the id now
+        $id = $article->id;
+    }
+
+Updating Data
+-------------
+
+Updating is equally easy, and the ``save()`` method is also used for that
+purpose::
+
+    use Cake\ORM\TableRegistry;
+
+    $articlesTable = TableRegistry::get('Articles');
+    $article = $articlesTable->get(12); // article with id 12
+
+    $article->title = 'A new title for the article';
+    $articlesTable->save($article);
+
+CakePHP will know whether to do an insert or an update based on the return value
+of the ``isNew()`` method. Entities that were retrieved with ``get()`` or
+``find()`` will always return ``false`` when ``isNew()`` is called on them.
+
+Saving With Associations
+------------------------
+
+By default the ``save()`` method will also save one level of associations::
+
+    $articlesTable = TableRegistry::get('Articles');
+    $author = $articlesTable->Authors->findByUserName('mark')->first();
+
+    $article = $articlesTable->newEntity();
+    $article->title = 'An article by mark';
+    $article->author = $author;
+
+    if ($articlesTable->save($article)) {
+        // The foreign key value was set automatically.
+        echo $article->author_id;
+    }
+
+The ``save()`` method is also able to create new records for associations::
+
+    $firstComment = $articlesTable->Comments->newEntity();
+    $firstComment->body = 'This is a great article';
+
+    $secondComment = $articlesTable->Comments->newEntity();
+    $secondComment->body = 'I like reading this!';
+
+    $tag1 = $articlesTable->Tags->findByName('cakephp')->first();
+    $tag2 = $articlesTable->Tags->newEntity();
+    $tag2->name = 'awesome';
+
+    $article = $articlesTable->get(12);
+    $article->comments = [$firstComment, $secondComment];
+    $article->tags = [$tag1, $tag2];
+
+    $articlesTable->save($article);
+
+Associate Many To Many Records
+------------------------------
+
+In the code above there was already an example of linking an article to
+a couple tags. There is another way of doing the same by using the ``link()``
+method in the association::
+
+    $tag1 = $articlesTable->Tags->findByName('cakephp')->first();
+    $tag2 = $articlesTable->Tags->newEntity();
+    $tag2->name = 'awesome';
+
+    $articlesTable->Tags->link($article, [$tag1, $tag2]);
+
+Saving Data To The Join Table
+-----------------------------
+
+Saving data to the join table is done by using the special ``_joinData``
+property. This property should be an Entity instance from the join Table class::
+
+    $tag1 = $articlesTable->Tags->findByName('cakephp')->first();
+    $tag1->_joinData = $articlesTable->ArticlesTags->newEntity();
+    $tag1->_joinData->tagComment = 'I think this is related to cake';
+
+    $articlesTable->Tags->link($article, [$tag1]);
+
+Unlink Many To Many Records
+---------------------------
+
+Unlinking many to many records is done via the ``unlink()`` method::
+
+    $tags = $articlesTable
+        ->Tags
+        ->find()
+        ->where(['name IN' => ['cakephp', 'awesome']])
+        ->toArray();
+
+    $articlesTable->Tags->unlink($article, $tags);
+
+When modifying records by directly setting or changing the properties no
+validation happens, which is a problem when accepting form data. The following
+sections will show you how to efficiently convert form data into entities so
+that they can be validated and saved.
+
 .. _converting-request-data:
 
 Converting Request Data into Entities
@@ -20,6 +143,7 @@ entities from request data. You can convert a single entity using::
 
     // In a controller.
     $articles = TableRegistry::get('Articles');
+    // Validate and convert to an Entity object
     $entity = $articles->newEntity($this->request->data());
 
 The request data should follow the structure of your entities. For example if
@@ -39,6 +163,46 @@ request data should look like::
         ]
     ];
 
+By default, the ``newEntity()`` method validates the data that gets passed to
+it, as explained in the :ref:`validating-request-data` section. If you wish to
+prevent data from being validated, pass the ``'validate' => false`` option::
+
+    $entity = $articles->newEntity($data, ['validate' => false]);
+
+When building forms that save nested associations, you need to define which
+associations should be marshalled::
+
+    // In a controller
+    $articles = TableRegistry::get('Articles');
+    $entity = $articles->newEntity($this->request->data(), [
+        'associated' => [
+            'Tags', 'Comments' => ['associated' => ['Users']]
+        ]
+    ]);
+
+The above indicates that the 'Tags', 'Comments' and 'Users' for the Comments
+should be marshalled. Alternatively, you can use dot notation for brevity::
+
+    // In a controller.
+    $articles = TableRegistry::get('Articles');
+    $entity = $articles->newEntity($this->request->data(), [
+        'associated' => ['Tags', 'Comments.Users']
+    ]);
+
+Associated data is also validated by default unless told otherwise. You may also
+change the validation set to be used per association::
+
+    $articles = TableRegistry::get('Articles');
+    $entity = $articles->newEntity($this->request->data(), [
+        'associated' => [
+            'Tags' => ['validate' => false],
+            'Comments.Users' => ['validate' => 'signup']
+        ]
+    ]);
+
+Converting BelongsToMany Data
+-----------------------------
+
 If you are saving belongsToMany associations you can either use a list of
 entity data or a list of ids. When using a list of entity data your request data
 should look like::
@@ -53,7 +217,8 @@ should look like::
         ]
     ];
 
-When using a list of ids, your request data should look like::
+The above will create 2 new tags. If you want to link an article with existing
+tags you can use a list of ids. Your request data should look like::
 
     $data = [
         'title' => 'My title',
@@ -64,37 +229,51 @@ When using a list of ids, your request data should look like::
         ]
     ];
 
-The marshaller will handle both of these forms correctly, but only for
-belongsToMany associations.
+If you need to link against some existing belongsToMany records, and create new
+ones at the same time you can use an expanded format::
 
-When building forms that save nested associations, you need to define which
-associations should be marshalled::
-
-    // In a controller
-    $articles = TableRegistry::get('Articles');
-    $entity = $articles->newEntity($this->request->data(), [
-        'associated' => [
-            'Tags', 'Comments' => ['associated' => ['Users']]
+    $data = [
+        'title' => 'My title',
+        'body' => 'The text',
+        'user_id' => 1,
+        'tags' => [
+            ['name' => 'A new tag'],
+            ['name' => 'Another new tag'],
+            ['id' => 5],
+            ['id' => 21]
         ]
-    ]);
+    ];
 
-The above indicates that the 'Tags', 'Comments' and 'Users' for the Comments
-should be marshalled. Alternatively, you can use dot notation for brevity::
+When the above data is converted into entities, you will have 4 tags. The first
+two will be new objects, and the second two will be references to existing
+records.
 
-    // In a controller.
-    $articles = TableRegistry::get('Articles');
-    $entity = $articles->newEntity($this->request->data(), [
-        'associated' => ['Tags', 'Comments.Users']
-    ]);
+Converting HasMany Data
+-----------------------
+
+If you are saving hasMany associations and want to link existing records to
+a new parent record you can use the ``_ids`` format::
+
+    $data = [
+        'title' => 'My new article',
+        'body' => 'The text',
+        'user_id' => 1,
+        'comments' => [
+            '_ids' => [1, 2, 3, 4]
+        ]
+    ];
+
+Converting Multiple Records
+---------------------------
 
-You can convert multiple entities using::
+When creating forms that create/update multiple records at once you can use
+``newEntities()``::
 
     // In a controller.
     $articles = TableRegistry::get('Articles');
     $entities = $articles->newEntities($this->request->data());
 
-When converting multiple entities, the request data for multiple articles should
-look like::
+In this situation, the request data for multiple articles should look like::
 
     $data = [
         [
@@ -107,6 +286,33 @@ look like::
         ],
     ];
 
+.. _changing-accessible-fields:
+
+Changing Accessible Fields
+--------------------------
+
+It's also possible to allow ``newEntity()`` to write into non accessible fields.
+For example, ``id`` is usually absent from the ``_accessible`` property.
+In such case, you can use the ``accessibleFields`` option. It could be useful to keep
+ids of associated entities::
+
+    // In a controller
+    $articles = TableRegistry::get('Articles');
+    $entity = $articles->newEntity($this->request->data(), [
+        'associated' => [
+            'Tags', 'Comments' => [
+                'associated' => [
+                    'Users' => [
+                        'accessibleFields' => ['id' => true]
+                    ]
+                ]
+            ]
+        ]
+    ]);
+
+The above will keep the association unchanged between Comments and Users for the
+concerned entity.
+
 Once you've converted request data into entities you can ``save()`` or
 ``delete()`` them::
 
@@ -143,7 +349,7 @@ In order to update entities you may choose to apply request data directly to an
 existing entity. This has the advantage that only the fields that actually
 changed will be saved, as opposed to sending all fields to the database to be
 persisted. You can merge an array of raw data into an existing entity using the
-``patchEntity`` method::
+``patchEntity()`` method::
 
     // In a controller.
     $articles = TableRegistry::get('Articles');
@@ -151,8 +357,33 @@ persisted. You can merge an array of raw data into an existing entity using the
     $articles->patchEntity($article, $this->request->data());
     $articles->save($article);
 
+
+Validation and patchEntity
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Similar to ``newEntity()``, the ``patchEntity`` method will validate the data
+before it is copied to the entity. The mechanism is explained in the
+:ref:`validating-request-data` section. If you wish to disable validation while
+patching an entity, pass the ``validate`` option as follows::
+
+    // In a controller.
+    $articles = TableRegistry::get('Articles');
+    $article = $articles->get(1);
+    $articles->patchEntity($article, $data, ['validate' => false]);
+
+You may also change the validation set used for the entity or any of the
+associations::
+
+    $articles->patchEntity($article, $this->request->data(), [
+        'validate' => 'custom',
+        'associated' => ['Tags', 'Comments.Users' => ['validate' => 'signup']]
+    ]);
+
+Patching HasMany and BelongsToMany
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 As explained in the previous section, the request data should follow the
-structure of your entity. The ``patchEntity`` method is equally capable of
+structure of your entity. The ``patchEntity()`` method is equally capable of
 merging associations, by default only the first level of associations are
 merged, but if you wish to control the list of associations to be merged or
 merge deeper to deeper levels, you can use the third parameter of the method::
@@ -188,6 +419,20 @@ a new user entity::
 The same can be said about hasMany and belongsToMany associations, but an
 important note should be made.
 
+.. note::
+
+    For belongsToMany associations, ensure the relevant entity has
+    a property accessible for the associated entity.
+
+
+If a Product belongsToMany Tag::
+
+    // in the Product Entity
+    protected $_accessible = [
+        // .. other properties
+       'tags' => true,
+    ];
+
 .. note::
 
     For hasMany and belongsToMany associations, if there were any entities that
@@ -209,6 +454,7 @@ For example, consider the following case::
         ]
     ];
     $entity = $articles->newEntity($data);
+    $articles->save($article);
 
     $newData = [
         'comments' => [
@@ -268,7 +514,7 @@ the original entities array will be removed and not present in the result::
         $articles->save($entity);
     }
 
-Similarly to using ``patchEntity``, you can use the third argument for
+Similarly to using ``patchEntity()``, you can use the third argument for
 controlling the associations that will be merged in each of the entities in the
 array::
 
@@ -279,6 +525,7 @@ array::
         ['associated' => ['Tags', 'Comments.Users']]
     );
 
+
 .. _before-marshal:
 
 Modifying Request Data Before Building Entities
@@ -297,106 +544,11 @@ request data just before entities are created::
 The ``$data`` parameter is an ``ArrayObject`` instance, so you don't have to
 return it to change the data used to create entities.
 
-
-.. _validating-request-data:
-
 Validating Data Before Building Entities
 ----------------------------------------
 
-When marshalling data into entities, you can validate data. Validating data
-allows you to check the type, shape and size of data. By default request data
-will be validated before it is converted into entities.
-If any validation rules fail, the returned entity will contain errors. The
-fields with errors will not be present in the returned entity::
-
-    $article = $articles->newEntity($this->request->data);
-    if ($article->errors()) {
-        // Entity failed validation.
-    }
-
-When building an entity with validation enabled the following things happen:
-
-1. The validator object is created.
-2. The ``table`` and ``default`` validation provider are attached.
-3. The named validation method is invoked. For example, ``validationDefault``.
-4. The ``Model.buildValidator`` event will be triggered.
-5. Request data will be validated.
-6. Request data will be type cast into types that match the column types.
-7. Errors will be set into the entity.
-8. Valid data will be set into the entity, while fields that failed validation
-   will be left out.
-
-If you'd like to disable validation when converting request data, set the
-``validate`` option to false::
-
-    $article = $articles->newEntity(
-        $this->request->data,
-        ['validate' => false]
-    );
-
-In addition to disabling validation you can choose which validation rule set you
-want applied::
-
-    $article = $articles->newEntity(
-        $this->request->data,
-        ['validate' => 'update']
-    );
-
-The above would call the ``validationUpdate`` method on the table instance to
-build the required rules. By default the ``validationDefault`` method will be
-used. A sample validator for our articles table would be::
-
-    class ArticlesTable extends Table
-    {
-        public function validationUpdate($validator)
-        {
-            $validator
-                ->add('title', 'notEmpty', [
-                    'rule' => 'notEmpty',
-                    'message' => __('You need to provide a title'),
-                ])
-                ->add('body', 'notEmpty', [
-                    'rule' => 'notEmpty',
-                    'message' => __('A body is required')
-                ]);
-            return $validator;
-        }
-    }
-
-You can have as many validation sets as you need. See the :doc:`validation
-chapter ` for more information on building
-validation rule-sets.
-
-Validation rules can use functions defined on any known providers. By default
-CakePHP sets up a few providers:
-
-1. Methods on the table class, or its behaviors are available on the ``table``
-   provider.
-2. The core :php:class:`~Cake\\Validation\\Validation` class is setup as the
-   ``default`` provider.
-
-When a validation rule is created you can name the provider of that rule. For
-example, if your entity had a 'isValidRole' method you could use it as
-a validation rule::
-
-    use Cake\ORM\Table;
-    use Cake\Validation\Validator;
-
-    class UsersTable extends Table
-    {
-
-        public function validationDefault(Validator $validator)
-        {
-            $validator
-                ->add('role', 'validRole', [
-                    'rule' => 'isValidRole',
-                    'message' => __('You need to provide a valid role'),
-                    'provider' => 'table',
-                ]);
-            return $validator;
-        }
-
-    }
+The :doc:`/orm/validation` chapter has more information on how to use the
+validation features of CakePHP to ensure your data stays correct and consistent.
 
 Avoiding Property Mass Assignment Attacks
 -----------------------------------------
@@ -442,7 +594,7 @@ can access and you want to let your users edit different data based on their
 privileges.
 
 The ``fieldList`` options is also accepted by the ``newEntity()``,
-``newEntities()`` and ``patchEntitites()`` methods.
+``newEntities()`` and ``patchEntities()`` methods.
 
 .. _saving-entities:
 
@@ -462,7 +614,7 @@ using ``newEntity()`` for passing into ``save()``. For example::
   }
 
 The ORM uses the ``isNew()`` method on an entity to determine whether or not an
-insert or update should be performed. If the ``isNew()`` method returns ``null``
+insert or update should be performed. If the ``isNew()`` method returns ``true``
 and the entity has a primary key value, an 'exists' query will be issued. The
 'exists' query can be suppressed by passing ``'checkExisting' => false`` in the
 ``$options`` argument::
@@ -536,36 +688,20 @@ option::
     // In a controller.
 
     // Only save the comments association
-    $articles->save($entity, ['associated' => ['Comments']);
+    $articles->save($entity, ['associated' => ['Comments']]);
 
 You can define save distant or deeply nested associations by using dot notation::
 
     // Save the company, the employees and related addresses for each of them.
     $companies->save($entity, ['associated' => ['Employees.Addresses']]);
 
-If you need to run a different validation rule set for any association you can
-specify it as an options array for the association::
-
-    // In a controller.
-
-    // Save the company, the employees and related addresses for each of them.
-    // For employees use the 'special' validation group
-    $companies->save($entity, [
-      'associated' => [
-        'Employees' => [
-          'associated' => ['Addresses'],
-          'validate' => 'special',
-        ]
-      ]
-    ]);
-
 Moreover, you can combine the dot notation for associations with the options
 array::
 
     $companies->save($entity, [
       'associated' => [
         'Employees',
-        'Employees.Addresses' => ['validate' => 'special']
+        'Employees.Addresses'
       ]
     ]);
 
@@ -573,11 +709,17 @@ Your entities should be structured in the same way as they are when
 loaded from the database. See the form helper documentation for :ref:`how to
 build inputs for associations `.
 
+If you are building or modifying association data after building your entities
+you will have to mark the association property as modified with ``dirty()``::
+
+    $company->author->name = 'Master Chef';
+    $company->dirty('author', true);
+
 Saving BelongsTo Associations
 -----------------------------
 
 When saving belongsTo associations, the ORM expects a single nested entity at
-the singular, camel cased version the association name. For
+the singular, underscored version of the association name. For
 example::
 
     // In a controller.
@@ -599,7 +741,7 @@ Saving HasOne Associations
 --------------------------
 
 When saving hasOne associations, the ORM expects a single nested entity at the
-singular, camel cased version the association name. For example::
+singular, underscored version of the association name. For example::
 
     // In a controller.
     $data = [
@@ -619,7 +761,7 @@ Saving HasMany Associations
 ---------------------------
 
 When saving hasMany associations, the ORM expects an array of entities at the
-plural, camel cased version the association name. For example::
+plural, underscored version of the association name. For example::
 
     // In a controller.
     $data = [
@@ -650,7 +792,7 @@ Saving BelongsToMany Associations
 ---------------------------------
 
 When saving belongsToMany associations, the ORM expects an array of entities at the
-plural, camel cased version the association name. For example::
+plural, underscored version of the association name. For example::
 
     // In a controller.
 
@@ -667,8 +809,8 @@ plural, camel cased version the association name. For example::
     ]);
     $articles->save($article);
 
-When converting request data into entities, the ``newEntity`` and
-``newEntities`` methods will handle both arrays of properties, as well as a list
+When converting request data into entities, the ``newEntity()`` and
+``newEntities()`` methods will handle both arrays of properties, as well as a list
 of ids at the ``_ids`` key. Using the ``_ids`` key makes it easy to build a
 select box or checkbox based form controls for belongs to many associations. See
 the :ref:`converting-request-data` section for more information.
@@ -696,6 +838,30 @@ persisted::
 
 Without the call to ``dirty()`` the updated tags will not be saved.
 
+Often you'll find yourself wanting to make an association between two existing
+entities, eg. a user coauthoring an article. This is done by using the method
+``link()``, like this::
+
+    $article = $this->Articles->get($articleId);
+    $user = $this->Users->get($userId);
+
+    $this->Articles->Users->link($article, [$user]);
+
+When saving belongsToMany Associations, it can be relevant to save some
+additional data to the Joint Table.  In the previous example of tags, it could
+be the ``vote_type`` of person who voted on that article.  The ``vote_type`` can
+be either ``upvote`` or ``downvote`` and is represented by a string.  The
+relation is between Users and Articles.
+
+Saving that association, and the ``vote_type`` is done by first adding some data
+to ``_joinData`` and then saving the association with ``link()``, example::
+
+    $article = $this->Articles->get($articleId);
+    $user = $this->Users->get($userId);
+
+    $user->_joinData = new Entity(['vote_type' => $voteType, ['markNew' => true]]);
+    $this->Articles->Users->link($article, [$user]);
+
 Saving Additional Data to the Joint Table
 -----------------------------------------
 
@@ -794,147 +960,6 @@ receiving from the end user is the correct type. Failing to correctly handle
 complex data could result in malicious users being able to store data they
 would not normally be able to.
 
-.. _application-rules:
-
-Applying Application Rules
-==========================
-
-While basic data validation is done when :ref:`request data is converted into
-entities `, many applications also have more complex
-validation that should only be applied after basic validation has completed.
-These types of rules are often referred to as 'domain rules' or 'application
-rules'. CakePHP exposes this concept through 'RulesCheckers' which are applied
-before entities are persisted. Some example domain rules are:
-
-* Ensuring email uniqueness
-* State transitions or workflow steps, for example updating an invoice's status.
-* Preventing modification of soft deleted items.
-* Enforcing usage/rate limit caps.
-
-Creating a Rules Checker
-------------------------
-
-Rules checker classes are generally defined by the ``buildRules`` method in your
-table class. Behaviors and other event subscribers can use the
-``Model.buildRules`` event to augment the rules checker for a given Table
-class::
-
-    use Cake\ORM\RulesChecker;
-
-    // In a table class
-    public function buildRules(RulesChecker $rules)
-    {
-        // Add a rule that is applied for create and update operations
-        $rules->add(function ($entity, $options) {
-            // Return a boolean to indicate pass/fail
-        }, 'ruleName');
-
-        // Add a rule for create.
-        $rules->addCreate(function ($entity, $options) {
-        }, 'ruleName');
-
-        // Add a rule for update
-        $rules->addUpdate(function ($entity, $options) {
-        }, 'ruleName');
-
-        // Add a rule for the deleting.
-        $rules->addDelete(function ($entity, $options) {
-        }, 'ruleName');
-
-        return $rules;
-    }
-
-Your rules functions can expect to get the Entity being checked, and an array of
-options. The options array will contain ``errorField``, ``message``, and
-``repository``. The ``repository`` option will contain the table class the rules
-are attached to. Because rules accept any ``callable``, you can also use
-instance functions::
-
-    $rules->addCreate([$this, 'uniqueEmail'], 'uniqueEmail');
-
-or callable classes::
-
-    $rules->addCreate(new IsUnique(['email']), 'uniqueEmail');
-
-When adding rules you can define the field the rule is for, and the error
-message as options::
-
-    $rules->add([$this, 'isValidState'], 'validState', [
-        'errorField' => 'status',
-        'message' => 'This invoice cannot be moved to that status.'
-    ]);
-
-Creating Unique Field Rules
----------------------------
-
-Because unique rules are quite common, CakePHP includes a simple Rule class that
-allows you to easily define unique field sets::
-
-    use Cake\ORM\Rule\IsUnique;
-
-    // A single field.
-    $rules->add($rules->isUnique(['email']));
-
-    // A list of fields
-    $rules->add($rules->isUnique(['username', 'account_id']));
-
-Foreign Key Rules
------------------
-
-While you could rely on database errors to enforce constraints, using rules code
-can help provide a nicer user experience. Because of this CakePHP includes an
-``ExistsIn`` rule class::
-
-    // A single field.
-    $rules->add($rules->existsIn('article_id', 'articles'));
-
-    // Multiple keys, useful for composite primary keys.
-    $rules->add($rules->existsIn(['site_id', 'article_id'], 'articles'));
-
-Using Entity Methods as Rules
------------------------------
-
-You may want to use entity methods as domain rules::
-
-    $rules->add(function ($entity, $options) {
-        return $entity->isOkLooking();
-    }, 'ruleName');
-
-Creating Custom Rule objects
-----------------------------
-
-If your application has rules that are commonly reused, it is helpful to package
-those rules into re-usable classes::
-
-    // in src/Model/Rule/CustomRule.php
-    namespace App\Model\Rule;
-
-    use Cake\Datasource\EntityInterface;
-
-    class CustomRule
-    {
-        public function __invoke(EntityInterface $entity, array $options)
-        {
-            // Do work
-            return false;
-        }
-    }
-
-
-    // Add the custom rule
-    use App\Model\Rule\CustomRule;
-
-    $rules->add(new CustomRule(...), 'ruleName');
-
-By creating custom rule classes you can keep your code DRY and make your domain
-rules easy to test.
-
-Disabling Rules
----------------
-
-When saving an entity, you can disable the rules if necessary::
-
-    $articles->save($article, ['checkRules' => false]);
 
 Bulk Updates
 ============
diff --git a/en/orm/schema-system.rst b/en/orm/schema-system.rst
index e7e64c6bf19272f167ae97bbf3facaa850bc553a..368ca24adc00adf36e944e0d1b0773c93b6013ed 100644
--- a/en/orm/schema-system.rst
+++ b/en/orm/schema-system.rst
@@ -115,10 +115,10 @@ platform::
 
     $t = new Table('posts');
     $t->addColumn('id', 'integer')
-        ->addConstraint('primary', [
-            'type' => 'primary',
-            'columns' => ['id']
-        ]);
+    ->addConstraint('primary', [
+        'type' => 'primary',
+        'columns' => ['id']
+    ]);
 
 In the above example the ``id`` column would generate the following SQL in
 MySQL::
diff --git a/en/orm/table-objects.rst b/en/orm/table-objects.rst
index efbe371f905b32e43b5eb205d91075eb17fe229e..bf45190034cbec900670724dff7fbb4c3cb6c374 100644
--- a/en/orm/table-objects.rst
+++ b/en/orm/table-objects.rst
@@ -18,7 +18,7 @@ Basic Usage
 ===========
 
 To get started, create a Table class. These classes live in
-``src/Model/Table``. Tables are a type model collection specific to relational
+**src/Model/Table**. Tables are a type model collection specific to relational
 databases, and the main interface to your database in CakePHP's ORM. The most
 basic table class would look like::
 
@@ -74,7 +74,7 @@ By default table objects use an entity class based on naming conventions. For
 example if your table class is called ``ArticlesTable`` the entity would be
 ``Article``. If the table class was ``PurchaseOrdersTable`` the entity would be
 ``PurchaseOrder``. If however, you want to use an entity that doesn't follow the
-conventions you can use the ``entityClass`` method to change things up::
+conventions you can use the ``entityClass()`` method to change things up::
 
     class PurchaseOrdersTable extends Table
     {
@@ -115,7 +115,7 @@ overriding methods. Event listeners can be defined in table or behavior classes.
 You can also use a table's event manager to bind listeners in.
 
 When using callback methods behaviors attached in the
-``initialize`` method will have their listeners fired **before** the table
+``initialize()`` method will have their listeners fired **before** the table
 callback methods are triggered. This follows the same sequencing as controllers
 & components.
 
@@ -174,8 +174,8 @@ beforeRules
 .. php:method:: beforeRules(Event $event, Entity $entity, ArrayObject $options, $operation)
 
 The ``Model.beforeRules`` event is fired before an entity has rules applied. By
-stopping this event, you can return the final value of the rules checking
-operation.
+stopping this event, you can short circuit the rules checking and set the result
+of applying rules'.
 
 afterRules
 --------------
@@ -202,6 +202,17 @@ afterSave
 
 The ``Model.afterSave`` event is fired after an entity is saved.
 
+afterSaveCommit
+---------------
+
+.. php:method:: afterSaveCommit(Event $event, Entity $entity, ArrayObject $options)
+
+The ``Model.afterSaveCommit`` event is fired after the transaction in which the
+save operation is wrapped has been committed. It's also triggered for non atomic
+saves where database operations are implicitly committed. The event is triggered
+only for the primary table on which ``save()`` is directly called. The event is
+not triggered if a transaction is started before calling save.
+
 beforeDelete
 ------------
 
@@ -215,12 +226,23 @@ afterDelete
 
 .. php:method:: afterDelete(Event $event, Entity $entity, ArrayObject $options)
 
-The ``Model.beforeDelete`` event is fired after an entity has been deleted.
+The ``Model.afterDelete`` event is fired after an entity has been deleted.
+
+afterDeleteCommit
+-----------------
+
+.. php:method:: afterDeleteCommit(Event $event, Entity $entity, ArrayObject $options)
+
+The ``Model.afterDeleteCommit`` event is fired after the transaction in which the
+delete operation is wrapped has been is committed. It's also triggered for non
+atomic deletes where database operations are implicitly committed. The event is
+triggered only for the primary table on which ``delete()`` is directly called.
+The event is not triggered if a transaction is started before calling delete.
 
 Behaviors
 =========
 
-.. php:method:: addBehavior($name, $config = [])
+.. php:method:: addBehavior($name, array $options = [])
 
 .. start-behaviors
 
@@ -229,8 +251,8 @@ related to table classes. You may be wondering why behaviors are regular classes
 and not traits. The primary reason for this is event listeners. While traits
 would allow for re-usable pieces of logic, they would complicate binding events.
 
-To add a behavior to your table you can call the ``addBehavior`` method.
-Generally the best place to do this is in the ``initialize`` method::
+To add a behavior to your table you can call the ``addBehavior()`` method.
+Generally the best place to do this is in the ``initialize()`` method::
 
     namespace App\Model\Table;
 
@@ -278,7 +300,7 @@ Configuring Connections
 
 By default all table instances use the ``default`` database connection. If your
 application uses multiple database connections you will want to configure which
-tables use which connections. This is the ``defaultConnectionName`` method::
+tables use which connections. This is the ``defaultConnectionName()`` method::
 
     namespace App\Model\Table;
 
@@ -293,7 +315,7 @@ tables use which connections. This is the ``defaultConnectionName`` method::
 
 .. note::
 
-    The ``defaultConnectionName`` method **must** be static.
+    The ``defaultConnectionName()`` method **must** be static.
 
 .. _table-registry-usage:
 
@@ -317,13 +339,17 @@ use mock objects by providing an ``$options`` array::
     $articles = TableRegistry::get('Articles', [
         'className' => 'App\Custom\ArticlesTable',
         'table' => 'my_articles',
-        'connection' => $connection,
+        'connection' => $connectionObject,
         'schema' => $schemaObject,
         'entityClass' => 'Custom\EntityClass',
         'eventManager' => $eventManager,
         'behaviors' => $behaviorRegistry
     ]);
 
+Pay attention to the connection and schema configuration settings, they aren't
+string values but objects. The connection will take an object of
+``Cake\Database\Connection`` and schema ``Cake\Database\Schema\Collection``.
+
 .. note::
 
     If your table also does additional configuration in its ``initialize()`` method,
diff --git a/en/orm/validation.rst b/en/orm/validation.rst
new file mode 100644
index 0000000000000000000000000000000000000000..ae8a5e222d638a3c1bbd0ec39c1d8cee6b2e39fd
--- /dev/null
+++ b/en/orm/validation.rst
@@ -0,0 +1,553 @@
+Validating Data
+###############
+
+Before you :doc:`save your data` you
+will probably want to ensure the data is correct and consistent. In CakePHP we
+have two stages of validation:
+
+1. Before request data is converted into entities, validation rules around
+   data types and formatting can be applied.
+2. Before data is saved, domain or application rules can be applied. These rules
+   help ensure that your application's data remains consistent.
+
+.. _validating-request-data:
+
+Validating Data Before Building Entities
+========================================
+
+When marshalling data into entities, you can validate data. Validating data
+allows you to check the type, shape and size of data. By default request data
+will be validated before it is converted into entities.
+If any validation rules fail, the returned entity will contain errors. The
+fields with errors will not be present in the returned entity::
+
+    $article = $articles->newEntity($this->request->data);
+    if ($article->errors()) {
+        // Entity failed validation.
+    }
+
+When building an entity with validation enabled the following occurs:
+
+1. The validator object is created.
+2. The ``table`` and ``default`` validation provider are attached.
+3. The named validation method is invoked. For example ``validationDefault``.
+4. The ``Model.buildValidator`` event will be triggered.
+5. Request data will be validated.
+6. Request data will be type-cast into types that match the column types.
+7. Errors will be set into the entity.
+8. Valid data will be set into the entity, while fields that failed validation
+   will be excluded.
+
+If you'd like to disable validation when converting request data, set the
+``validate`` option to false::
+
+    $article = $articles->newEntity(
+        $this->request->data,
+        ['validate' => false]
+    );
+
+The same can be said about the ``patchEntity()`` method::
+
+    $article = $articles->patchEntity($article, $newData, [
+        'validate' => false
+    ]);
+
+Creating A Default Validation Set
+=================================
+
+Validation rules are defined in the Table classes for convenience. This defines
+what data should be validated in conjunction with where it will be saved.
+
+
+To create a default validation object in your table, create the
+``validationDefault()`` function::
+
+    use Cake\ORM\Table;
+    use Cake\Validation\Validator;
+
+    class ArticlesTable extends Table
+    {
+
+        public function validationDefault(Validator $validator)
+        {
+            $validator
+                ->requirePresence('title', 'create')
+                ->notEmpty('title');
+
+            $validator
+                ->allowEmpty('link')
+                ->add('link', 'valid-url', ['rule' => 'url']);
+
+            ...
+
+            return $validator;
+        }
+    }
+
+The available validation methods and rules come from the ``Validator`` class and
+are documented in the :ref:`creating-validators` section.
+
+.. note::
+
+    Validation objects are intended primarily for validating user input, i.e.
+    forms and any other posted request data.
+
+
+Using A Different Validation Set
+================================
+
+In addition to disabling validation you can choose which validation rule set you
+want applied::
+
+    $article = $articles->newEntity(
+        $this->request->data,
+        ['validate' => 'update']
+    );
+
+The above would call the ``validationUpdate()`` method on the table instance to
+build the required rules. By default the ``validationDefault()`` method will be
+used. An example validator for our articles table would be::
+
+    class ArticlesTable extends Table
+    {
+        public function validationUpdate($validator)
+        {
+            $validator
+                ->add('title', 'notEmpty', [
+                    'rule' => 'notEmpty',
+                    'message' => __('You need to provide a title'),
+                ])
+                ->add('body', 'notEmpty', [
+                    'rule' => 'notEmpty',
+                    'message' => __('A body is required')
+                ]);
+            return $validator;
+        }
+    }
+
+You can have as many validation sets as necessary. See the :doc:`validation
+chapter ` for more information on building
+validation rule-sets.
+
+Using A Different Validation Set For Associations
+-------------------------------------------------
+
+Validation sets can also be defined per association. When using the
+``newEntity()`` or ``patchEntity()`` methods, you can pass extra options to each
+of the associations to be converted::
+
+   $data = [
+        'title' => 'My title',
+        'body' => 'The text',
+        'user_id' => 1,
+        'user' => [
+            'username' => 'mark'
+        ],
+        'comments' => [
+            ['body' => 'First comment'],
+            ['body' => 'Second comment'],
+        ]
+    ];
+
+    $article = $articles->patchEntity($article, $data, [
+        'validate' => 'update',
+        'associated' => [
+            'Users' => ['validate' => 'signup'],
+            'Comments' => ['validate' => 'custom']
+        ]
+    ]);
+
+Combining Validators
+====================
+
+Because of how validator objects are built, it is easy to break their
+construction process into multiple reusable steps::
+
+    // UsersTable.php
+
+    public function validateDefault(Validator $validator)
+    {
+        $validator->notEmpty('username');
+        $validator->notEmpty('password');
+        $validator->add('email', 'valid-email', ['rule' => 'email']);
+        ...
+
+        return $validator;
+    }
+
+    public function validateHardened(Validator $validator)
+    {
+        $validator = $this->validateDefault($validator);
+
+        $validator->add('password', 'length', ['rule' => 'between', 8, 100]);
+        return $validator;
+    }
+
+Given the above setup, when using the ``hardened`` validation set, it will also
+contain the validation rules declared in the ``default`` set.
+
+Validation Providers
+====================
+
+Validation rules can use functions defined on any known providers. By default
+CakePHP sets up a few providers:
+
+1. Methods on the table class or its behaviors are available on the ``table``
+   provider.
+2. The core :php:class:`~Cake\\Validation\\Validation` class is setup as the
+   ``default`` provider.
+
+When a validation rule is created you can name the provider of that rule. For
+example, if your table has an ``isValidRole`` method you can use it as
+a validation rule::
+
+    use Cake\ORM\Table;
+    use Cake\Validation\Validator;
+
+    class UsersTable extends Table
+    {
+
+        public function validationDefault(Validator $validator)
+        {
+            $validator
+                ->add('role', 'validRole', [
+                    'rule' => 'isValidRole',
+                    'message' => __('You need to provide a valid role'),
+                    'provider' => 'table',
+                ]);
+            return $validator;
+        }
+
+        public function isValidRole($value, array $context)
+        {
+            return in_array($value, ['admin', 'editor', 'author'], true);
+        }
+
+    }
+
+You can also use closures for validation rules::
+
+    $validator->add('name', 'myRule', [
+        'rule' => function ($data, $provider) {
+            if ($data > 1) {
+                return true;
+            }
+            return 'Not a good value.';
+        }
+    ]);
+
+Validation methods can return error messages when they fail. This is a simple
+way to make error messages dynamic based on the provided value.
+
+Getting Validators From Tables
+==============================
+
+Once you have created a few validation sets in your table class, you can get the
+resulting object by name::
+
+    $defaultValidator = $usersTable->validator('default');
+
+    $hardenedValidator = $usersTable->validator('hardened');
+
+Default Validator Class
+=======================
+
+As stated above, by default the validation methods receive an instance of
+``Cake\Validation\Validator``. Instead, if you want your custom validator's
+instance to be used each time, you can use table's ``$_validatorClass`` property::
+
+    // In your table class
+    public function initialize()
+    {
+        $this->_validatorClass = '\FullyNamespaced\Custom\Validator';
+    }
+
+.. _application-rules:
+
+Applying Application Rules
+==========================
+
+While basic data validation is done when :ref:`request data is converted into
+entities `, many applications also have more complex
+validation that should only be applied after basic validation has completed.
+
+These types of rules are often referred to as 'domain rules' or 'application
+rules'. CakePHP exposes this concept through 'RulesCheckers' which are applied
+before entities are persisted. Some example domain rules are:
+
+* Ensuring email uniqueness
+* State transitions or workflow steps (e.g., updating an invoice's status).
+* Preventing the modification of soft deleted items.
+* Enforcing usage/rate limit caps.
+
+Domain rules are checked when calling the Table ``save()`` and ``delete()`` methods.
+
+Creating a Rules Checker
+------------------------
+
+Rules checker classes are generally defined by the ``buildRules()`` method in your
+table class. Behaviors and other event subscribers can use the
+``Model.buildRules`` event to augment the rules checker for a given Table
+class::
+
+    use Cake\ORM\RulesChecker;
+
+    // In a table class
+    public function buildRules(RulesChecker $rules)
+    {
+        // Add a rule that is applied for create and update operations
+        $rules->add(function ($entity, $options) {
+            // Return a boolean to indicate pass/failure
+        }, 'ruleName');
+
+        // Add a rule for create.
+        $rules->addCreate(function ($entity, $options) {
+            // Return a boolean to indicate pass/failure
+        }, 'ruleName');
+
+        // Add a rule for update
+        $rules->addUpdate(function ($entity, $options) {
+            // Return a boolean to indicate pass/failure
+        }, 'ruleName');
+
+        // Add a rule for the deleting.
+        $rules->addDelete(function ($entity, $options) {
+            // Return a boolean to indicate pass/failure
+        }, 'ruleName');
+
+        return $rules;
+    }
+
+Your rules functions can expect to get the Entity being checked and an array of
+options. The options array will contain ``errorField``, ``message``, and
+``repository``. The ``repository`` option will contain the table class the rules
+are attached to. Because rules accept any ``callable``, you can also use
+instance functions::
+
+    $rules->addCreate([$this, 'uniqueEmail'], 'uniqueEmail');
+
+or callable classes::
+
+    $rules->addCreate(new IsUnique(['email']), 'uniqueEmail');
+
+When adding rules you can define the field the rule is for and the error
+message as options::
+
+    $rules->add([$this, 'isValidState'], 'validState', [
+        'errorField' => 'status',
+        'message' => 'This invoice cannot be moved to that status.'
+    ]);
+
+The error will be visible when calling the ``errors()`` method on the entity::
+
+    $entity->errors(); // Contains the domain rules error messages
+
+Creating Unique Field Rules
+---------------------------
+
+Because unique rules are quite common, CakePHP includes a simple Rule class that
+allows you to easily define unique field sets::
+
+    use Cake\ORM\Rule\IsUnique;
+
+    // A single field.
+    $rules->add($rules->isUnique(['email']));
+
+    // A list of fields
+    $rules->add($rules->isUnique(['username', 'account_id']));
+
+When setting rules on foreign key fields it is important to remember, that
+only the fields listed are used in the rule. This means that setting
+``$user->account->id`` will not trigger the above rule.
+
+
+Foreign Key Rules
+-----------------
+
+While you could rely on database errors to enforce constraints, using rules code
+can help provide a nicer user experience. Because of this CakePHP includes an
+``ExistsIn`` rule class::
+
+    // A single field.
+    $rules->add($rules->existsIn('article_id', 'articles'));
+
+    // Multiple keys, useful for composite primary keys.
+    $rules->add($rules->existsIn(['site_id', 'article_id'], 'articles'));
+
+The fields to check existence against in the related table must be part of the
+primary key.
+
+Using Entity Methods as Rules
+-----------------------------
+
+You may want to use entity methods as domain rules::
+
+    $rules->add(function ($entity, $options) {
+        return $entity->isOkLooking();
+    }, 'ruleName');
+
+Creating Custom Rule objects
+----------------------------
+
+If your application has rules that are commonly reused, it is helpful to package
+those rules into re-usable classes::
+
+    // in src/Model/Rule/CustomRule.php
+    namespace App\Model\Rule;
+
+    use Cake\Datasource\EntityInterface;
+
+    class CustomRule
+    {
+        public function __invoke(EntityInterface $entity, array $options)
+        {
+            // Do work
+            return false;
+        }
+    }
+
+
+    // Add the custom rule
+    use App\Model\Rule\CustomRule;
+
+    $rules->add(new CustomRule(...), 'ruleName');
+
+By creating custom rule classes you can keep your code DRY and make your domain
+rules easy to test.
+
+Disabling Rules
+---------------
+
+When saving an entity, you can disable the rules if necessary::
+
+    $articles->save($article, ['checkRules' => false]);
+
+
+Validation vs. Application Rules
+================================
+
+The CakePHP ORM is unique in that it uses a two-layered approach to validation.
+As you already discovered, the first layer is done through the ``Validator``
+objects when calling ``newEntity()`` or ``patchEntity()``::
+
+    $validatedEntity = $articlesTable->newEntity($unsafeData);
+    $validatedEntity = $articlesTable->patchEntity($entity, $unsafeData);
+
+Validation is defined using the ``validationCustomName()`` methods::
+
+    public function validationCustom($validator)
+    {
+        $validator->add(...);
+        return $validator;
+    }
+
+Validation is meant for forms and request data. This means that validation rule
+sets can assume things about the structure of a form and validate fields not in
+the schema of the database. Validation assumes strings or array are passed
+since that is what is received from any request::
+
+    // In src/Model/Table/UsersTable.php
+    public function validatePasswords($validator)
+    {
+        $validator->add('confirm_password', 'no-misspelling', [
+            'rule' => ['compareWith', 'password'],
+            'message' => 'Passwords are not equal',
+        ]);
+
+        ...
+        return $validator;
+    }
+
+Validation is **not** triggered when directly setting properties on your
+entities::
+
+    $userEntity->email = 'not an email!!';
+    $usersTable->save($userEntity);
+
+In the above example the entity will be saved as validation is only
+triggered for the ``newEntity()`` and ``patchEntity()`` methods. The second
+level of validation is meant to address this situation.
+
+Application rules as explained above will be checked whenever ``save()`` or
+``delete()`` are called::
+
+    // In src/Model/Table/UsersTable.php
+    public function buildRules(RulesChecker $rules)
+    {
+        $rules->add($rules->isUnique('email'));
+        return $rules;
+    }
+
+    // Elsewhere in your application code
+    $userEntity->email = 'a@duplicated.email';
+    $usersTable->save($userEntity); // Returns false
+
+While Validation is meant for direct user input, application rules are specific
+for data transitions generated inside your application::
+
+    // In src/Model/Table/OrdersTable.php
+    public function buildRules(RulesChecker $rules)
+    {
+        $check = function($order) {
+            return $order->price < 100 && $order->shipping_mode === 'free';
+        };
+        $rules->add($check, [
+            'errorField' => 'shipping_mode',
+            'message' => 'No free shipping for orders under 100!'
+        ]);
+        return $rules;
+    }
+
+    // Elsewhere in application code
+    $order->price = 50;
+    $order->shipping_mode = 'free';
+    $ordersTable->save($order); // Returns false
+
+
+Using Validation as Application Rules
+-------------------------------------
+
+In certain situations you may want to run the same data validation routines for
+data that was both generated by users and inside your application. This could
+come up when running a CLI script that directly sets properties on entities::
+
+    // In src/Model/Table/UsersTable.php
+    public function validationDefault(Validator $validator)
+    {
+        $validator->add('email', 'valid', [
+            'rule' => 'email',
+            'message' => 'Invalid email'
+        ]);
+        ...
+        return $validator;
+    }
+
+    public function buildRules(RulesChecker $rules)
+    {
+        // Add validation rules
+        $rules->add(function($entity) {
+            $data = $entity->extract($this->schema()->columns(), true);
+            $validator = $this->validator('default');
+            $errors = $validator->errors($data, $entity->isNew());
+            $entity->errors($errors);
+
+            return empty($errors);
+        });
+
+        ...
+
+        return $rules;
+    }
+
+When executed the save will fail thanks to the new application rule that 
+was added::
+
+    $userEntity->email = 'not an email!!!';
+    $usersTable->save($userEntity);
+    $userEntity->errors('email'); // Invalid email
+
+The same result can be expected when using ``newEntity()`` or
+``patchEntity()``::
+
+    $userEntity = $usersTable->newEntity(['email' => 'not an email!!']);
+    $userEntity->errors('email'); // Invalid email
diff --git a/en/pdf-contents.rst b/en/pdf-contents.rst
index f6af535cc6bf270e95238ed785609d81599e2a9b..a63813ef5c805b96740fd2e9c6c518b47c7a6dbd 100644
--- a/en/pdf-contents.rst
+++ b/en/pdf-contents.rst
@@ -17,19 +17,20 @@ Contents
     controllers
     views
     orm
-    development/errors
 
+    controllers/components/authentication
+    bake
     core-libraries/caching
     console-and-shells
-    bake
     development/debugging
     deployment
     core-libraries/email
+    development/errors
     core-libraries/events
     core-libraries/internationalization-and-localization
     core-libraries/logging
-    controllers/components/pagination
     core-libraries/form
+    controllers/components/pagination
     plugins
     development/rest
     security
@@ -51,6 +52,7 @@ Contents
 
     core-libraries/global-constants-and-functions
     debug-kit
+    migrations
     appendices
 
 
diff --git a/en/plugins.rst b/en/plugins.rst
index 02536caa077023b17599bea80d0b10dfcb4a7acd..6703bee1af1b0252ee67091c2489b2161d494104 100644
--- a/en/plugins.rst
+++ b/en/plugins.rst
@@ -10,7 +10,7 @@ in other applications and share with the community.
 
 The main tie between a plugin and the application it has been
 installed into is the application's configuration (database
-connection, etc.). Otherwise, it operates in its own space,
+connection, etc.). Otherwise it operates in its own space,
 behaving much like it would if it were an application on its own.
 
 In CakePHP 3.0 each plugin defines its own top-level namespace. For example:
@@ -44,7 +44,7 @@ Plugin Map File
 
 When installing plugins via Composer, you may notice that
 ``vendor/cakephp-plugins.php`` is created. This configuration file contains
-a map of plugin names, and their paths on the filesystem. It makes it possible
+a map of plugin names and their paths on the filesystem. It makes it possible
 for plugins to be installed into the standard vendor directory which is outside
 of the normal search paths. The ``Plugin`` class will use this file to locate
 plugins when they are loaded with ``load()`` or ``loadAll()``. You generally
@@ -77,6 +77,8 @@ plugins you explicitly specify.
     ``Plugin::loadAll()`` won't load vendor namespaced plugins that are not
     defined in ``vendor/cakephp-plugins.php``.
 
+.. _autoloading-plugin-classes:
+
 Autoloading Plugin Classes
 --------------------------
 
@@ -93,8 +95,8 @@ to contain the following information::
         "MyPlugin\\Test\\": "./plugins/MyPlugin/tests"
     }
 
-If you are using vendor namespace for your plugins the namespace to path mapping
-should be like::
+If you are using vendor namespaces for your plugins, the namespace to path mapping
+should resemble the following::
 
     "psr-4": {
         (...)
@@ -102,7 +104,7 @@ should be like::
         "AcmeCorp\\Users\\Test\\": "./plugins/AcmeCorp/Users/tests"
     }
 
-Additionally you will need to tell Composer to refresh its autoloading cache::
+Additionally, you will need to tell Composer to refresh its autoloading cache::
 
     $ php composer.phar dumpautoload
 
@@ -118,7 +120,7 @@ Plugin Configuration
 
 There is a lot you can do with the ``load()`` and ``loadAll()`` methods to help
 with plugin configuration and routing. Perhaps you want to load all plugins
-automatically, while specifying custom routes and bootstrap files for
+automatically while specifying custom routes and bootstrap files for
 certain plugins::
 
     Plugin::loadAll([
@@ -127,11 +129,11 @@ certain plugins::
         'WebmasterTools' => ['bootstrap' => true, 'routes' => true],
     ]);
 
-With this style of configuration, you no longer need to manually
+With this style of configuration you no longer need to manually
 ``include()`` or ``require()`` a plugin's configuration or routes file -- it happens
 automatically at the right time and place. The exact same parameters could
 have also been supplied to the ``load()`` method, which would have loaded only those
-three plugins, and not the rest.
+three plugins and not the rest.
 
 Finally, you can also specify a set of defaults for ``loadAll()`` which will
 apply to every plugin that doesn't have a more specific configuration.
@@ -153,7 +155,7 @@ potential warnings by using the ``ignoreMissing`` option::
     ]);
 
 When loading plugins, the plugin name used should match the namespace.
-For example you have a plugin with top level namespace ``Users`` you would load
+For example, if you have a plugin with top level namespace ``Users`` you would load
 it using::
 
     Plugin::load('User');
@@ -234,7 +236,7 @@ Creating a Plugin Using Bake
 The process of creating plugins can be greatly simplified by using the bake
 shell.
 
-In order to bake a plugin please use the following command::
+In order to bake a plugin, use the following command::
 
     $ bin/cake bake plugin ContactManager
 
@@ -254,12 +256,12 @@ Plugin Controllers
 ==================
 
 Controllers for our ContactManager plugin will be stored in
-``plugins/ContactManager/src/Controller/``. Since the main thing we'll
+**plugins/ContactManager/src/Controller/**. Since the main thing we'll
 be doing is managing contacts, we'll need a ContactsController for
 this plugin.
 
 So, we place our new ContactsController in
-``plugins/ContactManager/src/Controller`` and it looks like so::
+**plugins/ContactManager/src/Controller** and it looks like so::
 
     // plugins/ContactManager/src/Controller/ContactsController.php
     namespace ContactManager\Controller;
@@ -275,43 +277,51 @@ So, we place our new ContactsController in
         }
     }
 
-.. note::
+Also make the ``AppController`` if you don't have one already::
 
-    This controller extends the plugin's AppController (called
-    ContactManagerAppController) rather than the parent application's
-    AppController.
+    // plugins/ContactManager/src/Controller/AppController.php
+    namespace ContactManager\Controller;
+
+    use App\Controller\AppController as BaseController;
+
+    class AppController extends BaseController
+    {
+    }
+
+A plugin's ``AppController`` can hold controller logic common to all controllers
+in a plugin but is not required if you don't want to use one.
 
 Before you can access your controllers, you'll need to ensure the plugin is
-loaded and connect some routes. In your ``config/bootstrap.php`` add the
+loaded and connect some routes. In your **config/bootstrap.php** add the
 following::
 
     Plugin::load('ContactManager', ['routes' => true]);
 
 Then create the ContactManager plugin routes. Put the following into
-``plugins/ContactManager/config/routes.php``::
+**plugins/ContactManager/config/routes.php**::
 
     fallbacks('InflectedRoute');
+        $routes->fallbacks('DashedRoute');
     });
 
 The above will connect default routes for you plugin. You can customize this
 file with more specific routes later on.
 
 If you want to access what we've got going thus far, visit
-``/contact_manager/contacts``. You should get a "Missing Model" error
+``/contact-manager/contacts``. You should get a "Missing Model" error
 because we don't have a Contact model defined yet.
 
 If your application includes the default routing CakePHP provides you will be
 able to access your plugin controllers using URLs like::
 
     // Access the index route of a plugin controller.
-    /contact_manager/contacts
+    /contact-manager/contacts
 
     // Any action on a plugin controller.
-    /contact_manager/contacts/view/1
+    /contact-manager/contacts/view/1
 
 If your application defines routing prefixes, CakePHP's default routing will
 also connect routes that use the following pattern::
@@ -322,12 +332,16 @@ also connect routes that use the following pattern::
 See the section on :ref:`plugin-configuration` for information on how to load
 plugin specific route files.
 
+For plugins you did not create with bake, you will also need to edit the
+``composer.json`` file to add your plugin to the autoload classes, this can be
+done as per the documentation :ref:`autoloading-plugin-classes`.
+
 .. _plugin-models:
 
 Plugin Models
 =============
 
-Models for the plugin are stored in ``plugins/ContactManager/src/Model``.
+Models for the plugin are stored in **plugins/ContactManager/src/Model**.
 We've already defined a ContactsController for this plugin, so let's
 create the table and entity for that controller::
 
@@ -349,7 +363,7 @@ create the table and entity for that controller::
     {
     }
 
-If you need to reference a model within your plugin when building associations,
+If you need to reference a model within your plugin when building associations
 or defining entitiy classes, you need to include the plugin name with the class
 name, separated with a dot. For example::
 
@@ -405,7 +419,7 @@ action, so let's include that as well::
     

Following is a sortable list of your contacts

-Plugins can provide their own layouts. Add plugin layouts, inside +Plugins can provide their own layouts. To add plugin layouts, place your template files inside ``plugins/[PluginName]/src/Template/Layout``. To use a plugin layout in your controller you can do the following:: @@ -429,8 +443,8 @@ Contacts controller you could make the following file:: src/Template/Plugin/ContactManager/Contacts/index.ctp -Creating this file, would allow you to override -``plugins/ContactManager/src/Template/Contacts/index.ctp``. +Creating this file would allow you to override +**plugins/ContactManager/src/Template/Contacts/index.ctp**. .. _plugin-assets: @@ -452,7 +466,7 @@ You may put any type of file in any directory, just like a regular webroot. .. warning:: - Handling static assets, such as images, JavaScript and CSS files, + Handling static assets (such as images, JavaScript and CSS files) through the Dispatcher is very inefficient. See :ref:`symlink-assets` for more information. @@ -463,13 +477,13 @@ Linking to Assets in Plugins You can use the :term:`plugin syntax` when linking to plugin assets using the :php:class:`~Cake\\View\\Helper\\HtmlHelper`'s script, image, or css methods:: - // Generates a url of /contact_manager/css/styles.css + // Generates a URL of /contact_manager/css/styles.css echo $this->Html->css('ContactManager.styles'); - // Generates a url of /contact_manager/js/widget.js + // Generates a URL of /contact_manager/js/widget.js echo $this->Html->script('ContactManager.widget'); - // Generates a url of /contact_manager/img/logo.js + // Generates a URL of /contact_manager/img/logo.js echo $this->Html->image('ContactManager.logo'); Plugin assets are served using the ``AssetFilter`` dispatcher filter by default. @@ -477,9 +491,9 @@ This is only recommended for development. In production you should :ref:`symlink plugin assets ` to improve performance. If you are not using the helpers, you can prepend /plugin_name/ to the beginning -of a the URL for an asset within that plugin to serve it. Linking to +of the URL for an asset within that plugin to serve it. Linking to '/contact_manager/js/some_file.js' would serve the asset -``plugins/ContactManager/webroot/js/some_file.js``. +**plugins/ContactManager/webroot/js/some_file.js**. Components, Helpers and Behaviors ================================= @@ -519,13 +533,13 @@ Expand Your Plugin This example created a good start for a plugin, but there is a lot more that you can do. As a general rule, anything you can do with your -application, you can do inside of a plugin instead. +application you can do inside of a plugin as well. -Go ahead, include some third-party libraries in 'Vendor', add some +Go ahead - include some third-party libraries in 'Vendor', add some new shells to the cake console, and don't forget to create test cases so your plugin users can automatically test your plugin's functionality! -In our ContactManager example, we might create add/remove/edit/delete +In our ContactManager example we might create add/remove/edit/delete actions in the ContactsController, implement validation in the Contact model, and implement the functionality one might expect when managing their contacts. It's up to you to decide what to implement in your diff --git a/en/tutorials-and-examples/blog-auth-example/auth.rst b/en/tutorials-and-examples/blog-auth-example/auth.rst index ac06ae5b206b7f612f418793e0b0a0c0fe3fd942..468a9b573d475bd374a08e7c030ffbefcf7e7d9b 100644 --- a/en/tutorials-and-examples/blog-auth-example/auth.rst +++ b/en/tutorials-and-examples/blog-auth-example/auth.rst @@ -61,7 +61,6 @@ with CakePHP:: namespace App\Controller; use App\Controller\AppController; - use Cake\Network\Exception\ForbiddenException; use Cake\Event\Event; class UsersController extends AppController @@ -80,18 +79,15 @@ with CakePHP:: public function view($id) { - if (!$id) { - throw new NotFoundException(__('Invalid user')); - } - $user = $this->Users->get($id); $this->set(compact('user')); } public function add() { - $user = $this->Users->newEntity($this->request->data); + $user = $this->Users->newEntity(); if ($this->request->is('post')) { + $user = $this->Users->patchEntity($user, $this->request->data); if ($this->Users->save($user)) { $this->Flash->success(__('The user has been saved.')); return $this->redirect(['action' => 'add']); @@ -133,15 +129,15 @@ the :php:class:`Cake\\Controller\\Component\\AuthComponent`, a class responsible for requiring login for certain actions, handling user login and logout, and also authorizing logged-in users to the actions they are allowed to reach. -To add this component to your application open your ``src/Controller/AppController.php`` +To add this component to your application open your **src/Controller/AppController.php** file and add the following lines:: // src/Controller/AppController.php namespace App\Controller; - use Cake\Event\Event; use Cake\Controller\Controller; + use Cake\Event\Event; class AppController extends Controller { @@ -165,7 +161,7 @@ file and add the following lines:: public function beforeFilter(Event $event) { - $this->Auth->allow(['index', 'view']); + $this->Auth->allow(['index', 'view', 'display']); } //... } @@ -174,8 +170,8 @@ There is not much to configure, as we used the conventions for the users table. We just set up the URLs that will be loaded after the login and logout actions is performed, in our case to ``/articles/`` and ``/`` respectively. -What we did in the ``beforeFilter`` function was to tell the AuthComponent to not -require a login for all ``index`` and ``view`` actions, in every controller. We want +What we did in the ``beforeFilter()`` function was to tell the AuthComponent to not +require a login for all ``index()`` and ``view()`` actions, in every controller. We want our visitors to be able to read and list the entries without registering in the site. @@ -213,20 +209,23 @@ the users add function and implement the login and logout action:: } Password hashing is not done yet, we need an Entity class for our User in order -to handle its own specific logic. Create the ``src/Model/Entity/User.php`` entity file +to handle its own specific logic. Create the **src/Model/Entity/User.php** entity file and add the following:: // src/Model/Entity/User.php namespace App\Model\Entity; - use Cake\ORM\Entity; use Cake\Auth\DefaultPasswordHasher; + use Cake\ORM\Entity; class User extends Entity { - // Make all fields mass assignable for now. - protected $_accessible = ['*' => true]; + // Make all fields mass assignable except for primary key field "id". + protected $_accessible = [ + '*' => true, + 'id' => false + ]; // ... @@ -240,7 +239,7 @@ and add the following:: Now every time the password property is assigned to the user it will be hashed using the ``DefaultPasswordHasher`` class. We're just missing a template view -file for the login function. Open up your ``src/Template/Users/login.ctp`` file +file for the login function. Open up your **src/Template/Users/login.ctp** file and add the following lines: .. code-block:: php @@ -265,11 +264,11 @@ any other URL that was not explicitly allowed such as ``/articles/add``, you wil that the application automatically redirects you to the login page. And that's it! It looks too simple to be true. Let's go back a bit to explain what -happened. The ``beforeFilter`` function is telling the AuthComponent to not require a -login for the ``add`` action in addition to the ``index`` and ``view`` actions that were -already allowed in the AppController's ``beforeFilter`` function. +happened. The ``beforeFilter()`` function is telling the AuthComponent to not require a +login for the ``add()`` action in addition to the ``index()`` and ``view()`` actions +that were already allowed in the AppController's ``beforeFilter()`` function. -The ``login`` action calls the ``$this->Auth->identify()`` function in the AuthComponent, +The ``login()`` action calls the ``$this->Auth->identify()`` function in the AuthComponent, and it works without any further config because we are following conventions as mentioned earlier. That is, having a Users table with a username and a password column, and use a form posted to a controller with the user data. This function @@ -297,10 +296,14 @@ logged in user as a reference for the created article:: public function add() { - $article = $this->Articles->newEntity($this->request->data); + $article = $this->Articles->newEntity(); if ($this->request->is('post')) { + $article = $this->Articles->patchEntity($article, $this->request->data); // Added this line $article->user_id = $this->Auth->user('id'); + // You could also do the following + //$newData = ['user_id' => $this->Auth->user('id')]; + //$article = $this->Articles->patchEntity($article, $newData); if ($this->Articles->save($article)) { $this->Flash->success(__('Your article has been saved.')); return $this->redirect(['action' => 'index']); diff --git a/en/tutorials-and-examples/blog/blog.rst b/en/tutorials-and-examples/blog/blog.rst index 375943b2adff9ad418333a86dc06dcb4e41e28a4..0eaf7006c297de055f6b11ff61b0ce476d66bad9 100755 --- a/en/tutorials-and-examples/blog/blog.rst +++ b/en/tutorials-and-examples/blog/blog.rst @@ -38,7 +38,7 @@ Then simply type the following line in your terminal from your installation directory to install the CakePHP application skeleton in the [app_name] directory. :: - php composer.phar create-project --prefer-dist -s dev cakephp/app [app_name] + php composer.phar create-project --prefer-dist cakephp/app [app_name] The advantage to using Composer is that it will automatically complete some important set up tasks, such as setting the correct file permissions and @@ -145,7 +145,7 @@ For many, this will be the first and last time you will need to configure anything. The configuration should be pretty straightforward: just replace the -values in the ``Datasources.default`` array in the ``config/app.php`` file +values in the ``Datasources.default`` array in the **config/app.php** file with those that apply to your setup. A sample completed configuration array might look something like the following:: @@ -167,7 +167,7 @@ array might look something like the following:: // More configuration below. ]; -Once you've saved your ``config/app.php`` file, you should be able to open +Once you've saved your **config/app.php** file, you should be able to open your browser and see the CakePHP welcome page. It should also tell you that your database connection file was found, and that CakePHP can successfully connect to the database. @@ -175,7 +175,7 @@ can successfully connect to the database. .. note:: A copy of CakePHP's default configuration file is found in - ``config/app.default.php``. + **config/app.default.php**. Optional Configuration ====================== @@ -187,7 +187,7 @@ in security hashes. The security salt is used for generating hashes. If you used Composer this too is taken care of for you during the install. Else you'd need to change the default salt value -by editing ``config/app.php``. It doesn't matter much what the new value is, as long as +by editing **config/app.php**. It doesn't matter much what the new value is, as long as it's not easily guessed:: 'Security' => [ diff --git a/en/tutorials-and-examples/blog/part-three.rst b/en/tutorials-and-examples/blog/part-three.rst index 6fd494d14b05e6575c821d024a93990427d098ed..9725a7655cf421e2787ae0856a3536f730cdc2bc 100644 --- a/en/tutorials-and-examples/blog/part-three.rst +++ b/en/tutorials-and-examples/blog/part-three.rst @@ -18,53 +18,117 @@ We will use the `migrations plugin `_ to create a table in our database. If you already have an articles table in your database, erase it. -Now open your application's ``composer.json`` file. Normally you would see that +Now open your application's **composer.json** file. Normally you would see that the migrations plugin is already under ``require``. If not add it as follows:: "require": { - "cakephp/migrations": "dev-master" + "cakephp/migrations": "~1.0" } Then run ``composer update``. The migrations plugin will now be in your -application's ``plugins`` folder. Also add ``Plugin::load('Migrations');`` in +application's **plugins** folder. Also add ``Plugin::load('Migrations');`` in your application's bootstrap.php file. Once the plugin is loaded, run the following command to create a migration file:: - bin/cake migrations create Initial + bin/cake bake migration CreateArticles title:string body:text category_id:integer created modified -A migration file will be generated in the ``/config/Migrations`` folder. You can -open your new migration file and add the following:: +A migration file will be generated in the **/config/Migrations** folder with the following:: table('articles'); - $articles->addColumn('title', 'string', ['limit' => 50]) - ->addColumn('body', 'text', ['null' => true, 'default' => null]) - ->addColumn('category_id', 'integer', ['null' => true, 'default' => null]) - ->addColumn('created', 'datetime') - ->addColumn('modified', 'datetime', ['null' => true, 'default' => null]) - ->save(); - - $categories = $this->table('categories'); - $categories->addColumn('parent_id', 'integer', ['null' => true, 'default' => null]) - ->addColumn('lft', 'integer', ['null' => true, 'default' => null]) - ->addColumn('rght', 'integer', ['null' => true, 'default' => null]) - ->addColumn('name', 'string', ['limit' => 255]) - ->addColumn('description', 'string', ['limit' => 255, 'null' => true, 'default' => null]) - ->addColumn('created', 'datetime') - ->addColumn('modified', 'datetime', ['null' => true, 'default' => null]) - ->save(); + $table = $this->table('articles'); + $table->addColumn('title', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]); + $table->addColumn('body', 'text', [ + 'default' => null, + 'null' => false, + ]); + $table->addColumn('category_id', 'integer', [ + 'default' => null, + 'limit' => 11, + 'null' => false, + ]); + $table->addColumn('created', 'datetime', [ + 'default' => null, + 'null' => false, + ]); + $table->addColumn('modified', 'datetime', [ + 'default' => null, + 'null' => false, + ]); + $table->create(); + } + } + +Run another command to create a ``categories`` table:: + + bin/cake bake migration CreateCategories parent_id:integer lft:integer rght:integer name:string description:string created modified + +This will generate the following file in **config/Migrations**:: + + table('categories'); + $table->addColumn('parent_id', 'integer', [ + 'default' => null, + 'limit' => 11, + 'null' => false, + ]); + $table->addColumn('lft', 'integer', [ + 'default' => null, + 'limit' => 11, + 'null' => false, + ]); + $table->addColumn('rght', 'integer', [ + 'default' => null, + 'limit' => 11, + 'null' => false, + ]); + $table->addColumn('name', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]); + $table->addColumn('description', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]); + $table->addColumn('created', 'datetime', [ + 'default' => null, + 'null' => false, + ]); + $table->addColumn('modified', 'datetime', [ + 'default' => null, + 'null' => false, + ]); + $table->create(); } } -Now run the following command to create your tables:: +Now that the migration files are created, you can edit them before creating +your tables. We need to change the ``'null' => false`` for the ``parent_id`` +field with ``'null' => true`` because a top-level category has a null +``parent_id``. + +Once the files fits your envy, you can run the following command to create your +tables:: bin/cake migrations migrate @@ -78,7 +142,7 @@ We suppose you already have the files (Tables, Controllers and Templates of Articles) from part 2. So we'll just add the references to categories. We need to associated the Articles and Categories tables together. Open -the ``src/Model/Table/ArticlesTable.php`` file and add the following:: +the **src/Model/Table/ArticlesTable.php** file and add the following:: // src/Model/Table/ArticlesTable.php @@ -105,11 +169,18 @@ Create all files by launching bake commands:: bin/cake bake model Categories bin/cake bake controller Categories - bin/cake bake view Categories + bin/cake bake template Categories The bake tool has created all your files in a snap. You can give them a quick read if you want re-familiarize yourself with how CakePHP works. +.. note:: + If you are on Windows remember to use \ instead of /. + +You'll need to edit the following in **src/Template/Categories/index.ctp**:: + + echo $this->Form->input('parent_id', ['options' => $parentCategories, 'empty' => 'No Parent']); + Attach TreeBehavior to CategoriesTable ====================================== @@ -119,9 +190,10 @@ structures in database table. It uses the `MPTT logic MPTT tree structures are optimized for reads, which often makes them a good fit for read heavy applications like blogs. -If you open the ``src/Model/Table/CategoriesTable.php`` file, you'll see +If you open the **src/Model/Table/CategoriesTable.php** file, you'll see that the TreeBehavior has been attached to your CategoriesTable in the -``initialize`` method:: +``initialize()`` method. Bake adds this behavior to any Tables that contain +``lft`` and ``rght`` columns:: $this->addBehavior('Tree'); @@ -143,23 +215,24 @@ Using your web browser, add some new categories using the Reordering Categories with TreeBehavior ======================================== -In your categories index template file, you can list the categories and ordering +In your categories index template file, you can list the categories and re-order them. -Let's modify the index method in your ``CategoriesController.php`` and add -``move_up`` and ``move_down`` methods to be able to reorder the categories in +Let's modify the index method in your **CategoriesController.php** and add +``moveUp()`` and ``moveDown()`` methods to be able to reorder the categories in the tree:: class CategoriesController extends AppController { public function index() { - $categories = $this->Categories->find('threaded') + $categories = $this->Categories->find() ->order(['lft' => 'ASC']); $this->set(compact('categories')); + $this->set('_serialize', ['categories']); } - public function move_up($id = null) + public function moveUp($id = null) { $this->request->allowMethod(['post', 'put']); $category = $this->Categories->get($id); @@ -171,7 +244,7 @@ the tree:: return $this->redirect($this->referer(['action' => 'index'])); } - public function move_down($id = null) + public function moveDown($id = null) { $this->request->allowMethod(['post', 'put']); $category = $this->Categories->get($id); @@ -184,26 +257,51 @@ the tree:: } } -And the index.ctp:: - - - - Number->format($category->id) ?> - Number->format($category->parent_id) ?> - Number->format($category->lft) ?> - Number->format($category->rght) ?> - name) ?> - description) ?> - created) ?> - - Html->link(__('View'), ['action' => 'view', $category->id]) ?> - Html->link(__('Edit'), ['action' => 'edit', $category->id]) ?> - Form->postLink(__('Delete'), ['action' => 'delete', $category->id], ['confirm' => __('Are you sure you want to delete # {0}?', $category->id)]) ?> - Form->postLink(__('Move down'), ['action' => 'move_down', $category->id], ['confirm' => __('Are you sure you want to move down # {0}?', $category->id)]) ?> - Form->postLink(__('Move up'), ['action' => 'move_up', $category->id], ['confirm' => __('Are you sure you want to move up # {0}?', $category->id)]) ?> - - - +In **src/Template/Categories/index.ctp** replace the existing content with:: + +
+

+
    +
  • Html->link(__('New Category'), ['action' => 'add']) ?>
  • +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
idParent IdLftRghtNameDescriptionCreated
Number->format($category->id) ?>Number->format($category->parent_id) ?>Number->format($category->lft) ?>Number->format($category->rght) ?>name) ?>description) ?>created) ?> + Html->link(__('View'), ['action' => 'view', $category->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $category->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $category->id], ['confirm' => __('Are you sure you want to delete # {0}?', $category->id)]) ?> + Form->postLink(__('Move down'), ['action' => 'moveDown', $category->id], ['confirm' => __('Are you sure you want to move down # {0}?', $category->id)]) ?> + Form->postLink(__('Move up'), ['action' => 'moveUp', $category->id], ['confirm' => __('Are you sure you want to move up # {0}?', $category->id)]) ?> +
+
+ Modifying the ArticlesController ================================ @@ -225,8 +323,9 @@ it:: public function add() { - $article = $this->Articles->newEntity($this->request->data); + $article = $this->Articles->newEntity(); if ($this->request->is('post')) { + $article = $this->Articles->patchEntity($article, $this->request->data); if ($this->Articles->save($article)) { $this->Flash->success(__('Your article has been saved.')); return $this->redirect(['action' => 'index']); @@ -256,7 +355,7 @@ The article add file should look something like this: Form->create($article); // just added the categories input - echo $this->Form->input('categories'); + echo $this->Form->input('category_id'); echo $this->Form->input('title'); echo $this->Form->input('body', ['rows' => '3']); echo $this->Form->button(__('Save Article')); diff --git a/en/tutorials-and-examples/blog/part-two.rst b/en/tutorials-and-examples/blog/part-two.rst index 56fd741daf36190dd051dd719c8eea4c1f858599..684590fb4699e8a7fb1aae248bc1736e1c225d3c 100644 --- a/en/tutorials-and-examples/blog/part-two.rst +++ b/en/tutorials-and-examples/blog/part-two.rst @@ -11,8 +11,8 @@ edit, and delete operations later. CakePHP's model class files are split between ``Table`` and ``Entity`` objects. ``Table`` objects provide access to the collection of entities stored in a -specific table and go in ``src/Model/Table``. The file we'll be creating will -be saved to ``src/Model/Table/ArticlesTable.php``. The completed file should +specific table and go in **src/Model/Table**. The file we'll be creating will +be saved to **src/Model/Table/ArticlesTable.php**. The completed file should look like this:: // src/Model/Table/ArticlesTable.php @@ -37,7 +37,7 @@ be used in the ArticlesController, and will be tied to a database table called .. note:: CakePHP will dynamically create a model object for you if it - cannot find a corresponding file in ``src/Model/Table``. This also means + cannot find a corresponding file in **src/Model/Table**. This also means that if you accidentally name your file wrong (i.e. articlestable.php or ArticleTable.php), CakePHP will not recognize any of your settings and will use the a generated model instead. @@ -53,7 +53,7 @@ Next, we'll create a controller for our articles. The controller is where all interaction with articles will happen. In a nutshell, it's the place where you play with the business logic contained in the models and get work related to articles done. We'll place this new controller in a file called -``ArticlesController.php`` inside the ``src/Controller`` directory. Here's +``ArticlesController.php`` inside the **src/Controller** directory. Here's what the basic controller should look like:: // src/Controller/ArticlesController.php @@ -124,7 +124,7 @@ Remember in the last section how we assigned the 'articles' variable to the view using the ``set()`` method? That would hand down the query object to the view to be invoked with a ``foreach`` iteration. -CakePHP's template files are stored in ``src/Template`` inside a folder +CakePHP's template files are stored in **src/Template** inside a folder named after the controller they correspond to (we'll have to create a folder named 'Articles' in this case). To format this article data in a nice table, our view code might look something like this: @@ -189,8 +189,6 @@ ArticlesController now:: namespace App\Controller; - use Cake\Network\Exception\NotFoundException; - class ArticlesController extends AppController { @@ -201,9 +199,6 @@ ArticlesController now:: public function view($id = null) { - if (!$id) { - throw new NotFoundException(__('Invalid article')); - } $article = $this->Articles->get($id); $this->set(compact('article')); } @@ -218,16 +213,14 @@ we'd like to see. This parameter is handed to the action through the requested URL. If a user requests ``/articles/view/3``, then the value '3' is passed as ``$id``. -We also do a bit of error checking to ensure a user is actually -accessing a record. If a user requests ``/articles/view``, we will throw a -``NotFoundException`` and let the ErrorHandler take over. By using the -``get()`` function in the Articles table, we also perform a similar check to make -sure the user has accessed a record that exists. In case the requested article -is not present in the database, the ``get()`` function will throw +We also do a bit of error checking to ensure a user is actually accessing +a record. By using the ``get()`` function in the Articles table, we make sure +the user has accessed a record that exists. In case the requested article is not +present in the database, or the id is falsey the ``get()`` function will throw a ``NotFoundException``. Now let's create the view for our new 'view' action and place it in -``src/Template/Articles/view.ctp`` +**src/Template/Articles/view.ctp** .. code-block:: php @@ -254,7 +247,7 @@ ArticlesController:: namespace App\Controller; - use Cake\Network\Exception\NotFoundException; + use App\Controller\AppController; class ArticlesController extends AppController { @@ -273,10 +266,6 @@ ArticlesController:: public function view($id) { - if (!$id) { - throw new NotFoundException(__('Invalid article')); - } - $article = $this->Articles->get($id); $this->set(compact('article')); } @@ -317,10 +306,12 @@ information is available in ``$this->request->data``. You can use the :php:func:`pr()` or :php:func:`debug()` functions to print it out if you want to see what it looks like. -We use FlashComponent's magic ``__call`` method to set a message to a session -variable, which will be displayed on the page after redirection. In the layout -we have ``Flash->render() ?>`` which displays the message and clears -the corresponding session variable. The controller's +We use FlashComponent's ``success()`` and ``error()`` methods to set a message +to a session variable. These methods are provided using PHP's `magic method +features `_. +Flash messages will be displayed on the page after redirection. In the layout we +have ``Flash->render() ?>`` which displays the message and clears the +corresponding session variable. The controller's :php:meth:`Cake\\Controller\\Controller::redirect` function redirects to another URL. The param ``['action' => 'index']`` translates to URL /articles i.e the index action of the articles controller. You can refer to @@ -381,7 +372,7 @@ field specified. The ``$this->Form->end()`` call ends the form. Outputting hidden inputs if CSRF/Form Tampering prevention is enabled. -Now let's go back and update our ``src/Template/Articles/index.ctp`` +Now let's go back and update our **src/Template/Articles/index.ctp** view to include a new "Add Article" link. Before the ````, add the following line:: @@ -441,10 +432,6 @@ like:: public function edit($id = null) { - if (!$id) { - throw new NotFoundException(__('Invalid article')); - } - $article = $this->Articles->get($id); if ($this->request->is(['post', 'put'])) { $this->Articles->patchEntity($article, $this->request->data); @@ -622,7 +609,7 @@ By default, CakePHP responds to a request for the root of your site a view called "home". Instead, we'll replace this with our ArticlesController by creating a routing rule. -CakePHP's routing is found in ``config/routes.php``. You'll want +CakePHP's routing is found in **config/routes.php**. You'll want to comment out or remove the line that defines the default root route. It looks like this: diff --git a/en/tutorials-and-examples/bookmarks/intro.rst b/en/tutorials-and-examples/bookmarks/intro.rst index eb2a6892ad364be313b53e61576ba96afbb3bfcb..9803f1f27435c047603f220c5da94693cee1b9c4 100644 --- a/en/tutorials-and-examples/bookmarks/intro.rst +++ b/en/tutorials-and-examples/bookmarks/intro.rst @@ -31,13 +31,20 @@ Or, you can download ``composer.phar`` from the Then simply type the following line in your terminal from your installation directory to install the CakePHP application skeleton -in the ``bookmarker`` directory. :: +in the **bookmarker** directory:: - php composer.phar create-project --prefer-dist -s dev cakephp/app bookmarker + php composer.phar create-project --prefer-dist cakephp/app bookmarker + +If you downloaded and ran the `Composer Windows Installer +`_, then type the following line in +your terminal from your installation directory (ie. +C:\\wamp\\www\\dev\\cakephp3):: + + composer create-project --prefer-dist cakephp/app bookmarker The advantage to using Composer is that it will automatically complete some important set up tasks, such as setting the correct file permissions and -creating your ``config/app.php`` file for you. +creating your **config/app.php** file for you. There are other ways to install CakePHP. If you cannot or don't want to use Composer, check out the :doc:`/installation` section. @@ -75,8 +82,12 @@ home page. Before you can do that, you'll need to start the development server:: bin/cake server +.. note:: + + For Windows, the command needs to be ``bin\cake`` (note the backslash). + This will start PHP's built-in webserver on port 8765. Open up -``http://localhost:8765`` in your web browser to see the welcome page. All the +**http://localhost:8765** in your web browser to see the welcome page. All the bullet points should be checkmarks other than CakePHP being able to connect to your database. If not, you may need to install additional PHP extensions, or set directory permissions. @@ -94,7 +105,7 @@ the following SQL to create the necessary tables:: email VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, created DATETIME, - updated DATETIME + modified DATETIME ); CREATE TABLE bookmarks ( @@ -104,7 +115,7 @@ the following SQL to create the necessary tables:: description TEXT, url TEXT, created DATETIME, - updated DATETIME, + modified DATETIME, FOREIGN KEY user_key (user_id) REFERENCES users(id) ); @@ -112,7 +123,7 @@ the following SQL to create the necessary tables:: id INT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255), created DATETIME, - updated DATETIME, + modified DATETIME, UNIQUE KEY (title) ); @@ -120,7 +131,6 @@ the following SQL to create the necessary tables:: bookmark_id INT NOT NULL, tag_id INT NOT NULL, PRIMARY KEY (bookmark_id, tag_id), - INDEX tag_idx (tag_id, bookmark_id), FOREIGN KEY tag_key(tag_id) REFERENCES tags(id), FOREIGN KEY bookmark_key(bookmark_id) REFERENCES bookmarks(id) ); @@ -143,7 +153,7 @@ For many, this will be the first and last time you will need to configure anything. The configuration should be pretty straightforward: just replace the -values in the ``Datasources.default`` array in the ``config/app.php`` file +values in the ``Datasources.default`` array in the **config/app.php** file with those that apply to your setup. A sample completed configuration array might look something like the following:: @@ -166,33 +176,39 @@ array might look something like the following:: // More configuration below. ]; -Once you've saved your ``config/app.php`` file, you should the 'CakePHP is able -to connect to the database' section have a checkmark. +Once you've saved your **config/app.php** file, you should see that 'CakePHP is +able to connect to the database' section have a checkmark. .. note:: A copy of CakePHP's default configuration file is found in - ``config/app.default.php``. + **config/app.default.php**. Generating Scaffold Code ======================== Because our database is following the CakePHP conventions, we can use the -:doc:`bake console ` application to quickly generate a basic application. In your -command line run the following commands:: +:doc:`bake console ` application to quickly generate a basic +application. In your command line run the following commands:: + // On Windows you'll need to use bin\cake instead. bin/cake bake all users bin/cake bake all bookmarks bin/cake bake all tags This will generate the controllers, models, views, their corresponding test cases, and fixtures for our users, bookmarks and tags resources. If you've -stopped your server, restart it and go to ``http://localhost:8765/bookmarks``. +stopped your server, restart it and go to **http://localhost:8765/bookmarks**. You should see a basic but functional application providing data access to your application's database tables. Once you're at the list of bookmarks, add a few users, bookmarks, and tags. +.. note:: + + If you see a Not Found (404) page, confirm that the Apache mod_rewrite + module is loaded. + Adding Password Hashing ======================= @@ -203,20 +219,20 @@ that fixed. This is also a good time to talk about the model layer in CakePHP. In CakePHP, we separate the methods that operate on a collection of objects, and a single object into different classes. Methods that operate on the collection of -entities are put in the *Table* class, while features belonging to a single -record are put on the *Entity* class. +entities are put in the ``Table`` class, while features belonging to a single +record are put on the ``Entity`` class. For example, password hashing is done on the individual record, so we'll implement this behavior on the entity object. Because, we want to hash the password each time it is set, we'll use a mutator/setter method. CakePHP will call convention based setter methods any time a property is set in one of your -entities. Let's add a setter for the password. In ``src/Model/Entity/User.php`` +entities. Let's add a setter for the password. In **src/Model/Entity/User.php** add the following:: namespace App\Model\Entity; - use Cake\ORM\Entity; use Cake\Auth\DefaultPasswordHasher; + use Cake\ORM\Entity; class User extends Entity { @@ -246,11 +262,19 @@ a route, controller action, and finder method to search through bookmarks by tag. Ideally, we'd have a URL that looks like -``http://localhost:8765/bookmarks/tagged/funny/cat/gifs`` This would let us find -all the bookmarks that have the 'funny', 'cat' and 'gifs' tags. Before we can -implement this, we'll add a new route. In ``config/routes.php``, add the -following at the top of the file:: +**http://localhost:8765/bookmarks/tagged/funny/cat/gifs**. This would let us +find all the bookmarks that have the 'funny', 'cat' or 'gifs' tags. Before we +can implement this, we'll add a new route. Your **config/routes.php** should +look like:: + + 'Bookmarks'], @@ -259,40 +283,56 @@ following at the top of the file:: } ); -The above defines a new 'route' which connects the ``/bookmarks/tagged/*`` path, + Router::scope('/', function ($routes) { + // Connect the default routes. + $routes->fallbacks('InflectedRoute'); + }); + +The above defines a new 'route' which connects the **/bookmarks/tagged/** path, to ``BookmarksController::tags()``. By defining routes, you can isolate how your URLs look, from how they are implemented. If we were to visit -``http://localhost:8765/bookmarks/tagged``, we would see a helpful error page -from CakePHP. Let's implement that missing method now. In -``src/Controller/BookmarksController.php`` add the following:: +**http://localhost:8765/bookmarks/tagged**, we would see a helpful error page +from CakePHP informing you that the controller action does not exist. Let's +implement that missing method now. In **src/Controller/BookmarksController.php** +add the following:: public function tags() { + // The 'pass' key is provided by CakePHP and contains all + // the passed URL path segments in the request. $tags = $this->request->params['pass']; + + // Use the BookmarksTable to find tagged bookmarks. $bookmarks = $this->Bookmarks->find('tagged', [ 'tags' => $tags ]); - $this->set(compact('bookmarks', 'tags')); + + // Pass variables into the view template context. + $this->set([ + 'bookmarks' => $bookmarks, + 'tags' => $tags + ]); } +To access other parts of the request data, consult the :ref:`cake-request` +section. + Creating the Finder Method -------------------------- In CakePHP we like to keep our controller actions slim, and put most of our application's logic in the models. If you were to visit the -``/bookmarks/tagged`` URL now you would see an error that the ``findTagged`` +**/bookmarks/tagged** URL now you would see an error that the ``findTagged()`` method has not been implemented yet, so let's do that. In -``src/Model/Table/BookmarksTable.php`` add the following:: +**src/Model/Table/BookmarksTable.php** add the following:: + // The $query argument is a query builder instance. + // The $options array will contain the 'tags' option we passed + // to find('tagged') in our controller action. public function findTagged(Query $query, array $options) { - $fields = [ - 'Bookmarks.id', - 'Bookmarks.title', - 'Bookmarks.url', - ]; return $this->find() - ->distinct($fields) + ->distinct(['Bookmarks.id']) ->matching('Tags', function ($q) use ($options) { return $q->where(['Tags.title IN' => $options['tags']]); }); @@ -300,16 +340,23 @@ method has not been implemented yet, so let's do that. In We just implemented a :ref:`custom finder method `. This is a very powerful concept in CakePHP that allows you to package up re-usable -queries. In our finder we've leveraged the ``matching()`` method which allows us -to find bookmarks that have a 'matching' tag. +queries. Finder methods always get a :doc:`/orm/query-builder` object and an +array of options as parameters. Finders can manipulate the query and add any +required conditions or criteria. When complete, finder methods must return +a modified query object. In our finder we've leveraged the ``distinct()`` and +``matching()`` methods which allow us to find distinct bookmarks that have +a 'matching' tag. The ``matching()`` method accepts an `anonymous function +`_ that receives a query +builder as its argument. Inside the callback we use the query builder to define +conditions that will filter bookmarks that have specific tags. Creating the View ----------------- -Now if you visit the ``/bookmarks/tagged`` URL, CakePHP will show an error -letting you know that you have not made a view file. Next, let's build the view -file for our ``tags`` action. In ``src/Template/Bookmarks/tags.ctp`` put the -following content:: +Now if you visit the **/bookmarks/tagged** URL, CakePHP will show an error +letting you know that you have not made a view file. Next, let's build the +view file for our ``tags()`` action. In **src/Template/Bookmarks/tags.ctp** +put the following content::

Bookmarks tagged with @@ -319,27 +366,32 @@ following content::
+

Html->link($bookmark->title, $bookmark->url) ?>

url) ?> + + Text->autoParagraph($bookmark->description) ?>
-CakePHP expects that our templates follow the naming convention where the -template has the lower case and underscored version of the controller action -name. +In the above code we use the :doc:`/views/helpers/html` and +:doc:`/views/helpers/text` helpers to assist in generating our view output. We +also use the :php:func:`h` shortcut function to HTML encode output. You should +remember to always use ``h()`` when outputting user data to prevent HTML +injection issues. + +The ``tags.ctp`` file we just created follows the CakePHP conventions for view +template files. The convention is to have the template use the lower case and +underscored version of the controller action name. You may notice that we were able to use the ``$tags`` and ``$bookmarks`` variables in our view. When we use the ``set()`` method in our controller's we set specific variables to be sent to the view. The view will make all passed variables available in the templates as local variables. -In our view we've used a few of CakePHP's built-in :doc:`helpers -`. Helpers are used to make re-usable logic for formatting data, -creating HTML or other view output. - -You should now be able to visit the ``/bookmarks/tagged/funny`` URL and see all +You should now be able to visit the **/bookmarks/tagged/funny** URL and see all the bookmarks tagged with 'funny'. So far, we've created a basic application to manage bookmarks, tags and users. diff --git a/en/tutorials-and-examples/bookmarks/part-two.rst b/en/tutorials-and-examples/bookmarks/part-two.rst index 03e1a3a18ed39ee2e3a5804d23e861ba762183b9..bbf019e2f095cd42dd21e4ef230a84b40adf0c3d 100644 --- a/en/tutorials-and-examples/bookmarks/part-two.rst +++ b/en/tutorials-and-examples/bookmarks/part-two.rst @@ -52,7 +52,7 @@ AppController:: We've just told CakePHP that we want to load the ``Flash`` and ``Auth`` components. In addition, we've customized the configuration of AuthComponent, as our users table uses ``email`` as the username. Now, if you go to any URL you'll -be kicked to ``/users/login``, which will show an error page as we have +be kicked to **/users/login**, which will show an error page as we have not written that code yet. So let's create the login action:: // In src/Controller/UsersController.php @@ -69,7 +69,7 @@ not written that code yet. So let's create the login action:: } } -And in ``src/Template/Users/login.ctp`` add the following:: +And in **src/Template/Users/login.ctp** add the following::

Login

Form->create() ?> @@ -107,8 +107,8 @@ Now you can visit ``/users/logout`` to log out and be sent to the login page. Enabling Registrations ====================== -If you aren't logged in and you try to visit ``/users/add`` you will be kicked -to the login page. We should fix that as we'll if we want people to sign up for +If you aren't logged in and you try to visit **/users/add** you will be kicked +to the login page. We should fix that as we want to allow people to sign up for our application. In the ``UsersController`` add the following:: public function beforeFilter(\Cake\Event\Event $event) @@ -116,9 +116,9 @@ our application. In the ``UsersController`` add the following:: $this->Auth->allow(['add']); } -The above tells ``AuthComponent`` that the ``add`` action does *not* require +The above tells ``AuthComponent`` that the ``add()`` action does *not* require authentication or authorization. You may want to take the time to clean up the -``Users/add.ctp`` and remove the misleading links, or continue on to the next +**Users/add.ctp** and remove the misleading links, or continue on to the next section. We won't be building out user editing, viewing or listing in this tutorial so they will not work as ``AuthComponent`` will deny you access to those controller actions. @@ -143,7 +143,7 @@ Also, add the following to the configuration for ``Auth`` in your 'authorize' => 'Controller', -Your ``initialize`` method should now look like:: +Your ``initialize()`` method should now look like:: public function initialize() { @@ -158,10 +158,11 @@ Your ``initialize`` method should now look like:: ] ] ], - 'unauthorizedRedirect' => [ + 'loginAction' => [ 'controller' => 'Users', 'action' => 'login' - ] + ], + 'unauthorizedRedirect' => $this->referer() ]); // Allow the display action so our pages controller @@ -216,14 +217,16 @@ While view and delete are working, edit, add and index have a few problems: #. The list page shows bookmarks from other users. Let's tackle the add form first. To begin with remove the ``input('user_id')`` -from ``src/Template/Bookmarks/add.ctp``. With that removed, we'll also update -the add method to look like:: +from **src/Template/Bookmarks/add.ctp**. With that removed, we'll also update +the ``add()`` action from **src/Controller/BookmarksController.php** to look +like:: public function add() { - $bookmark = $this->Bookmarks->newEntity($this->request->data); - $bookmark->user_id = $this->Auth->user('id'); + $bookmark = $this->Bookmarks->newEntity(); if ($this->request->is('post')) { + $bookmark = $this->Bookmarks->patchEntity($bookmark, $this->request->data); + $bookmark->user_id = $this->Auth->user('id'); if ($this->Bookmarks->save($bookmark)) { $this->Flash->success('The bookmark has been saved.'); return $this->redirect(['action' => 'index']); @@ -232,11 +235,13 @@ the add method to look like:: } $tags = $this->Bookmarks->Tags->find('list'); $this->set(compact('bookmark', 'tags')); + $this->set('_serialize', ['bookmark']); } By setting the entity property with the session data, we remove any possibility of the user modifying which user a bookmark is for. We'll do the same for the -edit form and action. Your edit action should look like:: +edit form and action. Your ``edit()`` action from +**src/Controller/BookmarksController.php** should look like:: public function edit($id = null) { @@ -254,14 +259,15 @@ edit form and action. Your edit action should look like:: } $tags = $this->Bookmarks->Tags->find('list'); $this->set(compact('bookmark', 'tags')); + $this->set('_serialize', ['bookmark']); } List View --------- Now, we only need to show bookmarks for the currently logged in user. We can do -that by updating the call to ``paginate()``. Make your index() action look -like:: +that by updating the call to ``paginate()``. Make your ``index()`` action from +**src/Controller/BookmarksController.php** look like:: public function index() { @@ -271,6 +277,7 @@ like:: ] ]; $this->set('bookmarks', $this->paginate($this->Bookmarks)); + $this->set('_serialize', ['bookmarks']); } We should also update the ``tags()`` action and the related finder method, but @@ -289,7 +296,7 @@ Adding a Computed Field Because we'll want a simple way to access the formatted tags for an entity, we can add a virtual/computed field to the entity. In -``src/Model/Entity/Bookmark.php`` add the following:: +**src/Model/Entity/Bookmark.php** add the following:: use Cake\Collection\Collection; @@ -313,35 +320,37 @@ use this property in inputs later on. Remember to add the ``tag_string`` property to the ``_accessible`` list in your entity, as we'll want to 'save' it later on. -In ``src/Model/Entity/Bookmark.php`` add the ``tag_string`` to ``_accessible`` this way:: +In **src/Model/Entity/Bookmark.php** add the ``tag_string`` to ``$_accessible`` +this way:: - protected $_accessible = [ - 'user_id' => true, - 'title' => true, - 'description' => true, - 'url' => true, - 'user' => true, - 'tags' => true, - 'tag_string' => true, - ]; + protected $_accessible = [ + 'user_id' => true, + 'title' => true, + 'description' => true, + 'url' => true, + 'user' => true, + 'tags' => true, + 'tag_string' => true, + ]; Updating the Views ------------------ -With the entity updated we can add a new input for our tags. In the add and -edit view, replace the existing ``tags._ids`` input with the following:: +With the entity updated we can add a new input for our tags. In +**src/Template/Bookmarks/add.ctp** and **src/Template/Bookmarks/edit.ctp**, +replace the existing ``tags._ids`` input with the following:: - Form->input('tag_string', ['type' => 'text']) ?> + echo $this->Form->input('tag_string', ['type' => 'text']); Persisting the Tag String ------------------------- Now that we can view existing tags as a string, we'll want to save that data as well. Because we marked the ``tag_string`` as accessible, the ORM will copy that -data from the request into our entity. We can use a ``beforeSave`` hook method +data from the request into our entity. We can use a ``beforeSave()`` hook method to parse the tag string and find/build the related entities. Add the following -to ``src/Model/Table/BookmarksTable.php``:: +to **src/Model/Table/BookmarksTable.php**:: public function beforeSave($event, $entity, $options) @@ -388,5 +397,6 @@ We've expanded our bookmarking application to handle authentication and basic authorization/access control scenarios. We've also added some nice UX improvements by leveraging the FormHelper and ORM capabilities. -Thanks for taking the time to explore CakePHP. Next, you can learn more about -the :doc:`/orm`, or you can peruse the :doc:`/topics`. +Thanks for taking the time to explore CakePHP. Next, you can complete the +:doc:`/tutorials-and-examples/blog/blog`, learn more about the +:doc:`/orm`, or you can peruse the :doc:`/topics`. diff --git a/en/upgrade-tool.rst b/en/upgrade-tool.rst new file mode 100644 index 0000000000000000000000000000000000000000..1961c128f53466e18ae597bc05d30d22057a49c8 --- /dev/null +++ b/en/upgrade-tool.rst @@ -0,0 +1,107 @@ +Upgrade Tool +############ + +Upgrading to CakePHP 3 from CakePHP 2.x requires a number of transformations +that can easily be automated, such as adding namespaces. To assist in making +these mechanical changes easier, CakePHP provides a CLI based upgrade tool. + +Installation +============ + +The upgrade tool is installed as a standalone application. You'll need to clone +the upgrade tool with git, and install the dependencies with composer:: + + git clone https://github.com/cakephp/upgrade.git + cd upgrade + php ../composer.phar install + +At this point you should be able to get the help for the upgrade tool:: + + cd upgrade + bin/cake upgrade --help + +The above should output something like the following:: + + Welcome to CakePHP v3.0.8 Console + --------------------------------------------------------------- + App : src + Path: /Users/markstory/Sites/cake_plugins/upgrade/src/ + --------------------------------------------------------------- + A shell to help automate upgrading from CakePHP 2.x to 3.x. Be sure to + have a backup of your application before running these commands. + + Usage: + cake upgrade [subcommand] [-h] [-v] [-q] + + Subcommands: + + locations Move files/directories around. Run this *before* + adding namespaces with the namespaces command. + namespaces Add namespaces to files based on their file path. + Only run this *after* you have moved files. + app_uses Replace App::uses() with use statements + rename_classes Rename classes that have been moved/renamed. Run + after replacing App::uses() with use statements. + rename_collections Rename HelperCollection, ComponentCollection, and + TaskCollection. Will also rename component + constructor arguments and _Collection properties on + all objects. + method_names Update many of the methods that were renamed during + 2.x -> 3.0 + method_signatures Update many of the method signatures that were + changed during 2.x -> 3.0 + fixtures Update fixtures to use new index/constraint + features. This is necessary before running tests. + tests Update test cases regarding fixtures. + i18n Update translation functions regarding placeholders. + skeleton Add basic skeleton files and folders from the "app" + repository. + prefixed_templates Move view templates for prefixed actions. + all Run all tasks expect for skeleton. That task should + only be run manually, and only for apps (not + plugins). + + To see help on a subcommand use `cake upgrade [subcommand] --help` + + Options: + + --help, -h Display this help. + --verbose, -v Enable verbose output. + --quiet, -q Enable quiet output. + +Usage +===== + +Once you have correctly installed the upgrade tool, you are ready to start using +it on a 2.x application. + +.. warning:: + Make sure you have backups/version control for your application's code. + + It is also a good idea to make a backup/commits after each sub-command. + +To start off run the ``locations`` command:: + + # View the options for the command + bin/cake upgrade locations --help + + # Run the command in dry run mode. + bin/cake upgrade locations --dry-run /path/to/app + +The above will give a dry run output of what would happen. When you are ready to +run the command for real, remove the ``--dry-run`` flag. By using the ``--git`` +flag the upgrade tool can automate moving files in git. + +Once file locations have been updated, you can add namespaces to your code using +the ``namespaces`` command:: + + # View the options for the command + bin/cake upgrade namespaces --help + + # Run the command in dry run mode + bin/cake upgrade namespaces --dry-run /path/to/app + + # Run the command for real + bin/cake upgrade namespaces /path/to/app + +After these two commands, you can run the remaining subcommands in any order. diff --git a/en/views.rst b/en/views.rst index e3cba75584adaf7646defcfa9790f025eb7bd429..5c500c9e7929d87055c6c361590e207a069c3d5b 100644 --- a/en/views.rst +++ b/en/views.rst @@ -18,15 +18,18 @@ common rendering scenarios: :ref:`cake-response-file`. - To create multiple themed views, you can use :doc:`views/themes`. +.. _app-view: + The App View ============ -``AppView`` is your application’s default View class. ``AppView`` itself extends the -``Cake\View\View`` class included in CakePHP and is defined in -``src/View/AppView.php`` as follows: +``AppView`` is your application’s default View class. ``AppView`` itself +extends the ``Cake\View\View`` class included in CakePHP and is defined in +**src/View/AppView.php** as follows: .. code-block:: php + ` gives you a powerful way to keep your views -:term:`DRY`. For example, your application has a sidebar that needs to change depending -on the specific view being rendered. By extending a common view file, you can -avoid repeating the common markup for your sidebar, and only define the parts -that change: +:term:`DRY`. For example, your application has a sidebar that needs to change +depending on the specific view being rendered. By extending a common view file, +you can avoid repeating the common markup for your sidebar, and only define the +parts that change: .. code-block:: php @@ -174,14 +178,14 @@ uncaptured content from the extending view. Assuming our view file has a Html->link('edit', [ 'action' => 'edit', - $post['Post']['id'] + $post->id ]); ?> end(); ?> // The remaining content will be available as the 'content' block // In the parent view. - + body) ?> The post view above shows how you can extend a view, and populate a set of blocks. Any content not already in a defined block will be captured and put @@ -221,8 +225,8 @@ your views/layouts that will be defined elsewhere. For example, blocks are ideal for implementing things such as sidebars, or regions to load assets at the bottom/top of the layout. Blocks can be defined in two ways: either as a capturing block, or by direct assignment. The ``start()``, ``append()``, -``prepend()``, ``assign()``, ``fetch()``, and ``end()`` methods allow you to work with -capturing blocks:: +``prepend()``, ``assign()``, ``fetch()``, and ``end()`` methods allow you to +work with capturing blocks:: // Create the sidebar block. $this->start('sidebar'); @@ -345,12 +349,12 @@ A layout contains presentation code that wraps around a view. Anything you want to see in all of your views should be placed in a layout. -CakePHP's default layout is located at ``src/Template/Layout/default.ctp``. +CakePHP's default layout is located at **src/Template/Layout/default.ctp**. If you want to change the overall look of your application, then this is the right place to start, because controller-rendered view code is placed inside of the default layout when the page is rendered. -Other layout files should be placed in ``src/Template/Layout``. +Other layout files should be placed in **src/Template/Layout**. When you create a layout, you need to tell CakePHP where to place the output of your views. To do so, make sure your layout includes a place for ``$this->fetch('content')`` Here's an example of what a default layout @@ -404,14 +408,17 @@ You can set the ``title`` block content from inside your view file:: $this->assign('title', 'View Active Users'); You can create as many layouts as you wish: just place them in the -``src/Template/Layout`` directory, and switch between them inside of your +**src/Template/Layout** directory, and switch between them inside of your controller actions using the controller or view's ``$layout`` property:: // From a controller public function admin_view() { - // Stuff + // Set the layout. + $this->viewBuilder()->layout('admin'); + + // Before 3.1 $this->layout = 'admin'; } @@ -430,18 +437,24 @@ using something like:: public function view_active() { $this->set('title', 'View Active Users'); + $this->viewBuilder()->layout('default_small_ad'); + + // or the following before 3.1 $this->layout = 'default_small_ad'; } public function view_image() { + $this->viewBuilder()->layout('image'); + // or the following before 3.1 $this->layout = 'image'; + // Output user image } } -Besides a default layout CakePHP's official skeleton app also has an 'ajax' layout. -The Ajax layout is handy for crafting AJAX responses - it's an +Besides a default layout CakePHP's official skeleton app also has an 'ajax' +layout. The Ajax layout is handy for crafting AJAX responses - it's an empty layout. (Most AJAX calls only require a bit of markup in return, rather than a fully-rendered interface.) @@ -460,6 +473,8 @@ Contacts plugin:: { public function view_active() { + $this->viewBuilder()->layout('Contacts.contact'); + // or the following before 3.1 $this->layout = 'Contacts.contact'; } } @@ -484,7 +499,7 @@ make a view more readable, placing the rendering of repeating elements in its own file. They can also help you re-use content fragments in your application. -Elements live in the ``src/Template/Element/`` folder, and have the .ctp +Elements live in the **src/Template/Element/** folder, and have the .ctp filename extension. They are output using the element method of the view:: @@ -503,7 +518,7 @@ argument:: Inside the element file, all the passed variables are available as members of the parameter array (in the same way that ``Controller::set()`` in the controller works with template files). In the above example, the -``src/Template/Element/helpbox.ctp`` file can use the ``$helptext`` +**src/Template/Element/helpbox.ctp** file can use the ``$helptext`` variable:: // Inside src/Template/Element/helpbox.ctp @@ -526,9 +541,9 @@ The options supported are 'cache' and 'callbacks'. An example:: Element caching is facilitated through the ``Cache`` class. You can configure elements to be stored in any Cache configuration you've set up. This -gives you a great amount of flexibility to decide where and for how long elements -are stored. To cache different versions of the same element in an application, -provide a unique cache key value using the following format:: +gives you a great amount of flexibility to decide where and for how long +elements are stored. To cache different versions of the same element in an +application, provide a unique cache key value using the following format:: $this->element('helpbox', [], [ "cache" => ['config' => 'short', 'key' => 'unique value'] @@ -618,7 +633,7 @@ If you are using a plugin and wish to use elements from within the plugin, just use the familiar :term:`plugin syntax`. If the view is being rendered for a plugin controller/action, the plugin name will automatically be prefixed onto all elements used, unless another plugin name is present. -If the element doesn't exist in the plugin, it will look in the main APP folder. :: +If the element doesn't exist in the plugin, it will look in the main APP folder:: echo $this->element('Contacts.helpbox'); @@ -632,11 +647,25 @@ if you are in the ``ContactsController`` of the Contacts plugin, the following:: are equivalent and will result in the same element being rendered. For elements inside subfolder of a plugin -(e.g., ``plugins/Contacts/sidebar/helpbox.ctp``), use the following:: +(e.g., **plugins/Contacts/Template/Element/sidebar/helpbox.ctp**), use the following:: echo $this->element('Contacts.sidebar/helpbox'); +Routing prefix and Elements +--------------------------------- + +.. versionadded:: 3.0.1 + +If you have a Routing prefix configured, the Element path resolution can switch +to a prefix location, as Layouts and action View do. +Assuming you have a prefix "Admin" configured and you call:: + + echo $this->element('my_element'); + +The element first be looked for in **src/Template/Admin/Element/**. If such a +file does not exist, it will be looked for in the default location. + Caching Sections of Your View ----------------------------- @@ -663,11 +692,11 @@ You may need to create custom view classes to enable new types of data views, or add additional custom view-rendering logic to your application. Like most components of CakePHP, view classes have a few conventions: -* View class files should be put in ``src/View``. For example: - ``src/View/PdfView.php`` +* View class files should be put in **src/View**. For example: + **src/View/PdfView.php** * View classes should be suffixed with ``View``. For example: ``PdfView``. * When referencing view class names you should omit the ``View`` suffix. For - example: ``$this->viewClass = 'Pdf';``. + example: ``$builder->viewClass('Pdf');``. You'll also want to extend ``View`` to ensure things work correctly:: diff --git a/en/views/cells.rst b/en/views/cells.rst index 75a0fb089332aa822620e1b83f41351ecd446f35..14ca92988f772f5eeb9c67d0ddf1e50e8f1bdc93 100644 --- a/en/views/cells.rst +++ b/en/views/cells.rst @@ -18,8 +18,8 @@ with ``requestAction()``. Creating a Cell =============== -To create a cell, define a class in ``src/View/Cell`` and a template in -``src/Template/Cell/``. In this example, we'll be making a cell to display the +To create a cell, define a class in **src/View/Cell** and a template in +**src/Template/Cell/**. In this example, we'll be making a cell to display the number of messages in a user's notification inbox. First, create the class file. Its contents should look like:: @@ -36,7 +36,7 @@ Its contents should look like:: } -Save this file into ``src/View/Cell/InboxCell.php``. As you can see, like other +Save this file into **src/View/Cell/InboxCell.php**. As you can see, like other classes in CakePHP, Cells have a few conventions: * Cells live in the ``App\View\Cell`` namespace. If you are making a cell in @@ -46,7 +46,7 @@ classes in CakePHP, Cells have a few conventions: We added an empty ``display()`` method to our cell; this is the conventional default method when rendering a cell. We'll cover how to use other methods later -in the docs. Now, create the file ``src/Template/Cell/Inbox/display.ctp``. This +in the docs. Now, create the file **src/Template/Cell/Inbox/display.ctp**. This will be our template for our new cell. You can generate this stub code quickly using ``bake``:: @@ -91,10 +91,10 @@ following:: .. note:: - Cell templates have an isolated scope do not share the same View instance - as the one used to render template and layout for the current controller - action or other cells. Hence they are unaware of any helper calls made or - blocks set in the action's template / layout and vice versa. + Cell templates have an isolated scope that does not share the same View + instance as the one used to render template and layout for the current + controller action or other cells. Hence they are unaware of any helper calls + made or blocks set in the action's template / layout and vice versa. Loading Cells ============= diff --git a/en/views/helpers.rst b/en/views/helpers.rst index d28332b4998a6b29a02f00c60f2cf4124afb4be5..61f865e2a64f6ed7719bebc60d616a959e718bbd 100644 --- a/en/views/helpers.rst +++ b/en/views/helpers.rst @@ -32,50 +32,61 @@ check out the chapter for each helper: Configuring Helpers =================== -You enable helpers in CakePHP by making a controller aware of them. Each -controller has a :php:attr:`~Cake\\Controller\\Controller::$helpers` property -that lists the helpers to be made available in the view. To enable a helper in -your view, add the name of the helper to the controller's ``$helpers`` array:: +You enable helpers in CakePHP by declaring them in a view class. An ``AppView`` +class comes with every CakePHP application and is the ideal place to load +helpers:: - class BakeriesController extends AppController + class AppView extends View { - public $helpers = ['Form', 'Html', 'Time']; + public function initialize() + { + parent::initialize(); + $this->loadHelper('Html'); + $this->loadHelper('Form'); + $this->loadHelper('Flash'); + } } -Adding helpers from plugins uses the :term:`plugin syntax` used elsewhere in +Loading helpers from plugins uses the :term:`plugin syntax` used elsewhere in CakePHP:: - class BakeriesController extends AppController - { - public $helpers = ['Blog.Comment']; - } + $this->loadHelper('Blog.Comment'); + +You don't have to explicitly load Helpers that come from CakePHP or your +application. These helpers can be lazily loaded upon first use. For example:: + + // Loads the FormHelper if it has not already been loaded. + $this->Form->create($article); + +From within a plugin's views, plugin helpers can also be lazily loaded. For +example, view templates in the 'Blog' plugin, can lazily load helpers from the +same plugin. -You can also add helpers from within an action, so they will only -be available to that action and not to the other actions in the -controller. This saves processing power for the other actions that -do not use the helper and helps keep the controller better -organized:: +Conditionally Loading Helpers +----------------------------- - class BakeriesController extends AppController +You can use the current action name to conditionally load helpers:: + + class AppView extends View { - public function bake() - { - $this->helpers[] = 'Time'; - } - public function mix() + public function initialize() { - // The Time helper is not loaded here and thus not available + parent::initialize(); + if ($this->request->action === 'index') { + $this->loadHelper('ListPage'); + } } } -If you need to enable a helper for all controllers add the name of -the helper to the ``$helpers`` array in ``src/Controller/AppController.php`` (or -create if not present). Remember to include the default Html and -Form helpers:: +You can also use your controller's ``beforeRender`` method to load helpers:: - class AppController extends Controller + class ArticlesController extends AppController { - public $helpers = ['Form', 'Html', 'Time']; + public function beforeRender(Event $event) + { + parent::beforeRender($event); + $this->viewBuilder()->helpers(['MyHelper']); + } } Configuration options @@ -122,12 +133,6 @@ your helper requires. For example:: 'label' => '', ], ]; - - public function __construct(View $view, $config = []) - { - parent::__construct($view, $config); - $this->initStringTemplates(); - } } Any configuration provided to your helper's constructor will be merged with the @@ -147,7 +152,10 @@ you can set those in your controller's beforeRender callback:: public function beforeRender(Event $event) { parent::beforeRender($event); - $this->helpers['CustomStuff'] = $this->_getCustomStuffConfig(); + $builder = $this->viewBuilder(); + $builder->helpers([ + 'CustomStuff' => $this->_getCustomStuffConfig(), + ]); } } @@ -161,17 +169,20 @@ create aliased helpers in your views. This feature is useful when you want to replace ``$this->Html`` or another common Helper reference with a custom implementation:: - // src/Controller/PostsController.php - class PostsController extends AppController + // src/View/AppView.php + class AppView extends View { - public $helpers = [ - 'Html' => [ + public function initialize() + { + $this->loadHelper('Html', [ 'className' => 'MyHtml' - ] - ]; + ]); + } } // src/View/Helper/MyHtmlHelper.php + namespace App\View\Helper; + use Cake\View\Helper\HtmlHelper; class MyHtmlHelper extends HtmlHelper @@ -196,7 +207,7 @@ doing the following:: echo $this->Html->css('styles'); -The above would call the ``css`` method on the HtmlHelper. You can +The above would call the ``css()`` method on the HtmlHelper. You can access any loaded helper using ``$this->{$helperName}``. Loading Helpers On The Fly @@ -206,6 +217,8 @@ There may be situations where you need to dynamically load a helper from inside a view. You can use the view's :php:class:`Cake\\View\\HelperRegistry` to do this:: + // Either one works. + $mediaHelper = $this->loadHelper('Media', $mediaConfig); $mediaHelper = $this->helpers()->load('Media', $mediaConfig); The HelperRegistry is a :doc:`registry ` and @@ -229,7 +242,7 @@ Let's say we wanted to create a helper that could be used to output a specifically crafted CSS-styled link you needed at many different places in your application. In order to fit your logic into CakePHP's existing helper structure, you'll need to create a new -class in ``src/View/Helper``. Let's call our helper LinkHelper. The +class in **src/View/Helper**. Let's call our helper LinkHelper. The actual PHP class file would look something like this:: /* src/View/Helper/LinkHelper.php */ @@ -279,17 +292,19 @@ Using Your Helper ----------------- Once you've created your helper and placed it in -``src/View/Helper/``, you'll be able to include it in your -controllers using the special variable :php:attr:`~Controller::$helpers`:: +**src/View/Helper/**, you can load it in your views:: - class PostsController extends AppController + class AppView extends View { - public $helpers = ['Link']; + public function initialize() + { + parent::initialize(); + $this->loadHelper('Link'); + } } -Once your controller has been made aware of this new class, you can -use it in your views by accessing an object named after the -helper:: +Once your helper has been loaded, you can use it in your views by accessing +the matching view property:: Link->makeEdit('Change this Recipe', '/recipes/edit/5') ?> diff --git a/en/views/helpers/flash.rst b/en/views/helpers/flash.rst index 821ad696bd347d813d4802dc7bf8e62a8a03caa8..74a1188b3f3f51cb9fb956e4579cfa52aa588f1a 100644 --- a/en/views/helpers/flash.rst +++ b/en/views/helpers/flash.rst @@ -1,5 +1,5 @@ -FlashHelper -########### +Flash +##### .. php:namespace:: Cake\View\Helper @@ -9,7 +9,7 @@ FlashHelper provides a way to render flash messages that were set in ``$_SESSION`` by :doc:`FlashComponent `. :doc:`FlashComponent ` and FlashHelper primarily use elements to render flash messages. Flash elements are found under -the ``src/Template/Element/Flash`` directory. You'll notice that CakePHP's App +the **src/Template/Element/Flash** directory. You'll notice that CakePHP's App template comes with two flash elements: ``success.ctp`` and ``error.ctp``. Rendering Flash Messages @@ -40,9 +40,35 @@ You can also override any of the options that were set in FlashComponent:: ]); .. note:: - By default, CakePHP does not escape the HTML in flash messages. If you are using - any request or user data in your flash messages, you should escape it + + By default, CakePHP does not escape the HTML in flash messages. If you are + using any request or user data in your flash messages, you should escape it with :php:func:`h` when formatting your messages. +.. versionadded:: 3.1 + + The :doc:`FlashComponent ` now + stacks messages. If you set multiple flash messages, when you call + ``render()``, each message will be rendered in its own elements, in the + order they were set. + For more information about the available array options, please refer to the :doc:`FlashComponent ` section. + +Routing Prefix and Flash Messages +================================= + +.. versionadded:: 3.0.1 + +If you have a Routing prefix configured, you can now have your Flash elements +stored in **src/Template/{Prefix}/Element/Flash**. This way, you can have +specific messages layouts for each part of your application (for instance, have +different layouts for you front-end and your admin side). + +Flash Messages and Themes +========================= + +The FlashHelper uses normal elements to render the messages and will therefore +obey any theme you might have specified. So when your theme has a +**src/Template/Element/Flash/error.ctp** file it will be used, just as with any +Elements and Views. diff --git a/en/views/helpers/form.rst b/en/views/helpers/form.rst index c20d164a031f9a9c2f813670d0e113a45278715e..da2393c72c63ddcc41723a76676f5a37c7038c93 100644 --- a/en/views/helpers/form.rst +++ b/en/views/helpers/form.rst @@ -1,5 +1,5 @@ -FormHelper -########## +Form +#### .. php:namespace:: Cake\View\Helper @@ -22,8 +22,8 @@ is ``create()``. This method outputs an opening form tag. All parameters are optional. If ``create()`` is called with no parameters supplied, it assumes you are building a form that submits to the current controller, via the current URL. The default method for form submission is POST. -If you were to call ``create()`` inside the view for UsersController::add(), you would see -something like the following output in the rendered view: +If you were to call ``create()`` inside the view for UsersController::add(), you +would see something like the following output in the rendered view: .. code-block:: html @@ -189,6 +189,22 @@ rules that only apply when an account is being registered:: 'context' => ['validator' => 'register'] ]); +The above will use the ``register`` validator for the ``$user`` and all related +associations. If you are creating a form for associated entities, you can define +validation rules for each association by using an array:: + + echo $this->Form->create($user, [ + 'context' => [ + 'validator' => [ + 'Users' => 'register', + 'Comments' => 'default' + ] + ] + ]); + +The above would use ``register`` for the user, and ``default`` for the user's +comments. + Creating context classes ------------------------ @@ -313,6 +329,15 @@ Afterwards, add the following to your view template:: echo $this->Form->input('group_id', ['options' => $groups]); +To make a select box for a belongsToMany Groups association you can add the +following to your UsersController:: + + $this->set('groups', $this->Users->Groups->find('list')); + +Afterwards, add the following to your view template:: + + echo $this->Form->input('groups._ids', ['options' => $groups]); + If your model name consists of two or more words, e.g., "UserGroup", when passing the data using set() you should name your data in a pluralised and camelCased format as follows:: @@ -340,7 +365,8 @@ You can create inputs for associated models, or arbitrary models by passing in Any dots in your field names will be converted into nested request data. For example, if you created a field with a name ``0.comments.body`` you would get a name attribute that looks like ``0[comments][body]``. This convention makes it -easy to save data with the ORM. +easy to save data with the ORM. Details for the various association types can +be found in the :ref:`associated-form-inputs` section. When creating datetime related inputs, FormHelper will append a field-suffix. You may notice additional fields named ``year``, ``month``, ``day``, ``hour``, @@ -427,9 +453,7 @@ HTML attributes. The following will cover the options specific to * ``$options['error']`` Using this key allows you to override the default model - error messages and can be used, for example, to set i18n messages. It has a - number of suboptions which control the wrapping element, wrapping element - class name, and whether HTML in the error message will be escaped. + error messages and can be used, for example, to set i18n messages. To disable error message output & field classes set the error key to ``false``:: @@ -491,20 +515,19 @@ common options shared by all input methods are as follows: Date and datetime fields' default values can be set by using the 'selected' key. - Beware of using ``false`` to assign a default value. A ``false`` value is used to - disable/exclude options of an input field, so ``'default' => false`` would - not set any value at all. Instead use ``'default' => 0``. + Beware of using ``false`` to assign a default value. A ``false`` value is + used to disable/exclude options of an input field, so ``'default' => false`` + would not set any value at all. Instead use ``'default' => 0``. In addition to the above options, you can mixin any HTML attribute you wish to use. Any non-special option name will be treated as an HTML attribute, and applied to the generated HTML input element. - Options for Select, Checkbox and Radio Inputs --------------------------------------------- * ``$options['value']`` Used in combination with a select-type input (i.e. - For types select, date, time, datetime). Set 'selected' to the value of the + For types select, date, time, datetime). Set 'value' to the value of the item you wish to be selected by default when the input is rendered:: echo $this->Form->time('close_time', [ @@ -516,6 +539,15 @@ Options for Select, Checkbox and Radio Inputs The value key for date and datetime inputs may also be a UNIX timestamp, or a DateTime object. + For select input where you set the ``multiple`` attribute to true, + you can use an array of the values you want to select by default:: + + echo $this->Form->select('rooms', [ + 'multiple' => true, + // options with values 1 and 3 will be selected as default + 'default' => [1, 3] + ]); + * ``$options['empty']`` If set to ``true``, forces the input to remain empty. When passed to a select list, this creates a blank option with an @@ -533,7 +565,7 @@ Options for Select, Checkbox and Radio Inputs .. code-block:: html - @@ -550,8 +582,8 @@ Options for Select, Checkbox and Radio Inputs .. code-block:: html - - + + This can be disabled by setting the ``$options['hiddenField'] = false``:: @@ -632,7 +664,7 @@ Datetime Options * ``$options['interval']`` This option specifies the number of minutes between each option in the minutes select box:: - echo $this->Form->input('Model.time', [ + echo $this->Form->input('time', [ 'type' => 'time', 'interval' => 15 ]); @@ -640,11 +672,12 @@ Datetime Options Would create 4 options in the minute select. One for each 15 minutes. -* ``$options['round']`` Can be set to `up` or `down` to force rounding in either direction. - Defaults to null which rounds half up according to `interval`. +* ``$options['round']`` Can be set to `up` or `down` to force rounding in either + direction. Defaults to null which rounds half up according to `interval`. -* ``$options['monthNames']`` If ``false``, 2 digit numbers will be used instead of text. - If it is given an array like ``['01' => 'Jan', '02' => 'Feb', ...]`` then the given array will be used. +* ``$options['monthNames']`` If ``false``, 2 digit numbers will be used instead + of text. If it is given an array like ``['01' => 'Jan', '02' => 'Feb', ...]`` + then the given array will be used. Creating Input Elements ======================= @@ -802,7 +835,7 @@ Creating Radio Buttons Creates a set of radio button inputs. -**Options** +**Attributes** * ``value`` - Indicates the value when this radio button is checked. * ``label`` - boolean to indicate whether or not labels for widgets should be @@ -816,6 +849,33 @@ Creates a set of radio button inputs. option. When ``true`` the radio label will be 'empty'. Set this option to a string to control the label value. +Generally ``$options`` is a simple key => value pair. However, if you need to +put custom attributes on your radio buttons you can use an expanded format:: + + echo $this->Form->radio( + 'favorite_color', + [ + ['value' => 'r', 'text' => 'Red', 'style' => 'color:red;'], + ['value' => 'u', 'text' => 'Blue', 'style' => 'color:blue;'], + ['value' => 'g', 'text' => 'Green', 'style' => 'color:green;'], + ] + ); + + // Will output + + + + + Creating Select Pickers ----------------------- @@ -847,9 +907,9 @@ Defaults to ``true``:: $options = ['M' => 'Male', 'F' => 'Female']; echo $this->Form->select('gender', $options, ['escape' => false]); -* ``$attributes['options']`` This key allows you to manually specify options for a - select input, or for a radio group. Unless the 'type' is specified as 'radio', - the FormHelper will assume that the target output is a select input:: +* ``$attributes['options']`` This key allows you to manually specify options for + a select input, or for a radio group. Unless the 'type' is specified as + 'radio', the FormHelper will assume that the target output is a select input:: echo $this->Form->select('field', [1,2,3,4,5]); @@ -915,7 +975,7 @@ Defaults to ``true``:: * ``$attributes['multiple']`` If 'multiple' has been set to ``true`` for an input that outputs a select, the select will allow multiple selections:: - echo $this->Form->select('Model.field', $options, ['multiple' => true]); + echo $this->Form->select('field', $options, ['multiple' => true]); Alternatively set 'multiple' to 'checkbox' to output a list of related check boxes:: @@ -924,7 +984,7 @@ Defaults to ``true``:: 'Value 1' => 'Label 1', 'Value 2' => 'Label 2' ]; - echo $this->Form->select('Model.field', $options, [ + echo $this->Form->select('field', $options, [ 'multiple' => 'checkbox' ]); @@ -954,7 +1014,7 @@ Defaults to ``true``:: 'Value 1' => 'Label 1', 'Value 2' => 'Label 2' ]; - echo $this->Form->select('Model.field', $options, [ + echo $this->Form->select('field', $options, [ 'multiple' => 'checkbox', 'disabled' => ['Value 1'] ]); @@ -1029,8 +1089,8 @@ way PHP handles data passed via file fields encoding-type, by setting the type option to 'file' in ``$this->Form->create()``. -Creating Date and Time Inputs ------------------------------ +Creating DateTime Inputs +------------------------ .. php:method:: dateTime($fieldName, $options = []) @@ -1044,9 +1104,11 @@ of options: * ``interval`` The interval for the minutes select. Defaults to 1 * ``empty`` - If ``true``, the empty select option is shown. If a string, that string is displayed as the empty element. -* ``round`` - Set to ``up`` or ``down`` if you want to force rounding in either direction. Defaults to null. -* ``default`` The default value to be used by the input. A value in ``$this->request->data`` - matching the field name will override this value. If no default is provided ``time()`` will be used. +* ``round`` - Set to ``up`` or ``down`` if you want to force rounding in either + direction. Defaults to null. +* ``default`` The default value to be used by the input. A value in + ``$this->request->data`` matching the field name will override this value. If + no default is provided ``time()`` will be used. * ``timeFormat`` The time format to use, either 12 or 24. * ``second`` Set to ``true`` to enable seconds drop down. @@ -1056,6 +1118,60 @@ is:: {{year}}{{month}}{{day}}{{hour}}{{minute}}{{second}}{{meridian}} +Creating Time Inputs +-------------------- + +.. php:method:: time($fieldName, $options = []) + +Creates two select elements populated with 24 hours and 60 minutes for ``hour`` +and ``minute``, respectively. +Additionally, HTML attributes may be supplied in $options for each specific +``type``. If ``$options['empty']`` is ``false``, the select will not include an +empty option: + +* ``empty`` - If ``true``, the empty select option is shown. If a string, + that string is displayed as the empty element. +* ``default`` | ``value`` The default value to be used by the input. A value in + ``$this->request->data`` matching the field name will override this value. + If no default is provided ``time()`` will be used. +* ``timeFormat`` The time format to use, either 12 or 24. Defaults to 24. +* ``second`` Set to ``true`` to enable seconds drop down. +* ``interval`` The interval for the minutes select. Defaults to 1. + +For example, to create a time range with minutes selectable in 15 minute +increments, and to apply classes to the select boxes, you could do the +following:: + + echo $this->Form->time('released', [ + 'interval' => 15, + 'hour' => [ + 'class' => 'foo-class', + ], + 'minute' => [ + 'class' => 'bar-class', + ], + ]); + +Which would create the following two selects: + +.. code-block:: html + + + + Creating Year Inputs -------------------- @@ -1243,9 +1359,6 @@ Options: - 'escape' bool Whether or not to HTML escape the contents of the error. -- 'wrap' mixed Whether or not the error message should be wrapped - in a div. If a string, will be used as the HTML tag to use. -- 'class' string The class name for the error message .. TODO:: Add examples. @@ -1385,8 +1498,9 @@ Creating Standalone Buttons and POST links POST. This method creates a ``
`` element. So do not use this method in some - opened form. Instead use :php:meth:`Cake\\View\\Helper\\FormHelper::submit()` or - :php:meth:`Cake\\View\\Helper\\FormHelper::button()` to create buttons inside opened forms. + opened form. Instead use :php:meth:`Cake\\View\\Helper\\FormHelper::submit()` + or :php:meth:`Cake\\View\\Helper\\FormHelper::button()` to create buttons + inside opened forms. .. php:method:: postLink(string $title, mixed $url = null, array $options = []) @@ -1413,7 +1527,7 @@ option when including the helper in your controller:: 'templates' => 'app_form', ]); -This would load the tags in ``config/app_form.php``. This file should +This would load the tags in **config/app_form.php**. This file should contain an array of templates indexed by name:: // in config/app_form.php @@ -1444,8 +1558,8 @@ A list of the default templates and the variables they can expect are: * ``button`` {{attrs}}, {{text}} * ``checkbox`` {{name}}, {{value}}, {{attrs}} -* ``checkboxFormGroup`` {{input}}, {{label}}, {{error}} -* ``checkboxWrapper`` {{input}}, {{label}} +* ``checkboxFormGroup`` {{label}} +* ``checkboxWrapper`` {{label}} * ``dateWidget`` {{year}}, {{month}}, {{day}}, {{hour}}, {{minute}}, {{second}}, {{meridian}} * ``error`` {{content}} * ``errorList`` {{content}} @@ -1460,6 +1574,8 @@ A list of the default templates and the variables they can expect are: * ``inputContainerError`` {{type}}, {{required}}, {{content}}, {{error}} * ``inputSubmit`` {{type}}, {{attrs}} * ``label`` {{attrs}}, {{text}}, {{hidden}}, {{input}} +* ``nestingLabel`` {{hidden}}, {{attrs}}, {{input}}, {{text}} +* ``legend`` {{text}} * ``option`` {{value}}, {{attrs}}, {{text}} * ``optgroup`` {{label}}, {{attrs}}, {{content}} * ``radio`` {{name}}, {{value}}, {{attrs}} @@ -1481,11 +1597,39 @@ example:: ]); // Create a radio set with our custom wrapping div. - echo $this->Form->radio('User.email_notifications', [ - 'options' => ['y', 'n'], - 'type' => 'radio' + echo $this->Form->radio('User.email_notifications', ['y', 'n']); + +Similar to input containers, the ``input()`` method will also attempt to use +distinct templates for each form group. A form group is a combo of label and +input. For example, when creating a radio input the ``radioFormGroup`` will be +used if it is present. If that template is missing by default each set of label +& input is rendered using the ``formGroup`` template. For example:: + + // Add custom radio form group + $this->Form->templates([ + 'radioFormGroup' => '
{{label}}{{input}}
' + ]); + +Adding Additional Template Variables to Templates +------------------------------------------------- + +You can add additional template placeholders in custom templates, and populate +those placeholders when generating inputs:: + + // Add a template with the help placeholder. + $this->Form->templates([ + 'inputContainer' => '
+ {{content}} {{help}}
' + ]); + + // Generate an input and populate the help variable + echo $this->Form->input('password', [ + 'templateVars' => ['help' => 'At least 8 characters long.'] ]); +.. versionadded:: 3.1 + The templateVars option was added in 3.1.0 + Moving Checkboxes & Radios Outside of a Label --------------------------------------------- @@ -1527,8 +1671,9 @@ You can customize the generated inputs by defining additional options in the When customizing, ``fields``, you can use the ``$options`` parameter to control the generated legend/fieldset. -- ``fieldset`` Set to ``false`` to disable the fieldset. If a string is supplied - it will be used as the class name for the fieldset element. +- ``fieldset`` Set to ``false`` to disable the fieldset. You can also pass an + array of parameters to be applied as HTML attributes to the fieldset tag. If + you pass an empty array, the fieldset will be displayed without attributes. - ``legend`` Set to ``false`` to disable the legend for the generated input set. Or supply a string to customize the legend text. @@ -1590,6 +1735,13 @@ create the following inputs:: echo $this->Form->input('tags.1.id'); echo $this->Form->input('tags.1.name'); + // Multiple select element for belongsToMany + echo $this->Form->input('tags._ids', [ + 'type' => 'select', + 'multiple' => true, + 'options' => $tagList, + ]); + // Inputs for the joint table (articles_tags) echo $this->Form->input('tags.0._joinData.starred'); echo $this->Form->input('tags.1._joinData.starred'); @@ -1625,15 +1777,19 @@ Building a Widget Class Widget classes have a very simple required interface. They must implement the :php:class:`Cake\\View\\Widget\\WidgetInterface`. This interface requires -the ``render(array $data)`` method to be implemented. The render method -expects an array of data to build the widget and is expected to return a string -of HTML for the widget. If CakePHP is constructing your widget you can expect to +the ``render(array $data)`` and ``secureFields(array $data)`` methods to be +implemented. The ``render()`` method expects an array of data to build the +widget and is expected to return a string of HTML for the widget. +The ``secureFields()`` method expects an array of data as well and is expected +to return an array containing the list of fields to secure for this widget. +If CakePHP is constructing your widget you can expect to get a ``Cake\View\StringTemplate`` instance as the first argument, followed by any dependencies you define. If we wanted to build an Autocomplete widget you could do the following:: namespace App\View\Widget; + use Cake\View\Form\ContextInterface; use Cake\View\Widget\WidgetInterface; class AutocompleteWidget implements WidgetInterface @@ -1646,7 +1802,7 @@ could do the following:: $this->_templates = $templates; } - public function render(array $data) + public function render(array $data, ContextInterface $context) { $data += [ 'name' => '', @@ -1657,6 +1813,10 @@ could do the following:: ]); } + public function secureFields(array $data) + { + return [$data['name']]; + } } Obviously, this is a very simple example, but it demonstrates how a custom @@ -1698,7 +1858,7 @@ widgets using the ``addWidget()`` method would look like:: // Using a classname. $this->Form->addWidget( 'autocomplete', - ['Autocomplete', 'text' 'label'] + ['Autocomplete', 'text', 'label'] ); // Using an instance - requires you to resolve dependencies. diff --git a/en/views/helpers/html.rst b/en/views/helpers/html.rst index c4b02045ee20f09c7ac2d071dd52d64d49d4fbe6..5979845bf0f734912b4a39bc241c962c43786721 100644 --- a/en/views/helpers/html.rst +++ b/en/views/helpers/html.rst @@ -1,5 +1,5 @@ -HtmlHelper -########## +Html +#### .. php:namespace:: Cake\View\Helper @@ -71,7 +71,7 @@ will be appended to. By default it will append to the ``css`` block. If key 'rel' in ``$options`` array is set to 'import' the stylesheet will be imported. This method of CSS inclusion assumes that the CSS file specified -resides inside the ``webroot/css`` directory if path doesn't start with a '/'. :: +resides inside the **webroot/css** directory if path doesn't start with a '/'. :: echo $this->Html->css('forms'); @@ -94,14 +94,14 @@ Will output: You can include CSS files from any loaded plugin using -:term:`plugin syntax`. To include ``plugins/DebugKit/webroot/css/toolbar.css`` +:term:`plugin syntax`. To include **plugins/DebugKit/webroot/css/toolbar.css** you could use the following:: echo $this->Html->css('DebugKit.toolbar.css'); If you want to include a CSS file which shares a name with a loaded plugin you can do the following. For example if you had a ``Blog`` plugin, -and also wanted to include ``webroot/css/Blog.common.css``, you would:: +and also wanted to include **webroot/css/Blog.common.css**, you would:: echo $this->Html->css('Blog.common.css', ['plugin' => false]); @@ -240,7 +240,7 @@ Linking to Images Creates a formatted image tag. The path supplied should be relative -to ``webroot/img/``. :: +to **webroot/img/**. :: echo $this->Html->image('cake_logo.png', ['alt' => 'CakePHP']); @@ -278,7 +278,7 @@ Will output: You can include image files from any loaded plugin using -:term:`plugin syntax`. To include ``plugins/DebugKit/webroot/img/icon.png`` +:term:`plugin syntax`. To include **plugins/DebugKit/webroot/img/icon.png** You could use the following:: echo $this->Html->image('DebugKit.icon.png'); @@ -395,7 +395,7 @@ Will output: Brownies -Also check :php:meth:`Cake\View\Helper\UrlHelper::build()` method +Also check :php:meth:`Cake\\View\\Helper\\UrlHelper::build()` method for more examples of different types of URLs. Linking to Videos and Audio Files @@ -466,7 +466,7 @@ generated script tag. If an array of script tags is used, the attributes will be applied to all of the generated script tags. This method of JavaScript file inclusion assumes that the -JavaScript file specified resides inside the ``webroot/js`` +JavaScript file specified resides inside the **webroot/js** directory:: echo $this->Html->script('scripts'); @@ -478,7 +478,7 @@ Will output: You can link to files with absolute paths as well to link files -that are not in ``webroot/js``:: +that are not in **webroot/js**:: echo $this->Html->script('/otherdir/script_file'); @@ -514,7 +514,7 @@ In your layout you can output all the script tags added to 'scriptBottom':: echo $this->fetch('scriptBottom'); You can include script files from any loaded plugin using -:term:`plugin syntax`. To include ``plugins/DebugKit/webroot/js/toolbar.js`` +:term:`plugin syntax`. To include **plugins/DebugKit/webroot/js/toolbar.js** You could use the following:: echo $this->Html->script('DebugKit.toolbar.js'); @@ -563,7 +563,7 @@ Build a nested list (UL/OL) out of an associative array:: 'American', 'Canadian', 'British', - [, + ], 'Spanish', 'German', ] @@ -772,6 +772,7 @@ Creating Breadcrumb Trails with HtmlHelper .. php:method:: addCrumb(string $name, string $link = null, mixed $options = null) .. php:method:: getCrumbs(string $separator = '»', string $startText = false) +.. php:method:: getCrumbList(array $options = [], $startText = false) Many applications have breadcrumb trails to ease end user navigations. You can create a breadcrumb trail in your app with some help from HtmlHelper. To make @@ -798,13 +799,27 @@ breadcrumb trails on each of the pages:: $this->Html->addCrumb('Users', '/users'); $this->Html->addCrumb('Add User', ['controller' => 'Users', 'action' => 'add']); -This will add the output of "**Home > Users > Add User**" in your -layout where ``getCrumbs`` was added. +This will add the output of "**Home > Users > Add User**" in your layout where +``getCrumbs`` was added. You can also fetch the crumbs formatted inside an HTML list:: echo $this->Html->getCrumbList(); +As options you can use regular HTML parameter that fits in the ``
    `` +(Unordered List) such as ``class`` and for the specific options, you have: +``separator`` (will be between the ``
  • `` elements), ``firstClass`` and +``lastClass`` like:: + + echo $this->Html->getCrumbList( + [ + 'firstClass' => false, + 'lastClass' => 'active', + 'class' => 'breadcrumb' + ], + 'Home' + ); + This method uses :php:meth:`Cake\\View\\Helper\\HtmlHelper::tag()` to generate list and its elements. Works similar to :php:meth:`~Cake\\View\\Helper\\HtmlHelper::getCrumbs()`, so it uses options diff --git a/en/views/helpers/number.rst b/en/views/helpers/number.rst index 2e957765baef0a69e0639bea859faf37b1b6cacf..640860bf32d9c12932ea3617a162a2eb58c54527 100644 --- a/en/views/helpers/number.rst +++ b/en/views/helpers/number.rst @@ -1,5 +1,5 @@ -NumberHelper -############ +Number +###### .. php:namespace:: Cake\View\Helper diff --git a/en/views/helpers/paginator.rst b/en/views/helpers/paginator.rst index 11a438ec6e3c0b6f5b1635b8075c1a25bb620410..2f7aaa4f5b5fe3b68d56943b85caf5c5b342b831 100644 --- a/en/views/helpers/paginator.rst +++ b/en/views/helpers/paginator.rst @@ -1,5 +1,5 @@ -PaginatorHelper -############### +Paginator +######### .. php:namespace:: Cake\View\Helper @@ -36,8 +36,8 @@ customize multiple templates and keep your code DRY:: 'Paginator' => ['templates' => 'paginator-templates'] ]; -This will load the file located at ``config/paginator-templates.php`` and -read templates from the ``$config`` variable within that file. You can also load +This will load the file located at ``config/paginator-templates.php``. See the +example below for how the file should look like. You can also load templates from a plugin using :term:`plugin syntax`:: // In a controller. @@ -425,7 +425,7 @@ which can be easily integrated into your table column headers:
- + @@ -446,7 +446,7 @@ It is also possible to sort a column based on associations: - + diff --git a/en/views/helpers/rss.rst b/en/views/helpers/rss.rst index 2eac17e6608b272b4c315654381f92e0a9fd6ab5..dbf886b20b6da60ba5c75b47c9b536ca27061c7c 100644 --- a/en/views/helpers/rss.rst +++ b/en/views/helpers/rss.rst @@ -1,5 +1,5 @@ -RssHelper -######### +Rss +### .. php:namespace:: Cake\View\Helper @@ -10,30 +10,30 @@ The RSS helper makes generating XML for `RSS feeds loadComponent('RequestHandler'); } -Our view will also use the :php:class:`TextHelper` for formatting, so that -should be added to the controller as well:: - - public $helpers = ['Text']; - -Before we can make an RSS version of our posts/index we need to get -a few things in order. It may be tempting to put the channel -metadata in the controller action and pass it to your view using -the :php:meth:`Controller::set()` method but this is inappropriate. That -information can also go in the view. That will come later though, -for now if you have a different set of logic for the data used to -make the RSS feed and the data for the HTML view you can use the -:php:meth:`RequestHandler::isRss()` method, otherwise your controller can stay -the same:: +Before we can make an RSS version of our ``articles/index`` we need to get a few +things in order. It may be tempting to put the channel metadata in the +controller action and pass it to your view using the +:php:meth:`Cake\\Controller\\Controller::set()` method but this is +inappropriate. That information can also go in the view. That will come later +though, for now if you have a different set of logic for the data used to make +the RSS feed and the data for the HTML view you can use the +:php:meth:`Cake\\Controller\\Component\\RequestHandler::isRss()` method, +otherwise your controller can stay the same:: // Modify the Posts Controller action that corresponds to // the action which deliver the rss feed, which is the @@ -64,22 +59,21 @@ the same:: public function index() { if ($this->RequestHandler->isRss() ) { - $posts = $this->Posts->find( - 'all', - ['limit' => 20, 'order' => 'Post.created DESC'] - ); - return $this->set(compact('posts')); + $articles = $this->Articles + ->find() + ->limit(20) + ->order(['created' => 'desc']); + $this->set(compact('articles')); + } else { + // this is not an Rss request, so deliver + // data used by website's interface. + $this->paginate = [ + 'order' => ['created' => 'desc'], + 'limit' => 10 + ]; + $this->set('articles', $this->paginate($this->Articles)); + $this->set('_serialize', ['articles']); } - - // this is not an Rss request, so deliver - // data used by website's interface. - $this->paginate['Post'] = [ - 'order' => 'Post.created DESC', - 'limit' => 10 - ]; - - $posts = $this->paginate(); - $this->set(compact('posts')); } With all the View variables set we need to create an rss layout. @@ -88,7 +82,7 @@ Layout ------ An Rss layout is very simple, put the following contents in -``src/Template/Layout/rss/default.ctp``:: +**src/Template/Layout/rss/default.ctp**:: if (!isset($documentData)) { $documentData = []; @@ -105,79 +99,77 @@ An Rss layout is very simple, put the following contents in It doesn't look like much but thanks to the power in the ``RssHelper`` it's doing a lot of lifting for us. We haven't set ``$documentData`` or ``$channelData`` in the controller, however in CakePHP your views -can pass variables back to the layout. Which is where our -``$channelData`` array will come from setting all of the meta data for -our feed. +can pass variables back to the layout. Which is where our ``$channelData`` +array will come from setting all of the meta data for our feed. -Next up is view file for my posts/index. Much like the layout file -we created, we need to create a ``src/Template/Posts/rss/`` directory and +Next up is view file for my articles/index. Much like the layout file +we created, we need to create a **src/Template/Posts/rss/** directory and create a new ``index.ctp`` inside that folder. The contents of the file are below. View ---- -Our view, located at ``src/Template/Posts/rss/index.ctp``, begins by -setting the ``$documentData`` and ``$channelData`` variables for the -layout, these contain all the metadata for our RSS feed. This is -done by using the :php:meth:`View::set()`` method which is analogous to the -Controller::set() method. Here though we are passing the channel's -metadata back to the layout:: +Our view, located at **src/Template/Posts/rss/index.ctp**, begins by setting the +``$documentData`` and ``$channelData`` variables for the layout, these contain +all the metadata for our RSS feed. This is done by using the +:php:meth:`Cake\\View\\View::set()` method which is analogous to the +:php:meth:`Cake\\Controller\\Controller::set()` method. Here though we are +passing the channel's metadata back to the layout:: $this->set('channelData', [ 'title' => __("Most Recent Posts"), - 'link' => $this->Html->url('/', true), + 'link' => $this->Url->build('/', true), 'description' => __("Most recent posts."), 'language' => 'en-us' ]); -The second part of the view generates the elements for the actual -records of the feed. This is accomplished by looping through the -data that has been passed to the view ($items) and using the -:php:meth:`RssHelper::item()` method. The other method you can use, -:php:meth:`RssHelper::items()` which takes a callback and an array of items for -the feed. (The method I have seen used for the callback has always -been called ``transformRss()``. There is one downfall to this method, -which is that you cannot use any of the other helper classes to -prepare your data inside the callback method because the scope -inside the method does not include anything that is not passed -inside, thus not giving access to the TimeHelper or any other -helper that you may need. The :php:meth:`RssHelper::item()` transforms the -associative array into an element for each key value pair. +The second part of the view generates the elements for the actual records of +the feed. This is accomplished by looping through the data that has been passed +to the view ($items) and using the :php:meth:`RssHelper::item()` method. The +other method you can use, :php:meth:`RssHelper::items()` which takes a callback +and an array of items for the feed. The callback method is usually called +``transformRss()``. There is one downfall to this method, which is that you +cannot use any of the other helper classes to prepare your data inside the +callback method because the scope inside the method does not include anything +that is not passed inside, thus not giving access to the TimeHelper or any +other helper that you may need. The :php:meth:`RssHelper::item()` transforms +the associative array into an element for each key value pair. .. note:: - You will need to modify the $postLink variable as appropriate to - your application. + You will need to modify the $link variable as appropriate to + your application. You might also want to use a + :ref:`virtual property ` in your Entity. :: - foreach ($posts as $post) { - $postTime = strtotime($post['Post']['created']); + foreach ($articles as $article) { + $created = strtotime($article->created); - $postLink = [ - 'controller' => 'Posts', + $link = [ + 'controller' => 'Articles', 'action' => 'view', - 'year' => date('Y', $postTime), - 'month' => date('m', $postTime), - 'day' => date('d', $postTime), - $post['Post']['slug'] + 'year' => date('Y', $created), + 'month' => date('m', $created), + 'day' => date('d', $created), + 'slug' => $article->slug ]; // Remove & escape any HTML to make sure the feed content will validate. - $bodyText = h(strip_tags($post['Post']['body'])); - $bodyText = $this->Text->truncate($bodyText, 400, [ + $body = h(strip_tags($article->body)); + $body = $this->Text->truncate($body, 400, [ 'ending' => '...', 'exact' => true, 'html' => true, ]); echo $this->Rss->item([], [ - 'title' => $post['Post']['title'], - 'link' => $postLink, - 'guid' => ['url' => $postLink, 'isPermaLink' => 'true'], - 'description' => $bodyText, - 'pubDate' => $post['Post']['created'] + 'title' => $article->title, + 'link' => $link, + 'guid' => ['url' => $link, 'isPermaLink' => 'true'], + 'description' => $body, + 'pubDate' => $article->created ]); } @@ -185,7 +177,7 @@ You can see above that we can use the loop to prepare the data to be transformed into XML elements. It is important to filter out any non-plain text characters out of the description, especially if you are using a rich text editor for the body of your blog. In the code above we used ``strip_tags()`` and -:php:func:`h()` to remove/escape any XML special characaters from the content, +:php:func:`h()` to remove/escape any XML special characters from the content, as they could cause validation errors. Once we have set up the data for the feed, we can then use the :php:meth:`RssHelper::item()` method to create the XML in RSS format. Once you have all this setup, you can test your RSS feed by going diff --git a/en/views/helpers/session.rst b/en/views/helpers/session.rst index d9156bd5ee74acc0d253a93de8c04f14baf576ab..4033c9b1131dbe4adc6475cbe2b4ce3b3380529b 100644 --- a/en/views/helpers/session.rst +++ b/en/views/helpers/session.rst @@ -1,16 +1,16 @@ -SessionHelper -############# +Session +####### .. php:namespace:: Cake\View\Helper .. php:class:: SessionHelper(View $view, array $config = []) -As a natural counterpart to the Session Component, the Session -Helper replicates most of the component's functionality and makes it +As a natural counterpart to the Session object, the Session +Helper replicates most of the object's functionality and makes it available in your view. The major difference between the Session Helper and the Session -Component is that the helper does *not* have the ability to write +object is that the helper does *not* have the ability to write to the session. As with the session object, data is read by using diff --git a/en/views/helpers/text.rst b/en/views/helpers/text.rst index a3b6bf5e594ad6413fc6173557f218c6f614b1b3..f2575d94d5288b9111eed84387387b4dde4a90da 100644 --- a/en/views/helpers/text.rst +++ b/en/views/helpers/text.rst @@ -1,5 +1,5 @@ -TextHelper -########## +Text +#### .. php:namespace:: Cake\View\Helper diff --git a/en/views/helpers/time.rst b/en/views/helpers/time.rst index 5266866a8c59914002c5092068cbe134bee5a7a4..1b7cf3c081203e833f550af312644ea3279a7266 100644 --- a/en/views/helpers/time.rst +++ b/en/views/helpers/time.rst @@ -1,5 +1,5 @@ -TimeHelper -########## +Time +#### .. php:namespace:: Cake\View\Helper @@ -19,7 +19,7 @@ A common use of the Time Helper is to offset the date and time to match a user's time zone. Lets use a forum as an example. Your forum has many users who may post messages at any time from any part of the world. An easy way to manage the time is to save all dates and times as GMT+0 or UTC. Uncomment the -line ``date_default_timezone_set('UTC');`` in ``config/bootstrap.php`` to ensure +line ``date_default_timezone_set('UTC');`` in **config/bootstrap.php** to ensure your application's time zone is set to GMT+0. Next add a time zone field to your users table and make the necessary @@ -42,6 +42,9 @@ Most of TimeHelper's features are intended as backwards compatible interfaces for applications that are upgrading from older versions of CakePHP. Because the ORM returns :php:class:`Cake\\I18n\\Time` instances for every ``timestamp`` and ``datetime`` column, you can use the methods there to do most tasks. +E.g. to read about the accepted formatting strings take a look at the +`Cake\\I18n\\Time::i18nFormat() +`_ method. .. meta:: :title lang=en: TimeHelper diff --git a/en/views/helpers/url.rst b/en/views/helpers/url.rst index 4cd0e4463ce56a0e96fd5c8c2681ed8af6ac1a67..10c42795c1e0bc16c5665f770808ac7f6fc35c57 100644 --- a/en/views/helpers/url.rst +++ b/en/views/helpers/url.rst @@ -1,5 +1,5 @@ -UrlHelper -########## +Url +### .. php:namespace:: Cake\View\UrlHelper @@ -21,7 +21,7 @@ generates the URL for the controller and action combo. If ``full`` is ``true``, the full base URL will be prepended to the result:: echo $this->Url->build([ - "controller" => "posts", + "controller" => "Posts", "action" => "view", "bar" ]); @@ -34,7 +34,7 @@ Here are a few more usage examples: URL with named parameters:: echo $this->Url->build([ - "controller" => "posts", + "controller" => "Posts", "action" => "view", "foo" => "bar" ]); @@ -45,7 +45,7 @@ URL with named parameters:: URL with extension:: echo $this->Url->build([ - "controller" => "posts", + "controller" => "Posts", "action" => "list", "_ext" => "rss" ]); @@ -63,7 +63,7 @@ URL (starting with '/') with the full base URL prepended:: URL with GET params and named anchor:: echo $this->Url->build([ - "controller" => "posts", + "controller" => "Posts", "action" => "search", "?" => ["foo" => "bar"], "#" => "first" @@ -80,7 +80,7 @@ URL for named route:: // $router->connect( // '/products/:slug', // [ - // 'controller' => 'products', + // 'controller' => 'Products', // 'action' => 'view' // ], // [ diff --git a/en/views/json-and-xml-views.rst b/en/views/json-and-xml-views.rst index ca18af2e9e06d8fb8c8e57348ebae3eb814fd6aa..1dab844ea95af1903a81f81aabcbde414cec63fd 100644 --- a/en/views/json-and-xml-views.rst +++ b/en/views/json-and-xml-views.rst @@ -1,13 +1,13 @@ JSON and XML views ################## -The ``XmlView`` and ``JsonView`` -let you easily create XML and JSON responses, and integrate with the +The ``JsonView`` and ``XmlView`` +let you easily create JSON and XML responses, and integrate with the :php:class:`Cake\\Controller\\Component\\RequestHandlerComponent`. By enabling ``RequestHandlerComponent`` in your application, and enabling -support for the ``xml`` and or ``json`` extensions, you can automatically -leverage the new view classes. ``XmlView`` and ``JsonView`` will be referred to +support for the ``json`` and or ``xml`` extensions, you can automatically +leverage the new view classes. ``JsonView`` and ``XmlView`` will be referred to as data views for the rest of this page. There are two ways you can generate data views. The first is by using the @@ -16,31 +16,43 @@ There are two ways you can generate data views. The first is by using the Enabling Data Views in Your Application ======================================= -Before you can use the data view classes, you'll need to do a bit of setup: +Before you can use the data view classes, you'll first need to load the +:php:class:`Cake\\Controller\\Component\\RequestHandlerComponent` in your +contoller:: -#. Enable the json and or xml extensions with :ref:`file-extensions`. This will - enable Router to handle multiple extensions. -#. Add the :php:class:`Cake\\Controller\\Component\\RequestHandlerComponent` to - your controller's list of components. This will enable automatic view class - switching on content types. You can also set the component up with the - ``viewClassMap`` setting, to map types to your custom classes and/or map - other data types. + public function initialize() + { + ... + $this->loadComponent('RequestHandler'); + } + +This can be done in your `AppController` and will enable automatic view class +switching on content types. You can also set the component up with the +``viewClassMap`` setting, to map types to your custom classes and/or map other +data types. + +You can optionally enable the json and or xml extensions with +:ref:`file-extensions`. This will allow you to access the ``JSON``, ``XML`` or +any other special format views by using a custom URL ending with the name of the +response type as a file extension such as ``http://example.com/articles.json``. -After :ref:`enabling extension routing `, CakePHP -will automatically switch view classes when a request is done with the ``.json`` -extension, or the Accept header is ``application/json``. +By default, when not enabling :ref:`file-extensions`, the request the ``Accept`` +header is used for selecting which type of format should be rendered to the +user. An example ``Accept`` format that is used to render ``JSON`` responses is +``application/json``. Using Data Views with the Serialize Key ======================================= -The ``_serialize`` key is a special view variable that indicates which other view -variable(s) should be serialized when using a data view. This lets you skip +The ``_serialize`` key is a special view variable that indicates which other +view variable(s) should be serialized when using a data view. This lets you skip defining template files for your controller actions if you don't need to do any custom formatting before your data is converted into json/xml. If you need to do any formatting or manipulation of your view variables before -generating the response, you should use template files. The value of ``_serialize`` -can be either a string or an array of view variables to serialize:: +generating the response, you should use template files. The value of +``_serialize`` can be either a string or an array of view variables to +serialize:: namespace App\Controller; @@ -54,9 +66,9 @@ can be either a string or an array of view variables to serialize:: public function index() { - // You have to select which data type you want to output using viewClass - $this->viewClass = 'Json'; + // Set the view vars that have to be serialized. $this->set('articles', $this->paginate()); + // Specify which view vars JsonView should serialize. $this->set('_serialize', ['articles']); } } @@ -76,7 +88,11 @@ You can also define ``_serialize`` as an array of view variables to combine:: public function index() { // Some code that created $articles and $comments + + // Set the view vars that have to be serialized. $this->set(compact('articles', 'comments')); + + // Specify which view vars JsonView should serialize. $this->set('_serialize', ['articles', 'comments']); } } @@ -87,11 +103,16 @@ If you use a string value for ``_serialize`` and XmlView, make sure that your view variable has a single top-level element. Without a single top-level element the Xml will fail to generate. +.. versionadded:: 3.1.0 + + You can also set ``_serialized`` to ``true`` to serialize all view variables + instead of explicitly specifying them. + Using a Data View with Template Files ===================================== You should use template files if you need to do some manipulation of your view -content before creating the final output. For example if we had posts, that had +content before creating the final output. For example if we had articles, that had a field containing generated HTML, we would probably want to omit that from a JSON response. This is a situation where a view file would be useful:: @@ -105,11 +126,11 @@ JSON response. This is a situation where a view file would be useful:: } } - // View code - src/Template/Posts/json/index.ctp - foreach ($posts as &$post) { - unset($post->generated_html); + // View code - src/Template/Articles/json/index.ctp + foreach ($articles as &$$article) { + unset($article->generated_html); } - echo json_encode(compact('posts')); + echo json_encode(compact('articles')); You can do more complex manipulations, or use helpers to do formatting as well. @@ -128,6 +149,9 @@ By default when using ``_serialize`` the XmlView will wrap your serialized view variables with a ```` node. You can set a custom name for this node using the ``_rootNode`` view variable. +The XmlView class supports the ``_xmlOptions`` variable that allows you to +customize the options used to generate XML, e.g. ``tags`` vs ``attributes``. + Creating JSON Views =================== @@ -141,8 +165,9 @@ values of this option. JSONP Responses --------------- -When using ``JsonView`` you can use the special view variable ``_jsonp`` to enable -returning a JSONP response. Setting it to ``true`` makes the view class check if query -string parameter named "callback" is set and if so wrap the json response in the -function name provided. If you want to use a custom query string parameter name -instead of "callback" set ``_jsonp`` to required name instead of ``true``. +When using ``JsonView`` you can use the special view variable ``_jsonp`` to +enable returning a JSONP response. Setting it to ``true`` makes the view class +check if query string parameter named "callback" is set and if so wrap the json +response in the function name provided. If you want to use a custom query string +parameter name instead of "callback" set ``_jsonp`` to required name instead of +``true``. diff --git a/en/views/themes.rst b/en/views/themes.rst index df6348134b9ecf8b4c977ecef696a76695b3d070..41ff27941171dea9e1db951bdcc06d60765de2f7 100644 --- a/en/views/themes.rst +++ b/en/views/themes.rst @@ -7,30 +7,31 @@ providing template files. In addition to template files, they can also provide helpers and cells if your theming requires that. When using cells and helpers from your theme, you will need to continue using the :term:`plugin syntax`. -To use themes, specify the theme name in your controller:: +To use themes, set the theme name in your controller's action or ``beforeRender()`` callback:: class ExamplesController extends AppController { + // For CakePHP before 3.1 public $theme = 'Modern'; - } - -You can also set or change the theme name within an action or within the -``beforeFilter`` or ``beforeRender`` callback functions:: - $this->theme = 'AnotherExample'; + public function beforeRender(\Cake\Event\Event $event) + { + $this->viewBuilder()->theme('Modern'); + } + } Theme template files need to be within a plugin with the same name. For example, -the above theme would be found in ``plugins/AnotherExample/src/Template``. +the above theme would be found in **plugins/AnotherExample/src/Template**. It's important to remember that CakePHP expects CamelCase plugin/theme names. Beyond -that, the folder structure within the ``plugins/AnotherExample/src/Template`` folder is -exactly the same as ``src/Template/``. +that, the folder structure within the **plugins/AnotherExample/src/Template** folder is +exactly the same as **src/Template/**. For example, the view file for an edit action of a Posts controller would reside -at ``plugins/Modern/src/Template/Posts/edit.ctp``. Layout files would reside in -``plugins/Modern/src/Template/Layout/``. +at **plugins/Modern/src/Template/Posts/edit.ctp**. Layout files would reside in +**plugins/Modern/src/Template/Layout/**. If a view file can't be found in the theme, CakePHP will try to locate the view -file in the ``src/Template/`` folder. This way, you can create master template files +file in the **src/Template/** folder. This way, you can create master template files and simply override them on a case-by-case basis within your theme folder. Theme Assets diff --git a/es/_static/img/basic_mvc.png b/es/_static/img/basic_mvc.png deleted file mode 100644 index 099d13461e324b0239c37102694b1804f5f432d1..0000000000000000000000000000000000000000 Binary files a/es/_static/img/basic_mvc.png and /dev/null differ diff --git a/es/_static/img/debug-kit/history-panel-use.gif b/es/_static/img/debug-kit/history-panel-use.gif new file mode 100644 index 0000000000000000000000000000000000000000..54efaba67859b77f75275c705d4c2f11f59f5b53 Binary files /dev/null and b/es/_static/img/debug-kit/history-panel-use.gif differ diff --git a/es/_static/img/debug-kit/history-panel.png b/es/_static/img/debug-kit/history-panel.png new file mode 100644 index 0000000000000000000000000000000000000000..0c6b27e20c8c6ac8896b6f97bdcc3732f6ffdd74 Binary files /dev/null and b/es/_static/img/debug-kit/history-panel.png differ diff --git a/es/_static/img/typical-cake-request.png b/es/_static/img/typical-cake-request.png index f951d3619642a46a8c4de2b9123e47039c285760..bc5b0dc2a63aa68906b0cc00c334392a1a712280 100644 Binary files a/es/_static/img/typical-cake-request.png and b/es/_static/img/typical-cake-request.png differ diff --git a/es/appendices.rst b/es/appendices.rst index 314e7aa29082b7871142cc13f6364d50bd024755..13a6806dcc7a5331b7142f16781cb258f241a838 100644 --- a/es/appendices.rst +++ b/es/appendices.rst @@ -2,9 +2,13 @@ Appendices ########## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. Appendices contain information regarding the new features introduced in each version and the migration path between versions. @@ -12,15 +16,20 @@ introduced in each version and the migration path between versions. 3.0 Migration Guide =================== -3.0 is still under development, and any documented changes -will only be available in the ``3.0`` branch in git. - .. toctree:: :maxdepth: 1 appendices/3-0-migration-guide appendices/orm-migration +3.1 Migration Guide +=================== + +.. toctree:: + :maxdepth: 1 + + appendices/3-1-migration-guide + General Information =================== @@ -30,7 +39,6 @@ General Information appendices/cakephp-development-process appendices/glossary - .. meta:: - :title lang=en: Appendices - :keywords lang=en: migration guide,migration path,new features,glossary + :title lang=es: Appendices + :keywords lang=es: migration guide,migration path,new features,glossary diff --git a/es/appendices/3-0-migration-guide.rst b/es/appendices/3-0-migration-guide.rst index f9a9eedc6d290f8b47a963a48b0c40dc20fc8681..4599960f6dbf5995114039ee8887e55e50892961 100644 --- a/es/appendices/3-0-migration-guide.rst +++ b/es/appendices/3-0-migration-guide.rst @@ -2,1104 +2,11 @@ ################### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -This page summarizes the changes from CakePHP 2.x that will assist in migrating -a project to 3.0, as well as a reference to get up to date with the changes made -to the core since the CakePHP 2.x branch. Be sure to read the other pages in -this guide for all the new features and API changes. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón + **Improve this Doc** para proponer directamente los cambios. - -Requirements -============ - -- CakePHP 3.x supports PHP Version 5.4.16 and above. -- CakePHP 3.x requires the mbstring extension. -- CakePHP 3.x requires the mcrypt extension. - -.. warning:: - - CakePHP 3.0 will not work if you do not meet the above requirements. - -Application Directory Layout -============================ - -The application directory layout has changed and now follows -`PSR-4 `_. You should use the -`app skeleton `_ project as a reference point -when updating your application. - -CakePHP should be installed with Composer -========================================= - -Since CakePHP can no longer easily be installed via PEAR, or in a shared -directory, those options are no longer supported. Instead you should use -`Composer `_ to install CakePHP into your application. - -Namespaces -========== - -All of CakePHP's core classes are now namespaced and follow PSR-4 autoloading -specifications. For example ``src/Cache/Cache.php`` is namespaced as -``Cake\Cache\Cache``. Global constants and helper methods like :php:meth:`__()` -and :php:meth:`debug()` are not namespaced for convenience sake. - -Removed Constants -================= - -The following deprecated constants have been removed: - -* ``IMAGES`` -* ``CSS`` -* ``JS`` -* ``IMAGES_URL`` -* ``JS_URL`` -* ``CSS_URL`` -* ``DEFAULT_LANGUAGE`` - -Configuration -============= - -Configuration in CakePHP 3.0 is significantly different than in previous -versions. You should read the :doc:`/development/configuration` documentation -for how configuration is done in 3.0. - -You can no longer use ``App::build()`` to configure additional class paths. -Instead you should map additional paths using your application's autoloader. See -the section on :ref:`additional-class-paths` for more information. - -Two new configure variables provide the path configuration for plugins, and -views. You can add multiple paths to ``App.paths.templates`` and -``App.paths.plugins`` to configure multiple paths for templates & plugins. - -New ORM -======= - -CakePHP 3.0 features a new ORM that has been re-built from the ground up. The -new ORM is significantly different and incompatible with the previous one. -Upgrading to the new ORM will require extensive changes in any application that -is being upgraded. See the new :doc:`/orm` documentation for information on how -to use the new ORM. - - -Basics -====== - -* ``LogError()`` was removed, it provided no benefit and is rarely/never used. -* The following global functions have been removed: ``config()``, ``cache()``, - ``clearCache()``, ``convertSlashes()``, ``am()``, ``fileExistsInPath()``, - ``sortByKey()``. - -Debugging -========= - -* ``Configure::write('debug', $bool)`` does not support 0/1/2 anymore. A simple boolean - is used instead to switch debug mode on or off. - -Object settings/configuration -============================= - -* Objects used in CakePHP now have a consistent instance-configuration storage/retrieval - system. Code which previously accessed for example: ``$object->settings`` should instead - be updated to use ``$object->config()``. - -Cache -===== - -* ``Memcache`` engine has been removed, use :php:class:`Cake\\Cache\\Cache\\Engine\\Memcached` instead. -* Cache engines are now lazy loaded upon first use. -* :php:meth:`Cake\\Cache\\Cache::engine()` has been added. -* :php:meth:`Cake\\Cache\\Cache::enabled()` has been added. This replaced the - ``Cache.disable`` configure option. -* :php:meth:`Cake\\Cache\\Cache::enable()` has been added. -* :php:meth:`Cake\\Cache\\Cache::disable()` has been added. -* Cache configurations are now immutable. If you need to change configuration - you must first drop the configuration and then re-create it. This prevents - synchronization issues with configuration options. -* ``Cache::set()`` has been removed. It is recommended that you create multiple - cache configurations to replace runtime configuration tweaks previously - possible with ``Cache::set()``. -* All ``CacheEngine`` subclasses now implement a ``config()`` method. -* :php:meth:`Cake\\Cache\\Cache::readMany()`, :php:meth:`Cake\\Cache\\Cache::deleteMany()`, - and :php:meth:`Cake\\Cache\\Cache::writeMany()` were added. - -All :php:class:`Cake\\Cache\\Cache\\CacheEngine` methods now honor/are responsible for handling the -configured key prefix. The :php:meth:`Cake\\Cache\\CacheEngine::write()` no longer permits setting -the duration on write - the duration is taken from the cache engine's runtime config. Calling a -cache method with an empty key will now throw an :php:class:`InvalidArgumentException`, instead -of returning false. - - -Core -==== - -App ---- - -- ``App::pluginPath()`` has been removed. Use ``CakePlugin::path()`` instead. -- ``App::build()`` has been removed. -- ``App::location()`` has been removed. -- ``App::paths()`` has been removed. -- ``App::load()`` has been removed. -- ``App::objects()`` has been removed. -- ``App::RESET`` has been removed. -- ``App::APPEND`` has been removed. -- ``App::PREPEND`` has been removed. -- ``App::REGISTER`` has been removed. - -Plugin ------- - -- :php:meth:`Cake\\Core\\Plugin::load()` does not setup an autoloader unless - you set the ``autoload`` option to ``true``. -- When loading plugins you can no longer provide a callable. -- When loading plugins you can no longer provide an array of config files to - load. - -Configure ---------- - -The config reader classes have been renamed: - -- ``Cake\Configure\PhpReader`` renamed to :php:class:`Cake\\Configure\\Engine\PhpConfig` -- ``Cake\Configure\IniReader`` renamed to :php:class:`Cake\\Configure\\Engine\IniConfig` -- ``Cake\Configure\ConfigReaderInterface`` renamed to :php:class:`Cake\\Configure\\ConfigEngineInterface` -- :php:meth:`Cake\\Core\\Configure::consume()` was added. - -Object ------- - -The ``Object`` class has been removed. It formerly contained a grab bag of -methods that were used in various places across the framework. The most useful -of these methods have been extracted into traits. You can use the -:php:trait:`Cake\\Log\\LogTrait` to access the ``log()`` method. The -:php:trait:`Cake\\Routing\\RequestActionTrait` provides ``requestAction()``. - -Console -======= - -TaskCollection Replaced ------------------------ - -This class has been renamed to :php:class:`Cake\\Console\\TaskRegistry`. -See the section on :doc:`/core-libraries/registry-objects` for more information -on the features provided by the new class. You can use the ``cake upgrade -rename_collections`` to assist in upgrading your code. Tasks no longer have -access to callbacks, as there were never any callbacks to use. - -ApiShell Removed ----------------- - -The ApiShell was removed as it didn't provide any benefit over the file source itself -and the online documentation/`API `_. - -ExtractTask ------------ - -- ``bin/cake i18n extract`` no longer includes untranslated validation - messages. If you want translated validation messages you should wrap those - messages in `__()` calls like any other content. - -Shell ------ - -- ``Shell::__construct()`` has changed. It now takes an instance of - ``Cake\\Console\\ConsoleIo``. -- ``Shell::param()`` has been added as convenience access to the params. - -Additionally all shell methods will be transformed to camel case when invoked. -For example, if you had a ``hello_world()`` method inside a shell and invoked it -with ``bin/cake my_shell hello_world``, you will need to rename the method -to ``helloWorld``. There are no changes required in the way you invoke commands. - -BakeShell / TemplateTask ------------------------- - -- Bake templates have been moved under `src/Template/Bake`. Also, the ``theme`` - option, used for selecting a bake template, has been renamed to ``template``. - -Event -===== - -The ``getEventManager()`` method, was removed on all objects that had it. An -``eventManager()`` method is now provided by the ``EventManagerTrait``. The -``EventManagerTrait`` contains the logic of instantiating and keeping -a reference to a local event manager. - -The Event subsystem has had a number of optional features removed. When -dispatching events you can no longer use the following options: - - * ``passParams`` This option is now enabled always implicitly. You - cannot turn it off. - * ``break`` This option has been removed. You must now stop events. - * ``breakOn`` This option has been removed. You must now stop events. - -Log -=== - -* Log configurations are now immutable. If you need to change configuration - you must first drop the configuration and then re-create it. This prevents - synchronization issues with configuration options. -* Log engines are now lazily loaded upon the first write to the logs. -* :php:meth:`Cake\\Log\\Log::engine()` has been added. -* The following methods have been removed from :php:class:`Cake\\Log\\Log` :: - ``defaultLevels()``, ``enabled()``, ``enable()``, ``disable()``. -* You can no longer create custom levels using ``Log::levels()``. -* When configuring loggers you should use ``'levels'`` instead of ``'types'``. -* You can no longer specify custom log levels. You must use the default set of - log levels. You should use logging scopes to create custom log files or - specific handling for different sections of your application. Using - a non-standard log level will now throw an exception. -* :php:trait:`Cake\\Log\\LogTrait` was added. You can use this trait in your classes to - add the ``log()`` method. -* The logging scope passed to :php:meth:`Cake\\Log\\Log::write()` is now forwarded - to the log engines' ``write()`` method in order to provide better context to - the engines. - -Routing -======= - -Named Parameters ------------------ - -Named parameters were removed in 3.0. Named parameters were added in 1.2.0 as -a 'pretty' version of query string parameters. While the visual benefit is -arguable, the problems named parameters created are not. - -Named parameters required special handling in CakePHP as well as any PHP or -JavaScript library that needed to interact with them, as named parameters are -not implemented or understood by any library *except* CakePHP. The additional -complexity and code required to support named parameters did not justify their -existence, and they have been removed. In their place you should use standard -query string parameters or passed arguments. By default ``Router`` will treat -any additional parameters to ``Router::url()`` as query string arguments. - -Since many applications will still need to parse incoming URLs containing named -parameters. :php:meth:`Cake\\Routing\\Router::parseNamedParams()` has -been added to allow backwards compatiblity with existing URLs. - - -RequestActionTrait ------------------- - -- :php:meth:`Cake\\Routing\\RequestActionTrait::requestAction()` has had - some of the extra options changed: - - - ``options[url]`` is now ``options[query]``. - - ``options[data]`` is now ``options[post]``. - - Named parameters are no longer supported. - -Router ------- - -* Named parameters have been removed, see above for more information. -* The ``full_base`` option has been replaced with the ``_full`` option. -* The ``ext`` option has been replaced with the ``_ext`` option. -* ``_scheme``, ``_port``, ``_host``, ``_base``, ``_full``, ``_ext`` options added. -* String URLs are no longer modified by adding the plugin/controller/prefix names. -* The default fallback route handling was removed. If no routes - match a parameter set ``/`` will be returned. -* Route classes are responsible for *all* URL generation including - query string parameters. This makes routes far more powerful and flexible. -* Persistent parameters were removed. They were replaced with - :php:meth:`Cake\\Routing\\Router::urlFilter()` which allows - a more flexible way to mutate URLs being reverse routed. -* The signature of :php:meth:`Cake\\Routing\\Router::parseExtensions()` has changed - to ``parseExtensions(string|array $extensions = null, $merge = true)``. It no - longer takes variable arguments for specifying extensions. Also you can no - longer call it with no parameters to parse all extensions (doing so will - return existing extensions that are set). You need to whitelist the extensions -* ``Router::parseExtensions()`` **must** be called before routes are connected. - It no longer modifies existing routes when called. - your application supports. -* ``Router::setExtensions()`` has been removed. Use :php:meth:`Cake\\Routing\\Router::parseExtensions()` - instead. -* ``Router::resourceMap()`` has been removed. -* The ``[method]`` option has been renamed to ``_method``. -* The ability to match arbitrary headers with ``[]`` style parameters has been - removed. If you need to parse/match on arbitrary conditions consider using - custom route classes. -* ``Router::promote()`` has been removed. -* ``Router::parse()`` will now raise an exception when a URL cannot be handled - by any route. -* ``Router::url()`` will now raise an exception when no route matches a set of - parameters. -* Routing scopes have been introduced. Routing scopes allow you to keep your - routes file DRY and give Router hints on how to optimize parsing & reverse - routing URLs. - -Route ------ - -* ``CakeRoute`` was re-named to ``Route``. -* The signature of ``match()`` has changed to ``match($url, $context = array())`` - See :php:meth:`Cake\\Routing\\Route::match()` for information on the new signature. - -Dispatcher Filters Configuration Changed ----------------------------------------- - -Dispatcher filters are no longer added to your application using ``Configure``. -You now append them with :php:class:`Cake\\Routing\\DispatcherFactory``. This -means if your application used ``Dispatcher.filters``, you should now use -php:meth:`Cake\\Routing\\DispatcherFactory::add()`. - -In addition to configuration changes, dispatcher filters have had some -conventions updated, and features added. See the -:doc:`/development/dispatch-filters` documentation for more information. - -Filter\AssetFilter ------------------- - -* Plugin & theme assets handled by the AssetFilter are no longer read via - ``include`` instead they are treated as plain text files. This fixes a number - of issues with JavaScript libraries like TinyMCE and environments with - short_tags enabled. -* Support for the ``Asset.filter`` configuration and hooks were removed. This - feature can easily be replaced with a plugin or dispatcher filter. - - -Network -======= - -Request -------- - -* ``CakeRequest`` has been renamed to :php:class:`Cake\\Network\\Request`. -* :php:meth:`Cake\\Network\\Request::port()` was added. -* :php:meth:`Cake\\Network\\Request::scheme()` was added. -* :php:meth:`Cake\\Network\\Request::cookie()` was added. -* :php:attr:`Cake\\Network\\Request::$trustProxy` was added. This makes it easier to put - CakePHP applications behind load balancers. -* :php:attr:`Cake\\Network\\Request::$data` is no longer merged with the prefixed data - key, as that prefix has been removed. -* :php:meth:`Cake\\Network\\Request::env()` was added. -* :php:meth:`Cake\\Network\\Request::acceptLanguage()` was changed from static method - to non-static. -* Request detector for "mobile" has been removed from the core. Instead the app - template adds detectors for "mobile" and "tablet" using ``MobileDetect`` lib. -* The method ``onlyAllow()`` has been renamed to ``allowMethod()`` and no longer accepts "var args". - All method names need to be passed as first argument, either as string or array of strings. - -Response --------- - -* The mapping of mimetype ``text/plain`` to extension ``csv`` has been removed. - As a consequence :php:class:`Cake\\Controller\\Component\\RequestHandlerComponent` - doesn't set extension to ``csv`` if ``Accept`` header contains mimetype ``text/plain`` - which was a common annoyance when receiving a jQuery XHR request. - -Sessions -======== - -The session class is no longer static, instead the session can be accessed -through the request object. See the :doc:`/development/sessions` documentation -for using the session object. - -* :php:class:`Cake\\Network\\Session` and related session classes have been - moved under the ``Cake\Network`` namespace. -* ``SessionHandlerInterface`` has been removed in favor of the one provided by - PHP itself. -* The property ``Session::$requestCountdown`` has been removed. -* The session checkAgent feature has been removed. It caused a number of bugs - when chrome frame, and flash player are involved. -* The conventional sessions database table name is now ``sessions`` instead of - ``cake_sessions``. -* The session cookie timeout is automatically updated in tandem with the timeout - in the session data. -* The path for session cookie now defaults to app's base path instead of "/". - Also new config variable ``Session.cookiePath`` has been added to easily - customize the cookie path. - -Network\\Http -============= - -* ``HttpSocket`` is now :php:class:`Cake\\Network\\Http\\Client`. -* Http\Client has been re-written from the ground up. It has a simpler/easier to - use API, support for new authentication systems like OAuth, and file uploads. - It uses PHP's stream APIs so there is no requirement for cURL. See the - :doc:`/core-utility-libraries/httpclient` documentation for more information. - -Network\\Email -============== - -* :php:meth:`Cake\\Network\\Email\\Email::config()` is now used to define - configuration profiles. This replaces the ``EmailConfig`` classes in previous - versions. -* :php:meth:`Cake\\Network\\Email\\Email::profile()` replaces ``config()`` as - the way to modify per instance configuration options. -* :php:meth:`Cake\\Network\\Email\\Email::drop()` has been added to allow the - removal of email configuration. -* :php:meth:`Cake\\Network\\Email\\Email::configTransport()` has been added to allow the - definition of transport configurations. This change removes transport options - from delivery profiles and allows you to easily re-use transports across email - profiles. -* :php:meth:`Cake\\Network\\Email\\Email::dropTransport()` has been added to allow the - removal of transport configuration. - - -Controller -========== - -Controller ----------- - -- The ``$helpers``, ``$components`` properties are now merged - with **all** parent classes not just ``AppController`` and the plugin - AppController. The properties are merged differently now as well. Instead of - all settings in all classes being merged together, the configuration defined - in the child class will be used. This means that if you have some - configuration defined in your AppController, and some configuration defined in - a subclass, only the configuration in the subclass will be used. -- ``Controller::httpCodes()`` has been removed, use - :php:meth:`Cake\\Network\\Response::httpCodes()` instead. -- ``Controller::disableCache()`` has been removed, use - :php:meth:`Cake\\Network\\Response::disableCache()` instead. -- ``Controller::flash()`` has been removed. This method was rarely used in real - applications and served no purpose anymore. -- ``Controller::validate()`` and ``Controller::validationErrors()`` have been - removed. They were left over methods from the 1.x days where the concerns of - models + controllers were far more intertwined. -- ``Controller::loadModel()`` now loads table objects. -- The ``Controller::$scaffold`` property has been removed. Dynamic scaffolding - has been removed from CakePHP core, and will be provided as a standalone - plugin. -- The ``Controller::$ext`` property has been removed. You now have to extend and - overide the ``View::$_ext`` property if you want to use a non-default view file - extension. -- The ``Controller::$Components`` property has been removed and replaced with - ``_components``. If you need to load components at runtime you should use - ``$this->loadComponent()`` on your controller. -- The signature of :php:meth:`Cake\\Controller\\Controller::redirect()` has been - changed to ``Controller::redirect(string|array $url, int $status = null)``. - The 3rd argument ``$exit`` has been dropped. The method can no longer send - response and exit script, instead it returns a ``Response`` instance with - approriate headers set. -- The ``base``, ``webroot``, ``here``, ``data``, ``action``, and ``params`` - magic properties have been removed. You should access all of these properties - on ``$this->request`` instead. - -Scaffold Removed ----------------- - -The dynamic scaffolding in CakePHP has been removed from CakePHP core. It was -infrequently used, and never intended for production use. It will be replaced by -a standalone plugin that people requiring that feature can use. - -ComponentCollection Replaced ----------------------------- - -This class has been renamed to :php:class:`Cake\\Controller\\ComponentRegistry`. -See the section on :doc:`/core-libraries/registry-objects` for more information -on the features provided by the new class. You can use the ``cake upgrade -rename_collections`` to assist in upgrading your code. - -Component ---------- - -* The ``_Collection`` property is now ``_registry``. It contains an instance - of :php:class:`Cake\\Controller\\ComponentRegistry` now. -* All components should now use the ``config()`` method to get/set - configuration. -* Default configuration for components should be defined in the - ``$_defaultConfig`` property. This property is automatically merged with any - configuration provided to the constructor. -* Configuration options are no longer set as public properties. - -Controller\\Components -====================== - -CookieComponent ---------------- - -- Uses :php:meth:`Cake\\Network\\Request::cookie()` to read cookie data, - this eases testing, and allows for ControllerTestCase to set cookies. -- Cookies encrypted in previous versions of CakePHP using the ``cipher`` method - are now un-readable because ``Security::cipher()`` has been removed. You will - need to re-encrypt cookies with the ``rijndael`` or ``aes`` method before upgrading. -- ``CookieComponent::type()`` has been removed and replaced with configuration - data accessed through ``config()``. -- ``write()`` no longer takes ``encryption`` or ``expires`` parameters. Both of - these are now managed through config data. See - :doc:`/core-libraries/components/cookie` for more information. -- The path for cookies now defaults to app's base path instead of "/". - - -AuthComponent -------------- - -- ``Default`` is now the default password hasher used by authentication classes. - It uses exclusively the bcrypt hashing algorithm. If you want to continue using - SHA1 hashing used in 2.x use ``'passwordHasher' => 'Weak'`` in your authenticator configuration. -- ``BaseAuthenticate::_password()`` has been removed. Use a ``PasswordHasher`` - class instead. -- A new ``FallbackPasswordHasher`` was added to help users migrate old passwords - from one algorithm to another. Check AuthComponent's documentation for more - info. -- ``BlowfishAuthenticate`` class has been removed. Just use ``FormAuthenticate`` -- ``BlowfishPasswordHasher`` class has been removed. Use - ``DefaultPasswordHasher`` instead. -- The ``loggedIn()`` method has been removed. Use ``user()`` instead. -- Configuration options are no longer set as public properties. -- The methods ``allow()`` and ``deny()`` no longer accept "var args". All method names need - to be passed as first argument, either as string or array of strings. -- The method ``login()`` has been removed and replaced by ``setUser()`` instead. - To login a user you now have to call ``identify()`` which returns user info upon - successful identification and then use ``setUser()`` to save the info to - session for persistence across requests. - -ACL related classes were moved to a separate plugin. Password hashers, Authentication and -Authorization providers where moved to the ``\Cake\Auth`` namespace. You are -required to move your providers and hashers to the ``App\Auth`` namespace as -well. - -RequestHandlerComponent ------------------------ - -- The following methods have been removed from RequestHandler component:: - ``isAjax()``, ``isFlash()``, ``isSSL()``, ``isPut()``, ``isPost()``, ``isGet()``, ``isDelete()``. - Use the :php:meth:`Cake\\Network\\Request::is()` method instead with relevant argument. -- ``RequestHandler::setContent()`` was removed, use :php:meth:`Cake\\Network\\Response::type()` instead. -- ``RequestHandler::getReferer()`` was removed, use :php:meth:`Cake\\Network\\Request::referer()` instead. -- ``RequestHandler::getClientIP()`` was removed, use :php:meth:`Cake\\Network\\Request::clientIp()` instead. -- ``RequestHandler::getAjaxVersion()`` was removed. -- ``RequestHandler::mapType()`` was removed, use :php:meth:`Cake\\Network\\Response::mapType()` instead. -- Configuration options are no longer set as public properties. - -SecurityComponent ------------------ - -- The following methods and their related properties have been removed from Security component: - ``requirePost()``, ``requireGet()``, ``requirePut()``, ``requireDelete()``. - Use the :php:meth:`Cake\\Network\\Request::allowMethod()` instead. -- ``SecurityComponent::$disabledFields()`` has been removed, use - ``SecurityComponent::$unlockedFields()``. -- The CSRF related features in SecurityComponent have been extracted and moved - into a separate CsrfComponent. This allows you more easily use CSRF protection - without having to use form tampering prevention. -- Configuration options are no longer set as public properties. -- The methods ``requireAuth()`` and ``requireSecure()`` no longer accept "var args". - All method names need to be passed as first argument, either as string or array of strings. - -SessionComponent ----------------- - -- ``SessionComponent::setFlash()`` is deprecated. You should use - :doc:`/core-libraries/components/flash` instead. - -Model -===== - -The Model layer in 2.x has been entirely re-written and replaced. You should -review the :doc:`/appendices/orm-migration` for information on how to use the -new ORM. - -- The ``Model`` class has been removed. -- The ``BehaviorCollection`` class has been removed. -- The ``DboSource`` class has been removed. -- The ``Datasource`` class has been removed. -- The various datasource classes have been removed. - -ConnectionManager ------------------ - -- ConnectionManager has been moved to the ``Cake\\Database`` namespace. -- ConnectionManager has had the following methods removed: - - - ``sourceList`` - - ``getSourceName`` - - ``loadDataSource`` - - ``enumConnectionObjects`` - -- :php:meth:`~Cake\\Database\\ConnectionManager::config()` has been added and is - now the only way to configure connections. -- :php:meth:`~Cake\\Database\\ConnectionManager::get()` has been added. It - replaces ``getDataSource()``. -- :php:meth:`~Cake\\Database\\ConnectionManager::configured()` has been added. It - and ``config()`` replace ``sourceList()`` & ``enumConnectionObjects()`` with - a more standard and consistent API. -- ``ConnectionManager::create()`` has been removed. - It can be replaced by ``config($name, $config)`` and ``get($name)``. - -TreeBehavior ------------- - -The TreeBheavior was completely re-written to use the new ORM. Although it works -the same as in 2.x, a few methods were renamed or removed:: - -- ``TreeBehavior::children()`` is now a custom finder ``find('children')``. -- ``TreeBehavior::generateTreeList()`` is now a custom finder ``find('treeList')``. -- ``TreeBehavior::getParentNode()`` was removed. -- ``TreeBehavior::getPath()`` is now a custom finder ``find('path')``. -- ``TreeBehavior::reorder()`` was removed. -- ``TreeBehavior::verify()`` was removed. - -TestSuite -========= - -TestCase --------- - -- ``_normalizePath()`` has been added to allow path comparison tests to run across all - operation systems regarding their DS settings (``\`` in Windows vs ``/`` in UNIX, for example). - -The following assertion methods have been removed as they have long been deprecated and replaced by -their new PHPUnit counterpart: - -- ``assertEqual()`` in favor of ``assertEquals()`` -- ``assertNotEqual()`` in favor of ``assertNotEquals()`` -- ``assertIdentical()`` in favor of ``assertSame()`` -- ``assertNotIdentical()`` in favor of ``assertNotSame()`` -- ``assertPattern()`` in favor of ``assertRegExp()`` -- ``assertNoPattern()`` in favor of ``assertNotRegExp()`` -- ``assertReference()`` if favor of ``assertSame()`` -- ``assertIsA()`` in favor of ``assertInstanceOf()`` - -Note that some methods have switched the argument order, e.g. ``assertEqual($is, $expected)`` should now be -``assertEquals($expected, $is)``. - -The following assertion methods have been deprecated and will be removed in the future: - -- ``assertWithinMargin()`` in favor of ``assertWithinRange()`` -- ``assertTags()`` in favor of ``assertHtml()`` - -Both method replacements also switched the argument order for a consistent assert method API -with ``$expected`` as first argument. - -View -==== - -Themes are now Basic Plugins ----------------------------- - -Having themes and plugins as ways to create modular application components has -proven to be limited, and confusing. In CakePHP 3.0, themes no longer reside -**inside** the application. Instead they are standalone plugins. This solves -a few problems with themes: - -- You could not put themes *in* plugins. -- Themes could not provide helpers, or custom view classes. - -Both these issues are solved by converting themes into plugins. - -View Folders Renamed --------------------- - -The folders containing view files now go under `src/Template` instead of `src/View`. -This was done to separate the view files from files containing php classes (eg. Helpers, View classes). - -The following View folders have been renamed to avoid naming collisions with controller names: - -- ``Layouts`` is now ``Layout`` -- ``Elements`` is now ``Element`` -- ``Scaffolds`` is now ``Scaffold`` -- ``Errors`` is now ``Error`` -- ``Emails`` is now ``Email`` (same for ``Email`` inside ``Layout``) - -HelperCollection Replaced -------------------------- - -This class has been renamed to :php:class:`Cake\\View\\HelperRegistry`. -See the section on :doc:`/core-libraries/registry-objects` for more information -on the features provided by the new class. You can use the ``cake upgrade -rename_collections`` to assist in upgrading your code. - -View Class ----------- - -- The ``plugin`` key has been removed from ``$options`` argument of :php:meth:`Cake\\View\\View::element()`. - Specify the element name as ``SomePlugin.element_name`` instead. -- ``View::getVar()`` has been removed, use :php:meth:`Cake\\View\\View::get()` instead. -- ``View::$ext`` has been removed and instead a protected property ``View::$_ext`` - has been added. -- ``View::addScript()`` has been removed. Use :ref:`view-blocks` instead. -- The ``base``, ``webroot``, ``here``, ``data``, ``action``, and ``params`` - magic properties have been removed. You should access all of these properties - on ``$this->request`` instead. -- ``View::start()`` no longer appends to an existing block. Instead it will - overwrite the block content when end is called. If you need to combine block - contents you should fetch the block content when calling start a second time, - or use the capturing mode of ``append()``. -- ``View::prepend()`` no longer has a capturing mode. -- ``View::startIfEmpty()`` has been removed. Now that start() always overwrites - startIfEmpty serves no purpose. -- The ``View::$Helpers`` property has been removed and replaced with - ``_helpers``. If you need to load helpers at runtime you should use - ``$this->addHelper()`` in your view files. - -ViewBlock ---------- - -- ``ViewBlock::append()`` has been removed, use :php:meth:`Cake\\View\ViewBlock::concat()` instead. However, - ``View::append()`` still exists. - -JsonView --------- - -- By default JSON data will have HTML entities encoded now. This prevents - possible XSS issues when JSON view content is embedded in HTML files. -- :php:class:`Cake\\View\\JsonView` now supports the ``_jsonOptions`` view - variable. This allows you to configure the bit-mask options used when generating - JSON. - - -View\\Helper -============ - -- The ``$settings`` property is now called ``$_config`` and should be accessed - through the ``config()`` method. -- Configuration options are no longer set as public properties. -- ``Helper::clean()`` was removed. It was never robust enough - to fully prevent xss. instead you should escape content with :php:func:`h` or - use a dedicated libray like htmlPurifier. -- ``Helper::output()`` was removed. This method was - deprecated in 2.x. -- Methods ``Helper::webroot()``, ``Helper::url()``, ``Helper::assetUrl()``, - ``Helper::assetTimestamp()`` have been moved to new :php:class:`Cake\\View\\Helper\\UrlHelper` - helper. ``Helper::url()`` is now available as :php:meth:`Cake\\View\\Helper\\UrlHelper::build()`. -- Magic accessors to deprecated properties have been removed. The following - properties now need to be accessed from the request object: - - - base - - here - - webroot - - data - - action - - params - - -Helper ------- - -Helper has had the following methods removed: - -* Helper::setEntity() -* Helper::entity() -* Helper::model() -* Helper::field() -* Helper::value() -* Helper::_name() -* Helper::_initInputField() -* Helper::_selectedArray() - -These methods were part used only by FormHelper, and part of the persistent -field features that have proven to be problematic over time. FormHelper no -longer relies on these methods and the complexity they provide is not necessary -anymore. - -The following methods have been removed: - -* Helper::_parseAttributes() -* Helper::_formatAttribute() - -These methods can now be found on the ``StringTemplate`` class that helpers -frequently use. See the ``StringTemplateTrait`` for an easy way to integrate -string templates into your own helpers. - -FormHelper ----------- - -FormHelper has been entirely rewritten for 3.0. It features a few large changes: - -* FormHelper works with the new ORM. But has an extensible system for - integrating with other ORMs or datasources. -* FormHelper features an extensible widget system that allows you to create new - custom input widgets and easily augment the built-in ones. -* String templates are the foundation of the helper. Instead of munging arrays - together everywhere, most of the HTML FormHelper generates can be customized - in one central place using template sets. - -In addition to these larger changes, some smaller breaking changes have been -made as well. These changes should help streamline the HTML FormHelper generates -and reduce the problems people had in the past: - -- The ``data[`` prefix was removed from all generated inputs. The prefix serves no real purpose anymore. -- The various standalone input methods like ``text()``, ``select()`` and others - no longer generate id attributes. -- The ``inputDefaults`` option has been removed from ``create()``. -- Options ``default`` and ``onsubmit`` of ``create()`` have been removed. Instead - one should use javascript event binding or set all required js code for ``onsubmit``. -- ``end()`` can no longer make buttons. You should create buttons with - ``button()`` or ``submit()``. -- ``FormHelper::tagIsInvalid()`` has been removed. Use ``isFieldError()`` - instead. -- ``FormHelper::inputDefaults()`` has been removed. You can use ``templates()`` - to define/augment the templates FormHelper uses. -- The ``wrap`` and ``class`` options have been removed from the ``error()`` - method. -- The ``showParents`` option has been removed from select(). -- The ``div``, ``before``, ``after``, ``between`` and ``errorMessage`` options - have been removed from ``input()``. You can use templates to update the - wrapping HTML. The ``templates`` option allows you to override the loaded - templates for one input. -- The ``separator``, ``between``, and ``legend`` options have been removed from - ``radio()``. You can use templates to change the wrapping HTML now. -- The ``format24Hours`` parameter has been removed from ``hour()``. - It has been replaced with the ``format`` option. -- The ``minYear``, and ``maxYear`` parameters have been removed from ``year()``. - Both of these parameters can now be provided as options. -- The ``dateFormat`` and ``timeFormat`` parameters have been removed from - ``datetime()``. You can use the template to define the order the inputs should - be displayed in. -- The ``submit()`` has had the ``div``, ``before`` and ``after`` options - removed. You can customize the ``submitContainer`` template to modify this - content. -- The ``inputs`` method no longer accepts ``legend`` and ``fieldset`` in the - ``$fields`` parameter, you must use the ``$options`` parameter. - It now also requires ``$fields`` parameter to be an array. The ``$blacklist`` - parameter has been removed, the functionality has been replaced by specifying - ``'field' => false`` in the ``$fields`` parameter. -- The ``inline`` parameter has been removed from postLink() method. - You should use the ``block`` option instead. Setting ``block => true`` will - emulate the previous behavior. -- The ``timeFormat`` parameter for ``hour()``, ``time()`` and ``dateTime()`` now - defaults to 24, complying with ISO 8601. -- The ``$confirmMessage`` argument of :php:meth:`Cake\\View\\Helper\\FormHelper::postLink()` - has been removed. You should now use key ``confirm`` in ``$options`` to specify - the message. -- Templates tags are now all camelBacked. Pre-3.0 tags ``formstart``, ``formend``, ``hiddenblock`` - and ``inputsubmit`` are now ``formStart``, ``formEnd``, ``hiddenBlock`` and ``inputSubmit``. - Make sure you change them if they are customized in your app. - -It is recommended that you review the :doc:`/core-libraries/helpers/form` -documentation for more details on how to use the FormHelper in 3.0. - -HtmlHelper ----------- - -- ``HtmlHelper::useTag()`` has been removed, use ``tag()`` instead. -- ``HtmlHelper::loadConfig()`` has been removed. Customizing the tags can now be - done using ``templates()`` or the ``templates`` setting. -- The second parameter ``$options`` for ``HtmlHelper::css()`` now always requires an array as documented. -- The first parameter ``$data`` for ``HtmlHelper::style()`` now always requires an array as documented. -- The ``inline`` parameter has been removed from meta(), css(), script(), scriptBlock() - methods. You should use the ``block`` option instead. Setting ``block => - true`` will emulate the previous behavior. -- ``HtmlHelper::meta()`` now requires ``$type`` to be a string. Additional options can - further on be passed as ``$options``. -- ``HtmlHelper::nestedList()`` now requires ``$options`` to be an array. The forth argument for the tag type - has been removed and included in the ``$options`` array. -- The ``$confirmMessage`` argument of :php:meth:`Cake\\View\\Helper\\HtmlHelper::link()` - has been removed. You should now use key ``confirm`` in ``$options`` to specify - the message. - -PaginatorHelper ---------------- - -- ``link()`` has been removed. It was no longer used by the helper internally. - It had low usage in user land code, and no longer fit the goals of the helper. -- ``next()`` no longer has 'class', or 'tag' options. It no longer has disabled - arguments. Instead templates are used. -- ``prev()`` no longer has 'class', or 'tag' options. It no longer has disabled - arguments. Instead templates are used. -- ``first()`` no longer has 'after', 'ellipsis', 'separator', 'class', or 'tag' options. -- ``last()`` no longer has 'after', 'ellipsis', 'separator', 'class', or 'tag' options. -- ``numbers()`` no longer has 'separator', 'tag', 'currentTag', 'currentClass', - 'class', 'tag', 'ellipsis' options. These options are now facilitated through - templates. It also requires the ``$options`` parameter to be an array now. -- The ``%page%`` style placeholders have been removed from :php:meth:`Cake\\View\\Helper\\PaginatorHelper::counter()`. - Use ``{{page}}`` style placeholders instead. -- ``url()`` has been renamed to ``generateUrl()`` to avoid method declaration clashes with ``Helper::url()``. - -By default all links and inactive texts are wrapped in ``
  • `` elements. This -helps make CSS easier to write, and improves compatibility with popular CSS -frameworks. - -Instead of the various options in each method, you should use the templates -feature. See the :ref:`paginator-templates` documentation for -information on how to use templates. - -TimeHelper ----------- - -- ``TimeHelper::__set()``, ``TimeHelper::__get()``, and ``TimeHelper::__isset()`` were - removed. These were magic methods for deprecated attributes. -- ``TimeHelper::serverOffset()`` has been removed. It promoted incorrect time math practices. -- ``TimeHelper::niceShort()`` has been removed. - -NumberHelper ------------- - -- :php:meth:`NumberHelper::format()` now requires ``$options`` to be an array. - -SessionHelper -------------- - -- ``SessionHelper::flash()`` is deprecated. You should use - :doc:`/core-libraries/helpers/flash` instead. - -JsHelper --------- - -- ``JsHelper`` and all associated engines have been removed. It could only - generate a very small subset of javascript code for selected library and - hence trying to generate all javascript code using just the helper often - became an impediment. It's now recommended to directly use javascript library - of your choice. - -CacheHelper Removed -------------------- - -CacheHelper has been removed. The caching functionality it provided was -non-standard, limited and incompatible with non-html layouts and data views. -These limitations meant a full rebuild would be necessary. Edge Side Includes -have become a standardized way to implement the functionality CacheHelper used -to provide. However, implementing `Edge Side Includes -`_ in PHP has a number of -limitations and edge cases. Instead of building a sub-par solution, we recommend -that developers needing full response caching use `Varnish -`_ or `Squid `_ instead. - -I18n -==== - -- :php:class:`Cake\\I18n\\I18n` 's constructor now takes a :php:class:`Cake\\Network\\Request` instance as an argument. - -- The methods below have been moved: - - - From ``Cake\I18n\Multibyte::utf8()`` to ``Cake\Utility\String::utf8()`` - - From ``Cake\I18n\Multibyte::ascii()`` to ``Cake\Utility\String::ascii()`` - - From ``Cake\I18n\Multibyte::checkMultibyte()`` to ``Cake\Utility\String::isMultibyte()`` - -- Since having the mbstring extension is now a requirement, the ``Multibyte`` class has been removed. -- Error messages throughout CakePHP are no longer passed through I18n - functions. This was done to simplify the internals of CakePHP and reduce - overhead. The developer facing messages are rarely, if ever, actually translated - - so the additional overhead reaps very little benefit. - -L10n -==== - -- :php:class:`Cake\\I18n\\L10n` 's constructor now takes a :php:class:`Cake\\Network\\Request` instance as argument. - - -Testing -======= - -- The ``TestShell`` has been removed. CakePHP, the application skeleton and - newly baked plugins all use ``phpunit`` to run tests. -- The webrunner (webroot/test.php) has been removed. CLI adoption has greatly - increased since the initial release of 2.x. Additionaly, CLI runners offer - superior integration with IDE's and other automated tooling. - - If you find yourself in need of a way to run tests from a browser you should - checkout `VisualPHPUnit `_. It - offers many additional features over the old webrunner. -- ``ControllerTestCase`` is deprecated and will be removed for CakePHP 3.0.0. - You should use the new :ref:`integration-testing` features instead. -- The fixtures should now be referenced by plural form:: - - // Instead of - $fixtures = ['app.article']; - - // You should use - $fixtures = ['app.articles']; - -Utility -======= - -Set Class Removed ------------------ - -The Set class has been removed, you should use the Hash class instead now. - -Inflector ---------- - -Transliterations for :php:meth:`Cake\\Utility\\Inflector::slug()` have changed. If -you use custom transliterations you will need to update your code. Instead of -regular expressions, transliterations use simple string replacement. This -yielded significant performance improvements:: - - // Instead of - Inflector::rules('transliteration', array( - '/ä|æ/' => 'ae', - '/å/' => 'aa' - )); - - // You should use - Inflector::rules('transliteration', [ - 'ä' => 'ae', - 'æ' => 'ae', - 'å' => 'aa' - ]); - - -Sanitize --------- - -- ``Sanitize`` class has been removed. - -Security --------- - -- ``Security::cipher()`` has been removed. It is insecure and promoted bad - cryptographic practices. You should use :php:meth:`Security::rijndael()` - instead. -- The Configure value ``Security.cipherSeed`` is no longer required. With the - removal of ``Security::cipher()`` it serves no use. -- Backwards compatibility in :php:meth:`Cake\\Utility\\Security::rijndael()` for values encrypted prior - to CakePHP 2.3.1 has been removed. You should re-encrypt values using a recent - version of CakePHP 2.x before migrating. -- The ability to generate blowfish hash been removed. You can no longer use type - "blowfish" for ``Security::hash()``. One should just use PHP's `password_hash()` - and `password_verify()` to generate and verify blowfish hashes. The compability - library `ircmaxell/password-compat `_. - which is installed along with CakePHP provides these functions for PHP < 5.5. - -Time ----- - -- ``CakeTime`` has been renamed to :php:class:`Cake\\Utility\\Time`. -- ``CakeTime::serverOffset()`` has been removed. It promoted incorrect time math practises. -- ``CakeTime::niceShort()`` has been removed. -- ``CakeTime::convert()`` has been removed. -- ``CakeTime::convertSpecifiers()`` has been removed. -- ``CakeTime::dayAsSql()`` has been removed. -- ``CakeTime::daysAsSql()`` has been removed. -- ``CakeTime::fromString()`` has been removed. -- ``CakeTime::gmt()`` has been removed. -- ``CakeTime::toATOM()`` has been renamed to ``toAtomString``. -- ``CakeTime::toRSS()`` has been renamed to ``toRssString``. -- ``CakeTime::toUnix()`` has been renamed to ``toUnixString``. -- ``CakeTime::wasYesterday()`` has been renamed to ``isYesterday`` to match the rest - of the method naming. -- ``CakeTime::format()`` Does not use ``sprintf`` format strings anymore, you can use - ``i18nFormat`` instead. -- :php:meth:`Time::timeAgoInWords()` now requires ``$options`` to be an array. - -Time is not a collection of static methods anymore, it extends ``DateTime`` to -inherit all its methods and adds location aware formatting functions with the -help of the ``intl`` extension. - -In general, expressions looking like this:: - - CakeTime::aMethod($date); - -Can be migrated by rewriting it to:: - - (new Time($date))->aMethod(); - -Number ------- - -The Number library was rewritten to internally use the ``NumberFormatter`` -class. - -- ``CakeNumber`` has been renamed to :php:class:`Cake\\I18n\\Number`. -- :php:meth:`Number::format()` now requires ``$options`` to be an array. -- :php:meth:`Number::addFormat()` was removed. -- ``Number::fromReadableSize()`` has been moved to :php:meth:`Cake\\Utility\\String::parseFileSize()`. - -Validation ----------- - -- The range for :php:meth:`Validation::range()` now is inclusive if ``$lower`` and - ``$upper`` are provided. -- ``Validation::ssn()`` has been removed. - -Xml ---- - -- :php:meth:`Xml::build()` now requires ``$options`` to be an array. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. \ No newline at end of file diff --git a/es/appendices/3-1-migration-guide.rst b/es/appendices/3-1-migration-guide.rst new file mode 100644 index 0000000000000000000000000000000000000000..27622b6de603bc4e0319135bea6a20b1e12196aa --- /dev/null +++ b/es/appendices/3-1-migration-guide.rst @@ -0,0 +1,12 @@ +3.1 Migration Guide +################### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón + **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. \ No newline at end of file diff --git a/es/appendices/cakephp-development-process.rst b/es/appendices/cakephp-development-process.rst index 57649e9d7eef288564cf95c3ff799339acea3960..770870ec5c97232aafa55b0f6a54f4315b3c281e 100644 --- a/es/appendices/cakephp-development-process.rst +++ b/es/appendices/cakephp-development-process.rst @@ -2,60 +2,14 @@ CakePHP Development Process ########################### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Here we attempt to explain the process we use when developing the -CakePHP framework. We rely heavily on community interaction through -tickets and IRC chat. IRC is the best place to find members of the -`development team `_ and discuss -ideas, the latest code, and make general comments. If something more -formal needs to be proposed or there is a problem with a release, the -ticket system is the best place to share your thoughts. - -We currently maintain 4 versions of CakePHP. - -- **stable** : Tagged releases intended for production where stability - is more important than features. Issues filed against these releases - will be fixed in the related branch, and be part of the next release. -- **maintenance branch** : Development branches become maintenance - branches once a stable release point has been reached. Maintenance - branches are where all bugfixes are committed before making their way - into a stable release. Maintenance branches have the same name as the - major version they are for example *1.2*. If you are using a stable - release and need fixes that haven't made their way into a stable - release check here. -- **development branches** : Development branches contain leading edge - fixes and features. They are named after the version number they are - for example *1.3*. Once development branches have reached a stable - release point they become maintenance branches, and no further new - features are introduced unless absolutely necessary. -- **feature branches** : Feature branches contain unfinished or - possibly unstable features and are recommended only for power users - interested in the most advanced feature set and willing to contribute - back to the community. Feature branches are named with the following - convention *version-feature*. An example would be *1.3-router* Which - would contain new features for the Router for 1.3. - -Hopefully this will help you understand what version is right for you. -Once you pick your version you may feel compelled to contribute a bug -report or make general comments on the code. - -- If you are using a stable version or maintenance branch, please submit - tickets or discuss with us on IRC. -- If you are using the development branch or feature branch, the first - place to go is IRC. If you have a comment and cannot reach us in IRC - after a day or two, please submit a ticket. - -If you find an issue, the best answer is to write a test. The best -advice we can offer in writing tests is to look at the ones included in -the core. - -As always, if you have any questions or comments, visit us at #cakephp -on irc.freenode.net. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: CakePHP Development Process - :keywords lang=en: maintenance branch,community interaction,community feature,necessary feature,stable release,ticket system,advanced feature,power users,feature set,chat irc,leading edge,router,new features,members,attempt,development branches,branch development + :title lang=es: CakePHP Development Process + :keywords lang=es: maintenance branch,community interaction,community feature,necessary feature,stable release,ticket system,advanced feature,power users,feature set,chat irc,leading edge,router,new features,members,attempt,development branches,branch development diff --git a/es/appendices/glossary.rst b/es/appendices/glossary.rst index 8991415f4c13b3e01d07758c8c1ffc2d77d21bcb..2483ec1d6c8715b6eeca85f4d9d5dab9f996459d 100644 --- a/es/appendices/glossary.rst +++ b/es/appendices/glossary.rst @@ -2,84 +2,14 @@ Glossary ######## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -.. glossary:: - - routing array - An array of attributes that are passed to :php:meth:`Router::url()`. - They typically look like:: - - ['controller' => 'Posts', 'action' => 'view', 5] - - HTML attributes - An array of key => values that are composed into HTML attributes. For example:: - - // Given - ['class' => 'my-class', 'target' => '_blank'] - - // Would generate - class="my-class" target="_blank" - - If an option can be minimized or accepts it's name as the value, then ``true`` - can be used:: - - // Given - ['checked' => true] - - // Would generate - checked="checked" - - plugin syntax - Plugin syntax refers to the dot separated class name indicating classes - are part of a plugin:: - - // The plugin is "DebugKit", and the class name is "Toolbar". - 'DebugKit.Toolbar' - - // The plugin is "AcmeCorp/Tools", and the class name is "Toolbar". - 'AcmeCorp/Tools.Toolbar' - - dot notation - Dot notation defines an array path, by separating nested levels with ``.`` - For example:: - - Cache.default.engine - - Would point to the following value:: - - [ - 'Cache' => [ - 'default' => [ - 'engine' => 'File' - ] - ] - ] - - CSRF - Cross Site Request Forgery. Prevents replay attacks, double - submissions and forged requests from other domains. - - CDN - Content Delivery Network. A 3rd party vendor you can pay to help - distribute your content to data centers around the world. This helps - put your static assets closer to geographically distributed users. - - routes.php - A file in ``config`` directory that contains routing configuration. - This file is included before each request is processed. - It should connect all the routes your application needs so - requests can be routed to the correct controller + action. - - DRY - Don't repeat yourself. Is a principle of software development aimed at - reducing repetition of information of all kinds. In CakePHP DRY is used - to allow you to code things once and re-use them across your - application. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Glossary - :keywords lang=en: html attributes,array class,array controller,glossary glossary,target blank,dot notation,routing configuration,forgery,replay,router,syntax,config,submissions + :title lang=es: Glossary + :keywords lang=es: html attributes,array class,array controller,glossary glossary,target blank,dot notation,routing configuration,forgery,replay,router,syntax,config,submissions diff --git a/es/appendices/orm-migration.rst b/es/appendices/orm-migration.rst index 6324f39f5861631966daed1097817bfb8be33c94..7fb530228b9c199520f01d1523581537c41f7cc0 100644 --- a/es/appendices/orm-migration.rst +++ b/es/appendices/orm-migration.rst @@ -2,555 +2,10 @@ New ORM Upgrade Guide ##################### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -CakePHP 3.0 features a new ORM that has been re-written from the ground up. -While the ORM used in 1.x and 2.x has served us well for a long time it had -a few issues that we wanted to fix. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -* Frankenstein - is it a record, or a table? Currently it's both. -* Inconsistent API - Model::read() for example. -* No query object - Queries are always defined as arrays, this has some - limitations and restrictions. For example it makes doing unions and - sub-queries much harder. -* Returns arrays. This is a common complaint about CakePHP, and has probably - reduced adoption at some levels. -* No record object - This makes attaching formatting methods - difficult/impossible. -* Containable - Should be part of the ORM, not a crazy hacky behaviour. -* Recursive - This should be better controlled as defining which associations - are included, not a level of recursiveness. -* DboSource - It is a beast, and Model relies on it more than datasource. That - separation could be cleaner and simpler. -* Validation - Should be separate, it's a giant crazy function right now. Making - it a reusable bit would make the framework more extensible. - -The ORM in CakePHP 3.0 solves these and many more problems. The new ORM -focuses on relational data stores right now. In the future and through plugins -we will add non relational stores like ElasticSearch and others. - -Design of the New ORM -===================== - -The new ORM solves several problems by having more specialized and focused -classes. In the past you would use ``Model`` and a Datasource for all -operations. Now the ORM is split into more layers: - -* ``Cake\Database\Connection`` - Provides a platform independent way to create - and use connections. This class provides a way to use transactions, - execute queries and access schema data. -* ``Cake\Database\Dialect`` - The classes in this namespace provide platform - specific SQL and transform queries to work around platform specific - limitations. -* ``Cake\Database\Type`` - Is the gateway class to CakePHP database type - conversion system. It is a pluggable framework for adding abstract column - types and providing mappings between database, PHP representations and PDO - bindings for each data type. For example datetime columns are represented as - ``DateTime`` instances in your code now. -* ``Cake\ORM\Table`` - The main entry point into the new ORM. Provides access - to a single table. Handles the definition of assocation, use of behaviors and - creation of entities and query objects. -* ``Cake\ORM\Behavior`` - The base class for behaviors, which act very similar - to behaviors in previous versions of CakePHP. -* ``Cake\ORM\Query`` - A fluent object based query builder that replaces - the deeply nested arrays used in previous versions of CakePHP. -* ``Cake\ORM\ResultSet`` - A collection of results that gives powerful tools - for manipulating data in aggregate. -* ``Cake\ORM\Entity`` - Represents a single row result. Makes accessing data - and serializing to various formats a snap. - -Now that you are more familiar with some of the classes you'll interact with -most frequently in the new ORM it is good to look at the three most important -classes. The ``Table``, ``Query`` and ``Entity`` classes do much of the heavy -lifting in the new ORM, and each serves a different purpose. - -Table Objects -------------- - -Table objects are the gateway into your data. They handle many of the tasks that -``Model`` did in previous releases. Table classes handle tasks like: - -- Creating queries. -- Providing finders. -- Validating and saving entities. -- Deleting entities. -- Defining & accessing associations. -- Triggering callback events. -- Interacting with behaviors. - -The documentation chapter on :doc:`/orm/table-objects` provides far more detail -on how to use table objects than this guide can. Generally when moving existing -model code over it will end up in a table object. Table objects don't contain -any platform dependent SQL. Instead they collaborate with entities and the query -builder to do their work. Table objects also interact with behaviors and other -interested parties through published events. - -Query Objects -------------- - -While these are not classes you will build yourself, your application code will -make extensive use of the :doc:`/orm/query-builder` which is central to the new -ORM. The query builder makes it easy to build simple or complex queries -including those that were previously very difficult in CakePHP like ``HAVING``, -``UNION`` and sub-queries. - -The various find() calls your application has currently will need to be updated -to use the new query builder. The Query object is responsible for containing the -data to make a query without executing the query itself. It collaborates with -the connection/dialect to generate platform specific SQL which is executed -creating a ``ResultSet`` as the output. - -Entity Objects --------------- - -In previous versions of CakePHP the ``Model`` class returned dumb arrays that -could not contain any logic or behavior. While the community made this -short-coming less painful with projects like CakeEntity, the array results were -often a short coming that caused many developers trouble. For CakePHP 3.0, the -ORM always returns object result sets unless you explicitly disable that -feature. The chapter on :doc:`/orm/entities` covers the various tasks you can -accomplish with entities. - -Entities are created in one of two ways. Either by loading data from the -database, or converting request data into entities. Once created, entities allow -you to manipulate the data they contain and persist their data by collaborating -with table objects. - -Key Differences -=============== - -The new ORM is a large departure from the existing ``Model`` layer, there are -many important differences that are important in understanding how the new ORM -operates and how to update your code. - -Inflection Rules Updated ------------------------- - -You may have noticed that table classes have a pluralized name. In addition to -tables having pluralized names, associations are also referred in the plural -form. This is in contrast to ``Model`` where class names and association aliases -were singular. There are a few reasons for this change: - -* Table classes represent **collections** of data, not single rows. -* Associations link tables together, describing the relations between many - things. - -While the conventions for table objects are to always use plural forms, your -entity association properties will be populated based on the association type. - -.. note:: - - BelongsTo and HasOne associations will use the singular form in entity - properties, while HasMany and BelongsToMany (HABTM) will use plural forms. - -The convention change for table objects is most apparent when building queries. -Instead of expressing queries like:: - - // Wrong - $query->where(['User.active' => 1]); - -You need to use the plural form:: - - // Correct - $query->where(['Users.active' => 1]); - -Find returns a Query Object ---------------------------- - -One important difference in the new ORM is that calling ``find`` on a table will -not return the results immediately, but will return a Query object; this serves -several purposes. - -It is possible to alter queries further, after calling ``find``:: - - $articles = TableRegistry::get('Articles'); - $query = $articles->find(); - $query->where(['author_id' => 1])->order(['title' => 'DESC']); - -It is possible to stack custom finders to append conditions, sorting, limit and -any other clause to the same query before it is executed:: - - $query = $articles->find('approved')->find('popular'); - $query->find('latest'); - -You can compose queries one into the other to create subqueries easier than -ever:: - - $query = $articles->find('approved'); - $favoritesQuery = $article->find('favorites', ['for' => $user]); - $query->where(['id' => $favoritesQuery->select(['id'])]); - -You can decorate queries with iterators and call methods without even touching -the database, this is great when you have parts of your view cached and having -the results taken from the database is not actually required:: - - // No queries made in this example! - $results = $articles->find() - ->order(['title' => 'DESC']) - ->extract('title'); - -Queries can be seen as the result object, trying to iterate the query, calling -``toArray`` or any method inherited from :ref:`collection`, -will result in the query being executed and results returned to you. - -The biggest difference you will find when coming from CakePHP 2.x is that -``find('first')`` does not exist anymore. There is a trivial replacement for it, -and it is the ``first`` method:: - - // Before - $article = $this->Article->find('first'); - - // Now - $article = $this->Articles->find()->first(); - - // Before - $article = $this->Article->find('first', [ - 'conditions' => ['author_id' => 1] - ]); - - // Now - $article = $this->Articles->find('all', [ - 'conditions' => ['author_id' => 1] - ])->first(); - -If you are a loading a single record by its primary key, it will be better to -just call ``get``:: - - $article = $this->Articles->get(10); - -Finder Method Changes ---------------------- - -Returning a query object from a find method has several advantages, but comes at -a cost for people migrating from 2.x. If you had some custom find methods in -your models, they will need some modifications. This is how you create custom -finder methods in 3.0:: - - class ArticlesTable - { - - public function findPopular(Query $query, array $options) - { - return $query->where(['times_viewed' > 1000]); - } - - public function findFavorites(Query $query, array $options) - { - $for = $options['for']; - return $query->matching('Users.Favorites', function ($q) use ($for) { - return $q->where(['Favorites.user_id' => $for]); - }); - } - } - -As you can see, they are pretty straightforward, they get a Query object instead -of an array and must return a Query object back. For 2.x users that implemented -afterFind logic in custom finders, you should check out the :ref:`map-reduce` -section, or use the features found on the :ref:`collection-objects`. If in your -models you used to rely on having an afterFind for all find operations you can -migrate this code in one of a few ways: - -1. Override your entity constructor method and do additional formatting there. -2. Create accessor methods in your entity to create the virtual properties. -3. Redefine ``findAll()`` and attach a map/reduce function. - -In the 3rd case above your code would look like:: - - public function findAll(Query $query, array $options) - { - $mapper = function ($row, $key, $mr) { - // Your afterFind logic - }; - return $query->mapReduce($mapper); - } - -You may have noticed that custom finders receive an options array, you can pass -any extra information to your finder using this parameter. This is great -news for people migrating from 2.x. Any of the query keys that were used in -previous versions will be converted automatically for you in 3.x to the correct -functions:: - - // This works in both CakePHP 2.x and 3.0 - $articles = $this->Articles->find('all', [ - 'fields' => ['id', 'title'], - 'conditions' => [ - 'OR' => ['title' => 'Cake', 'author_id' => 1], - 'published' => true - ], - 'contain' => ['Authors'], // The only change! (notice plural) - 'order' => ['title' => 'DESC'], - 'limit' => 10, - ]); - -Hopefully, migrating from older versions is not as daunting as it first seems, -much of the features we have added helps you remove code as you can better -express your requirements using the new ORM and at the same time the -compatibility wrappers will help you rewrite those tiny differences in a fast -and painless way. - -One of the other nice improvements in 3.x around finder methods is that -behaviors can implement finder methods with no fuss. By simply defining a method -with a matching name and signature on a Behavior the finder will automatically -be available on any tables the behavior is attached to. - -Recursive and ContainableBehavior Removed ------------------------------------------ - -In previous versions of CakePHP you needed to use ``recursive``, -``bindModel()``, ``unbindModel()`` and ``ContainableBehavior`` to reduce the -loaded data to the set of associations you were interested in. A common tactic -to manage associations was to set ``recursive`` to ``-1`` and use Containable to -manage all associations. In CakePHP 3.0 ContainableBehavior, recursive, -bindModel, and unbindModel have all been removed. Instead the ``contain()`` -method has been promoted to be a core feature of the query builder. Associations -are only loaded if they are explicitly turned on. For example:: - - $query = $this->Articles->find('all'); - -Will **only** load data from the ``articles`` table as no associations have been -included. To load articles and their related authors you would do:: - - $query = $this->Articles->find('all')->contain(['Authors']); - -By only loading associated data that has been specifically requested you spend -less time fighting the ORM trying to get only the data you want. - -No afterFind Event or Virtual Fields ------------------------------------- - -In previous versions of CakePHP you needed to make extensive use of the -``afterFind`` callback and virtual fields in order to create generated data -properties. These features have been removed in 3.0. Because of how ResultSets -iteratively generate entities, the ``afterFind`` callback was not possible. -Both afterFind and virtual fields can largely be replaced with virtual -properies on entities. For example if your User entity has both first and last -name columns you can add an accessor for `full_name` and generate the property -on the fly:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - - class User extends Entity - { - public function getFullName() - { - return $this->first_name . ' ' . $this->last_name; - } - } - -Once defined you can access your new property using ``$user->full_name``. -Using the :ref:`map-reduce` features of the ORM allow you to build aggregated -data from your results, which is another use case that the ``afterFind`` -callback was often used for. - -While virtual fields are no longer an explicit feature of the ORM, adding -calculated fields is easy to do in your finder methods. By using the query -builder and expression objects you can achieve the same results that virtual -fields gave:: - - namespace App\Model\Table; - - use Cake\ORM\Table; - use Cake\ORM\Query; - - class ReviewsTable extends Table - { - function findAverage(Query $query, array $options = []) { - $avg = $query->func()->avg('rating'); - $query->select(['average' => $avg]); - return $query; - } - } - -Associations No Longer Defined as Properties --------------------------------------------- - -In previous versions of CakePHP the various associations your models had were -defined in properties like ``$belongsTo`` and ``$hasMany``. In CakePHP 3.0, -associations are created with methods. Using methods allows us to sidestep the -many limitations class definitions have, and provide only one way to define -associations. Your ``initialize`` method and all other parts of your application -code, interact with the same API when manipulating associations:: - - namespace App\Model\Table; - - use Cake\ORM\Table; - use Cake\ORM\Query; - - class ReviewsTable extends Table - { - - public function initialize(array $config) - { - $this->belongsTo('Movies'); - $this->hasOne('Ratings'); - $this->hasMany('Comments') - $this->belongsToMany('Tags') - } - - } - -As you can see from the example above each of the association types uses -a method to create the association. One other difference is that -``hasAndBelongsToMany`` has been renamed to ``belongsToMany``. To find out more -about creating associations in 3.0 see the section on :ref:`table-associations`. - -Another welcome improvement to CakePHP is the ability to create your own -association classes. If you have association types that are not covered by the -built-in relation types you can create a custom ``Association`` sub-class and -define the association logic you need. - -Validation No Longer Defined as a Property ------------------------------------------- - -Like associations, validation rules were defined as a class property in previous -versions of CakePHP. This array would then be lazily transformed into -a ``ModelValidator`` object. This transformation step added a layer of -indirection, complicating rule changes at runtime. Futhermore, validation rules -being defined as a property made it difficult for a model to have multiple sets -of validation rules. In CakePHP 3.0, both these problems have been remedied. -Validation rules are always built with a ``Validator`` object, and it is trivial to -have multiple sets of rules:: - - namespace App\Model\Table; - - use Cake\ORM\Table; - use Cake\ORM\Query; - - class ReviewsTable extends Table - { - - public function validationDefault($validator) - { - $validator->validatePresence('body') - ->add('body', 'length', [ - 'rule' => ['minLength', 20], - 'message' => 'Reviews must be 20 characters or more', - ]) - ->add('user_id', 'exists', [ - 'rule' => function ($value, $context) { - $q = $this->association('Users') - ->find() - ->where(['id' => $value]); - return $q->count() === 1; - }, - 'message' => 'A valid user is required.' - ]); - return $validator; - } - - } - -You can define as many validation methods as you need. Each method should be -prefixed with ``validation`` and accept a ``$validator`` argument. You can then -use your validators when saving using the ``validate`` option. See the -documentation on :ref:`saving-entities` for more information. - -Identifier Quoting Disabled by Default --------------------------------------- - -In the past CakePHP has always quoted identifiers. Parsing SQL snippets and -attempting to quote identifiers was both error prone and expensive. If you are -following the conventions CakePHP sets out, the cost of identifier quoting far -outweighs any benefit it provides. Because of this identifier quoting has been -disabled by default in 3.0. You should only need to enable identifier quoting if -you are using column names or table names that contain special characters or are -reserved words. If required, you can enable identifier quoting when configuring -a connection:: - - // In config/app.php - 'Datasources' => [ - 'default' => [ - 'className' => 'Cake\Database\Driver\Mysql', - 'username' => 'root', - 'password' => 'super_secret', - 'host' => 'localhost', - 'database' => 'cakephp', - 'quoteIdentifiers' => true - ] - ], - -.. note:: - - Identifiers in ``QueryExpression`` objects will not be quoted, and you will - need to quote them manually or use IdentifierExpression objects. - -Updating Behaviors -================== - -Like most ORM related features, behaviors have changed in 3.0 as well. They now -attach to ``Table`` instances which are the conceptual descendent of the -``Model`` class in previous versions of CakePHP. There are a few key -differences from behaviors in CakePHP 2.x: - -- Behaviors are no longer shared across multiple tables. This means you no - longer have to 'namespace' settings stored in a behavior. Each table using - a behavior will get its own instance. -- The method signatures for mixin methods have changed. -- The method signatures for callback methods have changed. -- The base class for behaviors have changed. -- Behaviors can easily add finder methods. - -New Base Class --------------- - -The base class for behaviors has changed. Behaviors should now extend -``Cake\ORM\Behavior``; if a behavior does not extend this class an exception -will be raised. In addition to the base class changing, the constructor for -behaviors has been modified, and the ``startup`` method has been removed. -Behaviors that need access to the table they are attached to should define -a constructor:: - - namespace App\Model\Behavior; - - use Cake\ORM\Behavior; - - class SluggableBehavior extends Behavior - { - - protected $_table; - - public function __construct(Table $table, array $config) - { - parent::__construct($table, $config); - $this->_table = $table; - } - - } - -Mixin Methods Signature Changes -------------------------------- - -Behaviors continue to offer the ability to add 'mixin' methods to Table objects, -however the method signature for these methods has changed. In CakePHP 3.0, -behavior mixin methods can expect the **same** arguments provided to the table -'method'. For example:: - - // Assume table has a slug() method provided by a behavior. - $table->slug($someValue); - -The behavior providing the ``slug`` method will receive only 1 argument, and its -method signature should look like:: - - public function slug($value) - { - // Code here. - } - -Callback Method Signature Changes ---------------------------------- - -Behavior callbacks have been unified with all other listener methods. Instead of -their previous arguments, they need to expect an event object as their first -argument:: - - public function beforeFind(Event $event, Query $query, array $options) - { - // Code. - } - -See :ref:`table-callbacks` for the signatures of all the callbacks a behavior -can subscribe to. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/bake.rst b/es/bake.rst new file mode 100644 index 0000000000000000000000000000000000000000..218b958f14a0259d650aa6d2d28292845e18b0d3 --- /dev/null +++ b/es/bake.rst @@ -0,0 +1,21 @@ +Bake Console +############ + +.. toctree:: + :maxdepth: 1 + + bake/usage + bake/development + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Bake Console + :keywords lang=es: command line interface,development,bake view, bake template syntax,erb tags,asp tags,percent tags diff --git a/es/bake/development.rst b/es/bake/development.rst new file mode 100644 index 0000000000000000000000000000000000000000..cf40187e0c464606371cddfdb7fabbab8ad192a8 --- /dev/null +++ b/es/bake/development.rst @@ -0,0 +1,15 @@ +Extending Bake +############## + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Extending Bake + :keywords lang=es: command line interface,development,bake view, bake template syntax,erb tags,asp tags,percent tags diff --git a/es/bake/usage.rst b/es/bake/usage.rst new file mode 100644 index 0000000000000000000000000000000000000000..9d90f63c3080796d525868fe155b519476575e03 --- /dev/null +++ b/es/bake/usage.rst @@ -0,0 +1,15 @@ +Code Generation with Bake +######################### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Code Generation with Bake + :keywords lang=es: command line interface,functional application,database,database configuration,bash script,basic ingredients,project,model,path path,code generation,scaffolding,windows users,configuration file,few minutes,config,iew,shell,models,running,mysql diff --git a/es/cakephp-overview.rst b/es/cakephp-overview.rst deleted file mode 100644 index 3306dd1d209d370d833334c7f31b64cfadaff960..0000000000000000000000000000000000000000 --- a/es/cakephp-overview.rst +++ /dev/null @@ -1,18 +0,0 @@ -Introducción a CakePHP -###################### - -Bienvenido al Cookbook, el manual web del framework CakePHP -hace que el desarrollo de aplicaciones sea pan comido. - -Este manual asume que tienes una comprensión general de PHP -y un conocimiento básico de programación orientada a objetos (POO). -Las diferentes funcionalidades que este framework posee hace uso de -teconolgías como SQL, JavaScript y XML y este manual no trata de -explicarlas, sino sólo la forma en que se utilizados en su contexto. - -.. toctree:: - :maxdepth: 1 - - cakephp-overview/what-is-cakephp-why-use-it - cakephp-overview/understanding-model-view-controller - cakephp-overview/where-to-get-help diff --git a/es/cakephp-overview/understanding-model-view-controller.rst b/es/cakephp-overview/understanding-model-view-controller.rst deleted file mode 100644 index 28ff95577fe5b91515ac241883bf895bbf98bf58..0000000000000000000000000000000000000000 --- a/es/cakephp-overview/understanding-model-view-controller.rst +++ /dev/null @@ -1,106 +0,0 @@ -Entendiendo el Modelo - Vista - Controlador -########################################### - -CakePHP sigue el patrón diseño de software llamado -`MVC `_. -Programar usando MVC separa tu aplicación en tres partes principalmente: - -La capa del Modelo -================== - -El modelo representa la parte de la aplicación que -implementa la lógica de negocio. Ésto significa que es responsable -de la recuperación de datos convirtiéndolos en conceptos significativos para la -aplicación, así como su procesamiento, validación, asociación y cualquier -otra tarea relativa a la manipulación de dichos datos. - -A primera vista los objetos del modelo puede ser considerados como la primera capa -de la interacción con cualquier base de datos que podría estar utilizando tu aplicación. -Pero en general representan los principales conceptos en torno a los cuales se -desea implementar un programa. - -En el caso de una red social, la capa de modelo se haría cargo de -tareas tales como guardar datos del usuario, el amacenamiento de asociaciones -con amigos, el almacenamiento y la recuperación de fotos de los usuarios, -encontrar sugerencias de nuevos amigos, etc. Mientras que los objetos del modelo -pueden ser considerados como "Amigo", "Usuario", "Comentario" y "Foto". - -La capa de la Vista -=================== - -La vista hace una presentación de los datos del modelo estando separada de -los objetos del modelo. Es responsable del uso de la información de la cual dispone -para producir cualquier interfaz de presentación de cualquier petición que se presente. - -Por ejemplo, como la capa de modelo devuelve un conjunto de datos, la vista los usaría -para hacer una página HTML que los contenga. O un resultado con formato XML para que otras -aplicaciones puedan consumir. - -La capa de la Vista no se limita únicamente a HTML o texto que represente los datos, -sino que puede ser utilizada para ofrecer una amplia variedad de formatos en función -de sus necesidades tales como videos, música, documentos y cualquier otro formato -que puedas imaginar. - -La capa del Controlador -======================= - -La capa del controlador gestiona las peticiones de los usuarios. Es responsable -de responder la información solicitada con la ayuda tanto del modelo como de -la vista. - -Los controladores pueden ser vistos como administradores cuidando de que todos -los recursos necesarios para completar una tarea se deleguen a los trabajadores -más adecuados. Espera peticiones de los clientes, comprueba su validez de acuerdo -a las normas de autenticación o autorización, delega la búsqueda de datos al modelo -y selecciona el tipo de respuesta más adecuado según las preferencias del cliente. -Finalmente delega este proceso de presentación a la capa de la Vista. - -El ciclo de una petición en CakePHP -=================================== - -|Figure 1| -Figure: 1: Una petición MVC típica - -Figure: 1 muestra el manejo de una petición típica a una aplicación CakePHP. - -El ciclo de una petición típica en CakePHP comienza cuando un usuario solicita -una página o un recurso de tu aplicación. Esta solicitud es procesada por un -despachador que selecciona el controlador correcto para manejarlo. - -Una vez que la solicitud llega al controlador, éste se comunicará con la capa del Modelo -para cualquier proceso de captación de datos o el guardado de los mismos según se requiera. -Una vez finalizada esta comunicación el controlador procederá a delegar en el -objeto de vista correcto la tarea de generar una presentación resultante de los datos -proporcionada por el modelo. - -Finalmente, cuando esta presentación se genera, se envía de inmediato al usuario. - -Casi todas las solicitudes para la aplicación van a seguir este patrón básico. -Vamos a añadir algunos detalles más adelante que son específicos a -CakePHP, así que mantén esto en mente a medida que avancemos. - -Beneficios -========== - -¿Por qué utilizar MVC? Debido a que es un patrón de diseño de software -verdaderamente probado que convierte una aplicación en un paquete modular -fácil de mantener y mejora la rapidez del desarrollo. La separación de las tareas -de tu aplicación en modelos, vistas y controladores hace que su aplicación sea -además muy ligeras de entender. Las nuevas características se añaden fácilmente -y agregar cosas nuevas a código viejo se hace muy sencillo. El diseño modular -también permite a los desarrolladores y los diseñadores trabajar simultáneamente, -incluyendo la capacidad de hacer -`prototipos rápidos `_. - -La separación también permite a los desarrolladores hacer cambios en una parte del -la aplicación sin afectar a los demás. - -Si nunca has creado una aplicación de esta forma se necesita algún tiempo -para acostumbrarse, pero estamos seguros que una vez que hayas terminado tu -primera aplicación con CakePHP no vas a querer hacerlo de cualquier otra -manera. - -Para iniciarte con tu primera aplicación en CakePHP -:doc:`haz este tutorial ahora ` - -.. |Figure 1| image:: /_static/img/basic_mvc.png diff --git a/es/cakephp-overview/what-is-cakephp-why-use-it.rst b/es/cakephp-overview/what-is-cakephp-why-use-it.rst deleted file mode 100644 index c59c117ef58807b7523ec8420667c046f64f5fa0..0000000000000000000000000000000000000000 --- a/es/cakephp-overview/what-is-cakephp-why-use-it.rst +++ /dev/null @@ -1,50 +0,0 @@ -¿Qué es CakePHP? y ¿Por qué usarlo? -################################### - -`CakePHP `_ es un -`famework `_ -`libre `_, -`de código abierto `_, para el -`desarrollo rápido de aplicaciones `_ -para `PHP `_. Es una estructura fundamental para la -ayudar a los programadores a crear aplicaciones web. Nuestro objetivo principal es -permitirte trabajar de forma estructurada y rápida y sin pérdida de -flexibilidad. - -CakePHP extrae la monotonía del desarrollo web. Pone a tu disposición todas -las herramientas que necesita para empezar a programar lo que realmente hay que -hacer: la lógica específica de tu aplicación. En lugar de reinventar la rueda -cada vez que te sientas a hacer un nuevo proyecto, obten una copia de CakePHP y -empieza con el verdadero corazón de tu aplicación. - -CakePHP tiene un -`equido de desarollo activo `_ -y una comunidad muy viva, lo que le da un gran valor al proyecto. Además de -no tener que reinventar la rueda, usar CakePHP significa que el -núcleo de la aplicación estará bien probado y está siendo constantemente -mejorado. - -He aquí una lista rápida de las características que disfrutarás al utilizar -CakePHP: - -- :ref:`cakephp-official-communities` activa y amigable. -- `Licencia flexible `_ -- Compatible con las versiones de PHP 5.4.16 y superiores. -- Contiene - `CRUD `_ para la - interacción de la base de datos. -- Generación automática de código. -- `Arquitectura MVC `_ -- Despachador de solicitudes (``request dispatcher``) con URLs y rutas limpias y - personalizadas. -- Función de `Validación `_. -- `Plantillas `_ rápidas y - flexibles. Sintaxis PHP con ayudantes (``helpers``). -- Ayudantes de vistas (``View helpers``) para AJAX, JavaScript, - formularios HTML y más. -- Componentes de Email, Cookie, Seguridad, Sesión y otros. -- `ACL `_ flexible. -- Sanitización de Datos. -- `Caché `_ flexible. -- Localización e Internacionalización. -- Funciona desde cualquier directorio de sitios web, con poca o ninguna configuración adicional. diff --git a/es/cakephp-overview/where-to-get-help.rst b/es/cakephp-overview/where-to-get-help.rst deleted file mode 100644 index 2bc7b55e6e59f3f425b7e3a3ffb427f37e7532aa..0000000000000000000000000000000000000000 --- a/es/cakephp-overview/where-to-get-help.rst +++ /dev/null @@ -1,96 +0,0 @@ -Dónde encontrar ayuda -##################### - -EL sitio oficial de CakePHP -=========================== - -`http://www.cakephp.org `_ - -EL sitio oficial de CakePHP siempre es un buen lugar para visitar. -Contiene enlaces a herramientas comunmente usadas, videos, oportunidades -para donar al proyecto y descargas útiles. - -El manual -========= - -`http://book.cakephp.org `_ - -Este manual debe ser probablemente el primer lugar al que acudir para obtener -respuestas. Al igual que con muchos otros proyectos de código abierto, tenemos gente nueva -con regularidad. Haz tu mejor esfuerzo para responder tus propias preguntas por -cuenta propia en primer lugar, esto te ayudará a entender los conceptos más -rápidamente y a nosotros a mejorar la documentación. - -The Bakery -========== - -`http://bakery.cakephp.org `_ - -`The Bakery` Es el sitio oficial para publicar todo lo relacionado a CakePHP, -desde tutoriales, nuevos plugins, actualizaciones a CakePHP hasta casos de -estudio de usuarios del framework. - -El API -====== - -`http://api20.cakephp.org/ `_ - -Directo al grano y directamente de los desarrolladores principales, el -API (Application Programming Interface) de CakePHP es el más -una amplia documentación en torno a todos los detalles del funcionamiento interno -del framework. Si quieres los detalles de cada función, los parámetros, y ver -cómo las clases se complementan entre sí, este es el lugar para buscar. - - -Las pruebas unitarias -===================== - -Si alguna vez sientes la información proporcionada en la API no es -suficiente, echa un vistazo al código de las pruebas unitarias de -CakePHP. Pueden servir como ejemplos prácticos para la utilización y -los datos parametros de cada clase. :: - - lib/Cake/Test/Case - -El canal IRC -============ - -**Canales IRC oficiales en irc.freenode.net:** - - -- `#cakephp `_ -- Discusión general en Inglés -- `#cakephp-es `_ -- Discusión general en Español - -Si no tienes ni idea, nos peagas un grito en el canal de IRC de CakePHP. -Alguien del equipo de desarrollo está alli generalmente, sobre todo -durante las horas del día de los usuarios del norte y América del Sur. Nos -encantaría saber de ti, si necesitas ayuda, quieres encontrar -los usuarios en tu área, o si deseas donarnos un nuevo coche. - -Los grupos de Google -==================== - -En Español: -`http://groups.google.com/group/cakephp-esp `_ - -En Inglés: -`http://groups.google.com/group/cake-php `_ - -CakePHP tiene también un Grupo de Google muy activo. Puede ser un gran -recurso para encontrar las respuestas archivadas, preguntas frecuentes, -y obtener respuestas a los problemas inmediatos. - -Stackoverflow (en inglés) -========================= - -`http://stackoverflow.com/ `_ - -Etiqueta tus preguntas con ``cakephp`` y la versión específica que utilizas -para permitir a usuarios existentes de stackoverflow encontrar tus preguntas. - -Where to get Help in your Language -================================== - -French ------- -- `French CakePHP Community `_ diff --git a/es/console-and-shells.rst b/es/console-and-shells.rst index e290aad345b9b263b7692844a9b5280ae1bbe52f..ca6457cafd81b5e5f81e119c9eae502c1813a3b7 100644 --- a/es/console-and-shells.rst +++ b/es/console-and-shells.rst @@ -1,911 +1,16 @@ Console & Shells ################ -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - .. php:namespace:: Cake\Console -CakePHP features not only a web framework but also a console framework -for creating console applications. Console applications are ideal for handling -a variety of background tasks such as maintenance, and completing work outside -of the request-response cycle. CakePHP console applications allow you -to reuse your application classes from the command line. - -CakePHP comes with a number of console applications out of the box. Some of -these applications are used in concert with other CakePHP features (like i18n), -and others are for general use to get you working faster. - -The CakePHP Console -=================== - -This section provides an introduction into CakePHP at the -command-line. Console tools are ideal for use in cron jobs, or command line -based utilities that don't need to be accessible from a web browser. - -PHP provides a CLI client that makes interfacing with your -file system and applications much smoother. The CakePHP console -provides a framework for creating shell scripts. The console uses a -dispatcher-type setup to load a shell or task, and hand it its -parameters. - -.. note:: - - A command-line (CLI) build of PHP must be available on the system - if you plan to use the Console. - -Before we get into specifics, let's make sure you can run the CakePHP console. -First, you'll need to bring up a system shell. The examples shown in this -section will be in bash, but the CakePHP Console is Windows-compatible as well. -This example assumes that the user is currently logged into a bash prompt and is -currently at the root of a CakePHP application. - -CakePHP applications contain a ``Console`` directory that contains all the -shells and tasks for an application. It also comes with an executable:: - - $ cd /path/to/app - $ bin/cake - -Running the Console with no arguments produces this help message:: - - Welcome to CakePHP v3.0.0 Console - --------------------------------------------------------------- - App : App - Path: /Users/markstory/Sites/cakephp-app/src/ - --------------------------------------------------------------- - Current Paths: - - -app: src - -root: /Users/markstory/Sites/cakephp-app - -core: /Users/markstory/Sites/cakephp-app/vendor/cakephp/cakephp - - Changing Paths: - - Your working path should be the same as your application path. To change your path use the '-app' param. - Example: -app relative/path/to/myapp or -app /absolute/path/to/myapp - - Available Shells: - - [CORE] bake, i18n, server, test - - [app] behavior_time, console, orm - - To run an app or core command, type cake shell_name [args] - To run a plugin command, type cake Plugin.shell_name [args] - To get help on a specific command, type cake shell_name --help - -The first information printed relates to paths. This is helpful if you're -running the console from different parts of the filesystem. - -.. php:class:: Shell - -Creating a Shell -================ - -Let's create a shell for use in the Console. For this example, -we'll create a simple Hello world shell. In your applications -``Console/Command`` directory create ``HelloShell.php``. Put the following -code inside it:: - - namespace App\Console\Command; - - use App\Console\Command\AppShell; - - class HelloShell extends AppShell - { - public function main() - { - $this->out('Hello world.'); - } - } - -The conventions for shell classes are that the class name should match -the file name, with the suffix of Shell. In our shell we created a ``main()`` method. -This method is called when a shell is called with no additional commands. We'll add -some more commands in a bit, but for now let's just run our shell. From your application -directory, run:: - - bin/cake hello - -You should see the following output:: - - Welcome to CakePHP Console - --------------------------------------------------------------- - App : app - Path: /Users/markstory/Sites/cake_dev/src/ - --------------------------------------------------------------- - Hello world. - -As mentioned before, the ``main()`` method in shells is a special method called -whenever there are no other commands or arguments given to a shell. You may have -also noticed that HelloShell is extending ``AppShell``. Much like -:ref:`app-controller`, AppShell gives you a base class to contain all your -common functions or logic. You can define an AppShell, by creating -``src/Console/Command/AppShell.php``. Since our main method wasn't very -interesting let's add another command that does something:: - - namespace App\Console\Command; - - use App\Console\Command\AppShell; - - class HelloShell extends AppShell - { - public function main() - { - $this->out('Hello world.'); - } - - public function heyThere($name = 'Anonymous') - { - $this->out('Hey there ' . $name); - } - } - -After saving this file, you should be able to run ``bin/cake hello hey_there -your-name`` and see your name printed out. Any public method not prefixed by an -``_`` is allowed to be called from the command line. As you can see, methods -invoked from the comand line are transformed from the underscored shell argument to -the correct camel-cased method name in the class. - -In our ``heyThere()`` method we can see that positional arguments are provided to our -``heyThere()`` function. Positional arguments are also available in the ``args`` property. -You can access switches or options on shell applications, which are available at -``$this->params``, but we'll cover that in a bit. - -When using a ``main()`` method you won't be able to use the positional -arguments. This is because the first positional argument or option is -interpreted as the command name. If you want to use arguments, you -should use method names other than ``main``. - -Using Models in Your Shells ---------------------------- - -You'll often need access to your application's business logic in shell -utilities; CakePHP makes that super easy. You can load models in shells, just as -you would in a controller using ``loadModel()``. The loaded models are set as -properties attached to your shell:: - - namespace App\Console\Command; - - use App\Console\Command\AppShell; - - class UserShell extends AppShell - { - - public function initialize() - { - parent::initialize(); - $this->loadModel('Users'); - } - - public function show() - { - if (empty($this->args[0])) { - return $this->error('Please enter a username.'); - } - $user = $this->Users->findByUsername($this->args[0]); - $this->out(print_r($user, true)); - } - } - -The above shell, will fetch a user by username and display the information -stored in the database. - -Shell Tasks -=========== - -There will be times when building more advanced console applications, you'll want -to compose functionality into re-usable classes that can be shared across many shells. -Tasks allow you to extract commands into classes. For example the ``bake`` is made -almost entirely of tasks. You define a tasks for a shell using the ``$tasks`` property:: - - class UserShell extends AppShell - { - public $tasks = ['Template']; - } - -You can use tasks from plugins using the standard :term:`plugin syntax`. -Tasks are stored in ``Console/Command/Task/`` in files named after -their classes. So if we were to create a new 'FileGenerator' task, you would create -``src/Console/Command/Task/FileGeneratorTask.php``. - -Each task must at least implement an ``main()`` method. The ShellDispatcher, -will call this method when the task is invoked. A task class looks like:: - - class FileGeneratorTask extends Shell - { - public function main() - { - - } - } - -A shell can also access it's tasks as properties, which makes tasks great for -making re-usable chunks of functionality similar to :doc:`/controllers/components`:: - - // Found in src/Console/Command/SeaShell.php - class SeaShell extends AppShell - { - // Found in src/Console/Command/Task/SoundTask.php - public $tasks = ['Sound']; - - public function main() - { - $this->Sound->main(); - } - } - -You can also access tasks directly from the command line:: - - $ cake sea sound - -.. note:: - - In order to access tasks directly from the command line, the task - **must** be included in the shell class' $tasks property. - Therefore, be warned that a method called "sound" in the SeaShell - class would override the ability to access the functionality in the - Sound task specified in the $tasks array. - -Loading Tasks On The Fly with TaskRegistry ------------------------------------------- - -You can load tasks on the fly using the Task registry object. You can load tasks that -were not declared in $tasks this way:: - - $project = $this->Tasks->load('Project'); - -Would load and return a ProjectTask instance. You can load tasks from plugins using:: - - $progressBar = $this->Tasks->load('ProgressBar.ProgressBar'); - -.. _invoking-other-shells-from-your-shell: - -Invoking Other Shells from Your Shell -===================================== - -.. php:method:: dispatchShell($args) - -There are still many cases where you will want to invoke one shell from another though. -``Shell::dispatchShell()`` gives you the ability to call other shells by providing the -``argv`` for the sub shell. You can provide arguments and options either -as var args or as a string:: - - // As a string - $this->dispatchShell('schema create Blog --plugin Blog'); - - // As an array - $this->dispatchShell('schema', 'create', 'Blog', '--plugin', 'Blog'); - -The above shows how you can call the schema shell to create the schema for a plugin -from inside your plugin's shell. - -Getting User Input -================== - -.. php:method:: in($question, $choices = null, $defaut = null) - -When building interactive console applications you'll need to get user input. -CakePHP provides an easy way to do this:: - - // Get arbitrary text from the user. - $color = $this->in('What color do you like?'); - - // Get a choice from the user. - $selection = $this->in('Red or Green?', ['R', 'G'], 'R'); - -Selection validation is case-insensitive. - -Creating Files -============== - -.. php:method:: createFile($path, $contents) - -Many Shell applications help automate development or deployment tasks. Creating -files is often important in these use cases. CakePHP provides an easy way to -create a file at a given path:: - - $this->createFile('bower.json', $stuff); - -If the Shell is interactive, a warning will be generated, and the user asked if -they want to overwrite the file if it already exists. If the shell's -interactive property is false, no question will be asked and the file will -simply be overwritten. - -Console Output -============== - -.. php:method:out($message, $newlines, $level) -.. php:method:err($message, $newlines) - -The ``Shell`` class provides a few methods for outputting content:: - - // Write to stdout - $this->out('normal message'); - - // Write to stderr - $this->err('error message'); - - // Write to stderr and stop the process - $this->error('Fatal error'); - -Shell also includes methods for clearing output, creating blank lines, or -drawing a line of dashes:: - - // Output 2 newlines - $this->out($this->nl(2)); - - // Clear the user's screen - $this->clear(); - - // Draw a horizontal line - $this->hr(); - -Lastly, you can update the current line of text on the screen using -``_io->overwrite()``:: - - $this->out('Counting down'); - $this->out('10', 0); - for ($i = 9; $i > 0; $i--) { - sleep(1); - $this->_io->overwrite($i, 0, 2); - } - -It is important to remember, that you cannot overwrite text -once a new line has been output. - -.. _shell-output-level: - -Console Output Levels ---------------------- - -Shells often need different levels of verbosity. When running as cron jobs, -most output is un-necessary. And there are times when you are not interested in -everything that a shell has to say. You can use output levels to flag output -appropriately. The user of the shell, can then decide what level of detail -they are interested in by setting the correct flag when calling the shell. -:php:meth:`Cake\\Console\\Shell::out()` supports 3 types of output by default. - -* QUIET - Only absolutely important information should be marked for quiet output. -* NORMAL - The default level, and normal usage -* VERBOSE - Mark messages that may be too noisy for everyday use, but helpful - for debugging as VERBOSE - -You can mark output as follows:: - - // Would appear at all levels. - $this->out('Quiet message', 1, Shell::QUIET); - $this->quiet('Quiet message'); - - // Would not appear when quiet output is toggled. - $this->out('normal message', 1, Shell::NORMAL); - $this->out('loud message', 1, Shell::VERBOSE); - $this->verbose('Verbose output'); - - // Would only appear when verbose output is enabled. - $this->out('extra message', 1, Shell::VERBOSE); - $this->verbose('Verbose output'); - -You can control the output level of shells, by using the ``--quiet`` and ``--verbose`` -options. These options are added by default, and allow you to consistently control -output levels inside your CakePHP shells. - -Styling Output --------------- - -Styling output is done by including tags - just like HTML - in your output. -ConsoleOutput will replace these tags with the correct ansi code sequence, or -remove the tags if you are on a console that doesn't support ansi codes. There -are several built-in styles, and you can create more. The built-in ones are - -* ``error`` Error messages. Red underlined text. -* ``warning`` Warning messages. Yellow text. -* ``info`` Informational messages. Cyan text. -* ``comment`` Additional text. Blue text. -* ``question`` Text that is a question, added automatically by shell. - -You can create additional styles using ``$this->stdout->styles()``. To declare a -new output style you could do:: - - $this->_io->styles('flashy', ['text' => 'magenta', 'blink' => true]); - -This would then allow you to use a ```` tag in your shell output, and if ansi -colours are enabled, the following would be rendered as blinking magenta text -``$this->out('Whoooa Something went wrong');``. When defining -styles you can use the following colours for the ``text`` and ``background`` attributes: - -* black -* red -* green -* yellow -* blue -* magenta -* cyan -* white - -You can also use the following options as boolean switches, setting them to a -truthy value enables them. - -* bold -* underline -* blink -* reverse - -Adding a style makes it available on all instances of ConsoleOutput as well, -so you don't have to redeclare styles for both stdout and stderr objects. - -Turning Off Colouring ---------------------- - -Although colouring is pretty awesome, there may be times when you want to turn it off, -or force it on:: - - $this->_io->outputAs(ConsoleOutput::RAW); - -The above will put the output object into raw output mode. In raw output mode, -no styling is done at all. There are three modes you can use. - -* ``ConsoleOutput::RAW`` - Raw output, no styling or formatting will be done. - This is a good mode to use if you are outputting XML or, want to debug why - your styling isn't working. -* ``ConsoleOutput::PLAIN`` - Plain text output, known style tags will be stripped - from the output. -* ``ConsoleOutput::COLOR`` - Output with color escape codes in place. - -By default on \*nix systems ConsoleOutput objects default to colour output. -On windows systems, plain output is the default unless the ``ANSICON`` environment -variable is present. - -Hook Methods -============ - -.. php:method:: initialize() - - Initializes the Shell acts as constructor for subclasses allows - configuration of tasks prior to shell execution. - -.. php:method:: startup() - - Starts up the Shell and displays the welcome message. Allows for checking - and configuring prior to command or main execution. - - Override this method if you want to remove the welcome information, or - otherwise modify the pre-command flow. - -Configuring Options and Generating Help -======================================= - -.. php:class:: ConsoleOptionParser - -``ConsoleOptionParser`` provides a command line option and -argument parser. - -OptionParsers allow you to accomplish two goals at the same time. First, they -allow you to define the options and arguments for your commands. This allows -you to separate basic input validation and your console commands. Secondly, it -allows you to provide documentation, that is used to generate a well formatted -help file. - -The console framework in CakePHP gets your shell's option parser by calling -``$this->getOptionParser()``. Overriding this method allows you to -configure the OptionParser to define the expected inputs of your shell. -You can also configure subcommand option parsers, which allow you to -have different option parsers for subcommands and tasks. -The ConsoleOptionParser implements a fluent interface and includes -methods for easily setting multiple options/arguments at once:: - - public function getOptionParser() - { - $parser = parent::getOptionParser(); - // Configure parser - return $parser; - } - -Configuring an Option Parser with the Fluent Interface ------------------------------------------------------- - -All of the methods that configure an option parser can be chained, -allowing you to define an entire option parser in one series of method calls:: - - public function getOptionParser() - { - $parser = parent::getOptionParser(); - $parser->addArgument('type', [ - 'help' => 'Either a full path or type of class.' - ])->addArgument('className', [ - 'help' => 'A CakePHP core class name (e.g: Component, HtmlHelper).' - ])->addOption('method', [ - 'short' => 'm', - 'help' => __('The specific method you want help on.') - ])->description(__('Lookup doc block comments for classes in CakePHP.')); - return $parser; - } - -The methods that allow chaining are: - -- description() -- epilog() -- command() -- addArgument() -- addArguments() -- addOption() -- addOptions() -- addSubcommand() -- addSubcommands() - -.. php:method:: description($text = null) - -Gets or sets the description for the option parser. The description -displays above the argument and option information. By passing in -either an array or a string, you can set the value of the description. -Calling with no arguments will return the current value:: - - // Set multiple lines at once - $parser->description(['line one', 'line two']); - - // Read the current value - $parser->description(); - -.. php:method:: epilog($text = null) - -Gets or sets the epilog for the option parser. The epilog -is displayed after the argument and option information. By passing in -either an array or a string, you can set the value of the epilog. -Calling with no arguments will return the current value:: - - // Set multiple lines at once - $parser->epilog(['line one', 'line two']); - - // Read the current value - $parser->epilog(); - -Adding Arguments ----------------- - -.. php:method:: addArgument($name, $params = []) - -Positional arguments are frequently used in command line tools, -and ``ConsoleOptionParser`` allows you to define positional -arguments as well as make them required. You can add arguments -one at a time with ``$parser->addArgument();`` or multiple at once -with ``$parser->addArguments();``:: - - $parser->addArgument('model', ['help' => 'The model to bake']); - -You can use the following options when creating an argument: - -* ``help`` The help text to display for this argument. -* ``required`` Whether this parameter is required. -* ``index`` The index for the arg, if left undefined the argument will be put - onto the end of the arguments. If you define the same index twice the - first option will be overwritten. -* ``choices`` An array of valid choices for this argument. If left empty all - values are valid. An exception will be raised when parse() encounters an - invalid value. - -Arguments that have been marked as required will throw an exception when -parsing the command if they have been omitted. So you don't have to -handle that in your shell. - -.. php:method:: addArguments(array $args) - -If you have an array with multiple arguments you can use ``$parser->addArguments()`` -to add multiple arguments at once. :: - - $parser->addArguments([ - 'node' => ['help' => 'The node to create', 'required' => true], - 'parent' => ['help' => 'The parent node', 'required' => true] - ]); - -As with all the builder methods on ConsoleOptionParser, addArguments -can be used as part of a fluent method chain. - -Validating Arguments --------------------- - -When creating positional arguments, you can use the ``required`` flag, to -indicate that an argument must be present when a shell is called. -Additionally you can use ``choices`` to force an argument to -be from a list of valid choices:: - - $parser->addArgument('type', [ - 'help' => 'The type of node to interact with.', - 'required' => true, - 'choices' => ['aro', 'aco'] - ]); - -The above will create an argument that is required and has validation -on the input. If the argument is either missing, or has an incorrect -value an exception will be raised and the shell will be stopped. - -Adding Options --------------- - -.. php:method:: addOption($name, $options = []) - -Options or flags are also frequently used in command line tools. -``ConsoleOptionParser`` supports creating options -with both verbose and short aliases, supplying defaults -and creating boolean switches. Options are created with either -``$parser->addOption()`` or ``$parser->addOptions()``. :: - - $parser->addOption('connection', [ - 'short' => 'c', - 'help' => 'connection', - 'default' => 'default', - ]); - -The above would allow you to use either ``cake myshell --connection=other``, -``cake myshell --connection other``, or ``cake myshell -c other`` -when invoking the shell. You can also create boolean switches, these switches do not -consume values, and their presence just enables them in the -parsed parameters. :: - - $parser->addOption('no-commit', ['boolean' => true]); - -With this option, when calling a shell like ``cake myshell --no-commit something`` -the no-commit param would have a value of true, and 'something' -would be a treated as a positional argument. -The built-in ``--help``, ``--verbose``, and ``--quiet`` options -use this feature. - -When creating options you can use the following options to -define the behavior of the option: - -* ``short`` - The single letter variant for this option, leave undefined for none. -* ``help`` - Help text for this option. Used when generating help for the option. -* ``default`` - The default value for this option. If not defined the default will be true. -* ``boolean`` - The option uses no value, it's just a boolean switch. - Defaults to false. -* ``choices`` An array of valid choices for this option. If left empty all - values are valid. An exception will be raised when parse() encounters an invalid value. - -.. php:method:: addOptions(array $options) - -If you have an array with multiple options you can use ``$parser->addOptions()`` -to add multiple options at once. :: - - $parser->addOptions([ - 'node' => ['short' => 'n', 'help' => 'The node to create'], - 'parent' => ['short' => 'p', 'help' => 'The parent node'] - ]); - -As with all the builder methods on ConsoleOptionParser, addOptions is can be used -as part of a fluent method chain. - -Validating Options ------------------- - -Options can be provided with a set of choices much like positional arguments -can be. When an option has defined choices, those are the only valid choices -for an option. All other values will raise an ``InvalidArgumentException``:: - - $parser->addOption('accept', [ - 'help' => 'What version to accept.', - 'choices' => ['working', 'theirs', 'mine'] - ]); - -Using Boolean Options ---------------------- - -Options can be defined as boolean options, which are useful when you need to create -some flag options. Like options with defaults, boolean options always include -themselves into the parsed parameters. When the flags are present they are set -to true, when they are absent false:: - - $parser->addOption('verbose', [ - 'help' => 'Enable verbose output.', - 'boolean' => true - ]); - -The following option would result in ``$this->params['verbose']`` always -being available. This lets you omit ``empty()`` or ``isset()`` -checks for boolean flags:: - - if ($this->params['verbose']) { - // Do something. - } - -Since the boolean options are always defined as ``true`` or -``false`` you can omit additional check methods. - -Adding Subcommands ------------------- - -.. php:method:: addSubcommand($name, $options = []) - -Console applications are often made of subcommands, and these subcommands -may require special option parsing and have their own help. A perfect -example of this is ``bake``. Bake is made of many separate tasks that all -have their own help and options. ``ConsoleOptionParser`` allows you to -define subcommands and provide command specific option parsers so the -shell knows how to parse commands for its tasks:: - - $parser->addSubcommand('model', [ - 'help' => 'Bake a model', - 'parser' => $this->Model->getOptionParser() - ]); - -The above is an example of how you could provide help and a specialized -option parser for a shell's task. By calling the Task's ``getOptionParser()`` -we don't have to duplicate the option parser generation, or mix concerns -in our shell. Adding subcommands in this way has two advantages. -First it lets your shell easily document its subcommands in the -generated help. It also gives easy access to the subcommand -help. With the above subcommand created you could call -``cake myshell --help`` and see the list of subcommands, and -also run ``cake myshell model --help`` to view the help for -just the model task. - .. note:: + La documentación no es compatible actualmente con el idioma español en esta página. - Once your Shell defines subcommands, all subcommands must be explicitly - defined. - -When defining a subcommand you can use the following options: - -* ``help`` - Help text for the subcommand. -* ``parser`` - A ConsoleOptionParser for the subcommand. This allows you - to create method specific option parsers. When help is generated for a - subcommand, if a parser is present it will be used. You can also - supply the parser as an array that is compatible with - :php:meth:`Cake\\Console\\ConsoleOptionParser::buildFromArray()` - -Adding subcommands can be done as part of a fluent method chain. - -Building a ConsoleOptionParser from an Array --------------------------------------------- - -.. php:method:: buildFromArray($spec) - -As previously mentioned, when creating subcommand option parsers, -you can define the parser spec as an array for that method. This can help -make building subcommand parsers easier, as everything is an array:: - - $parser->addSubcommand('check', [ - 'help' => __('Check the permissions between an ACO and ARO.'), - 'parser' => [ - 'description' => [ - __("Use this command to grant ACL permissions. Once executed, the "), - __("ARO specified (and its children, if any) will have ALLOW access "), - __("to the specified ACO action (and the ACO's children, if any).") - ], - 'arguments' => [ - 'aro' => ['help' => __('ARO to check.'), 'required' => true], - 'aco' => ['help' => __('ACO to check.'), 'required' => true], - 'action' => ['help' => __('Action to check')] - ] - ] - ]); - -Inside the parser spec, you can define keys for ``arguments``, ``options``, -``description`` and ``epilog``. You cannot define ``subcommands`` inside an -array style builder. The values for arguments, and options, should follow the -format that :php:func:`Cake\\Console\\ConsoleOptionParser::addArguments()` and -:php:func:`Cake\\Console\\ConsoleOptionParser::addOptions()` use. You can also use -buildFromArray on its own, to build an option parser:: - - public function getOptionParser() - { - return ConsoleOptionParser::buildFromArray([ - 'description' => [ - __("Use this command to grant ACL permissions. Once executed, the "), - __("ARO specified (and its children, if any) will have ALLOW access "), - __("to the specified ACO action (and the ACO's children, if any).") - ], - 'arguments' => [ - 'aro' => ['help' => __('ARO to check.'), 'required' => true], - 'aco' => ['help' => __('ACO to check.'), 'required' => true], - 'action' => ['help' => __('Action to check')] - ] - ]); - } - -Getting Help from Shells ------------------------- - -With the addition of ConsoleOptionParser getting help from shells is done -in a consistent and uniform way. By using the ``--help`` or -``h`` option you -can view the help for any core shell, and any shell that implements a ConsoleOptionParser:: - - cake bake --help - cake bake -h - -Would both generate the help for bake. If the shell supports subcommands -you can get help for those in a similar fashion:: - - cake bake model --help - cake bake model -h - -This would get you the help specific to bake's model task. - -Getting Help as XML -------------------- - -When building automated tools or development tools that need to interact -with CakePHP shells, its nice to have help available in a machine parse-able -format. The ConsoleOptionParser can provide help in xml by setting an -additional argument:: - - cake bake --help xml - cake bake -h xml - -The above would return an XML document with the generated help, options, -arguments and subcommands for the selected shell. A sample XML document -would look like: - -.. code-block:: xml - - - - bake fixture - Generate fixtures for use with the test suite. You can use - `bake fixture all` to bake all fixtures. - - Omitting all arguments and options will enter into an interactive - mode. - - - - - - - - - - - - - - - - - - -Routing in Shells / CLI -======================= - -In command-line interface (CLI), specifically your shells and tasks, ``env('HTTP_HOST')`` and -other webbrowser specific environment variables are not set. - -If you generate reports or send emails that make use of ``Router::url()`` those will contain -the default host ``http://localhost/`` and thus resulting in invalid URLs. In this case you need to -specify the domain manually. -You can do that using the Configure value ``App.fullBaseURL`` from your bootstrap or config, for example. - -For sending emails, you should provide Email class with the host you want to send the email with:: - - use Cake\Network\Email\Email; - - $email = new Email(); - $email->domain('www.example.org'); - -This asserts that the generated message IDs are valid and fit to the domain the emails are sent from. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. More Topics =========== @@ -913,14 +18,15 @@ More Topics .. toctree:: :maxdepth: 1 - console-and-shells/code-generation-with-bake + console-and-shells/helpers console-and-shells/repl console-and-shells/cron-jobs console-and-shells/i18n-shell console-and-shells/completion-shell + console-and-shells/plugin-shell + console-and-shells/routes-shell console-and-shells/upgrade-shell - .. meta:: - :title lang=en: Console and Shells - :keywords lang=en: shell scripts,system shell,application classes,background tasks,line script,cron job,request response,system path,acl,new projects,shells,specifics,parameters,i18n,cakephp,directory,maintenance,ideal,applications,mvc + :title lang=es: Console and Shells + :keywords lang=es: shell scripts,system shell,application classes,background tasks,line script,cron job,request response,system path,acl,new projects,shells,specifics,parameters,i18n,cakephp,directory,maintenance,ideal,applications,mvc diff --git a/es/console-and-shells/code-generation-with-bake.rst b/es/console-and-shells/code-generation-with-bake.rst deleted file mode 100644 index 5880817f54bbcf4528c07bb7af244c28c5228b47..0000000000000000000000000000000000000000 --- a/es/console-and-shells/code-generation-with-bake.rst +++ /dev/null @@ -1,148 +0,0 @@ -Code Generation with Bake -######################### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -CakePHP's bake console is another effort to get you up and running in CakePHP -– fast. The bake console can create any of CakePHP's basic ingredients: models, -behaviors, views, helpers, components, components test cases, fixtures and -plugins. And we aren't just talking skeleton classes: Bake can create a fully -functional application in just a few minutes. In fact, Bake is a natural step to -take once an application has been scaffolded. - -Depending on how your computer is configured, you may have to set -execute rights on the cake bash script to call it using ``bin/cake -bake``. The cake console is run using the PHP CLI (command line -interface). If you have problems running the script, ensure that -you have the PHP CLI installed and that it has the proper modules -enabled (eg: MySQL) Users also might have issues if the -database host is 'localhost' and should try '127.0.0.1' instead. -This could cause issues with PHP CLI. - -Before running bake you should make sure you have at least one database -connection configured. See the section on :ref:`database configuration -` for more information. - -When run with no arguments ``bin/cake bake`` will output a list of available -tasks. You should see something like:: - - --------------------------------------------------------------- - App : App - Path: /Users/markstory/Sites/cakephp-app/src/ - --------------------------------------------------------------- - The following commands you can generate skeleton code your your application. - - Available bake commands: - - behavior - component - controller - fixture - helper - model - plugin - project - test - view - - By using bin/cake bake [name] you can invoke a specific bake task. - -You can get more information on what each task does, and what options are -availble using the ``--help`` option:: - - $ bin/cake bake model --help - -Create New Tasks for Bake -========================= - -Bake features an extensible architecture that allows your application or plugins -to provide new tasks, or replace tasks provided by CakePHP. By extending -``Cake\Console\Command\Task\BakeTask``, bake will find your new task and include -it as part of bake. - -As an example, we'll make a task that creates shell classes. First, create -the task file ``src/Console/Command/Task/ShellTask.php``. We'll extend the -``SimpleBakeTask`` for now as our shell task will be simple. ``SimpleBakeTask`` -is abstract and requires us to define 4 methods that tell bake what the task is -called, where the files it generates should go, and what template to use. Our -ShellTask.php file should look like:: - - - namespace \Console\Command; - - use Cake\Console\Shell; - - /** - * shell - */ - class Shell extends Shell - { - - public function main() - { - // Add code. - } - } - -You should now see your new task in the output of ``bin/cake bake``. You can -run your new task by running ``bin/cake bake shell Example --template app``. -This will generate a new ``ExampleShell`` class for your application to use. - -Modify Default HTML/Code Produced by bake -========================================= - -If you wish to modify the default HTML output produced by the -"bake" command, you can create your own bake 'template' which allows you to replace -some or all of the templates that bake uses. To create a new bake template do the -following: - -#. Create a new directory in ``src/Template/Bake/[name]``. -#. Copy any templates you want to override from - ``vendor/cakephp/cakephp/src/Template/Bake/default``. to matching - directories in your application/plugin. -#. When running bake use the ``--template`` option to specify the bake template you - want to use. - -.. note:: - - Bake template names need to be unique, so don't use 'default'. - - -.. meta:: - :title lang=en: Code Generation with Bake - :keywords lang=en: command line interface,functional application,atabase,database configuration,bash script,basic ingredients,roject,odel,path path,code generation,scaffolding,windows users,configuration file,few minutes,config,iew,shell,models,running,mysql diff --git a/es/console-and-shells/completion-shell.rst b/es/console-and-shells/completion-shell.rst index c38b0e8ba7902c08cfe808c52cbf91eca64f80f5..c6dace293ed3b672de40161942e471540abeb169 100644 --- a/es/console-and-shells/completion-shell.rst +++ b/es/console-and-shells/completion-shell.rst @@ -2,117 +2,10 @@ Completion Shell ################ .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Working with the console gives the developer a lot of possibilities but having -to completely know and write those commands can be tedious. Especially when -developing new shells where the commands differ per minute iteration. The -Completion Shells aids in this matter by providing an API to write completion -scripts for shells like bash, zsh, fish etc. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -Sub Commands -============ - -The Completion Shell consists of a number of sub commands to assist the -developer creating it's completion script. Each for a different step in the -autocompletion process. - -Commands --------- - -For the first step commands outputs the available Shell Commands, including -plugin name when applicable. (All returned possibilities, for this and the other -sub commands, are separated by a space.) For example:: - - bin/cake Completion commands - -Returns:: - - acl api bake command_list completion console i18n schema server test testsuite upgrade - -Your completion script can select the relevant commands from that list to -continue with. (For this and the following sub commands.) - -subCommands ------------ - -Once the preferred command has been chosen subCommands comes in as the second -step and outputs the possible sub command for the given shell command. For -example:: - - bin/cake Completion subcommands bake - -Returns:: - - controller db_config fixture model plugin project test view - -options --------- - -As the third and final options outputs options for the given (sub) command as -set in getOptionParser. (Including the default options inherited from Shell.) -For example:: - - bin/cake Completion options bake - -Returns:: - - --help -h --verbose -v --quiet -q --connection -c --theme -t - -Bash Example -============ - -The following bash example comes from the original author:: - - # bash completion for CakePHP console - - _cake() - { - local cur prev opts cake - COMPREPLY=() - cake="${COMP_WORDS[0]}" - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - - if [[ "$cur" == -* ]] ; then - if [[ ${COMP_CWORD} = 1 ]] ; then - opts=$(${cake} Completion options) - elif [[ ${COMP_CWORD} = 2 ]] ; then - opts=$(${cake} Completion options "${COMP_WORDS[1]}") - else - opts=$(${cake} Completion options "${COMP_WORDS[1]}" "${COMP_WORDS[2]}") - fi - - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 - fi - - if [[ ${COMP_CWORD} = 1 ]] ; then - opts=$(${cake} Completion commands) - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 - fi - - if [[ ${COMP_CWORD} = 2 ]] ; then - opts=$(${cake} Completion subcommands $prev) - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - if [[ $COMPREPLY = "" ]] ; then - COMPREPLY=( $(compgen -df -- ${cur}) ) - return 0 - fi - return 0 - fi - - - opts=$(${cake} Completion fuzzy "${COMP_WORDS[@]:1}") - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - if [[ $COMPREPLY = "" ]] ; then - COMPREPLY=( $(compgen -df -- ${cur}) ) - return 0 - fi - return 0; - } - - complete -F _cake cake bin/cake + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/console-and-shells/cron-jobs.rst b/es/console-and-shells/cron-jobs.rst index e22e3b5b67334364118988efda426141c147e09b..70be87e75b4aca8f958bd8780294974cad11a485 100644 --- a/es/console-and-shells/cron-jobs.rst +++ b/es/console-and-shells/cron-jobs.rst @@ -2,27 +2,14 @@ Running Shells as Cron Jobs ########################### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -A common thing to do with a shell is making it run as a cronjob to -clean up the database once in a while or send newsletters. This is -trivial to setup, for example:: + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. - */5 * * * * cd /full/path/to/root && bin/cake myshell myparam - # * * * * * command to execute - # │ │ │ │ │ - # │ │ │ │ │ - # │ │ │ │ \───── day of week (0 - 6) (0 to 6 are Sunday to Saturday, - | | | | or use names) - # │ │ │ \────────── month (1 - 12) - # │ │ \─────────────── day of month (1 - 31) - # │ \──────────────────── hour (0 - 23) - # \───────────────────────── min (0 - 59) - -You can see more info here: http://en.wikipedia.org/wiki/Cron + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Running Shells as cronjobs - :keywords lang=en: cronjob,bash script,crontab + :title lang=es: Running Shells as cronjobs + :keywords lang=es: cronjob,bash script,crontab diff --git a/es/console-and-shells/helpers.rst b/es/console-and-shells/helpers.rst new file mode 100644 index 0000000000000000000000000000000000000000..32c2f07175fcef4e77ab465c4396fb3d2bf841b5 --- /dev/null +++ b/es/console-and-shells/helpers.rst @@ -0,0 +1,11 @@ +Shell Helpers +############# + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/console-and-shells/i18n-shell.rst b/es/console-and-shells/i18n-shell.rst index 774b44cdf6ce4298cd4eba28b5b7e5b88adb318e..2bfe87ffc29ec187c4896972351a3b8f076569d7 100644 --- a/es/console-and-shells/i18n-shell.rst +++ b/es/console-and-shells/i18n-shell.rst @@ -2,84 +2,14 @@ I18N Shell ########## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -The i18n features of CakePHP use `po files `_ -as their translation source. This makes them easily to integrate with tools -like `poedit `_ and other common translation tools. - -The i18n shell provides a quick and easy way to generate po template files. -These templates files can then be given to translators so they can translate the -strings in your application. Once you have translations done, pot files can be -merged with existing translations to help update your translations. - -Generating POT Files -==================== - -POT files can be generated for an existing application using the ``extract`` -command. This command will scan your entire application for ``__()`` style -function calls, and extract the message string. Each unique string in your -application will be combined into a single POT file:: - - bin/cake i18n extract - -The above will run the extraction shell. The result of this command will be the -file ``app/Locale/default.pot``. You use the pot file as a template for creating -po files. If you are manually creating po files from the pot file, be sure to -correctly set the ``Plural-Forms`` header line. - -Generating POT Files for Plugins --------------------------------- - -You can generate a POT file for a specific plugin using:: - - bin/cake i18n extract --plugin - -This will generate the required POT files used in the plugins. - -Excluding Folders ------------------ - -You can pass a comma separated list of folders that you wish to be excluded. -Any path containing a path segment with the provided values will be ignored:: - - bin/cake i18n extract --exclude Test,Vendor - -Skipping Overwrite Warnings for Existing POT Files --------------------------------------------------- - -By adding --overwrite, the shell script will no longer warn you if a POT file -already exists and will overwrite by default:: - - bin/cake i18n extract --overwrite - -Extracting Messages from the CakePHP Core Libraries ---------------------------------------------------- - -By default, the extract shell script will ask you if you like to extract -the messages used in the CakePHP core libraries. Set --extract-core to yes or -no to set the default behavior:: - - bin/cake i18n extract --extract-core yes - - or - - bin/cake i18n extract --extract-core no - - -Create the Tables used by TranslateBehavior -=========================================== - -The i18n shell can also be used to initialize the default tables used by the -:php:class:`TranslateBehavior`:: - - bin/cake i18n initdb - -This will create the ``i18n`` table used by translate behavior. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: I18N shell - :keywords lang=en: pot files,locale default,translation tools,message string,app locale,php class,validation,i18n,translations,shell,models + :title lang=es: I18N shell + :keywords lang=es: pot files,locale default,translation tools,message string,app locale,php class,validation,i18n,translations,shell,models diff --git a/es/console-and-shells/orm-cache.rst b/es/console-and-shells/orm-cache.rst index 06a207e4f49ab3c68f526b4f28997dfd5589f006..a9417ea1bcbf32506e57042c9c70d8670a3f6c91 100644 --- a/es/console-and-shells/orm-cache.rst +++ b/es/console-and-shells/orm-cache.rst @@ -2,28 +2,10 @@ ORM Cache Shell ############### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -The OrmCacheShell provides a simple CLI tool for managing your application's -metadata caches. In deployment situations it is helpful to rebuild the metadata -cache in-place without clearing the existing cache data. You can do this by -running:: + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. - bin/cake orm_cache build --connection default - -This will rebuild the metadata cache for all tables on the ``default`` -connection. If you only need to rebuild a single table you can do that by -providing its name:: - - bin/cake orm_cache build --connection default articles - -In addition to building cached data, you can use the OrmCacheShell to remove -cached metadata as well:: - - # Clear all metadata - bin/cake orm_cache clear - - # Clear a single table - bin/cake orm_cache clear articles + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/console-and-shells/plugin-shell.rst b/es/console-and-shells/plugin-shell.rst new file mode 100644 index 0000000000000000000000000000000000000000..cb8566496eee76c5b99fb5bc32ed42a33ecc9070 --- /dev/null +++ b/es/console-and-shells/plugin-shell.rst @@ -0,0 +1,19 @@ +.. _plugin-shell: + +Plugin Shell +############ + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta + página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve + this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección + superior para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Plugin Shell + :keywords lang=es: api docs,shell,plugin,load,unload diff --git a/es/console-and-shells/repl.rst b/es/console-and-shells/repl.rst index ee9867768c8011c0262eba832174639b6fdf5750..0953970dfb36ab3aa57bbbfccc5a1c392a714389 100644 --- a/es/console-and-shells/repl.rst +++ b/es/console-and-shells/repl.rst @@ -2,54 +2,12 @@ Interactive Console (REPL) ########################## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta + página. -The CakePHP app skeleton comes with a built in REPL(Read Eval Print Loop) that -makes it easy to explore some CakePHP and your application in an interactive -console. You can start the interactive console using:: + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve + this Doc** para proponer directamente los cambios. - $ bin/cake console - -This will bootstrap your application and start an interactive console. At this -point you can interact with your application code and execute queries using your -application's models:: - - $ bin/cake console - - Welcome to CakePHP v3.0.0 Console - --------------------------------------------------------------- - App : App - Path: /Users/mark/projects/cakephp-app/src/ - --------------------------------------------------------------- - [1] app > $articles = Cake\ORM\TableRegistry::get('Articles'); - // object(Cake\ORM\Table)( - // - // ) - [2] app > $articles->find(); - -Since your application has been bootstrapped you can also test routing using the -REPL:: - - [1] app > Cake\Routing\Router::parse('/articles/view/1'); - // [ - // 'controller' => 'Articles', - // 'action' => 'view', - // 'pass' => [ - // 0 => '1' - // ], - // 'plugin' => NULL - // ] - -You can also test generating URL's:: - - [1] app > Cake\Routing\Router::url(['controller' => 'Articles', 'action' => 'edit', 99]); - // '/articles/edit/99' - -To quit the REPL you can use ``CTRL-D``. - -.. warning:: - - The REPL does not work properly on windows systems due to issues with - readline and POSIX extensions. + Usted puede hacer referencia a la versión en Inglés en el menú de selección + superior para obtener información sobre el tema de esta página. diff --git a/es/console-and-shells/routes-shell.rst b/es/console-and-shells/routes-shell.rst new file mode 100644 index 0000000000000000000000000000000000000000..03e8e1b6a5429042572b97939e8d26359311a2c0 --- /dev/null +++ b/es/console-and-shells/routes-shell.rst @@ -0,0 +1,11 @@ +Routes Shell +############ + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/console-and-shells/upgrade-shell.rst b/es/console-and-shells/upgrade-shell.rst index 10cfe72cbc905881be27e8da01d71c8f4fbb7b9b..498b97b7defc50cc52be8dd4a9ddc2cd1d5f3ada 100644 --- a/es/console-and-shells/upgrade-shell.rst +++ b/es/console-and-shells/upgrade-shell.rst @@ -4,83 +4,14 @@ Upgrade Shell ############# .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -The upgrade shell will do most of the work to upgrade your CakePHP application -from 1.3 to 2.0. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -To run all upgrade steps:: - - bin/cake upgrade all - -If you would like to see what the shell will do without modifying files perform -a dry run first with --dry-run:: - - bin/cake upgrade all --dry-run - -To upgrade your plugin run the command:: - - bin/cake upgrade all --plugin YourPluginName - -You are able to run each upgrade step individually. To see all the steps -available run the command:: - - bin/cake upgrade --help - -Or visit the `API docs `_ for more info. - -Upgrade Your App ----------------- - -Here is a guide to help you upgrade your CakePHP 1.3 app to 2.x using the -upgrade shell. Your 1.3 app structure will likely look like this:: - - mywebsite/ - app/ <- Your App - cake/ <- 1.3 Version of CakePHP - plugins/ - vendors/ - .htaccess - index.php - -The first step is to download or ``git clone`` the new version of CakePHP into -another folder outside of your ``mywebsite`` folder, we'll call it ``cakephp``. -We don't want the downloaded ``app`` folder to overwrite your app folder. Now is -a good time to make a backup of your app folder, eg.: ``cp -R app app-backup``. - -Copy the ``cakephp/lib`` folder to your ``mywebsite/lib`` to setup the new -CakePHP version in your app, eg.: ``cp -R ../cakephp/lib .``. Symlinking is a -good alternative to copy as well, eg.: ``ln -s /var/www/cakephp/lib``. - -Before we can run the upgrade shell we need the new console scripts as well. -Copy the ``cakephp/src/Console`` folder into your ``mywebsite/App``, eg.: -``cp -R ../cakephp/src/Console ./App``. - -Your folder structure should look like this now:: - - mywebsite/ - app/ <- Your App - Console/ <- Copied app/Console Folder - app-backup/ <- Backup Copy of Your App - cake/ <- 1.3 Version of CakePHP - lib/ <- 2.x Version of CakePHP - Cake/ - plugins/ - vendors/ - .htaccess - index.php - -Now we can run the upgrade shell by ``cd``'ing into your ``app`` folder and -running the command:: - - bin/cake upgrade all - -This will do **most** of the work to upgrade your app to 2.x. Check things over -in your upgraded ``app`` folder. If everything looks good then congratulate -yourself and delete your ``mywebsite/cake`` folder. Welcome to 2.x! + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: .. _upgrade-shell: - :keywords lang=en: api docs,shell + :title lang=es: Upgrade Shell + :keywords lang=es: api docs,shell,upgrade diff --git a/es/contents.rst b/es/contents.rst index e5ef34f144cea298102413a5ab1fd63dee1e7aca..c8473b977576a7f57e807657793d9801d8b99e51 100644 --- a/es/contents.rst +++ b/es/contents.rst @@ -2,7 +2,13 @@ Contenidos ########## .. toctree:: - :maxdepth: 3 + :hidden: + + index + topics + +.. toctree:: + :maxdepth: 3 intro quickstart @@ -17,17 +23,19 @@ Contenidos controllers views orm - development/errors + controllers/components/authentication + bake core-libraries/caching console-and-shells development/debugging deployment core-libraries/email + development/errors core-libraries/events core-libraries/internationalization-and-localization core-libraries/logging - controllers/components/authentication + core-libraries/form controllers/components/pagination plugins development/rest @@ -44,11 +52,15 @@ Contenidos core-libraries/inflector core-libraries/number core-libraries/registry-objects - core-libraries/string + core-libraries/text core-libraries/time core-libraries/xml core-libraries/global-constants-and-functions + debug-kit + migrations + elasticsearch + upgrade-tool appendices .. todolist:: diff --git a/es/contributing.rst b/es/contributing.rst index 1a698507f1c8db6fdb191fec04b2b2bc9636df99..9aeed12a058f1e3da2ed4c2186d6b4b157591b62 100644 --- a/es/contributing.rst +++ b/es/contributing.rst @@ -2,12 +2,13 @@ Contributing ############ .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -There are a number of ways you can contribute to CakePHP. The following sections -cover the various ways you can contribute to CakePHP: + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. toctree:: :maxdepth: 1 @@ -18,8 +19,6 @@ cover the various ways you can contribute to CakePHP: contributing/cakephp-coding-conventions contributing/backwards-compatibility - - .. meta:: - :title lang=en: Contributing - :keywords lang=en: coding conventions,documentation,maxdepth + :title lang=es: Contributing + :keywords lang=es: coding conventions,documentation,maxdepth diff --git a/es/contributing/backwards-compatibility.rst b/es/contributing/backwards-compatibility.rst index d3e9eff71b1c923505a2ff4c3f82fc079270ef9d..bc7299940f2491e90614e008105b323200a130a4 100644 --- a/es/contributing/backwards-compatibility.rst +++ b/es/contributing/backwards-compatibility.rst @@ -2,170 +2,10 @@ Backwards Compatibility Guide ############################# .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Ensuring that you can upgrade your applications easily and smoothly is important -to us. That's why we only break compatibility at major release milestones. -You might be familiar with `semantic versioning `_, which is -the general guideline we use on all CakePHP projects. In short, semantic -versioning means that only major releases (such as 2.0, 3.0, 4.0) can break -backwards compatibility. Minor releases (such as 2.1, 3.1, 3.2) may introduce new -features, but are not allowed to break compatibility. Bug fix releases (such as 2.1.2, -3.0.1) do not add new features, but fix bugs or enhance performance only. - -.. note:: - - CakePHP started following semantic versioning in 2.0.0. These - rules do not apply to 1.x. - -To clarify what changes you can expect in each release tier we have more -detailed information for developers using CakePHP, and for developers working on -CakePHP that helps set expectations of what can be done in minor releases. Major -releases can have as many breaking changes as required. - -Migration Guides -================ - -For each major and minor release, the CakePHP team will provide a migration -guide. These guides explain the new features and any breaking changes that are -in each release. They can be found in the :doc:`/appendices` section of the -cookbook. - -Using CakePHP -============= - -If you are building your application with CakePHP, the following guidelines -explain the stability you can expect. - -Interfaces ----------- - -Outside of major releases, interfaces provided by CakePHP will **not** have any -existing methods changed. New methods may be added, but no existing methods will -be changed. - -Classes -------- - -Classes provided by CakePHP can be constructed and have their public methods and -properties used by application code and outside of major releases backwards -compatibility is ensured. - -.. note:: - - Some classes in CakePHP are marked with the ``@internal`` API doc tag. These - classes are **not** stable and do not have any backwards compatibility - promises. - -In minor releases, new methods may be added to classes, and existing methods may -have new arguments added. Any new arguments will have default values, but if -you've overidden methods with a differing signature you may see fatal errors. -Methods that have new arguments added will be documented in the migration guide -for that release. - -The following table outlines several use cases and what compatibility you can -expect from CakePHP: - -+-------------------------------+--------------------------+ -| If you... | Backwards compatibility? | -+===============================+==========================+ -| Typehint against the class | Yes | -+-------------------------------+--------------------------+ -| Create a new instance | Yes | -+-------------------------------+--------------------------+ -| Extend the class | Yes | -+-------------------------------+--------------------------+ -| Access a public property | Yes | -+-------------------------------+--------------------------+ -| Call a public method | Yes | -+-------------------------------+--------------------------+ -| **Extend a class and...** | -+-------------------------------+--------------------------+ -| Override a public property | Yes | -+-------------------------------+--------------------------+ -| Access a protected property | No [1]_ | -+-------------------------------+--------------------------+ -| Override a protected property | No [1]_ | -+-------------------------------+--------------------------+ -| Override a protected method | No [1]_ | -+-------------------------------+--------------------------+ -| Call a protected method | No [1]_ | -+-------------------------------+--------------------------+ -| Add a public property | No | -+-------------------------------+--------------------------+ -| Add a public method | No | -+-------------------------------+--------------------------+ -| Add an argument | No [1]_ | -| to an overridden method | | -+-------------------------------+--------------------------+ -| Add a default argument | Yes | -| to an existing method | | -+-------------------------------+--------------------------+ - -Working on CakePHP -================== - -If you are helping make CakePHP even better please keep the following guidelines -in mind when adding/changing functionality: - -In a minor release you can: - -+-------------------------------+--------------------------+ -| In a minor release can you... | -+===============================+==========================+ -| **Classes** | -+-------------------------------+--------------------------+ -| Remove a class | No | -+-------------------------------+--------------------------+ -| Remove an interface | No | -+-------------------------------+--------------------------+ -| Remove a trait | No | -+-------------------------------+--------------------------+ -| Make final | No | -+-------------------------------+--------------------------+ -| Make abstract | No | -+-------------------------------+--------------------------+ -| Change name | Yes [2]_ | -+-------------------------------+--------------------------+ -| **Properties** | -+-------------------------------+--------------------------+ -| Add a public property | Yes | -+-------------------------------+--------------------------+ -| Remove a public property | No | -+-------------------------------+--------------------------+ -| Add a protected property | Yes | -+-------------------------------+--------------------------+ -| Remove a protected property | Yes [3]_ | -+-------------------------------+--------------------------+ -| **Methods** | -+-------------------------------+--------------------------+ -| Add a public method | Yes | -+-------------------------------+--------------------------+ -| Remove a public method | No | -+-------------------------------+--------------------------+ -| Add a protected method | Yes | -+-------------------------------+--------------------------+ -| Move to parent class | Yes | -+-------------------------------+--------------------------+ -| Remove a protected method | Yes [3]_ | -+-------------------------------+--------------------------+ -| Reduce visibility | No | -+-------------------------------+--------------------------+ -| Change method name | Yes [2]_ | -+-------------------------------+--------------------------+ -| Add argument with | Yes | -| default value | | -+-------------------------------+--------------------------+ -| Add required argument | No | -+-------------------------------+--------------------------+ - - -.. [1] Your code *may* be broken by minor releases. Check the migration guide - for details. -.. [2] You can change a class/method name as long as the old name remains available. - This is generally avoided unless renaming has significant benefit. -.. [3] Avoid whenever possible. Any removals need to be documented in - the migration guide. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/contributing/cakephp-coding-conventions.rst b/es/contributing/cakephp-coding-conventions.rst index 50158b50a3a6219f48d1f4414711446511e87ee3..82667aa2202ba69530b499edac1e8f9c21f0ceaa 100644 --- a/es/contributing/cakephp-coding-conventions.rst +++ b/es/contributing/cakephp-coding-conventions.rst @@ -2,514 +2,14 @@ Coding Standards ################ .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -CakePHP developers will use the following coding standards. - -It is recommended that others developing CakeIngredients follow the same -standards. - -You can use the `CakePHP Code Sniffer -`_ to check that your code -follows required standards. - -Adding New Features -=================== - -No new features should be added, without having their own tests – which -should be passed before committing them to the repository. - -Indentation -=========== - -One tab will be used for indentation. - -So, indentation should look like this:: - - // base level - // level 1 - // level 2 - // level 1 - // base level - -Or:: - - $booleanVariable = true; - $stringVariable = 'moose'; - if ($booleanVariable) { - echo 'Boolean value is true'; - if ($stringVariable === 'moose') { - echo 'We have encountered a moose'; - } - } - -Control Structures -================== - -Control structures are for example "``if``", "``for``", "``foreach``", -"``while``", "``switch``" etc. Below, an example with "``if``":: - - if ((expr_1) || (expr_2)) { - // action_1; - } elseif (!(expr_3) && (expr_4)) { - // action_2; - } else { - // default_action; - } - -* In the control structures there should be 1 (one) space before the - first parenthesis and 1 (one) space between the last parenthesis and - the opening bracket. -* Always use curly brackets in control structures, even if they are not - needed. They increase the readability of the code, and they give you - fewer logical errors. -* Opening curly brackets should be placed on the same line as the - control structure. Closing curly brackets should be placed on new - lines, and they should have same indentation level as the control - structure. The statement included in curly brackets should begin on a - new line, and code contained within it should gain a new level of - indentation. -* Inline assignments should not be used inside of the control structures. - -:: - - // wrong = no brackets, badly placed statement - if (expr) statement; - - // wrong = no brackets - if (expr) - statement; - - // good - if (expr) { - statement; - } - - // wrong = inline assignment - if ($variable = Class::function()) { - statement; - } - - // good - $variable = Class::function(); - if ($variable) { - statement; - } - -Ternary Operator ----------------- - -Ternary operators are permissible when the entire ternary operation fits -on one line. Longer ternaries should be split into ``if else`` -statements. Ternary operators should not ever be nested. Optionally -parentheses can be used around the condition check of the ternary for -clarity:: - - // Good, simple and readable - $variable = isset($options['variable']) ? $options['variable'] : true; - - // Nested ternaries are bad - $variable = isset($options['variable']) ? isset($options['othervar']) ? true : false : false; - - -View Files ----------- - -In view files (.ctp files) developers should use keyword control structures. -Keyword control structures are easier to read in complex view files. Control -structures can either be contained in a larger PHP block, or in separate PHP -tags:: - - You are the admin user.

    '; - endif; - ?> -

    The following is also acceptable:

    - -

    You are the admin user.

    - - - -Comparison -========== - -Always try to be as strict as possible. If a none strict test is deliberate it might be wise to -comment it as such to avoid confusing it for a mistake. - -For testing if a variable is null, it is recommended to use a strict check:: - - if ($value === null) { - // ... - } - -The value to check against should be placed on the right side:: - - // not recommended - if (null === $this->foo()) { - // ... - } - - // recommended - if ($this->foo() === null) { - // ... - } - -Function Calls -============== - -Functions should be called without space between function's name and -starting bracket. There should be one space between every parameter of a -function call:: - - $var = foo($bar, $bar2, $bar3); - -As you can see above there should be one space on both sides of equals -sign (=). - -Method Definition -================= - -Example of a method definition:: - - public function someFunction($arg1, $arg2 = '') - { - if (expr) { - statement; - } - return $var; - } - -Parameters with a default value, should be placed last in function -definition. Try to make your functions return something, at least ``true`` -or ``false``, so it can be determined whether the function call was -successful:: - - public function connection($dns, $persistent = false) - { - if (is_array($dns)) { - $dnsInfo = $dns; - } else { - $dnsInfo = BD::parseDNS($dns); - } - - if (!($dnsInfo) || !($dnsInfo['phpType'])) { - return $this->addError(); - } - return true; - } - -There are spaces on both side of the equals sign. - -Typehinting ------------ - -Arguments that expect objects, arrays or callbacks (callable) can be typehinted. -We only typehint public methods, though, as typehinting is not cost-free:: - - /** - * Some method description. - * - * @param Model $Model The model to use. - * @param array $array Some array value. - * @param callable $callback Some callback. - * @param boolean $boolean Some boolean value. - */ - public function foo(Model $Model, array $array, callable $callback, $boolean) - { - } - -Here ``$Model`` must be an instance of ``Model``, ``$array`` must be an ``array`` and -``$callback`` must be of type ``callable`` (a valid callback). - -Note that if you want to allow ``$array`` to be also an instance of ``ArrayObject`` -you should not typehint as ``array`` accepts only the primitive type:: - - /** - * Some method description. - * - * @param array|ArrayObject $array Some array value. - */ - public function foo($array) - { - } - -Method Chaining -=============== - -Method chaining should have multiple methods spread across separate lines, and -indented with one tab:: - - $email->from('foo@example.com') - ->to('bar@example.com') - ->subject('A great message') - ->send(); - -Commenting Code -=============== - -All comments should be written in English, and should in a clear way -describe the commented block of code. - -Comments can include the following `phpDocumentor `_ -tags: - -* `@author `_ -* `@copyright `_ -* `@deprecated `_ -* `@example `_ -* `@ignore `_ -* `@internal `_ -* `@link `_ -* `@see `_ -* `@since `_ -* `@tutorial `_ -* `@version `_ - -PhpDoc tags are very much like JavaDoc tags in Java. Tags are only -processed if they are the first thing in a DocBlock line, for example:: - - /** - * Tag example. - * - * @author this tag is parsed, but this @version is ignored - * @version 1.0 this tag is also parsed - */ - -:: - - /** - * Example of inline phpDoc tags. - * - * This function works hard with foo() to rule the world. - * - * @return void - */ - function bar() - { - } - - /** - * Foo function. - * - * @return void - */ - function foo() - { - } - -Comment blocks, with the exception of the first block in a file, should -always be preceded by a newline. - -Variable Types --------------- - -Variable types for use in DocBlocks: - -Type - Description -mixed - A variable with undefined (or multiple) type. -int - Integer type variable (whole number). -float - Float type (point number). -bool - Logical type (true or false). -string - String type (any value in " " or ' '). -null - Null type. Usually used in conjunction with another type. -array - Array type. -object - Object type. A specific class name should be used if possible. -resource - Resource type (returned by for example mysql\_connect()). - Remember that when you specify the type as mixed, you should indicate - whether it is unknown, or what the possible types are. -callable - Callable function. - -You can also combine types using the pipe char:: - - int|bool - -For more than two types it is usually best to just use ``mixed``. - -When returning the object itself, e.g. for chaining, one should use ``$this`` instead:: - - /** - * Foo function. - * - * @return $this - */ - public function foo() - { - return $this; - } - -Including Files -=============== - -``include``, ``require``, ``include_once`` and ``require_once`` do not have parentheses:: - - // wrong = parentheses - require_once('ClassFileName.php'); - require_once ($class); - - // good = no parentheses - require_once 'ClassFileName.php'; - require_once $class; - -When including files with classes or libraries, use only and always the -`require\_once `_ function. - -PHP Tags -======== - -Always use long tags (````) Instead of short tags (````). The short echo -should be used in view files (``.ctp``) where appropriate. - -Short Echo ----------- - -The short echo should be used in view files in place of `` - - // good = spaces, no semicolon -
  • - -As of PHP 5.4 the short echo tag (```_ -* FTP: `ftp://ftp.example.com `_ - -The "example.com" domain name has been reserved for this (see :rfc:`2606`) and is recommended -for use in documentation or as examples. - -Files ------ - -File names which do not contain classes should be lowercased and underscored, for -example:: - - long_file_name.php - -Casting -------- - -For casting we use: - -Type - Description -(bool) - Cast to boolean. -(int) - Cast to integer. -(float) - Cast to float. -(string) - Cast to string. -(array) - Cast to array. -(object) - Cast to object. - -Constants ---------- - -Constants should be defined in capital letters:: - - define('CONSTANT', 1); - -If a constant name consists of multiple words, they should be separated -by an underscore character, for example:: - - define('LONG_NAMED_CONSTANT', 2); + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Coding Standards - :keywords lang=en: curly brackets,indentation level,logical errors,control structures,control structure,expr,coding standards,parenthesis,foreach,readability,moose,new features,repository,developers + :title lang=es: Coding Standards + :keywords lang=es: curly brackets,indentation level,logical errors,control structures,control structure,expr,coding standards,parenthesis,foreach,readability,moose,new features,repository,developers diff --git a/es/contributing/code.rst b/es/contributing/code.rst index 2d846aff712cf8f6f54c613b87c9fe2662d84215..1258901b29be6bb2ef820c5da191c94157175396 100644 --- a/es/contributing/code.rst +++ b/es/contributing/code.rst @@ -2,145 +2,14 @@ Code #### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Patches and pull requests are a great way to contribute code back to CakePHP. -Pull requests can be created in GitHub, and are prefered over patch files in -ticket comments. - -Initial Setup -============= - -Before working on patches for CakePHP, it's a good idea to get your environment -setup. You'll need the following software: - -* Git -* PHP 5.4.16 or greater -* PHPUnit 3.7.0 or greater - -Set up your user information with your name/handle and working email address:: - - git config --global user.name 'Bob Barker' - git config --global user.email 'bob.barker@example.com' - -.. note:: - - If you are new to Git, we highly recommend you to read the excellent and free - `ProGit `_ book. - -Get a clone of the CakePHP source code from GitHub: - -* If you don't have a `GitHub `_ account, create one. -* Fork the `CakePHP repository `_ by clicking - the **Fork** button. - -After your fork is made, clone your fork to your local machine:: - - git clone git@github.com:YOURNAME/cakephp.git - -Add the original CakePHP repository as a remote repository. You'll use this -later to fetch changes from the CakePHP repository. This will let you stay up -to date with CakePHP:: - - cd cakephp - git remote add upstream git://github.com/cakephp/cakephp.git - -Now that you have CakePHP setup you should be able to define a ``$test`` -:ref:`database connection `, and -:ref:`run all the tests `. - -Working on a Patch -================== - -Each time you want to work on a bug, feature or enhancement create a topic -branch. - -The branch you create should be based on the version that your fix/enhancement -is for. For example if you are fixing a bug in ``2.3`` you would want to use -the ``2.3`` branch as the base for your branch. If your change is a bug fix -for the current stable release, you should use the ``master`` branch. This -makes merging your changes in later much simpler:: - - # fixing a bug on 2.3 - git fetch upstream - git checkout -b ticket-1234 upstream/2.3 - -.. tip:: - - Use a descriptive name for your branch, referencing the ticket or feature - name is a good convention. e.g. ticket-1234, feature-awesome - -The above will create a local branch based on the upstream (CakePHP) 2.3 branch. -Work on your fix, and make as many commits as you need; but keep in mind the -following: - -* Follow the :doc:`/contributing/cakephp-coding-conventions`. -* Add a test case to show the bug is fixed, or that the new feature works. -* Keep your commits logical, and write good clear and concise commit messages. - - -Submitting a Pull Request -========================= - -Once your changes are done and you're ready for them to be merged into CakePHP, -you'll want to update your branch:: - - git checkout 2.3 - git fetch upstream - git merge upstream/2.3 - git checkout - git rebase 2.3 - -This will fetch + merge in any changes that have happened in CakePHP since you -started. It will then rebase - or replay your changes on top of the current -code. You might encounter a conflict during the ``rebase``. If the rebase -quits early you can see which files are conflicted/un-merged with ``git status``. -Resolve each conflict, and then continue the rebase:: - - git add # do this for each conflicted file. - git rebase --continue - -Check that all your tests continue to pass. Then push your branch to your -fork:: - - git push origin - -Once your branch is on GitHub, you can discuss it on the -`cakephp-core `_ mailing list or -submit a pull request on GitHub. - -Choosing Where Your Changes will be Merged Into ------------------------------------------------ - -When making pull requests you should make sure you select the correct base -branch, as you cannot edit it once the pull request is created. - -* If your change is a **bugfix** and doesn't introduce new functionality and only - corrects existing behavior that is present in the current release. Then - choose **master** as your merge target. -* If your change is a **new feature** or an addition to the framework, then you - should choose the branch with the next version number. For example if the - current stable release is ``2.2.2``, the branch accepting new features will be - ``2.3`` -* If your change is a breaks existing functionality, or API's then you'll have - to choose then next major release. For example, if the current release is - ``2.2.2`` then the next time existing behavior can be broken will be in - ``3.0`` so you should target that branch. - - -.. note:: - - Remember that all code you contribute to CakePHP will be licensed under the - MIT License, and the `Cake Software Foundation `_ - will become the owner of any contributed code and all contributed code is - subject to the `Contributors license agreement `_. - -All bug fixes merged into a maintenance branch will also be merged into upcoming -releases periodically by the core team. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Code - :keywords lang=en: cakephp source code,code patches,test ref,descriptive name,bob barker,initial setup,global user,database connection,clone,repository,user information,enhancement,back patches,checkout + :title lang=es: Code + :keywords lang=es: cakephp source code,code patches,test ref,descriptive name,bob barker,initial setup,global user,database connection,clone,repository,user information,enhancement,back patches,checkout diff --git a/es/contributing/documentation.rst b/es/contributing/documentation.rst index b6feb1b070093e1fd89eee51a3580a82c4bafc7e..be7211abe4f88bcd290629d690e8e4228a2eec1f 100644 --- a/es/contributing/documentation.rst +++ b/es/contributing/documentation.rst @@ -2,381 +2,14 @@ Documentation ############# .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Contributing to the documentation is simple. The files are hosted on -https://github.com/cakephp/docs. Feel free to fork the repo, add your -changes/improvements/translations and give back by issuing a pull request. -You can even edit the docs online with GitHub, without ever downloading the -files -- the "Improve this Doc" button on any given page will direct you to -GitHub's online editor for that page. - -Translations -============ - -Email the docs team (docs at cakephp dot org) or hop on IRC -(#cakephp on freenode) to discuss any translation efforts you would -like to participate in. - -Translator tips: - -- Browse and edit in the language you want the content to be - translated to - otherwise you won't see what has already been - translated. -- Feel free to dive right in if your chosen language already - exists on the book. -- Use `Informal Form `_. -- Translate both the content and the title at the same time. -- Do compare to the English content before submitting a correction - (if you correct something, but don't integrate an 'upstream' change - your submission won't be accepted). -- If you need to write an English term, wrap it in ```` tags. - E.g. "asdf asdf *Controller* asdf" or "asdf asdf Kontroller - (*Controller*) asfd" as appropriate. -- Do not submit partial translations. -- Do not edit a section with a pending change. -- Do not use - `html entities `_ - for accented characters, the book uses UTF-8. -- Do not significantly change the markup (HTML) or add new content -- If the original content is missing some info, submit an edit for - that first. - -Documentation Formatting Guide -============================== - -The new CakePHP documentation is written with `ReST formatted text `_. ReST -(Re Structured Text) is a plain text markup syntax similar to markdown, or -textile. To maintain consistency it is recommended that when adding to the -CakePHP documentation you follow the guidelines here on how to format and -structure your text. - -Line Length ------------ - -Lines of text should be wrapped at 80 columns. The only exception should be -long URLs, and code snippets. - -Headings and Sections ---------------------- - -Section headers are created by underlining the title with punctuation characters -at least the length of the text. - -- ``#`` Is used to denote page titles. -- ``=`` Is used for sections in a page. -- ``-`` Is used for subsections. -- ``~`` Is used for sub-subsections -- ``^`` Is used for sub-sub-sections. - -Headings should not be nested more than 5 levels deep. Headings should be -preceded and followed by a blank line. - -Paragraphs ----------- - -Paragraphs are simply blocks of text, with all the lines at the same level of indentation. -Paragraphs should be separated by more than one empty line. - -Inline Markup -------------- - -* One asterisk: *text* for emphasis (italics) - - * ``*text*`` - -* Two asterisks: **text** for strong emphasis (boldface) - - * ``**text**`` - -* Two backquotes: ``text`` for code samples - - * ````text```` - -If asterisks or backquotes appear in running text and could be confused with inline markup -delimiters, they have to be escaped with a backslash. - -Inline markup has a few restrictions: - -* It **may not** be nested. -* Content may not start or end with whitespace: ``* text*`` is wrong. -* Content must be separated from surrounding text by non-word characters. Use a - backslash escaped space to work around that: ``onelong\ *bolded*\ word``. - -Lists ------ - -List markup is very similar to markdown. Unordered lists are indicated by -starting a line with a single asterisk and a space. Numbered lists can be -created with either numerals, or ``#`` for auto numbering:: - - * This is a bullet - * So is this. But this line - has two lines. - - 1. First line - 2. Second line - - #. Automatic numbering - #. Will save you some time. - -Indented lists can also be created, by indenting sections and separating them -with an empty line:: - - * First line - * Second line - - * Going deeper - * Whoah - - * Back to the first level. - -Definition lists can be created by doing the following:: - - term - definition - CakePHP - An MVC framework for PHP - -Terms cannot be more than one line, but definitions can be multi-line and all -lines should be indented consistently. - -Links ------ - -There are several kinds of links, each with their own uses. - -External Links -~~~~~~~~~~~~~~ - -Links to external documents can be with the following:: - - `External Link `_ - -The above would generate a link pointing to http://example.com - -Links to Other Pages -~~~~~~~~~~~~~~~~~~~~ - -.. rst:role:: doc - - Other pages in the documentation can be linked to using the ``:doc:`` role. - You can link to the specified document using either an absolute or relative - path reference. You should omit the ``.rst`` extension. For example, if - the reference ``:doc:`form``` appears in the document ``core-helpers/html``, - then the link references ``core-helpers/form``. If the reference was - ``:doc:`/core-helpers```, it would always reference ``/core-helpers`` - regardless of where it was used. - -Cross Referencing Links -~~~~~~~~~~~~~~~~~~~~~~~ - -.. rst:role:: ref - - You can cross reference any arbitrary title in any document using the - ``:ref:`` role. Link label targets must be unique across the entire - documentation. When creating labels for class methods, it's best to use - ``class-method`` as the format for your link label. - - The most common use of labels is above a title. Example:: - - .. _label-name: - - Section heading - --------------- - - More content here. - - Elsewhere you could reference the above section using ``:ref:`label-name```. - The link's text would be the title that the link preceded. You can also - provide custom link text using ``:ref:`Link text ```. - -Describing Classes and their Contents -------------------------------------- - -The CakePHP documentation uses the `phpdomain -`_ to provide custom -directives for describing PHP objects and constructs. Using these directives -and roles is required to give proper indexing and cross referencing features. - -Describing Classes and Constructs ---------------------------------- - -Each directive populates the index, and or the namespace index. - -.. rst:directive:: .. php:global:: name - - This directive declares a new PHP global variable. - -.. rst:directive:: .. php:function:: name(signature) - - Defines a new global function outside of a class. - -.. rst:directive:: .. php:const:: name - - This directive declares a new PHP constant, you can also use it nested - inside a class directive to create class constants. - -.. rst:directive:: .. php:exception:: name - - This directive declares a new Exception in the current namespace. The - signature can include constructor arguments. - -.. rst:directive:: .. php:class:: name - - Describes a class. Methods, attributes, and constants belonging to the class - should be inside this directive's body:: - - .. php:class:: MyClass - - Class description - - .. php:method:: method($argument) - - Method description - - - Attributes, methods and constants don't need to be nested. They can also just - follow the class declaration:: - - .. php:class:: MyClass - - Text about the class - - .. php:method:: methodName() - - Text about the method - - - .. seealso:: :rst:dir:`php:method`, :rst:dir:`php:attr`, :rst:dir:`php:const` - -.. rst:directive:: .. php:method:: name(signature) - - Describe a class method, its arguments, return value, and exceptions:: - - .. php:method:: instanceMethod($one, $two) - - :param string $one: The first parameter. - :param string $two: The second parameter. - :returns: An array of stuff. - :throws: InvalidArgumentException - - This is an instance method. - -.. rst:directive:: .. php:staticmethod:: ClassName::methodName(signature) - - Describe a static method, its arguments, return value and exceptions, - see :rst:dir:`php:method` for options. - -.. rst:directive:: .. php:attr:: name - - Describe an property/attribute on a class. - -Cross Referencing -~~~~~~~~~~~~~~~~~ - -The following roles refer to PHP objects and links are generated if a -matching directive is found: - -.. rst:role:: php:func - - Reference a PHP function. - -.. rst:role:: php:global - - Reference a global variable whose name has ``$`` prefix. - -.. rst:role:: php:const - - Reference either a global constant, or a class constant. Class constants should - be preceded by the owning class:: - - DateTime has an :php:const:`DateTime::ATOM` constant. - -.. rst:role:: php:class - - Reference a class by name:: - - :php:class:`ClassName` - -.. rst:role:: php:meth - - Reference a method of a class. This role supports both kinds of methods:: - - :php:meth:`DateTime::setDate` - :php:meth:`Classname::staticMethod` - -.. rst:role:: php:attr - - Reference a property on an object:: - - :php:attr:`ClassName::$propertyName` - -.. rst:role:: php:exc - - Reference an exception. - - -Source Code ------------ - -Literal code blocks are created by ending a paragraph with ``::``. The literal -block must be indented, and like all paragraphs be separated by single lines:: - - This is a paragraph:: - - while ($i--) { - doStuff() - } - - This is regular text again. - -Literal text is not modified or formatted, save that one level of indentation is removed. - - -Notes and Warnings ------------------- - -There are often times when you want to inform the reader of an important tip, -special note or a potential hazard. Admonitions in sphinx are used for just -that. There are three kinds of admonitions. - -* ``.. tip::`` Tips are used to document or re-iterate interesting or important - information. The content of the directive should be written in complete - sentences and include all appropriate punctuation. -* ``.. note::`` Notes are used to document an especially important piece of - information. The content of the directive should be written in complete - sentences and include all appropriate punctuation. -* ``.. warning::`` Warnings are used to document potential stumbling blocks, or - information pertaining to security. The content of the directive should be - written in complete sentences and include all appropriate punctuation. - -All admonitions are made the same:: - - .. note:: - - Indented and preceded and followed by a blank line. Just like a paragraph. - - This text is not part of the note. - -Samples -~~~~~~~ - -.. tip:: - - This is a helpful tid-bit you probably forgot. - -.. note:: - - You should pay attention here. - -.. warning:: - - It could be dangerous. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Documentation - :keywords lang=en: partial translations,translation efforts,html entities,text markup,asfd,asdf,structured text,english content,markdown,formatted text,dot org,repo,consistency,translator,freenode,textile,improvements,syntax,cakephp,submission + :title lang=es: Documentation + :keywords lang=es: partial translations,translation efforts,html entities,text markup,asfd,asdf,structured text,english content,markdown,formatted text,dot org,repo,consistency,translator,freenode,textile,improvements,syntax,cakephp,submission diff --git a/es/contributing/tickets.rst b/es/contributing/tickets.rst index afb3e58be15bae746c05064608d45b165845a262..f7d9e85d98068aedffd82bd670103b7f05c5a65d 100644 --- a/es/contributing/tickets.rst +++ b/es/contributing/tickets.rst @@ -2,58 +2,14 @@ Tickets ####### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -Getting feedback and help from the community in the form of tickets is an -extremely important part of the CakePHP development process. All of CakePHP's -tickets are hosted on `GitHub `_. - -Reporting Bugs -============== - -Well written bug reports are very helpful. There are a few steps to help create -the best bug report possible: - -* **Do** `search `_ - for a similar existing ticket, and ensure someone hasn't already reported your - issue, or that it hasn't already been fixed in the repository. -* **Do** include detailed instructions on **how to reproduce the bug**. This - could be in the form of test cases or a code snippet that demonstrates the - issue. Not having a way to reproduce an issue, means it's less likely to get - fixed. -* **Do** give as many details as possible about your environment: (OS, PHP - version, CakePHP version). -* **Don't** use the ticket system to ask support questions. Use the `google - group `_ or the #cakephp IRC channel - for that. - - -Reporting Security Issues -========================= - -If you've found a security issue in CakePHP, please use the following procedure -instead of the normal bug reporting system. Instead of using the bug tracker, -mailing list or IRC please send an email to **security [at] cakephp.org**. -Emails sent to this address go to the CakePHP core team on a private mailing -list. - -For each report, we try to first confirm the vulnerability. Once confirmed, the -CakePHP team will take the following actions: - -* Acknowledge to the reporter that we've received the issue, and are working on - a fix. We ask that the reporter keep the issue confidential until we announce - it. -* Get a fix/patch prepared. -* Prepare a post describing the vulnerability, and the possible exploits. -* Release new versions of all affected versions. -* Prominently feature the problem in the release announcement. - - + La documentación no es compatible actualmente con el idioma español en esta página. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Tickets - :keywords lang=en: bug reporting system,code snippet,reporting security,private mailing,release announcement,google,ticket system,core team,security issue,bug tracker,irc channel,test cases,support questions,bug report,security issues,bug reports,exploits,vulnerability,repository + :title lang=es: Tickets + :keywords lang=es: bug reporting system,code snippet,reporting security,private mailing,release announcement,google,ticket system,core team,security issue,bug tracker,irc channel,test cases,support questions,bug report,security issues,bug reports,exploits,vulnerability,repository diff --git a/es/controllers.rst b/es/controllers.rst index 9794334c792cd9a73751f9cb365920787a724681..03a972a518979ff51c393b2b366349e2818c5e73 100644 --- a/es/controllers.rst +++ b/es/controllers.rst @@ -1,474 +1,18 @@ Controllers ########### -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - .. php:namespace:: Cake\Controller .. php:class:: Controller -Controllers are the 'C' in MVC. After routing has been applied and the correct -controller has been found, your controller's action is called. Your controller -should handle interpreting the request data, making sure the correct models -are called, and the right response or view is rendered. Controllers can be -thought of as middle man between the Model and View. You want to keep your -controllers thin, and your models fat. This will help you more easily reuse -your code and makes your code easier to test. - -Commonly, a controller is used to manage the logic around a single model. For -example, if you were building a site for an online bakery, you might have a -RecipesController managing your recipes and an IngredientsController managing your -ingredients. However, it's also possible to have controllers work with more than -one model. In CakePHP, a controller is named after the primary model it -handles. - -Your application's controllers extend the ``AppController`` class, which in turn -extends the core :php:class:`Controller` class. The ``AppController`` -class can be defined in ``src/Controller/AppController.php`` and it should -contain methods that are shared between all of your application's controllers. - -Controllers provide a number of methods that handle requests. These are called -*actions*. By default, each public method in -a controller is an action, and is accessible from a URL. An action is responsible -for interpreting the request and creating the response. Usually responses are -in the form of a rendered view, but there are other ways to create responses as -well. - -.. _app-controller: - -The App Controller -================== - -As stated in the introduction, the ``AppController`` class is the parent class -to all of your application's controllers. ``AppController`` itself extends the -:php:class:`Cake\\Controller\\Controller` class included in CakePHP. -``AppController`` is defined in ``src/Controller/AppController.php`` as -follows:: - - namespace App\Controller; - - use Cake\Controller\Controller; - - class AppController extends Controller - { - } - -Controller attributes and methods created in your ``AppController`` will be -available in all controllers that extend it. Components (which you'll -learn about later) are best used for code that is used in many (but not -necessarily all) controllers. - -While normal object-oriented inheritance rules apply, CakePHP does a bit of -extra work when it comes to special controller attributes. The components and -helpers used by a controller are treated specially. In these cases, -``AppController`` value arrays are merged with child controller class arrays. -The values in the child class will always override those in ``AppController.`` - .. note:: + La documentación no es compatible actualmente con el idioma español en esta página. - CakePHP merges the following variables from the ``AppController`` into - your application's controllers: - - - :php:attr:`~Controller::$components` - - :php:attr:`~Controller::$helpers` - -Remember to call ``AppController``'s callbacks within child -controller callbacks for best results:: - - public function beforeFilter(Event $event) - { - parent::beforeFilter($event); - } - -Request Parameters -================== - -When a request is made to a CakePHP application, CakePHP's -:php:class:`Cake\\Routing\\Router` and :php:class:`Cake\\Routing\\Dispatcher` -classes use :ref:`routes-configuration` to find and create the correct -controller instance. The request data is encapsulated in a request object. -CakePHP puts all of the important request information into the ``$this->request`` -property. See the section on :ref:`cake-request` for more information on the -CakePHP request object. - -Controller Actions -================== - -Controller actions are responsible for converting the request parameters into a -response for the browser/user making the request. CakePHP uses conventions to -automate this process and remove some boilerplate code you would otherwise need -to write. - -By convention, CakePHP renders a view with an inflected version of the action -name. Returning to our online bakery example, our RecipesController might contain the -``view()``, ``share()``, and ``search()`` actions. The controller would be found -in ``src/Controller/RecipesController.php`` and contain:: - - # src/Controller/RecipesController.php - - class RecipesController extends AppController - { - public function view($id) - { - // Action logic goes here.. - } - - public function share($customerId, $recipeId) - { - // Action logic goes here.. - } - - public function search($query) - { - // Action logic goes here.. - } - } - -The view files for these actions would be ``src/Template/Recipes/view.ctp``, -``src/Template/Recipes/share.ctp``, and ``src/Template/Recipes/search.ctp``. The -conventional view file name is the lowercased and underscored version of the -action name. - -Controller actions generally use -``Controller::set()`` to create a context that -``View`` uses to render the view. Because of the conventions that -CakePHP uses, you don't need to create and render the view manually. Instead, -once a controller action has completed, CakePHP will handle rendering and -delivering the View. - -If for some reason you'd like to skip the default behavior, you can return a -:php:class:`Cake\\Network\\Response` object from the action with the fully -created response. - -When you use controller methods with -:php:meth:`~Cake\\Routing\\RequestActionTrait::requestAction()` -you will typcially return a ``Response`` instance. If you have controller -methods that are used for normal web requests + requestAction, you should check -the request type before returning:: - - class RecipesController extends AppController - { - public function popular() - { - $popular = $this->Recipes->find('popular'); - if (!$this->request->is('requested')) { - $this->response->body(json_encode($popular)); - return $this->response; - } - $this->set('popular', $popular); - } - } - -The above controller action is an example of how a method can be used with -:php:meth:`~Cake\\Routing\\RequestActionTrait::requestAction()` and normal -requests. - -In order for you to use a controller effectively in your own application, we'll -cover some of the core attributes and methods provided by CakePHP's controllers. - -.. _controller-life-cycle: - -Request Life-cycle Callbacks -============================ - -CakePHP controllers come fitted with callbacks you can use to -insert logic around the request life-cycle: - -.. php:method:: beforeFilter(Event $event) - - This function is executed before every action in the controller. - It's a handy place to check for an active session or inspect user - permissions. - - .. note:: - - The beforeFilter() method will be called for missing actions. - -.. php:method:: beforeRender(Event $event) - - Called after controller action logic, but before the view is rendered. This - callback is not used often, but may be needed if you are calling - :php:meth:`Cake\\Controller\\Controller::render()` manually before the end - of a given action. - -.. php:method:: afterFilter(Event $event) - - Called after every controller action, and after rendering is - complete. This is the last controller method to run. - -In addition to controller life-cycle callbacks, :doc:`/controllers/components` -also provide a similar set of callbacks. - - -Interacting with Views -====================== - -Controllers interact with views in a number of ways. First, they -are able to pass data to the views, using ``Controller::set()``. You can also -decide which view class to use, and which view file should be -rendered from the controller. - -.. _setting-view_variables: - -Setting View Variables ----------------------- - -.. php:method:: set(string $var, mixed $value) - -The ``Controller::set()`` method is the main way to send data from your -controller to your view. Once you've used ``Controller::set()``, the variable -can be accessed in your view:: - - // First you pass data from the controller: - - $this->set('color', 'pink'); - - // Then, in the view, you can utilize the data: - ?> - - You have selected icing for the cake. - -The ``Controller::set()`` method also takes an -associative array as its first parameter. This can often be a quick way to -assign a set of information to the view:: - - $data = [ - 'color' => 'pink', - 'type' => 'sugar', - 'base_price' => 23.95 - ]; - - // Make $color, $type, and $base_price - // available to the view: - - $this->set($data); + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -Rendering a View ----------------- - -.. php:method:: render(string $view, string $layout) - -The ``render()`` method is automatically called at the end of each requested -controller action. This method performs all the view logic (using the data -you've submitted using the ``set()`` method), places the view inside its -``View::$layout``, and serves it back to the end user. - -The default view file used by render is determined by convention. -If the ``search()`` action of the RecipesController is requested, -the view file in ``src/Template/Recipes/search.ctp`` will be rendered:: - - namespace App\Controller; - - class RecipesController extends AppController - { - // ... - public function search() - { - // Render the view in src/Template/Recipes/search.ctp - $this->render(); - } - // ... - } - -Although CakePHP will automatically call it after every action's logic -(unless you've set ``$this->autoRender`` to false), you can use it to specify -an alternate view file by specifying a view file name as first argument of -``render()`` method. - -If ``$view`` starts with '/', it is assumed to be a view or -element file relative to the ``src/Template`` folder. This allows -direct rendering of elements, very useful in AJAX calls:: - - // Render the element in src/Template/Element/ajaxreturn.ctp - $this->render('/Element/ajaxreturn'); - -The second parameter ``$layout`` of ``render()`` allows you to specify the layout -with which the view is rendered. - -Rendering a Specific Template -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In your controller, you may want to render a different view than the -conventional one. You can do this by calling ``render()`` directly. Once you -have called ``render()``, CakePHP will not try to re-render the view:: - - namespace App\Controller; - - class PostsController extends AppController - { - public function my_action() - { - $this->render('custom_file'); - } - } - -This would render ``src/Template/Posts/custom_file.ctp`` instead of -``src/Template/Posts/my_action.ctp`` - - -You can also render views inside plugins using the following syntax: -``$this->render('PluginName.PluginController/custom_file')``. -For example:: - - namespace App\Controller; - - class PostsController extends AppController - { - public function my_action() - { - $this->render('Users.UserDetails/custom_file'); - } - } -     -This would render ``plugins/Users/src/Template/UserDetails/custom_file.ctp`` - -Redirecting to Other Pages -========================== - -.. php:method:: redirect(string|array $url, integer $status) - -The flow control method you'll use most often is ``Controller::redirect()``. -This method takes its first parameter in the form of a -CakePHP-relative URL. When a user has successfully placed an order, -you might wish to redirect them to a receipt screen. :: - - public function place_order() - { - // Logic for finalizing order goes here - if ($success) { - return $this->redirect( - ['controller' => 'Orders', 'action' => 'thanks'] - ); - } - return $this->redirect( - ['controller' => 'Orders', 'action' => 'confirm'] - ); - } - -The method will return the response instance with appropriate headers set. -You should return the response instance from your action to prevent -view rendering and let the dispatcher handle actual redirection. - -You can also use a relative or absolute URL as the $url argument:: - - return $this->redirect('/orders/thanks'); - return $this->redirect('http://www.example.com'); - -You can also pass data to the action:: - - return $this->redirect(['action' => 'edit', $id]); - -The second parameter of ``redirect()`` allows you to define an HTTP -status code to accompany the redirect. You may want to use 301 -(moved permanently) or 303 (see other), depending on the nature of -the redirect. - -If you need to redirect to the referer page you can use:: - - return $this->redirect($this->referer()); - -An example using query strings and hash would look like:: - - return $this->redirect([ - 'controller' => 'Orders', - 'action' => 'confirm', - '?' => [ - 'product' => 'pizza', - 'quantity' => 5 - ], - '#' => 'top' - ]); - -The generated URL would be:: - - http://www.example.com/orders/confirm?product=pizza&quantity=5#top - -Paginating a Model -================== - -.. php:method:: paginate() - -This method is used for paginating results fetched by your models. -You can specify page sizes, model find conditions and more. See the -:doc:`pagination ` section for more details on -how to use ``paginate()`` - -The paginate attribute gives you an easy way to customize how ``paginate()`` -behaves:: - - class ArticlesController extends AppController - { - public $paginate = [ - 'Articles' => [ - 'conditions' => ['published' => 1] - ] - ]; - } - -Loading Additional Models -========================= - -.. php:method:: loadModel(string $modelClass, string $type) - -The ``loadModel`` function comes handy when you need to use a model -table/collection that is not the controller's default one:: - - $this->loadModel('Articles'); - $recentArticles = $this->Articles->find('all', [ - 'limit' => 5, - 'order' => 'Articles.created DESC' - ]); - -If you are using a table provider other than the built-in ORM you can -link that table system into CakePHP's controllers by connecting its -factory method:: - - $this->modelFactory( - 'ElasticIndex', - ['ElasticIndexes', 'factory'] - ); - -After registering a table factory, you can use ``loadModel`` to load -instances:: - - $this->loadModel('Locations', 'ElasticIndex'); - -.. note:: - - The built-in ORM's TableRegistry is connected by default as the 'Table' - provider. - -Configuring Components to Load -============================== - -.. php:attr:: components - -The ``$components`` property on your controllers allows you to configure -components. Configured components and their dependencies will be created by -CakePHP for you. Read the :ref:`configuring-components` section for more -information. As mentioned earlier the ``$components`` property will be merged -with the property defined in each of you controller's parent classes. - -Configuring Helpers to Load -=========================== - -.. php:attr:: helpers - -Let's look at how to tell a CakePHP Controller that you plan to use -additional MVC classes:: - - class RecipesController extends AppController - { - public $helpers = ['Form']; - public $components = ['RequestHandler']; - } - -Each of these variables are merged with their inherited values, -therefore it is not necessary (for example) to redeclare the -``FormHelper``, or anything that is declared in your ``AppController``. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. More on Controllers =================== @@ -476,11 +20,9 @@ More on Controllers .. toctree:: :maxdepth: 1 - controllers/request-response controllers/pages-controller controllers/components - .. meta:: - :title lang=en: Controllers - :keywords lang=en: correct models,controller class,controller controller,core library,single model,request data,middle man,bakery,mvc,attributes,logic,recipes + :title lang=es: Controllers + :keywords lang=es: correct models,controller class,controller controller,core library,single model,request data,middle man,bakery,mvc,attributes,logic,recipes diff --git a/es/controllers/components.rst b/es/controllers/components.rst index 189e1c7c9447a0e2517cfcf05a8af1c5e36a0772..486504b6c58913df148ff34f14af09c84e9fcb6c 100644 --- a/es/controllers/components.rst +++ b/es/controllers/components.rst @@ -2,313 +2,25 @@ Components ########## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Components are packages of logic that are shared between controllers. -CakePHP comes with a fantastic set of core components you can use to aid in -various common tasks. You can also create your own components. If you find -yourself wanting to copy and paste things between controllers, you should -consider creating your own component to contain the functionality. Creating -components keeps controller code clean and allows you to reuse code between projects. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -Each of the core components is detailed in its own chapter. See :doc:`/core-libraries/toc-components`. -This section describes how to configure and use components, and how to create -your own components. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. -.. _configuring-components: +.. toctree:: + :maxdepth: 1 -Configuring Components -====================== - -Many of the core components require configuration. Some examples of -components requiring configuration are -:doc:`/core-libraries/components/authentication` and :doc:`/core-libraries/components/cookie`. -Configuration for these components, and for components in general, is usually done in the -``$components`` array or your controller's ``beforeFilter()`` method:: - - class PostsController extends AppController - { - public $components = [ - 'Auth' => [ - 'authorize' => ['controller'], - 'loginAction' => ['controller' => 'Users', 'action' => 'login'] - ], - 'Cookie' => ['name' => 'CookieMonster'] - ]; - -The previous fragment of code would be an example of configuring a component -with the ``$components`` array. You can configure components at runtime using -the ``config()`` method. Often, this is done in your controller's -``beforeFilter()`` method. The above could also be expressed as:: - - public function beforeFilter() - { - $this->Auth->config('authorize', ['controller']); - $this->Auth->config('loginAction', ['controller' => 'Users', 'action' => 'login']); - - $this->Cookie->config('name', 'CookieMonster'); - } - -Like helpers, components implement a ``config()`` method that is used to get and -set any configuration data for a component:: - - // Read config data. - $this->Auth->config('loginAction'); - - // Set config - $this->Csrf->config('cookieName', 'token'); - -As with helpers, components will automatically merge their ``$_defaultConfig`` -property with constructor configuration to create the ``$_config`` property -which is accessible with ``config()``. - -Aliasing Components -------------------- - -One common setting to use is the ``className`` option, which allows you to -alias components. This feature is useful when you want to -replace ``$this->Auth`` or another common Component reference with a custom -implementation:: - - // src/Controller/PostsController.php - class PostsController extends AppController - { - public $components = [ - 'Auth' => [ - 'className' => 'MyAuth' - ] - ]; - } - - // src/Controller/Component/MyAuthComponent.php - use Cake\Controller\Component\AuthComponent; - - class MyAuthComponent extends AuthComponent - { - // Add your code to override the core AuthComponent - } - -The above would *alias* ``MyAuthComponent`` to ``$this->Auth`` in your -controllers. - -.. note:: - - Aliasing a component replaces that instance anywhere that component is used, - including inside other Components. - -Using Components -================ - -Once you've included some components in your controller, using them is pretty -simple. Each component you use is exposed as a property on your controller. If -you had loaded up the :php:class:`Cake\\Controller\\Component\\FlashComponent` -and the :php:class:`Cake\\Controller\\Component\\CookieComponent` in your -controller, you could access them like so:: - - class PostsController extends AppController - { - public $components = ['Flash', 'Cookie']; - - public function delete() - { - if ($this->Post->delete($this->request->data('Post.id')) { - $this->Flash->success('Post deleted.'); - return $this->redirect(['action' => 'index']); - } - } - -.. note:: - - Since both Models and Components are added to Controllers as - properties they share the same 'namespace'. Be sure to not give a - component and a model the same name. - -Loading Components on the Fly ------------------------------ - -You might not need all of your components available on every controller -action. In situations like this you can load a component at runtime using the -:doc:`Component Registry `. From inside a -controller's method you can do the following:: - - $this->OneTimer = $this->Components->load('OneTimer'); - $this->OneTimer->getTime(); - -.. note:: - - Keep in mind that components loaded on the fly will not have missed - callbacks called. If you rely on the ``initialize`` or ``startup`` callbacks - being called, you may need to call them manually depending on when you load - your component. - -Component Callbacks -=================== - -Components also offer a few request life-cycle callbacks that allow them to -augment the request cycle. See the base :ref:`component-api` and -:doc:`/core-libraries/events` for more information on the callbacks components -offer. - -.. _creating-a-component: - -Creating a Component -==================== - -Suppose our online application needs to perform a complex -mathematical operation in many different parts of the application. -We could create a component to house this shared logic for use in -many different controllers. - -The first step is to create a new component file and class. Create -the file in ``src/Controller/Component/MathComponent.php``. The basic -structure for the component would look something like this:: - - namespace App\Controller\Component; - - use Cake\Controller\Component; - - class MathComponent extends Component - { - public function doComplexOperation($amount1, $amount2) - { - return $amount1 + $amount2; - } - } - -.. note:: - - All components must extend :php:class:`Component`. Failing to do this - will trigger an exception. - -Including your Component in your Controllers --------------------------------------------- - -Once our component is finished, we can use it in the application's -controllers by placing the component's name (without the "Component" -part) in the controller's ``$components`` array. The controller will -automatically be given a new attribute named after the component, -through which we can access an instance of it:: - - /* Make the new component available at $this->Math, - as well as the standard $this->Session */ - public $components = ['Math', 'Session']; - -Components declared in ``AppController`` will be merged with those -in your other controllers. So there is no need to re-declare the -same component twice. - -When including Components in a Controller you can also declare a -set of parameters that will be passed on to the Component's -constructor. These parameters can then be handled by -the Component:: - - public $components = [ - 'Math' => [ - 'precision' => 2, - 'randomGenerator' => 'srand' - ], - 'Session', 'Auth' - ]; - -The above would pass the array containing precision and -randomGenerator to ``MathComponent::__construct()`` as the -second parameter. By convention, if array keys match component's public -properties, the properties will be set to the values of these keys. - - -Using Other Components in your Component ----------------------------------------- - -Sometimes one of your components may need to use another component. -In this case you can include other components in your component the exact same -way you include them in controllers - using the ``$components`` var:: - - // src/Controller/Component/CustomComponent.php - use Cake\Controller\Component; - - class CustomComponent extends Component - { - // The other component your component uses - public $components = ['Existing']; - - public function initialize(Controller $controller) - { - $this->Existing->foo(); - } - - public function bar() - { - // ... - } - } - - // src/Controller/Component/ExistingComponent.php - use Cake\Controller\Component; - - class ExistingComponent extends Component - { - - public function foo() - { - // ... - } - } - -.. note:: - In contrast to a component included in a controller - no callbacks will be triggered on a component's component. - -.. _component-api: - -Component API -============= - -.. php:class:: Component - - The base Component class offers a few methods for lazily loading other - Components through :php:class:`Cake\\Controller\\ComponentRegistry` as well - as dealing with common handling of settings. It also provides prototypes - for all the component callbacks. - -.. php:method:: __construct(ComponentRegistry $registry, $config = []) - - Constructor for the base component class. All ``$config`` that - are also public properties will have their values changed to the - matching value in ``$config``. - -Callbacks ---------- - -.. php:method:: initialize(Event $event, Controller $controller) - - Is called before the controller's - beforeFilter method. - -.. php:method:: startup(Event $event, Controller $controller) - - Is called after the controller's beforeFilter - method but before the controller executes the current action - handler. - -.. php:method:: beforeRender(Event $event, Controller $controller) - - Is called after the controller executes the requested action's logic, - but before the controller's renders views and layout. - -.. php:method:: shutdown(Event $event, Controller $controller) - - Is called before output is sent to the browser. - -.. php:method:: beforeRedirect(Event $event, Controller $controller, $url, $response) - - Is invoked when the controller's redirect - method is called but before any further action. If this method - returns false the controller will not continue on to redirect the - request. The $url, and $response paramaters allow you to inspect and modify - the location or any other headers in the response. + /controllers/components/authentication + /controllers/components/cookie + /controllers/components/csrf + /controllers/components/flash + /controllers/components/security + /controllers/components/pagination + /controllers/components/request-handling .. meta:: - :title lang=en: Components - :keywords lang=en: array controller,core libraries,authentication request,array name,access control lists,public components,controller code,core components,cookiemonster,login cookie,configuration settings,functionality,logic,sessions,cakephp,doc + :title lang=es: Components + :keywords lang=es: array controller,core libraries,authentication request,array name,access control lists,public components,controller code,core components,cookiemonster,login cookie,configuration settings,functionality,logic,sessions,cakephp,doc diff --git a/es/controllers/components/authentication.rst b/es/controllers/components/authentication.rst new file mode 100644 index 0000000000000000000000000000000000000000..552273efa18b157d0f998b95ae3b6f7dab094dc2 --- /dev/null +++ b/es/controllers/components/authentication.rst @@ -0,0 +1,15 @@ +Authentication +############## + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Authentication + :keywords lang=es: authentication handlers,array php,basic authentication,web application,different ways,credentials,exceptions,cakephp,logging diff --git a/es/controllers/components/cookie.rst b/es/controllers/components/cookie.rst new file mode 100644 index 0000000000000000000000000000000000000000..288f615991492c624448956b89487df0ccd0f6fc --- /dev/null +++ b/es/controllers/components/cookie.rst @@ -0,0 +1,15 @@ +CookieComponent +############### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Cookie + :keywords lang=es: array controller,php setcookie,cookie string,controller setup,string domain,default description,string name,session cookie,integers,variables,domain name,null diff --git a/es/controllers/components/csrf.rst b/es/controllers/components/csrf.rst new file mode 100644 index 0000000000000000000000000000000000000000..2055c795986e636b1bd82fed6080d3add5dceac1 --- /dev/null +++ b/es/controllers/components/csrf.rst @@ -0,0 +1,15 @@ +Cross Site Request Forgery +########################## + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Csrf + :keywords lang=es: configurable parameters,security component,configuration parameters,invalid request,csrf,submission diff --git a/es/controllers/components/flash.rst b/es/controllers/components/flash.rst new file mode 100644 index 0000000000000000000000000000000000000000..57f94b1065b837baa998819daddd7df67dffd14d --- /dev/null +++ b/es/controllers/components/flash.rst @@ -0,0 +1,11 @@ +FlashComponent +############## + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/controllers/components/pagination.rst b/es/controllers/components/pagination.rst new file mode 100644 index 0000000000000000000000000000000000000000..b99a61a6a7bf87a284a50c789eef294de36fce79 --- /dev/null +++ b/es/controllers/components/pagination.rst @@ -0,0 +1,15 @@ +Pagination +########## + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Pagination + :keywords lang=es: order array,query conditions,php class,web applications,headaches,obstacles,complexity,programmers,parameters,paginate,designers,cakephp,satisfaction,developers diff --git a/es/controllers/components/request-handling.rst b/es/controllers/components/request-handling.rst new file mode 100644 index 0000000000000000000000000000000000000000..c219ab6f612f3584838c229f9569859a91a16992 --- /dev/null +++ b/es/controllers/components/request-handling.rst @@ -0,0 +1,15 @@ +Request Handling +################ + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Request Handling + :keywords lang=es: handler component,javascript libraries,public components,null returns,model data,request data,content types,file extensions,ajax,meth,content type,array,conjunction,cakephp,insight,php diff --git a/es/controllers/components/security.rst b/es/controllers/components/security.rst new file mode 100644 index 0000000000000000000000000000000000000000..9a0023d5f0afb7d1942e0a327d5bafca9dae4376 --- /dev/null +++ b/es/controllers/components/security.rst @@ -0,0 +1,15 @@ +Security +######## + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Security + :keywords lang=es: configurable parameters,security component,configuration parameters,invalid request,protection features,tighter security,holing,php class,meth,404 error,period of inactivity,csrf,array,submission,security class,disable security,unlockActions diff --git a/es/controllers/pages-controller.rst b/es/controllers/pages-controller.rst index d1bcfd021f319863e76f425139a5c4d37ecdd807..849f95f0cd44f141886020319a2ab029b7f7d21c 100644 --- a/es/controllers/pages-controller.rst +++ b/es/controllers/pages-controller.rst @@ -2,20 +2,14 @@ The Pages Controller #################### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -CakePHP ships with a default controller ``PagesController.php``. This is a -simple and optional controller for serving up static content. The home page -you see after installation is generated using this controller. If you make the -view file ``src/Template/Pages/about_us.ctp`` you can access it using the URL -``http://example.com/pages/about_us``. You are free to modify the Pages -Controller to meet your needs. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -When you "bake" an app using Composer the Pages Controller is created in your -``src/Controller/`` folder. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: The Pages Controller - :keywords lang=en: pages controller,default controller,cakephp,ships,php,file folder + :title lang=es: The Pages Controller + :keywords lang=es: pages controller,default controller,cakephp,ships,php,file folder diff --git a/es/controllers/request-response.rst b/es/controllers/request-response.rst index eb81f64bf1de9c118c8305227d84625362d34f63..1fb84e1223bb985a37a2f3bb45745bce7ea6b135 100644 --- a/es/controllers/request-response.rst +++ b/es/controllers/request-response.rst @@ -2,759 +2,14 @@ Request & Response Objects ########################## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -.. php:namespace:: Cake\Network + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -The request and response objects provide an abstraction around HTTP requests and -responses. The request object in CakePHP allows you to easily introspect an -incoming request, while the response object allows you to effortlessly create -HTTP responses from your controllers. - -.. index:: $this->request -.. _cake-request: - -Request -####### - -.. php:class:: Request - -``Request`` is the default request object used in CakePHP. It centralizes -a number of features for interrogating and interacting with request data. -On each request one Request is created and then passed by reference to the various -layers of an application that use request data. By default the request is assigned to -``$this->request``, and is available in Controllers, Cells, Views and Helpers. You can -also access it in Components using the controller reference. Some of the duties -``Request`` performs include: - -* Processing the GET, POST, and FILES arrays into the data structures you are - familiar with. -* Providing environment introspection pertaining to the request. Information like the - headers sent, the client's IP address, and the subdomain/domain names - the server your application is running on. -* Providing access to request parameters both as array indexes and object - properties. - -Request Parameters -================== - -Request exposes several interfaces for accessing request parameters:: - - $this->request->params['controller']; - $this->request->param('controller'); - -All of the above will access the same value. All :ref:`route-elements` are -accessed through this interface. - -In addition to :ref:`route-elements`, you also often need access to -:ref:`passed-arguments`. These are both available on the request object as well:: - - // Passed arguments - $this->request->pass; - $this->request['pass']; - $this->request->params['pass']; - -Will all provide you access to the passed arguments. There -are several important/useful parameters that CakePHP uses internally, these -are also all found in the request parameters: - -* ``plugin`` The plugin handling the request. Will be null when there is no plugin. -* ``controller`` The controller handling the current request. -* ``action`` The action handling the current request. -* ``prefix`` The prefix for the current action. See :ref:`prefix-routing` for - more information. -* ``bare`` Present when the request came from :php:meth:`~Cake\\Controller\\Controller::requestAction()` and included the - bare option. Bare requests do not have layouts rendered. -* ``requested`` Present and set to true when the action came from :php:meth:`~Cake\\Controller\\Controller::requestAction()`. - -Query String Parameters -======================= - -.. php:method:: query($name) - -Query string parameters can be read using :php:attr:`~Cake\\Network\\Request::$query`:: - - // URL is /posts/index?page=1&sort=title - $this->request->query['page']; - -You can either directly access the query property, or you can use -``query()`` method to read the URL query array in an error-free manner. -Any keys that do not exist will return ``null``:: - - $foo = $this->request->query('value_that_does_not_exist'); - // $foo === null - -Request Body Data -================= - -.. php:method:: data($name) - -All POST data can be accessed using :php:meth:`Cake\\Network\\Request::data()`. Any form data -that contains a ``data`` prefix will have that data prefix removed. For example:: - - // An input with a name attribute equal to 'MyModel[title]' is accessible at - $this->request->data('MyModel.title'); - -Any keys that do not exist will return ``null``:: - - $foo = $this->request->data('Value.that.does.not.exist'); - // $foo == null - -You can also access the array of data, as an array:: - - $this->request->data['title']; - $this->request->data['comments'][1]['author']; - -PUT, PATCH or DELETE Data -========================= - -.. php:method:: input($callback, [$options]) - -When building REST services, you often accept request data on ``PUT`` and -``DELETE`` requests. Any ``application/x-www-form-urlencoded`` request body data -will automatically be parsed and set to ``$this->data`` for ``PUT`` and -``DELETE`` requests. If you are accepting JSON or XML data, see below for how -you can access those request bodies. - -When accessing the input data, you can decode it with an optional function. -This is useful when interacting with XML or JSON request body content. -Additional parameters for the decoding function can be passed as arguments to -``input()``:: - - $this->request->input('json_decode'); - -Environment Variables (from $_SERVER and $_ENV) -=============================================== - -.. php:method:: env($key, $value = null) - -``Request::env()`` is a wrapper for ``env()`` global function and acts as -a getter/setter for enviroment variables without having to modify globals -``$_SERVER`` and ``$_ENV``:: - - // Get a value - $value = $this->request->env('HTTP_HOST'); - - // Set a value. Generally helpful in testing. - $this->request->env('REQUEST_METHOD', 'POST'); - -XML or JSON Data -================= - -Applications employing :doc:`/development/rest` often exchange data in non-URL-encoded -post bodies. You can read input data in any format using -:php:meth:`~Cake\\Network\\Request::input()`. By providing a decoding function, you can -receive the content in a deserialized format:: - - // Get JSON encoded data submitted to a PUT/POST action - $data = $this->request->input('json_decode'); - -Some deserializing methods require additional parameters when called, -such as the 'as array' parameter on ``json_decode``. If you want XML converted -into a DOMDocument object, :php:meth:`~Cake\\Network\\Request::input()` supports passing -in additional parameters as well:: - - // Get Xml encoded data submitted to a PUT/POST action - $data = $this->request->input('Xml::build', ['return' => 'domdocument']); - -Path Information -================ - -The request object also provides useful information about the paths in your -application. ``$request->base`` and ``$request->webroot`` are useful for -generating URLs, and determining whether or not your application is in -a subdirectory. The various properties you can use are:: - - // Assume the current request URL is /subdir/articles/edit/1?page=1 - - // Holds /subdir/articles/edit/1?page=1 - $request->here; - - // Holds /subdir - $request->base; - - // Holds /subdir/ - $request->webroot; - -.. _check-the-request: - -Checking Request Conditions -=========================== - -.. php:method:: is($type) - -The request object provides an easy way to inspect certain conditions in a given -request. By using the ``is()`` method you can check a number of common -conditions, as well as inspect other application specific request criteria:: - - $this->request->is('post'); - -You can also easily extend the request detectors that are available, by using -:php:meth:`Cake\\Network\\Request::addDetector()` to create new kinds of -detectors. There are four different types of detectors that you can create: - -* Environment value comparison - Compares a - value fetched from :php:func:`env()` for equality - with the provided value. -* Pattern value comparison - Pattern value comparison allows you to compare a - value fetched from :php:func:`env()` to a regular expression. -* Option based comparison - Option based comparisons use a list of options to - create a regular expression. Subsequent calls to add an already defined - options detector will merge the options. -* Callback detectors - Callback detectors allow you to provide a 'callback' type - to handle the check. The callback will receive the request object as its only - parameter. - -.. php:method:: addDetector($name, $options) - -Some examples would be:: - - // Add an environment detector. - $this->request->addDetector( - 'post', - ['env' => 'REQUEST_METHOD', 'value' => 'POST'] - ); - - // Add a pattern value detector. - $this->request->addDetector( - 'iphone', - ['env' => 'HTTP_USER_AGENT', 'pattern' => '/iPhone/i'] - ); - - // Add an option detector - $this->request->addDetector('internalIp', [ - 'env' => 'CLIENT_IP', - 'options' => ['192.168.0.101', '192.168.0.100'] - ]); - - // Add a callback detector. Can either be an anonymous function - // or a regular callable. - $this->request->addDetector( - 'awesome', - ['callback' => function ($request) { - return isset($request->awesome); - }] - ); - -``Request`` also includes methods like -:php:meth:`Cake\\Network\\Request::domain()`, -:php:meth:`Cake\\Network\\Request::subdomains()` and -:php:meth:`Cake\\Network\\Request::host()` to help applications with subdomains, -have a slightly easier life. - -There are several built-in detectors that you can use: - -* ``is('get')`` Check to see whether the current request is a GET. -* ``is('put')`` Check to see whether the current request is a PUT. -* ``is('post')`` Check to see whether the current request is a POST. -* ``is('delete')`` Check to see whether the current request is a DELETE. -* ``is('head')`` Check to see whether the current request is HEAD. -* ``is('options')`` Check to see whether the current request is OPTIONS. -* ``is('ajax')`` Check to see whether the current request came with - X-Requested-With = XMLHttpRequest. -* ``is('ssl')`` Check to see whether the request is via SSL -* ``is('flash')`` Check to see whether the request has a User-Agent of Flash -* ``is('mobile')`` Check to see whether the request came from a common list - of mobile agents. - - -Session Data -============ - -To access the session for a given request use the ``session()`` method:: - - $this->request->session()->read('User.name'); - -For more information, see the :doc:`/development/sessions` documentation for how -to use the session object. - -Host and Domain Name -==================== - -.. php:method:: domain($tldLength = 1) - -Returns the domain name your application is running on:: - - // Prints 'example.org' - echo $request->domain(); - -.. php:method:: subdomains($tldLength = 1) - -Returns the subdomains your application is running on as an array:: - - // Returns ['my', 'dev'] for 'my.dev.example.org' - $request->subdomains(); - -.. php:method:: host() - -Returns the host your application is on:: - - // Prints 'my.dev.example.org' - echo $request->host(); - -Working With HTTP Methods & Headers -=================================== - -.. php:method:: method() - -Returns the HTTP method the request was made with:: - - // Output POST - echo $request->method(); - -.. php:method:: allowMethod($methods) - -Set allowed HTTP methods. If not matched, will throw MethodNotAllowedException. -The 405 response will include the required ``Allow`` header with the passed methods - -.. php:method:: header($name) - -Allows you to access any of the ``HTTP_*`` headers that were used -for the request. For example:: - - $this->request->header('User-Agent'); - -would return the user agent used for the request. - -.. php:method:: referer($local = false) - -Returns the referring address for the request. - -.. php:method:: clientIp() - -Returns the current visitor's IP address. - -Trusting Proxy Headers -====================== - -If your application is behind a load balancer or running on a cloud service, you -will often get the load balancer host, port and scheme in your requests. Often -load balancers will also send ``HTTP-X-Forwarded-*`` headers with the original -values. The forwarded headers will not be used by CakePHP out of the box. To -have the request object use these headers set the ``trustProxy`` property to -true:: - - $this->request->trustProxy = true; - - // These methods will not use the proxied headers. - $this->request->port(); - $this->request->host(); - $this->request->scheme(); - $this->request->clientIp(); - -Checking Accept Headers -======================= - -.. php:method:: accepts($type = null) - -Find out which content types the client accepts, or check whether it accepts a -particular type of content. - -Get all types:: - - $this->request->accepts(); - -Check for a single type:: - - $this->request->accepts('application/json'); - -.. php:method:: acceptLanguage($language = null) - -Get all the languages accepted by the client, -or check whether a specific language is accepted. - -Get the list of accepted languages:: - - $this->request->acceptLanguage(); - -Check whether a specific language is accepted:: - - $this->request->acceptLanguage('es-es'); - -.. index:: $this->response - -Response -######## - -.. php:class:: Response - -:php:class:`Cake\\Network\\Response` is the default response class in CakePHP. It -encapsulates a number of features and functionality for generating HTTP -responses in your application. It also assists in testing, as it can be -mocked/stubbed allowing you to inspect headers that will be sent. -Like :php:class:`Cake\\Network\\Request`, :php:class:`Cake\\Network\\Response` consolidates a number -of methods previously found on :php:class:`Controller`, -:php:class:`RequestHandlerComponent` and :php:class:`Dispatcher`. The old -methods are deprecated in favour of using :php:class:`Cake\\Network\\Response`. - -``Response`` provides an interface to wrap the common response-related -tasks such as: - -* Sending headers for redirects. -* Sending content type headers. -* Sending any header. -* Sending the response body. - -Changing the Response Class -=========================== - -CakePHP uses ``Response`` by default. ``Response`` is a flexible and -transparent class. If you need to override it with your own application-specific class, -you can replace ``Response`` in ``webroot/index.php``. - -This will make all the controllers in your application use ``CustomResponse`` -instead of :php:class:`Cake\\Network\\Response`. You can also replace the response -instance by setting ``$this->response`` in your controllers. Overriding the -response object is handy during testing, as it allows you to stub -out the methods that interact with :php:meth:`~CakeResponse::header()`. See the section on -:ref:`cakeresponse-testing` for more information. - -Dealing with Content Types -========================== - -.. php:method:: type($contentType = null) - -You can control the Content-Type of your application's responses with -:php:meth:`Cake\\Network\\Response::type()`. If your application needs to deal with -content types that are not built into Response, you can map them -with ``type()`` as well:: - - // Add a vCard type - $this->response->type(['vcf' => 'text/v-card']); - - // Set the response Content-Type to vcard. - $this->response->type('vcf'); - -Usually, you'll want to map additional content types in your controller's -:php:meth:`~Controller::beforeFilter()` callback, so you can leverage the automatic view switching -features of :php:class:`RequestHandlerComponent` if you are using it. - -Setting the Character Set -========================= - -.. php:method:: charset($charset = null) - -Sets the charset that will be used in the response:: - - $this->response->charset('UTF-8'); - -.. _cake-response-file: - -Sending Files -============= - -.. php:method:: file($path, $options = []) - -There are times when you want to send files as responses for your requests. -You can accomplish that by using :php:meth:`Cake\\Network\\Response::file()`:: - - public function sendFile($id) - { - $file = $this->Attachment->getFile($id); - $this->response->file($file['path']); - // Return response object to prevent controller from trying to render - // a view. - return $this->response; - } - -As shown in the above example, you must pass the file path to the method. -CakePHP will send a proper content type header if it's a known file type listed in -`Cake\\Network\\Reponse::$_mimeTypes`. You can add new types prior to calling -:php:meth:`Cake\\Network\\Response::file()` by using the -:php:meth:`Cake\\Network\\Response::type()` method. - -If you want, you can also force a file to be downloaded instead of displayed in -the browser by specifying the options:: - - $this->response->file( - $file['path'], - ['download' => true, 'name' => 'foo'] - ); - -The supported options are: - -name - The name allows you to specify an alternate file name to be sent to - the user. -download - A boolean value indicating whether headers should be set to force - download. - -Sending a String as File -======================== - -You can respond with a file that does not exist on the disk, such as -a pdf or an ics generated on the fly from a string:: - - public function sendIcs() - { - $icsString = $this->Calendar->generateIcs(); - $this->response->body($icsString); - $this->response->type('ics'); - - // Optionally force file download - $this->response->download('filename_for_download.ics'); - - // Return response object to prevent controller from trying to render - // a view. - return $this->response; - } - -Setting Headers -=============== - -.. php:method:: header($header = null, $value = null) - -Setting headers is done with the :php:meth:`Cake\\Network\\Response::header()` method. It -can be called with a few different parameter configurations:: - - // Set a single header - $this->response->header('Location', 'http://example.com'); - - // Set multiple headers - $this->response->header([ - 'Location' => 'http://example.com', - 'X-Extra' => 'My header' - ]); - - $this->response->header([ - 'WWW-Authenticate: Negotiate', - 'Content-type: application/pdf' - ]); - -Setting the same :php:meth:`~CakeResponse::header()` multiple times will result in overwriting the previous -values, just as regular header calls. Headers are not sent when -:php:meth:`Cake\\Network\\Response::header()` is called; instead they are buffered -until the response is actually sent. - -You can now use the convenience method :php:meth:`Cake\\Network\\Response::location()` to directly set or get -the redirect location header. - -Interacting with Browser Caching -================================ - -.. php:method:: disableCache() - -You sometimes need to force browsers not to cache the results of a controller -action. :php:meth:`Cake\\Network\\Response::disableCache()` is intended for just that:: - - public function index() - { - // Do something. - $this->response->disableCache(); - } - -.. warning:: - - Using disableCache() with downloads from SSL domains while trying to send - files to Internet Explorer can result in errors. - -.. php:method:: cache($since, $time = '+1 day') - -You can also tell clients that you want them to cache responses. By using -:php:meth:`Cake\\Network\\Response::cache()`:: - - public function index() - { - // Do something. - $this->response->cache('-1 minute', '+5 days'); - } - -The above would tell clients to cache the resulting response for 5 days, -hopefully speeding up your visitors' experience. :php:meth:`CakeResponse::cache()` sets the -``Last-Modified`` value to the first argument. -``Expires`` header and the ``max-age`` directive are set based on the second parameter. -Cache-Control's ``public`` directive is set as well. - - -.. _cake-response-caching: - -Fine Tuning HTTP Cache -====================== - -One of the best and easiest ways of speeding up your application is to use HTTP -cache. Under this caching model, you are only required to help clients decide if -they should use a cached copy of the response by setting a few headers such as -modified time and response entity tag. - -Rather than forcing you to code the logic for caching and for invalidating (refreshing) -it once the data has changed, HTTP uses two models, expiration and validation, -which usually are much simpler to use. - -Apart from using :php:meth:`Cake\\Network\\Response::cache()`, you can also use many other -methods to fine-tune HTTP cache headers to take advantage of browser or reverse -proxy caching. - -The Cache Control Header ------------------------- - -.. php:method:: sharable($public = null, $time = null) - -Used under the expiration model, this header contains multiple indicators -that can change the way browsers or proxies use the cached content. A -``Cache-Control`` header can look like this:: - - Cache-Control: private, max-age=3600, must-revalidate - -``Response`` class helps you set this header with some utility methods that -will produce a final valid ``Cache-Control`` header. The first is the :php:meth:`Cake\\Network\\Response::sharable()` -method, which indicates whether a response is to be considered sharable across -different users or clients. This method actually controls the ``public`` -or ``private`` part of this header. Setting a response as private indicates that -all or part of it is intended for a single user. To take advantage of shared -caches, the control directive must be set as public. - -The second parameter of this method is used to specify a ``max-age`` for the cache, -which is the number of seconds after which the response is no longer considered -fresh:: - - public function view() - { - // ... - // Set the Cache-Control as public for 3600 seconds - $this->response->sharable(true, 3600); - } - - public function my_data() - { - // ... - // Set the Cache-Control as private for 3600 seconds - $this->response->sharable(false, 3600); - } - -``Response`` exposes separate methods for setting each of the directives in -the ``Cache-Control`` header. - -The Expiration Header ---------------------- - -.. php:method:: expires($time = null) - -You can set the ``Expires`` header to a date and time after which the response is -no longer considered fresh. This header can be set using the -:php:meth:`Cake\\Network\\Response::expires()` method:: - - public function view() - { - $this->response->expires('+5 days'); - } - -This method also accepts a :php:class:`DateTime` instance or any string that can be parsed by the -:php:class:`DateTime` class. - -The Etag Header ---------------- - -.. php:method:: etag($tag = null, $weak = false) - -Cache validation in HTTP is often used when content is constantly changing, and -asks the application to only generate the response contents if the cache is no -longer fresh. Under this model, the client continues to store pages in the -cache, but it asks the application every time -whether the resource has changed, instead of using it directly. -This is commonly used with static resources such as images and other assets. - -The :php:meth:`~CakeResponse::etag()` method (called entity tag) is a string that uniquely identifies the -requested resource, as a checksum does for a file, in order to determine whether -it matches a cached resource. - -To take advantage of this header, you must either call the -:php:meth:`Cake\\Network\\Response::checkNotModified()` method manually or include the -:php:class:`RequestHandlerComponent` in your controller:: - - public function index() - { - $articles = $this->Article->find('all'); - $this->response->etag($this->Article->generateHash($articles)); - if ($this->response->checkNotModified($this->request)) { - return $this->response; - } - // ... - } - -The Last Modified Header ------------------------- - -.. php:method:: modified($time = null) - -Also, under the HTTP cache validation model, you can set the ``Last-Modified`` -header to indicate the date and time at which the resource was modified for the -last time. Setting this header helps CakePHP tell caching clients whether -the response was modified or not based on their cache. - -To take advantage of this header, you must either call the -:php:meth:`Cake\\Network\\Response::checkNotModified()` method or include the -:php:class:`RequestHandlerComponent` in your controller:: - - public function view() - { - $article = $this->Article->find('first'); - $this->response->modified($article['Article']['modified']); - if ($this->response->checkNotModified($this->request)) { - return $this->response; - } - // ... - } - -The Vary Header ---------------- - -.. php:method:: vary($header) - -In some cases, you might want to serve different content using the same URL. -This is often the case if you have a multilingual page or respond with different -HTML depending on the browser. Under such circumstances you can use the ``Vary`` header:: - - $this->response->vary('User-Agent'); - $this->response->vary('Accept-Encoding', 'User-Agent'); - $this->response->vary('Accept-Language'); - -Sending Not-Modified Responses ------------------------------- - -.. php:method:: checkNotModified(Request $request) - -Compares the cache headers for the request object with the cache header from -the response and determines whether it can still be considered fresh. If so, -deletes the response content, and sends the `304 Not Modified` header:: - - // In a controller action. - if ($this->response->checkNotModfied($this->request)) { - return $this->response; - } - -Sending the Response -==================== - -.. php:method:: send() - -Once you are done creating a response, calling ``send()`` will send all -the set headers as well as the body. This is done automatically at the -end of each request by ``Dispatcher``. - - -.. _cakeresponse-testing: - -Response and Testing -==================== - -The ``Response`` class helps make testing controllers and components easier. -By having a single place to mock/stub headers you can more easily test -controllers and components:: - - public function testSomething() - { - $this->controller->response = $this->getMock('Cake\Network\Response'); - $this->controller->response->expects($this->once())->method('header'); - // ... - } - -Additionally, you can run tests from the command line more easily, as you can use -mocks to avoid the 'headers sent' errors that can occur when trying to set -headers in CLI. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Request and Response objects - :keywords lang=en: request controller,request parameters,array indexes,purpose index,response objects,domain information,request object,request data,interrogating,params,previous versions,introspection,dispatcher,rout,data structures,arrays,ip address,migration,indexes,cakephp + :title lang=es: Request and Response objects + :keywords lang=es: request controller,request parameters,array indexes,purpose index,response objects,domain information,request object,request data,interrogating,params,previous versions,introspection,dispatcher,rout,data structures,arrays,ip address,migration,indexes,cakephp diff --git a/es/core-libraries/app.rst b/es/core-libraries/app.rst new file mode 100644 index 0000000000000000000000000000000000000000..6a1f4f2237d8eb1883f360e3595f624d85760860 --- /dev/null +++ b/es/core-libraries/app.rst @@ -0,0 +1,15 @@ +App Class +######### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: App Class + :keywords lang=es: compatible implementation,model behaviors,path management,loading files,php class,class loading,model behavior,class location,component model,management class,autoloader,classname,directory location,override,conventions,lib,textile,cakephp,php classes,loaded diff --git a/es/core-libraries/behaviors/counter-cache.rst b/es/core-libraries/behaviors/counter-cache.rst deleted file mode 100644 index a96dc9cafaeb8b8dc6058e09dba1b2927450f103..0000000000000000000000000000000000000000 --- a/es/core-libraries/behaviors/counter-cache.rst +++ /dev/null @@ -1,81 +0,0 @@ -CounterCache Behavior -##################### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Model\Behavior - -.. php:class:: CounterCacheBehavior - -Often times web applications need to display counts of related objects. For -example, when showing a list of articles you may want to display how many -comments it has. Or when showing a user you might want to show how many -friends/followers she has. The CounterCache behavior is intended for these -situations. - -Basic Usage -=========== - -You enable the CounterCache behavior like any other behavior, but it won't do -anything until you configure some relations and the field counts that should be -stored on each of them. Using our example below, we could cache the comment -count for each article with the following:: - - class CommentsTable extends Table - { - public function initialize(array $config) - { - $this->addBehavior('CounterCache', [ - 'Articles' => ['comment_count'] - ]); - } - } - -The CounterCache configuration should be a map of relation names and the -specific configuration for that relation. - -The counter's value will be updated each time an entity is saved or deleted. The -counter **will not** be updated when you use ``updateAll()`` or ``deleteAll()``, -or execute SQL you have written. - -Advanced Usage -============== - -If you need to keep a cached counter for less than all of the related records, -you can supply additional conditions or finder methods to generate a -counter value:: - - // Use a specific find method. - // In this case find(published) - $this->addBehavior('CounterCache', [ - 'Articles' => [ - 'comment_count' => [ - 'findType' => 'published' - ] - ] - ]); - -If you don't have a custom finder method you can provide an array of conditions -to find records instead:: - - $this->addBehavior('CounterCache', [ - 'Articles' => [ - 'comment_count' => [ - 'conditions' => ['Comments.spam' => false] - ] - ] - ]); - -Lastly, if a custom finder and conditions are not suitable you can provide -a callback method. This callable must return the count value to be stored:: - - $this->addBehavior('CounterCache', [ - 'Articles' => [ - 'rating_avg' => function ($event, $entity, $table) { - return 4.5; - } - ] - ]); diff --git a/es/core-libraries/behaviors/timestamp.rst b/es/core-libraries/behaviors/timestamp.rst deleted file mode 100644 index c5426b999e088ff59e83790fabdcfe64ba8ce0c4..0000000000000000000000000000000000000000 --- a/es/core-libraries/behaviors/timestamp.rst +++ /dev/null @@ -1,80 +0,0 @@ -Timestamp Behavior -################## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Model\Behavior - -.. php:class:: TimestampBehavior - -The timestamp behavior allows your table objects to update one or more -timestamps on each model event. This is primarily used to populate data into -``created`` and ``modified`` fields. However, with some additional -configuration, you can update any timestamp/datetime column on any event a table -publishes. - -Basic Usage -=========== - -You enable the timestamp behavior like any other behavior:: - - class ArticlesTable extends Table - { - public function initialize(array $config) - { - $this->addBehavior('Timestamp'); - } - } - -The default configuration will do the following: - -- When a new entity is saved the ``created`` and ``modified`` fields will be set - to the current time. -- When an entity is updated, the ``modified`` field is set to the current time. - -Using and Configuring the Behavior -================================== - -If you need to modify fields with different names, or want to update additional -timestamp fields on custom events you can use some additional configuration:: - - class OrdersTable extends Table - { - public function initialize(array $config) - { - $this->addBehavior('Timestamp', [ - 'events' => [ - 'Model.beforeSave' => [ - 'created_at' => 'new', - 'updated_at' => 'always', - ], - 'Orders.completed' => [ - 'completed_at' => 'always' - ] - ] - ]); - } - } - -As you can see above, in addition to the standard ``Model.beforeSave`` event, we -are also updating the ``completed_at`` column when orders are completed. - -Updating Timestamps on Entities -=============================== - -Sometimes you'll want to update just the timestamps on an entity without -changing any other properties. This is sometimes referred to as 'touching' -a record. In CakePHP you can use the ``touch()`` method to do exactly this:: - - // Touch based on the Model.beforeSave event. - $articles->touch($article); - - // Touch based on a specific event. - $orders->touch($order, 'Orders.completed'); - -Touching records can be useful when you want to signal that a parent resource -has changed when a child resource is created/updated. For example: updating an -article when a new comment is added. diff --git a/es/core-libraries/behaviors/translate.rst b/es/core-libraries/behaviors/translate.rst deleted file mode 100644 index d73d7446fc654b423b071ac2a960acd35f841b03..0000000000000000000000000000000000000000 --- a/es/core-libraries/behaviors/translate.rst +++ /dev/null @@ -1,336 +0,0 @@ -Translate -######### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Model\Behavior - -.. php:class:: TranslateBehavior - -The Translate behavior allows you to create and retrieve translated copies -of your entities in multiple languages. It does so by using a separate -``i18n`` table where it stores the translation for each of the fields of any -given Table object that it's bound to. - -.. warning:: - - The TranslateBehavior does not support composite primary keys at this point - in time. - -A Quick Tour -============ - -After creating the ``i18n`` table in your database attach the behavior to any -Table object you want to make translatable:: - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->addBehavior('Translate', ['fields' => ['title']]); - } - } - -Now, select a language to be used for retrieving entities:: - - $articles = TableRegistry::get('Articles'); - $articles->locale('spa'); - -Then, get an existing entity:: - - $article = $articles->get(12); - echo $article->title; // Echoes 'A title', not translated yet - -Next, translate your entity:: - - $article->title = 'Un Artículo'; - $articles->save($article); - -You can try now getting your entity again:: - - $article = $articles->get(12); - echo $article->title; // Echoes 'Un Artículo', yay piece of cake! - -Working with multiple translations can be done easily by using a special trait -in your Entity class:: - - use Cake\Model\Behavior\Translate\TranslateTrait; - use Cake\ORM\Entity; - - class Article extends Entity - { - use TranslateTrait; - } - -Now you can find all translations for a single entity:: - - $article = $articles->find('translations')->first(); - echo $article->translation('spa')->title; // 'Un Artículo' - - echo $article->translation('eng')->title; // 'An Article'; - -It is equally easy to save multiple translations at once:: - - $article->translation('spa')->title = 'Otro Título'; - $article->translation('fre')->title = 'Un autre Titre'; - $articles->save($articles); - -Yes, that easy. If you want to go deeper on how it works or how to tune the -behavior for your needs, keep on reading the rest of this chapter. - -Initializing the i18n Database Table -==================================== - -In order to use the behavior, you need to create a ``i18n`` table with the -correct schema. Currently the only way of loading the ``i18n`` table is by -manually running the following SQL script in your database: - -.. code-block:: sql - - CREATE TABLE i18n ( - id int NOT NULL auto_increment, - locale varchar(6) NOT NULL, - model varchar(255) NOT NULL, - foreign_key int(10) NOT NULL, - field varchar(255) NOT NULL, - content text, - PRIMARY KEY (id), - UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field), - INDEX I18N_FIELD(model, foreign_key, field) - ); - - -Attaching the Translate Behavior to Your Tables -=============================================== - -Attaching the behavior can be done in the ``initialize`` method in your Table -class:: - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->addBehavior('Translate', ['fields' => ['title', 'body']]); - } - } - -The first thing to note is that you are required to pass the ``fields`` key in -the configuration array. This list of fields is needed to tell the behavior what -columns will be able to store translations. - -Using a Separate Translations Table ------------------------------------ - -If you wish to use a table other than ``i18n`` for translating a particular -repository, you can specify it in the behavior's configuration. This is common -when you have multiple tables to translate and you want a cleaner separation -of the data that is stored for each different table:: - - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->addBehavior('Translate', [ - 'fields' => ['title', 'body'], - 'translationTable' => 'ArticlesI18n' - ]); - } - } - -You need to make sure that any custom table you use has the columns ``field``, -``foreign_key``, ``locale`` and ``model``. - -Reading Translated Content -========================== - -As shown above you can use the ``locale`` method to choose the active -translation for entities that are loaded:: - - $articles = TableRegistry::get('Articles'); - $articles->locale('spa'); - - // All entities in results will contain spanish translation - $results = $articles->find()->all(); - -The locale method works with any finder in your tables. For example, you can -use TranslateBehavior with ``find('list')``:: - - $articles->locale('spa'); - $data = $articles->find('list')->toArray(); - - // Data will contain - [1 => 'Mi primer artículo', 2 => 'El segundo artículo', 15 => 'Otro articulo' ...] - -Retrieve All Translations For An Entity ---------------------------------------- - -When building interfaces for updating translated content, it is often helpful to -show one or more translation(s) at the same time. You can use the -``translations`` finder for this:: - - // Find the first article with all corresponding translations - $article = $articles->find('translations')->first(); - -In the example above you will get a list of entities back that have a -``_translations`` property set. This property will contain a list of translation -data entities. For example the following properties would be accessible:: - - // Outputs 'eng' - echo $article->_translations['eng']->locale; - - // Outputs 'title' - echo $article->_translations['eng']->field; - - // Outputs 'My awesome post!' - echo $article->_translations['eng']->body; - -A more elegant way for dealing with this data is by adding a trait to the entity -class that is used for your table:: - - use Cake\Model\Behavior\Translate\TranslateTrait; - use Cake\ORM\Entity; - - class Article extends Entity - { - use TranslateTrait; - } - -This trait contains a single method called ``translation``, which lets you -access or create new translation entities on the fly:: - - // Outputs 'title' - echo $article->translation('eng')->title; - - // Adds a new translation data entity to the article - $article->translation('deu')->title = 'Wunderbar'; - -Limiting the Translations to be Retrieved ------------------------------------------ - -You can limit the languages that are fetched from the database for a particular -set of records:: - - $results = $articles->find('translations', ['locales' => ['eng', 'spa']]); - $article = $results->first(); - $spanishTranslation = $article->translation('spa'); - $englishTranslation = $article->translation('eng'); - -Retrieving All Translations For Associations --------------------------------------------- - -It is also possible to find translations for any association in a single find -operation:: - - $article = $articles->find('translations')->contain([ - 'Categories' => function ($query) { - return $query->find('translations'); - } - ])->first(); - - // Outputs 'Programación' - echo $article->categories[0]->translation('spa')->name; - -This assumes that ``Categories`` has the TranslateBehavior attached to it. It -simply uses the query builder function for the ``contain`` clause to use the -``translations`` custom finder in the association. - -Saving in Another Language -========================== - -The philosophy behind the TranslateBehavior is that you have an entity -representing the default language, and multiple translations that can override -certain fields in such entity. Keeping this in mind, you can intuitively save -translations for any given entity. For example, given the following setup:: - - class ArticlesTable extends Table - { - public function initialize(array $config) - { - $this->addBehavior('Translate', ['fields' => ['title', 'body']]); - } - } - - class Article extends Entity - { - use TranslateTrait; - } - - $articles = TableRegistry::get('Articles'); - $article = new Article([ - 'title' => 'My First Article', - 'body' => 'This is the content', - 'footnote' => 'Some afterwords' - ]); - - $articles->save($article); - -So, after you save your first article, you can now save a translation for it, -there are a couple ways to do it. The first one is setting the language directly -into the entity:: - - $article->_locale = 'spa'; - $article->title = 'Mi primer Artículo'; - - $articles->save($article); - -After the entity has been saved, the translated field will be persisted as well, -one thing to note is that values from the default language that were not -overridden will be preserved:: - - // Outputs 'This is the content' - echo $article->body; - - // Outputs 'Mi primer Artículo' - echo $article->title; - -Once you override the value, the translation for that field will be saved and -can be retrieved as usual:: - - $article->body = 'El contendio'; - $articles->save($article); - -The second way to use for saving entities in another language is to set the -default language directly to the table:: - - $articles->locale('spa'); - $article->title = 'Mi Primer Artículo'; - $articles->save($article); - -Setting the language directly in the table is useful when you need to both -retrieve and save entities for the same language or when you need to save -multiple entities at once. - -Saving Multiple Translations -============================ - -It is a common requirement to be able to add or edit multiple translations to -any database record at the same time. This can be easily done using the -``TranslateTrait``:: - - use Cake\Model\Behavior\Translate\TranslateTrait; - use Cake\ORM\Entity; - - class Article extends Entity - { - use TranslateTrait; - } - -Now, You can populate translations before saving them:: - - $translations = [ - 'fra' => ['title' => "Un article"], - 'spa' => ['title' => 'Un artículo'] - ]; - - foreach ($translations as $lang => $data) { - $article->translation($lang)->set($data, ['guard' => false]); - } - - $articles->save($article); diff --git a/es/core-libraries/behaviors/tree.rst b/es/core-libraries/behaviors/tree.rst deleted file mode 100644 index 18f33d1af8f908652067ebf1c413845da5aff6cd..0000000000000000000000000000000000000000 --- a/es/core-libraries/behaviors/tree.rst +++ /dev/null @@ -1,232 +0,0 @@ -TreeBehavior -############ - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Model\Behavior - -.. php:class:: TreeBehavior - -It's fairly common to want to store hierarchical data in a database -table. Examples of such data might be categories with unlimited -subcategories, data related to a multilevel menu system or a -literal representation of hierarchy such as a departments in company. - -Relational databases are usually not well suited for storing and retrieving this -type of data, but there are a few known techniques that can make them effective -for working with multi-level information. - -The TreeBehavior helps you maintain a hierarchical data structure in the -database that can be queried without much overhead and helps reconstruct the -tree data for finding and displaying processes. - -Requirements -============ - -This behavior requires the following columns in your table: - -- ``parent_id`` (nullable) The column holding the ID of the parent row -- ``lft`` (integer) Used to maintain the tree structure -- ``rght`` (integer) Used to maintain the tree structure - -You can configure the name of those fields should you need to customize them. -More information on the meaning of the fields and how they are used can be found -in this article describing the `MPTT logic `_ - -.. warning:: - - The TreeBehavior does not support composite primary keys at this point in - time. - -A Quick Tour -============ - -You enable the Tree behavior by adding it to the Table you want to store -hierarchical data in:: - - class CategoriesTable extends Table - { - public function initialize(array $config) - { - $this->addBehavior('Tree'); - } - } - -Once added, you can let CakePHP build the internal structure if the table is -already holding some rows:: - - $categories = TableRegistry::get('Categories'); - $categories->recover(); - -You can verify it works by getting any row from the table and asking for the -count of descendants it has:: - - $node = $categories->get(1); - echo $categories->childCount($node); - -Getting a flat list of the descendants for a node is equally easy:: - - $descendants = $categories->find('children', ['for' => 1]); - - foreach ($descendants as $category) { - echo $category->name . "\n"; - } - -If you instead need a threaded list, where children for each node are nested -in a hierarchy, you can stack the 'threaded' finder:: - - $children = $categories - ->find('children', ['for' => 1]) - ->find('threaded') - ->toArray(); - - foreach ($children as $child) { - echo "{$child->name} has " . count($child->children) . " direct children"; - } - -Traversing threaded results usually requires recursive functions in, but if you -only require a result set containing a single field from each level so you can -display a list, in an HTML select for example, it is better to use the -'treeList' finder:: - - $list = $categories->find('treeList'); - - // In a CakePHP template file: - echo $this->Form->input('categories', ['options' => $list]); - - // Or you can output it in plain text, for example in a CLI script - foreach ($list as $categoryName) { - echo $categoryName . "\n"; - } - -The output will be similar to:: - - My Categories - _Fun - __Sport - ___Surfing - ___Skating - _Trips - __National - __International - -One very common task is to find the tree path from a particular node to the root -of the tree. This is useful, for example, for adding the breadcrumbs list for -a menu structure:: - - $nodeId = 5; - $crumbs = $categories->find('path', ['for' => $nodeId]); - - foreach ($crumbs as $crumb) { - echo $crumb->name . ' > '; - } - -Trees constructed with the TreeBehavior cannot be sorted by any column other -than ``lft``, this is because the internal representation of the tree depends on -this sorting. Luckily, you can reorder the nodes inside the same level without -having to change their parent:: - - $node = $categories->get(5); - - // Move the node so it shows up one position up when listing children. - $categories->moveUp($node); - - // Move the node to the top of the list inside the same level. - $categories->moveUp($node, true); - - // Move the node to the bottom. - $categories->moveDown($node, true); - -Configuration -============= - -If the default column names that are used by this behavior don't match your own -schema, you can provide aliases for them:: - - public function initialize(array $config) - { - $this->addBehavior('Tree', [ - 'parent' => 'ancestor_id', // Use this instead of parent_id, - 'left' => 'tree_left', // Use this instead of lft - 'right' => 'tree_right' // Use this instead of rght - ]); - } - -Scoping and Multi Trees -======================= - -Sometimes you want to persist more than one tree structure inside the same -table, you can achieve that by using the 'scope' configuration. For example, in -a locations table you may want to create one tree per country:: - - class LocationsTable extends Table - { - - public function initialize(array $config) - { - $this->addBehavior('Tree', [ - 'scope' => ['country_name' => 'Brazil'] - ]); - } - - } - -In the previous example, all tree operations will be scoped to only the rows -having the column ``country_name`` set to 'Brazil'. You can change the scoping -on the fly by using the 'config' function:: - - $this->behaviors()->Tree->config('scope', ['country_name' => 'France']); - -Optionally, you can have a finer grain control of the scope by passing a closure -as the scope:: - - $this->behaviors()->Tree->config('scope', function($query) { - $country = $this->getConfigureContry(); // A made-up function - return $query->where(['country_name' => $country]); - }); - -Saving Hierarchical Data -======================== - -When using the Tree behavior, you usually don't need to worry about the -internal representation of the hierarchical structure. The positions where nodes -are placed in the tree are deduced from the 'parent_id' column in each of your -entities:: - - $aCategory = $categoriesTable->get(10); - $aCategory->parent_id = 5; - $categoriesTable->save($aCategory); - -Providing inexistent parent ids when saving or attempting to create a loop in -the tree (making a node child of itself) will throw an exception. - -You can make a node a root in the tree by setting the 'parent_id' column to -null:: - - $aCategory = $categoriesTable->get(10); - $aCategory->parent_id = null; - $categoriesTable->save($aCategory); - -Children for the new root node will be preserved. - -Deleting Nodes -============== - -Deleting a node and all its sub-tree (any children it may have at any depth in -the tree) is trivial:: - - $aCategory = $categoriesTable->get(10); - $categoriesTable->delete($aCategory); - -The TreeBehavior will take care of all internal deleting operations for you. It -is also possible to Only delete one node and re-assign all children to the -immediately superior parent node in the tree:: - - $aCategory = $categoriesTable->get(10); - $categoriesTable->removeFromTree($aCategory); - $categoriesTable->delete($aCategory); - -All children nodes will be kept and a new parent will be assigned to them. diff --git a/es/core-libraries/caching.rst b/es/core-libraries/caching.rst index 3a592f19a56b9305e33cb423b44f053ac1518172..6bb1c5fa9382726e7fc8d0d74d8bf8a783670fd1 100644 --- a/es/core-libraries/caching.rst +++ b/es/core-libraries/caching.rst @@ -2,511 +2,14 @@ Caching ####### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -.. php:namespace:: Cake\Cache - -.. php:class:: Cache - -Caching is frequently used to reduce the time it takes to create or read from -other resources. Caching is often used to make reading from expensive -resources less expensive. You can easily store the results of expensive queries, -or remote webservice access that doesn't frequently change in a cache. Once -in the cache, re-reading the stored resource from the cache is much cheaper -than accessing the remote resource. - -Caching in CakePHP is primarily facilitated by the ``Cache`` class. -This class provides a set of static methods that provide a uniform API to -dealing with all different types of Caching implementations. CakePHP -comes with several cache engines built-in, and provides an easy system -to implement your own caching systems. The built-in caching engines are: - -* ``FileCache`` File cache is a simple cache that uses local files. It - is the slowest cache engine, and doesn't provide as many features for - atomic operations. However, since disk storage is often quite cheap, - storing large objects, or elements that are infrequently written - work well in files. -* ``ApcCache`` APC cache uses the PHP `APC `_ extension. - This extension uses shared memory on the webserver to store objects. - This makes it very fast, and able to provide atomic read/write features. -* ``Wincache`` Wincache uses the `Wincache `_ - extension. Wincache is similar to APC in features and performance, but - optimized for Windows and IIS. -* ``XcacheEngine`` `Xcache `_ - is a PHP extension that provides similar features to APC. -* ``MemcachedEngine`` Uses the `Memcached `_ - extension. It also interfaces with memcache but provides better performance. -* ``RedisEngine`` Uses the `phpredis `_ - extension. Redis provides a fast and persistent cache system similar to - memcached, also provides atomic operations. - -Regardless of the CacheEngine you choose to use, your application interacts with -:php:class:`Cake\\Cache\\Cache` in a consistent manner. This means you can -easily swap cache engines as your application grows. - -.. _cache-configuration: - -Configuring Cache Class -======================= - -.. php:staticmethod:: config($key, $config = null) - -Configuring the Cache class can be done anywhere, but generally you will want to -configure Cache during bootstrapping. The ``config/app.php`` file is the -conventional location to do this. You can configure as many cache -configurations as you need, and use any mixture of cache engines. CakePHP uses -two cache configurations internally. ``_cake_core_`` is used for storing file -maps, and parsed results of -:doc:`/core-libraries/internationalization-and-localization` files. -``_cake_model_``, is used to store schema descriptions for your applications -models. If you are using APC or Memcached you should make sure to set unique keys -for the core caches. This will prevent multiple applications from overwriting -each other's cached data. - -Using multiple configurations also lets you incrementally change the storage as -needed. Example:: - - // Using a short name - Cache::config('short', array( - 'className' => 'File', - 'duration' => '+1 hours', - 'path' => CACHE, - 'prefix' => 'cake_short_' - )); - - // Using a fully namespaced name. - Cache::config('long', array( - 'className' => 'Cake\Cache\Engine\FileEngine', - 'duration' => '+1 week', - 'probability' => 100, - 'path' => CACHE . 'long' . DS, - )); - - // Using a constructed object. - $object = new FileEngine($config); - Cache::config('other', $object); - -.. note:: - - You must specify which className to use. It does **not** default to - File. - -By placing the above code in your ``config/app.php`` you will have two -additional Cache configurations. The name of these configurations 'short' or -'long' is used as the ``$config`` parameter for -:php:meth:`Cake\\Cache\\Cache::write()` and -:php:meth:`Cake\\Cache\\Cache::read()`. When configuring Cache engines you can -refer to the class name using the following syntaxes: - -* Short classname without 'Engine' or a namespace. This will infer that you - want to use a Cache engine in ``Cake\Cache\Engine`` or ``App\Cache\Engine``. -* Using :term:`plugin syntax` which allows you to load engines from a specific - plugin. -* Using a fully qualified namespaced classname. This allows you to use - classes located outside of the conventional locations. -* Using an object that extends the ``CacheEngine`` class. - -Removing Configured Cache Engines ---------------------------------- - -.. php:staticmethod:: drop($key) - -Once a configuration is created you cannot change it. Instead you should drop -the configuration and re-create it using :php:meth:`Cake\\Cache\\Cache::drop()` and -:php:meth:`Cake\\Cache\\Cache::config()`. Dropping a cache engine will remove -the config and destroy the adapter if it was constructed. - -Other Cache Related Configuration ---------------------------------- - -Other than configuring caching adapters, there are a few other cache related -configuration properties: - -enabled - When set to true, persistent caching is disabled site-wide. - This will make all read/writes to :php:class:`Cake\\Cache\\Cache` fail. - You can control this value with :php:meth:`Cake\\Cache\\Cache::enable()` and - :php:meth:`Cake\\Cache\\Cache::disable()`. The current state can be read with - :php:meth:`Cake\\Cache\\Cache::enabled()`. - -.. note:: - - When using the FileEngine you might need to use the ``mask`` option to - ensure cache files are made with the correct permissions. - -Writing to a Cache -================== - -.. php:staticmethod:: write($key, $value, $config = 'default') - -``Cache::write()`` will write a $value to the Cache. You can read or -delete this value later by referring to it by ``$key``. You may -specify an optional configuration to store the cache in as well. If -no ``$config`` is specified, default will be used. ``Cache::write()`` -can store any type of object and is ideal for storing results of -model finds:: - - if (($posts = Cache::read('posts')) === false) { - $posts = $someService->getAllPosts(); - Cache::write('posts', $posts); - } - -Using ``Cache::write()`` and ``Cache::read()`` to easily reduce the number -of trips made to the database to fetch posts. - -.. note:: - - If you plan to cache the result of queries made with the CakePHP ORM, - it is better to use the built-in cache capabilities of the Query object - as described in the :ref:`caching-query-results` section - -Writing Multiple Keys at Once ------------------------------ - -.. php:staticmethod:: writeMany($data, $config = 'default') - -You may find yourself needing to write multiple cache keys at once. While you -can use multiple calls to ``write()``, ``writeMany()`` allows CakePHP to use -more efficient storage API's where available. For example using ``writeMany()`` -save multiple network connections when using Memcached:: - - $result = Cache::writeMany([ - 'article-' . $slug => $article, - 'article-' . $slug . '-comments' => $comments - ]); - - // $result will contain - ['article-first-post' => true, 'article-first-post-comments' => true] - -Read Through Caching --------------------- - -.. php:staticmethod:: remember($key, $callable, $config = 'default') - -Cache makes it easy to do read-through caching. If the named cache key exists, -it will be returned. If the key does not exist, the callable will be invoked -and the results stored in the cache at the provided key. - -For example, you often want to cache remote service call results. You could use -``remember()`` to make this simple:: - - class IssueService - { - - function allIssues($repo) - { - return Cache::remember($repo . '-issues', function() use ($repo) { - return $this->fetchAll($repo); - }); - } - - } - - -Reading From a Cache -==================== - -.. php:staticmethod:: read($key, $config = 'default') - -``Cache::read()`` is used to read the cached value stored under -``$key`` from the ``$config``. If $config is null the default -config will be used. ``Cache::read()`` will return the cached value -if it is a valid cache or ``false`` if the cache has expired or -doesn't exist. The contents of the cache might evaluate false, so -make sure you use the strict comparison operators: ``===`` or -``!==``. - -For example:: - - $cloud = Cache::read('cloud'); - - if ($cloud !== false) { - return $cloud; - } - - // Generate cloud data - // ... - - // Store data in cache - Cache::write('cloud', $cloud); - return $cloud; - -Reading Multiple Keys at Once ------------------------------ - -.. php:staticmethod:: readMany($keys, $config = 'default') - -After you've written multiple keys at once, you'll probably want to read them as -well. While you could use multiple calls to ``read()``, ``readMany()`` allows -CakePHP to use more efficient storage API's where available. For example using -``readMany()`` save multiple network connections when using Memcached:: - - $result = Cache::readMany([ - 'article-' . $slug, - 'article-' . $slug . '-comments' - ]); - // $result will contain - ['article-first-post' => '...', 'article-first-post-comments' => '...'] - - -Deleting From a Cache -===================== - -.. php:staticmethod:: delete($key, $config = 'default') - -``Cache::delete()`` will allow you to completely remove a cached -object from the store:: - - // Remove a key - Cache::delete('my_key'); - -Deleting Multiple Keys at Once ------------------------------- - -.. php:staticmethod:: deleteMany($keys, $config = 'default') - -After you've written multiple keys at once, you may want to delete them. While -you could use multiple calls to ``delete()``, ``deleteMany()`` allows CakePHP to use -more efficient storage API's where available. For example using ``deleteMany()`` -save multiple network connections when using Memcached:: - - $result = Cache::deleteMany([ - 'article-' . $slug, - 'article-' . $slug . '-comments' - ]); - // $result will contain - ['article-first-post' => true, 'article-first-post-comments' => true] - - -Clearing Cached Data -==================== - -.. php:staticmethod:: clear($check, $config = 'default') - -Destroy all cached values for a cache configuration. In engines like Apc, -Memcached and Wincache, the cache configuration's prefix is used to remove -cache entries. Make sure that different cache configurations have different -prefixes:: - - // Will only clear expired keys. - Cache::clear(true); - - // Will clear all keys. - Cache::clear(false); - - -.. php:staticmethod:: gc($config) - -Garbage collects entries in the cache configuration. This is primarily -used by FileEngine. It should be implemented by any Cache engine -that requires manual eviction of cached data. - -Using Cache to Store Counters -============================= - -.. php:staticmethod:: increment($key, $offset = 1, $config = 'default') - -.. php:staticmethod:: decrement($key, $offset = 1, $config = 'default') - -Counters for various things are easily stored in a cache. For example, a simple -countdown for remaining 'slots' in a contest could be stored in Cache. The -Cache class exposes atomic ways to increment/decrement counter values in an easy -way. Atomic operations are important for these values as it reduces the risk of -contention, and ability for two users to simultaneously lower the value by one, -resulting in an incorrect value. - -After setting an integer value you can manipulate it using ``increment()`` and -``decrement()``:: - - Cache::write('initial_count', 10); - - // Later on - Cache::decrement('initial_count'); - - // Or - Cache::increment('initial_count'); - -.. note:: - - Incrementing and decrementing do not work with FileEngine. You should use - APC, Wincache, Redis or Memcached instead. - - -Using Cache to Store Common Query Results -========================================= - -You can greatly improve the performance of your application by putting results -that infrequently change, or that are subject to heavy reads into the cache. -A perfect example of this are the results from -:php:meth:`Cake\\ORM\\Table::find()`. The Query object allows you to cache -results using the ``cache`` method. See the :ref:`caching-query-results` section -for more information. - -Using Groups -============ - -Sometimes you will want to mark multiple cache entries to belong to certain -group or namespace. This is a common requirement for mass-invalidating keys -whenever some information changes that is shared among all entries in the same -group. This is possible by declaring the groups in cache configuration:: - - Cache::config('site_home', [ - 'className' => 'Redis', - 'duration' => '+999 days', - 'groups' => ['comment', 'article'] - ]); - -.. php:method:: clearGroup($group, $config = 'default') - -Let's say you want to store the HTML generated for your homepage in cache, but -would also want to automatically invalidate this cache every time a comment or -post is added to your database. By adding the groups ``comment`` and ``article``, -we have effectively tagged any key stored into this cache configuration with -both group names. - -For instance, whenever a new post is added, we could tell the Cache engine to -remove all entries associated to the ``article`` group:: - - // src/Model/Table/ArticlesTable.php - public function afterSave($entity, $options = []) - { - if ($entity->isNew()) { - Cache::clearGroup('article', 'site_home'); - } - } - -.. php:staticmethod:: groupConfigs($group = null) - -``groupConfigs()`` can be used to retrieve mapping between group and -configurations, i.e.: having the same group:: - - // src/Model/Table/ArticlesTable.php - - /** - * A variation of previous example that clears all Cache configurations - * having the same group - */ - public function afterSave($entity, $options = []) - { - if ($entity->isNew()) { - $configs = Cache::groupConfigs('article'); - foreach ($configs['article'] as $config) { - Cache::clearGroup('article', $config); - } - } - } - -Groups are shared across all cache configs using the same engine and same -prefix. If you are using groups and want to take advantage of group deletion, -choose a common prefix for all your configs. - -Globally Enable or Disable Cache -================================ - -.. php:staticmethod:: disable() - -You may need to disable all Cache read & writes when trying to figure out cache -expiration related issues. You can do this using ``enable()`` and -``disable()``:: - - // Disable all cache reads, and cache writes. - Cache::disable(); - -Once disabled, all reads and writes will return ``null``. - -.. php:staticmethod:: enable() - -Once disabled, you can use ``enable()`` to re-enable caching:: - - // Re-enable all cache reads, and cache writes. - Cache::enable(); - -.. php:staticmethod:: enabled() - -If you need to check on the state of Cache, you can use ``enabled()``. - - -Creating a Storage Engine for Cache -=================================== - -You can provide custom ``Cache`` adapters in ``App\Cache\Engine`` as well -as in plugins using ``$plugin\Cache\Engine``. src/plugin cache engines can -also override the core engines. Cache adapters must be in a cache -directory. If you had a cache engine named ``MyCustomCacheEngine`` -it would be placed in either ``src/Cache/Engine/MyCustomCacheEngine.php`` -as an app/libs. Or in ``$plugin/Cache/Engine/MyCustomCacheEngine.php`` as -part of a plugin. Cache configs from plugins need to use the plugin -dot syntax. :: - - Cache::config('custom', array( - 'className' => 'CachePack.MyCustomCache', - // ... - )); - -Custom Cache engines must extend :php:class:`Cake\\Cache\\CacheEngine` which -defines a number of abstract methods as well as provides a few initialization -methods. - -The required API for a CacheEngine is - -.. php:class:: CacheEngine - - The base class for all cache engines used with Cache. - -.. php:method:: write($key, $value, $config = 'default') - - :return: boolean for success. - - Write value for a key into cache, optional string $config - specifies configuration name to write to. - -.. php:method:: read($key) - - :return: The cached value or false for failure. - - Read a key from the cache. Return false to indicate - the entry has expired or does not exist. - -.. php:method:: delete($key) - - :return: Boolean true on success. - - Delete a key from the cache. Return false to indicate that - the entry did not exist or could not be deleted. - -.. php:method:: clear($check) - - :return: Boolean true on success. - - Delete all keys from the cache. If $check is true, you should - validate that each value is actually expired. - -.. php:method:: clearGroup($group) - - :return: Boolean true on success. - - Delete all keys from the cache belonging to the same group. - -.. php:method:: decrement($key, $offset = 1) - - :return: Boolean true on success. - - Decrement a number under the key and return decremented value - -.. php:method:: increment($key, $offset = 1) - - :return: Boolean true on success. - - Increment a number under the key and return incremented value - -.. php:method:: gc() - - Not required, but used to do clean up when resources expire. - FileEngine uses this to delete files containing expired content. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Caching - :keywords lang=en: uniform api,xcache,cache engine,cache system,atomic operations,php class,disk storage,static methods,php extension,consistent manner,similar features,apc,memcache,queries,cakephp,elements,servers,memory + :title lang=es: Caching + :keywords lang=es: uniform api,xcache,cache engine,cache system,atomic operations,php class,disk storage,static methods,php extension,consistent manner,similar features,apc,memcache,queries,cakephp,elements,servers,memory diff --git a/es/core-libraries/collections.rst b/es/core-libraries/collections.rst index 7c4a676515c76db6b76c767ff74909affd0a07c3..de4626b311db61f17e0795d23425a1f5a08942f6 100644 --- a/es/core-libraries/collections.rst +++ b/es/core-libraries/collections.rst @@ -6,699 +6,14 @@ Collections ########### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -.. php:class:: Collection + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -The collection classes provide a set of tools to manipulate arrays or -``Traversable`` objects. If you have ever used underscore.js, -you have an idea of what you can expect from the collection classes. - -Collection instances are immutable, modifying a collection will instead generate -a new collection. This makes working with collection objects more predictable as -operations are side-effect free. - -Quick Example -============= - -Collections can be created using an array or ``Traversable`` object. You'll also -interact with collections every time you interact with the ORM in CakePHP. -A simple use of a Collection would be:: - - use Cake\Collection\Collection; - - $items = ['a' => 1, 'b' => 2, 'c' => 3]; - $collection = new Collection($items); - - // Create a new collection containing elements - // with a value greater than one. - $overOne = $collection->filter(function($value, $key, $iterator) { - return $value > 1; - }); - -The :php:trait:`~Cake\\Collection\\CollectionTrait` allows you to integrate -collection-like features into any ``Traversable`` object you have in your -application as well. - -Iterating -========= - -.. php:method:: each(callable $c) - -Collections can be iterated and/or transformed into new collections with the -``each()`` and ``map()`` methods. The ``each()`` method will not create a new -collection, but will allow you to modify any objects within the collection:: - - $collection = new Collection($items); - $collection = $collection->each(function($value, $key) { - echo "Element $key: $value"; - }); - -.. php:method:: map(callable $c) - -The return of ``each()`` will be the collection object. Each will iterate the -collection immediately applying the callback to each value in the collection. -The ``map()`` method will create a new collection based on the output of the -callback being applied to each object in the original collection:: - - $items = ['a' => 1, 'b' => 2, 'c' => 3]; - $collection = new Collection($items); - - $new = $collection->map(function($value, $key) { - return $value * 2; - }); - - // $result contains [2, 4, 6]; - $result = $new->toArray(); - -The ``map()`` method will create a new iterator which lazily creates -the resulting items when iterated. - -Filtering -========= - -.. php:method:: filter(callable $c) - -Collections make it easy to filter and create new collections based on -the result of callback functions. You can use ``filter()`` to create a new -collection of elements matching a criteria callback:: - - $collection = new Collection($people); - $ladies = $collection->filter(function($person, $key) { - return $person->gender === 'female'; - }); - $guys = $collection->filter(function($person, $key) { - return $person->gender === 'male'; - }); - -.. php:method:: reject(callable $c) - -The inverse of ``filter()`` is ``reject()``. This method does a negative filter, -removing elements that match the filter function:: - - $collection = new Collection($people); - $ladies = $collection->reject(function($person, $key) { - return $person->gender === 'male'; - }); - -.. php:method:: every(callable $c) - -You can do truth tests with filter functions. To see if every element in -a collection matches a test you can use ``every()``:: - - $collection = new Collection($people); - $allYoungPeople = $collection->every(function($person) { - return $person->age < 21; - }); - -.. php:method:: some(callable $c) - -You can see if the collection contains at least one element matching a filter -function using the ``some()`` method:: - - $collection = new Collection($people); - $hasYoungPeople = $collection->some(function($person) { - return $person->age < 21; - }); - -.. php:method:: match(array $conditions) - -If you need to extract a new collection containing only the elements that -contain a given set of properties, you should use the ``match()`` method:: - - $collection = new Collection($comments); - $commentsFromMark = $collection->match(['user.name' => 'Mark']); - -.. php:method:: firstMatch(array $conditions) - -The property name can be a dot-separated path. You can traverse into nested -entities and match the values they contain. When you only need the first -matching element from a collection, you can use ``firstMatch()``:: - - $collection = new Collection($comments); - $comment = $collection->firstMatch([ - 'user.name' => 'Mark', - 'active' => true - ]); - -As you can see from the above, both ``match()`` and ``firstMatch()`` allow you -to provide multiple conditions to match on. In addition, the conditions can be -for different paths, allowing you to express complex conditions to match -against. - -Aggregation -=========== - -.. php:method:: extract($matcher) - -One of the most common uses for a ``map()`` function is to extract a single -column from a collection. If you are looking to build a list of elements -containing the values for a particular property, you can use the ``extract()`` -method:: - - $collection = new Collection($people); - $names = $collection->extract('name'); - - // $result contains ['mark', 'jose', 'barbara']; - $result = $names->toArray(); - -As with many other functions in the collection class, you are allowed to specify -a dot-separated path for extracting columns. This example will return -a collection containing the author names from a list of articles:: - - $collection = new Collection($articles); - $names = $collection->extract('author.name'); - - // $result contains ['Maria', 'Stacy', 'Larry']; - $result = $names->toArray(); - -Finally, if the property you are looking after cannot be expressed as a path, -you can use a callback function to return it:: - - $collection = new Collection($articles); - $names = $collection->extract(function($article) { - return $article->author->name . ', ' . $article->author->last_name; - }); - -.. php:method:: reduce(callable $c) - -The counterpart of a ``map()`` operation is usually a ``reduce``. This -function will help you build a single result out of all the elements in a -collection:: - - $totalPrice = $collection->reduce(function($orderLine, $accumulated) { - return $accumulated + $orderLine->price; - }, 0); - -In the above example, ``$totalPrice`` will be the sum of all single prices -contained in the collection. Note the second argument for the ``reduce()`` -function, it takes the initial value for the reduce operation you are -performing:: - - $allTags = $collection->reduce(function($article, $accumulated) { - return array_merge($accumulated, $article->tags); - }, []); - -.. php:method:: min($callback, $type = SORT_NUMERIC) - -To extract the minimum value for a collection based on a property, just use the -``min()`` function. This will return the full element from the collection and -not just the smallest value found:: - - $collection = new Collection($people); - $youngest = $collection->min('age'); - - echo $yougest->name; - -You are also able to express the property to compare by providing a path or a -callback function:: - - $collection = new Collection($people); - $personYougestChild = $collection->min(function($person) { - return $person->child->age; - }); - - $personWithYoungestDad = $collection->min('dad.age'); - -.. php:method:: max($callback, $type = SORT_NUMERIC) - -The same can be applied to the ``max()`` function, which will return a single -element from the collection having the highest property value:: - - $collection = new Collection($people); - $oldest = $collection->max('age'); - - $personOldestChild = $collection->max(function($person) { - return $person->child->age; - }); - - $personWithOldestDad = $collection->min('dad.age'); - -Grouping and Counting ---------------------- - -.. php:method:: groupBy($callback) - -Collection values can be grouped by different keys in a new collection when they -share the same value for a property:: - - $students = [ - ['name' => 'Mark', 'grade' => 9], - ['name' => 'Andrew', 'grade' => 10], - ['name' => 'Stacy', 'grade' => 10], - ['name' => 'Barbara', 'grade' => 9] - ]; - $collection = new Collection($students); - $studentsByGrade = $collection->groupBy('grade'); - - // Result will look like this when converted to array: - [ - 10 => [ - ['name' => 'Andrew', 'grade' => 10], - ['name' => 'Stacy', 'grade' => 10] - ], - 9 => [ - ['name' => 'Mark', 'grade' => 9], - ['name' => 'Barbara', 'grade' => 9] - ] - ] - -As usual, it is possible to provide either a dot-separated path for nested -properties or your own callback function to generate the groups dynamically:: - - $commentsByUserId = $comments->groupBy('user.id'); - - $classResults = $students->groupBy(function($student) { - return $student->grade > 6 ? 'approved' : 'denied'; - }); - -.. php:method:: countBy($callback) - -If you only wish to know the number of occurrences per group, you can do so by -using the ``countBy()`` method. It takes the same arguments as ``groupBy`` so it -should be already familiar to you:: - - $classResults = $students->countBy(function($student) { - return $student->grade > 6 ? 'approved' : 'denied'; - }); - - // Result could look like this when converted to array: - ['approved' => 70, 'denied' => 20] - -.. php:method:: indexBy($callback) - -There will be certain cases where you know an element is unique for the property -you want to group by. If you wish a single result per group, you can use the -function ``indexBy()``:: - - $usersById = $users->indexBy('id'); - - // When converted to array result could look like - [ - 1 => 'markstory', - 3 => 'jose_zap', - 4 => 'jrbasso' - ] - -As with the ``groupBy()`` function you can also use a property path or -a callback:: - - $articlesByAuthorId = $articles->indexBy('author.id'); - - $filesByHash = $files->indexBy(function($file) { - return md5($file); - }); - -Sorting -======= - -.. php:method:: sortBy($callback) - -Collection values can be sorted in ascending or descending order based on -a column or custom function. To create a new sorted collection out of the values -of another one, you can use ``sortBy``:: - - $collection = new Collection($people); - $sorted = $collection->sortBy('age'); - -As seen above, you can sort by passing the name of a column or property that -is present in the collection values. You are also able to specify a property -path instead using the dot notation. The next example will sort articles by -their author's name:: - - $collection = new Collection($articles); - $sorted = $collection->sortBy('author.name'); - -The ``sortBy()`` method is flexible enough to let you specify an extractor -function that will let you dynamically select the value to use for comparing two -different values in the collection:: - - $collection = new Collection($articles); - $sorted = $collection->sortBy(function($article) { - return $article->author->name . '-' . $article->title; - }); - -In order to specify in which direction the collection should be sorted, you need -to provide either ``SORT_ASC`` or ``SORT_DESC`` as the second parameter for -sorting in ascending or descending direction respectively. By default, -collections are sorted in ascending direction:: - - $collection = new Collection($people); - $sorted = $collection->sortBy('age', SORT_ASC); - -Sometimes you will need to specify which type of data you are trying to compare -so that you get consistent results. For this purpose, you should supply a third -argument in the ``sortBy()`` function with one of the following constants: - -- **SORT_NUMERIC**: For comparing numbers -- **SORT_STRING**: For comparing string values -- **SORT_NATURAL**: For sorting string containing numbers and you'd like those - numbers to be order in a natural way. For example: showing "10" after "2". -- **SORT_LOCALE_STRING**: For comparing strings based on the current locale. - -By default, ``SORT_NUMERIC`` is used:: - - $collection = new Collection($articles); - $sorted = $collection->sortBy('title', SORT_ASC, SORT_NATURAL); - -.. warning:: - - If is often expensive to iterate sorted collections more than once. If you - plan to do so, consider converting the collection to an array or simply use - the ``compile()`` method on it. - -Working with Tree Data -====================== - -.. php:method:: nest($idPath, $parentPath) - -Not all data is meant to be represented in a linear way. Collections make it -easier to construct and flatten hierarchical or nested structures. Creating -a nested structure where children are grouped by a parent identifier property is -easy with the ``nest()`` method. - -Two parameters are required for this function. The first one is the property -representing the item identifier. The second parameter is the name of the -property representing the identifier for the parent item:: - - $items new Collection([ - ['id' => 1, 'parent_id' => null, 'name' => 'Birds'], - ['id' => 2, 'parent_id' => 1, 'name' => 'Land Birds'], - ['id' => 3, 'parent_id' => 1, 'name' => 'Eagle'], - ['id' => 4, 'parent_id' => 1, 'name' => 'Seagull'], - ['id' => 5, 'parent_id' => 6, 'name' => 'Clown Fish'], - ['id' => 6, 'parent_id' => null], 'name' => 'Fish'], - ]); - - $collection->nest('id', 'parent_id')->toArray(); - // Returns - [ - [ - 'id' => 1, - 'parent_id' => null, - 'name' => 'Bird', - 'children' => [ - [ - 'id' => 2, - 'parent_id' => 1, - 'name' => 'Land Birds', - 'children' => [ - ['id' => 3, 'name' => 'Eagle', 'parent_id' => 2] - ] - ], - ['id' => 4, 'parent_id' => 1, 'name' => 'Seagull', 'children' => []], - ] - ], - [ - 'id' => 6, - 'parent_id' => null, - 'name' => 'Fish', - 'children' => [ - ['id' => 5, 'parent_id' => 6, 'name' => 'Clown Fish', 'children' => []], - ] - ] - ]; - -Children elements are nested inside the ``children`` property inside each of the -items in the collection. This type of data representation is helpful for -rendering menus or traversing elements up to certain level in the tree. - -.. php:method:: listNested($dir = 'desc', $nestingKey = 'children') - -The inverse of ``nest()`` is ``listNested()``. This method allows you to flatten -a tree structure back into a linear structure. It takes two parameters, the -first one is the traversing mode (asc, desc or leaves), and the second one is -the name of the property containing the children for each element in the -collection. - -Taking the input the nested collection built in the previous example, we can -flatten it:: - - $nested->listNested()->toArray(); - - // Returns - [ - ['id' => 1, 'parent_id' => null, 'name' => 'Birds'], - ['id' => 2, 'parent_id' => 1, 'name' => 'Land Birds'], - ['id' => 3, 'parent_id' => 1, 'name' => 'Eagle'], - ['id' => 4, 'parent_id' => 1, 'name' => 'Seagull'], - ['id' => 6, 'parent_id' => null, 'name' => 'Fish'], - ['id' => 5, 'parent_id' => 6, 'name' => 'Clown Fish'] - ] - -By default, the tree is traversed from the root to the leaves. You can also -instruct it to only return the leaf elements in the tree:: - - $nested->listNested()->toArray(); - - // Returns - [ - ['id' => 3, 'parent_id' => 1, 'name' => 'Eagle'], - ['id' => 4, 'parent_id' => 1, 'name' => 'Seagull'], - ['id' => 5, 'parent_id' => 6, 'name' => 'Clown Fish'] - ] - -Other Methods -============= - -.. php:method:: contains($value) - -Collections allow you to quickly check if they contain one particular -value: by using the ``contains()`` method:: - - $items = ['a' => 1, 'b' => 2, 'c' => 3]; - $collection = new Collection($items); - $hasThree = $collection->contains(3); - -Comparisons are performed using the ``===`` operator. If you wish to do looser -comparison types you can use the ``some()`` method. - -.. php:method:: shuffle() - -Sometimes you may wish to show a collection of values in a random order. In -order to create a new collection that will return each value in a randomized -position, use the ``shuffle``:: - - $collection = new Collection(['a' => 1, 'b' => 2, 'c' => 3]); - - // This could return ['b' => 2, 'c' => 3, 'a' => 1] - $collection->shuffle()->toArray(); - -.. php:method:: combine($keyPath, $valuePath, $groupPath = null) - -Collections allow you to create a new collection made from keys and values in -an existing collection. Both the key and value paths can be specified with -dot notation paths:: - - $items = [ - ['id' => 1, 'name' => 'foo', 'parent' => 'a'], - ['id' => 2, 'name' => 'bar', 'parent' => 'b'], - ['id' => 3, 'name' => 'baz', 'parent' => 'a'], - ]; - $combined = (new Collection($items))->combine('id', 'name'); - - // Result will look like this when converted to array - [ - 1 => 'foo', - 2 => 'bar', - 3 => 'baz, - ]; - -You can also optionally use a ``groupPath`` to group results based on a path:: - - $combined = (new Collection($items))->combine('id', 'name', 'parent'); - - // Result will look like this when converted to array - [ - 'a' => [1 => 'foo', 3 => 'baz'], - 'b' => [2 => 'bar'] - ]; - -Withdrawing Elements --------------------- - -.. php:method: sample($size) - -Shuffling a collection is often useful when doing quick statistical analysis. -Another common operation when doing this sort of task is withdrawing a few -random values out of a collection so that more tests can be performed on those. -For example, if you wanted to select 5 random users to which you'd like to apply -some A/B tests to, you can use the ``sample()`` function:: - - $collection = new Collection($people); - - // Withdraw maximum 20 random users from this collection - $testSubjects = $collection->sample(20); - -``sample()`` will take at most the number of values you specify in the first -argument. If there are not enough elements in the collection to satisfy the -sample, the full collection in a random order is returned. - -.. php:method: take($size, $from) - -Whenever you want to take a slice of a collection use the ``take()`` function, -it will create a new collection with at most the number of values you specify in -the first argument, starting from the position passed in the second argument:: - - $topFive = $collection->sortBy('age')->take(5); - - // Take 5 people from the collection starting from position 4 - $nextTopFive = $collection->sortBy('age')->take(5, 4); - -Positions are zero-based, therefore the first position number is ``0``. - -Expanding Collections ---------------------- - -.. php:method: append($items) - -You can compose multiple collections into a single one. This enables you to -gather data from various sources, concatenate it, and apply other collection -functions to it very smoothly. The ``append()`` method will return a new -collection containing the values from both sources:: - - $cakephpTweets = new Collection($tweets); - $myTimeline = $cakephpTweets->append($phpTweets); - - // Tweets containing cakefest from both sources - $myTimeline->filter(function($tweet) { - return strpos($tweet, 'cakefest'); - }); - -.. warning:: - - When appending from different sources, you can expect some keys from both - collections to be the same. For example, when appending two simple arrays. - This can present a problem when converting a collection to an array using - ``toArray()``. If you do not want values from one collection to override - others in the previous one based on their key, make sure that you call - ``toArray(false)`` in order to drop the keys and preserve all values. - -Modifiying Elements -------------------- - -.. php:method: insert($path, $items) - -At times, you may have two separate sets of data that you would like to insert -the elements of one set into each of the elements of the other set. This is -a very common case when you fetch data from a data source that does not support -data-merging or joins natively. - -Collections offer an ``insert()`` method that will allow you to insert each of -the elements in one collection into a property inside each of the elements of -another collection:: - - $users = [ - ['username' => 'mark'], - ['username' => 'juan'], - ['username' => 'jose'] - ]; - - $languages = [ - ['PHP', 'Python', 'Ruby'], - ['Bash', 'PHP', 'Javascript'], - ['Javascript', 'Prolog'] - ]; - - $merged = (new Collection($users))->insert('skills', $languages); - -When converted to an array, the ``$merged`` collection will look like this:: - - [ - ['username' => 'mark', 'skills' => ['PHP', 'Python', 'Ruby']], - ['username' => 'juan', 'skills' => ['Bash', 'PHP', 'Javascript']], - ['username' => 'jose', 'skills' => ['Javascript', 'Prolog']] - ]; - -The first parameter for the ``insert()`` method is a dot-separated path of -properties to follow so that the elements can be inserted at that position. The -second argument is anything that can be converted to a collection object. - -Please observe that elements are inserted by the position they are found, thus, -the first element of the second collection is merged into the first -element of the first collection. - -If there are not enough elements in the second collection to insert into the -first one, then the target property will be filled with ``null`` values:: - - $languages = [ - ['PHP', 'Python', 'Ruby'], - ['Bash', 'PHP', 'Javascript'] - ]; - - $merged = (new Collection($users))->insert('skills', $languages); - - // Will yield - [ - ['username' => 'mark', 'skills' => ['PHP', 'Python', 'Ruby']], - ['username' => 'juan', 'skills' => ['Bash', 'PHP', 'Javascript']], - ['username' => 'jose', 'skills' => null] - ]; - -The ``insert()`` method can operate array elements or objects implementing the -``ArrayAccess`` interface. - -Optimizing Collections ----------------------- - -.. php:method: compile($preserveKeys = true) - -Collections often perform most operations that you create using its functions in -a lazy way. This means that even though you can call a function, it does not -mean it is executed right away. This is true for a great deal of functions in -this class. Lazy evaluation allows allows you to save resources in situations -where you don't use all the values in a collection. You might not use all the -values when iteration stops early, or when an exception/failure case is reached -early. - -Additionally, lazy evaluation helps speed up some operations. Consider the -following example:: - - $collection = new Collection($oneMillionItems); - $collection->map(function($item) { - return $item * 2; - }); - $itemsToShow = $collection->take(30); - -Had the collections not been lazy, we would have executed one million operations, -even though we only wanted to show 30 elements out of it. Instead, our map -operation was only applied to the 30 elements we used. We can also -derive benefits from this lazy evaluation for smaller collections when we -do more than one operation on them. For example: calling ``map()`` twice and -then ``filter()``. - -Lazy evaluation comes with its downside too. You could be doing the same -operations more than once if you optimize a collection prematurely. Consider -this example:: - - $ages = $collection->extract('age'); - - $youngerThan30 = $ages->filter(function($item) { - return $item < 30; - }); - - $olderThan30 = $ages->filter(function($item) { - return $item > 30; - }); - -If we iterate both ``youngerThan30`` and ``olderThan30``, the collection would -unfortunately execute the ``extract()`` operation twice. This is because -collections are immutable and the lazy-extracting operation would be done for -both filters. - -Luckily we can overcome this issue with a single function. If you plan to reuse -the values from certain operations more than once, you can compile the results -into another collection using the ``compile()`` function:: - - $ages = $collection->extract('age')->compile(); - $youngerThan30 = ... - $olderThan30 = ... - -Now, when both collections are iterated, they will only call the -extracting operation once. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Collections - :keywords lang=en: collections, cakephp, append, sort, compile, contains, countBy, each, every, extract, filter, first, firstMatch, groupBy, indexBy, jsonSerialize, map, match, max, min, reduce, reject, sample, shuffle, some, random, sortBy, take, toArray, insert + :title lang=es: Collections + :keywords lang=es: collections, cakephp, append, sort, compile, contains, countBy, each, every, extract, filter, first, firstMatch, groupBy, indexBy, jsonSerialize, map, match, max, min, reduce, reject, sample, shuffle, some, random, sortBy, take, toArray, insert diff --git a/es/core-libraries/components/authentication.rst b/es/core-libraries/components/authentication.rst deleted file mode 100644 index e1f7666827cfaf32131f58363a63280ddfaee4b3..0000000000000000000000000000000000000000 --- a/es/core-libraries/components/authentication.rst +++ /dev/null @@ -1,861 +0,0 @@ -Authentication -############## - -.. php:class:: AuthComponent(ComponentCollection $collection, array $config = []) - -Identifying, authenticating and authorizing users is a common part of -almost every web application. In CakePHP AuthComponent provides a -pluggable way to do these tasks. AuthComponent allows you to combine -authentication objects, and authorization objects to create flexible -ways of identifying and checking user authorization. - -.. _authentication-objects: - -Suggested Reading Before Continuing -=================================== - -Configuring authentication requires several steps including defining -a users table, creating a model, controller & views, etc. - -This is all covered step by step in the -:doc:`Blog Tutorial `. - - -Authentication -============== - -Authentication is the process of identifying users by provided -credentials and ensuring that users are who they say they are. -Generally this is done through a username and password, that are checked -against a known list of users. In CakePHP, there are several built-in -ways of authenticating users stored in your application. - -* ``FormAuthenticate`` allows you to authenticate users based on form POST - data. Usually this is a login form that users enter information into. -* ``BasicAuthenticate`` allows you to authenticate users using Basic HTTP - authentication. -* ``DigestAuthenticate`` allows you to authenticate users using Digest - HTTP authentication. - -By default ``AuthComponent`` uses ``FormAuthenticate``. - -Choosing an Authentication Type -------------------------------- - -Generally you'll want to offer form based authentication. It is the easiest for -users using a web-browser to use. If you are building an API or webservice, you -may want to consider basic authentication or digest authentication. The key -differences between digest and basic authentication are mostly related to how -passwords are handled. In basic authentication, the username and password are -transmitted as plain-text to the server. This makes basic authentication -un-suitable for applications without SSL, as you would end up exposing sensitive -passwords. Digest authentication uses a digest hash of the username, password, -and a few other details. This makes digest authentication more appropriate for -applications without SSL encryption. - -You can also use authentication systems like openid as well, however openid is -not part of CakePHP core. - -Configuring Authentication Handlers ------------------------------------ - -You configure authentication handlers using the ``authenticate`` config. -You can configure one or many handlers for authentication. Using -multiple handlers allows you to support different ways of logging users -in. When logging users in, authentication handlers are checked in the -order they are declared. Once one handler is able to identify the user, -no other handlers will be checked. Conversely you can halt all -authentication by throwing an exception. You will need to catch any -thrown exceptions, and handle them as needed. - -You can configure authentication handlers in your controller's -``beforeFilter`` or, in the ``$components`` array. You can pass -configuration information into each authentication object, using an -array:: - - // Basic setup - $this->Auth->config('authenticate', ['Form']); - - // Pass settings in - $this->Auth->config('authenticate', [ - 'Basic' => ['userModel' => 'Members'], - 'Form' => ['userModel' => 'Members'] - ]); - -In the second example you'll notice that we had to declare the -``userModel`` key twice. To help you keep your code DRY, you can use the -``all`` key. This special key allows you to set settings that are passed -to every attached object. The all key is also exposed as -``AuthComponent::ALL``:: - - // Pass settings in using 'all' - $this->Auth->config('authenticate', [ - AuthComponent::ALL => ['userModel' => 'Members'], - 'Basic', - 'Form' - ]); - -In the above example, both ``Form`` and ``Basic`` will get the settings -defined for the 'all' key. Any settings passed to a specific -authentication object will override the matching key in the 'all' key. -The core authentication objects support the following configuration -keys. - -- ``fields`` The fields to use to identify a user by. You can use keys - ``username`` and ``password`` to specify your username and password fields - respectively. -- ``userModel`` The model name of the users table, defaults to Users. -- ``scope`` Additional conditions to use when looking up and - authenticating users, i.e. ``['Users.is_active' => true]``. -- ``contain`` Extra models to contain and return with identified user's info. -- ``passwordHasher`` Password hasher class. Defaults to ``Default``. - -To configure different fields for user in ``$components`` array:: - - // Pass settings in $components array - public $components = [ - 'Auth' => [ - 'authenticate' => [ - 'Form' => [ - 'fields' => ['username' => 'email', 'password' => 'passwd'] - ] - ] - ] - ]; - -Do not put other Auth configuration keys (like authError, loginAction etc) -within the authenticate or Form element. They should be at the same level as -the authenticate key. The setup above with other Auth configuration -should look like:: - - // Pass settings in $components array - public $components = [ - 'Auth' => [ - 'loginAction' => [ - 'controller' => 'Users', - 'action' => 'login', - 'plugin' => 'Users' - ], - 'authError' => 'Did you really think you are allowed to see that?', - 'authenticate' => [ - 'Form' => [ - 'fields' => ['username' => 'email'] - ] - ] - ] - ]; - -In addition to the common configuration, Basic authentication supports -the following keys: - -- ``realm`` The realm being authenticated. Defaults to ``env('SERVER_NAME')``. - -In addition to the common configuration Digest authentication supports -the following keys: - -- ``realm`` The realm authentication is for, Defaults to the servername. -- ``nonce`` A nonce used for authentication. Defaults to ``uniqid()``. -- ``qop`` Defaults to auth, no other values are supported at this time. -- ``opaque`` A string that must be returned unchanged by clients. Defaults - to ``md5($config['realm'])`` - -Identifying Users and Logging Them In -------------------------------------- - -.. php:method:: identify() - -You need to manually call ``$this->Auth->identify()`` to identify the user using -credentials provided in request. Then use ``$this->Auth->setUser()`` -to log the user in i.e. save user info to session. - -When authenticating users, attached authentication objects are checked -in the order they are attached. Once one of the objects can identify -the user, no other objects are checked. A sample login function for -working with a login form could look like:: - - public function login() - { - if ($this->request->is('post')) { - $user = $this->Auth->identify(); - if ($user) { - $this->Auth->setUser($user); - return $this->redirect($this->Auth->redirectUrl()); - } else { - $this->Flash->error( - __('Username or password is incorrect'), - 'default', - [], - 'auth' - ); - } - } - } - -The above code will attempt to first identify a user in using the POST data. -If successful we set the user info to session so that it persists across requests -and redirect to either the last page they were visiting or a URL specified in the -``loginRedirect`` config. If the login is unsuccessful, a flash message is set. - -.. warning:: - - ``$this->Auth->setUser($data)`` will log the user in with whatever data is - passed to the method. It won't actually check the credentials against an - authentication class. - -Redirecting Users After Login ------------------------------ - -.. php:method:: redirectUrl - -After logging a user in, you'll generally want to redirect them back to where -they came from. Pass a URL in to set the destination a user should be redirected -to upon logging in. - -If no parameter is passed, gets the authentication redirect URL. The URL -returned is as per following rules: - -- Returns the normalized URL from session Auth.redirect value if it is - present and for the same domain the current app is running on. -- If there is no session value and there is a config ``loginRedirect``, the - ``loginRedirect`` value is returned. -- If there is no session and no ``loginRedirect``, / is returned. - -Using Digest and Basic Authentication for Logging In -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Basic and digest are stateless authentication schemes and don't require an -initial POST or a form. If using only basic / digest authenticators you don't -require a login action in your controller. Also you can set -``$this->Auth->sessionKey`` to ``false`` to ensure AuthComponent doesn't try to -read user info from session. You may also want to set config -``unauthorizedRedirect`` to ``false`` which will cause AuthComponent to throw -a ``ForbiddenException`` instead of default behavior of redirecting to referer. -Stateless authentication will re-verify the user's credentials on each request, -this creates a small amount of additional overhead, but allows clients to -login in without using cookies and makes is suitable for APIs. - -Creating Custom Authentication Objects --------------------------------------- - -Because authentication objects are pluggable, you can create custom -authentication objects in your application or plugins. If for example -you wanted to create an OpenID authentication object. In -``app/Auth/OpenidAuthenticate.php`` you could put the following:: - - use Cake\Auth\BaseAuthenticate; - - class OpenidAuthenticate extends BaseAuthenticate - { - public function authenticate(Request $request, Response $response) - { - // Do things for OpenID here. - // Return an array of user if they could authenticate the user, - // return false if not. - } - } - -Authentication objects should return ``false`` if they cannot identify the -user and an array of user information if they can. It's not required -that you extend ``BaseAuthenticate``, only that your authentication object -implements an ``authenticate()`` method. The ``BaseAuthenticate`` class -provides a number of helpful methods that are commonly used. You can -also implement a ``getUser()`` method if your authentication object needs -to support stateless or cookie-less authentication. See the sections on -basic and digest authentication below for more information. - -Using Custom Authentication Objects ------------------------------------ - -Once you've created your custom authentication object, you can use them -by including them in AuthComponents authenticate array:: - - $this->Auth->config('authenticate', [ - 'Openid', // app authentication object. - 'AuthBag.Combo', // plugin authentication object. - ]); - -Creating Stateless Authentication Systems ------------------------------------------ - -Authentication objects can implement a ``getUser()`` method that can be -used to support user login systems that don't rely on cookies. A -typical getUser method looks at the request/environment and uses the -information there to confirm the identity of the user. HTTP Basic -authentication for example uses ``$_SERVER['PHP_AUTH_USER']`` and -``$_SERVER['PHP_AUTH_PW']`` for the username and password fields. On each -request, these values are used to re-identify the user and ensure they are -valid user. As with authentication object's ``authenticate()`` method the -``getUser()`` method should return an array of user information on success or -``false`` on failure. :: - - public function getUser($request) - { - $username = env('PHP_AUTH_USER'); - $pass = env('PHP_AUTH_PW'); - - if (empty($username) || empty($pass)) { - return false; - } - return $this->_findUser($username, $pass); - } - -The above is how you could implement getUser method for HTTP basic -authentication. The ``_findUser()`` method is part of ``BaseAuthenticate`` -and identifies a user based on a username and password. - -Handling Unauthenticated Requests ---------------------------------- - -When an unauthenticated user tries to access a protected page first the -``unauthenticated()`` method of the last authenticator in the chain is called. -The authenticate object can handle sending response or redirection by returning -a response object, to indicate no further action is necessary. Due to this, the -order in which you specify the authentication provider in ``authenticate`` -config matters. - -If authenticator returns null, AuthComponent redirects user to login action. -If it's an AJAX request and config ``ajaxLogin`` is specified that element -is rendered else a 403 HTTP status code is returned. - -Displaying Auth Related Flash Messages --------------------------------------- - -In order to display the session error messages that Auth generates, you -need to add the following code to your layout. Add the following two -lines to the ``src/Template/Layout/default.ctp`` file in the body section:: - - echo $this->Flash->render(); - echo $this->Flash->render('auth'); - -You can customize the error messages, and flash settings AuthComponent -uses. Using ``flash`` config you can configure the parameters -AuthComponent uses for setting flash messages. The available keys are - -- ``key`` - The key to use, defaults to 'auth'. -- ``params`` - The array of additional params to use, defaults to []. - -In addition to the flash message settings you can customize other error -messages AuthComponent uses. In your controller's beforeFilter, or -component settings you can use ``authError`` to customize the error used -for when authorization fails:: - - $this->Auth->config('authError', "Woopsie, you are not authorized to access this area."); - -Sometimes, you want to display the authorization error only after -the user has already logged-in. You can suppress this message by setting -its value to boolean ``false``. - -In your controller's beforeFilter(), or component settings:: - - if (!$this->Auth->user()) { - $this->Auth->config('authError', false); - } - -.. _hashing-passwords: - -Hashing Passwords ------------------ - -You are responsible for hashing the passwords before they are persisted to the -database, the easiest way is to use a setter function in your User entity:: - - namespace App\Model\Entity; - - use Cake\Auth\DefaultPasswordHasher; - use Cake\ORM\Entity; - - class User extends Entity - { - - // ... - - protected function _setPassword($password) - { - return (new DefaultPasswordHasher)->hash($password); - } - - // ... - } - -AuthComponent is configured by default to use the ``DefaultPasswordHasher`` -when validating user credentials so no additional configuration is required in -order to authenticate users. - -``DefaultPasswordHasher`` uses the bcrypt hashing algorithm internally, which -is one of the stronger password hashing solution used in the industry. While it -is recommended that you use this password hasher class, the case may be that you -are managing a database of users whose password was hashed differently. - -Creating Custom Password Hasher Classes ---------------------------------------- - -In order to use a different password hasher, you need to create the class in -``src/Auth/LegacyPasswordHasher.php`` and implement the -``hash`` and ``check`` methods. This class needs to extend the -``AbstractPasswordHasher`` class:: - - namespace App\Auth; - - use \Cake\Auth\AbstractPasswordHasher; - - class LegacyPasswordHasher extends AbstractPasswordHasher - { - - public function hash($password) - { - return sha1($password); - } - - public function check($password, $hashedPassword) - { - return sha1($password) === $hashedPassword; - } - } - -Then you are required to configure the AuthComponent to use your own password -hasher:: - - public $components = [ - 'Auth' => [ - 'authenticate' => [ - 'Form' => [ - 'passwordHasher' => [ - 'className' => 'Legacy', - ] - ] - ] - ] - ]; - -Supporting legacy systems is a good idea, but it is even better to keep your -database with the latest security advancements. The following section will -explain how to migrate from one hashing algorithm to CakePHP's default - -Changing Hashing Algorithms ---------------------------- - -CakePHP provides a clean way to migrate your users' passwords from one algorithm -to another, this is achieved through the ``FallbackPasswordHasher`` class. -Assuming you are using ``LegacyPasswordHasher`` from the previous example, you -can configure the AuthComponent as follows:: - - public $components = [ - 'Auth' => [ - 'authenticate' => [ - 'Form' => [ - 'passwordHasher' => [ - 'className' => 'Fallback', - 'hashers' => ['Default', 'Legacy'] - ] - ] - ] - ] - ]; - -The first name appearing in the ``hashers`` key indicates which of the classes -is the preferred one, but it will fallback to the others in the list if the -check was unsuccessful. - -In order to update old users' passwords on the fly, you can change the login -function accordingly:: - - public function login() - { - if ($this->request->is('post')) { - $user = $this->Auth->identify(); - if ($user) { - $this->Auth->setUser($user); - if ($this->Auth->authenticationProvider()->needsPasswordRehash()) { - $user = $this->Users->get($this->Auth->user('id')); - $user->password = $this->request->data('password'); - $this->Users->save($user); - } - return $this->redirect($this->Auth->redirectUrl()); - } - ... - } - } - -As you cans see we are just setting the plain password again to to property so -the setter function in the entity hashes the password as shown in previous -examples and then saved again to the database. - -Hashing Passwords For Digest Authentication -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Because Digest authentication requires a password hashed in the format -defined by the RFC, in order to correctly hash a password for use with -Digest authentication you should use the special password hashing -function on ``DigestAuthenticate``. If you are going to be combining -digest authentication with any other authentication strategies, it's also -recommended that you store the digest password in a separate column, -from the normal password hash:: - - namespace App\Model\Table; - - use Cake\Auth\DigestAuthenticate; - use Cake\Event\Event; - use Cake\ORM\Table; - - class UsersTable extends Table - { - - public function beforeSave(Event $event) - { - $entity = $event->data['entity']; - - // Make a password for digest auth. - $entity->digest_hash = DigestAuthenticate::password( - $entity->username, - $entity->plain_password, - env('SERVER_NAME') - ); - return true; - } - } - -Passwords for digest authentication need a bit more information than -other password hashes, based on the RFC for digest authentication. - -.. note:: - - The third parameter of DigestAuthenticate::password() must match the - 'realm' config value defined when DigestAuthentication was - configured in AuthComponent::$authenticate. This defaults to - ``env('SCRIPT_NAME')``. You may wish to use a static string if you - want consistent hashes in multiple environments. - -Manually Logging Users In -------------------------- - -.. php:method:: setUser(array $user) - -Sometimes the need arises where you need to manually log a user in, such -as just after they registered for your application. You can do this by -calling ``$this->Auth->setUser()`` with the user data you want to 'login':: - - public function register() - { - $user = $this->Users->newEntity($this->request->data); - if ($this->Users->save($user)) { - $this->Auth->setUser($user->toArray()); - return $this->redirect([ - 'controller' => 'Users', - 'action' => 'home' - ]); - } - } - -.. warning:: - - Be sure to manually add the new User id to the array passed to the ``setUser()`` - method. Otherwise you won't have the user id available. - -Accessing the Logged In User ----------------------------- - -.. php:method:: user($key = null) - -Once a user is logged in, you will often need some particular -information about the current user. You can access the currently logged -in user using ``AuthComponent::user()``:: - - // From inside a controller or other component. - $this->Auth->user('id'); - -If the current user is not logged in or the key doesn't exist, null will -be returned. - - -Logging Users Out ------------------ - -.. php:method:: logout() - -Eventually you'll want a quick way to de-authenticate someone, and -redirect them to where they need to go. This method is also useful if -you want to provide a 'Log me out' link inside a members' area of your -application:: - - public function logout() - { - return $this->redirect($this->Auth->logout()); - } - -Logging out users that logged in with Digest or Basic auth is difficult -to accomplish for all clients. Most browsers will retain credentials -for the duration they are still open. Some clients can be forced to -logout by sending a 401 status code. Changing the authentication realm -is another solution that works for some clients. - -.. _authorization-objects: - -Authorization -============= - -Authorization is the process of ensuring that an -identified/authenticated user is allowed to access the resources they -are requesting. If enabled ``AuthComponent`` can automatically check -authorization handlers and ensure that logged in users are allowed to -access the resources they are requesting. There are several built-in -authorization handlers, and you can create custom ones for your -application, or as part of a plugin. - -- ``ControllerAuthorize`` Calls ``isAuthorized()`` on the active controller, - and uses the return of that to authorize a user. This is often the - most simple way to authorize users. - -.. note:: - - The ``ActionsAuthorize`` & ``CrudAuthorize`` adapter available in CakePHP - 2.x have now been moved to a separate plugin `cakephp/acl `_. - - -Configuring Authorization Handlers ----------------------------------- - -You configure authorization handlers using the ``authorize`` config key. -You can configure one or many handlers for authorization. Using -multiple handlers allows you to support different ways of checking -authorization. When authorization handlers are checked, they will be -called in the order they are declared. Handlers should return ``false``, if -they are unable to check authorization, or the check has failed. -Handlers should return ``true`` if they were able to check authorization -successfully. Handlers will be called in sequence until one passes. If -all checks fail, the user will be redirected to the page they came from. -Additionally you can halt all authorization by throwing an exception. -You will need to catch any thrown exceptions, and handle them. - -You can configure authorization handlers in your controller's -``beforeFilter`` or, in the ``$components`` array. You can pass -configuration information into each authorization object, using an -array:: - - // Basic setup - $this->Auth->config('authorize', ['Controller']); - - // Pass settings in - $this->Auth->config('authorize', [ - 'Actions' => ['actionPath' => 'controllers/'], - 'Controller' - ]); - -Much like ``authenticate``, ``authorize``, helps you -keep your code DRY, by using the ``all`` key. This special key allows you -to set settings that are passed to every attached object. The all key -is also exposed as ``AuthComponent::ALL``:: - - // Pass settings in using 'all' - $this->Auth->config('authorize', [ - AuthComponent::ALL => ['actionPath' => 'controllers/'], - 'Actions', - 'Controller' - ]); - -In the above example, both the ``Actions`` and ``Controller`` will get the -settings defined for the 'all' key. Any settings passed to a specific -authorization object will override the matching key in the 'all' key. - -If an authenticated user tries to go to a URL he's not authorized to access, -he's redirected back to the referrer. If you do not want such redirection -(mostly needed when using stateless authentication adapter) you can set config -option ``unauthorizedRedirect`` to ``false``. This causes AuthComponent -to throw a ``ForbiddenException`` instead of redirecting. - -Creating Custom Authorize Objects ---------------------------------- - -Because authorize objects are pluggable, you can create custom authorize -objects in your application or plugins. If for example you wanted to -create an LDAP authorize object. In -``src/Auth/LdapAuthorize.php`` you could put the -following:: - - namespace App\Auth; - - use Cake\Auth\BaseAuthorize; - use Cake\Network\Request; - - class LdapAuthorize extends BaseAuthorize - { - public function authorize($user, Request $request) - { - // Do things for ldap here. - } - } - -Authorize objects should return ``false`` if the user is denied access, or -if the object is unable to perform a check. If the object is able to -verify the user's access, ``true`` should be returned. It's not required -that you extend ``BaseAuthorize``, only that your authorize object -implements an ``authorize()`` method. The ``BaseAuthorize`` class provides -a number of helpful methods that are commonly used. - -Using Custom Authorize Objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Once you've created your custom authorize object, you can use them by -including them in your AuthComponent's authorize array:: - - $this->Auth->config('authorize', [ - 'Ldap', // app authorize object. - 'AuthBag.Combo', // plugin authorize object. - ]); - -Using No Authorization ----------------------- - -If you'd like to not use any of the built-in authorization objects, and -want to handle things entirely outside of AuthComponent you can set -``$this->Auth->config('authorize', false);``. By default AuthComponent starts off -with ``authorize`` set to ``false``. If you don't use an authorization scheme, -make sure to check authorization yourself in your controller's -beforeFilter, or with another component. - - -Making Actions Public ---------------------- - -.. php:method:: allow($actions = null) - -There are often times controller actions that you wish to remain -entirely public, or that don't require users to be logged in. -AuthComponent is pessimistic, and defaults to denying access. You can -mark actions as public actions by using ``AuthComponent::allow()``. By -marking actions as public, AuthComponent, will not check for a logged in -user, nor will authorize objects be checked:: - - // Allow all actions - $this->Auth->allow(); - - // Allow only the index action. - $this->Auth->allow('index'); - - // Allow only the view and index actions. - $this->Auth->allow(['view', 'index']); - -By calling it empty you allow all actions to be public. -For a single action you can provide the action name as string. Otherwise use an array. - -.. note:: - - You should not add the "login" action of your ``UsersController`` to allow list. - Doing so would cause problems with normal functioning of ``AuthComponent``. - - -Making Actions Require Authorization ------------------------------------- - -.. php:method:: deny($actions = null) - -By default all actions require authorization. However, after making actions -public, you want to revoke the public access. You can do so using -``AuthComponent::deny()``:: - - // Deny all actions. - $this->Auth->deny(); - - // Deny one action - $this->Auth->deny('add'); - - // Deny a group of actions. - $this->Auth->deny(['add', 'edit']); - -By calling it empty you deny all actions. -For a single action you can provide the action name as string. Otherwise use an array. - - -Using ControllerAuthorize -------------------------- - -ControllerAuthorize allows you to handle authorization checks in a -controller callback. This is ideal when you have very simple -authorization, or you need to use a combination of models + components -to do your authorization, and don't want to create a custom authorize -object. - -The callback is always called ``isAuthorized()`` and it should return a -boolean as to whether or not the user is allowed to access resources in -the request. The callback is passed the active user, so it can be -checked:: - - class AppController extends Controller - { - public $components = [ - 'Auth' => ['authorize' => 'Controller'], - ]; - public function isAuthorized($user = null) - { - // Any registered user can access public functions - if (empty($this->request->params['prefix'])) { - return true; - } - - // Only admins can access admin functions - if ($this->request->params['prefix'] === 'admin') { - return (bool)($user['role'] === 'admin'); - } - - // Default deny - return false; - } - } - -The above callback would provide a very simple authorization system -where, only users with role = admin could access actions that were in -the admin prefix. - -Configuration options -===================== - -The following settings can all be defined either in your controller's -``$components`` array or using ``$this->Auth->config()``: - -ajaxLogin - The name of an optional view element to render when an AJAX request is made - with an invalid or expired session. -allowedActions - Controller actions for which user validation is not required. -authenticate - Set to an array of Authentication objects you want to use when - logging users in. There are several core authentication objects, - see the section on :ref:`authentication-objects`. -authError - Error to display when user attempts to access an object or action to which - they do not have access. - - You can suppress authError message from being displayed by setting this - value to boolean ``false``. -authorize - Set to an array of Authorization objects you want to use when - authorizing users on each request, see the section on - :ref:`authorization-objects`. -flash - Settings to use when Auth needs to do a flash message with - ``FlashComponent::set()``. - Available keys are: - - - ``element`` - The element to use, defaults to 'default'. - - ``key`` - The key to use, defaults to 'auth' - - ``params`` - The array of additional params to use, defaults to [] - -loginAction - A URL (defined as a string or array) to the controller action that handles - logins. Defaults to ``/users/login``. -loginRedirect - The URL (defined as a string or array) to the controller action users - should be redirected to after logging in. This value will be ignored if the - user has an ``Auth.redirect`` value in their session. -logoutRedirect - The default action to redirect to after the user is logged out. While - AuthComponent does not handle post-logout redirection, a redirect URL will - be returned from :php:meth:`AuthComponent::logout()`. Defaults to - ``loginAction``. -unauthorizedRedirect - Controls handling of unauthorized access. By default unauthorized user is - redirected to the referrer URL or ``loginAction`` or '/'. - If set to ``false`` a ForbiddenException exception is thrown instead of redirecting. - -.. meta:: - :title lang=en: Authentication - :keywords lang=en: authentication handlers,array php,basic authentication,web application,different ways,credentials,exceptions,cakephp,logging diff --git a/es/core-libraries/components/cookie.rst b/es/core-libraries/components/cookie.rst deleted file mode 100644 index 276ecb70e7107fcee6e80117499519213b8f1caf..0000000000000000000000000000000000000000 --- a/es/core-libraries/components/cookie.rst +++ /dev/null @@ -1,130 +0,0 @@ -CookieComponent -############### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Controller\Component - -.. php:class:: CookieComponent(ComponentRegistry $collection, array $config = []) - -The CookieComponent is a wrapper around the native PHP ``setcookie`` method. It -makes it easier to manipulate cookies, and automatically encrypt cookie data. - -Configuring Cookies -=================== - -Cookies can be configured either globally or per top-level name. The global -configuration data will be merged with the top-level configuration. So only need -to override the parts that are different. To configure the global settings use -the ``config()`` method:: - - $this->Cookie->config('path', '/'); - $this->Cookie->config([ - 'expires' => '+10 days', - 'httpOnly' => true - ]); - -To configure a specific key use the ``configKey()`` method:: - - $this->Cookie->configKey('User', 'path', '/'); - $this->Cookie->configKey('User', [ - 'expires' => '+10 days', - 'httpOnly' => true - ]); - -There are a number of configurable values for cookies: - -expires - How long the cookies should last for. Defaults to 1 month. -path - The path on the server in which the cookie will be available on. - If path is set to '/foo/', the cookie will only be available within the - /foo/ directory and all sub-directories such as /foo/bar/ of domain. - The default value is app's base path. -domain - The domain that the cookie is available. To make the cookie - available on all subdomains of example.com set domain to '.example.com'. -secure - Indicates that the cookie should only be transmitted over a - secure HTTPS connection. When set to true, the cookie will only be set if - a secure connection exists. -key - Encryption key used when encrypted cookies are enabled. Defaults to Security.salt. -httpOnly - Set to true to make HTTP only cookies. Cookies that are HTTP only - are not accessible in JavaScript. Defaults to false. -encryption - Type of encryption to use. Defaults to 'aes'. Can also be 'rijndael' for - backwards compatibility. - -Using the Component -=================== - -The CookieComponent offers a number of methods for working with Cookies. - -.. php:method:: write(mixed $key, mixed $value = null) - - The write() method is the heart of the cookie component. $key is the - cookie variable name you want, and the $value is the information to - be stored:: - - $this->Cookie->write('name', 'Larry'); - - You can also group your variables by using dot notation in the - key parameter:: - - $this->Cookie->write('User.name', 'Larry'); - $this->Cookie->write('User.role', 'Lead'); - - If you want to write more than one value to the cookie at a time, - you can pass an array:: - - $this->Cookie->write('User', - ['name' => 'Larry', 'role' => 'Lead'] - ); - - All values in the cookie are encrypted with AES by default. If you want to - store the values as plain text, be sure to configure the key space:: - - $this->Cookie->configKey('User', 'encryption', false); - -.. php:method:: read(mixed $key = null) - - This method is used to read the value of a cookie variable with the - name specified by $key. :: - - // Outputs "Larry" - echo $this->Cookie->read('name'); - - // You can also use the dot notation for read - echo $this->Cookie->read('User.name'); - - // To get the variables which you had grouped - // using the dot notation as an array use the following - $this->Cookie->read('User'); - - // This outputs something like ['name' => 'Larry', 'role' => 'Lead'] - -.. php:method:: check($key) - - :param string $key: The key to check. - - Used to check whether a key/path exists and has a non-null value. - -.. php:method:: delete(mixed $key) - - Deletes a cookie variable of the name in $key. Works with dot - notation:: - - // Delete a variable - $this->Cookie->delete('bar'); - - // Delete the cookie variable bar, but not everything under foo - $this->Cookie->delete('foo.bar'); - -.. meta:: - :title lang=en: Cookie - :keywords lang=en: array controller,php setcookie,cookie string,controller setup,string domain,default description,string name,session cookie,integers,variables,domain name,null diff --git a/es/core-libraries/components/csrf-component.rst b/es/core-libraries/components/csrf-component.rst deleted file mode 100644 index 12ad2676eaa065389737a75a91e7c31f14e39f14..0000000000000000000000000000000000000000 --- a/es/core-libraries/components/csrf-component.rst +++ /dev/null @@ -1,83 +0,0 @@ -Cross Site Request Forgery -########################## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -By enabling the CSRF Component you get protection against attacks. `CSRF -`_ or Cross Site -Request Forgery is a common vulnerability in web applications. It allows an -attacker to capture and replay a previous request, and sometimes submit data -requests using image tags or resources on other domains. - -The CsrfComponent works by setting a cookie to the user's browser. When forms -are created with the :php:class:`Cake\\View\\Helper\\FormHelper`, a hidden field -is added containing the CSRF token. During the ``Controller.startup`` event, if -the request is a POST, PUT, DELETE, PATCH request the component will compare the -request data & cookie value. If either is missing or the two values mismatch the -component will throw a :php:class:`Cake\\Error\\ForbiddenException`. - -Using the CsrfComponent -======================= - -Simply by adding the ``CsrfComponent`` to your components array, -you can benefit from the CSRF protection it provides:: - - public $components = [ - 'Csrf' => [ - 'secure' => true - ] - ]; - -Settings can be passed into the component through your component's settings. -The available configuration options are: - -- ``cookieName`` The name of the cookie to send. Defaults to ``csrfToken``. -- ``expiry`` How long the CSRF token should last. Defaults to browser session. -- ``secure`` Whether or not the cookie will be set with the Secure flag. - Defaults to false. -- ``field`` The form field to check. Defaults to ``_csrfToken``. Changing this - will also require configuring FormHelper. - -When enabled, you can access the current CSRF token on the request object:: - - $token = $this->request->param('_csrfToken'); - -Integration with FormHelper -=========================== - -The CsrfComponent integrates seamlessly with ``FormHelper``. Each time you -create a form with FormHelper will insert a hidden field containing the CSRF -token. - -.. note:: - - When using the CsrfComponent you should always start your forms with the - FormHelper. If you do not, you will need to manually create hidden inputs in - each of your forms. - -CSRF Protection and AJAX Requests -================================== - -In addition to request data parameters, CSRF tokens can be submitted through -a special ``X-CSRF-Token`` header. Using a header often makes it easier to -integrate a CSRF token with JavaScript heavy applications, or XML/JSON based API -endpoints. - -Disabling the CSRF Component for Specific Actions -================================================= - -While not recommended, you may want to disable the CsrfComponent on certain -requests. You can do this using the controller's event dispatcher, during the -``beforeFilter`` method:: - - public function beforeFilter(Event $event) - { - $this->eventManager()->off($this->Csrf); - } - -.. meta:: - :title lang=en: Csrf - :keywords lang=en: configurable parameters,security component,configuration parameters,invalid request,csrf,submission diff --git a/es/core-libraries/components/flash.rst b/es/core-libraries/components/flash.rst deleted file mode 100644 index c3af44d04d61f1b266c7dcba3154c115ea5021a8..0000000000000000000000000000000000000000 --- a/es/core-libraries/components/flash.rst +++ /dev/null @@ -1,75 +0,0 @@ -FlashComponent -############## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Controller\Component - -.. php:class:: FlashComponent(ComponentCollection $collection, array $config = []) - -FlashComponent provides a way to set one-time notification messages to be -displayed after processing a form or acknowledging data. CakePHP refers to these -messages as "flash messages". FlashComponent writes flash messages to -``$_SESSION``, to be rendered in a View using -:doc:`FlashHelper `. - -Setting Flash Messages -====================== - -FlashComponent provides two ways to set flash messages: its ``__call`` magic -method and its ``set()`` method. To furnish your application with verbosity, -FlashComponent's ``__call`` magic method allows you use a method name that maps -to an element located under the ``src/Template/Element/Flash`` directory. By -convention, camelcased methods will map to the lowercased and underscored -element name:: - - // Uses src/Template/Element/Flash/success.ctp - $this->Flash->success('This was successful'); - - // Uses src/Template/Element/Flash/great_success.ctp - $this->Flash->greatSuccess('This was greatly successful'); - -Alternatively, to set a plain-text message without rendering an element, you can -use the ``set()`` method:: - - $this->Flash->set('This is a message'); - -FlashComponent's ``__call`` and ``set()`` methods optionally take a second -parameter, an array of options: - -* ``key`` Defaults to 'flash'. The array key found under the 'Flash' key in - the session. -* ``element`` Defaults to null, but will automatically be set when using the - ``__call()`` magic method. The element name to use for rendering. -* ``params`` An optional array of keys/values to make available as variables - within an element. - -An example of using these options:: - - // In your Controller - $this->Flash->success('The user has been saved', [ - 'key' => 'positive', - 'params' => [ - 'name' => $user->name, - 'email' => $user->email - ] - ]); - - // In your View - Flash->render('positive') ?> - - -
    - : , . -
    - -.. note:: - By default, CakePHP does not escape the HTML in flash messages. If you - are using any request or user data in your flash messages, you should - escape it with :php:func:`h` when formatting your messages. - -For more information about rendering your flash messages, please refer to the -:doc:`FlashHelper ` section. diff --git a/es/core-libraries/components/pagination.rst b/es/core-libraries/components/pagination.rst deleted file mode 100644 index 14cc9d74bdb40493138da398f2eeabe954d4178e..0000000000000000000000000000000000000000 --- a/es/core-libraries/components/pagination.rst +++ /dev/null @@ -1,218 +0,0 @@ -Pagination -########## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Controller\Component - -.. php:class:: PaginatorComponent - -One of the main obstacles of creating flexible and user-friendly web -applications is designing an intuitive user interface. Many applications tend to -grow in size and complexity quickly, and designers and programmers alike find -they are unable to cope with displaying hundreds or thousands of records. -Refactoring takes time, and performance and user satisfaction can suffer. - -Displaying a reasonable number of records per page has always been a critical -part of every application and used to cause many headaches for developers. -CakePHP eases the burden on the developer by providing a quick, easy way to -paginate data. - -Pagination in CakePHP is offered by a Component in the controller, to make -building paginated queries easier. In the View -:php:class:`~Cake\\View\\Helper\\PaginatorHelper` is used to make the generation -of pagination links & buttons simple. - -Using Controller::paginate() -============================ - -In the controller, we start by defining the default query conditions pagination -will use in the ``$paginate`` controller variable. These conditions, serve as -the basis for your pagination queries. They are augmented by the sort, direction -limit, and page parameters passed in from the URL. It is important to note -that the order key must be defined in an array structure like below:: - - class ArticlesController extends AppController - { - - public $components = ['Paginator']; - - public $paginate = [ - 'limit' => 25, - 'order' => [ - 'Articles.title' => 'asc' - ] - ]; - } - -You can also include any of the options supported by -:php:meth:`~Cake\\ORM\\Table::find()`, such as ``fields``:: - - class ArticlesController extends AppController - { - - public $components = ['Paginator']; - - public $paginate = [ - 'fields' => ['Articles.id', 'Articles.created'], - 'limit' => 25, - 'order' => [ - 'Articles.title' => 'asc' - ] - ]; - } - -While you can pass most of the query options from the paginate property it is -often cleaner and simpler to bundle up your pagination options into -a :ref:`custom-find-methods`. You can define the finder pagination uses by -setting the ``finder`` option:: - - class ArticlesController extends AppController - { - - public $paginate = [ - 'finder' => 'published', - ]; - } - -In addition to defining general pagination values, you can define more than one -set of pagination defaults in the controller, you just name the keys of the -array after the model you wish to configure:: - - class ArticlesController extends AppController - { - - public $paginate = [ - 'Articles' => [], - 'Authors' => [], - ]; - } - -The values of the ``Articles`` and ``Authors`` keys could contain all the properties -that a model/key less ``$paginate`` array could. - -Once the ``$paginate`` property has been defined, we can use the -:php:meth:`~Cake\\Controller\\Controller::paginate()` method to create the -pagination data, and add the ``PaginatorHelper`` if it hasn't already been -added. The controller's paginate method will return the result set of the -paginated query, and set pagination metadata to the request. You can access the -pagination metadata at ``$this->request->params['paging']``. A more complete -example of using ``paginate()`` would be:: - - class ArticlesController extends AppController - { - - public function index() - { - $this->set('articles', $this->paginate()); - } - } - -By default the ``paginate()`` method will use the default model for -a controller. You can also pass the resulting query of a find method:: - - public function index() - { - $query = $this->Articles->find('popular')->where(['author_id' => 1]); - $this->set('articles', $this->paginate($query)); - } - -If you want to paginate a different model you can provide a query for it, the -table object itself, or its name:: - - // Using a query - $comments = $this->paginate($commentsTable->find()); - - // Using the model name. - $comments = $this->paginate('Comments'); - - // Using a table object. - $comments = $this->paginate($commentTable); - -Using the Paginator Directly -============================ - -If you need to paginate data from another component you may want to use the -PaginatorComponent directly. It features a similar API to the controller -method:: - - $articles = $this->Paginator->paginate($articleTable->find(), $config); - - // Or - $articles = $this->Paginator->paginate($articleTable, $config); - -The first parameter should be the query object from a find on table object you wish -to paginate results from. Optionally, you can pass the table object and let the query -be constructed for you. The second parameter should be the array of settings to use for -pagination. This array should have the same structure as the ``$paginate`` -property on a controller. - -Control which Fields Used for Ordering -====================================== - -By default sorting can be done on any non-virtual column a table has. This is -sometimes undesirable as it allows users to sort on un-indexed columnsthat can -be expensive to order by. You can set the whitelist of fields that can be sorted -using the ``sortWhitelist`` option. This option is required when you want to -sort on any associated data, or computed fields that may be part of your -pagination query:: - - public $paginate = [ - 'sortWhitelist' => [ - 'id', 'title', 'Users.username', 'created' - ] - ]; - -Any requests that attempt to sort on fields not in the whitelist will be -ignored. - -Limit the Maximum Number of Rows that can be Fetched -==================================================== - -The number of results that are fetched is exposed to the user as the -``limit`` parameter. It is generally undesirable to allow users to fetch all -rows in a paginated set. By default CakePHP limits the maximum number of rows -that can be fetched to 100. If this default is not appropriate for your -application, you can adjust it as part of the pagination options:: - - public $paginate = [ - // Other keys here. - 'maxLimit' => 10 - ]; - -If the request's limit param is greater than this value, it will be reduced to -the ``maxLimit`` value. - -Out of Range Page Requests -========================== - -The PaginatorComponent will throw a ``NotFoundException`` when trying to -access a non-existent page, i.e. page number requested is greater than total -page count. - -So you could either let the normal error page be rendered or use a try catch -block and take appropriate action when a ``NotFoundException`` is caught:: - - public function index() - { - try { - $this->paginate(); - } catch (NotFoundException $e) { - // Do something here like redirecting to first or last page. - // $this->request->params['paging'] will give you required info. - } - } - -Pagination in the View -====================== - -Check the :php:class:`~Cake\\View\\Helper\\PaginatorHelper` documentation for -how to create links for pagination navigation. - - -.. meta:: - :title lang=en: Pagination - :keywords lang=en: order array,query conditions,php class,web applications,headaches,obstacles,complexity,programmers,parameters,paginate,designers,cakephp,satisfaction,developers diff --git a/es/core-libraries/components/request-handling.rst b/es/core-libraries/components/request-handling.rst deleted file mode 100644 index 74959928f48c63799e424871a5f9afc01a23a6fc..0000000000000000000000000000000000000000 --- a/es/core-libraries/components/request-handling.rst +++ /dev/null @@ -1,258 +0,0 @@ -Request Handling -################ - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:class:: RequestHandlerComponent(ComponentCollection $collection, array $config = []) - -The Request Handler component is used in CakePHP to obtain -additional information about the HTTP requests that are made to -your applications. You can use it to inform your controllers about -AJAX as well as gain additional insight into content types that the -client accepts and automatically changes to the appropriate layout -when file extensions are enabled. - -By default RequestHandler will automatically detect AJAX requests -based on the HTTP-X-Requested-With header that many JavaScript -libraries use. When used in conjunction with -:php:meth:`Router::parseExtensions()` RequestHandler will automatically switch -the layout and view files to those that match the requested type. -Furthermore, if a helper with the same name as the requested -extension exists, it will be added to the Controllers Helper array. -Lastly, if XML/JSON data is POST'ed to your Controllers, it will be -parsed into an array which is assigned to ``$this->request->data``, -and can then be saved as model data. In order to make use of -RequestHandler it must be included in your $components array:: - - class WidgetsController extends AppController - { - - public $components = ['RequestHandler']; - - // Rest of controller - } - -Obtaining Request Information -============================= - -Request Handler has several methods that provide information about -the client and its request. - -.. php:method:: accepts($type = null) - - $type can be a string, or an array, or null. If a string, accepts - will return true if the client accepts the content type. If an - array is specified, accepts return true if any one of the content - types is accepted by the client. If null returns an array of the - content-types that the client accepts. For example:: - - class ArticlesController extends AppController - { - - public $components = ['RequestHandler']; - - public function beforeFilter() - { - if ($this->RequestHandler->accepts('html')) { - // Execute code only if client accepts an HTML (text/html) - // response. - } elseif ($this->RequestHandler->accepts('xml')) { - // Execute XML-only code - } - if ($this->RequestHandler->accepts(['xml', 'rss', 'atom'])) { - // Executes if the client accepts any of the above: XML, RSS - // or Atom. - } - } - } - -Other request 'type' detection methods include: - -.. php:method:: isXml() - - Returns true if the current request accepts XML as a response. - -.. php:method:: isRss() - - Returns true if the current request accepts RSS as a response. - -.. php:method:: isAtom() - - Returns true if the current call accepts an Atom response, false - otherwise. - -.. php:method:: isMobile() - - Returns true if user agent string matches a mobile web browser, or - if the client accepts WAP content. The supported Mobile User Agent - strings are: - - - Android - - AvantGo - - BlackBerry - - DoCoMo - - Fennec - - iPad - - iPhone - - iPod - - J2ME - - MIDP - - NetFront - - Nokia - - Opera Mini - - Opera Mobi - - PalmOS - - PalmSource - - portalmmm - - Plucker - - ReqwirelessWeb - - SonyEricsson - - Symbian - - UP.Browser - - webOS - - Windows CE - - Windows Phone OS - - Xiino - -.. php:method:: isWap() - - Returns true if the client accepts WAP content. - -All of the above request detection methods can be used in a similar -fashion to filter functionality intended for specific content -types. For example when responding to AJAX requests, you often will -want to disable browser caching, and change the debug level. -However, you want to allow caching for non-AJAX requests. The -following would accomplish that:: - - if ($this->request->is('ajax')) { - $this->disableCache(); - } - // Continue Controller action - -Automatically Decoding Request Data -=================================== - -.. php:method:: addInputType($type, $handler) - -Add a request data decoder. The handler should contain a callback, and any -additional arguments for the callback. The callback should return -an array of data contained in the request input. For example adding a CSV -handler in your controllers' beforeFilter could look like:: - - $parser = function ($data) { - $rows = str_getcsv($data, "\n"); - foreach ($rows as &$row) { - $row = str_getcsv($row, ','); - } - return $rows; - }; - $this->RequestHandler->addInputType('csv', [$parser]); - -You can use any `callable `_ for the handling function. -You can also pass additional arguments to the callback, this is useful for -callbacks like ``json_decode``:: - - $this->RequestHandler->addInputType('json', ['json_decode', true]); - -The above will make ``$this->request->data`` an array of the JSON input data, -without the additional ``true`` you'd get a set of ``StdClass`` objects. - -Checking Content-Type Preferences -================================= - -.. php:method:: prefers($type = null) - -Determines which content-types the client prefers. If no parameter -is given the most likely content type is returned. If $type is an -array the first type the client accepts will be returned. -Preference is determined primarily by the file extension parsed by -Router if one has been provided, and secondly by the list of -content-types in ``HTTP\_ACCEPT``:: - - $this->RequestHandler->prefers('json'); - -Responding To Requests -====================== - -.. php:method:: renderAs($controller, $type) - -Change the render mode of a controller to the specified type. Will -also append the appropriate helper to the controller's helper array -if available and not already in the array:: - - // Force the controller to render an xml response. - $this->RequestHandler->renderAs($this, 'xml'); - -This method will also attempt to add a helper that matches your current content -type. For example if you render as ``rss``, the ``RssHelper`` will be added. - -.. php:method:: respondAs($type, $options) - -Sets the response header based on content-type map names. This method lets you -set a number of response properties at once:: - - $this->RequestHandler->respondAs('xml', [ - // Force download - 'attachment' => true, - 'charset' => 'UTF-8' - ]); - -.. php:method:: responseType() - -Returns the current response type Content-type header or null if one has yet to -be set. - - -Taking Advantage of HTTP Cache Validation -========================================= - -The HTTP cache validation model is one of the processes used for cache -gateways, also known as reverse proxies, to determine if they can serve a -stored copy of a response to the client. Under this model, you mostly save -bandwidth, but when used correctly you can also save some CPU processing, -reducing this way response times. - -Enabling the RequestHandlerComponent in your controller automatically activates -a check done before rendering the view. This check compares the response object -against the original request to determine whether the response was not modified -since the last time the client asked for it. - -If response is evaluated as not modified, then the view rendering process is -stopped, saving processing time, saving bandwidth and no content is returned to -the client. The response status code is then set to ``304 Not Modified``. - -You can opt-out this automatic checking by setting the ``checkHttpCache`` -setting to false:: - - public $components = [ - 'RequestHandler' => [ - 'checkHttpCache' => false - ]]; - -Using custom ViewClasses -======================== - -.. php:method:: viewClassMap($type, $viewClass) - -When using JsonView/XmlView you might want to override the default serialization -with a custom View class, or add View classes for other types. - -You can map existing and new types to your custom classes. You can also set this -automatically by using the ``viewClassMap`` setting:: - - public $components = [ - 'RequestHandler' => [ - 'viewClassMap' => [ - 'json' => 'ApiKit.MyJson', - 'xml' => 'ApiKit.MyXml', - 'csv' => 'ApiKit.Csv' - ] - ]]; - -.. meta:: - :title lang=en: Request Handling - :keywords lang=en: handler component,javascript libraries,public components,null returns,model data,request data,content types,file extensions,ajax,meth,content type,array,conjunction,cakephp,insight,php diff --git a/es/core-libraries/components/security-component.rst b/es/core-libraries/components/security-component.rst deleted file mode 100644 index 910301bd01166e8a3b377d27c51ddc0787dcbfd0..0000000000000000000000000000000000000000 --- a/es/core-libraries/components/security-component.rst +++ /dev/null @@ -1,214 +0,0 @@ -Security -######## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:class:: SecurityComponent(ComponentCollection $collection, array $config = []) - -The Security Component creates an easy way to integrate tighter -security in your application. It provides methods for various tasks like: - -* Restricting which HTTP methods your application accepts. -* Form tampering protection -* Requiring that SSL be used. -* Limiting cross controller communication. - -Like all components it is configured through several configurable parameters. -All of these properties can be set directly or through setter methods of the -same name in your controller's beforeFilter. - -By using the Security Component you automatically get `CSRF -`_ and -form tampering protection. Hidden token fields will -automatically be inserted into forms and checked by the Security -component. Among other things, a form submission will not be accepted after a -certain period of inactivity, which is controlled by the -``csrfExpires`` time. - -If you are using Security component's form protection features and -other components that process form data in their ``startup()`` -callbacks, be sure to place Security Component before those -components in your ``$components`` array. - -.. note:: - - When using the Security Component you **must** use the FormHelper to create - your forms. In addition, you must **not** override any of the fields' "name" - attributes. The Security Component looks for certain indicators that are - created and managed by the FormHelper (especially those created in - :php:meth:`~Cake\\View\\Helper\\FormHelper::create()` and - :php:meth:`~Cake\\View\\Helper\\FormHelper::end()`). Dynamically altering - the fields that are submitted in a POST request (e.g. disabling, deleting - or creating new fields via JavaScript) is likely to cause the request to be - send to the blackhole callback. See the ``$validatePost`` or - ``$disabledFields`` configuration parameters. - -Handling Blackhole Callbacks -============================ - -.. php:method:: blackHole(object $controller, string $error) - -If an action is restricted by the Security Component it is -'black-holed' as an invalid request which will result in a 400 error -by default. You can configure this behavior by setting the -``blackHoleCallback`` configuration option to a callback function -in the controller. - -By configuring a callback method you can customize how the blackhole process -works:: - - public function beforeFilter() - { - $this->Security->config('blackHoleCallback', 'blackhole'); - } - - public function blackhole($type) - { - // Handle errors. - } - -The ``$type`` parameter can have the following values: - -* 'auth' Indicates a form validation error, or a controller/action mismatch - error. -* 'secure' Indicates an SSL method restriction failure. - -Restrict Actions to SSL -======================= - -.. php:method:: requireSecure() - - Sets the actions that require a SSL-secured request. Takes any - number of arguments. Can be called with no arguments to force all - actions to require a SSL-secured. - -.. php:method:: requireAuth() - - Sets the actions that require a valid Security Component generated - token. Takes any number of arguments. Can be called with no - arguments to force all actions to require a valid authentication. - -Restricting Cross Controller Communication -========================================== - -allowedControllers - A List of Controller from which the actions of the current - controller are allowed to receive requests from. This can be used - to control cross controller requests. -allowedActions - Actions from which actions of the current controller are allowed to - receive requests. This can be used to control cross controller - requests. - -These configuration options allow you to restrict cross controller -communication. Set them with the ``config()`` method. - -Form Tampering Prevention -========================= - -By default ``SecurityComponent`` prevents users from tampering with forms in -specific ways. The ``SecurityComponent`` will prevent the following things: - -* Unknown fields cannot be added to the form. -* Fields cannot be removed from the form. -* Values in hidden inputs cannot be modified. - -Preventing these forms of tampering is accomplished by working with FormHelper -and tracking which fields are in a form. The values for hidden fields are -tracked as well. All of this data is combined and turned into a hash. When -a form is submitted, SecurityComponent will use the POST data to build the same -structure and compare the hash. - -.. note:: - - SecurityComponent will **not** prevent select options from being - added/changed. Nor will it prevent radio options from being added/changed. - -.. php:attr:: unlockedFields - - Set to a list of form fields to exclude from POST validation. Fields can be - unlocked either in the Component, or with - :php:meth:`FormHelper::unlockField()`. Fields that have been unlocked are - not required to be part of the POST and hidden unlocked fields do not have - their values checked. - -.. php:attr:: validatePost - - Set to ``false`` to completely skip the validation of POST - requests, essentially turning off form validation. - -Usage -===== - -Using the security component is generally done in the controller -beforeFilter(). You would specify the security restrictions you -want and the Security Component will enforce them on its startup:: - - class WidgetController extends AppController - { - - public $components = ['Security']; - - public function beforeFilter() - { - if (isset($this->request->params['admin'])) { - $this->Security->requireSecure(); - } - } - } - -The above example would force all actions that had admin routing to -require secure SSL requests. - -:: - - class WidgetController extends AppController - { - - public $components = ['Security']; - - public function beforeFilter() - { - if (isset($this->params['admin'])) { - $this->Security->blackHoleCallback = 'forceSSL'; - $this->Security->requireSecure(); - } - } - - public function forceSSL() - { - return $this->redirect('https://' . env('SERVER_NAME') . $this->here); - } - } - -This example would force all actions that had admin routing to require secure -SSL requests. When the request is black holed, it will call the nominated -``forceSSL()`` callback which will redirect non-secure requests to secure -requests automatically. - -.. _security-csrf: - -CSRF Protection -=============== - -CSRF or Cross Site Request Forgery is a common vulnerability in web -applications. It allows an attacker to capture and replay a previous request, -and sometimes submit data requests using image tags or resources on other -domains. To enable CSRF protection features use the -:doc:`/core-libraries/components/csrf-component`. - -Disabling Security Component for Specific Actions -================================================= - -There may be cases where you want to disable all security checks for an action -(ex. AJAX requests). You may "unlock" these actions by listing them in -``$this->Security->unlockedActions`` in your ``beforeFilter``. The -``unlockedActions`` property will **not** affect other features of -``SecurityComponent``. - -.. meta:: - :title lang=en: Security - :keywords lang=en: configurable parameters,security component,configuration parameters,invalid request,protection features,tighter security,holing,php class,meth,404 error,period of inactivity,csrf,array,submission,security class,disable security,unlockActions diff --git a/es/core-libraries/components/sessions.rst b/es/core-libraries/components/sessions.rst deleted file mode 100644 index aa7a4d9b448ddc2d6880621753a354f5d7302598..0000000000000000000000000000000000000000 --- a/es/core-libraries/components/sessions.rst +++ /dev/null @@ -1,86 +0,0 @@ -Sessions -######## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:class:: SessionComponent(ComponentCollection $collection, array $config = []) - -The CakePHP SessionComponent provides a way to persist client data -between page requests. It acts as a wrapper for ``$_SESSION`` as -well as providing convenience methods for several ``$_SESSION`` -related functions. - -Sessions can be configured in a number of ways in CakePHP. For more information, -you should see the :doc:`Session configuration ` -documentation. - -Interacting with Session Data -============================= - -The Session component is used to interact with session information. -It includes basic CRUD functions as well as features for creating -feedback messages to users. - -It should be noted that Array structures can be created in the -Session by using :term:`dot notation`. So ``User.username`` would -reference the following:: - - ['User' => [ - 'username' => 'clark-kent@dailyplanet.com' - ]]; - -Dots are used to indicate nested arrays. This notation is used for -all Session component methods wherever a name/key is used. - -.. php:method:: write($name, $value) - - Write to the Session puts $value into $name. $name can be a dot - separated array. For example:: - - $this->Session->write('Person.eyeColor', 'Green'); - - This writes the value 'Green' to the session under Person => - eyeColor. - - -.. php:method:: read($name) - - Returns the value at $name in the Session. If $name is null the - entire session will be returned. E.g:: - - $green = $this->Session->read('Person.eyeColor'); - - Retrieve the value Green from the session. Reading data that does not exist - will return null. - -.. php:method:: check($name) - - Used to check if a Session variable has been set. Returns true on - existence and false on non-existence. - -.. php:method:: delete($name) - - Clear the session data at $name. E.g:: - - $this->Session->delete('Person.eyeColor'); - - Our session data no longer has the value 'Green', or the index - eyeColor set. However, Person is still in the Session. To delete - the entire Person information from the session use:: - - $this->Session->delete('Person'); - -.. php:method:: destroy() - - The ``destroy`` method will delete the session cookie and all - session data stored in the temporary file system. It will then - destroy the PHP session and then create a fresh session:: - - $this->Session->destroy(); - -.. meta:: - :title lang=en: Sessions - :keywords lang=en: php array,dailyplanet com,configuration documentation,dot notation,feedback messages,reading data,session data,page requests,clark kent,dots,existence,sessions,convenience,cakephp diff --git a/es/core-libraries/email.rst b/es/core-libraries/email.rst new file mode 100644 index 0000000000000000000000000000000000000000..aceaad7e25ebd7e03f82b9160c5047ec189da44b --- /dev/null +++ b/es/core-libraries/email.rst @@ -0,0 +1,15 @@ +Email +##### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Email + :keywords lang=es: sending mail,email sender,envelope sender,php class,database configuration,sending emails,meth,shells,smtp,transports,attributes,array,config,flexibility,php email,new email,sending email,models diff --git a/es/core-libraries/events.rst b/es/core-libraries/events.rst index 8a1cc1ca353a01760423ccaae0d389369078f8cc..99ad4eff40df32fd1e9fe133f3877b2eda8e01d4 100644 --- a/es/core-libraries/events.rst +++ b/es/core-libraries/events.rst @@ -2,455 +2,14 @@ Events System ############# .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Creating maintainable applications is both a science and an art. It is -well-known that a key for having good quality code is making your objects -loosely coupled and strongly cohesive at the same time. Cohesion means that -all methods and properties for a class are strongly related to the class -itself and it is not trying to do the job other objects should be doing, -while loosely coupling is the measure of how little a class is "wired" -to external objects, and how much that class is depending on them. - -There are certain cases where you need to cleanly communicate with other parts -of an application, without having to hard code dependencies, thus losing -cohesion and increasing class coupling. Using the Observer pattern, which allows -objects to notify other objects and anonymous listeners about changes is -a useful pattern to achieve this goal. - -Listeners in the observer pattern can subscribe to events and choose to act upon -them if they are relevant. If you have used JavaScript, there is a good chance -that you are already familiar with event driven programming. - -CakePHP emulates several aspects of how events are triggered and managed in -popular JavaScript libraries such as jQuery. In the CakePHP implementation, an -event object is dispatched to all listeners. The event object holds information -about the event, and provides the ability to stop event propagation at any -point. Listeners can register themselves or can delegate this task to other -objects and have the chance to alter the state and the event itself for the rest -of the callbacks. - -The event subsystem is at the heart of Model, Behavior, Controller, View and -Helper callbacks. If you've ever used any of them, you are already somewhat -familiar with events in CakePHP. - -Example Event Usage -=================== - -Let's suppose you are building a Cart plugin, and you'd like to focus on just -handling order logic. You don't really want to include shipping logic, emailing -the user or decrementing the item from the stock, but these are important tasks -to the people using your plugin. If you were not using events, you may try to -implement this by attaching behaviors to models, or adding components to your -controllers. Doing so represents a challenge most of the time, since you -would have to come up with the code for externally loading those behaviors or -attaching hooks to your plugin controllers. - -Instead, you can use events to allow you to cleanly separate the concerns of -your code and allow additional concerns to hook into your plugin using events. -For example, in your Cart plugin you have an Orders model that deals with creating -orders. You'd like to notify the rest of the application that an order has been -created. To keep your Orders model clean you could use events:: - - // Cart/Model/Table/OrdersTable.php - namespace Cart\Model\Table; - - use Cake\Event\Event; - use Cake\ORM\Table; - - class OrdersTable extends Table - { - - public function place($order) - { - if ($this->save($order)) { - $this->Cart->remove($order); - $event = new Event('Model.Order.afterPlace', $this, array( - 'order' => $order - )); - $this->eventManager()->dispatch($event); - return true; - } - return false; - } - } - -The above code allows you to easily notify the other parts of the application -that an order has been created. You can then do tasks like send email -notifications, update stock, log relevant statistics and other tasks in separate -objects that focus on those concerns. - -Accessing Event Managers -======================== - -In CakePHP events are triggered against event managers. Event managers are -available in every Table, View and Controller using ``eventManager()``:: - - $events = $this->eventManager(); - -Each model has a separate event manager, while the View and Controller -share one. This allows model events to be self contained, and allow components -or controllers to act upon events created in the view if necessary. - -Global Event Manager --------------------- - -In addition to instance level event managers, CakePHP provides a global event -manager that allows you to listen to any event fired in an application. This is -useful when attaching listeners to a specific instance might be cumbersome or -difficult. The global manager is a singleton instance of -:php:class:`Cake\\Event\\EventManager`. Listeners attached to the global -dispatcher will be fired before instance listeners at the same priority. You can -access the global manager using a static method:: - - // In any configuration file or piece of code that executes before the event - use Cake\Event\EventManager; - - EventManager::instance()->on( - 'Model.Order.afterPlace', - $aCallback - ); - -One important thing you should consider is that there are events that will be -triggered having the same name but different subjects, so checking it in the -event object is usually required in any function that gets attached globally in -order to prevent some bugs. Remember that with the flexibility of using the -global manager, some additional complexity is incurred. - -:php:meth:`Cake\\Event\\EventManager::dispatch()` method accepts the event object -as an argument and notifies all listener and callbacks passing this object -along. The listeners will handle all the extra logic around the -``afterPlace`` event, you can log the time, send emails, update user statistics -possibly in separate objects and even delegating it to offline tasks if you have -the need. - -Dispatching Events -================== - -Once you have obtained an instance of an event manager you can dispatch events -using :php:meth:`~Cake\\Event\\EventManager::dispatch()`. This method takes an instance -of the :php:class:`Cake\\Event\\Event` class. Let's look at dispatching an event:: - - // Create a new event and dispatch it. - $event = new Event('Model.Order.afterPlace', $this, array( - 'order' => $order - )); - $this->eventManager()->dispatch($event); - -:php:class:`Cake\\Event\\Event` accepts 3 arguments in its constructor. The first one is -the event name, you should try to keep this name as unique as possible, while -making it readable. We suggest a convention as follows: ``Layer.eventName`` for -general events happening at a layer level (e.g. ``Controller.startup``, -``View.beforeRender``) and ``Layer.Class.eventName`` for events happening in -specific classes on a layer, for example ``Model.User.afterRegister`` or -``Controller.Courses.invalidAccess``. - -The second argument is the ``subject``, meaning the object associated to the event, -usually when it is the same class triggering events about itself, using ``$this`` -will be the most common case. Although a Component could trigger -controller events too. The subject class is important because listeners will get -immediate access to the object properties and have the chance to inspect or -change them on the fly. - -Finally, the third argument is any additional event data.This can be any data you consider -useful to pass around so listeners can act upon it. While this can be an argument -of any type, we recommend passing an associative array. - -The :php:meth:`~Cake\\Event\\EventManager::dispatch()` method accepts an event object as an argument -and notifies all subscribed listeners. - -Registering Listeners -===================== - -Listeners are the preferred way to register callbacks for an event. This is done by -implementing the :php:class:`Cake\\Event\\EventListener` interface in any class you wish -to register some callbacks. Classes implementing it need to provide the -``implementedEvents()`` method. This method must return an associative array -with all event names that the class will handle. - -To continue our previous example, let's imagine we have a UserStatistic class -responsible for calculating a user's purchasing history, and compiling into -global site statistics. This is a great place to use a listener class. Doing so -allows you concentrate the statistics logic in one place and react to events as -necessary. Our ``UserStatistics`` listener might start out like:: - - use Cake\Event\EventListener; - - class UserStatistic implements EventListener - { - - public function implementedEvents() - { - return array( - 'Model.Order.afterPlace' => 'updateBuyStatistic', - ); - } - - public function updateBuyStatistic($event) - { - // Code to update statistics - } - } - - // Attach the UserStatistic object to the Order's event manager - $statistics = new UserStatistic(); - $this->Orders->eventManager()->on($statistics); - -As you can see in the above code, the ``attach`` function will accept instances -of the ``EventListener`` interface. Internally, the event manager will use -``implementedEvents`` to attach the correct callbacks. - -Registering Anonymous Listeners -------------------------------- - -While event listener objects are generally a better way to implement listeners, -you can also bind any ``callable`` as an event listener. For example if we -wanted to put any orders into the log files, we could use a simple anonymous -function to do so:: - - use Cake\Log\Log; - - $this->Orders->eventManager()->on('Model.Order.afterPlace', function($event) { - Log::write( - 'info', - 'A new order was placed with id: ' . $event->subject()->id - ); - }); - -In addition to anonymous functions you can use any other callable type that PHP -supports:: - - $events = array( - 'email-sending' => 'EmailSender::sendBuyEmail', - 'inventory' => array($this->InventoryManager, 'decrement'), - ); - foreach ($events as $callable) { - $eventManager->on('Model.Order.afterPlace', $callable); - } - -.. _event-priorities: - -Establishing Priorities ------------------------ - -In some cases you might want to control the order that listeners are invoked. -For instance, if we go back to our user statistics example. It would ideal if -this listener was called at the end of the stack. By calling it at the end of -the listener stack, we can ensure that the event was not canceled, and that no -other listeners raised exceptions. We can also get the final state of the -objects in the case that other listeners have modified the subject or event -object. - -Priorities are defined as an integer when adding a listener. The higher the -number, the later the method will be fired. The default priority for all -listeners is ``10``. If you need your method to be run earlier, using any value -below this default will work. On the other hand if you desire to run the -callback after the others, using a number above ``10`` will do. - -If two callbacks happen to have the same priority value, they will be executed -with a the order they were attached. You set priorities using the ``attach`` -method for callbacks, and declaring it in the ``implementedEvents`` function for -event listeners:: - - // Setting priority for a callback - $callback = array($this, 'doSomething'); - $this->eventManager()->on( - 'Model.Order.afterPlace', - array('priority' => 2), - $callback - ); - - // Setting priority for a listener - class UserStatistic implements EventListener - { - public function implementedEvents() - { - return array( - 'Model.Order.afterPlace' => array( - 'callable' => 'updateBuyStatistic', - 'priority' => 100 - ), - ); - } - } - -As you see, the main difference for ``EventListener`` objects is that you need -to use an array for specifying the callable method and the priority preference. -The ``callable`` key is an special array entry that the manager will read to know -what function in the class it should be calling. - -Getting Event Data as Function Parameters ------------------------------------------ - -When events have data provided in their constructor, the provided data is -converted into arguments for the listeners. An example from the View layer is -the afterRender callback:: - - $this->eventManager() - ->dispatch(new Event('View.afterRender', $this, [$viewFileName])); - -The listeners of the ``View.afterRender`` callback should have the following -signature:: - - function (Event $event, $viewFileName) - -Each value provided to the Event constructor will be converted into function -parameters in the order they appear in the data array. If you use an associative -array, the result of ``array_values`` will determine the function argument -order. - -.. note:: - - Unlike in 2.x, converting event data to listener arguments is the default - behavior and cannot be disabled. - - -Stopping Events ---------------- - -Much like DOM events, you may want to stop an event to prevent additional -listeners from being notified. You can see this in action during model callbacks -(e.g. beforeSave) in which it is possible to stop the saving operation if -the code detects it cannot proceed any further. - -In order to stop events you can either return ``false`` in your callbacks or call -the ``stopPropagation`` method on the event object:: - - public function doSomething($event) - { - // ... - return false; // Stops the event - } - - public function updateBuyStatistic($event) - { - // ... - $event->stopPropagation(); - } - -Stopping an event will prevent any additional callbacks from being called. -Additionally the code triggering the event may behave differently based on the -event being stopped or not. Generally it does not make sense to stop 'after' -events, but stopping 'before' events is often used to prevent the entire -operation from occurring. - -To check if an event was stopped, you call the ``isStopped()`` method in the -event object:: - - public function place($order) - { - $event = new Event('Model.Order.beforePlace', $this, ['order' => $order]); - $this->eventManager()->dispatch($event); - if ($event->isStopped()) { - return false; - } - if ($this->Orders->save($order)) { - // ... - } - // ... - } - -In the previous example the order would not get saved if the event is stopped -during the ``beforePlace`` process. - -Getting Event Results ---------------------- - -Every time a callback returns a value, it gets stored in the ``$result`` -property of the event object. This is useful when you want to allow callbacks to -modify the event execution. Let's take again our ``beforePlace`` example and let -callbacks modify the $order data. - -Event results can be altered either using the event object result property -directly or returning the value in the callback itself:: - - // A listener callback - public function doSomething($event) - { - // ... - $alteredData = $event->data['order'] + $moreData; - return $alteredData; - } - - // Another listener callback - public function doSomethingElse($event) - { - // ... - $event->result['order'] = $alteredData; - } - - // Using the event result - public function place($order) - { - $event = new Event('Model.Order.beforePlace', $this, ['order' => $order]); - $this->eventManager()->dispatch($event); - if (!empty($event->result['order'])) { - $order = $event->result['order']; - } - if ($this->Orders->save($order)) { - // ... - } - // ... - } - -It is possible to alter any event object property and have the new data passed -to the next callback. In most of the cases, providing objects as event data or -result and directly altering the object is the best solution as the reference is -kept the same and modifications are shared across all callback calls. - -Removing Callbacks and Listeners --------------------------------- - -If for any reason you want to remove any callback from the event manager just -call the :php:meth:`Cake\\Event\\EventManager::off()` method using as -arguments the first two params you used for attaching it:: - - // Attaching a function - $this->eventManager()->on('My.event', [$this, 'doSomething']); - - // Detaching the function - $this->eventManager()->off('My.event', [$this, 'doSomething']); - - // Attaching an anonymous function. - $myFunction = function ($event) { ... }; - $this->eventManager()->on('My.event', $myFunction); - - // Detaching the anonymous function - $this->eventManager()->off('My.event', $myFunction); - - // Attaching a EventListener - $listener = new MyEventLister(); - $this->eventManager()->on($listener); - - // Detaching a single event key from a listener - $this->eventManager()->off('My.event', $listener); - - // Detaching all callbacks implemented by a listener - $this->eventManager()->off($listener); - -Conclusion -========== - -Events are a great way of separating concerns in your application and make -classes both cohesive and decoupled from each other. Events can be utilized to -de-couple application code and make extensible plugins. - -Keep in mind that with great power comes great responsibility. Using too many -events can make debugging harder and require additional integration testing. - -Additional Reading -================== - -.. toctree:: - :maxdepth: 1 - - /orm/behaviors - /controllers/components - /views/helpers + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Events system - :keywords lang=en: events, dispatch, decoupling, cakephp, callbacks, triggers, hooks, php + :title lang=es: Events system + :keywords lang=es: events, dispatch, decoupling, cakephp, callbacks, triggers, hooks, php diff --git a/es/core-libraries/file-folder.rst b/es/core-libraries/file-folder.rst new file mode 100644 index 0000000000000000000000000000000000000000..5ed8e5803b549a557583bc7db2fa10e92556d604 --- /dev/null +++ b/es/core-libraries/file-folder.rst @@ -0,0 +1,16 @@ +Folder & File +############# + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Folder & File + :description lang=es: The Folder and File utilities are convenience classes to help you read, write, and append to files; list files within a folder and other common directory related tasks. + :keywords lang=es: file,folder,cakephp utility,read file,write file,append file,recursively copy,copy options,folder path,class folder,file php,php files,change directory,file utilities,new folder,directory structure,delete file diff --git a/es/core-libraries/form.rst b/es/core-libraries/form.rst new file mode 100644 index 0000000000000000000000000000000000000000..77345fb7ed19c9e75ac885e17dfc4ce69361be35 --- /dev/null +++ b/es/core-libraries/form.rst @@ -0,0 +1,15 @@ +Modelless Forms +############### + +.. php:namespace:: Cake\Form + +.. php:class:: Form + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/core-libraries/global-constants-and-functions.rst b/es/core-libraries/global-constants-and-functions.rst index 597df72e7ac2311ccfc4a59e8dfbc4caa5e1dfba..dddb8aa52a779b37075453bc89a1ccbded02a427 100644 --- a/es/core-libraries/global-constants-and-functions.rst +++ b/es/core-libraries/global-constants-and-functions.rst @@ -2,238 +2,14 @@ Constants & Functions ##################### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -While most of your day-to-day work in CakePHP will be utilizing -core classes and methods, CakePHP features a number of global -convenience functions that may come in handy. Many of these -functions are for use with CakePHP classes (loading model or -component classes), but many others make working with arrays or -strings a little easier. - -We'll also cover some of the constants available in CakePHP -applications. Using these constants will help make upgrades more -smooth, but are also convenient ways to point to certain files or -directories in your CakePHP application. - -Global Functions -================ - -Here are CakePHP's globally available functions. Most of them -are just convenience wrappers for other CakePHP functionality, -such as debugging and translating content. - -.. php:function:: \_\_(string $string_id, [$formatArgs]) - - This function handles localization in CakePHP applications. The - ``$string_id`` identifies the ID for a translation. Strings - used for translations are treated as format strings for - ``sprintf()``. You can supply additional arguments to replace - placeholders in your string:: - - __('You have {0} unread messages', $number); - - .. note:: - - Check out the - :doc:`/core-libraries/internationalization-and-localization` - section for more information. - -.. php:function:: __c(string $msg, integer $category, mixed $args = null) - - Note that the category must be specified with an I18n class constant, instead of - only the constant name. The values are: - - - I18n::LC_ALL - LC_ALL - - I18n::LC_COLLATE - LC_COLLATE - - I18n::LC_CTYPE - LC_CTYPE - - I18n::LC_MONETARY - LC_MONETARY - - I18n::LC_NUMERIC - LC_NUMERIC - - I18n::LC_TIME - LC_TIME - - I18n::LC_MESSAGES - LC_MESSAGES - -.. php:function:: __d(string $domain, string $msg, mixed $args = null) - - Allows you to override the current domain for a single message lookup. - - Useful when internationalizing a plugin: - ``echo __d('PluginName', 'This is my plugin');`` - -.. php:function:: __dc(string $domain, string $msg, integer $category, mixed $args = null) - - Allows you to override the current domain for a single message lookup. It - also allows you to specify a category. - - Note that the category must be specified with an I18n class constant, instead of - only the constant name. The values are: - - - I18n::LC_ALL - LC_ALL - - I18n::LC_COLLATE - LC_COLLATE - - I18n::LC_CTYPE - LC_CTYPE - - I18n::LC_MONETARY - LC_MONETARY - - I18n::LC_NUMERIC - LC_NUMERIC - - I18n::LC_TIME - LC_TIME - - I18n::LC_MESSAGES - LC_MESSAGES - -.. php:function:: __dcn(string $domain, string $singular, string $plural, integer $count, integer $category, mixed $args = null) - - Allows you to override the current domain for a single plural message - lookup. It also allows you to specify a category. Returns correct plural - form of message identified by $singular and $plural for count $count from - domain $domain. - - Note that the category must be specified with an I18n class constant, instead of - only the constant name. The values are: - - - I18n::LC_ALL - LC_ALL - - I18n::LC_COLLATE - LC_COLLATE - - I18n::LC_CTYPE - LC_CTYPE - - I18n::LC_MONETARY - LC_MONETARY - - I18n::LC_NUMERIC - LC_NUMERIC - - I18n::LC_TIME - LC_TIME - - I18n::LC_MESSAGES - LC_MESSAGES - -.. php:function:: __dn(string $domain, string $singular, string $plural, integer $count, mixed $args = null) - - Allows you to override the current domain for a single plural message - lookup. Returns correct plural form of message identified by $singular and - $plural for count $count from domain $domain. - -.. php:function:: __n(string $singular, string $plural, integer $count, mixed $args = null) - - Returns correct plural form of message identified by $singular and $plural - for count $count. Some languages have more than one form for plural - messages dependent on the count. - -.. php:function:: debug(mixed $var, boolean $showHtml = null, $showFrom = true) - - If the core ``$debug`` variable is true, $var is printed out. - If ``$showHTML`` is true or left as null, the data is rendered to be - browser-friendly. - If ``$showFrom`` is not set to false, the debug output will start with the line from - which it was called. - Also see :doc:`/development/debugging` - -.. php:function:: env(string $key) - - Gets an environment variable from available sources. Used as a - backup if ``$_SERVER`` or ``$_ENV`` are disabled. - - This function also emulates PHP\_SELF and DOCUMENT\_ROOT on - unsupporting servers. In fact, it's a good idea to always use - ``env()`` instead of ``$_SERVER`` or ``getenv()`` (especially if - you plan to distribute the code), since it's a full emulation - wrapper. - -.. php:function:: h(string $text, boolean $double = true, string $charset = null) - - Convenience wrapper for ``htmlspecialchars()``. - -.. php:function:: pluginSplit(string $name, boolean $dotAppend = false, string $plugin = null) - - Splits a dot syntax plugin name into its plugin and class name. If $name - does not have a dot, then index 0 will be null. - - Commonly used like ``list($plugin, $name) = pluginSplit('Users.User');`` - -.. php:function:: pr(mixed $var) - - Convenience wrapper for ``print_r()``, with the addition of - wrapping
     tags around the output.
    -
    -Core Definition Constants
    -=========================
    -
    -Most of the following constants refer to paths in your application.
    -
    -.. php:const:: APP
    -
    -   Absolute path to your application directory, including a trailing slash.
    -
    -.. php:const:: APP_DIR
    -
    -    Equals ``app`` or the name of your application directory.
    -
    -.. php:const:: CACHE
    -
    -    Path to the cache files directory. It can be shared between hosts in a
    -    multi-server setup.
    -
    -.. php:const:: CAKE
    -
    -    Path to the cake directory.
    -
    -.. php:const:: CAKE_CORE_INCLUDE_PATH
    -
    -    Path to the root lib directory.
    -
    -.. php:const:: CORE_PATH
    -
    -   Path to the root directory with ending directory slash.
    -
    -.. php:const:: DS
    -
    -    Short for PHP's DIRECTORY\_SEPARATOR, which is / on Linux and \\ on windows.
    -
    -.. php:const:: LOGS
    -
    -    Path to the logs directory.
    -
    -.. php:const:: ROOT
    -
    -    Path to the root directory.
    -
    -.. php:const:: TESTS
    -
    -    Path to the tests directory.
    -
    -.. php:const:: TMP
    -
    -    Path to the temporary files directory.
    -
    -.. php:const:: WWW\_ROOT
    -
    -    Full path to the webroot.
    -
    -
    -Timing Definition Constants
    -===========================
    -
    -.. php:const:: TIME_START
    -
    -    Unix timestamp in microseconds as a float from when the application started.
    -
    -.. php:const:: SECOND
    -
    -    Equals 1
    -
    -.. php:const:: MINUTE
    -
    -    Equals 60
    -
    -.. php:const:: HOUR
    -
    -    Equals 3600
    -
    -.. php:const:: DAY
    -
    -    Equals 86400
    -
    -.. php:const:: WEEK
    -
    -    Equals 604800
    -
    -.. php:const:: MONTH
    -
    -    Equals 2592000
    -
    -.. php:const:: YEAR
    -
    -    Equals 31536000
    +    Por favor, siéntase libre de enviarnos un pull request en
    +    `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios.
     
    +    Usted puede hacer referencia a la versión en Inglés en el menú de selección superior
    +    para obtener información sobre el tema de esta página.
     
     .. meta::
    -    :title lang=en: Global Constants and Functions
    -    :keywords lang=en: internationalization and localization,global constants,example config,array php,convenience functions,core libraries,component classes,optional number,global functions,string string,core classes,format strings,unread messages,placeholders,useful functions,sprintf,arrays,parameters,existence,translations
    +    :title lang=es: Global Constants and Functions
    +    :keywords lang=es: internationalization and localization,global constants,example config,array php,convenience functions,core libraries,component classes,optional number,global functions,string string,core classes,format strings,unread messages,placeholders,useful functions,sprintf,arrays,parameters,existence,translations
    diff --git a/es/core-libraries/hash.rst b/es/core-libraries/hash.rst
    new file mode 100644
    index 0000000000000000000000000000000000000000..f29389a73b01b1e2b02b6aa235560c627201767f
    --- /dev/null
    +++ b/es/core-libraries/hash.rst
    @@ -0,0 +1,15 @@
    +Hash
    +####
    +
    +.. note::
    +    La documentación no es compatible actualmente con el idioma español en esta página.
    +
    +    Por favor, siéntase libre de enviarnos un pull request en
    +    `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios.
    +
    +    Usted puede hacer referencia a la versión en Inglés en el menú de selección superior
    +    para obtener información sobre el tema de esta página.
    +
    +.. meta::
    +    :title lang=es: Hash
    +    :keywords lang=es: array array,path array,array name,numeric key,regular expression,result set,person name,brackets,syntax,cakephp,elements,php,set path
    diff --git a/es/core-libraries/helpers/flash.rst b/es/core-libraries/helpers/flash.rst
    deleted file mode 100644
    index 7cd3f86299d992c8457a9d7a42cc16b1b9f2a8e0..0000000000000000000000000000000000000000
    --- a/es/core-libraries/helpers/flash.rst
    +++ /dev/null
    @@ -1,53 +0,0 @@
    -FlashHelper
    -###########
    -
    -.. note::
    -    Esta página todavía no ha sido traducida y pertenece a la documentación de
    -    CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación
    -    desde Github `_.
    -
    -.. php:namespace:: Cake\View\Helper
    -
    -.. php:class:: FlashHelper(View $view, array $config = [])
    -
    -FlashHelper provides a way to render flash messages that were set in
    -``$_SESSION`` by :doc:`FlashComponent `.
    -:doc:`FlashComponent ` and FlashHelper
    -primarily use elements to render flash messages.  Flash elements are found under
    -the ``src/Template/Element/Flash`` directory.  You'll notice that CakePHP's App
    -template comes with two flash elements: ``success.ctp`` and ``error.ctp``.
    -
    -Rendering Flash Messages
    -========================
    -
    -To render a flash message, you can simply use FlashHelper's ``render()``
    -method::
    -
    -    Flash->render() ?>
    -
    -By default, CakePHP uses a "flash" key for flash messages in a session.  But, if
    -you've specified a key when setting the flash message in
    -:doc:`FlashComponent `, you can specify which
    -flash key to render::
    -
    -    Flash->render('other') ?>
    -
    -You can also override any of the options that were set in FlashComponent::
    -
    -    // In your Controller
    -    $this->Flash->set('The user has been saved.', [
    -        'element' => 'success'
    -    ]);
    -
    -    // In your View: Will use great_success.ctp instead of succcess.ctp
    -    Flash->render('flash', [
    -        'element' => 'great_success'
    -    ]);
    -
    -.. note::
    -    By default, CakePHP does not escape the HTML in flash messages. If you are using
    -    any request or user data in your flash messages, you should escape it
    -    with :php:func:`h` when formatting your messages.
    -
    -For more information about the available array options, please refer to the
    -:doc:`FlashComponent ` section.
    diff --git a/es/core-libraries/helpers/form.rst b/es/core-libraries/helpers/form.rst
    deleted file mode 100644
    index a925fec19d51033c1f75f9155af8fd4fa2138c42..0000000000000000000000000000000000000000
    --- a/es/core-libraries/helpers/form.rst
    +++ /dev/null
    @@ -1,1681 +0,0 @@
    -FormHelper
    -##########
    -
    -.. note::
    -    Esta página todavía no ha sido traducida y pertenece a la documentación de
    -    CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación
    -    desde Github `_.
    -
    -.. php:namespace:: Cake\View\Helper
    -
    -.. php:class:: FormHelper(View $view, array $config = [])
    -
    -The FormHelper does most of the heavy lifting in form creation.  The FormHelper
    -focuses on creating forms quickly, in a way that will streamline validation,
    -re-population and layout. The FormHelper is also flexible - it will do almost
    -everything for you using conventions, or you can use specific methods to get
    -only what you need.
    -
    -Starting a Form
    -===============
    -
    -.. php:method:: create(mixed $model = null, array $options = [])
    -
    -The first method you'll need to use in order to take advantage of the FormHelper
    -is ``create()``. This method outputs an opening form tag.
    -
    -All parameters are optional. If ``create()`` is called with no parameters
    -supplied, it assumes you are building a form that submits to the current
    -controller, via the current URL. The default method for form submission is POST.
    -If you were to call ``create()`` inside the view for UsersController::add(), you would see
    -something like the following output in the rendered view:
    -
    -.. code-block:: html
    -
    -    
    -
    -The ``$model`` argument is used as the form's 'context'. There are several
    -built-in form contexts and you can add your own, which we'll cover in the next
    -section. The built-in providers map to the following values of ``$model``:
    -
    -* An ``Entity`` instance or, an iterator map to the ``EntityContext``, this
    -  context allows FormHelper to work with results from the built-in ORM.
    -* An array containing the ``schema`` key, maps to ``ArrayContext`` which allows
    -  you to create simple data structures to build forms against.
    -* ``null`` and ``false`` map to the ``NullContext``, this context class simply
    -  satisifies the interface FormHelper requires. This context is useful if you
    -  want to build a short form that doesn't require ORM persistence.
    -
    -All contexts classes also have access to the request data, making it simpler to
    -build forms.
    -
    -Once a form has been created with a context, all inputs you create will use the
    -active context. In the case of an ORM backed form, FormHelper can access
    -associated data, validation errors and schema metadata easily making building
    -forms simple.  You can close the active context using the ``end()`` method, or
    -by calling ``create()`` again. To create a form for an entity, do the
    -following::
    -
    -    // If you are on /articles/add
    -    // $article should be an empty Article entity.
    -    echo $this->Form->create($article);
    -
    -Output:
    -
    -.. code-block:: html
    -
    -    
    -
    -This will POST the form data to the ``add()`` action of ArticlesController.
    -However, you can also use the same logic to create an edit form. The FormHelper
    -uses the ``$this->request->data`` property to automatically detect whether to
    -create an add or edit form. If the provided entity is not 'new', the form will
    -be created as an edit form.  For example, if we browse to
    -http://example.org/articles/edit/5, we could do the following::
    -
    -    // src/Controller/ArticlesController.php:
    -    public function edit($id = null)
    -    {
    -        if (empty($id)) {
    -            throw new NotFoundException;
    -        }
    -        $article = $this->Articles->get($id);
    -        // Save logic goes here
    -        $this->set('article', $article);
    -    }
    -
    -    // View/Articles/edit.ctp:
    -    // Since $article->isNew() is false, we will get an edit form
    -    Form->create($article) ?>
    -
    -Output:
    -
    -.. code-block:: html
    -
    -    
    -    
    -
    -.. note::
    -
    -    Since this is an edit form, a hidden input field is generated to
    -    override the default HTTP method.
    -
    -The ``$options`` array is where most of the form configuration
    -happens. This special array can contain a number of different
    -key-value pairs that affect the way the form tag is generated.
    -
    -
    -Changing the HTTP Method for a Form
    ------------------------------------
    -
    -By using the ``type`` option you can change the HTTP method a form will use::
    -
    -    echo $this->Form->create($article, ['type' => 'get']);
    -
    -Output:
    -
    -.. code-block:: html
    -
    -    
    -
    -Specifying 'file' changes the form submission method to 'post', and includes an
    -enctype of "multipart/form-data" on the form tag. This is to be used if there
    -are any file elements inside the form. The absence of the proper enctype
    -attribute will cause the file uploads not to function::
    -
    -    echo $this->Form->create($article, ['type' => 'file']);
    -
    -Output:
    -
    -.. code-block:: html
    -
    -   
    -
    -When using 'put', 'patch' or 'delete', your form will be functionally equivalent
    -to a 'post' form, but when submitted, the HTTP request method will be overridden
    -with 'PUT', 'PATCH' or 'DELETE', respectively.  This allows CakePHP to emulate
    -proper REST support in web browsers.
    -
    -Setting the Controller Action for the Form
    -------------------------------------------
    -
    -Using the ``action`` option allows  you to point the form to a
    -specific action in your current controller. For example, if you'd like to
    -point the form to the login() action of the current controller, you would
    -supply an $options array like the following::
    -
    -    echo $this->Form->create($article, ['action' => 'login']);
    -
    -Output:
    -
    -.. code-block:: html
    -
    -    
    -
    -Setting a URL for the Form
    ---------------------------
    -
    -If the desired form action isn't in the current controller, you can specify
    -a URL for the form action using the 'url' key of the $options array. The
    -supplied URL can be relative to your CakePHP application::
    -
    -    echo $this->Form->create(null, [
    -        'url' => ['controller' => 'Articles', 'action' => 'publish']
    -    ]);
    -
    -Output:
    -
    -.. code-block:: html
    -
    -    
    -
    -or can point to an external domain::
    -
    -    echo $this->Form->create(null, [
    -        'url' => 'http://www.google.com/search',
    -        'type' => 'get'
    -    ]);
    -
    -Output:
    -
    -.. code-block:: html
    -
    -    
    -
    -Using Custom Validators
    ------------------------
    -
    -Often models will have multiple validation sets, and you will want FormHelper to
    -mark fields required based on a the specific validation rules your controller
    -action is going to apply. For example, your Users table has specific validation
    -rules that only apply when an account is being registered::
    -
    -    echo $this->Form->create($user, [
    -        'context' => ['validator' => 'register']
    -    ]);
    -
    -Creating context classes
    -------------------------
    -
    -While the built-in context classes are intended to cover the basic cases you'll
    -encounter you may need to build a new context class if you are using a different
    -ORM. In these situations you need to implement the
    -`Cake\\View\\Form\\ContextInterface
    -`_ . Once
    -you have implemented this interface you can wire your new context into the
    -FormHelper. It is often best to do this in a ``View.beforeRender`` event
    -listener, or in an application view class::
    -
    -    $this->Form->addContextProvider('myprovider', function($request, $data) {
    -        if ($data['entity'] instanceof MyOrmClass) {
    -            return new MyProvider($request, $data);
    -        }
    -    });
    -
    -Context factory functions are where you can add logic for checking the form
    -options for the correct type of entity. If matching input data is found you can
    -return an object. If there is no match return null.
    -
    -.. _automagic-form-elements:
    -
    -Creating Form Inputs
    -====================
    -
    -.. php:method:: input(string $fieldName, array $options = [])
    -
    -The ``input()`` method lets you easily generate complete form inputs. These
    -inputs will include a wrapping div, label, input widget, and validation error if
    -necessary. By using the metadata in the form context, this method will choose an
    -appropriate input type for each field. Internally ``input()`` uses the other
    -methods of FormHelper.
    -
    -The type of input created depends on the column datatype:
    -
    -Column Type
    -    Resulting Form Field
    -string, uuid (char, varchar, etc.)
    -    text
    -boolean, tinyint(1)
    -    checkbox
    -decimal
    -    number
    -float
    -    number
    -integer
    -    number
    -text
    -    textarea
    -text, with name of password, passwd
    -    password
    -text, with name of email
    -    email
    -text, with name of tel, telephone, or phone
    -    tel
    -date
    -    day, month, and year selects
    -datetime, timestamp
    -    day, month, year, hour, minute, and meridian selects
    -time
    -    hour, minute, and meridian selects
    -binary
    -    file
    -
    -The ``$options`` parameter allows you to choose a specific input type if
    -you need to::
    -
    -    echo $this->Form->input('published', ['type' => 'checkbox']);
    -
    -.. _html5-required:
    -
    -The wrapping div will have a ``required`` class name appended if the
    -validation rules for the model's field indicate that it is required and not
    -allowed to be empty. You can disable automatic required flagging using the
    -required option::
    -
    -    echo $this->Form->input('title', ['required' => false]);
    -
    -To skip browser validation triggering for the whole form you can set option
    -``'formnovalidate' => true`` for the input button you generate using
    -:php:meth:`~Cake\\View\\Helper\\FormHelper::submit()` or set ``'novalidate' =>
    -true`` in options for :php:meth:`~Cake\\View\\Helper\\FormHelper::create()`.
    -
    -For example, let's assume that your User model includes fields for a
    -username (varchar), password (varchar), approved (datetime) and
    -quote (text). You can use the input() method of the FormHelper to
    -create appropriate inputs for all of these form fields::
    -
    -    echo $this->Form->create($user);
    -    // Text
    -    echo $this->Form->input('username');
    -    // Password
    -    echo $this->Form->input('password');
    -    // Day, month, year, hour, minute, meridian
    -    echo $this->Form->input('approved');
    -    // Textarea
    -    echo $this->Form->input('quote');
    -
    -    echo $this->Form->button('Add');
    -    echo $this->Form->end();
    -
    -A more extensive example showing some options for a date field::
    -
    -    echo $this->Form->input('birth_dt', [
    -        'label' => 'Date of birth',
    -        'minYear' => date('Y') - 70,
    -        'maxYear' => date('Y') - 18,
    -    ]);
    -
    -Besides the specific options for ``input()`` found below, you can specify
    -any option for the input type & any HTML attribute (for instance ``onfocus``).
    -
    -Assuming that User BelongsToMany Group. In your controller, set a
    -camelCase plural variable (group -> groups in this case, or ExtraFunkyModel
    --> extraFunkyModels) with the select options. In the controller action you
    -would put the following::
    -
    -    $this->set('groups', $this->Users->Groups->find('list'));
    -
    -And in the view a multiple select can be created with this simple
    -code::
    -
    -    echo $this->Form->input('groups._ids', ['options' => $groups]);
    -
    -If you want to create a select field while using a belongsTo - or
    -hasOne - Relation, you can add the following to your Users-controller
    -(assuming your User belongsTo Group)::
    -
    -    $this->set('groups', $this->Users->Groups->find('list'));
    -
    -Afterwards, add the following to your view template::
    -
    -    echo $this->Form->input('group_id', ['options' => $groups]);
    -
    -If your model name consists of two or more words, e.g.,
    -"UserGroup", when passing the data using set() you should name your
    -data in a pluralised and camelCased format as follows::
    -
    -    $this->set('userGroups', $this->UserGroups->find('list'));
    -
    -.. note::
    -
    -    You should not use ``FormHelper::input()`` to generate submit buttons. Use
    -    :php:meth:`~Cake\\View\\Helper\\FormHelper::submit()` instead.
    -
    -Field Naming Conventions
    -------------------------
    -
    -When creating input widgets you should name your fields after the matching
    -attributes in the form's entity. For example, if you created a form for an
    -``$article``, you would create fields named after the properities. E.g
    -``title``, ``body`` and ``published``.
    -
    -You can create inputs for associated models, or arbitrary models by passing in
    -``association.fieldname`` as the first parameter::
    -
    -    echo $this->Form->input('association.fieldname');
    -
    -Any dots in your field names will be converted into nested request data. For
    -example, if you created a field with a name ``0.comments.body`` you would get
    -a name attribute that looks like ``0[comments][body]``. This convention makes it
    -easy to save data with the ORM.
    -
    -When creating datetime related inputs, FormHelper will append a field-suffix.
    -You may notice additional fields named ``year``, ``month``, ``day``, ``hour``,
    -``minute``, or ``meridian`` being added. These fields will be automatically
    -converted into ``DateTime`` objects when entities are marshalled.
    -
    -
    -Options
    --------
    -
    -``FormHelper::input()`` supports a large number of options. In addition to its
    -own options ``input()`` accepts options for the generated input types, as well as
    -HTML attributes. The following will cover the options specific to
    -``FormHelper::input()``.
    -
    -* ``$options['type']`` You can force the type of an input, overriding model
    -  introspection, by specifying a type. In addition to the field types found in
    -  the :ref:`automagic-form-elements`, you can also create 'file', 'password',
    -  and any type supported by HTML5::
    -
    -    echo $this->Form->input('field', ['type' => 'file']);
    -    echo $this->Form->input('email', ['type' => 'email']);
    -
    -  Output:
    -
    -  .. code-block:: html
    -
    -    
    - - -
    - - -* ``$options['label']`` Set this key to the string you would like to be - displayed within the label that usually accompanies the input:: - - echo $this->Form->input('name', [ - 'label' => 'The User Alias' - ]); - - Output: - - .. code-block:: html - -
    - - -
    - - Alternatively, set this key to false to disable the output of the - label:: - - echo $this->Form->input('name', ['label' => false]); - - Output: - - .. code-block:: html - -
    - -
    - - Set this to an array to provide additional options for the - ``label`` element. If you do this, you can use a ``text`` key in - the array to customize the label text:: - - echo $this->Form->input('name', [ - 'label' => [ - 'class' => 'thingy', - 'text' => 'The User Alias' - ] - ]); - - Output: - - .. code-block:: html - -
    - - -
    - -* ``$options['error']`` Using this key allows you to override the default model - error messages and can be used, for example, to set i18n messages. It has a - number of suboptions which control the wrapping element, wrapping element - class name, and whether HTML in the error message will be escaped. - - To disable error message output & field classes set the error key to false:: - - echo $this->Form->input('name', ['error' => false]); - - To override the model error messages use an array with - the keys matching the validation rule names:: - - $this->Form->input('name', [ - 'error' => ['tooShort' => __('This is not long enough')] - ]); - - As seen above you can set the error message for each validation - rule you have in your models. In addition you can provide i18n - messages for your forms. - -Generating Specific Types of Inputs -=================================== - -In addition to the generic ``input()`` method, ``FormHelper`` has specific -methods for generating a number of different types of inputs. These can be used -to generate just the input widget itself, and combined with other methods like -:php:meth:`~Cake\\View\\Helper\\FormHelper::label()` and -:php:meth:`~Cake\\View\\Helper\\FormHelper::error()` to generate fully custom -form layouts. - -.. _general-input-options: - -Common Options --------------- - -Many of the various input element methods support a common set of options. All -of these options are also supported by ``input()``. To reduce repetition the -common options shared by all input methods are as follows: - -* ``$options['id']`` Set this key to force the value of the DOM id for the input. - This will override the idPrefix that may be set. - -* ``$options['default']`` Used to set a default value for the input field. The - value is used if the data passed to the form does not contain a value for the - field (or if no data is passed at all). - - Example usage:: - - echo $this->Form->text('ingredient', ['default' => 'Sugar']); - - Example with select field (Size "Medium" will be selected as - default):: - - $sizes = ['s' => 'Small', 'm' => 'Medium', 'l' => 'Large']; - echo $this->Form->select('size', $sizes, ['default' => 'm']); - - .. note:: - - You cannot use ``default`` to check a checkbox - instead you might - set the value in ``$this->request->data`` in your controller, - or set the input option ``checked`` to true. - - Date and datetime fields' default values can be set by using the - 'selected' key. - - Beware of using false to assign a default value. A false value is used to - disable/exclude options of an input field, so ``'default' => false`` would - not set any value at all. Instead use ``'default' => 0``. - -In addition to the above options, you can mixin any HTML attribute you wish to -use. Any non-special option name will be treated as an HTML attribute, and -applied to the generated HTML input element. - - -Options for Select, Checkbox and Radio Inputs ---------------------------------------------- - -* ``$options['value']`` Used in combination with a select-type input (i.e. - For types select, date, time, datetime). Set 'selected' to the value of the - item you wish to be selected by default when the input is rendered:: - - echo $this->Form->time('close_time', [ - 'value' => '13:30:00' - ]); - - .. note:: - - The value key for date and datetime inputs may also be a UNIX - timestamp, or a DateTime object. - -* ``$options['empty']`` If set to true, forces the input to remain empty. - - When passed to a select list, this creates a blank option with an - empty value in your drop down list. If you want to have a empty - value with text displayed instead of just a blank option, pass in a - string to empty:: - - echo $this->Form->select( - 'field', - [1, 2, 3, 4, 5], - ['empty' => '(choose one)'] - ); - - Output: - - .. code-block:: html - -
    - - -
    - - .. note:: - - If you need to set the default value in a password field to blank, - use 'value' => '' instead. - - Options can also supplied as key-value pairs. - -* ``$options['hiddenField']`` For certain input types (checkboxes, radios) a - hidden input is created so that the key in $this->request->data will exist - even without a value specified: - - .. code-block:: html - - - - - This can be disabled by setting the ``$options['hiddenField'] = false``:: - - echo $this->Form->checkbox('published', ['hiddenField' => false]); - - Which outputs: - - .. code-block:: html - - - - If you want to create multiple blocks of inputs on a form that are - all grouped together, you should use this parameter on all inputs - except the first. If the hidden input is on the page in multiple - places, only the last group of input's values will be saved - - In this example, only the tertiary colors would be passed, and the - primary colors would be overridden: - - .. code-block:: html - -

    Primary Colors

    - - - - - - - - -

    Tertiary Colors

    - - - - - - - - - Disabling the ``'hiddenField'`` on the second input group would - prevent this behavior. - - You can set a different hidden field value other than 0 such as 'N':: - - echo $this->Form->checkbox('published', ] - 'value' => 'Y', - 'hiddenField' => 'N', - ]); - -Datetime Options ----------------- - -* ``$options['timeFormat']`` Used to specify the format of the select inputs for - a time-related set of inputs. Valid values include ``12``, ``24``, and ``null``. - -* ``$options['minYear'], $options['maxYear']`` Used in combination with a - date/datetime input. Defines the lower and/or upper end of values shown in the - years select field. - -* ``$options['orderYear']`` Used in combination with a date/datetime input. - Defines the order in which the year values will be set. Valid values include - 'asc', 'desc'. The default value is 'desc'. - -* ``$options['interval']`` This option specifies the number of minutes between - each option in the minutes select box:: - - echo $this->Form->input('Model.time', [ - 'type' => 'time', - 'interval' => 15 - ]); - - Would create 4 options in the minute select. One for each 15 - minutes. - -* ``$options['round']`` Can be set to `up` or `down` to force rounding in either direction. - Defaults to null which rounds half up according to `interval`. - -* ``$options['monthNames']`` If false, 2 digit numbers will be used instead of text. - If it is given an array like ``['01' => 'Jan', '02' => 'Feb', ...]`` then the given array will be used. - -Creating Input Elements -======================= - -Creating Text Inputs --------------------- - -.. php:method:: text(string $name, array $options) - -The rest of the methods available in the FormHelper are for -creating specific form elements. Many of these methods also make -use of a special $options parameter. In this case, however, -$options is used primarily to specify HTML tag attributes (such as -the value or DOM id of an element in the form):: - - echo $this->Form->text('username', ['class' => 'users']); - -Will output: - -.. code-block:: html - - - -Creating Password Inputs ------------------------- - -.. php:method:: password(string $fieldName, array $options) - -Creates a password field. :: - - echo $this->Form->password('password'); - -Will output: - -.. code-block:: html - - - -Creating Hidden Inputs ----------------------- - -.. php:method:: hidden(string $fieldName, array $options) - -Creates a hidden form input. Example:: - - echo $this->Form->hidden('id'); - -Will output: - -.. code-block:: html - - - -Creating Textareas ------------------- - -.. php:method:: textarea(string $fieldName, array $options) - -Creates a textarea input field. :: - - echo $this->Form->textarea('notes'); - -Will output: - -.. code-block:: html - - - -If the form is edited (that is, the array ``$this->request->data`` will -contain the information saved for the ``User`` model), the value -corresponding to ``notes`` field will automatically be added to the HTML -generated. Example: - -.. code-block:: html - - - -.. note:: - - The ``textarea`` input type allows for the ``$options`` attribute - of ``'escape'`` which determines whether or not the contents of the - textarea should be escaped. Defaults to ``true``. - -:: - - echo $this->Form->textarea('notes', ['escape' => false]); - // OR.... - echo $this->Form->input('notes', ['type' => 'textarea', 'escape' => false]); - - -**Options** - -In addition to the :ref:`general-input-options`, textarea() supports a few -specific options: - -* ``$options['rows'], $options['cols']`` These two keys specify the number of - rows and columns:: - - echo $this->Form->textarea('textarea', ['rows' => '5', 'cols' => '5']); - - Output: - -.. code-block:: html - - - -Creating Checkboxes -------------------- - -.. php:method:: checkbox(string $fieldName, array $options) - -Creates a checkbox form element. This method also generates an -associated hidden form input to force the submission of data for -the specified field. :: - - echo $this->Form->checkbox('done'); - -Will output: - -.. code-block:: html - - - - -It is possible to specify the value of the checkbox by using the -$options array:: - - echo $this->Form->checkbox('done', ['value' => 555]); - -Will output: - -.. code-block:: html - - - - -If you don't want the Form helper to create a hidden input:: - - echo $this->Form->checkbox('done', ['hiddenField' => false]); - -Will output: - -.. code-block:: html - - - - -Creating Radio Buttons ----------------------- - -.. php:method:: radio(string $fieldName, array $options, array $attributes) - -Creates a set of radio button inputs. - -**Options** - -* ``$attributes['value']`` to set which value should be selected default. - -* ``$attributes['disabled']`` Setting this to ``true`` or ``'disabled'`` - will disable all of the generated radio buttons. - -* ``$attributes['legend']`` Radio elements are wrapped with a legend and - fieldset by default. Set ``$attributes['legend']`` to false to remove - them. :: - - $options = ['M' => 'Male', 'F' => 'Female']; - $attributes = ['legend' => false]; - echo $this->Form->radio('gender', $options, $attributes); - - Will output: - - .. code-block:: html - - - - - - - -If for some reason you don't want the hidden input, setting -``$attributes['value']`` to a selected value or boolean false will -do just that. - -Creating Select Pickers ------------------------ - -.. php:method:: select(string $fieldName, array $options, array $attributes) - -Creates a select element, populated with the items in ``$options``, -with the option specified by ``$attributes['value']`` shown as selected by -default. Set the 'empty' key in the ``$attributes`` variable to false to -turn off the default empty option:: - - $options = ['M' => 'Male', 'F' => 'Female']; - echo $this->Form->select('gender', $options); - -Will output: - -.. code-block:: html - - - -The ``select`` input type allows for a special ``$option`` -attribute called ``'escape'`` which accepts a bool and determines -whether to HTML entity encode the contents of the select options. -Defaults to true:: - - $options = ['M' => 'Male', 'F' => 'Female']; - echo $this->Form->select('gender', $options, ['escape' => false]); - -* ``$attributes['options']`` This key allows you to manually specify options for a - select input, or for a radio group. Unless the 'type' is specified as 'radio', - the FormHelper will assume that the target output is a select input:: - - echo $this->Form->select('field', [1,2,3,4,5]); - - Output: - - .. code-block:: html - - - - Options can also be supplied as key-value pairs:: - - echo $this->Form->select('field', [ - 'Value 1' => 'Label 1', - 'Value 2' => 'Label 2', - 'Value 3' => 'Label 3' - ]); - - Output: - - .. code-block:: html - - - - If you would like to generate a select with optgroups, just pass - data in hierarchical format. This works on multiple checkboxes and radio - buttons too, but instead of optgroups wraps elements in fieldsets:: - - $options = [ - 'Group 1' => [ - 'Value 1' => 'Label 1', - 'Value 2' => 'Label 2' - ], - 'Group 2' => [ - 'Value 3' => 'Label 3' - ] - ]; - echo $this->Form->select('field', $options); - - Output: - - .. code-block:: html - - - -* ``$attributes['multiple']`` If 'multiple' has been set to ``true`` for an - input that outputs a select, the select will allow multiple selections:: - - echo $this->Form->select('Model.field', $options, ['multiple' => true]); - - Alternatively set 'multiple' to 'checkbox' to output a list of - related check boxes:: - - $options = [ - 'Value 1' => 'Label 1', - 'Value 2' => 'Label 2' - ]; - echo $this->Form->select('Model.field', $options, [ - 'multiple' => 'checkbox' - ]); - - Output: - - .. code-block:: html - - -
    - - -
    -
    - - -
    - -* ``$attributes['disabled']`` When creating checkboxes, this option can be set - to disable all or some checkboxes. To disable all checkboxes set disabled - to ``true``:: - - $options = [ - 'Value 1' => 'Label 1', - 'Value 2' => 'Label 2' - ]; - echo $this->Form->select('Model.field', $options, [ - 'multiple' => 'checkbox', - 'disabled' => ['Value 1'] - ]); - - Output: - - .. code-block:: html - - -
    - - -
    -
    - - -
    - -Creating File Inputs --------------------- - -.. php:method:: file(string $fieldName, array $options) - -To add a file upload field to a form, you must first make sure that -the form enctype is set to "multipart/form-data", so start off with -a create function such as the following:: - - echo $this->Form->create($document, ['enctype' => 'multipart/form-data']); - // OR - echo $this->Form->create($document, ['type' => 'file']); - -Next add either of the two lines to your form view file:: - - echo $this->Form->input('submittedfile', [ - 'type' => 'file' - ]); - - // OR - echo $this->Form->file('submittedfile'); - -Due to the limitations of HTML itself, it is not possible to put -default values into input fields of type 'file'. Each time the form -is displayed, the value inside will be empty. - -Upon submission, file fields provide an expanded data array to the -script receiving the form data. - -For the example above, the values in the submitted data array would -be organized as follows, if the CakePHP was installed on a Windows -server. 'tmp\_name' will have a different path in a Unix -environment:: - - $this->request->data['submittedfile'] = [ - 'name' => 'conference_schedule.pdf', - 'type' => 'application/pdf', - 'tmp_name' => 'C:/WINDOWS/TEMP/php1EE.tmp', - 'error' => 0, // On Windows this can be a string. - 'size' => 41737, - ]; - -This array is generated by PHP itself, so for more detail on the -way PHP handles data passed via file fields -`read the PHP manual section on file uploads `_. - -.. note:: - - When using ``$this->Form->file()``, remember to set the form - encoding-type, by setting the type option to 'file' in - ``$this->Form->create()`` - -Creating Date and Time Inputs ------------------------------ - -.. php:method:: dateTime($fieldName, $options = []) - -Creates a set of select inputs for date and time. This method accepts a number -of options: - -* ``monthNames`` If false, 2 digit numbers will be used instead of text. - If an array, the given array will be used. -* ``minYear`` The lowest year to use in the year select -* ``maxYear`` The maximum year to use in the year select -* ``interval`` The interval for the minutes select. Defaults to 1 -* ``empty`` - If true, the empty select option is shown. If a string, - that string is displayed as the empty element. -* ``round`` - Set to ``up`` or ``down`` if you want to force rounding in either direction. Defaults to null. -* ``default`` The default value to be used by the input. A value in ``$this->request->data`` - matching the field name will override this value. If no default is provided ``time()`` will be used. -* ``timeFormat`` The time format to use, either 12 or 24. -* ``second`` Set to true to enable seconds drop down. - -To control the order of inputs, and any elements/content between the inputs you -can override the ``dateWidget`` template. By default the ``dateWidget`` template -is:: - - {{year}}{{month}}{{day}}{{hour}}{{minute}}{{second}}{{meridian}} - -Creating Year Inputs --------------------- - -.. php:method:: year(string $fieldName, array $options = []) - -Creates a select element populated with the years from ``minYear`` -to ``maxYear``. Additionally, HTML attributes may be supplied in $options. If -``$options['empty']`` is false, the select will not include an -empty option: - -* ``empty`` - If true, the empty select option is shown. If a string, - that string is displayed as the empty element. -* ``orderYear`` - Ordering of year values in select options. - Possible values 'asc', 'desc'. Default 'desc' -* ``value`` The selected value of the input. -* ``maxYear`` The max year to appear in the select element. -* ``minYear`` The min year to appear in the select element. - -For example, to create a year range range from 2000 to the current year you -would do the following:: - - echo $this->Form->year('purchased', [ - 'minYear' => 2000, - 'maxYear' => date('Y') - ]); - -If it was 2009, you would get the following: - -.. code-block:: html - - - -Creating Month Inputs ---------------------- - -.. php:method:: month(string $fieldName, array $attributes) - -Creates a select element populated with month names:: - - echo $this->Form->month('mob'); - -Will output: - -.. code-block:: html - - - -You can pass in your own array of months to be used by setting the -'monthNames' attribute, or have months displayed as numbers by -passing false. (Note: the default months can be localized with CakePHP -:doc:`/core-libraries/internationalization-and-localization` features.):: - - echo $this->Form->month('mob', ['monthNames' => false]); - -Creating Day Inputs --------------------- - -.. php:method:: day(string $fieldName, array $attributes) - -Creates a select element populated with the (numerical) days of the -month. - -To create an empty option with prompt text of your choosing (e.g. -the first option is 'Day'), you can supply the text as the final -parameter as follows:: - - echo $this->Form->day('created'); - -Will output: - -.. code-block:: html - - - -Creating Hour Inputs --------------------- - -.. php:method:: hour(string $fieldName, array $attributes) - -Creates a select element populated with the hours of the day. You can -create either 12 or 24 hour pickers using the format option:: - - echo $this->Form->hour('created', [ - 'format' => 12 - ]); - echo $this->Form->hour('created', [ - 'format' => 24 - ]); - -Creating Minute Inputs ----------------------- - -.. php:method:: minute(string $fieldName, array $attributes) - -Creates a select element populated with the minutes of the hour. You -can create a select that only contains specific values using the ``interval`` -option. For example, if you wanted 10 minute increments you would do the -following:: - - echo $this->Form->minute('created', [ - 'interval' => 10 - ]); - -Creating Meridian Inputs ------------------------- - -.. php:method:: meridian(string $fieldName, array $attributes) - -Creates a select element populated with 'am' and 'pm'. - -Creating Labels -=============== - -.. php:method:: label(string $fieldName, string $text, array $options) - -Create a label element. ``$fieldName`` is used for generating the -DOM id. If ``$text`` is undefined, ``$fieldName`` will be used to inflect -the label's text:: - - echo $this->Form->label('User.name'); - echo $this->Form->label('User.name', 'Your username'); - -Output: - -.. code-block:: html - - - - -``$options`` can either be an array of HTML attributes, or a string that -will be used as a class name:: - - echo $this->Form->label('User.name', null, ['id' => 'user-label']); - echo $this->Form->label('User.name', 'Your username', 'highlight'); - -Output: - -.. code-block:: html - - - - -Displaying and Checking Errors -============================== - -.. php:method:: error(string $fieldName, mixed $text, array $options) - -Shows a validation error message, specified by $text, for the given -field, in the event that a validation error has occurred. - -Options: - -- 'escape' bool Whether or not to HTML escape the contents of the - error. -- 'wrap' mixed Whether or not the error message should be wrapped - in a div. If a string, will be used as the HTML tag to use. -- 'class' string The class name for the error message - -.. TODO:: Add examples. - -.. php:method:: isFieldError(string $fieldName) - -Returns true if the supplied $fieldName has an active validation -error. :: - - if ($this->Form->isFieldError('gender')) { - echo $this->Form->error('gender'); - } - -.. note:: - - When using :php:meth:`~Cake\\View\\Helper\\FormHelper::input()`, errors are - rendered by default. - -Creating Buttons and Submit Elements -==================================== - -.. php:method:: submit(string $caption, array $options) - - Creates a submit button with caption ``$caption``. If the supplied - ``$caption`` is a URL to an image (it contains a '.' character), - the submit button will be rendered as an image. The following:: - - echo $this->Form->submit(); - - Will output: - - .. code-block:: html - -
    - - You can also pass a relative or absolute URL to an image for the - caption parameter instead of caption text. :: - - echo $this->Form->submit('ok.png'); - - Will output: - - .. code-block:: html - -
    - -Creating Button Elements ------------------------- - -.. php:method:: button(string $title, array $options = []) - -Creates an HTML button with the specified title and a default type -of "button". Setting ``$options['type']`` will output one of the -three possible button types: - -#. submit: Same as the ``$this->Form->submit`` method - (the - default). -#. reset: Creates a form reset button. -#. button: Creates a standard push button. - -:: - - echo $this->Form->button('A Button'); - echo $this->Form->button('Another Button', ['type' => 'button']); - echo $this->Form->button('Reset the Form', ['type' => 'reset']); - echo $this->Form->button('Submit Form', ['type' => 'submit']); - -Will output: - -.. code-block:: html - - - - - - -The ``button`` input type supports the ``escape`` option, which accepts -a boolean and defaults to false. It determines whether to HTML encode the -``$title`` of the button:: - - echo $this->Form->button('Submit Form', ['type' => 'submit', 'escape' => true]); - -Closing the Form -================ - -.. php:method:: end($secureAttributes = []) - -The ``end()`` method closes and completes a form. Often, ``end()`` will only -output a closing form tag, but using ``end()`` is a good practice as it -enables FormHelper to insert hidden form elements that -:php:class:`Cake\\Controller\\Component\\SecurityComponent` requires: - -.. code-block:: php - - Form->create(); ?> - - - - Form->end(); ?> - -The ``$secureAttributes`` parameter allows you to pass additional HTML -attributes to the hidden inputs that are generated when your application is -using ``SecurityComponent``. If you need to add additional attributes to the -generated hidden inputs you can use the ``$secureAttributes`` argument:: - - echo $this->Form->end(['data-type' => 'hidden']); - -Will output: - -.. code-block:: html - -
    - - -
    - -.. note:: - - If you are using - :php:class:`Cake\\Controller\\Component\\SecurityComponent` in your - application you should always end your forms with ``end()``. - -Creating Standalone Buttons and POST links -========================================== - -.. php:method:: postButton(string $title, mixed $url, array $options = []) - - Create a ``
    Paginator->sort('id', 'ID') ?> Paginator->sort('title', 'Title') ?>
    id ?> title) ?> Paginator->sort('title', 'Title') ?> Paginator->sort('Authors.name', 'Author') ?>
    title) ?> name) ?>
    -tags. :: - - echo $this->Html->tableHeaders(['Date', 'Title', 'Active']); - -Output: - -.. code-block:: html - - - - - - - -:: - - echo $this->Html->tableHeaders( - ['Date','Title','Active'], - ['class' => 'status'], - ['class' => 'product_table'] - ); - -Output: - -.. code-block:: html - - - - - - - -You can set attributes per column, these are used instead of the -defaults provided in the ``$thOptions``:: - - echo $this->Html->tableHeaders([ - 'id', - ['Name' => ['class' => 'highlight']], - ['Date' => ['class' => 'sortable']] - ]); - -Output: - -.. code-block:: html - - - - - - - -Creating Table Cells --------------------- - -.. php:method:: tableCells(array $data, array $oddTrOptions = null, array $evenTrOptions = null, $useCount = false, $continueOddEven = true) - -Creates table cells, in rows, assigning attributes differently -for odd- and even-numbered rows. Wrap a single table cell within an -[] for specific - - - -:: - - echo $this->Html->tableCells([ - ['Jul 7th, 2007', ['Best Brownies', ['class' => 'highlight']] , 'Yes'], - ['Jun 21st, 2007', 'Smart Cookies', 'Yes'], - ['Aug 1st, 2006', 'Anti-Java Cake', ['No', ['id' => 'special']]], - ]); - -Output: - -.. code-block:: html - - - - - - - - - - - - - - - - - -:: - - echo $this->Html->tableCells( - [ - ['Red', 'Apple'], - ['Orange', 'Orange'], - ['Yellow', 'Banana'], - ], - ['class' => 'darker'] - ); - -Output: - -.. code-block:: html - - - - - -Changing the Tags Output by HtmlHelper -====================================== - -.. php:method:: templates($templates) - -The ``$templates`` parameter can be either a string file path to the PHP -file containing the tags you want to load, or an array of templates to -add/replace:: - - // Load templates from config/my_html.php - $this->Html->templates('my_html.php'); - - // Load specific templates. - $this->Html->templates([ - 'javascriptlink' => '' - ]); - -When loading files of templates, your file should look like:: - - '' - ]; - -.. warning:: - - Template strings containing a percentage sign (``%``) need special attention, - you should prefix this character with another percentage so it looks like - ``%%``. The reason is that internally templates are compiled to be used with - ``sprintf()``. Example: '
    {{content}}
    ' - -Creating Breadcrumb Trails with HtmlHelper -========================================== - -.. php:method:: addCrumb(string $name, string $link = null, mixed $options = null) -.. php:method:: getCrumbs(string $separator = '»', string $startText = false) - -Many applications have breadcrumb trails to ease end user navigations. You can -create a breadcrumb trail in your app with some help from HtmlHelper. To make -bread crumbs, first the following in your layout -template:: - - echo $this->Html->getCrumbs(' > ', 'Home'); - -The ``$startText`` option can also accept an array. This gives more control -over the generated first link:: - - echo $this->Html->getCrumbs(' > ', [ - 'text' => $this->Html->image('home.png'), - 'url' => ['controller' => 'Pages', 'action' => 'display', 'home'], - 'escape' => false - ]); - -Any keys that are not ``text`` or ``url`` will be passed to -:php:meth:`~HtmlHelper::link()` as the ``$options`` parameter. - -Now, in your view you'll want to add the following to start the -breadcrumb trails on each of the pages:: - - $this->Html->addCrumb('Users', '/users'); - $this->Html->addCrumb('Add User', ['controller' => 'Users', 'action' => 'add']); - -This will add the output of "**Home > Users > Add User**" in your -layout where ``getCrumbs`` was added. - -You can also fetch the crumbs formatted inside an HTML list:: - - echo $this->Html->getCrumbList(); - -This method uses :php:meth:`Cake\\View\\Helper\\HtmlHelper::tag()` to generate -list and its elements. Works similar to -:php:meth:`~Cake\\View\\Helper\\HtmlHelper::getCrumbs()`, so it uses options -which every crumb was added with. You can use the ``$startText`` parameter to -provide the first breadcrumb link/text. This is useful when you always want to -include a root link. This option works the same as the ``$startText`` option for -:php:meth:`~Cake\\View\\Helper\\HtmlHelper::getCrumbs()`. - - -.. meta:: - :title lang=en: HtmlHelper - :description lang=en: The role of the HtmlHelper in CakePHP is to make HTML-related options easier, faster, and more resilient to change. - :keywords lang=en: html helper,cakephp css,cakephp script,content type,html image,html link,html tag,script block,script start,html url,cakephp style,cakephp crumbs diff --git a/es/core-libraries/helpers/number.rst b/es/core-libraries/helpers/number.rst deleted file mode 100644 index e87d095d8384ecf2f5f79436e7e95f42e52bcc78..0000000000000000000000000000000000000000 --- a/es/core-libraries/helpers/number.rst +++ /dev/null @@ -1,30 +0,0 @@ -NumberHelper -############ - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\View\Helper - -.. php:class:: NumberHelper(View $view, array $config = []) - -The NumberHelper contains convenient methods that enable display -numbers in common formats in your views. These methods include ways -to format currency, percentages, data sizes, format numbers to -specific precisions and also to give you more flexibility with -formatting numbers. - -.. include:: ../../core-utility-libraries/number.rst - :start-after: start-cakenumber - :end-before: end-cakenumber - -.. warning:: - - All symbols are UTF-8. - -.. meta:: - :title lang=en: NumberHelper - :description lang=en: The Number Helper contains convenience methods that enable display numbers in common formats in your views. - :keywords lang=en: number helper,currency,number format,number precision,format file size,format numbers diff --git a/es/core-libraries/helpers/paginator.rst b/es/core-libraries/helpers/paginator.rst deleted file mode 100644 index 1bde619f68862d38d4bd2d7ca5a5f857516feab5..0000000000000000000000000000000000000000 --- a/es/core-libraries/helpers/paginator.rst +++ /dev/null @@ -1,496 +0,0 @@ -PaginatorHelper -############### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\View\Helper - -.. php:class:: PaginatorHelper(View $view, array $config = []) - -The Pagination helper is used to output pagination controls such as -page numbers and next/previous links. It works in tandem with -:php:class:`PaginatorComponent`. - -See also :doc:`/core-libraries/components/pagination` for information on how to -create paginated datasets and do paginated queries. - -.. _paginator-templates: - -PaginatorHelper Templates -========================= - -Internally PaginatorHelper uses a series of simple HTML templates to generate -markup. You can modify these templates to customize the HTML generated by the -PaginatorHelper. - -Templates use ``{{var}}`` style placeholders. It is important to not add any -spaces around the `{{}}` or the replacements will not work. - -Loading Templates from a File ------------------------------ - -When adding the PaginatorHelper in your controller, you can define the -'templates' setting to define a template file to load. This allows you easily -customize multiple templates and keep your code DRY:: - - // In a controller. - public $helpers = [ - 'Paginator' => ['templates' => 'paginator-templates.php'] - ]; - -This will load the file located at ``config/paginator-templates.php`` and -read templates from the ``$config`` variable within that file. You can also load -templates from a plugin using :term:`plugin syntax`:: - - // In a controller. - public $helpers = [ - 'Paginator' => ['templates' => 'MyPlugin.paginator-templates.php'] - ]; - -Whether your templates are in the primary application or a plugin, your -templates file should look something like:: - - return [ - 'number' => '{{text}}', - ]; - -Changing Templates at Run-time ------------------------------- - -.. php:method:: templates($templates = null) - -This method allows you to change the templates used by PaginatorHelper at -runtime. This can be useful when you want to customize templates for -a particular method call:: - - // Read the current template value. - $result = $this->Paginator->templates('number'); - - // Change a template - $this->Paginator->templates([ - 'number' => '{{text}}' - ]); - -.. warning:: - - Template strings containing a percentage sign (``%``) need special attention, - you should prefix this character with another percentage so it looks like - ``%%``. The reason is that internally templates are compiled to be used with - ``sprintf()``. Example: '
    {{content}}
    ' - -Template Names --------------- - -PaginatorHelper uses the following templates: - -- ``nextActive`` The active state for a link generated by next(). -- ``nextDisabled`` The disabled state for next(). -- ``prevActive`` The active state for a link generated by prev(). -- ``prevDisabled`` The disabled state for prev() -- ``counterRange`` The template counter() uses when format == range. -- ``counterPages`` The template counter() uses when format == pages. -- ``first`` The template used for a link generated by first(). -- ``last`` The template used for a link generated by last() -- ``number`` The template used for a link generated by numbers(). -- ``current`` The template used for the current page. -- ``ellipsis`` The template used for ellipses generated by numbers(). -- ``sort`` The template for a sort link with no direction. -- ``sortAsc`` The template for a sort link with an ascending direction. -- ``sortDesc`` The template for a sort link with a descending direction. - - -Creating Sort Links -=================== - -.. php:method:: sort($key, $title = null, $options = []) - - :param string $key: The name of the column that the recordset should be sorted. - :param string $title: Title for the link. If $title is null $key will be - used for the title and will be generated by inflection. - :param array $options: Options for sorting link. - -Generates a sorting link. Sets querystring parameters for the sort and -direction. Links will default to sorting by asc. After the first click, links -generated with ``sort()`` will handle direction switching automatically. If the -resultset is sorted 'asc' by the specified key the returned link will sort by -'desc'. - -Accepted keys for ``$options``: - -* ``escape`` Whether you want the contents HTML entity encoded, defaults to - true. -* ``model`` The model to use, defaults to :php:meth:`PaginatorHelper::defaultModel()`. -* ``direction`` The default direction to use when this link isn't active. -* ``lock`` Lock direction. Will only use the default direction then, defaults to false. - -Assuming you are paginating some posts, and are on page one:: - - echo $this->Paginator->sort('user_id'); - -Output: - -.. code-block:: html - - User Id - -You can use the title parameter to create custom text for your link:: - - echo $this->Paginator->sort('user_id', 'User account'); - -Output: - -.. code-block:: html - - User account - -If you are using HTML like images in your links remember to set escaping off:: - - echo $this->Paginator->sort( - 'user_id', - 'User account', - ['escape' => false] - ); - -Output: - -.. code-block:: html - - User account - -The direction option can be used to set the default direction for a link. Once a -link is active, it will automatically switch directions like normal:: - - echo $this->Paginator->sort('user_id', null, ['direction' => 'desc']); - -Output: - -.. code-block:: html - - User Id - -The lock option can be used to lock sorting into the specified direction:: - - echo $this->Paginator->sort('user_id', null, ['direction' => 'asc', 'lock' => true]); - -.. php:method:: sortDir(string $model = null, mixed $options = []) - - Gets the current direction the recordset is sorted. - -.. php:method:: sortKey(string $model = null, mixed $options = []) - - Gets the current key by which the recordset is sorted. - -Creating page number links -========================== - -.. php:method:: numbers($options = []) - -Returns a set of numbers for the paged result set. Uses a modulus to -decide how many numbers to show on each side of the current page By default -8 links on either side of the current page will be created if those pages exist. -Links will not be generated for pages that do not exist. The current page is -also not a link. - -Supported options are: - -* ``before`` Content to be inserted before the numbers. -* ``after`` Content to be inserted after the numbers. -* ``model`` Model to create numbers for, defaults to - :php:meth:`PaginatorHelper::defaultModel()`. -* ``modulus`` how many numbers to include on either side of the current page, - defaults to 8. -* ``first`` Whether you want first links generated, set to an integer to - define the number of 'first' links to generate. Defaults to false. If a - string is set a link to the first page will be generated with the value as the - title:: - - echo $this->Paginator->numbers(['first' => 'First page']); - -* ``last`` Whether you want last links generated, set to an integer to define - the number of 'last' links to generate. Defaults to false. Follows the same - logic as the ``first`` option. There is a - :php:meth:`~PaginatorHelper::last()`` method to be used separately as well if - you wish. - -While this method allows a lot of customization for its output. It is -also ok to just call the method without any params. :: - - echo $this->Paginator->numbers(); - -Using the first and last options you can create links to the beginning -and end of the page set. The following would create a set of page links that -include links to the first 2 and last 2 pages in the paged results:: - - echo $this->Paginator->numbers(['first' => 2, 'last' => 2]); - -Creating jump links -=================== - -In addition to generating links that go directly to specific page numbers, -you'll often want links that go to the previous and next links, first and last -pages in the paged data set. - -.. php:method:: prev($title = '<< Previous', $options = []) - - :param string $title: Title for the link. - :param mixed $options: Options for pagination link. - - Generates a link to the previous page in a set of paged records. - - ``$options`` supports the following keys: - - * ``escape`` Whether you want the contents HTML entity encoded, - defaults to true. - * ``model`` The model to use, defaults to :php:meth:`PaginatorHelper::defaultModel()`. - * ``disabledTitle`` The text to use when the link is disabled. Defaults to - the ``$title`` parameter. - - A simple example would be:: - - echo $this->Paginator->prev(' << ' . __('previous')); - - If you were currently on the second page of posts, you would get the following: - - .. code-block:: html - - - - If there were no previous pages you would get: - - .. code-block:: html - - - - To change the templates used by this method see :ref:`paginator-templates`. - -.. php:method:: next($title = 'Next >>', $options = []) - - This method is identical to :php:meth:`~PagintorHelper::prev()` with a few exceptions. It - creates links pointing to the next page instead of the previous one. It also - uses ``next`` as the rel attribute value instead of ``prev`` - -.. php:method:: first($first = '<< first', $options = []) - - Returns a first or set of numbers for the first pages. If a string is given, - then only a link to the first page with the provided text will be created:: - - echo $this->Paginator->first('< first'); - - The above creates a single link for the first page. Will output nothing if you - are on the first page. You can also use an integer to indicate how many first - paging links you want generated:: - - echo $this->Paginator->first(3); - - The above will create links for the first 3 pages, once you get to the third or - greater page. Prior to that nothing will be output. - - The options parameter accepts the following: - - - ``model`` The model to use defaults to :php:meth:`PaginatorHelper::defaultModel()` - - ``escape`` Whether or not the text should be escaped. Set to false if your - content contains HTML. - -.. php:method:: last($last = 'last >>', $options = []) - - This method works very much like the :php:meth:`~PaginatorHelper::first()` - method. It has a few differences though. It will not generate any links if you - are on the last page for a string values of ``$last``. For an integer value of - ``$last`` no links will be generated once the user is inside the range of last - pages. - -Checking the Pagination State -============================= - -.. php:method:: current(string $model = null) - - Gets the current page of the recordset for the given model:: - - // Our URL is: http://example.com/comments/view/page:3 - echo $this->Paginator->current('Comment'); - // Output is 3 - -.. php:method:: hasNext(string $model = null) - - Returns true if the given result set is not at the last page. - -.. php:method:: hasPrev(string $model = null) - - Returns true if the given result set is not at the first page. - -.. php:method:: hasPage(string $model = null, integer $page = 1) - - Returns true if the given result set has the page number given by ``$page``. - -Creating a Page Counter -======================= - -.. php:method:: counter($options = []) - -Returns a counter string for the paged result set. Using a provided format -string and a number of options you can create localized and application -specific indicators of where a user is in the paged data set. - -There are a number of options for ``counter()``. The supported ones are: - -* ``format`` Format of the counter. Supported formats are 'range', 'pages' - and custom. Defaults to pages which would output like '1 of 10'. In the - custom mode the supplied string is parsed and tokens are replaced with - actual values. The available tokens are: - - - ``{{page}}`` - the current page displayed. - - ``{{pages}}`` - total number of pages. - - ``{{current}}`` - current number of records being shown. - - ``{{count}}`` - the total number of records in the result set. - - ``{{start}}`` - number of the first record being displayed. - - ``{{end}`` - number of the last record being displayed. - - ``{{model}}`` - The pluralized human form of the model name. - If your model was 'RecipePage', ``{{model}}`` would be 'recipe pages'. - - You could also supply only a string to the counter method using the tokens - available. For example:: - - echo $this->Paginator->counter( - 'Page {{page}} of {{pages}}, showing {{current}} records out of - {{count}} total, starting on record {{start}}, ending on {{end}}' - ); - - Setting 'format' to range would output like '1 - 3 of 13':: - - echo $this->Paginator->counter([ - 'format' => 'range' - ]); - -* ``model`` The name of the model being paginated, defaults to - :php:meth:`PaginatorHelper::defaultModel()`. This is used in - conjunction with the custom string on 'format' option. - -Modifying the Options PaginatorHelper Uses -========================================== - -.. php:method:: options($options = []) - -Sets all the options for the Paginator Helper. Supported options are: - -* ``url`` The URL of the paginating action. 'url' has a few sub options as well: - - - ``sort`` The key that the records are sorted by. - - ``direction`` The direction of the sorting. Defaults to 'ASC'. - - ``page`` The page number to display. - - The above mentioned options can be used to force particular pages/directions. - You can also append additional URL content into all URLs generated in the - helper:: - - $this->Paginator->options([ - 'url' => [ - 'sort' => 'email', - 'direction' => 'desc', - 'page' => 6, - 'lang' => 'en' - ] - ]); - - The above adds the ``en`` route parameter to all links the helper will - generate. It will also create links with specific sort, direction and page - values. By default PaginatorHelper will merge in all of the current passed - arguments and query string parameters. - -* ``escape`` Defines if the title field for links should be HTML escaped. - Defaults to true. - -* ``model`` The name of the model being paginated, defaults to - :php:meth:`PaginatorHelper::defaultModel()`. - -Pagination in Views -=================== - -It's up to you to decide how to show records to the user, but most -often this will be done inside HTML tables. The examples below -assume a tabular layout, but the PaginatorHelper available in views -doesn't always need to be restricted as such. - -See the details on -`PaginatorHelper `_ -in the API. As mentioned, the PaginatorHelper also offers sorting features -which can be easily integrated into your table column headers: - -.. code-block:: php - - -
    DateTitleActive
    DateTitleActive
    idNameDate
    -attributes. :: - - echo $this->Html->tableCells([ - ['Jul 7th, 2007', 'Best Brownies', 'Yes'], - ['Jun 21st, 2007', 'Smart Cookies', 'Yes'], - ['Aug 1st, 2006', 'Anti-Java Cake', 'No'], - ]); - -Output: - -.. code-block:: html - -
    Jul 7th, 2007Best BrowniesYes
    Jun 21st, 2007Smart CookiesYes
    Aug 1st, 2006Anti-Java CakeNo
    - Jul 7th, 2007 - - Best Brownies - - Yes -
    - Jun 21st, 2007 - - Smart Cookies - - Yes -
    - Aug 1st, 2006 - - Anti-Java Cake - - No -
    RedApple
    OrangeOrange
    YellowBanana
    - - - - - - - - - - -
    Paginator->sort('id', 'ID') ?>Paginator->sort('title', 'Title') ?>
    id ?> title) ?>
    - -The links output from the ``sort()`` method of the ``PaginatorHelper`` -allow users to click on table headers to toggle the sorting of the -data by a given field. - -It is also possible to sort a column based on associations: - -.. code-block:: php - - - - - - - - - - - - -
    Paginator->sort('title', 'Title') ?>Paginator->sort('Author.name', 'Author') ?>
    title) ?> name) ?>
    - -The final ingredient to pagination display in views is the addition -of page navigation, also supplied by the PaginationHelper:: - - // Shows the page numbers - Paginator->numbers() ?> - - // Shows the next and previous links - Paginator->prev('« Previous') ?> - Paginator->next('Next »') ?> - - // Prints X of Y, where X is current page and Y is number of pages - Paginator->counter() ?> - -The wording output by the counter() method can also be customized -using special markers:: - - Paginator->counter([ - 'format' => 'Page {{page}} of {{pages}}, showing {{current}} records out of - {{count}} total, starting on record {{start}}, ending on {{end}}' - ]) ?> - -Generating Pagination URLs -========================== - -.. php:method:: generateUrl(array $options = [], $model = null, $full = false) - -By default returns a full pagination URL string for use in non-standard -contexts (i.e. JavaScript). :: - - echo $this->Paginator->generateUrl(['sort' => 'title']); - -.. meta:: - :title lang=en: PaginatorHelper - :description lang=en: The Pagination helper is used to output pagination controls such as page numbers and next/previous links. - :keywords lang=en: paginator helper,pagination,sort,page number links,pagination in views,prev link,next link,last link,first link,page counter diff --git a/es/core-libraries/helpers/rss.rst b/es/core-libraries/helpers/rss.rst deleted file mode 100644 index 7967e29f230f239841f8a965b9498232367c0afa..0000000000000000000000000000000000000000 --- a/es/core-libraries/helpers/rss.rst +++ /dev/null @@ -1,208 +0,0 @@ -RSS -### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\View\Helper - -.. php:class:: RssHelper(View $view, array $config = []) - -The RSS helper makes generating XML for RSS feeds easy. - -Creating an RSS Feed with the RssHelper -======================================= - -This example assumes you have a Posts Controller and Post Model -already created and want to make an alternative view for RSS. - -Creating an xml/rss version of posts/index is a snap with CakePHP. -After a few simple steps you can simply append the desired -extension .rss to ``posts/index`` making your URL ``posts/index.rss``. -Before we jump too far ahead trying to get our webservice up and -running we need to do a few things. First parseExtensions needs to -be activated, this is done in ``config/routes.php``:: - - Router::parseExtensions('rss'); - -In the call above we've activated the .rss extension. When using -:php:meth:`Router::parseExtensions()` you can pass as many arguments or -extensions as you want. This will activate each -extension/content-type for use in your application. Now when the -address ``posts/index.rss`` is requested you will get an xml version of -your ``posts/index``. However, first we need to edit the controller to -add in the rss-specific code. - -Controller Code ---------------- - -It is a good idea to add RequestHandler to your PostsController's -$components array. This will allow a lot of automagic to occur:: - - public $components = ['RequestHandler']; - -Our view will also use the :php:class:`TextHelper` for formatting, so that -should be added to the controller as well:: - - public $helpers = ['Text']; - -Before we can make an RSS version of our posts/index we need to get -a few things in order. It may be tempting to put the channel -metadata in the controller action and pass it to your view using -the :php:meth:`Controller::set()` method but this is inappropriate. That -information can also go in the view. That will come later though, -for now if you have a different set of logic for the data used to -make the RSS feed and the data for the HTML view you can use the -:php:meth:`RequestHandler::isRss()` method, otherwise your controller can stay -the same:: - - // Modify the Posts Controller action that corresponds to - // the action which deliver the rss feed, which is the - // Index action in our example. - - public function index() - { - if ($this->RequestHandler->isRss() ) { - $posts = $this->Posts->find( - 'all', - ['limit' => 20, 'order' => 'Post.created DESC'] - ); - return $this->set(compact('posts')); - } - - // this is not an Rss request, so deliver - // data used by website's interface. - $this->paginate['Post'] = [ - 'order' => 'Post.created DESC', - 'limit' => 10 - ]; - - $posts = $this->paginate(); - $this->set(compact('posts')); - } - -With all the View variables set we need to create an rss layout. - -Layout ------- - -An Rss layout is very simple, put the following contents in -``src/Template/Layout/rss/default.ctp``:: - - if (!isset($documentData)) { - $documentData = []; - } - if (!isset($channelData)) { - $channelData = []; - } - if (!isset($channelData['title'])) { - $channelData['title'] = $this->fetch('title'); - } - $channel = $this->Rss->channel([], $channelData, $this->fetch('content')); - echo $this->Rss->document($documentData, $channel); - -It doesn't look like much but thanks to the power in the ``RssHelper`` -it's doing a lot of lifting for us. We haven't set ``$documentData`` or -``$channelData`` in the controller, however in CakePHP your views -can pass variables back to the layout. Which is where our -``$channelData`` array will come from setting all of the meta data for -our feed. - -Next up is view file for my posts/index. Much like the layout file -we created, we need to create a ``src/Template/Posts/rss/`` directory and -create a new ``index.ctp`` inside that folder. The contents of the file -are below. - -View ----- - -Our view, located at ``src/Template/Posts/rss/index.ctp``, begins by -setting the ``$documentData`` and ``$channelData`` variables for the -layout, these contain all the metadata for our RSS feed. This is -done by using the :php:meth:`View::set()`` method which is analogous to the -Controller::set() method. Here though we are passing the channel's -metadata back to the layout:: - - $this->set('channelData', [ - 'title' => __("Most Recent Posts"), - 'link' => $this->Html->url('/', true), - 'description' => __("Most recent posts."), - 'language' => 'en-us' - ]); - -The second part of the view generates the elements for the actual -records of the feed. This is accomplished by looping through the -data that has been passed to the view ($items) and using the -:php:meth:`RssHelper::item()` method. The other method you can use, -:php:meth:`RssHelper::items()` which takes a callback and an array of items for -the feed. (The method I have seen used for the callback has always -been called ``transformRss()``. There is one downfall to this method, -which is that you cannot use any of the other helper classes to -prepare your data inside the callback method because the scope -inside the method does not include anything that is not passed -inside, thus not giving access to the TimeHelper or any other -helper that you may need. The :php:meth:`RssHelper::item()` transforms the -associative array into an element for each key value pair. - -.. note:: - - You will need to modify the $postLink variable as appropriate to - your application. - -:: - - foreach ($posts as $post) { - $postTime = strtotime($post['Post']['created']); - - $postLink = [ - 'controller' => 'Posts', - 'action' => 'view', - 'year' => date('Y', $postTime), - 'month' => date('m', $postTime), - 'day' => date('d', $postTime), - $post['Post']['slug'] - ]; - - // Remove & escape any HTML to make sure the feed content will validate. - $bodyText = h(strip_tags($post['Post']['body'])); - $bodyText = $this->Text->truncate($bodyText, 400, [ - 'ending' => '...', - 'exact' => true, - 'html' => true, - ]); - - echo $this->Rss->item([], [ - 'title' => $post['Post']['title'], - 'link' => $postLink, - 'guid' => ['url' => $postLink, 'isPermaLink' => 'true'], - 'description' => $bodyText, - 'pubDate' => $post['Post']['created'] - ]); - } - -You can see above that we can use the loop to prepare the data to be transformed -into XML elements. It is important to filter out any non-plain text characters -out of the description, especially if you are using a rich text editor for the -body of your blog. In the code above we used ``strip_tags()`` and -:php:func:`h()` to remove/escape any XML special characaters from the content, -as they could cause validation errors. Once we have set up the data for the -feed, we can then use the :php:meth:`RssHelper::item()` method to create the XML -in RSS format. Once you have all this setup, you can test your RSS feed by going -to your site ``/posts/index.rss`` and you will see your new feed. It is always -important that you validate your RSS feed before making it live. This can be -done by visiting sites that validate the XML such as Feed Validator or the w3c -site at http://validator.w3.org/feed/. - -.. note:: - - You may need to set the value of 'debug' in your core configuration - to ``false`` to get a valid feed, because of the various debug - information added automagically under higher debug settings that - break XML syntax or feed validation rules. - -.. meta:: - :title lang=en: RssHelper - :description lang=en: The RSS helper makes generating XML for RSS feeds easy. - :keywords lang=en: rss helper,rss feed,isrss,rss item,channel data,document data,parse extensions,request handler diff --git a/es/core-libraries/helpers/session.rst b/es/core-libraries/helpers/session.rst deleted file mode 100644 index 044fe08123c4eaa9c0a91d43df9fc61a5e090ae0..0000000000000000000000000000000000000000 --- a/es/core-libraries/helpers/session.rst +++ /dev/null @@ -1,50 +0,0 @@ -SessionHelper -############# - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\View\Helper - -.. php:class:: SessionHelper(View $view, array $config = []) - -As a natural counterpart to the Session Component, the Session -Helper replicates most of the component's functionality and makes it -available in your view. - -The major difference between the Session Helper and the Session -Component is that the helper does *not* have the ability to write -to the session. - -As with the Session Component, data is read by using -:term:`dot notation` array structures:: - - ['User' => [ - 'username' => 'super@example.com' - ]]; - -Given the previous array structure, the node would be accessed by -``User.username``, with the dot indicating the nested array. This -notation is used for all Session helper methods wherever a ``$key`` is -used. - -.. php:method:: read(string $key) - - :rtype: mixed - - Read from the Session. Returns a string or array depending on the - contents of the session. - -.. php:method:: check(string $key) - - :rtype: boolean - - Check to see whether a key is in the Session. Returns a boolean representing the - key's existence. - -.. meta:: - :title lang=en: SessionHelper - :description lang=en: As a natural counterpart to the Session Component, the Session Helper replicates most of the component's functionality and makes it available in your view. - :keywords lang=en: session helper,flash messages,session flash,session read,session check diff --git a/es/core-libraries/helpers/text.rst b/es/core-libraries/helpers/text.rst deleted file mode 100644 index ab4d8521a7fd5aeb8c672eada95e6a51136f611f..0000000000000000000000000000000000000000 --- a/es/core-libraries/helpers/text.rst +++ /dev/null @@ -1,92 +0,0 @@ -TextHelper -########## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\View\Helper - -.. php:class:: TextHelper(View $view, array $config = []) - -The TextHelper contains methods to make text more usable and -friendly in your views. It aids in enabling links, formatting URLs, -creating excerpts of text around chosen words or phrases, -highlighting key words in blocks of text, and gracefully -truncating long stretches of text. - -Linking Email addresses -======================= - -.. php:method:: autoLinkEmails(string $text, array $options=[]) - -Adds links to the well-formed email addresses in $text, according -to any options defined in ``$options`` (see -:php:meth:`HtmlHelper::link()`). :: - - $myText = 'For more information regarding our world-famous ' . - 'pastries and desserts, contact info@example.com'; - $linkedText = $this->Text->autoLinkEmails($myText); - -Output:: - - For more information regarding our world-famous pastries and desserts, - contact info@example.com - -This method automatically escapes its input. Use the ``escape`` -option to disable this if necessary. - -Linking URLs -============ - -.. php:method:: autoLinkUrls(string $text, array $options=[]) - -Same as ``autoLinkEmails()``, only this method searches for -strings that start with https, http, ftp, or nntp and links them -appropriately. - -This method automatically escapes its input. Use the ``escape`` -option to disable this if necessary. - -Linking Both URLs and Email Addresses -===================================== - -.. php:method:: autoLink(string $text, array $options=[]) - -Performs the functionality in both ``autoLinkUrls()`` and -``autoLinkEmails()`` on the supplied ``$text``. All URLs and emails -are linked appropriately given the supplied ``$htmlOptions``. - -This method automatically escapes its input. Use the ``escape`` -option to disable this if necessary. - - -Converting Text into Paragraphs -=============================== - -.. php:method:: autoParagraph(string $text) - -Adds proper

    around text where double-line returns are found, and
    where -single-line returns are found. :: - - $myText = 'For more information - regarding our world-famous pastries and desserts. - - contact info@example.com'; - $formattedText = $this->Text->autoParagraph($myText); - -Output:: - -

    For more information
    - regarding our world-famous pastries and desserts.

    -

    contact info@example.com

    - -.. include:: ../../core-utility-libraries/string.rst - :start-after: start-string - :end-before: end-string - -.. meta:: - :title lang=en: TextHelper - :description lang=en: The Text Helper contains methods to make text more usable and friendly in your views. - :keywords lang=en: text helper,autoLinkEmails,autoLinkUrls,autoLink,excerpt,highlight,stripLinks,truncate,string text diff --git a/es/core-libraries/helpers/time.rst b/es/core-libraries/helpers/time.rst deleted file mode 100644 index eade96a2d2685bd98167bd86dbcff8c44b65257d..0000000000000000000000000000000000000000 --- a/es/core-libraries/helpers/time.rst +++ /dev/null @@ -1,53 +0,0 @@ -TimeHelper -########## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\View\Helper - -.. php:class:: TimeHelper(View $view, array $config = []) - -The Time Helper does what it says on the tin: saves you time. It -allows for the quick processing of time related information. The -Time Helper has two main tasks that it can perform: - -#. It can format time strings. -#. It can test time (but cannot bend time, sorry). - -Using the Helper -================ - -A common use of the Time Helper is to offset the date and time to match a -user's time zone. Lets use a forum as an example. Your forum has many users who -may post messages at any time from any part of the world. An easy way to -manage the time is to save all dates and times as GMT+0 or UTC. Uncomment the -line ``date_default_timezone_set('UTC');`` in ``config/bootstrap.php`` to ensure -your application's time zone is set to GMT+0. - -Next add a time zone field to your users table and make the necessary -modifications to allow your users to set their time zone. Now that we know -the time zone of the logged in user we can correct the date and time on our -posts using the Time Helper:: - - echo $this->Time->format( - $post['Post']['created'], - 'F jS, Y h:i A', - null, - $user['User']['time_zone'] - ); - // Will display August 22nd, 2011 11:53 PM for a user in GMT+0 - // August 22nd, 2011 03:53 PM for a user in GMT-8 - // and August 23rd, 2011 09:53 AM GMT+10 - -Most of TimeHelper's features are intended as backwards compatible interfaces -for applications that are upgrading from older versions of CakePHP. Because the -ORM returns :php:class:`Cake\\Utility\\Time` instances for every ``timestamp`` -and ``datetime`` column, you can use the methods there to do most tasks. - -.. meta:: - :title lang=en: TimeHelper - :description lang=en: The Time Helper will help you format time and test time. - :keywords lang=en: time helper,format time,timezone,unix epoch,time strings,time zone offset,utc,gmt diff --git a/es/core-libraries/helpers/url.rst b/es/core-libraries/helpers/url.rst deleted file mode 100644 index 83192d535238b152ea0c749c2d604aa4ee510344..0000000000000000000000000000000000000000 --- a/es/core-libraries/helpers/url.rst +++ /dev/null @@ -1,104 +0,0 @@ -UrlHelper -########## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\View\UrlHelper - -.. php:class:: UrlHelper(View $view, array $config = []) - -The UrlHelper makes it easy for you to generate URL's from your other helpers. -It also gives you a single place to customize how URLs are generated by -overriding the core helper with an application one. See the -:ref:`aliasing-helpers` section for how to do this. - -Generating URLs -=============== - -.. php:method:: build(mixed $url = NULL, boolean $full = false) - -Returns a URL pointing to a combination of controller and action. -If ``$url`` is empty, it returns the ``REQUEST\_URI``, otherwise it -generates the URL for the controller and action combo. If ``full`` is -``true``, the full base URL will be prepended to the result:: - - echo $this->Url->build([ - "controller" => "posts", - "action" => "view", - "bar" - ]); - - // Output - /posts/view/bar - -Here are a few more usage examples: - -URL with named parameters:: - - echo $this->Url->build([ - "controller" => "posts", - "action" => "view", - "foo" => "bar" - ]); - - // Output - /posts/view/foo:bar - -URL with extension:: - - echo $this->Url->build([ - "controller" => "posts", - "action" => "list", - "ext" => "rss" - ]); - - // Output - /posts/list.rss - -URL (starting with '/') with the full base URL prepended:: - - echo $this->Url->build('/posts', true); - - // Output - http://somedomain.com/posts - -URL with GET params and named anchor:: - - echo $this->Url->build([ - "controller" => "posts", - "action" => "search", - "?" => ["foo" => "bar"], - "#" => "first" - ]); - - // Output - /posts/search?foo=bar#first - -URL for named route:: - - echo $this->Url->build(['_name' => 'product-page', 'slug' => 'i-m-slug']); - - // Assuming route is setup like: - // $router->connect( - // '/products/:slug', - // [ - // 'controller' => 'products', - // 'action' => 'view' - // ], - // [ - // '_name' => 'product-page' - // ] - // ); - /products/i-m-slug - -For further information check -`Router::url `_ -in the API. - -.. meta:: - :title lang=en: UrlHelper - :description lang=en: The role of the UrlHelper in CakePHP is to help build urls. - :keywords lang=en: url helper,url diff --git a/es/core-libraries/httpclient.rst b/es/core-libraries/httpclient.rst new file mode 100644 index 0000000000000000000000000000000000000000..311e1c76075814e299ee655c67dc98d85a36504e --- /dev/null +++ b/es/core-libraries/httpclient.rst @@ -0,0 +1,19 @@ +Http Client +########### + +.. php:namespace:: Cake\Network\Http + +.. php:class:: Client(mixed $config = []) + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: HttpClient + :keywords lang=es: array name,array data,query parameter,query string,php class,string query,test type,string data,google,query results,webservices,apis,parameters,cakephp,meth,search results diff --git a/es/core-libraries/inflector.rst b/es/core-libraries/inflector.rst new file mode 100644 index 0000000000000000000000000000000000000000..2f857aa8aaf82fab87c3657be29e9feca950d62d --- /dev/null +++ b/es/core-libraries/inflector.rst @@ -0,0 +1,19 @@ +Inflector +######### + +.. php:namespace:: Cake\Utility + +.. php:class:: Inflector + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Inflector + :keywords lang=es: apple orange,word variations,apple pie,person man,latin versions,profile settings,php class,initial state,puree,slug,apples,oranges,user profile,underscore diff --git a/es/core-libraries/internationalization-and-localization.rst b/es/core-libraries/internationalization-and-localization.rst index 2717729b9476654d8649706b379e87b2a090e8ca..2fafe177fb77614b35853084bd2c1c3816ac7b2a 100644 --- a/es/core-libraries/internationalization-and-localization.rst +++ b/es/core-libraries/internationalization-and-localization.rst @@ -2,502 +2,14 @@ Internationalization & Localization ################################### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -One of the best ways for your applications to reach a larger -audience is to cater for multiple languages. This can often prove -to be a daunting task, but the internationalization and -localization features in CakePHP make it much easier. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -First, it's important to understand some terminology. -*Internationalization* refers to the ability of an application to -be localized. The term *localization* refers to the adaptation of -an application to meet specific language (or culture) requirements -(i.e. a "locale"). Internationalization and localization are often -abbreviated as i18n and l10n respectively; 18 and 10 are the number -of characters between the first and last character. - -Setting Up Translations -======================= - -There are only a few steps to go from a single-language application -to a multi-lingual application, the first of which is to make use -of the :php:func:`__()` function in your code. Below is an example of some code for a -single-language application:: - -

    Popular Articles

    - -To internationalize your code, all you need to do is to wrap -strings in :php:func:`__()` like so:: - -

    - -If you do nothing further, these two code examples are functionally -identical - they will both send the same content to the browser. -The :php:func:`__()` function will translate the passed string -if a translation is available, or return it unmodified. - -Language Files --------------- - -Translations can be made available by using language files stored in your -application. The default format for CakePHP translation files is the -`Gettext `_ format. Files neeed to be -placed under ``src/Locale/`` and within this directory, there should be -a subfolder for each language the application needs to support:: - - /src - /Locale - /en_US - default.po - /en_GB - default.po - validation.po - /es - default.po - -The default domain is 'default', therefore your locale folder should at least -contain the ``default.po`` file as shown above. A domain refers to any arbitrary -grouping of translation messages. When no group is used, then the default group -is selected. - -Plugins can also contain translation files, the convention is to use the -``under_scored`` version of the plugin name as the domain for the translation -messages:: - - MyPlugin - /src - /Locale - /fr - my_plugin.po - /de - my_plugin.po - -Translation folders can either be the two letter ISO code of the language or the -full locale name such as ``fr_FR``, ``es_AR``, ``da_DK`` which contains both the -language and the country where it is spoken. - -An example translation file could look like this: - -.. code-block:: pot - - msgid "My name is {0}" - msgstr "Je m'appelle {0}" - - msgid "I'm {0,number} years old" - msgstr "J'ai {0,number} ans" - -Setting the Default Locale --------------------------- - -The default locale can be set in your ``config/bootstrap.php`` folder by using -the following line:: - - ini_set('intl.default_locale', 'fr_FR'); - -This will control several aspects of your application, including the default -translations language, the date format, number format and currency whenever any -of those is displayed using the localization libraries that CakePHP provides. - -Changing the Locale at Runtime ------------------------------- - -To change the language for translated strings you can call this method:: - - use Cake\I18n\I18n; - - I18n::locale('de_DE'); - -This will also change how numbers and dates are formatted when using one of -the localization tools. - -Using Translation Functions -=========================== - -CakePHP provides several functions that will help you internationalize your -application. The most frequently used one is :php:func:`__()`. This function -is used to retrieve a single translation message or return the same string if no -translation was found:: - - echo __('Popular Articles'); - -If you need to group your messages, for example, translations inside a plugin, -you can use the :php:func:`__d()` function to fetch messages from another domain:: - - echo __d('my_plugin', 'Trending right now'); - -Sometimes translations strings can be ambiguous for people translating them. -This can happen if two strings are identical but refer to different things. For -example, 'letter' has multiple meanings in english. To solve that problem, you -can use the :php:func:`__x()` function:: - - echo __x('written communication', 'He read the first letter'); - - echo __x('alphabet learning', 'He read the first letter'); - -The first argument is the context of the message and the second is the message -to be translated. - -Using Variables in Translation Messages ---------------------------------------- - -Translation functions allow you to interpolate variables into the messages using -special markers defined in the message itself or in the translated string:: - - echo __("Hello, my name is {0}, I'm {1} years old", ['Sara', 12]); - -Markers are numeric, and correspond to the keys in the passed array. You can -also pass variables as independent arguments to the function:: - - echo __("Small step for {0}, Big leap for {1}", 'Man', 'Humanity'); - -All translation functions support placeholder replacements:: - - __d('validation', 'The field {0} cannot be left empty', 'Name'); - - __x('alphabet', 'He read the letter {0}', 'Z'); - -These functions take advantage of the -`ICU MessageFormatter `_ -so you and translate messages and localize dates, numbers and -currency at the same time:: - - echo __( - 'Hi {0,string}, your balance on the {1,date} is {2,number,currency}', - ['Charles', '2014-01-13 11:12:00', 1354.37] - ); - - // Returns - Hi Charles, your balance on the Jan 13, 2014, 11:12 AM is $ 1,354.37 - - -Numbers in placeholders can be formatted as well with fine grain control of the -output:: - - echo __( - 'You have traveled {0,number,decimal} kilometers in {1,number,integer} weeks', - [5423.344, 5.1] - ); - - // Returns - You have traveled 5,423.34 kilometers in 5 weeks - - echo __('There are {0,number,#,###} people on earth', 6.1 * pow(10, 8)); - - // Returns - There are 6,100,000,000 people on earth - -This is the list of formatter specifiers you can put after the word ``number``: - -* ``integer``: Removes the decimal part -* ``decimal``: Formats the number as a float -* ``currency``: Puts the locale currency symbol and rounds decimals -* ``percent``: Formats the number as a percentage - -Dates can also be formatted by using the word ``date`` after the placeholder -number. A list of extra options follows: - -* ``short`` -* ``medium`` -* ``long`` -* ``full`` - -The word ``time`` after the placeholder number is also accepted and it -understands the same options as ``date``. - -.. note:: - - If you are using PHP 5.5+, you can use also named placeholders like {name} - {age}, etc. And pass the variables in an array having the corresponding key - names like ``['name' => 'Sara', 'age' => 12]``. This feature is not available - in PHP 5.4. - -Plurals -------- - -One crucial part of internationalizing your application is getting your messages -pluralized correctly depending on the language they are shown. CakePHP provides -a couple ways to correctly select plurals in your messages. - -Using ICU Plural Selection -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The first one is taking advantage of the ``ICU`` message format that comes -by default in the translation functions. In the translations file you could have -the following strings - -.. code-block:: pot - - msgid "{0,plural,=0{No records found} =1{Found 1 record} other{Found {1} records}}" - msgstr "{0,plural,=0{Ningún resultado} =1{1 resultado} other{{1} resultados}}" - -And in your application use the following code to output either of the -translations for such string:: - - __('{0,plural,=0{No records found }=1{Found 1 record} other{Found {1} records}}', [0]); - - // Returns "Ningún resultado" as the argument {0} is 0 - - __('{0,plural,=0{No records found} =1{Found 1 record} other{Found {1} records}}', [1]); - - // Returns "1 resultado" because the argument {0} is 1 - - __('{0,plural,=0{No records found} =1{Found 1 record} other{Found {1} records}}', [2, 2]); - - // Returns "2 resultados" because the argument {0} is 2 - -A closer look to the format we just used will make it evident how messages are -built:: - - { [count placeholder],plural, case1{message} case2{message} case3{...} ... } - -The ``[count placeholder]`` can be the array key number of any of the variables -you pass to the translation function. It will be used for selecting the correct -plural form. - -You can of course use simpler message ids if you don't want to type the full -plural selection sequence in your code - -.. code-block:: pot - - msgid "search.results" - msgstr "{0,plural,=0{Ningún resultado} =1{1 resultado} other{{1} resultados}}" - -Then use the new string in your code:: - - __('search.results', [2, 2]); - - // Returns: "2 resultados" - -The latter version has the downside that you will need to have a translation -messages file even for the default language, but has the advantage that it makes -the code more readable and leaves the complicated plural selection strings in -the translation files. - -Sometimes using direct number matching in plurals is impractical. For example, -languages like Arabic require a different plural when you refer -to few things and other plural form for many things. In those cases you can -use the ICU matching aliases. Instead of writing:: - - =0{No results} =1{...} other{...} - -You can do:: - - zero{No Results} one{One result} few{...} many{...} other{...} - -Make sure you read the -`Language Plural Rules Guide `_ -to get a complete overview of the aliases you can use for each language. - -Using Gettext Plural Selection -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The second plural selection format accepted is using the built-in capabilities -of Gettext. In this case, plurals will be stored in the ``.po`` -file by creating a separate message translation line per plural form - -.. code-block:: pot - - msgid "One file removed" # One message identifier for singular - msgid_plural "{0} files removed" # Another one for plural - msgstr[0] "Un fichero eliminado" # Translation in singular - msgstr[1] "{0} ficheros eliminados" # Translation in plural - -When using this other format, you are required to use another translation -function:: - - // Returns: "10 ficheros eliminados" - $count = 10; - __n('One file removed', '{0} files removed', $count, $count); - - // It is also possible to use it inside a domain - __dn('my_plugin', 'One file removed', '{0} files removed', $count, $count); - -The number inside ``msgstr[]`` is the number assigned by Gettext for the plural -form of the language. Some languages have more than two plural forms, for -example Croatian: - -.. code-block:: pot - - msgid "One file removed" - msgid_plural "{0} files removed" - msgstr[0] "jednom datotekom je uklonjen" - msgstr[1] "{0} datoteke uklonjenih" - msgstr[2] "{0} slika uklonjenih" - -Please visit the `Launchpad languages page `_ -for a detailed explanation of the plural form numbers for each language. - -Creating Your Own Translators -============================= - -If you need to diverge from CakePHP conventions regarding where and how -translation messages are stored, you can create your own translation message -loader. The easiest way to create your own translator is by defining a loader -for a single domain and locale:: - - use Aura\Intl\Package; - - I18n::translator('animals', 'fr_FR', function() { - $package = new Package( - 'default', // The formatting strategy (ICU) - 'default', // The fallback domain - ); - $package->setMessages([ - 'Dog' => 'Chien', - 'Cat' => 'Chat', - 'Bird' => 'Oiseau' - ... - ]); - - return $package; - }); - -The above code can be added to your ``config/bootstrap.php`` so that -translations can be found before any translation function is used. The absolute -minimum that is required for creating a translator is that the loader function -should return a ``Aura\Intl\Package`` object. Once the code is in place you can -use the translation functions as usual:: - - I18n::locale('fr_FR'); - __d('animals', 'Dog'); // Returns "Chien" - -As you see, ``Package`` objects take translation messages as an array. You can -pass the ``setMessages()`` method however you like: with inline code, including -another file, calling another function, etc. CakePHP provides a few loader -functions you can reuse if you just need to change where messages are loaded. -For example, you can still use ``.po`` files, but loaded from another location:: - - use Cake\I18n\MessagesFileLoader as Loader; - - // Load messages from src/Locale/folder/sub_folder/filename.po - - I18n::translator( - 'animals', - 'fr_FR', - new Loader('filename', 'folder/sub_folder', 'po') - ); - -Creating Message Parsers ------------------------- - -It is possible to continue using the same conventions CakePHP uses, but use -a message parser other than ``PoFileParser``. For example, if you wanted to load -translation messages using ``YAML``, you will first need to created the parser -class:: - - namespace App\I18n\Parser; - - class YamlFileParser - { - - public function parse($file) - { - return yaml_parse_file($file); - } - } - -The file should be created in the ``src/I18n/Parser`` directory of your -application. Next, create the translations file under -``src/Locale/fr_FR/animals.yaml`` - -.. code-block:: yaml - - Dog: Chien - Cat: Chat - Bird: Oiseau - -And finally, configure the translation loader for the domain and locale:: - - use Cake\I18n\MessagesFileLoader as Loader; - - I18n::translator( - 'animals', - 'fr_FR', - new Loader('animals', 'fr_FR', 'yaml') - ); - -Creating Generic Translators ----------------------------- - -Configuring translators by calling ``I18n::translator()`` for each domain and -locale you need to support can be tedious, specially if you need to support more -than a few different locales. To avoid this problem, CakePHP lets you define -generic translator loaders for each domain. - -Imagine that you wanted to load all translations for the default domain and for -any language from an external service:: - - use Aura\Intl\Package; - - I18n::config('default', function($domain, $locale) { - $locale = Locale::parseLocale($locale); - $language = $locale['language']; - $messages = file_get_contents("http://example.com/translations/$lang.json"); - - return new Package( - 'default', // Formatter - null, // Fallback (none for default domain) - json_decode($messages, true) - ) - }); - -The above example calls an example external service to load a json file with the -translations and then just build a ``Package`` object for any locale that is -requested in the application. - -Plurals and Context in Custom Translators ------------------------------------------ - -The arrays used for ``setMessages()`` can be crafted to instruct the translator -to store messages under different domains or to trigger Gettext-style plural selection. -The following is an example of storing translations for the same key in -different contexts:: - - [ - 'He reads the letter {0}' => [ - 'alphabet' => 'Él lee la letra {0}', - 'written communication' => 'Él lee la carta {0}' - ] - ] - -Similarly, you can express Gettext-style plurals using the messages array by -having a nested array key per plural form:: - - [ - 'I have read one book' => 'He leído un libro', - 'I have read {0} books' => [ - 'He leído un libro', - 'He leído {0} libros' - ] - ] - -Using Different Formatters --------------------------- - -In previous examples we have seen that Packages are built using ``default`` as -first argument, and it was indicated with a comment that it corresponded to the -formatter to be used. Formatters are classes responsible for interpolating variables -in translation messages and selecting the correct plural form. - -If you're dealing with a legacy application, or you don't need the power offered -by the ICU message formatting, CakePHP also provides the ``sprintf`` formatter:: - - return Package('sprintf', 'fallback_domain', $messages); - -The messages to be translated will be passed to the ``sprintf`` function for -interpolating the variables:: - - __('Hello, my name is %s and I am %d years old', 'José', 29); - -It is possible to set the default formatter for all translators created by -CakePHP before they are used for the first time. This does not include manually -created translators using the ``translator()`` and ``config()`` methods:: - - I18n::defaultFormatter('sprintf'); + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Internationalization & Localization - :keywords lang=en: internationalization localization,internationalization and localization,language application,gettext,l10n,pot,i18n,translation,languages + :title lang=es: Internationalization & Localization + :keywords lang=es: internationalization localization,internationalization and localization,language application,gettext,l10n,pot,i18n,translation,languages diff --git a/es/core-libraries/logging.rst b/es/core-libraries/logging.rst index e067a3138785d70533d93c10dd72345f1292707c..9b2206f53e05c01fa5ed297f3a9ca1b7452f4098 100644 --- a/es/core-libraries/logging.rst +++ b/es/core-libraries/logging.rst @@ -2,393 +2,15 @@ Logging ####### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -While CakePHP core Configure Class settings can really help you see -what's happening under the hood, there are certain times that -you'll need to log data to the disk in order to find out what's -going on. In a world that is becoming more dependent on -technologies like SOAP and AJAX, debugging can be rather -difficult. - -Logging can also be a way to find out what's been going on in your -application over time. What search terms are being used? What sorts -of errors are my users being shown? How often is a particular query -being executed? - -Logging data in CakePHP is easy - the log() function is provided by the -``LogTrait``, which is the common ancestor for almost all CakePHP classes. If -the context is a CakePHP class (Model, Controller, Component... almost -anything), you can log your data. You can also use ``Log::write()`` directly. -See :ref:`writing-to-logs`. - -.. _log-configuration: - -Logging Configuration -===================== - -Configuring ``Log`` should be done during your application's bootstrap phase. -The ``config/app.php`` file is intended for just this. You can define -as many or as few loggers as your application needs. Loggers should be -configured using :php:class:`Cake\\Core\\Log`. An example would be:: - - use Cake\Log\Log; - - // Short classname - Log::config('debug', [ - 'className' => 'FileLog', - 'levels' => ['notice', 'info', 'debug'], - 'file' => 'debug', - ]); - - // Fully namespaced name. - Log::config('error', [ - 'className' => 'Cake\Log\Engine\FileLog', - 'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'], - 'file' => 'error', - ]); - -The above creates two loggers. One named ``debug`` the other named ``error``. -Each is configured to handle different levels of messages. They also store their -log messages in separate files, so its easy to separate debug/notice/info logs -from more serious errors. See the section on :ref:`logging-levels` for more -information on the different levels and what they mean. - -Once a configuration is created you cannot change it. Instead you should drop -the configuration and re-create it using :php:meth:`Cake\\Log\\Log::drop()` and -:php:meth:`Cake\\Log\\Log::config()`. - -Creating Log Adapters ---------------------- - -Log adapters can be part of your application, or part of -plugins. If for example you had a database logger called -``DatabaseLog``. As part of your application it would be placed in -``src/Log/Engine/DatabaseLog.php``. As part of a plugin it would be placed in -``plugins/LoggingPack/src/Log/Engine/DatabaseLog.php``. To configure log -adapters you should use :php:meth:`Cake\\Log\\Log::config()`. For example -configuring our DatabaseLog would look like:: - - // For src/Log - Log::config('otherFile', [ - 'className' => 'DatabaseLog', - 'model' => 'LogEntry', - // ... - ]); - - // For plugin called LoggingPack - Log::config('otherFile', [ - 'className' => 'LoggingPack.DatabaseLog', - 'model' => 'LogEntry', - // ... - ]); - -When configuring a log adapter the ``className`` parameter is used to -locate and load the log handler. All of the other configuration -properties are passed to the log adapter's constructor as an array. :: - - use Cake\Log\LogInterface; - - class DatabaseLog implements LogInterface - { - public function __construct($options = []) - { - // ... - } - - public function write($level, $message, $scope = []) - { - // Write to the database. - } - } - -CakePHP requires that all logging adapters implement -:php:class:`Cake\\Log\\LogInterface`. - -.. _file-log: - -``FileLog`` engine takes the following options: - -* ``size`` Used to implement basic log file rotation. If log file size - reaches specified size the existing file is renamed by appending timestamp - to filename and new log file is created. Can be integer bytes value or - human reabable string values like '10MB', '100KB' etc. Defaults to 10MB. -* ``rotate`` Log files are rotated specified times before being removed. - If value is 0, old versions are removed rather then rotated. Defaults to 10. -* ``mask`` Set the file permissions for created files. If left empty the default - permissions are used. - -.. warning:: - - Engines have the suffix ``Log``. You should avoid class names like ``SomeLogLog`` - which include the suffix twice at the end. - -.. note:: - - You should configure loggers during bootstrapping. ``config/app.php`` is the - conventional place to configure log adapters. - - In debug mode missing directories will be automatically created to avoid unnecessary - errors thrown when using the FileEngine. - -Error and Exception Logging -=========================== - -Errors and Exceptions can also be logged. By configuring the co-responding -values in your app.php file. Errors will be displayed when debug > 0 and logged -when debug is ``false``. To log uncaugh exceptions, set the ``log`` option to -``true``. See :doc:`/development/configuration` for more information. - -Interacting with Log Streams -============================ - -You can introspect the configured streams with -:php:meth:`Cake\\Log\\Log::configured()`. The return of ``configured()`` is an -array of all the currently configured streams. You can remove -streams using :php:meth:`Cake\\Log\\Log::drop()`. Once a log stream has been -dropped it will no longer receive messages. - - -Using the FileLog Adapter -========================= - -As its name implies FileLog writes log messages to files. The level of log -message being written determines the name of the file the message is stored in. -If a level is not supplied, :php:const:`LOG_ERROR` is used which writes to the -error log. The default log location is ``logs/$level.log``:: - - // Executing this inside a CakePHP class - $this->log("Something didn't work!"); - - // Results in this being appended to logs/error.log - // 2007-11-02 10:22:02 Error: Something didn't work! - -The configured directory must be writable by the web server user in -order for logging to work correctly. - -You can configure additional/alternate FileLog locations when configuring -a logger.FileLog accepts a ``path`` which allows for -custom paths to be used:: - - Log::config('custom_path', [ - 'className' => 'File', - 'path' => '/path/to/custom/place/' - ]); - -.. warning:: - If you do not configure a logging adapter, log messages will not be stored. - -.. _syslog-log: - -Logging to Syslog -================= - -In production environments it is highly recommended that you setup your system to -use syslog instead of the files logger. This will perform much better as any -writes will be done in a (almost) non-blocking fashion and your operating system -logger can be configured separately to rotate files, pre-process writes or use -a completely different storage for your logs. - -Using syslog is pretty much like using the default FileLog engine, you just need -to specify ``Syslog`` as the engine to be used for logging. The following -configuration snippet will replace the default logger with syslog, this should -be done in the ``bootstrap.php`` file:: - - CakeLog::config('default', array( - 'engine' => 'Syslog' - )); - -The configuration array accepted for the Syslog logging engine understands the -following keys: - -* ``format``: An sprintf template strings with two placeholders, the first one - for the error level, and the second for the message itself. This key is - useful to add additional information about the server or process in the - logged message. For example: ``%s - Web Server 1 - %s`` will look like - ``error - Web Server 1 - An error occurred in this request`` after - replacing the placeholders. -* ``prefix``: An string that will be prefixed to every logged message. -* ``flag``: An integer flag to be used for opening the connection to the - logger, by default ``LOG_ODELAY`` will be used. See ``openlog`` documentation - for more options -* ``facility``: The logging slot to use in syslog. By default ``LOG_USER`` is - used. See ``syslog`` documentation for more options - -.. _writing-to-logs: - -Writing to Logs -=============== - -Writing to the log files can be done in 2 different ways. The first -is to use the static :php:meth:`Cake\\Log\\Log::write()` method:: - - Log::write('debug', 'Something did not work'); - -The second is to use the log() shortcut function available on any -using the ``LogTrait`` Calling log() will internally call -``Log::write()``:: - - // Executing this inside a class using LogTrait - $this->log("Something did not work!", 'debug'); - -All configured log streams are written to sequentially each time -:php:meth:`Cake\\Log\\Log::write()` is called. If you have not configured any -logging adapters ``log()`` will return false and no log messages will be -written. - -.. _logging-levels: - -Using Levels ------------- - -CakePHP supports the standard POSIX set of logging levels. Each level represents -an increasing level of severity: - -* Emergency: system is unusable -* Alert: action must be taken immediately -* Critical: critical conditions -* Error: error conditions -* Warning: warning conditions -* Notice: normal but significant condition -* Info: informational messages -* Debug: debug-level messages - -You can refer to these levels by name when configuring loggers, and when writing -log messages. Alternatively, you can use convenience methods like -:php:meth:`Cake\\Log\\Log::error()` to clearly and easily indicate the logging -level. Using a level that is not in the above levels will result in an -exception. - -.. _logging-scopes: - -Logging Scopes --------------- - -Often times you'll want to configure different logging behavior for different -subsystems or parts of your application. Take for example an e-commerce shop. -You'll probably want to handle logging for orders and payments differently than -you do other less critical logs. - -CakePHP exposes this concept as logging scopes. When log messages are written -you can include a scope name. If there is a configured logger for that scope, -the log messages will be directed to those loggers. If a log message is written -to an unknown scope, loggers that handle that level of message will log the -message. For example:: - - // Configure logs/shops.log to receive all levels, but only - // those with `orders` and `payments` scope. - Log::config('shops', [ - 'className' => 'FileLog', - 'levels' => [], - 'scopes' => ['orders', 'payments'], - 'file' => 'shops.log', - ]); - - // Configure logs/payments.log to receive all levels, but only - // those with `payments` scope. - Log::config('payments', [ - 'className' => 'FileLog', - 'levels' => [], - 'scopes' => ['payments'], - 'file' => 'payments.log', - ]); - - Log::warning('this gets written only to shops.log', 'orders'); - Log::warning('this gets written to both shops.log and payments.log', 'payments'); - Log::warning('this gets written to both shops.log and payments.log', 'unknown'); - -As of 3.0 the logging scope passed to :php:meth:`Cake\\Log\\Log::write()` is -forwarded to the log engines' ``write()`` method in order to provide better -context to the engines. - -Log API -======= - -.. php:namespace:: Cake\Log - -.. php:class:: Log - - A simple class for writing to logs. - -.. php:staticmethod:: config($key, $config) - - :param string $name: Name for the logger being connected, used - to drop a logger later on. - :param array $config: Array of configuration information and - constructor arguments for the logger. - - Get or set the configuration for a Logger. See :ref:`log-configuration` for - more information. - -.. php:staticmethod:: configured() - - :returns: An array of configured loggers. - - Get the names of the configured loggers. - -.. php:staticmethod:: drop($name) - - :param string $name: Name of the logger you wish to no longer receive - messages. - -.. php:staticmethod:: write($level, $message, $scope = array()) - - Write a message into all the configured loggers. - ``$level`` indicates the level of log message being created. - ``$message`` is the message of the log entry being written to. - ``$scope`` is the scope(s) a log message is being created in. - -.. php:staticmethod:: levels() - -Call this method without arguments, eg: `Log::levels()` to obtain current -level configuration. - -Convenience Methods -------------------- - -The following convenience methods were added to log `$message` with the -appropriate log level. - -.. php:staticmethod:: emergency($message, $scope = array()) -.. php:staticmethod:: alert($message, $scope = array()) -.. php:staticmethod:: critical($message, $scope = array()) -.. php:staticmethod:: error($message, $scope = array()) -.. php:staticmethod:: warning($message, $scope = array()) -.. php:staticmethod:: notice($message, $scope = array()) -.. php:staticmethod:: debug($message, $scope = array()) -.. php:staticmethod:: info($message, $scope = array()) - -Log Adapter Interface -===================== - -.. php:interface:: LogInterface - - This interface is required for logging adapters. When creating a new logging - adapter you'll need to implement this interface. - -.. php:method:: write($level, $message, $scope = []) - - Write a message to the log storage system. ``$level`` will be the level of - the log message. ``$message`` will be the content of the log message. - ``$scope`` is the scope(s) a log message is being created in. - -Logging Trait -============= - -.. php:trait:: LogTrait - - A trait that provides shortcut methods for logging - -.. php:method:: log($msg, $level = LOG_ERR) - - Log a message to the logs. By default messages are logged as - ERROR messages. If ``$msg`` isn't isn't a string it will be converted with - ``print_r`` before being logged. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Logging - :description lang=en: Log CakePHP data to the disk to help debug your application over longer periods of time. - :keywords lang=en: cakephp logging,log errors,debug,logging data,cakelog class,ajax logging,soap logging,debugging,logs + :title lang=es: Logging + :description lang=es: Log CakePHP data to the disk to help debug your application over longer periods of time. + :keywords lang=es: cakephp logging,log errors,debug,logging data,cakelog class,ajax logging,soap logging,debugging,logs diff --git a/es/core-libraries/number.rst b/es/core-libraries/number.rst new file mode 100644 index 0000000000000000000000000000000000000000..e28d1223118cf5520a8d2d128a25681ae296c6c2 --- /dev/null +++ b/es/core-libraries/number.rst @@ -0,0 +1,20 @@ +Number +###### + +.. php:namespace:: Cake\I18n + +.. php:class:: Number + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: NumberHelper + :description lang=es: The Number Helper contains convenience methods that enable display numbers in common formats in your views. + :keywords lang=es: number helper,currency,number format,number precision,format file size,format numbers diff --git a/es/core-libraries/registry-objects.rst b/es/core-libraries/registry-objects.rst index 44313b4e37b0d724e55a051098759f606c743dd9..525e3efdeb3cf71ddef22cd78dab6422540a55e7 100644 --- a/es/core-libraries/registry-objects.rst +++ b/es/core-libraries/registry-objects.rst @@ -2,62 +2,14 @@ Registry Objects ################ .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -The registry classes provide a simple way to create and retrieve loaded -instances of a given object type. There are registry classes for Components, -Helpers, Tasks, and Behaviors. - -While the examples below, will use Components, the same behavior can be expected -for Helpers, Behaviors, and Tasks in addition to Components. - -Loading Objects -=============== - -Objects can be loaded on-the-fly using add() -Example:: - - $this->loadComponent('Acl.Acl'); - $this->addHelper('Flash') - -Will result in the ``Toolbar`` property and ``Flash`` helper being loaded. -Configuration can also be set on-the-fly. Example:: - - $this->loadComponent('Cookie', ['name' => 'sweet']); - -Any keys & values provided will be passed to the Component's constructor. The -one exception to this rule is ``className``. Classname is a special key that is -used to alias objects in a registry. This allows you to have component names -that do not reflect the classnames, which can be helpful when extending core -components:: - - $this->Auth = $this->loadComponent('Auth', ['className' => 'MyCustomAuth']); - $this->Auth->user(); // Actually using MyCustomAuth::user(); - -Triggering Callbacks -==================== - -Callbacks are not provided by registry objects. You should use the -:doc:`events system ` to dispatch any events/callbacks -for your application. - -Disabling Callbacks -=================== - -In previous versions collection objects provided a ``disable`` method to disable -objects from recieving callbacks. To do this now, you should use the features in -the events system. For example you could disable component callbacks in the -following way:: - - // Remove Auth from callbacks. - $this->eventManager()->off($this->Auth); - - // Re-enable Auth for callbacks. - $this->eventManager()->on($this->Auth); + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Object Registry - :keywords lang=en: array name,loading components,several different kinds,unified api,loading objects,component names,special key,core components,callbacks,prg,callback,alias,fatal error,collections,memory,priority,priorities + :title lang=es: Object Registry + :keywords lang=es: array name,loading components,several different kinds,unified api,loading objects,component names,special key,core components,callbacks,prg,callback,alias,fatal error,collections,memory,priority,priorities diff --git a/es/core-libraries/security.rst b/es/core-libraries/security.rst new file mode 100644 index 0000000000000000000000000000000000000000..908fccac5b35530cdd9df819f1bf8a24b18c5d24 --- /dev/null +++ b/es/core-libraries/security.rst @@ -0,0 +1,19 @@ +Security +######## + +.. php:namespace:: Cake\Utility + +.. php:class:: Security + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Security + :keywords lang=es: security api,secret password,cipher text,php class,class security,text key,security library,object instance,security measures,basic security,security level,string type,fallback,hash,data security,singleton,inactivity,php encrypt,implementation,php security diff --git a/es/core-libraries/text.rst b/es/core-libraries/text.rst new file mode 100644 index 0000000000000000000000000000000000000000..6e02eb93e8749233184c5029a871661aa18a95fd --- /dev/null +++ b/es/core-libraries/text.rst @@ -0,0 +1,19 @@ +Text +#### + +.. php:namespace:: Cake\Utility + +.. php:class:: Text + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Text + :keywords lang=es: array php,array name,string options,data options,result string,class string,string data,string class,placeholders,default method,key value,markup,rfc,replacements,convenience,templates diff --git a/es/core-libraries/time.rst b/es/core-libraries/time.rst new file mode 100644 index 0000000000000000000000000000000000000000..75cc083dd7221b52a1eaded86feab198b8af083f --- /dev/null +++ b/es/core-libraries/time.rst @@ -0,0 +1,20 @@ +Time +#### + +.. php:namespace:: Cake\Utility + +.. php:class:: Time + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Time + :description lang=es: Time class helps you format time and test time. + :keywords lang=es: time,format time,timezone,unix epoch,time strings,time zone offset,utc,gmt diff --git a/es/core-libraries/toc-behaviors.rst b/es/core-libraries/toc-behaviors.rst deleted file mode 100644 index 9a22bc7a41220c998b0f50e3839018078f5f71cb..0000000000000000000000000000000000000000 --- a/es/core-libraries/toc-behaviors.rst +++ /dev/null @@ -1,29 +0,0 @@ -Behaviors -######### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -Behaviors add extra functionality to your table objects. CakePHP comes with -a number of built-in behaviors such as -:php:class:`~Cake\\Model\\Behavior\\TimestampBehavior`. - -To learn about creating and using behaviors, read the section -on :doc:`/orm/behaviors`. - -.. start-toc - -CakePHP ships with a selection of built-in behaviors. To find out more about -each one, view the relevant chapters below. - -.. toctree:: - :maxdepth: 1 - - /core-libraries/behaviors/timestamp - /core-libraries/behaviors/counter-cache - /core-libraries/behaviors/translate - /core-libraries/behaviors/tree - -.. end-toc diff --git a/es/core-libraries/toc-components.rst b/es/core-libraries/toc-components.rst deleted file mode 100644 index 2ad1cac7e83568b14c37ccaef925139808665c20..0000000000000000000000000000000000000000 --- a/es/core-libraries/toc-components.rst +++ /dev/null @@ -1,23 +0,0 @@ -Components -########## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -CakePHP has a selection of components to help take care of basic tasks in your -controllers. See the section on :doc:`/controllers/components` for how to -configure and use components. - -.. toctree:: - :maxdepth: 1 - - /core-libraries/components/pagination - /core-libraries/components/sessions - /core-libraries/components/flash - /core-libraries/components/authentication - /core-libraries/components/csrf-component - /core-libraries/components/security-component - /core-libraries/components/request-handling - /core-libraries/components/cookie diff --git a/es/core-libraries/toc-general-purpose.rst b/es/core-libraries/toc-general-purpose.rst deleted file mode 100644 index 7424dc46423ca49eeee9f4d2c1f4abfc4ee5eac2..0000000000000000000000000000000000000000 --- a/es/core-libraries/toc-general-purpose.rst +++ /dev/null @@ -1,12 +0,0 @@ -Uso general -########### - -.. toctree:: - :maxdepth: 2 - - global-constants-and-functions - ../core-utility-libraries/app - collections - events - registry-objects - validation diff --git a/es/core-libraries/toc-helpers.rst b/es/core-libraries/toc-helpers.rst deleted file mode 100644 index 5c6ac72178edcd7657bedafe3cc6cc450c1aa040..0000000000000000000000000000000000000000 --- a/es/core-libraries/toc-helpers.rst +++ /dev/null @@ -1,28 +0,0 @@ -Helpers -####### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -CakePHP features a number of helpers that aid in view creation. They assist in -creating well-formed markup (including forms), aid in formatting text, times and -numbers. Here is a summary of the built-in helpers. - -Read :doc:`/views/helpers` to learn more about helpers, their API, and how you -can create and use your own helpers. - -.. toctree:: - :maxdepth: 1 - - /core-libraries/helpers/url - /core-libraries/helpers/form - /core-libraries/helpers/html - /core-libraries/helpers/number - /core-libraries/helpers/paginator - /core-libraries/helpers/rss - /core-libraries/helpers/session - /core-libraries/helpers/flash - /core-libraries/helpers/text - /core-libraries/helpers/time diff --git a/es/core-libraries/toc-utilities.rst b/es/core-libraries/toc-utilities.rst deleted file mode 100644 index 5fcbc454bd003a2ed4e5856ca119918303819211..0000000000000000000000000000000000000000 --- a/es/core-libraries/toc-utilities.rst +++ /dev/null @@ -1,20 +0,0 @@ -Utiliades -######### - -.. toctree:: - :maxdepth: 2 - - caching - ../core-utility-libraries/email - ../core-utility-libraries/file-folder - ../core-utility-libraries/hash - ../core-utility-libraries/httpclient - ../core-utility-libraries/inflector - internationalization-and-localization - logging - ../core-utility-libraries/number - ../core-utility-libraries/router - ../core-utility-libraries/security - ../core-utility-libraries/string - ../core-utility-libraries/time - ../core-utility-libraries/xml diff --git a/es/core-libraries/validation.rst b/es/core-libraries/validation.rst index 73bb22bf8bca4c5ab96553e07c6bac1be554f25c..30e79e257efd66292b7cb1389883ac0895ee0e56 100644 --- a/es/core-libraries/validation.rst +++ b/es/core-libraries/validation.rst @@ -4,363 +4,10 @@ Validation ########## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -The validation package in CakePHP provides features to build validators that can -validate arbitrary arrays of data with ease. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -Creating Validators -=================== - -.. php:class:: Validator - -Validator objects define the rules that apply to a set of fields. -Validator objects contain a mapping between fields and validation sets. In turn, the -validation sets contain a collection of rules that apply to the field they are -attached to. Creating a validator is simple:: - - use Cake\Validation\Validator; - - $validator = new Validator(); - -Once created, you can start defining sets of rules for the fields you want to -validate:: - - $validator - ->validatePresence('title') - ->notEmpty('title', 'Please fill this field') - ->add('title', [ - 'length' => [ - 'rule' => ['minLength', 10], - 'message' => 'Titles need to be at least 10 characters long', - ] - ]) - ->allowEmpty('published') - ->add('published', 'boolean', [ - 'rule' => 'boolean' - ]) - ->validatePresence('body') - ->add('body', 'length', [ - 'rule' => ['minLength', 50], - 'message' => 'Articles must have a substantial body.' - ]); - -As seen in the example above, validators are built with a fluent interface that -allows you to define rules for each field you want to validate. - -There were a few methods called in the example above, so let's go over the -various features. The ``add()`` method allows you to add new rules to -a validator. You can either add rules individually or in groups as seen above. - -Validating Field Presence -------------------------- - -The ``validatePresence()`` method requires the field to be present in any -validated array. If the field is absent, validation will fail. The -``validatePresence()`` method has 4 modes: - -* ``true`` The field's presence is always required. -* ``false`` The field's presence is not required. -* ``create`` The field's presence is required when validating a **create** - operation. -* ``update`` The field's presence is required when validating an **update** - operation. - -By default, ``true`` is used. Key presence is checked by using -``array_key_exists()`` so that null values will count as present. You can set the -mode using the second parameter:: - - $validator->validatePresence('author_id', 'create'); - -Allowing Empty Fields ---------------------- - -The ``allowEmpty()`` and ``notEmpty()`` methods allow you to control which fields are -allowed to be 'empty'. By using the ``notEmpty()`` method, the given field will be marked -invalid when it is empty. You can use ``allowEmpty()`` to allow a field to be -empty. Both ``allowEmpty()`` and ``notEmpty()`` support a mode parameter that -allows you to control when a field can or cannot be empty: - -* ``false`` The field is not allowed to be empty. -* ``create`` The field is required when validating a **create** - operation. -* ``update`` The field is required when validating an **update** - operation. - -The values ``''``, ``null`` and ``[]`` (empty array) will cause validation -errors when fields are not allowed to be empty. When fields are allowed to be -empty, the values ``''``, ``null``, ``false``, ``[]``, ``0``, ``'0'`` are -accepted. - -An example of these methods in action is:: - - $validator->allowEmpty('published') - ->notEmpty('title', 'A title is required') - ->notEmpty('body', 'A title is required', 'create') - ->allowEmpty('header_image', 'update'); - -Unique Fields -------------- - -The ``Table`` class provides a validation rule to ensure that a given field -is unique within a table. For example, if you wanted to make sure that an e-mail -address is unique, you could do the following:: - - $validator->add('email', [ - 'unique' => ['rule' => 'validateUnique', 'provider' => 'table'] - ]); - -If you wish to only ensure uniqueness of a field based on an another field in -your table, such as a foreign key of an associated table, you can scope it with -the following:: - - $validator->add('email', [ - 'unique' => [ - 'rule' => ['validateUnique', ['scope' => 'site_id']], - 'provider' => 'table' - ] - ]); - -This will ensure that the provided e-mail address is only unique to other -records with the same ``site_id``. - -Notice that these examples take a ``provider`` key. Adding ``Validator`` -providers is further explained in the following sections. - -Marking Rules as the Last to Run --------------------------------- - -When fields have multiple rules, each validation rule will be run even if the -previous one has failed. This allows you to collect as many validation errors as -you can in a single pass. However, if you want to stop execution after -a specific rule has failed, you can set the ``last`` option to ``true``:: - - $validator = new Validator(); - $validator - ->add('body', [ - 'minLength' => [ - 'rule' => ['minLength', 10], - 'last' => true, - 'message' => 'Comments must have a substantial body.' - ], - 'maxLength' => [ - 'rule' => ['maxLength', 250], - 'message' => 'Comments cannot be too long.' - ] - ]); - -If the minLength rule fails in the example above, the maxLength rule will not be -run. - -Adding Validation Providers ---------------------------- - -The ``Validator``, ``ValidationSet`` and ``ValidationRule`` classes do not -provide any validation methods themselves. Validation rules come from -'providers'. You can bind any number of providers to a Validator object. -Validator instances come with a 'default' provider setup automatically. The -default provider is mapped to the :php:class:`~Cake\\Validation\\Validation` -class. This makes it simple to use the methods on that class as validation -rules. When using Validators and the ORM together, additional providers are -configured for the table and entity objects. You can use the ``provider`` method -to add any additional providers your application needs:: - - $validator = new Validator(); - - // Use an object instance. - $validator->provider('custom', $myObject); - - // Use a class name. Methods must be static. - $validator->provider('custom', 'App\Model\Validation'); - -Validation providers can be objects, or class names. If a class name is used the -methods must be static. To use a provider other than 'default', be sure to set -the ``provider`` key in your rule:: - - // Use a rule from the table provider - $validator->add('title', 'unique', [ - 'rule' => 'uniqueTitle', - 'provider' => 'table' - ]); - -Custom Validation Rules ------------------------ - -In addition to using methods coming from providers, you can also use any -callable, including anonymous functions, as validation rules:: - - // Use a global function - $validator->add('title', 'custom', [ - 'rule' => 'validate_title' - ]); - - // Use an array callable that is not in a provider - $validator->add('title', 'custom', [ - 'rule' => [$this, 'method'] - ]); - - // Use a closure - $validator->add('title', 'custom', [ - 'rule' => function ($value, $context) { - // Custom logic that returns true/false - } - ]); - - // Use a rule from a custom provider - $validator->add('title', 'unique', [ - 'rule' => 'uniqueTitle', - 'provider' => 'custom' - ]); - -Closures or callable methods will receive 2 arguments when called. The first -will be the value for the field being validated. The second is a context array -containing data related to the validation process: - -- **data**: The original data passed to the validation method, useful if you - plan to to create rules comparing values. -- **providers**: The complete list of rule provider objects, useful if you - need to create complex rules by calling multiple providers. -- **newRecord**: Whether the validation call is for a new record or - a pre-existent one. - -Conditional Validation ----------------------- - -When defining validation rules, you can use the ``on`` key to define when -a validation rule should be applied. If left undefined, the rule will always be -applied. Other valid values are ``create`` and ``update``. Using one of these -values will make the rule apply to only create or update operations. - -Additionally, you can provide a callable function that will determine whether or -not a particular rule should be applied:: - - $validator->add('picture', 'file', [ - 'rule' => ['mimeType', ['image/jpeg', 'image/png']], - 'on' => function ($context) { - return !empty($context['data']['show_profile_picture']); - } - ]); - -The above example will make the rule for 'picture' optional depending on whether -the value for ``show_profile_picture`` is empty. - -The same can be done for the ``allowEmpty()`` and ``notEmpty`` validation method. -Both take a callable function as the last argument, which determines whether or not -the rule should be applied. For example, a field can be sometimes allowed to be -empty:: - - $validator->allowEmpty('tax', function($context) { - return !$context['data']['is_taxable']; - }); - -Likewise, a field can be required to be populated when certain conditions are -met:: - - $validator->notEmpty('email_frequency', 'This field is required', function($context) { - return !empty($context['data']['wants_newsletter']); - }); - -In the above example, the ``email_frequency`` field cannot be left empty if the -the user wants to receive the newsletter. - -.. _reusable-validators: - -Creating Reusable Validators ----------------------------- - -While defining validators inline where they are used makes for good example -code, it doesn't lead to easily maintainable applications. Instead, you should -create ``Validator`` sub-classes for your reusable validation logic:: - - // In src/Model/Validation/ContactValidator.php - namespace App\Model\Validation; - - use Cake\Validation\Validator; - - class ContactValidator extends Validator - { - public function __construct() - { - // Add validation rules here. - } - } - -Validating Data -=============== - -Now that you've created a validator and added the rules you want to it, you can -start using it to validate data. Validators are able to validate array based -data. For example, if you wanted to validate a contact form before creating and -sending an email you could do the following:: - - use Cake\Validation\Validator; - - $validator = new Validator(); - $validator - ->validatePresence('email') - ->add('email', 'validFormat', [ - 'rule' => 'email', - 'message' => 'E-mail must be valid' - ]) - ->validatePresence('name') - ->notEmpty('name', 'We need your name.') - ->validatePresence('comment') - ->notEmpty('comment', 'You need to give a comment.'); - - $errors = $validator->errors($this->request->data()); - if (!empty($errors)) { - // Send an email. - } - -The ``errors()`` method will return a non-empty array when there are validation -failures. The returned array of errors will be structured like:: - - $errors = [ - 'email' => ['E-mail must be valid'] - ]; - -If you have multiple errors on a single field, an array of error messages will -be returned per field. By default the ``errors()`` method applies rules for -the 'create' mode. If you'd like to apply 'update' rules you can do the following:: - - $errors = $validator->errors($this->request->data(), false); - if (!empty($errors)) { - // Send an email. - } - -.. note:: - - If you need to validate entities you should use methods like - :php:meth:`~Cake\\ORM\\Table::validate()` or - :php:meth:`~Cake\\ORM\\Table::save()` as they are designed for that. - -Core Validation Rules -===================== - -CakePHP provides a basic suite of validation methods in the ``Validation`` -class. The Validation class contains a variety of static methods that provide -validators for a several common validation situations. - -The `API documentation -`_ for the -``Validation`` class provides a good list of the validation rules that are -available, and their basic usage. - -Some of the validation methods accept additional parameters to define boundary -conditions or valid options. You can provide these boundary conditions & options -as follows:: - - $validator = new Validator(); - $validator - ->add('title', 'minLength', [ - 'rule' => ['minLength', 10] - ]) - ->add('rating', 'validValue', [ - 'rule' => ['between', 1, 5] - ]); - -Core rules that take additional parameters should have an array for the ``rule`` key -that contains the rule as the first element, and the additional parameters as -the remaining parameters. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/core-libraries/xml.rst b/es/core-libraries/xml.rst new file mode 100644 index 0000000000000000000000000000000000000000..5e7bc351df7ef78ae6eac8d8fd7eef072cb111b2 --- /dev/null +++ b/es/core-libraries/xml.rst @@ -0,0 +1,19 @@ +Xml +### + +.. php:namespace:: Cake\Utility + +.. php:class:: Xml + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Xml + :keywords lang=es: array php,xml class,xml objects,post xml,xml object,string url,string data,xml parser,php 5,bakery,constructor,php xml,cakephp,php file,unicorns,meth diff --git a/es/core-utility-libraries/app.rst b/es/core-utility-libraries/app.rst deleted file mode 100644 index 7ed412b4f0044fb504ec015e6d5ca35da0f67cc0..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/app.rst +++ /dev/null @@ -1,133 +0,0 @@ -App Class -######### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Core - -.. php:class:: App - -The App class is responsible for resource location and path management. - -Finding Classes -=============== - -.. php:staticmethod:: classname($name, $type = '', $suffix = '') - -This method is used to resolve classnames throughout CakePHP. It resolves -the short form names CakePHP uses and returns the fully resolved classname:: - - // Resolve a short classname with the namespace + suffix. - App::classname('Auth', 'Controller/Component', 'Component'); - // Returns Cake\Controller\Component\AuthComponent - - // Resolve a plugin name. - App::classname('DebugKit.Toolbar', 'Controller/Component', 'Component'); - // Returns DebugKit\Controller\Component\ToolbarComponent - - // Names with \ in them will be returned unaltered. - App::classname('App\Cache\ComboCache'); - // Returns App\Cache\ComboCache - -When resolving classes, the ``App`` namespace will be tried, and if the -class does not exist the ``Cake`` namespace will be attempted. If both -classnames do not exist, ``false`` will be returned. - -Finding Paths to Namespaces -=========================== - -.. php:staticmethod:: path(string $package, string $plugin = null) - -Used to get locations for paths based on conventions:: - - // Get the path to Controller/ in your application - App::path('Controller'); - -This can be done for all namespaces that are part of your application. You -can also fetch paths for a plugin:: - - // Returns the component paths in DebugKit - App::path('Component', 'DebugKit'); - -``App::path()`` will only return the default path, and will not be able to -provide any information about additional paths the autoloader is configured -for. - -.. php:staticmethod:: core(string $package) - -Used for finding the path to a package inside CakePHP:: - - // Get the path to Cache engines. - App::core('Cache/Engine'); - - -Locating Plugins -================ - -.. php:staticmethod:: pluginPath(string $plugin) - -Plugins can be located with App as well. Using ``App::pluginPath('DebugKit');`` -for example, will give you the full path to the DebugKit plugin:: - - $path = App::pluginPath('DebugKit'); - -Locating Themes -=============== - -Since themes are plugins, you can use the methods above to get the path to -a theme. - -Loading Vendor Files -==================== - -Ideally vendor files should be autoloaded with ``Composer``, if you have vendor -files that cannot be autoloaded or installed with Composer you will need to use -``require`` to load them. - -If you cannot install a library with Composer, it is best to install each library in -a directory following Composer's convention of ``vendor/$author/$package``. -If you had a library called AcmeLib, you could install it into -``vendor/Acme/AcmeLib``. Assuming it did not use PSR-0 compatible classnames -you could autoload the classes within it using ``classmap`` in your -application's ``composer.json``:: - - "autoload": { - "psr-4": { - "App\\": "App", - "App\\Test\\": "Test", - "": "./Plugin" - }, - "classmap": [ - "vendor/Acme/AcmeLib" - ] - } - -If your vendor library does not use classes, and instead provides functions, you -can configure Composer to load these files at the beginning of each request -using the ``files`` autoloading strategy:: - - "autoload": { - "psr-4": { - "App\\": "App", - "App\\Test\\": "Test", - "": "./Plugin" - }, - "files": [ - "vendor/Acme/AcmeLib/functions.php" - ] - } - -After configuring the vendor libraries you will need to regenerate your -application's autoloader using:: - - $ php composer.phar dump-autoload - -If you happen to not be using Composer in your application, you will need to -manually load all vendor libraries yourself. - -.. meta:: - :title lang=en: App Class - :keywords lang=en: compatible implementation,model behaviors,path management,loading files,php class,class loading,model behavior,class location,component model,management class,autoloader,classname,directory location,override,conventions,lib,textile,cakephp,php classes,loaded diff --git a/es/core-utility-libraries/email.rst b/es/core-utility-libraries/email.rst deleted file mode 100644 index 14b74be7cfb7a71e327685c980cd1f719b23511f..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/email.rst +++ /dev/null @@ -1,430 +0,0 @@ -Email -##### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Network\Email - -.. php:class:: Email(mixed $profile = null) - -``Email`` is a new class to send email. With this -class you can send email from any place inside of your application. - -Basic Usage -=========== - -First of all, you should ensure the class is loaded:: - - use Cake\Network\Email\Email; - -After you've loaded ``Email``, you can send an email with the following:: - - $email = new Email(); - $email->from(['me@example.com' => 'My Site']) - ->to('you@example.com') - ->subject('About') - ->send('My message'); - -Since ``Email``'s setter methods return the instance of the class, you are able -to set its properties with method chaining. - -Choosing the Sender -------------------- - -When sending email on behalf of other people, it's often a good idea to define the -original sender using the Sender header. You can do so using ``sender()``:: - - $email = new Email(); - $email->sender('app@example.com', 'MyApp emailer'); - -.. note:: - - It's also a good idea to set the envelope sender when sending mail on another - person's behalf. This prevents them from getting any messages about - deliverability. - -.. _email-configuration: - -Configuration -============= - -Configuration for ``Email`` defaults is created using ``config()`` and -``configTransport()``. You should put your email presets in the -``config/app.php`` file. The ``config/app.php.default`` file is an -example of this file. It is not required to define email configuration in -``config/app.php``. ``Email`` can be used without it and use the respective -methods to set all configurations separately or load an array of configs. - -By defining profiles and transports, you can keep your application code free of -configuration data, and avoid duplication that makes maintenance and deployment -less difficult. - -To load a predefined configuration, you can use the ``profile()`` method or pass it -to the constructor of ``Email``:: - - $email = new Email(); - $email->profile('default'); - - // Or in constructor - $email = new Email('default'); - -Instead of passing a string which matches a preset configuration name, you can -also just load an array of options:: - - $email = new Email(); - $email->profile(['from' => 'me@example.org', 'transport' => 'my_custom']); - - // Or in constructor - $email = new Email(['from' => 'me@example.org', 'transport' => 'my_custom']); - -Configuring Transports ----------------------- - -.. php:staticmethod:: configTransport($key, $config = null) - -Email messages are delivered by transports. Different transports allow you to -send messages via PHP's ``mail()`` function, SMTP servers, or not at all which -is useful for debugging. Configuring transports allows you to keep configuration -data out of your application code and makes deployment simpler as you can simply -change the configuration data. An example transport configuration looks like:: - - use Cake\Network\Email\Email; - - // Sample Mail configuration - Email::configTransport('default', [ - 'className' => 'Mail' - ]); - - // Sample smtp configuration. - Email::configTransport('gmail', [ - 'host' => 'ssl://smtp.gmail.com', - 'port' => 465, - 'username' => 'my@gmail.com', - 'password' => 'secret', - 'className' => 'Smtp' - ]); - -You can configure SSL SMTP servers, like Gmail. To do so, put the ``ssl://`` -prefix in the host and configure the port value accordingly. You can also -enable TLS SMTP using the ``tls`` option:: - - use Cake\Network\Email\Email; - - Email::configTransport('gmail', [ - 'host' => 'smtp.gmail.com', - 'port' => 465, - 'username' => 'my@gmail.com', - 'password' => 'secret', - 'className' => 'Smtp', - 'tls' => true - ]); - -The above configuration would enable TLS communication for email messages. - -.. note:: - - To use SSL + SMTP, you will need to have the SSL configured in your PHP - install. - - -.. php:staticmethod:: dropTransport($key) - -Once configured, transports cannot be modified. In order to modify a transport -you must first drop it and then reconfigure it. - -.. _email-configurations: - -Configuration Profiles ----------------------- - -Defining delivery profiles allows you to consolidate common email settings into -re-usable profiles. Your application can have as many profiles as necessary. The -following configuration keys are used: - -- ``'from'``: Email or array of sender. See ``Email::from()``. -- ``'sender'``: Email or array of real sender. See ``Email::sender()``. -- ``'to'``: Email or array of destination. See ``Email::to()``. -- ``'cc'``: Email or array of carbon copy. See ``Email::cc()``. -- ``'bcc'``: Email or array of blind carbon copy. See ``Email::bcc()``. -- ``'replyTo'``: Email or array to reply the e-mail. See ``Email::replyTo()``. -- ``'readReceipt'``: Email address or an array of addresses to receive the - receipt of read. See ``Email::readReceipt()``. -- ``'returnPath'``: Email address or and array of addresses to return if have - some error. See ``Email::returnPath()``. -- ``'messageId'``: Message ID of e-mail. See ``Email::messageId()``. -- ``'subject'``: Subject of the message. See ``Email::subject()``. -- ``'message'``: Content of message. Do not set this field if you are using rendered content. -- ``'headers'``: Headers to be included. See ``Email::setHeaders()``. -- ``'viewRender'``: If you are using rendered content, set the view classname. - See ``Email::viewRender()``. -- ``'template'``: If you are using rendered content, set the template name. See - ``Email::template()``. -- ``'theme'``: Theme used when rendering template. See ``Email::theme()``. -- ``'layout'``: If you are using rendered content, set the layout to render. If - you want to render a template without layout, set this field to null. See - ``Email::template()``. -- ``'viewVars'``: If you are using rendered content, set the array with - variables to be used in the view. See ``Email::viewVars()``. -- ``'attachments'``: List of files to attach. See ``Email::attachments()``. -- ``'emailFormat'``: Format of email (html, text or both). See ``Email::emailFormat()``. -- ``'transport'``: Transport configuration name. See - :php:meth:`~Cake\\Network\\Email\\Email::configTransport()`. -- ``'log'``: Log level to log the email headers and message. ``true`` will use - LOG_DEBUG. See also ``CakeLog::write()`` - -All these configurations are optional, except ``'from'``. - -.. note:: - - The values of above keys using Email or array, like from, to, cc, etc will be passed - as first parameter of corresponding methods. The equivalent for: - ``Email::from('my@example.com', 'My Site')`` - would be defined as ``'from' => ['my@example.com' => 'My Site']`` in your config - -Setting Headers -=============== - -In ``Email`` you are free to set whatever headers you want. When migrating -to use Email, do not forget to put the ``X-`` prefix in your headers. - -See ``Email::setHeaders()`` and ``Email::addHeaders()`` - -Sending Templated Emails -======================== - -Emails are often much more than just a simple text message. In order -to facilitate that, CakePHP provides a way to send emails using CakePHP's -:doc:`view layer `. - -The templates for emails reside in a special folder in your application's -``Template`` directory called ``Email``. Email views can also use layouts -and elements just like normal views:: - - $email = new Email(); - $email->template('welcome', 'fancy') - ->emailFormat('html') - ->to('bob@example.com') - ->from('app@domain.com') - ->send(); - -The above would use ``src/Template/Email/html/welcome.ctp`` for the view -and ``src/Template/Layout/Email/html/fancy.ctp`` for the layout. You can -send multipart templated email messages as well:: - - $email = new Email(); - $email->template('welcome', 'fancy') - ->emailFormat('both') - ->to('bob@example.com') - ->from('app@domain.com') - ->send(); - -This would use the following view files: - -* ``src/Template/Email/text/welcome.ctp`` -* ``src/Template/Layout/Email/text/fancy.ctp`` -* ``src/Template/Email/html/welcome.ctp`` -* ``src/Template/Layout/Email/html/fancy.ctp`` - -When sending templated emails you have the option of sending either -``text``, ``html`` or ``both``. - -You can set view variables with ``Email::viewVars()``:: - - $email = new Email('templated'); - $email->viewVars(['value' => 12345]); - -In your email templates you can use these with:: - -

    Here is your value:

    - -You can use helpers in emails as well, much like you can in normal view files. -By default only the ``HtmlHelper`` is loaded. You can load additional -helpers using the ``helpers()`` method:: - - $Email->helpers(['Html', 'Custom', 'Text']); - -When setting helpers be sure to include 'Html' or it will be removed from the -helpers loaded in your email template. - -If you want to send email using templates in a plugin you can use the familiar -:term:`plugin syntax` to do so:: - - $email = new Email(); - $email->template('Blog.new_comment', 'Blog.auto_message'); - -The above would use templates from the Blog plugin as an example. - -In some cases, you might need to override the default template provided by plugins. -You can do this using themes by telling Email to use appropriate theme using -``Email::theme()`` method:: - - $email = new Email(); - $email->template('Blog.new_comment', 'Blog.auto_message'); - $email->theme('TestTheme'); - -This allows you to override the ``new_comment`` template in your theme without -modifying the Blog plugin. The template file needs to be created in the -following path: -``src/Template/Plugin/TestTheme/Blog/Email/text/new_comment.ctp``. - -Sending Attachments -=================== - -.. php:method:: attachments($attachments = null) - -You can attach files to email messages as well. There are a few -different formats depending on what kind of files you have, and how -you want the filenames to appear in the recipient's mail client: - -1. String: ``$Email->attachments('/full/file/path/file.png')`` will attach this - file with the name file.png. -2. Array: ``$Email->attachments(['/full/file/path/file.png'])`` will have - the same behavior as using a string. -3. Array with key: - ``$Email->attachments(['photo.png' => '/full/some_hash.png'])`` will - attach some_hash.png with the name photo.png. The recipient will see - photo.png, not some_hash.png. -4. Nested arrays:: - - $Email->attachments([ - 'photo.png' => [ - 'file' => '/full/some_hash.png', - 'mimetype' => 'image/png', - 'contentId' => 'my-unique-id' - ] - ]); - - The above will attach the file with different mimetype and with custom - Content ID (when set the content ID the attachment is transformed to inline). - The mimetype and contentId are optional in this form. - - 4.1. When you are using the ``contentId``, you can use the file in the HTML - body like ````. - - 4.2. You can use the ``contentDisposition`` option to disable the - ``Content-Disposition`` header for an attachment. This is useful when - sending ical invites to clients using outlook. - - 4.3 Instead of the ``file`` option you can provide the file contents as - a string using the ``data`` option. This allows you to attach files without - needing file paths to them. - -Using Transports -================ - -Transports are classes designed to send the e-mail over some protocol or method. -CakePHP supports the Mail (default), Debug and SMTP transports. - -To configure your method, you must use the :php:meth:`Cake\\Network\Email\\Email::transport()` -method or have the transport in your configuration:: - - $email = new Email(); - - // Use a named transport already configured using Email::configTransport() - $email->transport('gmail'); - - // Use a constructed object. - $transport = new DebugTransport(); - $email->transport($transport); - -Creating Custom Transports --------------------------- - -You are able to create your custom transports to integrate with others email -systems (like SwiftMailer). To create your transport, first create the file -``src/Network/Email/ExampleTransport.php`` (where Example is the name of your -transport). To start off your file should look like:: - - use Cake\Network\Email\AbstractTransport; - - class ExampleTransport extends AbstractTransport - { - - public function send(Email $email) - { - // Magic inside! - } - - } - -You must implement the method ``send(Email $email)`` with your custom logic. -Optionally, you can implement the ``config($config)`` method. ``config()`` is -called before send() and allows you to accept user configurations. By default, -this method puts the configuration in protected attribute ``$_config``. - -If you need to call additional methods on the transport before send, you can use -:php:meth:`Cake\\Network\\Email\\Email::transportClass()` to get an instance of the transport. -Example:: - - $yourInstance = $Email->transport('your')->transportClass(); - $yourInstance->myCustomMethod(); - $Email->send(); - -Relaxing Address Validation Rules ---------------------------------- - -.. php:method:: emailPattern($pattern = null) - -If you are having validation issues when sending to non-compliant addresses, you -can relax the pattern used to validate email addresses. This is sometimes -necessary when dealing with some Japanese ISP's:: - - $email = new Email('default'); - - // Relax the email pattern, so you can send - // to non-conformant addresses. - $email->emailPattern($newPattern); - - -Sending Messages Quickly -======================== - -Sometimes you need a quick way to fire off an email, and you don't necessarily -want do setup a bunch of configuration ahead of time. -:php:meth:`Cake\\Network\Email\\Email::deliver()` is intended for that purpose. - -You can create your configuration using -:php:meth:`Cake\\Network\\Email\\Email::config()`, or use an array with all -options that you need and use the static method ``Email::deliver()``. -Example:: - - Email::deliver('you@example.com', 'Subject', 'Message', ['from' => 'me@example.com']); - -This method will send an email to "you@example.com", from "me@example.com" with -subject "Subject" and content "Message". - -The return of ``deliver()`` is a :php:class:`Cake\\Email\\Email` instance with all -configurations set. If you do not want to send the email right away, and wish -to configure a few things before sending, you can pass the 5th parameter as -false. - -The 3rd parameter is the content of message or an array with variables (when -using rendered content). - -The 4th parameter can be an array with the configurations or a string with the -name of configuration in ``Configure``. - -If you want, you can pass the to, subject and message as null and do all -configurations in the 4th parameter (as array or using ``Configure``). -Check the list of :ref:`configurations ` to see all accepted configs. - - -Sending Emails from CLI -======================== - -When sending emails within a CLI script (Shells, Tasks, ...) you should manually -set the domain name for CakeEmail to use. It will serve as the host name for the -message id (since there is no host name in a CLI environment):: - - $Email->domain('www.example.org'); - // Results in message ids like ```` (valid) - // Instead of ``` (invalid) - -A valid message id can help to prevent emails ending up in spam folders. - -.. meta:: - :title lang=en: Email - :keywords lang=en: sending mail,email sender,envelope sender,php class,database configuration,sending emails,meth,shells,smtp,transports,attributes,array,config,flexibility,php email,new email,sending email,models diff --git a/es/core-utility-libraries/file-folder.rst b/es/core-utility-libraries/file-folder.rst deleted file mode 100644 index ff3ca89d84ad52a5cc9581ba05e9d8d51ec831a1..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/file-folder.rst +++ /dev/null @@ -1,452 +0,0 @@ -Folder & File -############# - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -The Folder and File utilities are convenience classes to help you read from and -write/append to files; list files within a folder and other common directory -related tasks. - -Basic Usage -=========== - -Ensure the classes are loaded:: - - use Cake\Utility\Folder; - use Cake\Utility\File; - -Then we can setup a new folder instance:: - - $dir = new Folder('/path/to/folder'); - -and search for all *.ctp* files within that folder using regex:: - - $files = $dir->find('.*\.ctp'); - -Now we can loop through the files and read from or write/append to the contents or -simply delete the file:: - - foreach ($files as $file) { - $file = new File($dir->pwd() . DS . $file); - $contents = $file->read(); - // $file->write('I am overwriting the contents of this file'); - // $file->append('I am adding to the bottom of this file.'); - // $file->delete(); // I am deleting this file - $file->close(); // Be sure to close the file when you're done - } - -Folder API -========== - -.. php:class:: Folder(string $path = false, boolean $create = false, string|boolean $mode = false) - -:: - - // Create a new folder with 0755 permissions - $dir = new Folder('/path/to/folder', true, 0755); - -.. php:attr:: path - - Path of the current folder. :php:meth:`Folder::pwd()` will return the same - information. - -.. php:attr:: sort - - Whether or not the list results should be sorted by name. - -.. php:attr:: mode - - Mode to be used when creating folders. Defaults to ``0755``. Does nothing on - windows machines. - -.. php:staticmethod:: addPathElement(string $path, string $element) - - Returns $path with $element added, with correct slash in-between:: - - $path = Folder::addPathElement('/a/path/for', 'testing'); - // $path equals /a/path/for/testing - - $element can also be an array:: - - $path = Folder::addPathElement('/a/path/for', array('testing', 'another')); - // $path equals /a/path/for/testing/another - -.. php:method:: cd( $path ) - - Change directory to $path. Returns false on failure:: - - $folder = new Folder('/foo'); - echo $folder->path; // Prints /foo - $folder->cd('/bar'); - echo $folder->path; // Prints /bar - $false = $folder->cd('/non-existent-folder'); - -.. php:method:: chmod(string $path, integer $mode = false, boolean $recursive = true, array $exceptions = array()) - - Change the mode on a directory structure recursively. This includes - changing the mode on files as well:: - - $dir = new Folder(); - $dir->chmod('/path/to/folder', 0755, true, array('skip_me.php')); - -.. php:method:: copy(array|string $options = array()) - - Recursively copy a directory. The only parameter $options can either - be a path into copy to or an array of options:: - - $folder1 = new Folder('/path/to/folder1'); - $folder1->copy('/path/to/folder2'); - // Will put folder1 and all its contents into folder2 - - $folder = new Folder('/path/to/folder'); - $folder->copy(array( - 'to' => '/path/to/new/folder', - 'from' => '/path/to/copy/from', // Will cause a cd() to occur - 'mode' => 0755, - 'skip' => array('skip-me.php', '.git'), - 'scheme' => Folder::SKIP // Skip directories/files that already exist. - )); - - There are 3 supported schemes: - - * ``Folder::SKIP`` skip copying/moving files & directories that exist in the - destination directory. - * ``Folder::MERGE`` merge the source/destination directories. Files in the - source directory will replace files in the target directory. Directory - contents will be merged. - * ``Folder::OVERWRITE`` overwrite existing files & directories in the target - directory with those in the source directory. If both the target and - destination contain the same subdirectory, the target directory's contents - will be removed and replaced with the source's. - - -.. php:staticmethod:: correctSlashFor(string $path) - - Returns a correct set of slashes for given $path ('\\' for - Windows paths and '/' for other paths). - -.. php:method:: create(string $pathname, integer $mode = false) - - Create a directory structure recursively. Can be used to create - deep path structures like `/foo/bar/baz/shoe/horn`:: - - $folder = new Folder(); - if ($folder->create('foo' . DS . 'bar' . DS . 'baz' . DS . 'shoe' . DS . 'horn')) { - // Successfully created the nested folders - } - -.. php:method:: delete(string $path = null) - - Recursively remove directories if the system allows:: - - $folder = new Folder('foo'); - if ($folder->delete()) { - // Successfully deleted foo and its nested folders - } - -.. php:method:: dirsize() - - Returns the size in bytes of this Folder and its contents. - -.. php:method:: errors() - - Get the error from latest method. - -.. php:method:: find(string $regexpPattern = '.*', boolean $sort = false) - - Returns an array of all matching files in the current directory:: - - // Find all .png in your webroot/img/ folder and sort the results - $dir = new Folder(WWW_ROOT . 'img'); - $files = $dir->find('.*\.png', true); - /* - Array - ( - [0] => cake.icon.png - [1] => test-error-icon.png - [2] => test-fail-icon.png - [3] => test-pass-icon.png - [4] => test-skip-icon.png - ) - */ - -.. note:: - - The folder find and findRecursive methods will only find files. If you - would like to get folders and files see :php:meth:`Folder::read()` or - :php:meth:`Folder::tree()` - -.. php:method:: findRecursive(string $pattern = '.*', boolean $sort = false) - - Returns an array of all matching files in and below the current directory:: - - // Recursively find files beginning with test or index - $dir = new Folder(WWW_ROOT); - $files = $dir->findRecursive('(test|index).*'); - /* - Array - ( - [0] => /var/www/cake/webroot/index.php - [1] => /var/www/cake/webroot/test.php - [2] => /var/www/cake/webroot/img/test-skip-icon.png - [3] => /var/www/cake/webroot/img/test-fail-icon.png - [4] => /var/www/cake/webroot/img/test-error-icon.png - [5] => /var/www/cake/webroot/img/test-pass-icon.png - ) - */ - -.. php:method:: inCakePath(string $path = '') - - Returns true if the file is in a given CakePath. - -.. php:method:: inPath(string $path = '', boolean $reverse = false) - - Returns true if the file is in the given path:: - - $Folder = new Folder(WWW_ROOT); - $result = $Folder->inPath(APP); - // $result = true, /var/www/example/app/ is in /var/www/example/app/webroot/ - - $result = $Folder->inPath(WWW_ROOT . 'img' . DS, true); - // $result = true, /var/www/example/app/webroot/ is in /var/www/example/app/webroot/img/ - -.. php:staticmethod:: isAbsolute(string $path) - - Returns true if the given $path is an absolute path. - -.. php:staticmethod:: isSlashTerm(string $path) - - Returns true if given $path ends in a slash (i.e. is slash-terminated):: - - $result = Folder::isSlashTerm('/my/test/path'); - // $result = false - $result = Folder::isSlashTerm('/my/test/path/'); - // $result = true - -.. php:staticmethod:: isWindowsPath(string $path) - - Returns true if the given $path is a Windows path. - -.. php:method:: messages() - - Get the messages from the latest method. - -.. php:method:: move(array $options) - - Recursive directory move. - -.. php:staticmethod:: normalizePath(string $path) - - Returns a correct set of slashes for given $path ('\\' for - Windows paths and '/' for other paths). - -.. php:method:: pwd() - - Return current path. - -.. php:method:: read(boolean $sort = true, array|boolean $exceptions = false, boolean $fullPath = false) - - Returns an array of the contents of the current directory. The - returned array holds two sub arrays: One of directories and one of files:: - - $dir = new Folder(WWW_ROOT); - $files = $dir->read(true, array('files', 'index.php')); - /* - Array - ( - [0] => Array // Folders - ( - [0] => css - [1] => img - [2] => js - ) - [1] => Array // Files - ( - [0] => .htaccess - [1] => favicon.ico - [2] => test.php - ) - ) - */ - -.. php:method:: realpath(string $path) - - Get the real path (taking ".." and such into account). - -.. php:staticmethod:: slashTerm(string $path) - - Returns $path with added terminating slash (corrected for - Windows or other OS). - -.. php:method:: tree(null|string $path = null, array|boolean $exceptions = true, null|string $type = null) - - Returns an array of nested directories and files in each directory. - -File API -======== - -.. php:class:: File(string $path, boolean $create = false, integer $mode = 755) - -:: - - // Create a new file with 0644 permissions - $file = new File('/path/to/file.php', true, 0644); - -.. php:attr:: Folder - - The Folder object of the file. - -.. php:attr:: name - - The name of the file with the extension. Differs from - :php:meth:`File::name()` which returns the name without the extension. - -.. php:attr:: info - - An array of file info. Use :php:meth:`File::info()` instead. - -.. php:attr:: handle - - Holds the file handler resource if the file is opened. - -.. php:attr:: lock - - Enable locking for file reading and writing. - -.. php:attr:: path - - The current file's absolute path. - -.. php:method:: append(string $data, boolean $force = false) - - Append the given data string to the current file. - -.. php:method:: close() - - Closes the current file if it is opened. - -.. php:method:: copy(string $dest, boolean $overwrite = true) - - Copy the file to $dest. - -.. php:method:: create() - - Creates the file. - -.. php:method:: delete() - - Deletes the file. - -.. php:method:: executable() - - Returns true if the file is executable. - -.. php:method:: exists() - - Returns true if the file exists. - -.. php:method:: ext() - - Returns the file extension. - -.. php:method:: Folder() - - Returns the current folder. - -.. php:method:: group() - - Returns the file's group, or false in case of an error. - -.. php:method:: info() - - Returns the file info. - -.. php:method:: lastAccess( ) - - Returns last access time. - -.. php:method:: lastChange() - - Returns last modified time, or false in case of an error. - -.. php:method:: md5(integer|boolean $maxsize = 5) - - Get the MD5 Checksum of file with previous check of filesize, - or false in case of an error. - -.. php:method:: name() - - Returns the file name without extension. - -.. php:method:: offset(integer|boolean $offset = false, integer $seek = 0) - - Sets or gets the offset for the currently opened file. - -.. php:method:: open(string $mode = 'r', boolean $force = false) - - Opens the current file with the given $mode. - -.. php:method:: owner() - - Returns the file's owner. - -.. php:method:: perms() - - Returns the "chmod" (permissions) of the file. - -.. php:staticmethod:: prepare(string $data, boolean $forceWindows = false) - - Prepares a ascii string for writing. Converts line endings to the - correct terminator for the current platform. For Windows "\r\n" - will be used, "\n" for all other platforms. - -.. php:method:: pwd() - - Returns the full path of the file. - -.. php:method:: read(string $bytes = false, string $mode = 'rb', boolean $force = false) - - Return the contents of the current file as a string or return false on failure. - -.. php:method:: readable() - - Returns true if the file is readable. - -.. php:method:: safe(string $name = null, string $ext = null) - - Makes filename safe for saving. - -.. php:method:: size() - - Returns the filesize. - -.. php:method:: writable() - - Returns true if the file is writable. - -.. php:method:: write(string $data, string $mode = 'w', boolean$force = false) - - Write given data to the current file. - - -.. php:method:: mime() - - Get the file's mimetype, returns false on failure. - - -.. php:method:: replaceText( $search, $replace ) - - Replaces text in a file. Returns false on failure and true on success. - - -.. todo:: - - Better explain how to use each method with both classes. - -.. meta:: - :title lang=en: Folder & File - :description lang=en: The Folder and File utilities are convenience classes to help you read, write, and append to files; list files within a folder and other common directory related tasks. - :keywords lang=en: file,folder,cakephp utility,read file,write file,append file,recursively copy,copy options,folder path,class folder,file php,php files,change directory,file utilities,new folder,directory structure,delete file diff --git a/es/core-utility-libraries/hash.rst b/es/core-utility-libraries/hash.rst deleted file mode 100644 index e187f2ee56921e1469c55ab49223d1c642e6314b..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/hash.rst +++ /dev/null @@ -1,815 +0,0 @@ -Hash -#### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:class:: Hash - -Array management, if done right, can be a very powerful and useful -tool for building smarter, more optimized code. CakePHP offers a -very useful set of static utilities in the Hash class that allow you -to do just that. - -CakePHP's Hash class can be called from any model or controller in -the same way Inflector is called. Example: :php:meth:`Hash::combine()`. - -.. _hash-path-syntax: - -Hash Path Syntax -================ - -The path syntax described below is used by all the methods in ``Hash``. Not all -parts of the path syntax are available in all methods. A path expression is -made of any number of tokens. Tokens are composed of two groups. Expressions, -are used to traverse the array data, while matchers are used to qualify -elements. You apply matchers to expression elements. - -Expression Types ----------------- - -+--------------------------------+--------------------------------------------+ -| Expression | Definition | -+================================+============================================+ -| ``{n}`` | Represents a numeric key. Will match | -| | any string or numeric key. | -+--------------------------------+--------------------------------------------+ -| ``{s}`` | Represents a string. Will match any | -| | string value including numeric string | -| | values. | -+--------------------------------+--------------------------------------------+ -| ``Foo`` | Matches keys with the exact same value. | -+--------------------------------+--------------------------------------------+ - -All expression elements are supported by all methods. In addition to expression -elements, you can use attribute matching with certain methods. They are ``extract()``, -``combine()``, ``format()``, ``check()``, ``map()``, ``reduce()``, -``apply()``, ``sort()``, ``insert()``, ``remove()`` and ``nest()``. - -Attribute Matching Types ------------------------- - -+--------------------------------+--------------------------------------------+ -| Matcher | Definition | -+================================+============================================+ -| ``[id]`` | Match elements with a given array key. | -+--------------------------------+--------------------------------------------+ -| ``[id=2]`` | Match elements with id equal to 2. | -+--------------------------------+--------------------------------------------+ -| ``[id!=2]`` | Match elements with id not equal to 2. | -+--------------------------------+--------------------------------------------+ -| ``[id>2]`` | Match elements with id greater than 2. | -+--------------------------------+--------------------------------------------+ -| ``[id>=2]`` | Match elements with id greater than | -| | or equal to 2. | -+--------------------------------+--------------------------------------------+ -| ``[id<2]`` | Match elements with id less than 2 | -+--------------------------------+--------------------------------------------+ -| ``[id<=2]`` | Match elements with id less than | -| | or equal to 2. | -+--------------------------------+--------------------------------------------+ -| ``[text=/.../]`` | Match elements that have values matching | -| | the regular expression inside ``...``. | -+--------------------------------+--------------------------------------------+ - -.. php:staticmethod:: get(array $data, $path) - - ``get()`` is a simplified version of ``extract()``, it only supports direct - path expressions. Paths with ``{n}``, ``{s}`` or matchers are not - supported. Use ``get()`` when you want exactly one value out of an array. - -.. php:staticmethod:: extract(array $data, $path) - - ``Hash::extract()`` supports all expression, and matcher components of - :ref:`hash-path-syntax`. You can use extract to retrieve data from arrays, - along arbitrary paths quickly without having to loop through the data - structures. Instead you use path expressions to qualify which elements you - want returned :: - - // Common Usage: - $users = $this->User->find("all"); - $results = Hash::extract($users, '{n}.User.id'); - // $results equals: - // [1,2,3,4,5,...]; - -.. php:staticmethod:: Hash::insert(array $data, $path, $values = null) - - Inserts $data into an array as defined by ``$path``:: - - $a = [ - 'pages' => ['name' => 'page'] - ]; - $result = Hash::insert($a, 'files', ['name' => 'files']); - // $result now looks like: - [ - [pages] => [ - [name] => page - ] - [files] => [ - [name] => files - ] - ] - - You can use paths using ``{n}`` and ``{s}`` to insert data into multiple - points:: - - $users = $this->User->find('all'); - $users = Hash::insert($users, '{n}.User.new', 'value'); - -.. php:staticmethod:: remove(array $data, $path = null) - - Removes all elements from an array that match $path. :: - - $a = [ - 'pages' => ['name' => 'page'], - 'files' => ['name' => 'files'] - ]; - $result = Hash::remove($a, 'files'); - /* $result now looks like: - [ - [pages] => [ - [name] => page - ] - - ] - */ - - Using ``{n}`` and ``{s}`` will allow you to remove multiple values at once. - - -.. php:staticmethod:: combine(array $data, $keyPath = null, $valuePath = null, $groupPath = null) - - Creates an associative array using a $keyPath as the path to build its keys, - and optionally $valuePath as path to get the values. If $valuePath is not - specified, or doesn't match anything, values will be initialized to null. - You can optionally group the values by what is obtained when following the - path specified in $groupPath. :: - - $a = [ - [ - 'User' => [ - 'id' => 2, - 'group_id' => 1, - 'Data' => [ - 'user' => 'mariano.iglesias', - 'name' => 'Mariano Iglesias' - ] - ] - ], - [ - 'User' => [ - 'id' => 14, - 'group_id' => 2, - 'Data' => [ - 'user' => 'phpnut', - 'name' => 'Larry E. Masters' - ] - ] - ], - ]; - - $result = Hash::combine($a, '{n}.User.id'); - /* $result now looks like: - [ - [2] => - [14] => - ] - */ - - $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data'); - /* $result now looks like: - [ - [2] => [ - [user] => mariano.iglesias - [name] => Mariano Iglesias - ] - [14] => [ - [user] => phpnut - [name] => Larry E. Masters - ] - ] - */ - - $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name'); - /* $result now looks like: - [ - [2] => Mariano Iglesias - [14] => Larry E. Masters - ] - */ - - $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id'); - /* $result now looks like: - [ - [1] => [ - [2] => [ - [user] => mariano.iglesias - [name] => Mariano Iglesias - ] - ] - [2] => [ - [14] => [ - [user] => phpnut - [name] => Larry E. Masters - ] - ] - ] - */ - - $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id'); - /* $result now looks like: - [ - [1] => [ - [2] => Mariano Iglesias - ] - [2] => [ - [14] => Larry E. Masters - ] - ] - */ - - You can provide array's for both $keyPath and $valuePath. If you do this, - the first value will be used as a format string, for values extracted by the - other paths:: - - $result = Hash::combine( - $a, - '{n}.User.id', - ['%s: %s', '{n}.User.Data.user', '{n}.User.Data.name'], - '{n}.User.group_id' - ); - /* $result now looks like: - [ - [1] => [ - [2] => mariano.iglesias: Mariano Iglesias - ] - [2] => [ - [14] => phpnut: Larry E. Masters - ] - ] - */ - - $result = Hash::combine( - $a, - ['%s: %s', '{n}.User.Data.user', '{n}.User.Data.name'], - '{n}.User.id' - ); - /* $result now looks like: - [ - [mariano.iglesias: Mariano Iglesias] => 2 - [phpnut: Larry E. Masters] => 14 - ] - */ - -.. php:staticmethod:: format(array $data, array $paths, $format) - - Returns a series of values extracted from an array, formatted with a - format string:: - - $data = [ - [ - 'Person' => [ - 'first_name' => 'Nate', - 'last_name' => 'Abele', - 'city' => 'Boston', - 'state' => 'MA', - 'something' => '42' - ] - ], - [ - 'Person' => [ - 'first_name' => 'Larry', - 'last_name' => 'Masters', - 'city' => 'Boondock', - 'state' => 'TN', - 'something' => '{0}' - ] - ], - [ - 'Person' => [ - 'first_name' => 'Garrett', - 'last_name' => 'Woodworth', - 'city' => 'Venice Beach', - 'state' => 'CA', - 'something' => '{1}' - ] - ] - ]; - - $res = Hash::format($data, ['{n}.Person.first_name', '{n}.Person.something'], '%2$d, %1$s'); - /* - [ - [0] => 42, Nate - [1] => 0, Larry - [2] => 0, Garrett - ] - */ - - $res = Hash::format($data, ['{n}.Person.first_name', '{n}.Person.something'], '%1$s, %2$d'); - /* - [ - [0] => Nate, 42 - [1] => Larry, 0 - [2] => Garrett, 0 - ] - */ - -.. php:staticmethod:: contains(array $data, array $needle) - - Determines if one Hash or array contains the exact keys and values - of another:: - - $a = [ - 0 => ['name' => 'main'], - 1 => ['name' => 'about'] - ]; - $b = [ - 0 => ['name' => 'main'], - 1 => ['name' => 'about'], - 2 => ['name' => 'contact'], - 'a' => 'b' - ]; - - $result = Hash::contains($a, $a); - // true - $result = Hash::contains($a, $b); - // false - $result = Hash::contains($b, $a); - // true - -.. php:staticmethod:: check(array $data, string $path = null) - - Checks if a particular path is set in an array:: - - $set = [ - 'My Index 1' => ['First' => 'The first item'] - ]; - $result = Hash::check($set, 'My Index 1.First'); - // $result == True - - $result = Hash::check($set, 'My Index 1'); - // $result == True - - $set = [ - 'My Index 1' => [ - 'First' => [ - 'Second' => [ - 'Third' => [ - 'Fourth' => 'Heavy. Nesting.' - ] - ] - ] - ] - ]; - $result = Hash::check($set, 'My Index 1.First.Second'); - // $result == True - - $result = Hash::check($set, 'My Index 1.First.Second.Third'); - // $result == True - - $result = Hash::check($set, 'My Index 1.First.Second.Third.Fourth'); - // $result == True - - $result = Hash::check($set, 'My Index 1.First.Seconds.Third.Fourth'); - // $result == False - -.. php:staticmethod:: filter(array $data, $callback = ['Hash', 'filter']) - - Filters empty elements out of array, excluding '0'. You can also supply a - custom $callback to filter the array elements. You callback should return - ``false`` to remove elements from the resulting array:: - - $data = [ - '0', - false, - true, - 0, - ['one thing', 'I can tell you', 'is you got to be', false] - ]; - $res = Hash::filter($data); - - /* $data now looks like: - [ - [0] => 0 - [2] => true - [3] => 0 - [4] => [ - [0] => one thing - [1] => I can tell you - [2] => is you got to be - ] - ] - */ - -.. php:staticmethod:: flatten(array $data, string $separator = '.') - - Collapses a multi-dimensional array into a single dimension:: - - $arr = [ - [ - 'Post' => ['id' => '1', 'title' => 'First Post'], - 'Author' => ['id' => '1', 'user' => 'Kyle'], - ], - [ - 'Post' => ['id' => '2', 'title' => 'Second Post'], - 'Author' => ['id' => '3', 'user' => 'Crystal'], - ], - ]; - $res = Hash::flatten($arr); - /* $res now looks like: - [ - [0.Post.id] => 1 - [0.Post.title] => First Post - [0.Author.id] => 1 - [0.Author.user] => Kyle - [1.Post.id] => 2 - [1.Post.title] => Second Post - [1.Author.id] => 3 - [1.Author.user] => Crystal - ] - */ - -.. php:staticmethod:: expand(array $data, string $separator = '.') - - Expands an array that was previously flattened with - :php:meth:`Hash::flatten()`:: - - $data = [ - '0.Post.id' => 1, - '0.Post.title' => First Post, - '0.Author.id' => 1, - '0.Author.user' => Kyle, - '1.Post.id' => 2, - '1.Post.title' => Second Post, - '1.Author.id' => 3, - '1.Author.user' => Crystal, - ]; - $res = Hash::expand($data); - /* $res now looks like: - [ - [ - 'Post' => ['id' => '1', 'title' => 'First Post'], - 'Author' => ['id' => '1', 'user' => 'Kyle'], - ], - [ - 'Post' => ['id' => '2', 'title' => 'Second Post'], - 'Author' => ['id' => '3', 'user' => 'Crystal'], - ], - ]; - */ - -.. php:staticmethod:: merge(array $data, array $merge[, array $n]) - - This function can be thought of as a hybrid between PHP's - ``array_merge`` and ``array_merge_recursive``. The difference to the two - is that if an array key contains another array then the function - behaves recursive (unlike ``array_merge``) but does not do if for keys - containing strings (unlike ``array_merge_recursive``). - - .. note:: - - This function will work with an unlimited amount of arguments and - typecasts non-array parameters into arrays. - - :: - - $array = [ - [ - 'id' => '48c2570e-dfa8-4c32-a35e-0d71cbdd56cb', - 'name' => 'mysql raleigh-workshop-08 < 2008-09-05.sql ', - 'description' => 'Importing an sql dump' - ], - [ - 'id' => '48c257a8-cf7c-4af2-ac2f-114ecbdd56cb', - 'name' => 'pbpaste | grep -i Unpaid | pbcopy', - 'description' => 'Remove all lines that say "Unpaid".', - ] - ]; - $arrayB = 4; - $arrayC = [0 => "test array", "cats" => "dogs", "people" => 1267]; - $arrayD = ["cats" => "felines", "dog" => "angry"]; - $res = Hash::merge($array, $arrayB, $arrayC, $arrayD); - - /* $res now looks like: - [ - [0] => [ - [id] => 48c2570e-dfa8-4c32-a35e-0d71cbdd56cb - [name] => mysql raleigh-workshop-08 < 2008-09-05.sql - [description] => Importing an sql dump - ] - [1] => [ - [id] => 48c257a8-cf7c-4af2-ac2f-114ecbdd56cb - [name] => pbpaste | grep -i Unpaid | pbcopy - [description] => Remove all lines that say "Unpaid". - ] - [2] => 4 - [3] => test array - [cats] => felines - [people] => 1267 - [dog] => angry - ] - */ - -.. php:staticmethod:: numeric(array $data) - - Checks to see if all the values in the array are numeric:: - - $data = ['one']; - $res = Hash::numeric(array_keys($data)); - // $res is true - - $data = [1 => 'one']; - $res = Hash::numeric($data); - // $res is false - -.. php:staticmethod:: dimensions (array $data) - - Counts the dimensions of an array. This method will only - consider the dimension of the first element in the array:: - - $data = ['one', '2', 'three']; - $result = Hash::dimensions($data); - // $result == 1 - - $data = ['1' => '1.1', '2', '3']; - $result = Hash::dimensions($data); - // $result == 1 - - $data = ['1' => ['1.1' => '1.1.1'], '2', '3' => ['3.1' => '3.1.1']]; - $result = Hash::dimensions($data); - // $result == 2 - - $data = ['1' => '1.1', '2', '3' => ['3.1' => '3.1.1']]; - $result = Hash::dimensions($data); - // $result == 1 - - $data = ['1' => ['1.1' => '1.1.1'], '2', '3' => ['3.1' => ['3.1.1' => '3.1.1.1']]]; - $result = Hash::dimensions($data); - // $result == 2 - -.. php:staticmethod:: maxDimensions(array $data) - - Similar to :php:meth:`~Hash::dimensions()`, however this method returns, - the deepest number of dimensions of any element in the array:: - - $data = ['1' => '1.1', '2', '3' => ['3.1' => '3.1.1']]; - $result = Hash::maxDimensions($data, true); - // $result == 2 - - $data = ['1' => ['1.1' => '1.1.1'], '2', '3' => ['3.1' => ['3.1.1' => '3.1.1.1']]]; - $result = Hash::maxDimensions($data, true); - // $result == 3 - -.. php:staticmethod:: map(array $data, $path, $function) - - Creates a new array, by extracting $path, and mapping $function - across the results. You can use both expression and matching elements with - this method:: - - // Call the noop function $this->noop() on every element of $data - $result = Hash::map($data, "{n}", array($this, 'noop')); - - function noop($array) - { - // Do stuff to array and return the result - return $array; - } - -.. php:staticmethod:: reduce(array $data, $path, $function) - - Creates a single value, by extracting $path, and reducing the extracted - results with $function. You can use both expression and matching elements - with this method. - -.. php:staticmethod:: apply(array $data, $path, $function) - - Apply a callback to a set of extracted values using $function. The function - will get the extracted values as the first argument. - -.. php:staticmethod:: sort(array $data, $path, $dir, $type = 'regular') - - Sorts an array by any value, determined by a :ref:`hash-path-syntax` - Only expression elements are supported by this method:: - - $a = [ - 0 => ['Person' => ['name' => 'Jeff']], - 1 => ['Shirt' => ['color' => 'black']] - ]; - $result = Hash::sort($a, '{n}.Person.name', 'asc'); - /* $result now looks like: - [ - [0] => [ - [Shirt] => [ - [color] => black - ] - ] - [1] => [ - [Person] => [ - [name] => Jeff - ] - ] - ] - */ - - ``$dir`` can be either ``asc`` or ``desc``. ``$type`` - can be one of the following values: - - * ``regular`` for regular sorting. - * ``numeric`` for sorting values as their numeric equivalents. - * ``string`` for sorting values as their string value. - * ``natural`` for sorting values in a human friendly way. Will - sort ``foo10`` below ``foo2`` as an example. Natural sorting - requires PHP 5.4 or greater. - -.. php:staticmethod:: diff(array $data, array $compare) - - Computes the difference between two arrays:: - - $a = [ - 0 => ['name' => 'main'], - 1 => ['name' => 'about'] - ]; - $b = [ - 0 => ['name' => 'main'], - 1 => ['name' => 'about'], - 2 => ['name' => 'contact'] - ]; - - $result = Hash::diff($a, $b); - /* $result now looks like: - [ - [2] => [ - [name] => contact - ] - ] - */ - -.. php:staticmethod:: mergeDiff(array $data, array $compare) - - This function merges two arrays and pushes the differences in - data to the bottom of the resultant array. - - **Example 1** - :: - - $array1 = ['ModelOne' => ['id' => 1001, 'field_one' => 'a1.m1.f1', 'field_two' => 'a1.m1.f2']]; - $array2 = ['ModelOne' => ['id' => 1003, 'field_one' => 'a3.m1.f1', 'field_two' => 'a3.m1.f2', 'field_three' => 'a3.m1.f3']]; - $res = Hash::mergeDiff($array1, $array2); - - /* $res now looks like: - [ - [ModelOne] => [ - [id] => 1001 - [field_one] => a1.m1.f1 - [field_two] => a1.m1.f2 - [field_three] => a3.m1.f3 - ] - ] - */ - - **Example 2** - :: - - $array1 = ["a" => "b", 1 => 20938, "c" => "string"]; - $array2 = ["b" => "b", 3 => 238, "c" => "string", ["extra_field"]]; - $res = Hash::mergeDiff($array1, $array2); - /* $res now looks like: - [ - [a] => b - [1] => 20938 - [c] => string - [b] => b - [3] => 238 - [4] => [ - [0] => extra_field - ] - ] - */ - -.. php:staticmethod:: normalize(array $data, $assoc = true) - - Normalizes an array. If ``$assoc`` is true, the resulting array will be - normalized to be an associative array. Numeric keys with values, will be - converted to string keys with null values. Normalizing an array, makes using - the results with :php:meth:`Hash::merge()` easier:: - - $a = ['Tree', 'CounterCache', - 'Upload' => [ - 'folder' => 'products', - 'fields' => ['image_1_id', 'image_2_id'] - ] - ]; - $result = Hash::normalize($a); - /* $result now looks like: - [ - [Tree] => null - [CounterCache] => null - [Upload] => [ - [folder] => products - [fields] => [ - [0] => image_1_id - [1] => image_2_id - ] - ] - ] - */ - - $b = [ - 'Cacheable' => ['enabled' => false], - 'Limit', - 'Bindable', - 'Validator', - 'Transactional' - ]; - $result = Hash::normalize($b); - /* $result now looks like: - [ - [Cacheable] => [ - [enabled] => false - ] - - [Limit] => null - [Bindable] => null - [Validator] => null - [Transactional] => null - ] - */ - -.. php:staticmethod:: nest(array $data, array $options = []) - - Takes a flat array set, and creates a nested, or threaded data structure. - Used by methods like ``Table::find('threaded')``. - - **Options:** - - - ``children`` The key name to use in the result set for children. Defaults - to 'children'. - - ``idPath`` The path to a key that identifies each entry. Should be - compatible with :php:meth:`Hash::extract()`. Defaults to ``{n}.$alias.id`` - - ``parentPath`` The path to a key that identifies the parent of each entry. - Should be compatible with :php:meth:`Hash::extract()`. Defaults to ``{n}.$alias.parent_id`` - - ``root`` The id of the desired top-most result. - - Example:: - - $data = [ - ['ModelName' => ['id' => 1, 'parent_id' => null]], - ['ModelName' => ['id' => 2, 'parent_id' => 1]], - ['ModelName' => ['id' => 3, 'parent_id' => 1]], - ['ModelName' => ['id' => 4, 'parent_id' => 1]], - ['ModelName' => ['id' => 5, 'parent_id' => 1]], - ['ModelName' => ['id' => 6, 'parent_id' => null]], - ['ModelName' => ['id' => 7, 'parent_id' => 6]], - ['ModelName' => ['id' => 8, 'parent_id' => 6]], - ['ModelName' => ['id' => 9, 'parent_id' => 6]], - ['ModelName' => ['id' => 10, 'parent_id' => 6]] - ]; - - $result = Hash::nest($data, ['root' => 6]); - /* $result now looks like: - [ - (int) 0 => [ - 'ModelName' => [ - 'id' => (int) 6, - 'parent_id' => null - ], - 'children' => [ - (int) 0 => [ - 'ModelName' => [ - 'id' => (int) 7, - 'parent_id' => (int) 6 - ], - 'children' => [] - ], - (int) 1 => [ - 'ModelName' => [ - 'id' => (int) 8, - 'parent_id' => (int) 6 - ], - 'children' => [] - ], - (int) 2 => [ - 'ModelName' => [ - 'id' => (int) 9, - 'parent_id' => (int) 6 - ], - 'children' => [] - ], - (int) 3 => [ - 'ModelName' => [ - 'id' => (int) 10, - 'parent_id' => (int) 6 - ], - 'children' => [] - ] - ] - ] - ] - */ - - -.. meta:: - :title lang=en: Hash - :keywords lang=en: array array,path array,array name,numeric key,regular expression,result set,person name,brackets,syntax,cakephp,elements,php,set path diff --git a/es/core-utility-libraries/httpclient.rst b/es/core-utility-libraries/httpclient.rst deleted file mode 100644 index c21ebcad22ed0fef10c644b28b4374d505d5861a..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/httpclient.rst +++ /dev/null @@ -1,371 +0,0 @@ -Http Client -########### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Network\Http - -.. php:class:: Client(mixed $config = []) - -CakePHP includes a basic but powerful HTTP client which can be easily used for -making requests. It is a great way to communicate with webservices, and -remote APIs. - -Doing Requests -============== - -Doing requests is simple and straight forward. Doing a get request looks like:: - - use Cake\Network\Http\Client; - - $http = new Client(); - - // Simple get - $response = $http->get('http://example.com/test.html'); - - // Simple get with querystring - $response = $http->get('http://example.com/search', ['q' => 'widget']); - - // Simple get with querystring & additional headers - $response = $http->get('http://example.com/search', ['q' => 'widget'], [ - 'headers' => ['X-Requested-With' => 'XMLHttpRequest'] - ]); - -Doing post and put requests is equally simple:: - - // Send a POST request with application/x-www-form-urlencoded encoded data - $http = new Client(); - $response = $http->post('http://example.com/posts/add', [ - 'title' => 'testing', - 'body' => 'content in the post' - ]); - - // Send a PUT request with application/x-www-form-urlencoded encoded data - $response = $http->put('http://example.com/posts/add', [ - 'title' => 'testing', - 'body' => 'content in the post' - ]); - - // Other methods as well. - $http->delete(...); - $http->head(...); - $http->patch(...); - -Creating Multipart Requests with Files -====================================== - -You can include files in request bodies by including them in the data array:: - - $http = new Client(); - $response = $http->post('http://example.com/api', [ - 'image' => '@/path/to/a/file', - 'logo' => $fileHandle - ]); - -By prefixing data values with ``@`` or including a filehandle in the data. If -a filehandle is used, the filehandle will be read until its end, it will not be -rewound before being read. - -Sending Request Bodies -====================== - -When dealing with REST API's you often need to send request bodies that are not -form encoded. Http\\Client exposes this through the type option:: - - // Send a JSON request body. - $http = new Client(); - $response = $http->post( - 'http://example.com/tasks', - json_encode($data), - ['type' => 'json'] - ); - -The ``type`` key can either be a one of 'json', 'xml' or a full mime type. -When using the ``type`` option, you should provide the data as a string. If you're -doing a GET request that needs both querystring parameters and a request body -you can do the following:: - - // Send a JSON body in a GET request with query string parameters. - $http = new Client(); - $response = $http->get( - 'http://example.com/tasks', - ['q' => 'test', '_content' => json_encode($data)], - ['type' => 'json'] - ); - -.. _http_client_request_options: - -Request Method Options -======================= - -Each HTTP method takes an ``$options`` parameter which is used to provide -addition request information. The following keys can be used in ``$options``: - -- ``headers`` - Array of additional headers -- ``cookie`` - Array of cookies to use. -- ``proxy`` - Array of proxy information. -- ``auth`` - Array of authentication data, the ``type`` key is used to delegate to - an authentication strategy. By default Basic auth is used. -- ``ssl_verify_peer`` - defaults to true. Set to false to disable SSL certification - verification (not advised) -- ``ssl_verify_depth`` - defaults to 5. Depth to traverse in the CA chain. -- ``ssl_verify_host`` - defaults to true. Validate the SSL certificate against the host name. -- ``ssl_cafile`` - defaults to built in cafile. Overwrite to use custom CA bundles. -- ``timeout`` - Duration to wait before timing out. -- ``type`` - Send a request body in a custom content type. Requires ``$data`` to - either be a string, or the ``_content`` option to be set when doing GET - requests. - -The options parameter is always the 3rd parameter in each of the HTTP methods. -They can also be use when constructing ``Client`` to create -:ref:`scoped clients `. - -Authentication -============== - -Http\\Client supports a few different authentication systems. Different -authentication strategies can be added by developers. Auth strategies are called -before the request is sent, and allow headers to be added to the request -context. - -Using Basic Authentication --------------------------- - -An example of basic authentication:: - - $http = new Client(); - $response = $http->get('http://example.com/profile/1', [], [ - 'auth' => ['username' => 'mark', 'password' => 'secret'] - ]); - -By default Http\\Client will use basic authentication if there is no ``'type'`` -key in the auth option. - - -Using Digest Authentication ---------------------------- - -An example of basic authentication:: - - $http = new Client(); - $response = $http->get('http://example.com/profile/1', [], [ - 'auth' => [ - 'type' => 'digest', - 'username' => 'mark', - 'password' => 'secret', - 'realm' => 'myrealm', - 'nonce' => 'onetimevalue', - 'qop' => 1, - 'opaque' => 'someval' - ] - ]); - -By setting the 'type' key to 'digest', you tell the authentication subsystem to -use digest authentication. - -OAuth 1 Authentication ----------------------- - -Many modern web-services require OAuth authentication to access their API's. -The included OAuth authentication assumes that you already have your consumer -key and consumer secret:: - - $http = new Client(); - $response = $http->get('http://example.com/profile/1', [], [ - 'auth' => [ - 'type' => 'oauth', - 'consumerKey' => 'bigkey', - 'consumerSecret' => 'secret', - 'token' => '...', - 'tokenSecret' => '...', - 'realm' => 'tickets', - ] - ]); - -Proxy Authentication --------------------- - -Some proxies require authentication to use them. Generally this authentication -is Basic, but it can be implemented by any authentication adapter. By default -Http\\Client will assume Basic authentication, unless the type key is set:: - - $http = new Client(); - $response = $http->get('http://example.com/test.php', [], [ - 'proxy' => [ - 'username' => 'mark', - 'password' => 'testing', - 'port' => 12345, - ] - ]); - -.. _http_client_scoped_client: - -Creating Scoped Clients -======================= - -Having to re-type the domain name, authentication and proxy settings can become -tedious & error prone. To reduce the change for mistake and relieve some of the -tedium, you can create scoped clients:: - - // Create a scoped client. - $http = new Client([ - 'host' => 'api.example.com', - 'scheme' => 'https', - 'auth' => ['username' => 'mark', 'password' => 'testing'] - ]); - - // Do a request to api.example.com - $response = $http->get('/test.php'); - -The following information can be used when creating a scoped client: - -* host -* scheme -* proxy -* auth -* port -* cookies -* timeout -* ssl_verify_peer -* ssl_verify_depth -* ssl_verify_host - -Any of these options can be overridden by specifying them when doing requests. -host, scheme, proxy, port are overridden in the request URL:: - - // Using the scoped client we created earlier. - $response = $http->get('http://foo.com/test.php'); - -The above will replace the domain, scheme, and port. However, this request will -continue using all the other options defined when the scoped client was created. -See :ref:`http_client_request_options` for more information on the options -supported. - - -Setting and Managing Cookies -============================ - -Http\\Client can also accept cookies when making requests. In addition to -accepting cookies, it will also automatically store valid cookies set in -responses. Any response with cookies, will have them stored in the originating -instance of Http\\Client. The cookies stored in a Client instance are -automatically included in future requests to domain + path combinations that -match:: - - $http = new Client([ - 'host' => 'cakephp.org' - ]); - - // Do a request that sets some cookies - $response = $http->get('/'); - - // Cookies from the first request will be included - // by default. - $response2 = $http->get('/changelogs'); - -You can always override the auto-included cookies by setting them in the -request's ``$options`` parameters:: - - // Replace a stored cookie with a custom value. - $response = $http->get('/changelogs', [], [ - 'cookies' => ['sessionid' => '123abc'] - ]); - - -Response Objects -================ - -.. php:class:: Response - -Response objects have a number of methods for inspecting the response data. - -.. php:method:: body($parser = null) - - Get the response body. Pass in an optional parser, to decode the response - body. For example. `json_decode` could be used for decoding response data. - -.. php:method:: header($name) - - Get a header with ``$name``. ``$name`` is case-insensitive. - -.. php:method:: headers() - - Get all the headers. - -.. php:method:: isOk() - - Check if the response was ok. Any valid 20x response code will be - treated as OK. - -.. php:method:: isRedirect() - - Check if the response was a redirect. - -.. php:method:: cookies() - - Get the cookies from the response. Cookies will be returned as - an array with all the properties that were defined in the response header. - To access the raw cookie data you can use :php:meth:`header()` - -.. php:method:: cookie($name = null, $all = false) - - Get a single cookie from the response. By default only the value of a cookie - is returned. If you set the second parameter to true, all the properties - set in the response will be returned. - -.. php:method:: statusCode() - - Get the status code. - -.. php:method:: encoding() - - Get the encoding of the response. Will return null if the response - headers did not contain an encoding. - -In addition to the above methods you can also use object accessors to read data -from the following properties: - -* cookies -* headers -* body -* code -* json -* xml - - -:: - - $http = new Client(['host' => 'example.com']); - $response = $http->get('/test'); - - // Use object accessors to read data. - debug($response->body); - debug($response->code); - debug($response->headers); - -Reading JSON and XML Response Bodies ------------------------------------- - -Since JSON and XML responses are commonly used, response objects provide easy to -use accessors to read decoded data. JSON data is decoded into an array, while -XML data is decoded into a ``SimpleXMLElement`` tree:: - - // Get some XML - $http = new Client(); - $response = $http->get('http://example.com/test.xml'); - $xml = $response->xml; - - // Get some JSON - $http = new Client(); - $response = $http->get('http://example.com/test.json'); - $json = $response->json; - -The decoded response data is stored in the response object, so accessing it -multiple times has no additional cost. - -.. meta:: - :title lang=en: HttpClient - :keywords lang=en: array name,array data,query parameter,query string,php class,string query,test type,string data,google,query results,webservices,apis,parameters,cakephp,meth,search results diff --git a/es/core-utility-libraries/inflector.rst b/es/core-utility-libraries/inflector.rst deleted file mode 100644 index 3e069dd2f69bbb2e387c922d090259f28c468e71..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/inflector.rst +++ /dev/null @@ -1,150 +0,0 @@ -Inflector -######### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Utility - -.. php:class:: Inflector - -The Inflector class takes a string and can manipulate it to handle -word variations such as pluralizations or camelizing and is -normally accessed statically. Example: -``Inflector::pluralize('example')`` returns "examples". - -You can try out the inflections online at `inflector.cakephp.org -`_. - -Creating Plural & Singular Forms -================================ - -.. php:staticmethod:: singularize($singular) -.. php:staticmethod:: pluralize($singular) - -Both ``pluralize`` and ``singularize()`` work on most English nouns. If you need -to support other languages, you can use :ref:`inflection-configuration` to -customize the rules used:: - - // Apples - echo Inflector::pluralize('Apple'); - - // Person - echo Inflector::singularize('People'); - -Creating CamelCase and under_scored Forms -========================================= - -.. php:staticmethod:: camelize($underscored) -.. php:staticmethod:: underscore($camelCase) - -These methods are useful when creating class names, or property names:: - - // ApplePie - Inflector::camelize('Apple_pie') - - // apple_pie - Inflector::undescore('ApplePie'); - -It should be noted that underscore will only convert camelCase -formatted words. Words that contains spaces will be lower-cased, -but will not contain an underscore. - -Creating Human Readable Forms -============================= - -.. php:staticmethod:: humanize($underscored) - -This method is useful when converting underscored forms into "Title Case" forms -for human readable values:: - - // Apple Pie - Inflector::humanize('apple_pie'); - -Creating Table and Class Name Forms -=================================== - -.. php:staticmethod:: tableize($camelCase) -.. php:staticmethod:: classify($underscored) - -When generating code, or using CakePHP's conventions you may need to inflect -table names or class names:: - - // UserProfileSetting - Inflector::classify('user_profile_settings'); - - // user_profile_settings - Inflector::tableize('UserProfileSetting'); - -Creating Variable Names -======================= - -.. php:staticmethod:: variable($underscored) - -Variable names are often useful when doing meta-programming tasks that involve -generating code or doing work based on conventions:: - - // applePie - Inflector::variable('apple_pie'); - -Creating URL Safe Strings -========================= - -.. php:staticmethod:: slug($word, $replacement = '_') - -Slug converts special characters into latin versions and converting -unmatched characters and spaces to underscores. The slug method -expects UTF-8 encoding:: - - // apple\_puree - Inflector::slug('apple purée'); - - -.. _inflection-configuration: - -Inflection Configuration -======================== - -CakePHP's naming conventions can be really nice - you can name your -database table ``big\_boxes``, your model ``BigBoxes``, your controller -``BigBoxesController``, and everything just works together -automatically. The way CakePHP knows how to tie things together is -by *inflecting* the words between their singular and plural forms. - -There are occasions (especially for our non-English speaking -friends) where you may run into situations where CakePHP's -inflector (the class that pluralizes, singularizes, camelCases, and -under\_scores) might not work as you'd like. If CakePHP won't -recognize your Foci or Fish, you can tell CakePHP about your -special cases. - -Loading Custom Inflections --------------------------- - -.. php:staticmethod:: rules($type, $rules, $reset = false) - -Define new inflection and transliteration rules for Inflector to use. Often, -this method is used in your ``config/bootstrap.php``:: - - Inflector::rules('singular', [ - 'rules' => ['/^(bil)er$/i' => '\1', '/^(inflec|contribu)tors$/i' => '\1ta'], - 'uninflected' => ['singulars'], - 'irregular' => ['spins' => 'spinor'] - ]); - -or:: - - Inflector::rules('plural', [ - 'irregular' => ['phylum' => 'phyla'] - ]); - -Will merge the supplied rules into the inflection sets defined in -``Cake/Utility/Inflector``, with the added rules taking precedence -over the core rules. You can use ``Inflector::reset()`` to clear rules and -restore the original Inflector state. - -.. meta:: - :title lang=en: Inflector - :keywords lang=en: apple orange,word variations,apple pie,person man,latin versions,profile settings,php class,initial state,puree,slug,apples,oranges,user profile,underscore diff --git a/es/core-utility-libraries/number.rst b/es/core-utility-libraries/number.rst deleted file mode 100644 index 7774368e614b080f5bdcebd18855143c8ac45c2e..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/number.rst +++ /dev/null @@ -1,320 +0,0 @@ -Number -###### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\I18n - -.. php:class:: Number - -If you need :php:class:`NumberHelper` functionalities outside of a ``View``, -use the ``Number`` class:: - - namespace App\Controller; - - use Cake\I18n\Number; - - class UsersController extends AppController - { - - public $components = array('Auth'); - - public function afterLogin() - { - $storageUsed = $this->Auth->user('storage_used'); - if ($storageUsed > 5000000) { - // Notify users of quota - $this->Flash->success(__('You are using {0} storage', Number::toReadableSize($storageUsed))); - } - } - } - -.. start-cakenumber - -All of these functions return the formatted number; They do not -automatically echo the output into the view. - -Formatting Currency Values -========================== - -.. php:method:: currency(mixed $value, string $currency = null, array $options = []) - -This method is used to display a number in common currency formats -(EUR, GBP, USD). Usage in a view looks like:: - - // Called as NumberHelper - echo $this->Number->currency($value, $currency); - - // Called as Number - echo Number::currency($value, $currency); - -The first parameter, ``$value``, should be a floating point number -that represents the amount of money you are expressing. The second -parameter is a string used to choose a predefined currency formatting -scheme: - -+---------------------+----------------------------------------------------+ -| $currency | 1234.56, formatted by currency type | -+=====================+====================================================+ -| EUR | €1.234,56 | -+---------------------+----------------------------------------------------+ -| GBP | £1,234.56 | -+---------------------+----------------------------------------------------+ -| USD | $1,234.56 | -+---------------------+----------------------------------------------------+ - -The third parameter is an array of options for further defining the -output. The following options are available: - -+---------------------+----------------------------------------------------+ -| Option | Description | -+=====================+====================================================+ -| before | Text to display before the rendered number. | -+---------------------+----------------------------------------------------+ -| after | Text to display before the rendered number. | -+---------------------+----------------------------------------------------+ -| zero | The text to use for zero values, can be a string | -| | or a number. ie. 0, 'Free!'. | -+---------------------+----------------------------------------------------+ -| places | Number of decimal places to use, ie. 2 | -+---------------------+----------------------------------------------------+ -| precision | Maximal number of decimal places to use, ie. 2 | -+---------------------+----------------------------------------------------+ -| locale | The locale name to use for formating number, | -| | ie. "fr_FR". | -+---------------------+----------------------------------------------------+ -| fractionSymbol | String to use for fraction numbers, ie. ' cents'. | -+---------------------+----------------------------------------------------+ -| fractionPosition | Either 'before' or 'after' to place the fraction | -| | symbol. | -+---------------------+----------------------------------------------------+ -| pattern | An ICU number pattern to use for formatting the | -| | number ie. #,###.00 | -+---------------------+----------------------------------------------------+ -| useIntlCode | Set to ``true`` to replace the currency symbol | -| | with the international currency code. | -+---------------------+----------------------------------------------------+ - -If $currency value is ``null``, the default currency will be retrieved form -:php:meth:`Cake\\I18n\\Number::defaultCurrency()` - - -Setting the Default Currency -============================ - -.. php:method:: defaultCurrency($currency) - -Setter/getter for the default currency. This removes the need to always pass the -currency to :php:meth:`Cake\\I18n\\Number::currency()` and change all -currency outputs by setting other default. If ``$currency`` is set to ``false``, -it will clear the currently stored value. By default, it will retrieve the -``intl.default_locale`` if set and 'en_US' if not. - -Formatting Floating Point Numbers -================================= - -.. php:method:: precision(float $value, int $precision = 3) - -This method displays a number with the specified amount of -precision (decimal places). It will round in order to maintain the -level of precision defined. :: - - // Called as NumberHelper - echo $this->Number->precision(456.91873645, 2); - - // Outputs - 456.92 - - // Called as Number - echo Number::precision(456.91873645, 2); - - -Formatting Percentages -====================== - -.. php:method:: toPercentage(mixed $value, int $precision = 2, array $options = []) - -+---------------------+----------------------------------------------------+ -| Option | Description | -+=====================+====================================================+ -| multiply | Boolean to indicate whether the value has to be | -| | multiplied by 100. Useful for decimal percentages. | -+---------------------+----------------------------------------------------+ - -Like :php:meth:`Cake\\I18n\\Number::precision()`, this method formats a number -according to the supplied precision (where numbers are rounded to meet the -given precision). This method also expresses the number as a percentage -and prepends the output with a percent sign. :: - - // Called as NumberHelper. Output: 45.69% - echo $this->Number->toPercentage(45.691873645); - - // Called as Number. Output: 45.69% - echo Number::toPercentage(45.691873645); - - // Called with multiply. Output: 45.7% - echo Number::toPercentage(0.45691, 1, [ - 'multiply' => true - ]); - - -Interacting with Human Readable Values -====================================== - -.. php:method:: toReadableSize(string $size) - -This method formats data sizes in human readable forms. It provides -a shortcut way to convert bytes to KB, MB, GB, and TB. The size is -displayed with a two-digit precision level, according to the size -of data supplied (i.e. higher sizes are expressed in larger -terms):: - - // Called as NumberHelper - echo $this->Number->toReadableSize(0); // 0 Byte - echo $this->Number->toReadableSize(1024); // 1 KB - echo $this->Number->toReadableSize(1321205.76); // 1.26 MB - echo $this->Number->toReadableSize(5368709120); // 5 GB - - // Called as Number - echo Number::toReadableSize(0); // 0 Byte - echo Number::toReadableSize(1024); // 1 KB - echo Number::toReadableSize(1321205.76); // 1.26 MB - echo Number::toReadableSize(5368709120); // 5 GB - -Formatting Numbers -================== - -.. php:method:: format(mixed $value, array $options = []) - -This method gives you much more control over the formatting of -numbers for use in your views (and is used as the main method by -most of the other NumberHelper methods). Using this method might -looks like:: - - // Called as NumberHelper - $this->Number->format($value, $options); - - // Called as Number - Number::format($value, $options); - -The ``$value`` parameter is the number that you are planning on -formatting for output. With no ``$options`` supplied, the number -1236.334 would output as 1,236. Note that the default precision is -zero decimal places. - -The ``$options`` parameter is where the real magic for this method -resides. - -- If you pass an integer then this becomes the amount of precision - or places for the function. -- If you pass an associated array, you can use the following keys: - -+---------------------+----------------------------------------------------+ -| Option | Description | -+=====================+====================================================+ -| places | Number of decimal places to use, ie. 2 | -+---------------------+----------------------------------------------------+ -| precision | Maximal number of decimal places to use, ie. 2 | -+---------------------+----------------------------------------------------+ -| pattern | An ICU number pattern to use for formatting the | -| | number ie. #,###.00 | -+---------------------+----------------------------------------------------+ -| locale | The locale name to use for formating number, | -| | ie. "fr_FR". | -+---------------------+----------------------------------------------------+ -| before | Text to display before the rendered number. | -+---------------------+----------------------------------------------------+ -| after | Text to display before the rendered number. | -+---------------------+----------------------------------------------------+ - -Example:: - - // Called as NumberHelper - echo $this->Number->format('123456.7890', [ - 'places' => 2, - 'before' => '¥ ', - 'after' => ' !' - ]); - // Output '¥ 123,456.79 !' - - echo $this->Number->format('123456.7890', [ - 'locale' => 'fr_FR' - ]); - // Output '123 456,79 !' - - // Called as Number - echo Number::format('123456.7890', [ - 'places' => 2, - 'before' => '¥ ', - 'after' => ' !' - ]); - // Output '¥ 123,456.79 !' - - echo Number::format('123456.7890', [ - 'locale' => 'fr_FR' - ]); - // Output '123 456,79 !' - - -Format Differences -================== - -.. php:method:: formatDelta(mixed $value, array $options = []) - -This method displays differences in value as a signed number:: - - // Called as NumberHelper - $this->Number->formatDelta($value, $options); - - // Called as Number - Number::formatDelta($value, $options); - -The ``$value`` parameter is the number that you are planning on -formatting for output. With no ``$options`` supplied, the number -1236.334 would output as 1,236. Note that the default precision is -zero decimal places. - -The ``$options`` parameter takes the same keys as :php:meth:`Number::format()` itself: - -+---------------------+----------------------------------------------------+ -| Option | Description | -+=====================+====================================================+ -| places | Number of decimal places to use, ie. 2 | -+---------------------+----------------------------------------------------+ -| precision | Maximal number of decimal places to use, ie. 2 | -+---------------------+----------------------------------------------------+ -| locale | The locale name to use for formating number, | -| | ie. "fr_FR". | -+---------------------+----------------------------------------------------+ -| before | Text to display before the rendered number. | -+---------------------+----------------------------------------------------+ -| after | Text to display before the rendered number. | -+---------------------+----------------------------------------------------+ - -Example:: - - // Called as NumberHelper - echo $this->Number->formatDelta('123456.7890', [ - 'places' => 2, - 'before' => '[', - 'after' => ']' - ]); - // Output '[+123,456.79]' - - // Called as Number - echo Number::formatDelta('123456.7890', [ - 'places' => 2, - 'before' => '[', - 'after' => ']' - ]); - // Output '[+123,456.79]' - -.. end-cakenumber - -.. meta:: - :title lang=en: NumberHelper - :description lang=en: The Number Helper contains convenience methods that enable display numbers in common formats in your views. - :keywords lang=en: number helper,currency,number format,number precision,format file size,format numbers diff --git a/es/core-utility-libraries/security.rst b/es/core-utility-libraries/security.rst deleted file mode 100644 index 6046b6f1807fbd9eaadcb5427bd346dd145517e3..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/security.rst +++ /dev/null @@ -1,88 +0,0 @@ -Security -######## - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Utility - -.. php:class:: Security - -The `security library `_ -handles basic security measures such as providing methods for -hashing and encrypting data. - -Encrypting and Decrypting Data -============================== - -.. php:staticmethod:: encrypt($text, $key, $hmacSalt = null) -.. php:staticmethod:: decrypt($cipher, $key, $hmacSalt = null) - -Encrypt ``$text`` using AES-256. The ``$key`` should be a value with a -lots of variance in the data much like a good password. The returned result -will be the encrypted value with an HMAC checksum. - -This method should **never** be used to store passwords. Instead you should use -the one way hashing methods provided by -:php:meth:`~Cake\Utility\Security::hash()`. An example use would be:: - - // Assuming key is stored somewhere it can be re-used for - // decryption later. - $key = 'wt1U5MACWJFTXGenFoZoiLwQGrLgdbHA'; - $result = Security::encrypt($value, $key); - -If you do not supply an HMAC salt, the ``Security.salt`` value will be used. -Encrypted values can be decrypted using -:php:meth:`Cake\\Utility\\Security::decrypt()`. - -Decrypt a previously encrypted value. The ``$key`` and ``$hmacSalt`` -parameters must match the values used to encrypt or decryption will fail. An -example use would be:: - - // Assuming the key is stored somewhere it can be re-used for - // Decryption later. - $key = 'wt1U5MACWJFTXGenFoZoiLwQGrLgdbHA'; - - $cipher = $user->secrets; - $result = Security::decrypt($cipher, $key); - -If the value cannot be decrypted due to changes in the key or HMAC salt -``false`` will be returned. - -Hashing Data -============ - -.. php:staticmethod:: hash( $string, $type = NULL, $salt = false ) - -Create a hash from string using given method. Fallback on next -available method. If ``$salt`` is set to true, the applications salt -value will be used:: - - // Using the application's salt value - $sha1 = Security::hash('CakePHP Framework', 'sha1', true); - - // Using a custom salt value - $sha1 = Security::hash('CakePHP Framework', 'sha1', 'my-salt'); - - // Using the default hash algorithm - $hash = Security::hash('CakePHP Framework'); - -The ``hash`` method supports the following hashing strategies: - -- md5 -- sha1 -- sha256 - -And any other hash algorithmn that PHP's ``hash()`` function supports. - -.. warning:: - - You should not be using ``hash()`` for passwords in new applications. - Instead you should use the ``DefaultPasswordHasher`` class which uses bcrpyt - by default. - -.. meta:: - :title lang=en: Security - :keywords lang=en: security api,secret password,cipher text,php class,class security,text key,security library,object instance,security measures,basic security,security level,string type,fallback,hash,data security,singleton,inactivity,php encrypt,implementation,php security diff --git a/es/core-utility-libraries/string.rst b/es/core-utility-libraries/string.rst deleted file mode 100644 index de7e364419e184411c51f9bd820e8e54b17c1359..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/string.rst +++ /dev/null @@ -1,325 +0,0 @@ -String -###### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Utility - -.. php:class:: String - -The String class includes convenience methods for creating and -manipulating strings and is normally accessed statically. Example: -``String::uuid()``. - -If you need :php:class:`Cake\\View\\Helper\\TextHelper` functionalities outside -of a ``View``, use the ``String`` class:: - - namespace App\Controller; - - use Cake\Utility\String; - - class UsersController extends AppController - { - - public $components = array('Auth'); - - public function afterLogin() - { - $message = $this->User->find('new_message'); - if (!empty($message)) { - // Notify user of new message - $this->Flash->success(__( - 'You have a new message: {0}', - String::truncate($message['Message']['body'], 255, array('html' => true)) - )); - } - } - } - -Generating UUIDs -================ - -.. php:staticmethod:: uuid() - -The UUID method is used to generate unique identifiers as per :rfc:`4122`. The -UUID is a 128bit string in the format of 485fc381-e790-47a3-9794-1337c0a8fe68. :: - - String::uuid(); // 485fc381-e790-47a3-9794-1337c0a8fe68 - - -Simple String Parsing -===================== - -.. php:staticmethod:: tokenize($data, $separator = ',', $leftBound = '(', $rightBound = ')') - -Tokenizes a string using ``$separator``, ignoring any instance of -``$separator`` that appears between ``$leftBound`` and ``$rightBound``. - -This method can be useful when splitting up data in that has regular -formatting such as tag lists:: - - $data = "cakephp 'great framework' php"; - $result = String::tokenize($data, ' ', "'", "'"); - // Result contains - array('cakephp', "'great framework'", 'php'); - -.. php:method:: parseFileSize(string $size, $default) - -This method unformats a number from a human readable byte size -to an integer number of bytes:: - - $int = String::parseFileSize('2GB'); - -Formatting Strings -================== - -.. php:staticmethod:: insert($string, $data, $options = array()) - -The insert method is used to create string templates and to allow -for key/value replacements:: - - String::insert( - 'My name is :name and I am :age years old.', - array('name' => 'Bob', 'age' => '65') - ); - // Returns: "My name is Bob and I am 65 years old." - -.. php:staticmethod:: cleanInsert($string, $options = array()) - -Cleans up a ``String::insert`` formatted string with given $options -depending on the 'clean' key in $options. The default method used -is text but html is also available. The goal of this function is to -replace all whitespace and unneeded markup around placeholders that -did not get replaced by ``String::insert``. - -You can use the following options in the options array:: - - $options = array( - 'clean' => array( - 'method' => 'text', // or html - ), - 'before' => '', - 'after' => '' - ); - -Wrapping Text -============= - -.. php:staticmethod:: wrap($text, $options = array()) - -Wraps a block of text to a set width, and indent blocks as well. -Can intelligently wrap text so words are not sliced across lines:: - - $text = 'This is the song that never ends.'; - $result = String::wrap($text, 22); - - // Returns - This is the song - that never ends. - -You can provide an array of options that control how wrapping is done. The -supported options are: - -* ``width`` The width to wrap to. Defaults to 72. -* ``wordWrap`` Whether or not to wrap whole words. Defaults to true. -* ``indent`` The character to indent lines with. Defaults to ''. -* ``indentAt`` The line number to start indenting text. Defaults to 0. - -.. start-string - -Highlighting Substrings -======================= - -.. php:method:: highlight(string $haystack, string $needle, array $options = array() ) - -Highlights ``$needle`` in ``$haystack`` using the ``$options['format']`` string -specified or a default string. - -Options: - -- 'format' - string The piece of HTML with that the phrase will be - highlighted -- 'html' - bool If true, will ignore any HTML tags, ensuring that - only the correct text is highlighted - -Example:: - - // Called as TextHelper - echo $this->Text->highlight( - $lastSentence, - 'using', - array('format' => '\1') - ); - - // Called as String - use Cake\Utility\String; - - echo String::highlight( - $lastSentence, - 'using', - array('format' => '\1') - ); - -Output:: - - Highlights $needle in $haystack using - the $options['format'] string specified or a default string. - -Removing Links -============== - -.. php:method:: stripLinks($text) - -Strips the supplied ``$text`` of any HTML links. - - -Truncating Text -=============== - -.. php:method:: truncate(string $text, int $length = 100, array $options) - -If ``$text`` is longer than ``$length``, this method truncates it at ``$length`` -and adds a prefix consisting of ``'ellipsis'``, if defined. If ``'exact'`` is -passed as ``false``, the truncation will occur at the first whitespace after the -point at which ``$length`` is exceeded. If ``'html'`` is passed as ``true``, -HTML tags will be respected and will not be cut off. - -``$options`` is used to pass all extra parameters, and has the -following possible keys by default, all of which are optional:: - - array( - 'ellipsis' => '...', - 'exact' => true, - 'html' => false - ) - -Example:: - - // Called as TextHelper - echo $this->Text->truncate( - 'The killer crept forward and tripped on the rug.', - 22, - array( - 'ellipsis' => '...', - 'exact' => false - ) - ); - - // Called as String - use Cake\Utility\String; - - echo String::truncate( - 'The killer crept forward and tripped on the rug.', - 22, - array( - 'ellipsis' => '...', - 'exact' => false - ) - ); - -Output:: - - The killer crept... - -Truncating the Tail of a String -=============================== - -.. php:method:: tail(string $text, int $length = 100, array $options) - -If ``$text`` is longer than ``$length``, this method removes an initial -substring with length consisting of the difference and prepends a suffix -consisting of ``'ellipsis'``, if defined. If ``'exact'`` is passed as ``false``, -the truncation will occur at the first whitespace prior to the point at which -truncation would otherwise take place. - -``$options`` is used to pass all extra parameters, and has the -following possible keys by default, all of which are optional:: - - array( - 'ellipsis' => '...', - 'exact' => true - ) - -Example:: - - $sampleText = 'I packed my bag and in it I put a PSP, a PS3, a TV, ' . - 'a C# program that can divide by zero, death metal t-shirts' - - // Called as TextHelper - echo $this->Text->tail( - $sampleText, - 70, - array( - 'ellipsis' => '...', - 'exact' => false - ) - ); - - // Called as String - use Cake\Utility\String; - - echo String::tail( - $sampleText, - 70, - array( - 'ellipsis' => '...', - 'exact' => false - ) - ); - -Output:: - - ...a TV, a C# program that can divide by zero, death metal t-shirts - -Extracting an Excerpt -===================== - -.. php:method:: excerpt(string $haystack, string $needle, integer $radius=100, string $ellipsis="...") - -Extracts an excerpt from ``$haystack`` surrounding the ``$needle`` -with a number of characters on each side determined by ``$radius``, -and prefix/suffix with ``$ellipsis``. This method is especially handy for -search results. The query string or keywords can be shown within -the resulting document. :: - - // Called as TextHelper - echo $this->Text->excerpt($lastParagraph, 'method', 50, '...'); - - // Called as String - use Cake\Utility\String; - - echo String::excerpt($lastParagraph, 'method', 50, '...'); - -Output:: - - ... by $radius, and prefix/suffix with $ellipsis. This method is - especially handy for search results. The query... - -Converting an Array to Sentence Form -==================================== - -.. php:method:: toList(array $list, $and='and') - -Creates a comma-separated list where the last two items are joined -with 'and'. :: - - // Called as TextHelper - echo $this->Text->toList($colors); - - // Called as String - use Cake\Utility\String; - - echo String::toList($colors); - -Output:: - - red, orange, yellow, green, blue, indigo and violet - -.. end-string - -.. meta:: - :title lang=en: String - :keywords lang=en: array php,array name,string options,data options,result string,class string,string data,string class,placeholders,default method,key value,markup,rfc,replacements,convenience,templates diff --git a/es/core-utility-libraries/time.rst b/es/core-utility-libraries/time.rst deleted file mode 100644 index 183dc2db46926b86e274d72542bfb44b3ad21e56..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/time.rst +++ /dev/null @@ -1,288 +0,0 @@ -Time -#### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Utility - -.. php:class:: Time - -If you need :php:class:`TimeHelper` functionalities outside of a ``View``, -use the ``Time`` class:: - - use Cake\Utility\Time; - - class UsersController extends AppController - { - - public $components = ['Auth']; - - public function afterLogin() - { - $time = new Time($this->Auth->user('date_of_birth')); - if ($time->isToday()) { - // Greet user with a happy birthday message - $this->Flash->success(__('Happy birthday to you...')); - } - } - } - - -Under the hood, CakePHP uses `Carbon `_ -to power its Time utility. Anything you can do with ``Carbon`` and -``DateTime``, you can do with ``Time``. - -.. start-time - -Creating Time Instances -======================= - -There are a few ways to create ``Time`` instances:: - - use Cake\Utility\Time; - - // Create from a string datetime. - $time = Time::createFromFormat( - 'Y-m-d H:i:s', - $datetime, - 'America/New_York' - ); - - // Create from a timestamp - $time = Time::createFromTimestamp($ts); - - // Get the current time. - $time = Time::now(); - - // Or just use 'new' - $time = new Time('2014-01-10 11:11', 'America/New_York'); - - $time = new Time('2 hours ago'); - -The ``Time`` class constructor can take any paramenter the internal ``DateTime`` -PHP class can. When passing a number or numeric string, it will be interpreted -as a UNIX timestamp. - -In test cases, you can easily mock out ``now()`` using ``setTestNow()``:: - - // Fixate time. - $now = new Time('2014-04-12 12:22:30'); - Time::setTestNow($now); - - // Returns '2014-04-12 12:22:30' - $now = Time::now(); - - // Returns '2014-04-12 12:22:30' - $now = Time::parse('now'); - -Manipulation -============ - -Once created, you can manipulate ``Time`` instances using setter methods:: - - $now = Time::now(); - $now->year(2013) - ->month(10) - ->day(31); - -You can also use the methods provided by PHP's built-in ``DateTime`` class:: - - $now->setDate(2013, 10, 31); - -Dates can be modified through subtraction and addition of their components:: - - $now = Time::now(); - $now->subDays(5); - $now->addMonth(1); - - // Using strtotime strings. - $now->modify('+5 days'); - -You can get the internal components of a date by accessing its properties:: - - $now = Time::now(); - echo $now->y; // 2014 - echo $now->m; // 5 - echo $now->d; // 10 - echo $now->timezone; // America/New_York - -It is also allowed to directly assign those properties to modify the date:: - - $time->y = 2015; - $time->timezone = 'Europe/Paris'; - -Formatting -========== - -.. php:method:: i18nFormat($format = null, $timezone = null, $locale = null) - -A very common thing to do with ``Time`` instances is to print out formatted -dates. CakePHP makes this a snap:: - - $now = Time::parse('2014-10-31'); - - // Prints a localized datetime stamp. - echo $now; - - // Outputs '4/20/14, 10:10 PM' for the en-US locale - $now->i18nFormat(); - - // Use the full date and time format - $now->i18nFormat(\IntlDateFormatter::FULL); - - // Use full date but short time format - $now->i18nFormat([\IntlDateFormatter::FULL, \IntlDateFormatter::Short]); - - // Outputs '2014-04-20 22:10' - $now->i18nFormat('YYYY-MM-dd HH:mm:ss'); - -.. php:method:: nice() - -Print out a predefined 'nice' format:: - - $now = Time::parse('2014-10-31'); - - // Outputs 'Oct 31, 2014 12:32pm' in en-US - echo $now->nice(); - -You can alter the timezone in which the date is displayed without altering the -``Time`` object itself. This is useful when you store dates in one timezone, but -want to display them in a user's own timezone:: - - $now->i18nFormat(\IntlDateFormatter::FULL, 'Europe/Paris'); - -Leaving the first parameter as null will use the default formatting string:: - - $now->i18nFormat(null, 'Europe/Paris'); - -Finally, it is possible to use a different locale for displaying a date:: - - echo $now->i18nFormat(\IntlDateFormatter::FULL, 'Europe/Paris', 'fr-FR'); - - echo $now->nice('Europe/Paris', 'fr-FR'); - -Setting the Default Locale and Format String --------------------------------------------- - -The default locale in which dates are displayed when using ``nice`` -``18nFormat`` is taken from the directive -`intl.default_locale `_. -You can, however, modify this default at runtime:: - - Time::$defaultLocale = 'es-ES'; - -From now on, dates will be displayed in the Spanish preferred format, unless -a different locale is specified directly in the formatting method. - -Likewise, it is possible to alter the default formatting string to be used for -``i18nFormat``:: - - Time::setToStringFormat(\IntlDateFormatter::Short); - - Time::setToStringFormat([\IntlDateFormatter::FULL, \IntlDateFormatter::Short]); - - Time::setToStringFormat('YYYY-MM-dd HH:mm:ss'); - -It is recommended to always use the constants instead of directly passing a date -format string. - -Formatting Relative Times -------------------------- - -.. php:method:: timeAgoInWords(array $options = []) - -Often it is useful to print times relative to the present:: - - $now = new Time('Aug 22, 2011'); - echo $now->timeAgoInWords( - ['format' => 'F jS, Y', 'end' => '+1 year'] - ); - // On Nov 10th, 2011 this would display: 2 months, 2 weeks, 6 days ago - -The ``end`` option lets you define at which point after which relative times should be -formatted using the ``format`` option. The ``accuracy`` option lets us control -what level of detail should be used for each interval range:: - - // If $timestamp is 1 month, 1 week, 5 days and 6 hours ago - echo $timestamp->timeAgoInWords([ - 'accuracy' => ['month' => 'month'], - 'end' => '1 year' - ]); - // Outputs '1 month ago' - -By setting ``accuracy`` to a string, you can specify what is the maximum level of detail you -want output:: - - $time = new Time('+23 hours'); - // Outputs 'in about a day' - $result = $time->timeAgoInWords([ - 'accuracy' => 'day' - ]); - -Conversion -========== - -.. php:method:: toQuarter() - -Once created, you can convert ``Time`` instances into timestamps or quarter -values:: - - $time = new Time('2014-06-15'); - $time->toQuarter(); - $time->toUnixString(); - -Comparing With the Present -========================== - -.. php:method:: isYesterday() -.. php:method:: isThisWeek() -.. php:method:: isThisMonth() -.. php:method:: isThisYear() - -You can compare a ``Time`` instance with the present in a variety of ways:: - - $time = new Time('2014-06-15'); - - echo $time->isYesterday(); - echo $time->isThisWeek(); - echo $time->isThisMonth(); - echo $time->isThisYear(); - -Each of the above methods will return true/false based on whether or not the -``Time`` instance matches the present. - -Comparing With Intervals -======================== - -.. php:method:: isWithinNext($interval) - -You can see if a ``Time`` instance falls within a given range using -``wasWithinLast()`` and ``isWithinNext()``:: - - $time = new Time('2014-06-15'); - - // Within 2 days. - echo $time->isWithinNext(2); - - // Within 2 next weeks. - echo $time->isWithinNext('2 weeks'); - -.. php:method:: isWithinPast($interval) - -You can also compare a ``Time`` instance within a range in the past:: - - // Within past 2 days. - echo $time->isWithinPast(2); - - // Within past 2 weeks. - echo $time->isWithinPast('2 weeks'); - -.. end-time - -.. meta:: - :title lang=en: Time - :description lang=en: Time class helps you format time and test time. - :keywords lang=en: time,format time,timezone,unix epoch,time strings,time zone offset,utc,gmt diff --git a/es/core-utility-libraries/xml.rst b/es/core-utility-libraries/xml.rst deleted file mode 100644 index 1f1e1a89e8af37aa4e9091d966b9b529a0f66284..0000000000000000000000000000000000000000 --- a/es/core-utility-libraries/xml.rst +++ /dev/null @@ -1,208 +0,0 @@ -Xml -### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -.. php:namespace:: Cake\Utility - -.. php:class:: Xml - -The Xml class allows you to easily transform arrays into SimpleXMLElement or -DOMDocument objects, and back into arrays again. - - -Importing Data to Xml Class -=========================== - -.. php:staticmethod:: build($input, $options = []) - -You can load XML-ish data do it using ``Xml::build()``. This method will return -a SimpleXMLElement or DOMDocument object (depending of your options parameter -- default is SimpleXMLElement). Below the samples how to import data from URL:: - - // First Load the Utility Class - use Cake\Utility\Xml; - - // Load XML from a URL. - $xml = Xml::build('http://bakery.cakephp.org/articles.rss'); - // $xml now is a instance of SimpleXMLElement - - // Or - $xml = Xml::build('http://bakery.cakephp.org/articles.rss', array('return' => 'simplexml')); - // $xml now is a instance of SimpleXMLElement - - // Load XML and get a DOMDocument instance back. - $xml = Xml::build('http://bakery.cakephp.org/articles.rss', array('return' => 'domdocument')); - // $xml now is a instance of DOMDocument - -You can use ``Xml::build()`` to build XML objects from a variety of sources. -For example, you can load XML from strings:: - - $text = ' - - 1 - Best post - ... - '; - $xml = Xml::build($text); - -You can also build Xml objects from either local files, or remote files. Remote -files will be fetched with :doc:`/core-utility-libraries/httpclient`:: - - // Local file - $xml = Xml::build('/home/awesome/unicorns.xml'); - - // Remote file - $xml = Xml::build('http://bakery.cakephp.org/articles.rss'); - -You can also build Xml objects using an array:: - - $data = array( - 'post' => array( - 'id' => 1, - 'title' => 'Best post', - 'body' => ' ... ' - ) - ); - $xml = Xml::build($data); - -If your input is invalid the Xml class will throw an Exception:: - - $xmlString = 'What is XML?' - try { - $xmlObject = Xml::build($xmlString); // Here will throw a Exception - } catch (\Cake\Utility\Error\XmlException $e) { - throw new InternalErrorException(); - } - -.. note:: - - `DOMDocument `_ and - `SimpleXML `_ implement different API's. - Be sure to use the correct methods on the object you request from Xml. - - -Transforming a XML String in Array -================================== - -.. php:staticmethod:: toArray($xml); - -Converting XML strings into arrays is simple with the Xml class as well. By -default you'll get a SimpleXml object back:: - - $xmlString = 'value'; - $xmlArray = Xml::toArray(Xml::build($xmlString)); - -If your XML is invalid a ``Cake\Utility\Error\XmlException`` will be raised. - -Transforming an Array into a String of XML -========================================== - -:: - - $xmlArray = array('root' => array('child' => 'value')); - // You can use Xml::build() too. - $xmlObject = Xml::fromArray($xmlArray, array('format' => 'tags')); - $xmlString = $xmlObject->asXML(); - -Your array must have only one element in the "top level" and it can not be -numeric. If the array is not in this format, Xml will throw a Exception. -Examples of invalid arrays:: - - // Top level with numeric key - array( - array('key' => 'value') - ); - - // Multiple keys in top level - array( - 'key1' => 'first value', - 'key2' => 'other value' - ); - - -By default array values will be output as XML tags, if you want to define -attributes or text values you can should prefix the keys that are supposed to be -attributes with ``@``. For value text, use ``@`` as the key:: - - $xmlArray = array( - 'project' => array( - '@id' => 1, - 'name' => 'Name of project, as tag', - '@' => 'Value of project' - ) - ); - $xmlObject = Xml::fromArray($xmlArray); - $xmlString = $xmlObject->asXML(); - -The content of ``$xmlString`` will be:: - - - Value of projectName of project, as tag - - -Using Namespaces ----------------- - -To use XML Namespaces, in your array you must create a key with name ``xmlns:`` -to generic namespace or input the prefix ``xmlns:`` in a custom namespace. See -the samples:: - - $xmlArray = array( - 'root' => array( - 'xmlns:' => 'http://cakephp.org', - 'child' => 'value' - ) - ); - $xml1 = Xml::fromArray($xmlArray); - - $xmlArray( - 'root' => array( - 'tag' => array( - 'xmlns:pref' => 'http://cakephp.org', - 'pref:item' => array( - 'item 1', - 'item 2' - ) - ) - ) - ); - $xml2 = Xml::fromArray($xmlArray); - -The value of ``$xml1`` and ``$xml2`` will be, respectively:: - - - value - - - - item 1item 2 - -Creating a Child ----------------- - -After you have created your XML document, you just use the native interfaces for -your document type to add, remove, or manipulate child nodes:: - - // Using SimpleXML - $myXmlOriginal = 'value'; - $xml = Xml::build($myXmlOriginal); - $xml->root->addChild('young', 'new value'); - - // Using DOMDocument - $myXmlOriginal = 'value'; - $xml = Xml::build($myXmlOriginal, array('return' => 'domdocument')); - $child = $xml->createElement('young', 'new value'); - $xml->firstChild->appendChild($child); - -.. tip:: - - After manipulate your XML using SimpleXMLElement or DomDocument you can use - ``Xml::toArray()`` without a problem. - -.. meta:: - :title lang=en: Xml - :keywords lang=en: array php,xml class,xml objects,post xml,xml object,string url,string data,xml parser,php 5,bakery,constructor,php xml,cakephp,php file,unicorns,meth diff --git a/es/debug-kit.rst b/es/debug-kit.rst new file mode 100644 index 0000000000000000000000000000000000000000..7f0d272e433d4280c1e7539e9fd0813c4d54b244 --- /dev/null +++ b/es/debug-kit.rst @@ -0,0 +1,11 @@ +Debug Kit +######### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/deployment.rst b/es/deployment.rst index 1a8635fa59f82d344040fcff756f14ab198cb86e..4f71474555024dea8b7897a0361d69eb4639ffbc 100644 --- a/es/deployment.rst +++ b/es/deployment.rst @@ -2,8 +2,14 @@ ES - Deployment ############### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Steps to deploy on a Hosting Server + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Deployment + :keywords lang=es: stack traces,application extensions,set document,installation documentation,development features,generic error,document root,func,debug,caches,error messages,configuration files,webroot,deployment,cakephp,applications diff --git a/es/development.rst b/es/development.rst deleted file mode 100644 index de8eda4e8ead8bd71c7f2949cf3afb939e6dee8d..0000000000000000000000000000000000000000 --- a/es/development.rst +++ /dev/null @@ -1,29 +0,0 @@ -Development -########### - -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - -In this section we'll cover the various aspects of developing a CakePHP -application. Topics like Configuration, handling errors & exceptions, -debugging, and testing will be covered. - -.. toctree:: - :maxdepth: 1 - - development/configuration - development/routing - development/sessions - development/exceptions - development/errors - development/debugging - development/testing - development/rest - development/dispatch-filters - - -.. meta:: - :title lang=en: Development - :keywords lang=en: development sessions,debugging,exceptions diff --git a/es/development/configuration.rst b/es/development/configuration.rst index 1469beac27d53f56e46ed9c7c60eb6fc98f4d384..322d2a7453149ca4bf68047619fb4a322348ae4d 100644 --- a/es/development/configuration.rst +++ b/es/development/configuration.rst @@ -2,632 +2,14 @@ Configuration ############# .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Configuring a CakePHP application is a piece of cake. After you -have installed CakePHP, creating a basic web application requires -only that you setup a database configuration. - -There are, however, other optional configuration steps you can take -in order to take advantage of CakePHP flexible architecture. You -can easily add to the functionality inherited from the CakePHP -core, configure additional/different URL mappings (routes), and -define additional/different inflections. - -.. index:: app.php, app.php.default - -.. index:: configuration - -Configuring your Application -============================ - -While CakePHP is a conventions over configuration framework, it still exposes -a number of configuration options that allow you to tailor CakePHP for your -needs. We've tried to ship CakePHP with useful defaults to get you developing more -rapidly. - -Configuration is generally stored in either PHP or INI files, and loaded during -the application bootstrap. CakePHP comes with one configuration file by default, -but if required you can add additional configuration files and load them in -``config/bootstrap.php``. :php:class:`Cake\\Core\\Configure` is used for -general configuration, and the adapter based classes provide ``config()`` -methods to make configuration simple and transparent. - -Loading Additional Configuration Files --------------------------------------- - -If your application has many configuration options it can be helpful to split -configuration into multiple files. After creating each of the files in your -``config/`` directory you can load them during bootstrap.php:: - - use Cake\Core\Configure; - use Cake\Configure\Engine\PhpConfig; - - Configure::config('default', new PhpConfig()); - Configure::load('app', 'default', false); - Configure::load('other_config', 'default'); - -You can also use additional configuration files to provide environment specific -overrides. Each file loaded after ``app.php`` can redefine previously declared -values allowing you to customize configuration for development or staging -environments. - -General Configuration ---------------------- - -Below is a description of the variables and how they affect your CakePHP -application. - -debug - Changes CakePHP debugging output. false = Production mode. No error - messages, errors, or warnings shown. true = Errors and warnings shown. -App.namespace - The namespace to find app classes under. - - .. note:: - - When changing the namespace in your configuration, you will also - need to update your ``composer.json`` file to use this namespace - as well. Additionally, create a new autoloader by running - ``php composer.phar dumpautoload``. - -.. _core-configuration-baseurl: - -App.baseUrl - Un-comment this definition if you **don’t** plan to use Apache’s - mod\_rewrite with CakePHP. Don’t forget to remove your .htaccess - files too. -App.base - The base directory the app resides in. If false this - will be auto detected. -App.encoding - Define what encoding your application uses. This encoding - is used to generate the charset in the layout, and encode entities. - It should match the encoding values specified for your database. -App.webroot - The webroot directory. -App.www_root - The file path to webroot. -App.fullBaseUrl - The fully qualified domain name (including protocol) to your application's - root. This is used when generating absolute URLs. By default this is value - is generated using the $_SERVER environment. However, you should define it - manually to optimize performance or if you are concerned about people - manipulating the ``Host`` header. -App.imageBaseUrl - Web path to the public images directory under webroot. If you are using - a :term:`CDN` you should set this value to the CDN's location. -App.cssBaseUrl - Web path to the public css directory under webroot. If you are using - a :term:`CDN` you should set this value to the CDN's location. -App.jsBaseUrl - Web path to the public js directory under webroot. If you are using - a :term:`CDN` you should set this value to the CDN's location. -Security.salt - A random string used in security hashing. This value is also used as the - HMAC salt when doing symetric encryption. -Asset.timestamp - Appends a timestamp which is last modified time of the particular - file at the end of asset files URLs (CSS, JavaScript, Image) when - using proper helpers. - Valid values: - (bool) false - Doesn't do anything (default) - (bool) true - Appends the timestamp when debug > 0 - (string) 'force' - Always appends the timestamp. - -Database Configuration -====================== - -See the :ref:`database-configuration` for information on configuring your -database connections. - - -Caching Configuration ---------------------- - -See the :ref:`cache-configuration` for information on configuring caching in -CakePHP. - -Error and Exception Handling Configuration ------------------------------------------- - -See the sections on :ref:`error-configuration` for information on configuring -error and exception handlers. - -Logging Configuration ---------------------- - -See the :ref:`log-configuration` for information on configuring logging in -CakePHP. - -Email Configuration -------------------- - -See the :ref:`email-configuration` for information on configuring email presets in -CakePHP. - -Session Configuration ---------------------- - -See the :ref:`session-configuration` for information on configuring session -handling in CakePHP. - -Routing configuration ---------------------- - -See :ref:`routes-configuration` for more information on configuring routing and -creating routes for your application. - -Configuration Constants ------------------------ - -While most configuration options are handled by Configure, there -are a few constants that CakePHP uses during runtime. - -.. php:const:: LOG_ERROR - - Error constant. Used for differentiating error logging and - debugging. Currently PHP supports LOG\_DEBUG. - -.. _additional-class-paths: - -Additional Class Paths -====================== - -Additional class paths are setup through the autoloaders your application uses. -When using ``Composer`` to generate your autoloader, you could do the following, -to provide fallback paths for controllers in your application:: - - "autoload": { - "psr-4": { - "App\\Controller": "/path/to/directory/with/controller/folders", - "App\": "src" - } - } - -The above would setup paths for both the ``App`` and ``App\Controller`` -namespace. The first key will be searched, and if that path does not contain the -class/file the second key will be searched. You can also map a single namespace -to multiple directories with the following:: - - "autoload": { - "psr-4": { - "App\": ["src", "/path/to/directory"] - } - } - -View and Plugin Paths ---------------------- - -Since views and plugins are not classes, they cannot have an autoloader -configured. CakePHP provides two configure variables to setup additional paths -for these resources. In your ``config/app.php`` you can set these -variables:: - - return [ - // More configuration - 'App' => [ - 'paths' => [ - 'views' => [APP . 'View/', APP . 'View2/'], - 'plugins' => [ROOT . '/Plugin/', '/path/to/other/plugins/'] - ] - ] - ]; - -Paths should be suffixed with ``/``, or they will not work properly. - -Inflection Configuration -======================== - -See the :ref:`inflection-configuration` docs for more information. - -Configure Class -=============== - -.. php:namespace:: Cake\Core - -.. php:class:: Configure - -Despite few things needing to be configured in CakePHP, it's -sometimes useful to have your own configuration rules for your -application. In the past you may have defined custom configuration -values by defining variable or constants in some files. Doing so -forces you to include that configuration file every time you needed -to use those values. - -CakePHP's Configure class can be used to store and retrieve -application or runtime specific values. Be careful, this class -allows you to store anything in it, then use it in any other part -of your code: a sure temptation to break the MVC pattern CakePHP -was designed for. The main goal of Configure class is to keep -centralized variables that can be shared between many objects. -Remember to try to live by "convention over configuration" and you -won't end up breaking the MVC structure we've set in place. - -This class can be called from anywhere within your application, in a static -context:: - - Configure::read('debug'); - -.. php:staticmethod:: write($key, $value) - - :param string $key: The key to write, can use be a :term:`dot notation` value. - :param mixed $value: The value to store. - - Use ``write()`` to store data in the application's configuration:: - - Configure::write('Company.name','Pizza, Inc.'); - Configure::write('Company.slogan','Pizza for your body and soul'); - - .. note:: - - The :term:`dot notation` used in the ``$key`` parameter can be used to - organize your configuration settings into logical groups. - - The above example could also be written in a single call:: - - Configure::write( - 'Company', - array( - 'name' => 'Pizza, Inc.', - 'slogan' => 'Pizza for your body and soul' - ) - ); - - You can use ``Configure::write('debug', $bool)`` to switch between - debug and production modes on the fly. This is especially handy for - AMF or JSON interactions where debugging information can cause - parsing problems. - -.. php:staticmethod:: read($key = null) - - :param string $key: The key to read, can use be a :term:`dot notation` value - - Used to read configuration data from the application. Defaults to - CakePHP's important debug value. If a key is supplied, the data is - returned. Using our examples from write() above, we can read that - data back:: - - Configure::read('Company.name'); // Yields: 'Pizza, Inc.' - Configure::read('Company.slogan'); // Yields: 'Pizza for your body - // and soul' - - Configure::read('Company'); - - // Yields: - array('name' => 'Pizza, Inc.', 'slogan' => 'Pizza for your body and soul'); - - If $key is left null, all values in Configure will be returned. - -.. php:staticmethod:: check($key) - - :param string $key: The key to check. - - Used to check if a key/path exists and has not-null value. - -.. php:staticmethod:: delete($key) - - :param string $key: The key to delete, can use be a :term:`dot notation` value - - Used to delete information from the application's configuration:: - - Configure::delete('Company.name'); - -.. php:staticmethod:: version() - - Returns the CakePHP version for the current application. - -.. php:staticmethod:: consume($key) - - Read and delete a key from Configure. This is useful when you want to - combine reading and deleting values in a single operation. - - .. versionadded:: 3.0 - -.. php:staticmethod:: config($name, $engine) - - :param string $name: The name of the engine being attached. - :param ConfigEngineInterface $engine: The engine instance being attached. - - Attach a configuration reader to Configure. Attached readers can - then be used to load configuration files. See :ref:`loading-configuration-files` - for more information on how to read configuration files. - -.. php:staticmethod:: configured($name = null) - - :param string $name: The name of the engine to check, if null - a list of all attached engines will be returned. - - Either check that a engine with a given name is attached, or get - the list of attached engines. - -.. php:staticmethod:: drop($name) - - Drops a connected engine object. - - -Reading and writing configuration files -======================================= - -CakePHP comes with two built-in configuration file engines. -:php:class:`Cake\\Configure\\Engine\\PhpConfig` is able to read PHP config files, in the same -format that Configure has historically read. :php:class:`Cake\\Configure\\Engine\\IniConfig` is -able to read ini config files. See the `PHP documentation `_ -for more information on the specifics of ini files. -To use a core config engine, you'll need to attach it to Configure -using :php:meth:`Configure::config()`:: - - use Cake\\Configure\\Engine\\PhpConfig; - // Read config files from config - Configure::config('default', new PhpConfig()); - - // Read config files from another path. - Configure::config('default', new PhpConfig('/path/to/your/config/files/')); - -You can have multiple engines attached to Configure, each reading -different kinds of configuration files, or reading from -different types of sources. You can interact with attached engines -using a few other methods on Configure. To see check which engine -aliases are attached you can use :php:meth:`Configure::configured()`:: - - // Get the array of aliases for attached engines. - Configure::configured(); - - // Check if a specific engine is attached - Configure::configured('default'); - -You can also remove attached engines. ``Configure::drop('default')`` -would remove the default engine alias. Any future attempts to load configuration -files with that engine would fail. - - -.. _loading-configuration-files: - -Loading Configuration Files ---------------------------- - -.. php:staticmethod:: load($key, $config = 'default', $merge = true) - - :param string $key: The identifier of the configuration file to load. - :param string $config: The alias of the configured engine. - :param boolean $merge: Whether or not the contents of the read file - should be merged, or overwrite the existing values. - -Once you've attached a config engine to Configure you can load configuration files:: - - // Load my_file.php using the 'default' engine object. - Configure::load('my_file', 'default'); - -Loaded configuration files merge their data with the existing runtime configuration -in Configure. This allows you to overwrite and add new values -into the existing runtime configuration. By setting ``$merge`` to true, values -will not ever overwrite the existing configuration. - -Creating or Modifying Configuration Files ------------------------------------------ - -.. php:staticmethod:: dump($key, $config = 'default', $keys = array()) - - :param string $key: The name of the file/stored configuration to be created. - :param string $config: The name of the engine to store the data with. - :param array $keys: The list of top-level keys to save. Defaults to all - keys. - -Dumps all or some of the data in Configure into a file or storage system -supported by a config engine. The serialization format -is decided by the config engine attached as $config. For example, if the -'default' engine is a :php:class:`Cake\\Configure\\Engine\\PhpConfig`, the generated file will be a PHP -configuration file loadable by the :php:class:`Cake\\Configure\\Engine\\PhpConfig` - -Given that the 'default' engine is an instance of PhpConfig. -Save all data in Configure to the file `my_config.php`:: - - Configure::dump('my_config.php', 'default'); - -Save only the error handling configuration:: - - Configure::dump('error.php', 'default', array('Error', 'Exception')); - -``Configure::dump()`` can be used to either modify or overwrite -configuration files that are readable with :php:meth:`Configure::load()` - - -Storing Runtime Configuration ------------------------------ - -.. php:staticmethod:: store($name, $cacheConfig = 'default', $data = null) - - :param string $name: The storage key for the cache file. - :param string $cacheConfig: The name of the cache configuration to store the - configuration data with. - :param mixed $data: Either the data to store, or leave null to store all data - in Configure. - -You can also store runtime configuration values for use in a future request. -Since configure only remembers values for the current request, you will -need to store any modified configuration information if you want to -use it in subsequent requests:: - - // Store the current configuration in the 'user_1234' key in the 'default' cache. - Configure::store('user_1234', 'default'); - -Stored configuration data is persisted in the :php:class:`Cache` class. This allows -you to store Configuration information in any storage engine that :php:class:`Cache` can talk to. - -Restoring Runtime Configuration -------------------------------- - -.. php:staticmethod:: restore($name, $cacheConfig = 'default') - - :param string $name: The storage key to load. - :param string $cacheConfig: The cache configuration to load the data from. - -Once you've stored runtime configuration, you'll probably need to restore it -so you can access it again. ``Configure::restore()`` does exactly that:: - - // Restore runtime configuration from the cache. - Configure::restore('user_1234', 'default'); - -When restoring configuration information it's important to restore it with -the same key, and cache configuration as was used to store it. Restored -information is merged on top of the existing runtime configuration. - -Creating your Own Configuration Engines -======================================= - -Since configuration engines are an extensible part of CakePHP, -you can create configuration engines in your application and plugins. -Configuration engines need to implement the :php:interface:`Cake\\Configure\\ConfigEngineInterface`. -This interface defines a read method, as the only required method. -If you really like XML files, you could create a simple Xml config -engine for you application:: - - // In app/Lib/Configure/Engine/XmlConfig.php - use Cake\\Utility\\Xml; - - class XmlConfig implements ConfigEngineInterface - { - public function __construct($path = null) - { - if (!$path) { - $path = APP . 'Config' . DS; - } - $this->_path = $path; - } - - public function read($key) - { - $xml = Xml::build($this->_path . $key . '.xml'); - return Xml::toArray($xml); - } - - // As of 2.3 a dump() method is also required - public function dump($key, $data) - { - // Code to dump data to file - } - } - -In your ``config/bootstrap.php`` you could attach this engine and use it:: - - use Cake\\Configure\\Engine\\XmlConfig; - Configure::config('xml', new XmlConfig()); - ... - - Configure::load('my_xml'); - -The ``read()`` method of a config engine, must return an array of the configuration information -that the resource named ``$key`` contains. - -.. php:namespace:: Cake\Configure - -.. php:interface:: ConfigEngineInterface - - Defines the interface used by classes that read configuration data and - store it in :php:class:`Configure` - -.. php:method:: read($key) - - :param string $key: The key name or identifier to load. - - This method should load/parse the configuration data identified by ``$key`` - and return an array of data in the file. - -.. php:method:: dump($key) - - :param string $key: The identifier to write to. - :param array $data: The data to dump. - - This method should dump/store the provided configuration data to a key identified by ``$key``. - -.. php:exception:: ConfigureException - - Thrown when errors occur when loading/storing/restoring configuration data. - :php:interface:`ConfigEngineInterface` implementations should throw this - error when they encounter an error. - -Built-in Configuration Engines ------------------------------- - -.. php:class:: PhpConfig - - Allows you to read configuration files that are stored as plain PHP files. - You can read either files from your ``config`` or from plugin configs - directories by using :term:`plugin syntax`. Files **must** contain a ``$config`` - variable. An example configuration file would look like:: - - $config = [ - 'debug' => 0, - 'Security' => [ - 'salt' => 'its-secret' - ], - 'App' => [ - 'namespace' => 'App' - ] - ]; - - Files without ``$config`` will cause an :php:exc:`ConfigureException` - - Load your custom configuration file by inserting the following in config/bootstrap.php:: - - Configure::load('customConfig'); - -.. php:class:: IniConfig - - Allows you to read configuration files that are stored as plain .ini files. - The ini files must be compatible with php's ``parse_ini_file`` function, and - benefit from the following improvements - - * dot separated values are expanded into arrays. - * boolean-ish values like 'on' and 'off' are converted to booleans. - - An example ini file would look like:: - - debug = 0 - - [Security] - salt = its-secret - - [App] - namespace = App - - The above ini file, would result in the same end configuration data - as the PHP example above. Array structures can be created either - through dot separated values, or sections. Sections can contain - dot separated keys for deeper nesting. - -Bootstrapping CakePHP -===================== - -If you have any additional configuration needs, use CakePHP's -bootstrap file, found in config/bootstrap.php. This file is -executed just after CakePHP's core bootstrapping. - -This file is ideal for a number of common bootstrapping tasks: - -- Defining convenience functions. -- Registering global constants. -- Defining additional model, view, and controller paths. -- Creating cache configurations. -- Configuring inflections. -- Loading configuration files. - -Be careful to maintain the MVC software design pattern when you add -things to the bootstrap file: it might be tempting to place -formatting functions there in order to use them in your -controllers. - -Resist the urge. You'll be glad you did later on down the line. - -You might also consider placing things in the :php:class:`AppController` class. -This class is a parent class to all of the controllers in your -application. :php:class:`AppController` is a handy place to use controller -callbacks and define methods to be used by all of your -controllers. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Configuration - :keywords lang=en: finished configuration,legacy database,database configuration,value pairs,default connection,optional configuration,example database,php class,configuration database,default database,configuration steps,index database,configuration details,class database,host localhost,inflections,key value,database connection,piece of cake,basic web + :title lang=es: Configuration + :keywords lang=es: finished configuration,legacy database,database configuration,value pairs,default connection,optional configuration,example database,php class,configuration database,default database,configuration steps,index database,configuration details,class database,host localhost,inflections,key value,database connection,piece of cake,basic web diff --git a/es/development/debugging.rst b/es/development/debugging.rst index 1ad444bb36c8655e1318265aad1695399230f71b..dc23a04f210210a5413370d2b02275ccbe38c760 100644 --- a/es/development/debugging.rst +++ b/es/development/debugging.rst @@ -2,175 +2,15 @@ Debugging ######### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Debugging is an inevitable and necessary part of any development -cycle. While CakePHP doesn't offer any tools that directly connect -with any IDE or editor, CakePHP does provide several tools to -assist in debugging and exposing what is running under the hood of -your application. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -Basic Debugging -=============== - -.. php:function:: debug(mixed $var, boolean $showHtml = null, $showFrom = true) - -The ``debug()`` function is a globally available function that works -similarly to the PHP function ``print\_r()``. The ``debug()`` function -allows you to show the contents of a variable in a number of -different ways. First, if you'd like data to be shown in an -HTML-friendly way, set the second parameter to true. The function -also prints out the line and file it is originating from by -default. - -Output from this function is only shown if the core ``$debug`` variable -has been set to true. - -.. php:function stackTrace() - -The ``stackTrace()`` function is available globally, and allows you to output -a stack trace whereever the function is called. - -Using the Debugger Class -======================== - -.. php:namespace:: Cake\Utility - -.. php:class:: Debugger - -To use the debugger, first ensure that ``Configure::read('debug')`` is -set to ``true``. - -Outputting Values -================= - -.. php:staticmethod:: dump($var, $depth = 3) - -Dump prints out the contents of a variable. It will print out all -properties and methods (if any) of the supplied variable:: - - $foo = array(1,2,3); - - Debugger::dump($foo); - - // Outputs - array( - 1, - 2, - 3 - ) - - // Simple object - $car = new Car(); - - Debugger::dump($car); - - // Outputs - object(Car) { - color => 'red' - make => 'Toyota' - model => 'Camry' - mileage => (int)15000 - } - -Logging With Stack Traces -========================= - -.. php:staticmethod:: log($var, $level = 7, $depth = 3) - -Creates a detailed stack trace log at the time of invocation. The -``log()`` method prints out data similar to that done by -``Debugger::dump()``, but to the debug.log instead of the output -buffer. Note your ``tmp`` directory (and its contents) must be -writable by the web server for ``log()`` to work correctly. - -Generating Stack Traces -======================= - -.. php:staticmethod:: trace($options) - -Returns the current stack trace. Each line of the trace includes -the calling method, including which file and line the call -originated from:: - - // In PostsController::index() - pr(Debugger::trace()); - - // Outputs - PostsController::index() - APP/Controller/DownloadsController.php, line 48 - Dispatcher::_invoke() - CORE/src/Routing/Dispatcher.php, line 265 - Dispatcher::dispatch() - CORE/src/Routing/Dispatcher.php, line 237 - [main] - APP/webroot/index.php, line 84 - -Above is the stack trace generated by calling ``Debugger::trace()`` in -a controller action. Reading the stack trace bottom to top shows -the order of currently running functions (stack frames). - - - -Getting an Excerpt From a File -============================== - -.. php:staticmethod:: excerpt($file, $line, $context) - -Grab an excerpt from the file at $path (which is an absolute -filepath), highlights line number $line with $context number of -lines around it. :: - - pr(Debugger::excerpt(ROOT . DS . LIBS . 'debugger.php', 321, 2)); - - // Will output the following. - Array - ( - [0] => * @access public - [1] => */ - [2] => function excerpt($file, $line, $context = 2) { - - [3] => $data = $lines = array(); - [4] => $data = @explode("\n", file_get_contents($file)); - ) - -Although this method is used internally, it can be handy if you're -creating your own error messages or log entries for custom -situations. - -.. php:staticmethod:: Debugger::getType($var) - -Get the type of a variable. Objects will return their class name - - -Using Logging to Debug -====================== - -Logging messages is another good way to debug applications, and you can use -:php:class:`Cake\\Log\\Log` to do logging in your application. All objects that -use ``LogTrait`` have an instance method `log()` which can be used -to log messages:: - - $this->log('Got here', 'debug'); - -The above would write ``Got here`` into the debug log. You can use log entries -to help debug methods that involve redirects or complicated loops. You can also -use :php:meth:`Cake\\Log\\Log::write()` to write log messages. This method can be called -statically anywhere in your application one CakeLog has been loaded:: - - // At the top of the file you want to log in. - use Cake\Log\Log; - - // Anywhere that Log has been imported. - Log::debug('Got here'); - -Debug Kit -========= - -DebugKit is a plugin that provides a number of good debugging tools. It -primarily provides a toolbar in the rendered HTML, that provides a plethora of -information about your application and the current request. You can download -`DebugKit `_ from GitHub. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Debugging - :description lang=en: Debugging CakePHP with the Debugger class, logging, basic debugging and using the DebugKit plugin. - :keywords lang=en: code excerpt,stack trace,default output,error link,default error,web requests,error report,debugger,arrays,different ways,excerpt from,cakephp,ide,options + :title lang=es: Debugging + :description lang=es: Debugging CakePHP with the Debugger class, logging, basic debugging and using the DebugKit plugin. + :keywords lang=es: code excerpt,stack trace,default output,error link,default error,web requests,error report,debugger,arrays,different ways,excerpt from,cakephp,ide,options diff --git a/es/development/dispatch-filters.rst b/es/development/dispatch-filters.rst index 20f5ff0301fe188323eae6a9f79668c605bead30..06f9e8df0c88514909d2d12d59d17494c0589f90 100644 --- a/es/development/dispatch-filters.rst +++ b/es/development/dispatch-filters.rst @@ -2,191 +2,15 @@ Dispatcher Filters ################## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -There are several reasons to want a piece of code to be run before any -controller code is executed or right before the response is sent to the client, -such as response caching, header tuning, special authentication or just to -provide access to a mission-critical API response in lesser time than a complete -request dispatching cycle would take. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -CakePHP provides a clean interface for attaching filters to the dispatch -cycle. It is similar to a middleware layer, but re-uses the existing event -subsystem used in other parts of CakePHP. Since they do not work exactly -like traditional middleware, we refer to them as *Dispatcher Filters*. - -Built-in Filters -================ - -CakePHP comes with several dispatcher filters built-in. They handle common -features that all applications are likely to need. The built-in filters are: - -* ``AssetFilter`` checks whether the request is referring to a theme - or plugin asset file, such as a CSS, JavaScript or image file stored in either a - plugin's webroot folder or the corresponding one for a Theme. It will serve the - file accordingly if found, stopping the rest of the dispatching cycle. -* ``CacheFilter`` when ``Cache.check`` config variable is enabled, will check if the - response was already cached in the file system for a similar request and serve - the cached code immediately. -* ``RoutingFilter`` applies application routing rules to the request URL. - Populates ``$request->params`` with the results of routing. -* ``ControllerFactory`` uses ``$request->params`` to locate the controller that - will handle the current request. - -Using Filters -============= - -Filters are usually enabled in your application's ``bootstrap.php`` file, but -you could easily load them any time before the request is dispatched. Adding -and removing filters is done through ``Cake\\Routing\\DispatcherFactory``. By -default, the CakePHP application template comes with a couple filter classes -already enabled for all requests; let's take a look at how they are added:: - - DispatcherFactory::add('Cache'); - DispatcherFactory::add('Routing'); - DispatcherFactory::add('ControllerFactory'); - - // Use options to set priority - DispatcherFactory::add('Asset', ['priority' => 1]); - -While using the string name is convenient, you can also pass instances into -``add()``:: - - use Cake\Routing\Filter\RoutingFilter; - - DispatcherFactory::add(new RoutingFilter()); - -Configuring Filter Order ------------------------- - -When adding filters, you can control the order they are invoked in using -event handler priorities. While filters can define a default priority using the -``_priority`` property, you can set a specific priority when attaching the -filter:: - - DispatcherFactory::add('Asset', ['priority' => 1]); - DispatcherFactory::add(new AssetFilter(['priority' => 1])); - -Conditionally Applying Filters ------------------------------- - -If you don't want to run a filter on every request, you can use conditions to -only apply it some of the time. You can apply conditions using the ``for`` and -``when`` options. The ``for`` option lets you match on URL substrings, while the -``when`` option allows you to run a callable:: - - // Only runs on requests starting with `/blog` - DispatcherFactory::add('BlogHeader', ['for' => '/blog']); - - // Only run on GET requests. - DispatcherFactory::add('Cache', [ - 'when' => function ($request, $response) { - return $request->is('get'); - } - ]); - -The callable provided to ``when`` should return true when the filter should run. -The callable can expect to get the current request and response as arguments. - -Building a Filter -================= - -To create a filter, define a class in ``src/Routing/Filter``. In this example, -we'll be making a filter that adds a tracking cookie for the first landing -page. First, create the file. Its contents should look like:: - - namespace App\Routing\Filter; - - use Cake\Event\Event; - use Cake\Routing\DispatcherFilter; - - class TrackingCookieFilter extends DispatcherFilter - { - - public function beforeDispatch(Event $event) - { - $request = $event->data['request']; - $response = $event->data['response']; - if (!$request->cookie('landing_page')) { - $response->cookie([ - 'name' => 'landing_page', - 'value' => $request->here(), - 'expire' => '+ 1 year', - ]); - } - } - } - -Save this file into ``src/Routing/Filter/TrackingCookieFilter.php``. As you can see, like other -classes in CakePHP, dispatcher filters have a few conventions: - -* Class names end in ``Filter``. -* Classes are in the ``Routing\\Filter`` namespace. For example, - ``App\\Routing\\Filter``. -* Generally filters extend ``Cake\\Routing\\DispatcherFilter``. - -``DispatcherFilter`` exposes two methods that can be overridden in subclasses, -they are ``beforeDispatch`` and ``afterDispatch``. These methods are executed -before or after any controller is executed respectively. Both methods receive -a :php:class:`Cake\\Event\\Event` object containing the ``request`` and -``response`` objects (:php:class:`Cake\\Network\\Request` and -:php:class:`Cake\\Network\\Response` instances) inside the ``data`` property. - -While our filter was pretty simple, there are a few other interesting things we -can do in filter methods. By returning an ``Response`` object, you can -short-circuit the dispatch process and prevent the controller from being called. -When returning a response, you should also remember to call -``$event->stopPropagation()`` so other filters are not called. - -.. note:: - - When a beforeDispatch method returns a response, the controller, and - afterDispatch event will not be invoked. - -Let's now create another filter for altering response headers in any public -page, in our case it would be anything served from the ``PagesController``:: - - namespace App\Routing\Filter; - - use Cake\Event\Event; - use Cake\Routing\DispatcherFilter; - - class HttpCacheFilter extends DispatcherFilter - { - - public function afterDispatch(Event $event) - { - $request = $event->data['request']; - $response = $event->data['response']; - - if ($response->statusCode() === 200) { - $response->sharable(true); - $response->expires(strtotime('+1 day')); - } - } - } - - - // In our bootstrap.php - DispatcherFactory::add('HttpCache', ['for' => '/pages']) - -This filter will send a expiration header to 1 day in the future for -all responses produced by the pages controller. You could of course do the same -in the controller, this is just an example of what could be done with filters. -For instance, instead of altering the response, you could cache it using -:php:class:`Cake\\Cache\\Cache` and serve the response from the ``beforeDispatch`` -callback. - -While powerful, dispatcher filters have the potential to make your application -more difficult to maintain. Filters are an extremely powerful tool when used -wisely and adding response handlers for each URL in your app is not a good use for -them. Keep in mind that not everything needs to be a filter; `Controllers` and -`Components` are usually a more accurate choice for adding any request handling -code to your app. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Dispatcher Filters - :description lang=en: Dispatcher filters are a middleware layer for CakePHP allowing to alter the request or response before it is sent - :keywords lang=en: middleware, filters, dispatcher, request, response, rack, application stack, events, beforeDispatch, afterDispatch, router + :title lang=es: Dispatcher Filters + :description lang=es: Dispatcher filters are a middleware layer for CakePHP allowing to alter the request or response before it is sent + :keywords lang=es: middleware, filters, dispatcher, request, response, rack, application stack, events, beforeDispatch, afterDispatch, router diff --git a/es/development/errors.rst b/es/development/errors.rst index 8af9d343b2d482f6c0e0f67fd1520f10221799e1..e0e93e9c99bbb45bc02ed9215c5f572dea769f9e 100644 --- a/es/development/errors.rst +++ b/es/development/errors.rst @@ -2,482 +2,14 @@ Error & Exception Handling ########################## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Many of PHP's internal methods use errors to communicate failures. These errors -will need to be trapped and dealt with. CakePHP comes with default error -trapping that prints and or logs errors as they occur. This same error handler -is used to catch uncaught exceptions from controllers and other parts of your -application. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -.. _error-configuration: - -Error & Exception Configuration -================================ - -Error configuration is done inside your application's ``config/app.php`` -file. By default CakePHP uses the ``ErrorHandler`` or ``ConsoleErrorHandler`` -class to trap errors and print/log the errors. You can replace this behavior by -changing out the default error handler. The default error handler also handles -uncaught exceptions. - -Error handling accepts a few options that allow you to tailor error handling for -your application: - -* ``errorLevel`` - int - The level of errors you are interested in capturing. Use the - built-in php error constants, and bitmasks to select the level of error you - are interested in. -* ``trace`` - boolean - Include stack traces for errors in log files. Stack traces - will be included in the log after each error. This is helpful for finding - where/when errors are being raised. -* ``exceptionRenderer`` - string - The class responsible for rendering uncaught exceptions. - If you choose a custom class you should place the file for that class in app/Error. - This class needs to implement a ``render()`` method. -* ``log`` - boolean - When true, exceptions + their stack traces will be logged - to :php:class:`Cake\\Log\\Log`. -* ``skipLog`` - array - An array of exception classnames that should not be - logged. This is useful to remove NotFoundExceptions or other common, but - uninteresting logs messages. - -ErrorHandler by default, displays errors when ``debug`` > 0, and logs errors -when debug = 0. The type of errors captured in both cases is controlled by -``errorLevel``. The fatal error handler will be called independent of ``debug`` -level or ``errorLevel`` configuration, but the result will be different based on -``debug`` level. The default behavior for fatal errors is show a page to -internal server error (``debug`` disabled) or a page with the message, file and -line (``debug`` enabled). - -.. note:: - - If you use a custom error handler, the supported options will - depend on your handler. - -Creating your Own Error Handler -=============================== - -You can create an error handler out of any callback type. For example you could -use a class called ``AppError`` to handle your errors. By extending the -``BaseErrorHandler`` you can supply custom logic for handling errors. An example would be:: - - // In config/app.php - use App\Error\AppError; - - $errorHandler = new AppError(); - $errorHandler->register(); - - // In app/Error/AppError.php - namespace App\Error; - - use Cake\Error\BaseErrorHandler; - - class AppError extends BaseErrorHandler - { - public function _displayError($error, $debug) - { - echo 'There has been an error!'; - } - public function _displayException($exception) - { - echo 'There has been an exception!'; - } - } - -The ``BaseErrorHandler`` defines two abstract methods. ``_displayError`` is used when errors -are triggered. The ``_displayException`` method is called when there is an -uncaught exception. - - -Changing Fatal Error Behavior -============================= - -The default error handlers convert fatal errors into exceptions and re-use the -exception handling logic to render an error page. If you do not want to show the -standard error page, you can override it like:: - - // In config/app.php - use App\Error\AppError; - - $errorHandler = new AppError(); - $errorHandler->register(); - - // In app/Error/AppError.php - namespace App\Error; - - use Cake\Error\BaseErrorHandler; - - class AppError - { - // Other methods. - - public function handleFatalError($code, $description, $file, $line) - { - echo 'A fatal error has happened'; - } - } - -.. php:namespace:: Cake\Error - -Exception Classes -================= - -There are a number of exception classes in CakePHP. The built in exception -handling will capture any uncaught exceptions and render a useful page. -Exceptions that do not specifically use a 400 range code, will be treated as an -Internal Server Error. - -.. _built-in-exceptions: - -Built in Exceptions for CakePHP -=============================== - -There are several built-in exceptions inside CakePHP, outside of the -internal framework exceptions, there are several -exceptions for HTTP methods - -.. php:exception:: BadRequestException - - Used for doing 400 Bad Request error. - -.. php:exception::UnauthorizedException - - Used for doing a 401 Not found error. - -.. php:exception:: ForbiddenException - - Used for doing a 403 Forbidden error. - -.. php:exception:: NotFoundException - - Used for doing a 404 Not found error. - -.. php:exception:: MethodNotAllowedException - - Used for doing a 405 Method Not Allowed error. - -.. php:exception:: InternalErrorException - - Used for doing a 500 Internal Server Error. - -.. php:exception:: NotImplementedException - - Used for doing a 501 Not Implemented Errors. - -You can throw these exceptions from you controllers to indicate failure states, -or HTTP errors. An example use of the HTTP exceptions could be rendering 404 -pages for items that have not been found:: - - public function view($id) - { - $post = $this->Post->findById($id); - if (!$post) { - throw new NotFoundException('Could not find that post'); - } - $this->set('post', $post); - } - -By using exceptions for HTTP errors, you can keep your code both clean, and give -RESTful responses to client applications and users. - -In addition, the following framework layer exceptions are available, and will -be thrown from a number of CakePHP core components: - -.. php:exception:: MissingViewException - - The chosen view file could not be found. - -.. php:exception:: MissingLayoutException - - The chosen layout could not be found. - -.. php:exception:: MissingHelperException - - A helper was not found. - -.. php:exception:: MissingBehaviorException - - A configured behavior could not be found. - -.. php:exception:: MissingComponentException - - A configured component could not be found. - -.. php:exception:: MissingTaskException - - A configured task was not found. - -.. php:exception:: MissingShellException - - The shell class could not be found. - -.. php:exception:: MissingShellMethodException - - The chosen shell class has no method of that name. - -.. php:exception:: MissingDatabaseException - - The configured database is missing. - -.. php:exception:: MissingConnectionException - - A model's connection is missing. - -.. php:exception:: MissingTableException - - A model's table is missing. - -.. php:exception:: MissingActionException - - The requested controller action could not be found. - -.. php:exception:: MissingControllerException - - The requested controller could not be found. - -.. php:exception:: PrivateActionException - - Private action access. Either accessing - private/protected/_ prefixed actions, or trying - to access prefixed routes incorrectly. - -.. php:exception:: Exception - - Base exception class in CakePHP. All framework layer exceptions thrown by - CakePHP will extend this class. - -These exception classes all extend :php:exc:`Exception`. -By extending Exception, you can create your own 'framework' errors. -All of the standard Exceptions that CakePHP will throw also extend Exception. - -.. php:exception:: BaseException - - Base exception class in CakePHP. - All CakeExceptions and HttpExceptions above extend this class. - -.. php:method:: responseHeader($header = null, $value = null) - - See :php:func:`CakeResponse::header()` - -All Http and Cake exceptions extend the CakeBaseException class, which has a method -to add headers to the response. For instance when throwing a 405 MethodNotAllowedException -the rfc2616 says: - - "The response MUST include an Allow header containing a list of valid - methods for the requested resource." - -Using HTTP Exceptions in your Controllers -========================================= - -You can throw any of the HTTP related exceptions from your controller actions -to indicate failure states. For example:: - - public function view($id) - { - $post = $this->Post->read(null, $id); - if (!$post) { - throw new NotFoundException(); - } - $this->set(compact('post')); - } - -The above would cause the configured exception handler to catch and -process the :php:exc:`NotFoundException`. By default this will create an error page, -and log the exception. - -.. _error-views: - -Exception Renderer -================== - -.. php:class:: ExceptionRenderer(Exception $exception) - -The ExceptionRenderer class with the help of ``CakeErrorController`` takes care of rendering -the error pages for all the exceptions thrown by you application. - -The error page views are located at ``src/Template/Error/``. For all 4xx and 5xx errors -the view files ``error400.ctp`` and ``error500.ctp`` are used respectively. You can -customize them as per your needs. By default your ``src/Template/Layout/default.ctp`` is used -for error pages too. If for example, you want to use another layout ``src/Template/Layout/my_error.ctp`` -for your error pages. Simply edit the error views and add the statement -``$this->layout = 'my_error';`` to the ``error400.ctp`` and ``error500.ctp``. - -Each framework layer exception has its own view file located in the core templates but -you really don't need to bother customizing them as they are used only during development. -With debug turned off all framework layer exceptions are converted to ``InternalErrorException``. - -.. index:: application exceptions - -Creating your own Application Exceptions -======================================== - -You can create your own application exceptions using any of the built in `SPL -exceptions `_, ``Exception`` -itself, or :php:exc:`Cake\\Error\\Exception`. Application exceptions that -extend Exception or the SPL exceptions will be treated as 500 error in -production mode. :php:exc:`Cake\\Error\\Exception` is special in that all -:php:exc:`Cake\\Error\\Exception` objects are coerced into into either 500 or -404 errors depending on the code they use. When in development mode -:php:exc:`Cake\\Error\\Exception` objects simply need a new template that -matches the class name in order to provide useful information. If your -application contained the following exception:: - - use Cake\Error\Exception; - - class MissingWidgetException extends Exception - {}; - -You could provide nice development errors, by creating -``src/Template/Error/missing_widget.ctp``. When in production mode, the above -error would be treated as a 500 error. The constructor for :php:exc:`Cake\\Error\\Exception` -has been extended, allowing you to pass in hashes of data. These hashes are -interpolated into the the messageTemplate, as well as into the view that is used -to represent the error in development mode. This allows you to create data rich -exceptions, by providing more context for your errors. You can also provide a message -template which allows the native ``__toString()`` methods to work as normal:: - - - use Cake\Error\Exception; - - class MissingWidgetException extends Exception - { - protected $_messageTemplate = 'Seems that %s is missing.'; - } - - throw new MissingWidgetException(array('widget' => 'Pointy')); - - -When caught by the built in exception handler, you would get a ``$widget`` -variable in your error view template. In addition if you cast the exception -as a string or use its ``getMessage()`` method you will get -``Seems that Pointy is missing.``. This allows you easily and quickly create -your own rich development errors, just like CakePHP uses internally. - - -Creating Custom Status Codes ----------------------------- - -You can create custom HTTP status codes by changing the code used when -creating an exception:: - - throw new MissingWidgetHelperException('Its not here', 501); - -Will create a ``501`` response code, you can use any HTTP status code -you want. In development, if your exception doesn't have a specific -template, and you use a code equal to or greater than ``500`` you will -see the ``error500`` template. For any other error code you'll get the -``error400`` template. If you have defined an error template for your -custom exception, that template will be used in development mode. -If you'd like your own exception handling logic even in production, -see the next section. - - -Extending and Implementing your own Exception Handlers -====================================================== - -You can implement application specific exception handling in one of a -few ways. Each approach gives you different amounts of control over -the exception handling process. - -- Create and register your own custom error handlers. -- Extend the ``BaseErrorHandler`` provided by CakePHP. -- Set the ``exceptionRenderer`` option on the default error handler. - -In the next few sections, we will detail the various approaches and the benefits each has. - -Create and Register your own Exception Handler -============================================== - -Creating your own exception handler gives you full control over the exception -handling process. You will have to call ``set_exception_handler`` yourself in this situation. - -Extend the BaseErrorHandler -=========================== - -The :ref:`error-configuration` section has an example of this. - -Using the exceptionRenderer Option of the Default Handler -========================================================= - -If you don't want to take control of the exception handling, but want to change -how exceptions are rendered you can use the ``exceptionRenderer`` option in -config/app.php to choose a class that will render exception pages. By -default :php:class:`Cake\\Error\\ExceptionRenderer` is used. Your custom -exception renderer class should be placed in ``src/Error``. In a custom -exception rendering class you can provide specialized handling for application -specific errors:: - - // In app/Error/AppExceptionRenderer.php - namespace App\Error; - - use Cake\Error\ExceptionRenderer; - - class AppExceptionRenderer extends ExceptionRenderer - { - public function missingWidget($error) - { - echo 'Oops that widget is missing!'; - } - } - - -The above would handle any exceptions of the type ``MissingWidgetException``, -and allow you to provide custom display/handling logic for those application -exceptions. Exception handling methods get the exception being handled as -their argument. - -.. note:: - - Your custom renderer should expect an exception in its constructor, and - implement a render method. Failing to do so will cause additional errors. - - If you are using a custom exception handling this setting will have - no effect. Unless you reference it inside your implementation. - -Creating a Custom Controller to Handle Exceptions -------------------------------------------------- - -In your ExceptionRenderer sub-class, you can use the ``_getController`` -method to allow you to return a custom controller to handle your errors. -By default CakePHP uses ``CakeErrorController`` which omits a few of the normal -callbacks to help ensure errors always display. However, you may need a more -custom error handling controller in your application. By implementing -``_getController`` in your ``AppExceptionRenderer`` class, you can use any -controller you want:: - - namespace App\Error; - - use App\Controller\SuperCustomErrorController; - use Cake\Error\ExceptionRenderer; - - class AppExceptionRenderer extends ExceptionRenderer - { - protected function _getController($exception) - { - return new SuperCustomErrorController(); - } - } - -Alternatively, you could just override the core CakeErrorController, -by including one in ``src/Controller``. If you are using a custom -controller for error handling, make sure you do all the setup you need -in your constructor, or the render method. As those are the only methods -that the built-in ``ErrorHandler`` class directly call. - - -Logging Exceptions ------------------- - -Using the built-in exception handling, you can log all the exceptions that are -dealt with by ErrorHandler by setting the ``log`` option to true in your -config/app.php. Enabling this will log every exception to -:php:class:`Cake\\Log\\Log` and the configured loggers. - -.. note:: - - If you are using a custom exception handler this setting will have - no effect. Unless you reference it inside your implementation. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Error & Exception Handling - :keywords lang=en: stack traces,error constants,error array,default displays,anonymous functions,error handlers,default error,error level,exception handler,php error,error handler,write error,core classes,exception handling,configuration error,application code,callback,custom error,exceptions,bitmasks,fatal error + :title lang=es: Error & Exception Handling + :keywords lang=es: stack traces,error constants,error array,default displays,anonymous functions,error handlers,default error,error level,exception handler,php error,error handler,write error,core classes,exception handling,configuration error,application code,callback,custom error,exceptions,bitmasks,fatal error diff --git a/es/development/exceptions.rst b/es/development/exceptions.rst deleted file mode 100644 index 4d99d2024fc0118d7021f17e18b2a83845c5cb9d..0000000000000000000000000000000000000000 --- a/es/development/exceptions.rst +++ /dev/null @@ -1,8 +0,0 @@ -Excepciones -########### - -Mira la documentación en :doc:`/development/errors` para más información. - -.. meta:: - :title lang=es: Excepciones - :keywords lang=es: uncaught exceptions,stack traces,logic errors,anonymous functions,renderer,html page,error messages,flexibility,lib,array,cakephp,php diff --git a/es/development/rest.rst b/es/development/rest.rst index b854b1f11d4ad47fa36fd1b11ef4d20bc477463f..5566464f1ae2c89ba46b3c204303e4d406671d3a 100644 --- a/es/development/rest.rst +++ b/es/development/rest.rst @@ -2,157 +2,14 @@ REST #### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Many newer application programmers are realizing the need to open -their core functionality to a greater audience. Providing easy, -unfettered access to your core API can help get your platform -accepted, and allows for mashups and easy integration with other -systems. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -While other solutions exist, REST is a great way to provide easy -access to the logic you've created in your application. It's -simple, usually XML-based (we're talking simple XML, nothing like a -SOAP envelope), and depends on HTTP headers for direction. Exposing -an API via REST in CakePHP is simple. - -The Simple Setup -================ - -The fastest way to get up and running with REST is to add a few lines to setup -:ref:`resource routes ` in your config/routes.php file. - -Once the router has been set up to map REST requests to certain -controller actions, we can move on to creating the logic in our -controller actions. A basic controller might look something like -this:: - - // src/Controller/RecipesController.php - class RecipesController extends AppController - { - - public $components = array('RequestHandler'); - - public function index() - { - $recipes = $this->Recipes->find('all')->toArray(); - $this->set(array( - 'recipes' => $recipes, - '_serialize' => array('recipes') - )); - } - - public function view($id) - { - $recipe = $this->Recipes->findById($id)->toArray(); - $this->set(array( - 'recipe' => $recipe, - '_serialize' => array('recipe') - )); - } - - public function edit($id) - { - $recipe = $this->Recipes->get($id); - if ($this->request->is(['post', 'put'])) { - $this->Recipes->patchEntity($recipe, $this->request->data); - if ($this->Recipes->save($this->request->data)) { - $message = 'Saved'; - } else { - $message = 'Error'; - } - } - $this->set(array( - 'message' => $message, - '_serialize' => array('message') - )); - } - - public function delete($id) - { - $recipe = $this->Recipes->get($id); - if ($this->Recipes->delete($recipe)) { - $message = 'Deleted'; - } else { - $message = 'Error'; - } - $this->set(array( - 'message' => $message, - '_serialize' => array('message') - )); - } - } - -RESTful controllers often use parsed extensions to serve up different views -based on different kinds of requests. Since we're dealing with REST requests, -we'll be making XML views. You can also easily make JSON views using CakePHP's -built-in :doc:`/views/json-and-xml-views`. By using the built in -:php:class:`XmlView` we can define a ``_serialize`` view variable. This special -view variable is used to define which view variables ``XmlView`` should -serialize into XML. - -If we wanted to modify the data before it is converted into XML we should not -define the ``_serialize`` view variable, and instead use view files. We place -the REST views for our RecipesController inside ``src/Template/recipes/xml``. We can also use -the :php:class:`Xml` for quick-and-easy XML output in those views. Here's what -our index view might look like:: - - // app/View/Recipes/xml/index.ctp - // Do some formatting and manipulation on - // the $recipes array. - $xml = Xml::fromArray(array('response' => $recipes)); - echo $xml->asXML(); - -When serving up a specific content type using parseExtensions(), -CakePHP automatically looks for a view helper that matches the type. -Since we're using XML as the content type, there is no built-in helper, -however if you were to create one it would automatically be loaded -for our use in those views. - -The rendered XML will end up looking something like this:: - - - - 234 - 2008-06-13 - 2008-06-14 - - 23423 - Billy - Bob - - - 245 - Yummy yummmy - - - ... - - -Creating the logic for the edit action is a bit trickier, but not by much. Since -you're providing an API that outputs XML, it's a natural choice to receive XML -as input. Not to worry, the -:php:class:`Cake\\Controller\\Component\\RequestHandler` and -:php:class:`Cake\\Routing\\Router` classes make things much easier. If a POST or -PUT request has an XML content-type, then the input is run through CakePHP's -:php:class:`Xml` class, and the array representation of the data is assigned to -``$this->request->data``. Because of this feature, handling XML and POST data in -parallel is seamless: no changes are required to the controller or model code. -Everything you need should end up in ``$this->request->data``. - -Accepting Input in Other Formats -================================ - -Typically REST applications not only output content in alternate data formats -they also accept data in different formats. In CakePHP, the -:php:class:`RequestHandlerComponent` helps facilitate this. By default -it will decode any incoming JSON/XML input data for POST/PUT requests -and supply the array version of that data in ``$this->request->data``. -You can also wire in additional deserializers for alternate formats if you -need them, using :php:meth:`RequestHandler::addInputType()` + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: REST - :keywords lang=en: application programmers,default routes,core functionality,result format,mashups,recipe database,request method,easy access,config,soap,recipes,logic,audience,cakephp,running,api + :title lang=es: REST + :keywords lang=es: application programmers,default routes,core functionality,result format,mashups,recipe database,request method,easy access,config,soap,recipes,logic,audience,cakephp,running,api diff --git a/es/development/routing.rst b/es/development/routing.rst index cc34e03f1fd355aa2679432991fe791334affe56..93abd63a705f1839434cbd5f465061f6cb1dd034 100644 --- a/es/development/routing.rst +++ b/es/development/routing.rst @@ -1,1031 +1,25 @@ Routing ####### -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - .. php:namespace:: Cake\Routing .. php:class:: Router -Routing is a feature that maps URLs to controller actions. It was -added to CakePHP to make pretty URLs more configurable and -flexible. Using Apache's mod\_rewrite is not required for using -routes, but it will make your address bar look much more tidy. - -Routing in CakePHP also encompasses the idea of reverse routing, -where an array of parameters can be reversed into a string URL. -By using reverse routing, you can easily re-factor your application's -URL structure without having to update all your code. - -Routes in an application are configured in ``config/routes.php``. -Routes are processed based on the scopes they are defined in. Within each scope -routes are processed top to bottom, so you should place the most frequently used -routes at the top of each scope. - -.. index:: routes.php - -Quick Tour -========== - -This section will teach you by example the most common uses of the CakePHP -Router. Typically you want to display something as a landing page, so you add -this to your **routes.php** file:: - - use Cake\Routing\Router; - - Router::connect('/', ['controller' => 'Articles', 'action' => 'index']); - -This will execute the index method in the ``ArticlesController`` when the homepage -of your site is visited. Sometimes you need dynamic routes that will accept -multiple parameters, this would be the case, for example of a route for viewing -an article's content:: - - Router::connect('/articles/*', ['controller' => 'Articles', 'action' => 'view']); - -The above route will accept any url looking like ``/articles/15`` and invoke the -method ``view(15)`` in the ``ArticlesController``. This will not, though, -prevent people from trying to access URLs looking like ``/articles/foobar``. If -you wish, you can restring some parameters to conform to a regular expression:: - - Router::connect( - '/articles/:id', - ['controller' => 'Articles', 'action' => 'view'], - ['id' => '\d+', 'pass' => ['id']] - ); - -The previous example changed the star matcher by a new placeholder ``:id``. -Using placeholders allows us to validate parts of the url, in this case we used -the ``\d+`` regular expression so that only digits are matched. Finally, we told -the Router to treat the ``id`` placeholder as a function argument to the -``view()`` function by specifying the ``pass`` option. More on using this -options later. - -The CakePHP Router can also match routes in reverse. That means that from an -array containing similar parameters, it is capable of generation a URL string:: - - use Cake\Routing\Router; - - echo Router::url(['controller' => 'Articles', 'action' => 'view', 'id' => 15]); - // Will output - /articles/15 - -Routes can also be labelled with a unique name, this allows you to quickly -reference them when building links instead of specifying each of the routing -parameters:: - - use Cake\Routing\Router; - - Router::connect( - '/login', - ['controller' => 'Users', 'action' => 'login'], - ['_name' => 'login'] - ); - - echo Router::url('login'); - // Will output - /login - -The application skeleton comes with a few routes to get you started. Once you've -added your own routes, you can remove the default routes if you don't need them. - -.. index:: :controller, :action, :plugin -.. index:: greedy star, trailing star -.. _connecting-routes: -.. _routes-configuration: - -Connecting Routes -================= - -.. php:staticmethod:: connect($route, $defaults = [], $options = []) - -Defining your own routes allows you to define how your application will respond -to a given URL. Routes are defined in the ``config/routes.php`` file. - -To keep your code :term:`DRY` you can should use 'routing scopes'. Routing -scopes not only let you keep your code DRY, they also help Router optimize its -operation. As seen above you can also use ``Router::connect()`` to connect -routes. This method defaults to the ``/`` scope. To create a scope and connect -some routes we'll use the ``scope()`` method:: - - // In config/routes.php - Router::scope('/', function($routes) { - $routes->connect('/:controller', ['action' => 'index']); - $routes->connect('/:controller/:action/*'); - }); - -The ``connect()`` method takes up to three parameters: the URL template you wish -to match, the default values for your route elements, and the options for the -route. Options frequently include regular expression rules to help the router -match elements in the URL. - -The basic format for a route definition is:: - - $routes->connect( - 'URL template', - ['default' => 'defaultValue'], - ['option' => 'matchingRegex'] - ); - -The first parameter is used to tell the router what sort of URL you're trying to -control. The URL is a normal slash delimited string, but can also contain -a wildcard (\*) or :ref:`route-elements`. Using a wildcard tells the router -that you are willing to accept any additional arguments supplied. Routes without -a \* only match the exact template pattern supplied. - -Once you've specified a URL, you use the last two parameters of ``connect()`` to -tell CakePHP what to do with a request once it has been matched. The second -parameter is an associative array. The keys of the array should be named after -the route elements the URL template represents. The values in the array are the -default values for those keys. Let's look at some basic examples before we -start using the third parameter of connect():: - - $routes->connect( - '/pages/*', - ['controller' => 'Pages', 'action' => 'display'] - ); - -This route is found in the routes.php file distributed with CakePHP. It matches -any URL starting with ``/pages/`` and hands it to the ``display()`` action of -the ``PagesController();``. A request to ``/pages/products`` would be mapped to -``PagesController->display('products')``. - -In addition to the greedy star ``/*`` there is also the ``/**`` trailing star -syntax. Using a trailing double star, will capture the remainder of a URL as a -single passed argument. This is useful when you want to use an argument that -included a ``/`` in it:: - - $routes->connect( - '/pages/**', - ['controller' => 'Pages', 'action' => 'show'] - ); - -The incoming URL of ``/pages/the-example-/-and-proof`` would result in a single -passed argument of ``the-example-/-and-proof``. - -You can use the second parameter of ``connect()`` to provide any routing -parameters that are composed of the default values of the route:: - - $routes->connect( - '/government', - ['controller' => 'Pages', 'action' => 'display', 5] - ); - -This example shows how you can use the second parameter of ``connect()`` to -define default parameters. If you built a site that features products for -different categories of customers, you might consider creating a route. This -allows you link to ``/government`` rather than ``/pages/display/5``. - -Another common use for the Router is to define an "alias" for a -controller. Let's say that instead of accessing our regular URL at -``/users/some_action/5``, we'd like to be able to access it by -``/cooks/some_action/5``. The following route easily takes care of -that:: - - $routes->connect( - '/cooks/:action/*', ['controller' => 'Users'] - ); - -This is telling the Router that any URL beginning with ``/cooks/`` should be -sent to the users controller. The action called will depend on the value of the -``:action`` parameter. By using :ref:`route-elements`, you can create variable -routes, that accept user input or variables. The above route also uses the -greedy star. The greedy star indicates to ``Router`` that this route -should accept any additional positional arguments given. These arguments will be -made available in the :ref:`passed-arguments` array. - -When generating URLs, routes are used too. Using -``['controller' => 'Users', 'action' => 'some_action', 5]`` as -a url will output ``/cooks/some_action/5`` if the above route is the -first match found. - -.. _route-elements: - -Route Elements --------------- - -You can specify your own route elements and doing so gives you the -power to define places in the URL where parameters for controller -actions should lie. When a request is made, the values for these -route elements are found in ``$this->request->params`` in the controller. -When you define a custom route element, you can optionally specify a regular -expression - this tells CakePHP how to know if the URL is correctly formed or -not. If you choose to not provide a regular expression, any non ``/`` character will be -treated as part of the parameter:: - - $routes->connect( - '/:controller/:id', - ['action' => 'view'], - ['id' => '[0-9]+'] - ); - -The above example illustrates how to create a quick way to view -models from any controller by crafting a URL that looks like -``/controllername/:id``. The URL provided to ``connect()`` specifies two -route elements: ``:controller`` and ``:id``. The ``:controller`` element -is a CakePHP default route element, so the router knows how to match and -identify controller names in URLs. The ``:id`` element is a custom -route element, and must be further clarified by specifying a -matching regular expression in the third parameter of connect(). - -CakePHP does not automatically produce lowercased urls when using the -``:controller`` parameter. If you need this, the above example could be -rewritten like so:: - - $routes->connect( - '/:controller/:id', - ['action' => 'view'], - ['id' => '[0-9]+', 'routeClass' => 'Cake\Routing\Route\InflectedRoute'] - ); - -The special ``InflectedRoute`` class will make sure that the ``:controller`` and -``:plugin`` parameters are correctly lowercased. - -.. note:: - - Patterns used for route elements must not contain any capturing - groups. If they do, Router will not function correctly. - -Once this route has been defined, requesting ``/apples/5`` would call the view() -method of the ApplesController. Inside the view() method, you would need to -access the passed ID at ``$this->request->params['id']``. - -If you have a single controller in your application and you do not want the -controller name to appear in the URL, you can map all URLs to actions in your -controller. For example, to map all URLs to actions of the ``home`` controller, -e.g have URLs like ``/demo`` instead of ``/home/demo``, you can do the -following:: - - $routes->connect('/:action', ['controller' => 'Home']); - -If you would like to provide a case insensitive URL, you can use regular -expression inline modifiers:: - - $routes->connect( - '/:userShortcut', - ['controller' => 'Teachers', 'action' => 'profile', 1], - ['userShortcut' => '(?i:principal)'] - ); - -One more example, and you'll be a routing pro:: - - $routes->connect( - '/:controller/:year/:month/:day', - ['action' => 'index'], - [ - 'year' => '[12][0-9]{3}', - 'month' => '0[1-9]|1[012]', - 'day' => '0[1-9]|[12][0-9]|3[01]' - ] - ); - -This is rather involved, but shows how powerful routes can be The URL supplied -has four route elements. The first is familiar to us: it's a default route -element that tells CakePHP to expect a controller name. - -Next, we specify some default values. Regardless of the controller, -we want the index() action to be called. - -Finally, we specify some regular expressions that will match years, -months and days in numerical form. Note that parenthesis (grouping) -are not supported in the regular expressions. You can still specify -alternates, as above, but not grouped with parenthesis. - -Once defined, this route will match ``/articles/2007/02/01``, -``/articles/2004/11/16``, handing the requests to -the index() actions of their respective controllers, with the date -parameters in ``$this->request->params``. - -There are several route elements that have special meaning in -CakePHP, and should not be used unless you want the special meaning - -* ``controller`` Used to name the controller for a route. -* ``action`` Used to name the controller action for a route. -* ``plugin`` Used to name the plugin a controller is located in. -* ``prefix`` Used for :ref:`prefix-routing` -* ``_ext`` Used for :ref:`file-extensions` routing. -* ``_base`` Set to false to remove the base path from the generated URL. If your application - is not in the root directory, this can be used to generate URLs that are 'cake relative'. - cake relative URLs are required when using requestAction. -* ``_scheme`` Set to create links on different schemes like `webcal` or `ftp`. Defaults - to the current scheme. -* ``_host`` Set the host to use for the link. Defaults to the current host. -* ``_port`` Set the port if you need to create links on non-standard ports. -* ``_full`` If true the `FULL_BASE_URL` constant will be prepended to generated URLs. -* ``#`` Allows you to set URL hash fragments. -* ``_ssl`` Set to true to convert the generated URL to https, or false to force http. -* ``_method`` Define the HTTP verb/method to use. Useful when working with - :ref:`resource-routes`. -* ``_name`` Name of route. If you have setup named routes, you can use this key - to specify it. - -Passing Parameters to Action ----------------------------- - -When connecting routes using :ref:`route-elements` you may want -to have routed elements be passed arguments instead. By using the 3rd -argument of :php:meth:`Cake\\Routing\\Router::connect()` you can define which route -elements should also be made available as passed arguments:: - - // SomeController.php - public function view($articleId = null, $slug = null) - { - // Some code here... - } - - // routes.php - Router::connect( - '/blog/:id-:slug', // E.g. /blog/3-CakePHP_Rocks - ['controller' => 'Blog', 'action' => 'view'], - [ - // order matters since this will simply map ":id" to $articleId in your action - 'pass' => ['id', 'slug'], - 'id' => '[0-9]+' - ] - ); - -And now, thanks to the reverse routing capabilities, you can pass -in the URL array like below and CakePHP will know how to form the URL -as defined in the routes:: - - // view.ctp - // This will return a link to /blog/3-CakePHP_Rocks - echo $this->Html->link('CakePHP Rocks', [ - 'controller' => 'Blog', - 'action' => 'view', - 'id' => 3, - 'slug' => 'CakePHP_Rocks' - ]); - -.. _named-routes: - -Using Named Routes ------------------- - -Sometimes you'll find typing out all the URL parameters for a route too verbose, -or you'd like to take advantage of the performance improvements that named routes -have. When connecting routes you can specifiy a ``_name`` option, this option -can be used in reverse routing to identify the route you want to use:: - - // Connect a route with a name. - $routes->connect( - '/login', - ['controller' => 'Users', 'action' => 'login'], - ['_name' => 'login'] - ); - - // Generate a URL using a named route. - $url = Router::url(['_name' => 'login']); - - // Generate a URL using a named route, - // with some query string args. - $url = Router::url(['_name' => 'login', 'username' => 'jimmy']); - -If your route template contains any route elements like ``:controller`` you'll -need to supply those as part of the options to ``Router::url()``. - -.. index:: admin routing, prefix routing -.. _prefix-routing: - -Prefix Routing --------------- - -.. php:staticmethod:: prefix($name, $callback) - -Many applications require an administration section where -privileged users can make changes. This is often done through a -special URL such as ``/admin/users/edit/5``. In CakePHP, prefix routing -can be enabled by using the ``prefix`` scope method:: - - Router::prefix('admin', function($routes) { - // All routes here will be prefixed with `/admin` - // And have the prefix => admin route element added. - $routes->connect('/:controller', ['action' => 'index']); - $routes->connect('/:controller/:action/*'); - }); - -Prefixes are mapped to sub-namespaces in your application's ``Controller`` -namespace. By having prefixes as separate controllers you can create smaller and -simpler controllers. Behavior that is common to the prefixed and non-prefixed -controllers can be encapsulated using inheritance, -:doc:`/controllers/components`, or traits. Using our users example, accessing -the URL ``/admin/users/edit/5`` would call the ``edit`` method of our -``App\Controller\Admin\UsersController`` passing 5 as the first parameter. The -view file used would be ``src/Template/Admin/Users/edit.ctp`` - -You can map the URL /admin to your ``index`` action of pages controller using -following route:: - - Router::prefix('admin', function($routes) { - // Because you are in the admin scope, - // you do not need to include the /admin prefix - // or the admin route element. - $routes->connect('/', ['controller' => 'Pages', 'action' => 'index']); - }); - -You can define prefixes inside plugin scopes as well:: - - Router::plugin('DebugKit', function($routes) { - $routes->prefix('admin', function($routes) { - $routes->connect('/:controller'); - }); - }); - -The above would create a route template like ``/debug_kit/admin/:controller``. -The connected route would have the ``plugin`` and ``prefix`` route elements set. - -When defining prefixes, you can nest multiple prefixes if necessary:: - - Router::prefix('manager', function($routes) { - $routes->prefix('admin', function($routes) { - $routes->connect('/:controller'); - }); - }); - -The above would create a route template like ``/manager/admin/:controller``. -The connected route would have the ``prefix`` route element set to -``manager/admin``. - -The current prefix will be available from the controller methods through -``$this->request->params['prefix']`` - -When using prefix routes it's important to set the prefix option. Here's how to -build this link using the HTML helper:: - - // Go into a prefixed route. - echo $this->Html->link( - 'Manage articles', - ['prefix' => 'manager', 'controller' => 'Articles', 'action' => 'add'] - ); - - // Leave a prefix - echo $this->Html->link( - 'View Post', - ['prefix' => false, 'controller' => 'Articles', 'action' => 'view', 5] - ); - .. note:: + La documentación no es compatible actualmente con el idioma español en esta página. - You should connect prefix routes *before* you connect fallback routes. - -.. index:: plugin routing - -Plugin Routing --------------- - -.. php:staticmethod:: plugin($name, $options = [], $callback) - -Plugin routes are most easily created using the ``plugin()`` method. This method -creates a new routing scope for the plugin's routes:: - - Router::plugin('DebugKit', function($routes) { - // Routes connected here are prefixed with '/debug_kit' and - // have the plugin route element set to 'DebugKit'. - $routes->connect('/:controller'); - }); - -When creating plugin scopes, you can customize the path element used with the -``path`` option:: - - Router::plugin('DebugKit', ['path' => '/debugger'], function($routes) { - // Routes connected here are prefixed with '/debugger' and - // have the plugin route element set to 'DebugKit'. - $routes->connect('/:controller'); - }); - -When using scopes you can nest plugin scopes within prefix scopes:: - - Router::prefix('admin', function($routes) { - $routes->plugin('DebugKit', function($routes) { - $routes->connect('/:controller'); - }); - }); - -The above would create a route that looks like ``/admin/debug_kit/:controller``. -It would have the ``prefix``, and ``plugin`` route elements set. - -You can create links that point to a plugin, by adding the plugin key to your -URL array:: - - echo $this->Html->link( - 'New todo', - ['plugin' => 'Todo', 'controller' => 'TodoItems', 'action' => 'create'] - ); - -Conversely if the active request is a plugin request and you want to create -a link that has no plugin you can do the following:: - - echo $this->Html->link( - 'New todo', - ['plugin' => null, 'controller' => 'Users', 'action' => 'profile'] - ); - -By setting ``plugin => null`` you tell the Router that you want to -create a link that is not part of a plugin. - -.. index:: file extensions -.. _file-extensions: - -Routing File Extensions ------------------------ - -.. php:staticmethod:: parseExtensions($extensions, $merge = true) - -To handle different file extensions with your routes, you need one -extra line in your routes config file:: - - Router::parseExtensions(['html', 'rss']); - -This will enable the named extensions for all routes connected **after** this -method call. Any routes connected prior to it will not inerit the extensions. -You can set extensions per scope as well:: - - Router::scope('/api', function($routes) { - $routes->extensions(['json', 'xml']); - }); - -Setting the extensions should be the first thing you do in a scope, as the -extensions will only be applied to routes connected **after** the extensions are -set. - -By using extensions, you tell the router to remove any matching file extensions, -and then parse what remains. If you want to create a URL such as -/page/title-of-page.html you would create your route using:: - - Router::scope('/api', function($routes) { - $routes->extensions(['json', 'xml']); - $routes->connect( - '/page/:title', - ['controller' => 'Pages', 'action' => 'view'], - [ - 'pass' => ['title'] - ] - ); - }); - -Then to create links which map back to the routes simply use:: - - $this->Html->link( - 'Link title', - ['controller' => 'Pages', 'action' => 'view', 'title' => 'super-article', '_ext' => 'html'] - ); - -File extensions are used by :doc:`/core-libraries/components/request-handling` -to do automatic view switching based on content types. - -.. _resource-routes: - -Creating RESTful Routes -======================= - -.. php:staticmethod:: mapResources($controller, $options) - -Router makes it easy to generate RESTful routes for your controllers. -If we wanted to allow REST access to a recipe database, we'd do -something like this:: - - // In config/routes.php... - - Router:scope('/', function($routes) { - $routes->extensions(['json']); - $routes->resources('recipes'); - }); - -The first line sets up a number of default routes for easy REST -access where method specifies the desired result format (e.g. xml, -json, rss). These routes are HTTP Request Method sensitive. - -=========== ===================== ============================== -HTTP format URL.format Controller action invoked -=========== ===================== ============================== -GET /recipes.format RecipesController::index() ------------ --------------------- ------------------------------ -GET /recipes/123.format RecipesController::view(123) ------------ --------------------- ------------------------------ -POST /recipes.format RecipesController::add() ------------ --------------------- ------------------------------ -PUT /recipes/123.format RecipesController::edit(123) ------------ --------------------- ------------------------------ -PATCH /recipes/123.format RecipesController::edit(123) ------------ --------------------- ------------------------------ -DELETE /recipes/123.format RecipesController::delete(123) -=========== ===================== ============================== - -CakePHP's Router class uses a number of different indicators to -detect the HTTP method being used. Here they are in order of -preference: - -#. The \_method POST variable -#. The X\_HTTP\_METHOD\_OVERRIDE -#. The REQUEST\_METHOD header - -The \_method POST variable is helpful in using a browser as a -REST client (or anything else that can do POST easily). Just set -the value of \_method to the name of the HTTP request method you -wish to emulate. - -Creating Nested Resources -------------------------- - -Once you have connected resources in a scope, you can connect routes for -sub-resources as well. Sub-resource routes will be prepended by the original -resource name and a id parameter. For example:: - - Router::scope('/api', function($routes) { - $routes->resources('Articles', function($routes) { - $routes->resources('Comments'); - }); - }); - -Will generate resource routes for both ``articles`` and ``comments``. The -comments routes will look like:: - - /api/articles/:article_id/comments - /api/articles/:article_id/comments/:id - -.. note:: - - While you can nest resources as deeply as you require, it is not recommended to - nest more than 2 resources together. - -Limiting the Routes Created ---------------------------- - -By default CakePHP will connect 6 routes for each resource. If you'd like to -only connect specific resource routes you can use the ``only`` option:: - - $routes->resources('Articles', [ - 'only' => ['index', 'view'] - ]); - -Would create read only resource routes. The route names are ``create``, -``update``, ``view``, ``index``, and ``delete``. - -Changing the Controller Actions Used ------------------------------------- - -You may need to change the controller action names that are used when connecting -routes. For example, if your ``edit`` action is called ``update`` you can use -the ``actions`` key to rename the actions used:: - - $routes->resources('Articles', [ - 'actions' => ['update' => 'update', 'add' => 'create'] - ]); - -The above would use ``update`` for the update action, and ``create`` instead of -``add``. - -.. _custom-rest-routing: - -Custom Route Classes for Resource Routes ----------------------------------------- - -You can provide ``connectOptions`` key in the ``$options`` array for -``resources()`` to provide custom setting used by ``connect()``:: - - Router::scope('/', function($routes) { - $routes->resources('books', array( - 'connectOptions' => array( - 'routeClass' => 'ApiRoute', - ) - ); - }); - -.. index:: passed arguments -.. _passed-arguments: - -Passed Arguments -================ - -Passed arguments are additional arguments or path segments that are -used when making a request. They are often used to pass parameters -to your controller methods. :: - - http://localhost/calendars/view/recent/mark - -In the above example, both ``recent`` and ``mark`` are passed arguments to -``CalendarsController::view()``. Passed arguments are given to your controllers -in three ways. First as arguments to the action method called, and secondly they -are available in ``$this->request->params['pass']`` as a numerically indexed -array. When using custom routes you can force particular parameters to go into -the passed arguments as well. - -If you were to visit the previously mentioned URL, and you -had a controller action that looked like:: - - CalendarsController extends AppController { - public function view($arg1, $arg2) - { - debug(func_get_args()); - } - } - -You would get the following output:: - - Array - ( - [0] => recent - [1] => mark - ) - -This same data is also available at ``$this->request->params['pass']`` -and ``$this->passedArgs`` in your controllers, views, and helpers. -The values in the pass array are numerically indexed based on the -order they appear in the called URL:: - - debug($this->request->params['pass']); - -Either of the above would output:: - - Array - ( - [0] => recent - [1] => mark - ) - -When generating URLs, using a :term:`routing array` you add passed -arguments as values without string keys in the array:: - - ['controller' => 'Articles', 'action' => 'view', 5] - -Since ``5`` has a numeric key, it is treated as a passed argument. - -Generating URLs -=============== - -.. php:staticmethod:: url($url = null, $full = false) - -Generating URLs or Reverse routing is a feature in CakePHP that is used to allow you to -easily change your URL structure without having to modify all your code. -By using :term:`routing arrays ` to define your URLs, you can -later configure routes and the generated URLs will automatically update. - -If you create URLs using strings like:: - - $this->Html->link('View', '/articles/view/' . $id); - -And then later decide that ``/articles`` should really be called -'articles' instead, you would have to go through your entire -application renaming URLs. However, if you defined your link like:: - - $this->Html->link( - 'View', - ['controller' => 'Articles', 'action' => 'view', $id] - ); - -Then when you decided to change your URLs, you could do so by defining a -route. This would change both the incoming URL mapping, as well as the -generated URLs. - -When using array URLs, you can define both query string parameters and -document fragments using special keys:: - - Router::url([ - 'controller' => 'Articles', - 'action' => 'index', - '?' => ['page' => 1], - '#' => 'top' - ]); - - // Will generate a URL like. - /articles/index?page=1#top - -Router will also convert any unknown parameters in a routing array to -querystring parameters. The ``?`` is offered for backwards compatibility with -older versions of CakePHP. - -You can also use any of the special route elements when generating URLs: - -* ``_ext`` Used for :ref:`file-extensions` routing. -* ``_base`` Set to false to remove the base path from the generated URL. If your application - is not in the root directory, this can be used to generate URLs that are 'cake relative'. - cake relative URLs are required when using requestAction. -* ``_scheme`` Set to create links on different schemes like `webcal` or `ftp`. Defaults - to the current scheme. -* ``_host`` Set the host to use for the link. Defaults to the current host. -* ``_port`` Set the port if you need to create links on non-standard ports. -* ``_full`` If true the `FULL_BASE_URL` constant will be prepended to generated URLs. -* ``_ssl`` Set to true to convert the generated URL to https, or false to force http. -* ``_name`` Name of route. If you have setup named routes, you can use this key - to specify it. - -.. _redirect-routing: - -Redirect Routing -================ - -.. php:staticmethod:: redirect($route, $url, $options = []) - -Redirect routing allows you to issue HTTP status 30x redirects for -incoming routes, and point them at different URLs. This is useful -when you want to inform client applications that a resource has moved -and you don't want to expose two URLs for the same content - -Redirection routes are different from normal routes as they perform an actual -header redirection if a match is found. The redirection can occur to -a destination within your application or an outside location:: - - $routes->redirect( - '/home/*', - ['controller' => 'Articles', 'action' => 'view'], - ['persist' => true] - // Or ['persist'=>['id']] for default routing where the - // view action expects $id as an argument. - ); - -Redirects ``/home/*`` to ``/articles/view`` and passes the parameters to -``/articles/view``. Using an array as the redirect destination allows -you to use other routes to define where a URL string should be -redirected to. You can redirect to external locations using -string URLs as the destination:: - - $routes->redirect('/articles/*', 'http://google.com', ['status' => 302]); - -This would redirect ``/articles/*`` to ``http://google.com`` with a -HTTP status of 302. - -.. _custom-route-classes: - -Custom Route Classes -==================== - -Custom route classes allow you to extend and change how individual routes parse -requests and handle reverse routing. Route classes have a few conventions: - -* Route classes are expected to be found in the ``Routing\\Route`` namespace of your application or plugin. -* Route classes should extend :php:class:`Cake\\Routing\\Route`. -* Route classes should implement one or both of ``match()`` and/or ``parse()``. - -The ``parse()`` method is used to parse an incoming URL. It should generate an -array of request parameters that can be resolved into a controller & action. -Return ``false`` from this method to indicate a match failure. - -The ``match()`` method is used to match an array of URL parameters and create a string URL. -If the URL parameters do not match the route ``false`` should be returned. - -You can use a custom route class when making a route by using the ``routeClass`` -option:: - - Router::connect( - '/:slug', - ['controller' => 'Articles', 'action' => 'view'], - ['routeClass' => 'SlugRoute'] - ); - -This route would create an instance of ``SlugRoute`` and allow you -to implement custom parameter handling. You can use plugin route classes using -standard :term:`plugin syntax`. - -Handling Named Parameters in URLs -================================= - -Although named parameters were removed in CakePHP 3.0, applications may have -published URLs containing them. You can continue to accept URLs containing -named parameters. - -In your controller's ``beforeFilter()`` method you can call -``parseNamedParams()`` to extract any named parameters from the passed -arguments:: - - public function beforeFilter() - { - parent::beforeFilter(); - Router::parseNamedParams($this->request); - } - -This will populate ``$this->request->params['named']`` with any named parameters -found in the passed arguments. Any passed argument that was interpreted as a -named parameter, will be removed from the list of passed arguments. - -.. _request-action: - -RequestActionTrait -================== - -.. php:trait:: RequestActionTrait - - This trait allows classes which include it to create sub-requests or - request actions. - -.. php:method:: requestAction(string $url, array $options) - - This function calls a controller's action from any location and - returns data from the action. The ``$url`` passed is a - CakePHP-relative URL (/controllername/actionname/params). To pass - extra data to the receiving controller action add to the $options - array. - - .. note:: - - You can use ``requestAction()`` to retrieve a fully rendered view - by passing 'return' in the options: - ``requestAction($url, ['return']);``. It is important to note - that making a requestAction using 'return' from a controller method - can cause script and css tags to not work correctly. - - .. warning:: - - If used without caching ``requestAction`` can lead to poor - performance. It is seldom appropriate to use in a controller. - - ``requestAction`` is best used in conjunction with (cached) - elements – as a way to fetch data for an element before rendering. - Let's use the example of putting a "latest comments" element in the - layout. First we need to create a controller function that will - return the data:: - - // Controller/CommentsController.php - class CommentsController extends AppController - { - public function latest() - { - if (!$this->request->is('requested')) { - throw new ForbiddenException(); - } - return $this->Comments->find('all', [ - 'order' => 'Comment.created DESC', - 'limit' => 10 - ]); - } - } - - You should always include checks to make sure your requestAction methods are - actually originating from ``requestAction``. Failing to do so will allow - requestAction methods to be directly accessible from a URL, which is - generally undesirable. - - If we now create a simple element to call that function:: - - // View/Element/latest_comments.ctp - - $comments = $this->requestAction('/comments/latest'); - foreach ($comments as $comment) { - echo $comment->title; - } - - We can then place that element anywhere to get the output - using:: - - echo $this->element('latest_comments'); - - Written in this way, whenever the element is rendered, a request - will be made to the controller to get the data, the data will be - processed, and returned. However in accordance with the warning - above it's best to make use of element caching to prevent needless - processing. By modifying the call to element to look like this:: - - echo $this->element('latest_comments', [], ['cache' => '+1 hour']); - - The ``requestAction`` call will not be made while the cached - element view file exists and is valid. - - In addition, requestAction now takes array based cake style URLs:: - - echo $this->requestAction( - ['controller' => 'Articles', 'action' => 'featured'], - ['return'] - ); - - The URL based array are the same as the ones that :php:meth:`HtmlHelper::link()` - uses with one difference - if you are using passed parameters, you must put them - in a second array and wrap them with the correct key. This is because - requestAction merges the extra parameters (requestAction's 2nd parameter) - with the ``request->params`` member array and does not explicitly place them - under the ``pass`` key. Any additional keys in the ``$option`` array will - be made available in the requested action's ``request->params`` property:: - - echo $this->requestAction('/articles/view/5'); - - As an array in the requestAction would then be:: - - echo $this->requestAction( - ['controller' => 'Articles', 'action' => 'view', 5], - ); - - You can also pass querystring arguments, post data or cookies using the - appropriate keys. Cookies can be passed using the ``cookies`` key. - Get parameters can be set with ``query`` and post data can be sent - using the ``post`` key:: - - $vars = $this->requestAction('/articles/popular', [ - 'query' => ['page' = > 1], - 'cookies' => ['remember_me' => 1], - ]); - - .. note:: + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. - Unlike other places where array URLs are analogous to string URLs, - requestAction treats them differently. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. - When using an array URL in conjunction with requestAction() you - must specify **all** parameters that you will need in the requested - action. This includes parameters like ``$this->request->data``. In addition - to passing all required parameters, passed arguments must be done - in the second array as seen above. +.. toctree:: + :glob: + :maxdepth: 1 + /development/dispatch-filters .. meta:: - :title lang=en: Routing - :keywords lang=en: controller actions,default routes,mod rewrite,code index,string url,php class,incoming requests,dispatcher,url url,meth,maps,match,parameters,array,config,cakephp,apache,router + :title lang=es: Routing + :keywords lang=es: controller actions,default routes,mod rewrite,code index,string url,php class,incoming requests,dispatcher,url url,meth,maps,match,parameters,array,config,cakephp,apache,router diff --git a/es/development/sessions.rst b/es/development/sessions.rst index 7177ba787b2835c01fd7dce1bd9d72e0acc42de7..671d08ecd00dd96084a1fbf7bef17bf7ef28cda9 100644 --- a/es/development/sessions.rst +++ b/es/development/sessions.rst @@ -2,385 +2,14 @@ Sessions ######## .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -CakePHP provides a wrapper and suite of utility features on top of PHP's native -``session`` extension. Sessions allow you to identify unique users across the -requests and store persistent data for specific users. Unlike Cookies, session -data is not available on the client side. Usage of ``$_SESSION`` is generally -avoided in CakePHP, and instead usage of the Session classes is preferred. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -.. _session-configuration: - -Session Configuration -===================== - -Session configuration is stored in ``Configure`` under the top -level ``Session`` key, and a number of options are available: - -* ``Session.cookie`` - Change the name of the session cookie. - -* ``Session.cookiePath`` - The url path for which session cookie is set. - Maps to the ``session.cookie_path`` php.ini config. Defaults to base path of app. - -* ``Session.timeout`` - The number of *minutes* before CakePHP's session handler expires the session. - -* ``Session.cookieTimeout`` - The number of *minutes* before the session cookie expires. - If this is undefined, it will use the same value as ``Session.timeout``. - This affects the session cookie, and is handled by PHP itself. - -* ``Session.defaults`` - Allows you to use one the built-in default session - configurations as a base for your session configuration. See below for the - built-in defaults. - -* ``Session.handler`` - Allows you to define a custom session handler. The core - database and cache session handlers use this. See below for additional - information on Session handlers. - -* ``Session.ini`` - Allows you to set additional session ini settings for your - config. This combined with ``Session.handler`` replace the custom session - handling features of previous versions - -CakePHP's defaults ``session.cookie_secure`` to true, when your application is -on an SSL protocol. If your application serves from both SSL and non-SSL -protocols, then you might have problems with sessions being lost. If you need -access to the session on both SSL and non-SSL domains you will want to disable -this:: - - Configure::write('Session', [ - 'defaults' => 'php', - 'ini' => [ - 'session.cookie_secure' => false - ] - ]); - -The session cookie path defaults to app's base path. To change this you can use -the ``cookiePath`` config. For e.g. if you want your session to persist across -all subdomains you can do:: - - Configure::write('Session', [ - 'defaults' => 'php', - 'cookiePath' => '/', - 'ini' => [ - 'session.cookie_domain' => '.yourdomain.com' - ] - ]); - -Built-in Session Handlers & Configuration -========================================= - -CakePHP comes with several built-in session configurations. You can either use -these as the basis for your session configuration, or you can create a fully -custom solution. To use defaults, simply set the 'defaults' key to the name of -the default you want to use. You can then override any sub setting by declaring -it in your Session config:: - - Configure::write('Session', [ - 'defaults' => 'php' - ]); - -The above will use the built-in 'php' session configuration. You could augment -part or all of it by doing the following:: - - Configure::write('Session', [ - 'defaults' => 'php', - 'cookie' => 'my_app', - 'timeout' => 4320 // 3 days - ]); - -The above overrides the timeout and cookie name for the 'php' session -configuration. The built-in configurations are: - -* ``php`` - Saves sessions with the standard settings in your php.ini file. -* ``cake`` - Saves sessions as files inside ``app/tmp/sessions``. This is a - good option when on hosts that don't allow you to write outside your own home - dir. -* ``database`` - Use the built-in database sessions. See below for more information. -* ``cache`` - Use the built-in cache sessions. See below for more information. - -Session Handlers ----------------- - -Session handlers can also be defined in the session config array. By defining -the 'handler.engine' config key, you can name the class name, or provide -a handler instance. The class/object must implement the -native PHP ``SessionHandlerInterface``. Implementing this interface will allow ``Session`` -to automatically map the methods for the handler. Both the core Cache and -Database session handlers use this method for saving sessions. Additional -settings for the handler should be placed inside the handler array. You can then -read those values out from inside your handler:: - - 'Session' => [ - 'handler' => [ - 'engine' => 'Database', - 'model' => 'CustomSessions' - ] - ] - -The above shows how you could setup the Database session handler with an -application model. When using class names as your handler.engine, CakePHP will -expect to find your class in the ``Network\\Session`` namespace. For example, if -you had a ``AppSessionHandler`` class, the file should be -``src/Network/Session/AppSessionHandler.php``, and the class name should be -``App\\Network\\Session\\AppSessionHandler``. You can also use session handlers -from inside plugins. By setting the engine to ``MyPlugin.PluginSessionHandler``. - -Database Sessions ------------------ - -The changes in session configuration change how you define database sessions. -Most of the time you will only need to set ``Session.handler.model`` in your -configuration as well as choose the database defaults:: - - Configure::write('Session', [ - 'defaults' => 'database', - 'handler' => [ - 'model' => 'CustomSessions' - ] - ]); - -The above will tell Session to use the built-in 'database' defaults, and -specify that a model called ``CustomSessions`` will be the delegate for saving -session information to the database. - -If you do not need a fully custom session handler, but still require -database-backed session storage, you can simplify the above code to:: - - Configure::write('Session', [ - 'defaults' => 'database' - ]); - -This configuration will require a database table to be added with -at least these fields:: - - CREATE TABLE `sessions` ( - `id` varchar(255) NOT NULL DEFAULT '', - `data` text, - `expires` int(11) DEFAULT NULL, - PRIMARY KEY (`id`) - ); - -You can find a copy of the schema for the sessions table in the application -skeleton. - -Cache Sessions --------------- - -The Cache class can be used to store sessions as well. This allows you to store -sessions in a cache like APC, memcache, or Xcache. There are some caveats to -using cache sessions, in that if you exhaust the cache space, sessions will -start to expire as records are evicted. - -To use Cache based sessions you can configure you Session config like:: - - Configure::write('Session', [ - 'defaults' => 'cache', - 'handler' => [ - 'config' => 'session' - ] - ]); - -This will configure Session to use the ``CacheSession`` class as the -delegate for saving the sessions. You can use the 'config' key which cache -configuration to use. The default cache configuration is ``'default'``. - -Setting ini directives -====================== - -The built-in defaults attempt to provide a common base for session -configuration. You may need to tweak specific ini flags as well. CakePHP -exposes the ability to customize the ini settings for both default -configurations, as well as custom ones. The ``ini`` key in the session settings, -allows you to specify individual configuration values. For example you can use -it to control settings like ``session.gc_divisor``:: - - Configure::write('Session', [ - 'defaults' => 'php', - 'ini' => [ - 'session.gc_divisor' => 1000, - 'session.cookie_httponly' => true - ] - ]); - - -Creating a Custom Session Handler -================================= - -Creating a custom session handler is straightforward in CakePHP. In this -example we'll create a session handler that stores sessions both in the Cache -(apc) and the database. This gives us the best of fast IO of apc, -without having to worry about sessions evaporating when the cache fills up. - -First we'll need to create our custom class and put it in -``src/Network/Session/ComboSession.php``. The class should look -something like:: - - namespace App\Network\Session; - - use Cake\Cache\Cache; - use Cake\Core\Configure; - use Cake\Network\Session\DatabaseSession; - - class ComboSession extends DatabaseSession - { - public $cacheKey; - - public function __construct() - { - $this->cacheKey = Configure::read('Session.handler.cache'); - parent::__construct(); - } - - // Read data from the session. - public function read($id) - { - $result = Cache::read($id, $this->cacheKey); - if ($result) { - return $result; - } - return parent::read($id); - } - - // Write data into the session. - public function write($id, $data) - { - $result = Cache::write($id, $data, $this->cacheKey); - if ($result) { - return parent::write($id, $data); - } - return false; - } - - // Destroy a session. - public function destroy($id) - { - Cache::delete($id, $this->cacheKey); - return parent::destroy($id); - } - - // Removes expired sessions. - public function gc($expires = null) - { - return Cache::gc($this->cacheKey) && parent::gc($expires); - } - } - -Our class extends the built-in ``DatabaseSession`` so we don't have to duplicate -all of its logic and behavior. We wrap each operation with -a :php:class:`Cake\\Cache\\Cache` operation. This lets us fetch sessions from -the fast cache, and not have to worry about what happens when we fill the cache. -Using this session handler is also easy. In your ``app.php`` make the session -block look like the following:: - - 'Session' => [ - 'defaults' => 'database', - 'handler' => [ - 'engine' => 'ComboSession', - 'model' => 'Session', - 'cache' => 'apc' - ] - ], - // Make sure to add a apc cache config - 'Cache' => [ - 'apc' => ['engine' => 'Apc'] - ] - -Now our application will start using our custom session handler for reading & -writing session data. - - -.. php:class:: Session - -Accessing the Session Object -============================ - -You can access the session data any place you have access to a request object. -This means the session is easily accessible from: - -* Controllers -* Views -* Helpers -* Cells -* Components - -In addition to the basic session object, you can also use the -:php:class:`Cake\\Controller\\Component\\SessionComponent` and -:php:class:`Cake\\View\\Helper\\SessionHelper` to interact with the session in -controllers and views. A basic example of session usage would be:: - - $name = $this->request->session()->read('User.name'); - - // If you are accessing the session multiple times, - // you will probably want a local variable. - $session = $this->request->session(); - $name = $session->read('User.name'); - -Reading & Writing Session Data -============================== - -.. php:method:: read($key) - -You can read values from the session using :php:meth:`Hash::extract()` -compatible syntax:: - - $session->read('Config.language'); - -.. php:method:: write($key, $value) - -``$key`` should be the dot separated path you wish to write ``$value`` to:: - - $session->write('Config.language', 'eng'); - -.. php:method:: delete($key) - -When you need to delete data from the session, you can use delete:: - - $session->delete('Config.language'); - -.. php:method:: check($key) - -If you want to see if data exists in the session, you can use ``check()``:: - - if ($session->check('Config.language')) { - // Config.language exists and is not null. - } - -Destroying the Session -====================== - -.. php:method:: destroy() - -Destroying the session is useful when users log out. To destroy a session, use -the ``destroy()`` method:: - - $session->destroy(); - -Destroying a session will remove all serverside data in the session, but will **not** -remove the session cookie. - -Rotating Session Identifiers -============================ - -.. php:method:: renew() - -While ``AuthComponent`` automatically renews the session id when users login and -out, you may need to rotate the session id's manually. To do this use the -``renew()`` method:: - - $session->renew(); - -Flash Messages -============== - -Flash messages are small messages displayed to end users once. They are often used to -present error messages, or confirm that actions took place successfully. - -To set and display flash messages you should use -:doc:`/core-libraries/components/flash` and -:doc:`/core-libraries/helpers/flash` + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Sessions - :keywords lang=en: session defaults,session classes,utility features,session timeout,session ids,persistent data,session key,session cookie,session data,last session,core database,security level,useragent,security reasons,session id,attr,countdown,regeneration,sessions,config + :title lang=es: Sessions + :keywords lang=es: session defaults,session classes,utility features,session timeout,session ids,persistent data,session key,session cookie,session data,last session,core database,security level,useragent,security reasons,session id,attr,countdown,regeneration,sessions,config diff --git a/es/development/testing.rst b/es/development/testing.rst index 5d92b715db30665fb146f24c5a580197b32f03e4..828e27438a00cba753a0add1614abc38a57f55e5 100644 --- a/es/development/testing.rst +++ b/es/development/testing.rst @@ -2,1362 +2,14 @@ Testing ####### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -CakePHP comes with comprehensive testing support built-in. CakePHP comes with -integration for `PHPUnit `_. In addition to the features -offered by PHPUnit, CakePHP offers some additional features to make testing -easier. This section will cover installing PHPUnit, and getting started with -Unit Testing, and how you can use the extensions that CakePHP offers. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -Installing PHPUnit -================== - -CakePHP uses PHPUnit as its underlying test framework. PHPUnit is the de-facto -standard for unit testing in PHP. It offers a deep and powerful set of features -for making sure your code does what you think it does. PHPUnit can be installed -through using either a `PHAR package `_ or `Composer -`_. - -Install PHPUnit with Composer ------------------------------ - -To install PHPUnit with Composer, add the following to you application's -``require`` section in its ``composer.json``:: - - "phpunit/phpunit": "*", - -After updating your package.json, run Composer again inside your application -directory:: - - $ php composer.phar install - -You can now run PHPUnit using:: - - $ bin/phpunit - -Using the PHAR File -------------------- - -After you have downloaded the ``phpunit.phar`` file, you can use it to run your -tests:: - - php phpunit.phar - - -Test Database Setup -=================== - -Remember to have a debug level of at least 1 in your ``config/app.php`` -file before running any tests. Tests are not accessible via the web runner when -debug is equal to 0. Before running any tests you should be sure to add a -``test`` datasource configuration to ``config/app.php``. This -configuration is used by CakePHP for fixture tables and data:: - - 'Datasources' => [ - 'test' => [ - 'datasource' => 'Cake\Database\Driver\Mysql', - 'persistent' => false, - 'host' => 'dbhost', - 'username' => 'dblogin', - 'password' => 'dbpassword', - 'database' => 'test_database' - ], - ], - -.. note:: - - It's a good idea to make the test database and your actual database - different databases. This will prevent embarrassing mistakes later. - -Checking the Test Setup -======================= - -After installing PHPUnit and setting up your ``test`` datasource configuration -you can make sure you're ready to write and run your own tests by running your -application's tests:: - - // For system wide PHPUnit - $ phpunit - - // For phpunit.phar - $ php phpunit.phar - - // For Composer installed phpunit - $ bin/phpunit - -The above should run any tests you have, or let you know that no tests were run. -To run a specific test you can supply the path to the test as a parameter to -PHPUnit. For example, if you had a test case for ArticlesTable class you could -run it with:: - - $ phpunit tests/TestCase/Model/Table/ArticlesTableTest - -You should see a green bar with some additional information about the tests run, -and number passed. - -.. note:: - - If you are on a windows system you probably won't see any colours. - -Test Case Conventions -===================== - -Like most things in CakePHP, test cases have some conventions. Concerning -tests: - -#. PHP files containing tests should be in your - ``tests/TestCase/[Type]`` directories. -#. The filenames of these files should end in ``Test.php`` instead - of just .php. -#. The classes containing tests should extend ``Cake\TestSuite\TestCase``, - ``Cake\TestSuite\ControllerTestCase`` or ``\PHPUnit_Framework_TestCase``. -#. Like other classnames, the test case classnames should match the filename. - ``RouterTest.php`` should contain ``class RouterTest extends TestCase``. -#. The name of any method containing a test (i.e. containing an - assertion) should begin with ``test``, as in ``testPublished()``. - You can also use the ``@test`` annotation to mark methods as test methods. - -Creating Your First Test Case -============================= - -In the following example, we'll create a test case for a very simple helper -method. The helper we're going to test will be formatting progress bar HTML. -Our helper looks like:: - - namespace App\View\Helper; - use Cake\View\Helper; - - class ProgressHelper extends Helper - { - public function bar($value) - { - $width = round($value / 100, 2) * 100; - return sprintf( - '
    -
    -
    ', $width); - } - } - -This is a very simple example, but it will be useful to show how you can create -a simple test case. After creating and saving our helper, we'll create the test -case file in ``tests/TestCase/View/Helper/ProgressHelperTest.php``. In that file -we'll start with the following:: - - namespace App\Test\TestCase\View\Helper; - - use App\View\Helper\ProgressHelper; - use Cake\TestSuite\TestCase; - use Cake\View\View; - - class ProgressHelperTest extends TestCase - { - public function setUp() - { - - } - - public function testBar() - { - - } - } - -We'll flesh out this skeleton in a minute. We've added two methods to start -with. First is ``setUp()``. This method is called before every *test* method -in a test case class. Setup methods should initialize the objects needed for the -test, and do any configuration needed. In our setup method we'll add the -following:: - - public function setUp() - { - parent::setUp(); - $View = new View(); - $this->Progress = new ProgressHelper($View); - } - -Calling the parent method is important in test cases, as TestCase::setUp() -does a number things like backing up the values in :php:class:`~Cake\\Core\\Configure` and, -storing the paths in :php:class:`~Cake\\Core\\App`. - -Next, we'll fill out the test method. We'll use some assertions to ensure that -our code creates the output we expect:: - - public function testBar() - { - $result = $this->Progress->bar(90); - $this->assertContains('width: 90%', $result); - $this->assertContains('progress-bar', $result); - - $result = $this->Progress->bar(33.3333333); - $this->assertContains('width: 33%', $result); - } - -The above test is a simple one but shows the potential benefit of using test -cases. We use ``assertContains()`` to ensure that our helper is returning a -string that contains the content we expect. If the result did not contain the -expected content the test would fail, and we would know that our code is -incorrect. - -By using test cases you can easily describe the relationship between a set of -known inputs and their expected output. This helps you be more confident of the -code you're writing as you can easily check that the code you wrote fulfills the -expectations and assertions your tests make. Additionally because tests are -code, they are easy to re-run whenever you make a change. This helps prevent -the creation of new bugs. - -.. _running-tests: - -Running Tests -============= - -Once you have PHPUnit installed and some test cases written, you'll want to run -the test cases very frequently. It's a good idea to run tests before committing -any changes to help ensure you haven't broken anything. - -By using ``phpunit`` you can run your application and plugin tests. To run your -application's tests you can simply run:: - - $ phpunit - -From your application's root directory. To run a plugin's tests, first ``cd`` -into the plugin directory, then use ``phpunit`` to run the tests. - -Filtering Test Cases --------------------- - -When you have larger test cases, you will often want to run a subset of the test -methods when you are trying to work on a single failing case. With the -CLI runner you can use an option to filter test methods:: - - $ phpunit --filter testSave tests/TestCase/Model/Table/ArticlesTableTest - -The filter parameter is used as a case-sensitive regular expression for filtering -which test methods to run. - -Generating Code Coverage ------------------------- - -You can generate code coverage reports from the command line using PHPUnit's -built-in code coverage tools. PHPUnit will generate a set of static HTML files -containing the coverage results. You can generate coverage for a test case by -doing the following:: - - $ phpunit --coverage-html webroot/coverage tests/TestCase/Model/Table/ArticlesTableTest - -This will put the coverage results in your application's webroot directory. You -should be able to view the results by going to -``http://localhost/your_app/coverage``. - -Combining Test Suites for Plugins ---------------------------------- - -Often times your application will be composed of several plugins. In these -situations it can be pretty tedious to run tests for each plugin. You can make -running tests for each of the plugins that compose your application by adding -additional ```` sections to your application's ``phpunit.xml`` file:: - - - - ./tests/TestCase - - - - - ./plugins/Forum/tests/TestCase - - - -Any additional test suites added to the ```` element will -automatically be run when you use ``phpunit``. - -Test Case Lifecycle Callbacks -============================= - -Test cases have a number of lifecycle callbacks you can use when doing testing: - -* ``setUp`` is called before every test method. Should be used to create the - objects that are going to be tested, and initialize any data for the test. - Always remember to call ``parent::setUp()`` -* ``tearDown`` is called after every test method. Should be used to cleanup after - the test is complete. Always remember to call ``parent::tearDown()``. -* ``setupBeforeClass`` is called once before test methods in a case are started. - This method must be *static*. -* ``tearDownAfterClass`` is called once after test methods in a case are started. - This method must be *static*. - -.. _test-fixtures: - -Fixtures -======== - -When testing code that depends on models and the database, one can use -**fixtures** as a way to generate temporary data tables loaded with sample data -that can be used by the test. The benefit of using fixtures is that your test -has no chance of disrupting live application data. In addition, you can begin -testing your code prior to actually developing live content for an application. - -CakePHP uses the connection named ``test`` in your ``config/datasources.php`` -configuration file. If this connection is not usable, an exception will be -raised and you will not be able to use database fixtures. - -CakePHP performs the following during the course of a fixture based -test case: - -#. Creates tables for each of the fixtures needed. -#. Populates tables with data, if data is provided in fixture. -#. Runs test methods. -#. Empties the fixture tables. -#. Removes fixture tables from database. - -Test Connections ----------------- - -By default CakePHP will alias each connection in your application. Each -connection defined in your application's bootstrap that does not start with -``test_`` will have a ``test_`` prefixed alias created. Aliasing connections -ensures, you don't accidentally use the wrong connection in test cases. -Connection aliasing is transparent to the rest of your application. For example -if you use the 'default' connection, instead you will get the ``test`` -connection in test cases. If you use the 'replica' connection, the test suite -will attempt to use 'test_replica'. - -Creating Fixtures ------------------ - -When creating a fixture you will mainly define two things: how the table is -created (which fields are part of the table), and which records will be -initially populated to the table. Let's create our first fixture, that will be -used to test our own Article model. Create a file named ``ArticlesFixture.php`` -in your ``tests/Fixture`` directory, with the following content:: - - namespace App\Test\Fixture; - - use Cake\Test\TestFixture; - - class ArticlesFixture extends TestFixture - { - - // Optional. Set this property to load fixtures to a different test datasource - public $connection = 'test'; - - public $fields = [ - 'id' => ['type' => 'integer'], - 'title' => ['type' => 'string', 'length' => 255, 'null' => false], - 'body' => 'text', - 'published' => ['type' => 'integer', 'default' => '0', 'null' => false], - 'created' => 'datetime', - 'updated' => 'datetime', - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id']] - ] - ]; - public $records = [ - [ - 'id' => 1, - 'title' => 'First Article', - 'body' => 'First Article Body', - 'published' => '1', - 'created' => '2007-03-18 10:39:23', - 'updated' => '2007-03-18 10:41:31' - ], - [ - 'id' => 2, - 'title' => 'Second Article', - 'body' => 'Second Article Body', - 'published' => '1', - 'created' => '2007-03-18 10:41:23', - 'updated' => '2007-03-18 10:43:31' - ], - [ - 'id' => 3, - 'title' => 'Third Article', - 'body' => 'Third Article Body', - 'published' => '1', - 'created' => '2007-03-18 10:43:23', - 'updated' => '2007-03-18 10:45:31' - ] - ]; - } - -The ``$connection`` property defines the datasource of which the fixture will -use. If your application uses multiple datasources, you should make the -fixtures match the model's datasources but prefixed with ``test_``. -For example if your model uses the ``mydb`` datasource, your fixture should use -the ``test_mydb`` datasource. If the ``test_mydb`` connection doesn't exist, -your models will use the default ``test`` datasource. Fixture datasources must -be prefixed with ``test`` to reduce the possibility of accidentally truncating -all your application's data when running tests. - -We use ``$fields`` to specify which fields will be part of this table, -and how they are defined. The format used to define these fields is -the same used with :php:class:`Cake\\Database\\Schema\\Table`. The keys available for table -definition are: - -type - CakePHP internal data type. Currently supported: - - - ``string``: maps to ``VARCHAR`` or ``CHAR`` - - ``uuid``: maps to ``UUID`` - - ``text``: maps to ``TEXT`` - - ``integer``: maps to ``INT`` - - ``biginteger``: maps to ``BIGINTEGER`` - - ``decimal``: maps to ``DECIMAL`` - - ``float``: maps to ``FLOAT`` - - ``datetime``: maps to ``DATETIME`` - - ``timestamp``: maps to ``TIMESTAMP`` - - ``time``: maps to ``TIME`` - - ``date``: maps to ``DATE`` - - ``binary``: maps to ``BLOB`` -fixed - Used with string types to create CHAR columns in platforms that support - them. -length - Set to the specific length the field should take. -precision - Set the number of decimal places used on float & decimal fields. -null - Set to either ``true`` (to allow NULLs) or ``false`` (to disallow NULLs). -default - Default value the field takes. - -We can define a set of records that will be populated after the fixture table is -created. The format is fairly straight forward, ``$records`` is an array of -records. Each item in ``$records`` should be a single row. Inside each row, -should be an associative array of the columns and values for the row. Just keep -in mind that each record in the $records array must have a key for **every** -field specified in the ``$fields`` array. If a field for a particular record needs -to have a ``null`` value, just specify the value of that key as ``null``. - -Dynamic Data and Fixtures -------------------------- - -Since records for a fixture are declared as a class property, you cannot easily -use functions or other dynamic data to define fixtures. To solve this problem, -you can define ``$records`` in the init() function of your fixture. For example -if you wanted all the created and updated timestamps to reflect today's date you -could do the following:: - - namespace App\Test\Fixture; - - use Cake\TestSuite\Fixture\TestFixture; - - class ArticlesFixture extends TestFixture - { - - public $fields = [ - 'id' => ['type' => 'integer'], - 'title' => ['type' => 'string', 'length' => 255, 'null' => false], - 'body' => 'text', - 'published' => ['type' => 'integer', 'default' => '0', 'null' => false], - 'created' => 'datetime', - 'updated' => 'datetime', - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id']], - ] - ]; - - public function init() - { - $this->records = [ - [ - 'id' => 1, - 'title' => 'First Article', - 'body' => 'First Article Body', - 'published' => '1', - 'created' => date('Y-m-d H:i:s'), - 'updated' => date('Y-m-d H:i:s'), - ], - ]; - parent::init(); - } - } - -When overriding ``init()`` remember to always call ``parent::init()``. - -Importing Table Information ---------------------------- - -Defining the schema in fixture files can be really handy when creating plugins -or libraries or if you are creating an application that needs to easily be -portable. Redefining the schema in fixtures can become difficult to maintain in -larger applications. Because of this CakePHP provides the ability to import the -schema from an existing connection and use the reflected table definition to -create the table definition used in the test suite. - -Let's start with an example. Assuming you have a table named articles available -in your application, change the example fixture given in the previous section -(``tests/Fixture/ArticlesFixture.php``) to:: - - - class ArticlesFixture extends TestFixture - { - public $import = ['table' => 'articles'] - } - -If you want to use a different connection use:: - - class ArticlesFixture extends TestFixture - { - public $import = ['table' => 'articles', 'connection' => 'other']; - } - - -You can naturally import your table definition from an existing -model/table, but have your records defined directly on the fixture -as it was shown on previous section. For example:: - - class ArticlesFixture extends TestFixture - { - public $import = ['table' => 'articles']; - public $records = [ - [ - 'id' => 1, - 'title' => 'First Article', - 'body' => 'First Article Body', - 'published' => '1', - 'created' => '2007-03-18 10:39:23', - 'updated' => '2007-03-18 10:41:31' - ], - [ - 'id' => 2, - 'title' => 'Second Article', - 'body' => 'Second Article Body', - 'published' => '1', - 'created' => '2007-03-18 10:41:23', - 'updated' => '2007-03-18 10:43:31' - ], - [ - 'id' => 3, - 'title' => 'Third Article', - 'body' => 'Third Article Body', - 'published' => '1', - 'created' => '2007-03-18 10:43:23', - 'updated' => '2007-03-18 10:45:31' - ] - ]; - } - -Finally, you can not load/create any schema in a fixture. This is useful if you -already have a test database setup with all the empty tables created. By -defining neither ``$fields`` or ``$import`` a fixture will only insert its -records and truncate the records on each test method. - -Loading Fixtures in your Test Cases ------------------------------------ - -After you've created your fixtures, you'll want to use them in your test cases. -In each test case you should load the fixtures you will need. You should load a -fixture for every model that will have a query run against it. To load fixtures -you define the ``$fixtures`` property in your model:: - - class ArticlesTest extends TestCase - { - public $fixtures = ['app.articles', 'app.comments']; - } - -The above will load the Article and Comment fixtures from the application's -Fixture directory. You can also load fixtures from CakePHP core, or plugins:: - - class ArticlesTest extends TestCase - { - public $fixtures = ['plugin.debug_kit.articles', 'core.comments']; - } - -Using the ``core`` prefix will load fixtures from CakePHP, and using a plugin -name as the prefix, will load the fixture from the named plugin. - -You can control when your fixtures are loaded by setting -:php:attr:`Cake\\TestSuite\\TestCase::$autoFixtures` to ``false`` and later load them using -:php:meth:`Cake\\TestSuite\\TestCase::loadFixtures()`:: - - class ArticlesTest extends TestCase - { - public $fixtures = ['app.articles', 'app.comments']; - public $autoFixtures = false; - - public function testMyFunction() - { - $this->loadFixtures('Article', 'Comment'); - } - } - -You can load fixtures in subdirectories. Using multiple directories -can make it easier to organize your fixtures if you have a larger application. -To load fixtures in subdirectories, simply include the subdirectory name in the -fixture name:: - - class ArticlesTest extends CakeTestCase - { - public $fixtures = ['app.blog/articles', 'app.blog/comments']; - } - -In the above example, both fixtures would be loaded from -``tests/Fixture/blog/``. - -Testing Tables -============== - -Let's say we already have our Articles Table class defined in -``src/Model/Table/ArticlesTable.php``, and it looks like:: - - namespace App\Model\Table; - - use Cake\ORM\Table; - use Cake\ORM\Query; - - class ArticlesTable extends Table - { - - public function findPublished(Query $query, array $options) - { - $query->where([ - $this->alias() . '.published' => 1 - ]); - return $query; - } - } - -We now want to set up a test that will test this table class. Let's now create -a file named ``ArticlesTableTest.php`` in your ``tests/TestCase/Model/Table`` directory, -with the following contents:: - - namespace App\Test\TestCase\Model\Table; - - use Cake\ORM\TableRegistry; - use Cake\TestSuite\TestCase; - - class ArticleTest extends TestCase - { - public $fixtures = ['app.articles']; - } - -In our test cases' variable ``$fixtures`` we define the set of fixtures that -we'll use. You should remember to include all the fixtures that will have -queries run against them. - -Creating a Test Method ----------------------- - -Let's now add a method to test the function published() in the Article model. -Edit the file ``tests/TestCase/Model/Table/ArticlesTableTest.php`` so it now -looks like this:: - - namespace App\Test\TestCase\Model\Table; - - use Cake\ORM\TableRegistry; - use Cake\TestSuite\TestCase; - - class ArticleTest extends TestCase - { - public $fixtures = ['app.articles']; - - public function setUp() - { - parent::setUp(); - $this->Articles = TableRegistry::get('Articles'); - } - - public function testFindPublished() - { - $query = $this->Articles->find('published'); - $this->assertInstanceOf('Cake\ORM\Query', $query); - $result = $query->hydrate(false)->toArray(); - $expected = [ - ['id' => 1, 'title' => 'First Article'], - ['id' => 2, 'title' => 'Second Article'], - ['id' => 3, 'title' => 'Third Article'] - ]; - - $this->assertEquals($expected, $result); - } - } - -You can see we have added a method called ``testPublished()``. We start by -creating an instance of our ``ArticlesTable`` class, and then run our -``find('published')`` method. In ``$expected`` we set what we expect should be -the proper result (that we know since we have defined which records are -initially populated to the article table.) We test that the result equals our -expectation by using the ``assertEquals`` method. See the :ref:`running-tests` -section for more information on how to run your test case. - - -Mocking Model Methods ---------------------- - -There will be times you'll want to mock methods on models when testing them. You should -use ``getMockForModel`` to create testing mocks of table classes. It avoids issues -with reflected properties that normal mocks have:: - - public function testSendingEmails() - { - $model = $this->getMockForModel('EmailVerification', ['send']); - $model->expects($this->once()) - ->method('send') - ->will($this->returnValue(true)); - - $model->verifyEmail('test@example.com'); - } - -Testing Controllers -=================== - -While you can test controller classes in a similar fashion to Helpers, Models, -and Components, CakePHP offers a specialized ``ControllerTestCase`` class. -Using this class as the base class for your controller test cases allows you to -use ``testAction()`` for simpler test cases. ``ControllerTestCase`` allows you -to easily mock out components and models, as well as potentially difficult to -test methods like :php:meth:`~Cake\\Controller\Controller::redirect()`. - -Say you have a typical Articles controller, and its corresponding -model. The controller code looks like:: - - namespace App\Controller; - - use App\Controller\AppController; - - class ArticlesController extends AppController - { - public $helpers = ['Form', 'Html']; - - public function index($short = null) - { - if (!empty($this->request->data)) { - $article = $this->Articles->newEntity($this->request->data); - $this->Articles->save($article); - } - if (!empty($short)) { - $result = $this->Article->find('all', [ - 'fields' => ['id', 'title'] - ]); - } else { - $result = $this->Article->find(); - } - - $this->set('title', 'Articles'); - $this->set('articles', $result); - } - } - -Create a file named ``ArticlesControllerTest.php`` in your -``tests/TestCase/Controller`` directory and put the following inside:: - - namespace App\Test\TestCase\Controller; - - use Cake\TestSuite\ControllerTestCase; - - class ArticlesControllerTest extends ControllerTestCase - { - public $fixtures = ['app.articles']; - - public function testIndex() - { - $result = $this->testAction('/articles?page=1'); - debug($result); - } - - public function testIndexQueryData() - { - $result = $this->testAction('/articles', [ - 'query' => ['page' => 1] - ]); - debug($result); - } - - public function testIndexShort() - { - $result = $this->testAction('/articles/index/short'); - debug($result); - } - - public function testIndexShortGetRenderedHtml() - { - $result = $this->testAction( - '/articles/index/short', - ['return' => 'contents'] - ); - debug($result); - } - - public function testIndexShortGetViewVars() - { - $result = $this->testAction( - '/articles/index/short', - ['return' => 'vars'] - ); - debug($result); - } - - public function testIndexPostData() - { - $data = [ - 'user_id' => 1, - 'published' => 1, - 'slug' => 'new-article', - 'title' => 'New Article', - 'body' => 'New Body' - ]; - $result = $this->testAction( - '/articles', - ['data' => $data, 'method' => 'post'] - ); - debug($result); - } - } - -This example shows a few of the ways you can use testAction to test your -controllers. The first parameter of ``testAction`` should always be the URL you -want to test. CakePHP will create a request and dispatch the controller and -action. - -Simulating HTTP Methods ------------------------ - -As seen in the ``testIndexPostData()`` example above, you can use -``testAction()`` to test POST actions as well as GET actions. By default all -requests will be GET requests. You can simulate any HTTP verb by setting the:: - - public function testUpdating() - { - $data = [ - 'id' => 1, - 'title' => 'New post' - ]; - $this->testAction('/posts/edit', ['data' => $data, 'method' => 'put']); - // Some assertions. - } - -Choosing the Return Type ------------------------- - -You can choose from a number of ways to inspect the success of your controller -action. Each offers a different way to ensure your code is doing what you -expect: - -* ``vars`` Get the set view variables. -* ``view`` Get the rendered view, without a layout. -* ``contents`` Get the rendered view including the layout. -* ``result`` Get the return value of the controller action. Useful - for testing requestAction methods. - -The default value is ``result``. As long as your return type is not ``result`` -you can also access the various other return types as properties in the test -case:: - - public function testIndex() - { - $this->testAction('/posts'); - $this->assertInstanceOf('Cake\ORM\Query', $this->vars['posts']); - } - - -Using Mocks with testAction ---------------------------- - -There will be times when you want to replace components or models with either -partially mocked objects or completely mocked objects. You can do this by using -:php:meth:`Cake\\TestSuite\\ControllerTestCase::generate()`. ``generate()`` -takes the hard work out of generating mocks on your controller. If you decide to -generate a controller to be used in testing, you can generate mocked versions of -its models and components along with it:: - - $Posts = $this->generate('Articles', [ - 'methods' => [ - 'isAuthorized' - ], - 'models' => [ - 'Articles' => ['save'] - ], - 'components' => [ - 'Email' => ['send'], - 'Session' - ] - ]); - -The above would create a mocked ``ArticlesController``, stubbing out the ``isAuthorized`` -method. The attached Post model will have ``save()`` stubbed, and the attached -components would have their respective methods stubbed. You can choose to stub -an entire class by not passing methods to it, like Session in the example above. - -Generated controllers are automatically used as the testing controller to test. -To enable automatic generation, set the ``autoMock`` variable on the test case to -true. If ``autoMock`` is false, your original controller will be used in the test. - -The response object in the generated controller is always replaced with a mock -that does not send headers. After using ``generate()`` or ``testAction()`` you -can access the controller object at ``$this->controller``. - -A More Complex Example ----------------------- - -In its simplest form, ``testAction()`` will run ``ArticlesController::index()`` on -your testing controller (or an automatically generated one), including all of the -mocked models and components. The results of the test are stored in the ``vars``, -``contents``, ``view``, and ``return`` properties. Also available is a headers -property which gives you access to the ``headers`` that would have been sent, -allowing you to check for redirects:: - - public function testAdd() - { - $Articles = $this->generate('Articles', [ - 'components' => [ - 'Session', - 'Email' => ['send'] - ] - ]); - $Articles->Session - ->expects($this->once()) - ->method('setFlash'); - $Articles->Email - ->expects($this->once()) - ->method('send') - ->will($this->returnValue(true)); - - $this->testAction('/articles', [ - 'method' => 'post', - 'data' => [ - 'title' => 'New Article' - ] - ]); - $this->assertContains('/articles', $this->headers['Location']); - } - - public function testAddGet() - { - $this->testAction('/articles', [ - 'method' => 'GET', - 'return' => 'contents' - ]); - $this->assertRegExp('/contents); - $this->assertRegExp('/view); - } - - -This example shows a slightly more complex use of the ``testAction()`` and -``generate()`` methods. First, we generate a testing controller and mock the -:php:class:`Cake\\Controller\\Component\\SessionComponent`. Now that the -SessionComponent is mocked, we have the ability to run testing methods on it. -Assuming ``ArticlesController::add()`` redirects us to index, sends an email and -sets a flash message, the test will pass. A second test was added to do basic -sanity testing when fetching the add form. We check to see if the layout was -loaded by checking the entire rendered contents, and checks the view for a form -tag. As you can see, your freedom to test controllers and easily mock its -collaborators is greatly expanded with these changes. - -Testing a JSON Responding Controller ------------------------------------- - -JSON is a very friendly and common format to use when building a web service. -Testing the endpoints of your web service is very simple with CakePHP. Let us -begin with a simple example controller that responds in JSON:: - - class MarkersController extends AppController - { - public $autoRender = false; - public function index() - { - $data = $this->Markers->find()->first(); - $this->response->body(json_encode($data)); - } - } - -Now we create the file ``tests/TestCase/Controller/MarkersControllerTest.php`` -and make sure our web service is returning the proper response:: - - class MarkersControllerTest extends ControllerTestCase - { - public function testIndex() - { - $result = $this->testAction('/markers/index.json'); - $result = json_decode($result, true); - $expected = [ - ['id' => 1, 'lng' => 66, 'lat' => 45], - ]; - $this->assertEquals($expected, $result); - } - } - -Testing Views -============= - -Generally most applications will not directly test their HTML code. Doing so is -often results in fragile, difficult to maintain test suites that are prone to -breaking. When writing functional tests using :php:class:`ControllerTestCase` -you can inspect the rendered view content by setting the ``return`` option to -'view'. While it is possible to test view content using ControllerTestCase, -a more robust and maintable integration/view testing can be accomplished using -tools like `Selenium webdriver `_. - - -Testing Components -================== - -Lets pretend we have a component called PagematronComponent in our application. -This component helps us set the pagination limit value across all the -controllers that use it. Here is our example component located in -``app/Controller/Component/PagematronComponent.php``:: - - class PagematronComponent extends Component - { - public $controller = null; - - public function setController($controller) - { - $this->controller = $controller; - // Make sure the controller is using pagination - if (!isset($this->controller->paginate)) { - $this->controller->paginate = []; - } - } - - public function startup(Event $event) - { - $this->setController($event->subject()); - } - - public function adjust($length = 'short') - { - switch ($length) { - case 'long': - $this->controller->paginate['limit'] = 100; - break; - case 'medium': - $this->controller->paginate['limit'] = 50; - break; - default: - $this->controller->paginate['limit'] = 20; - break; - } - } - } - -Now we can write tests to ensure our paginate ``limit`` parameter is being -set correctly by the ``adjust`` method in our component. We create the file -``tests/TestCase/Controller/Component/PagematronComponentTest.php``:: - - namespace App\Test\TestCase\Controller\Component; - - use App\Controller\Component\PagematronComponent; - use Cake\Controller\Controller; - use Cake\Controller\ComponentCollection; - use Cake\Network\Request; - use Cake\Network\Response; - - class PagematronComponentTest extends TestCase - { - - public $component = null; - public $controller = null; - - public function setUp() - { - parent::setUp(); - // Setup our component and fake test controller - $collection = new ComponentCollection(); - $this->component = new PagematronComponent($collection); - - $request = new Request(); - $response = new Response(); - $this->controller = $this->getMock( - 'Cake\Controller\Controller', - [], - [$request, $response] - ); - $this->component->setController($this->controller); - } - - public function testAdjust() - { - // Test our adjust method with different parameter settings - $this->component->adjust(); - $this->assertEquals(20, $this->controller->paginate['limit']); - - $this->component->adjust('medium'); - $this->assertEquals(50, $this->controller->paginate['limit']); - - $this->component->adjust('long'); - $this->assertEquals(100, $this->controller->paginate['limit']); - } - - public function tearDown() - { - parent::tearDown(); - // Clean up after we're done - unset($this->component, $this->controller); - } - } - -Testing Helpers -=============== - -Since a decent amount of logic resides in Helper classes, it's -important to make sure those classes are covered by test cases. - -First we create an example helper to test. The ``CurrencyRendererHelper`` will -help us display currencies in our views and for simplicity only has one method -``usd()``:: - - // src/View/Helper/CurrencyRendererHelper.php - namespace App\View\Helper; - - use Cake\View\Helper; - - class CurrencyRendererHelper extends Helper - { - public function usd($amount) - { - return 'USD ' . number_format($amount, 2, '.', ','); - } - } - -Here we set the decimal places to 2, decimal separator to dot, thousands -separator to comma, and prefix the formatted number with 'USD' string. - -Now we create our tests:: - - // tests/TestCase/View/Helper/CurrencyRendererHelperTest.php - - namespace App\Test\TestCase\View\Helper; - - use App\View\Helper\CurrencyRendererHelper; - use Cake\TestSuite\TestCase; - use Cake\View\View; - - class CurrencyRendererHelperTest extends TestCase - { - - public $helper = null; - - // Here we instantiate our helper - public function setUp() - { - parent::setUp(); - $view = new View(); - $this->helper = new CurrencyRendererHelper($view); - } - - // Testing the usd() function - public function testUsd() - { - $this->assertEquals('USD 5.30', $this->helper->usd(5.30)); - - // We should always have 2 decimal digits - $this->assertEquals('USD 1.00', $this->helper->usd(1)); - $this->assertEquals('USD 2.05', $this->helper->usd(2.05)); - - // Testing the thousands separator - $this->assertEquals( - 'USD 12,000.70', - $this->helper->usd(12000.70) - ); - } - } - -Here, we call ``usd()`` with different parameters and tell the test suite to -check if the returned values are equal to what is expected. - -Save this and execute the test. You should see a green bar and messaging -indicating 1 pass and 4 assertions. - -Creating Test Suites -==================== - -If you want several of your tests to run at the same time, you can create a test -suite. A test suite is composed of several test cases. You can either create -test suites in your application's ``phpunit.xml`` file, or by creating suite -classes using ``CakeTestSuite``. Using ``phpunit.xml`` is good when you only -need simple include/exclude rules to define your test suite. A simple example -would be - -.. code-block:: xml - - - - src/Model - src/Service/UserServiceTest.php - src/Model/Cloud/ImagesTest.php - - - -``CakeTestSuite`` offers several methods for easily creating test suites based -on the file system. It allows you to run any code you want to prepare your test -suite. If we wanted to create a test suite for all our model tests we could -would create ``tests/TestCase/AllModelTest.php``. Put the following in it:: - - class AllModelTest extends TestSuite - { - public static function suite() { - $suite = new CakeTestSuite('All model tests'); - $suite->addTestDirectory(TESTS . 'Case/Model'); - return $suite; - } - } - -The code above will group all test cases found in the -``tests/TestCase/Model/`` folder. To add an individual file, use -``$suite->addTestFile($filename);``. You can recursively add a directory -for all tests using:: - - $suite->addTestDirectoryRecursive(TESTS . 'TestCase'); - -Would recursively add all test cases in the ``tests/TestCase/`` -directory. - -Creating Tests for Plugins -========================== - -Tests for plugins are created in their own directory inside the -plugins folder. :: - - /app - /Plugin - /Blog - /Test - /TestCase - /Fixture - -They work just like normal tests but you have to remember to use -the naming conventions for plugins when importing classes. This is -an example of a testcase for the ``BlogPost`` model from the plugins -chapter of this manual. A difference from other tests is in the -first line where 'Blog.BlogPost' is imported. You also need to -prefix your plugin fixtures with ``plugin.blog.blog_posts``:: - - namespace Blog\Test\TestCase\Model; - - use Blog\Model\BlogPost; - use Cake\TestSuite\TestCase; - - class BlogPostTest extends TestCase - { - - // Plugin fixtures located in /plugins/Blog/tests/Fixture/ - public $fixtures = ['plugin.blog.blog_posts']; - public $BlogPost; - - public function testSomething() - { - // Test something. - } - } - -If you want to use plugin fixtures in the app tests you can -reference them using ``plugin.pluginName.fixtureName`` syntax in the -``$fixtures`` array. - -Generating Tests with Bake -========================== - -If you use :doc:`bake ` to -generate scaffolding, it will also generate test stubs. If you need to -re-generate test case skeletons, or if you want to generate test skeletons for -code you wrote, you can use ``bake``: - -.. code-block:: bash - - bin/cake bake test - -```` should be one of: - -#. Entity -#. Table -#. Controller -#. Component -#. Behavior -#. Helper -#. Shell -#. Cell - -While ```` should be the name of the object you want to bake a test -skeleton for. - -Integration with Jenkins -======================== - -`Jenkins `_ is a continuous integration server, that can -help you automate the running of your test cases. This helps ensure that all -your tests stay passing and your application is always ready. - -Integrating a CakePHP application with Jenkins is fairly straightforward. The -following assumes you've already installed Jenkins on \*nix system, and are able -to administer it. You also know how to create jobs, and run builds. If you are -unsure of any of these, refer to the `Jenkins documentation `_ . - -Create a Job ------------- - -Start off by creating a job for your application, and connect your repository -so that jenkins can access your code. - -Add Test Database Config ------------------------- - -Using a separate database just for Jenkins is generally a good idea, as it stops -bleed through and avoids a number of basic problems. Once you've created a new -database in a database server that jenkins can access (usually localhost). Add -a *shell script step* to the build that contains the following: - -.. code-block:: bash - - cat > config/app_local.php <<'CONFIG' - [ - 'test' => [ - 'datasource' => 'Database/Mysql', - 'host' => 'localhost', - 'database' => 'jenkins_test', - 'username' => 'jenkins', - 'password' => 'cakephp_jenkins', - 'encoding' => 'utf8' - ] - ] - ]; - CONFIG - -Then uncomment the following line in your ``config/bootstrap.php`` file:: - - //Configure::load('app_local', 'default'); - -By creating an ``app_local.php`` file, you have an easy way to define -configuration specific to Jenkins. You can use this same configuration file to -override any other configuration files you need on Jenkins. - -It's often a good idea to drop and re-create the database before each build as -well. This insulates you from chained failures, where one broken build causes -others to fail. Add another *shell script step* to the build that contains the -following:: - - mysql -u jenkins -pcakephp_jenkins -e 'DROP DATABASE IF EXISTS jenkins_test; CREATE DATABASE jenkins_test'; - -Add your Tests --------------- - -Add another *shell script step* to your build. In this step install your -dependencies and run the tests for your application. Creating a junit log file, -or clover coverage is often a nice bonus, as it gives you a nice graphical view -of your testing results: - -.. code-block:: bash - - # Download Composer if it is missing. - test -f 'composer.phar' || curl -sS https://getcomposer.org/installer| php - # Install dependencies - php composer.phar install - bin/phpunit --log-junit junit.xml --coverage-clover clover.xml - -If you use clover coverage, or the junit results, make sure to configure those -in Jenkins as well. Failing to configure those steps will mean you won't see the results. - -Run a Build ------------ - -You should be able to run a build now. Check the console output and make any -necessary changes to get a passing build. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. .. meta:: - :title lang=en: Testing - :keywords lang=en: web runner,phpunit,test database,database configuration,database setup,database test,public test,test framework,running one,test setup,de facto standard,pear,runners,array,databases,cakephp,php,integration + :title lang=es: Testing + :keywords lang=es: web runner,phpunit,test database,database configuration,database setup,database test,public test,test framework,running one,test setup,de facto standard,pear,runners,array,databases,cakephp,php,integration diff --git a/es/elasticsearch.rst b/es/elasticsearch.rst new file mode 100644 index 0000000000000000000000000000000000000000..78acd152fd6bb091e328afa34263bdcdd38529bd --- /dev/null +++ b/es/elasticsearch.rst @@ -0,0 +1,11 @@ +ElasticSearch +############# + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/epub-contents.rst b/es/epub-contents.rst index 5afbc7189a7d256a408738b53b5a51ab7adbb2d3..3ae714127658da55b6b98cfa09a5fa6df59e1fe1 100644 --- a/es/epub-contents.rst +++ b/es/epub-contents.rst @@ -2,7 +2,7 @@ Contents ######## .. toctree:: - :maxdepth: 3 + :maxdepth: 3 intro quickstart @@ -17,16 +17,19 @@ Contents controllers views orm - development/errors + controllers/components/authentication + bake core-libraries/caching console-and-shells development/debugging deployment core-libraries/email + development/errors core-libraries/events core-libraries/internationalization-and-localization core-libraries/logging + core-libraries/form controllers/components/pagination plugins development/rest @@ -43,12 +46,17 @@ Contents core-libraries/inflector core-libraries/number core-libraries/registry-objects - core-libraries/string + core-libraries/text core-libraries/time core-libraries/xml core-libraries/global-constants-and-functions + debug-kit + migrations appendices .. todolist:: +.. meta:: + :title lang=es: Contents + :keywords lang=es: core libraries,ref search,shells,deployment,appendices,glossary,models diff --git a/es/getting-started.rst b/es/getting-started.rst deleted file mode 100644 index 009add16d51af593b7cfedeb60965b0b6d0657ea..0000000000000000000000000000000000000000 --- a/es/getting-started.rst +++ /dev/null @@ -1,31 +0,0 @@ -Primeros Pasos -############## - -CakePHP te proporciona una base robusta para construir tus aplicaciones. -Se encarga de todo, desde la petición inicial del usuario hasta la -construcción del código HTML final. Como CakePHP sigue los fundamentos del -patrón MVC, te permite personalizar y extender fácilmente cada una de sus -partes. - -Este framework también proporciona una estructura organizacional: desde los -nombres de ficheros hasta los nombres de las tablas en la base de datos. Esto -mantiene tu aplicación consistente y ordenada. Siendo un concepto sencillo, -seguir las convenciones definidas te facilitará encontrar rápidamente cada cosa -y aprenderás en menos tiempo los fundamentos del framework. - -La mejor manera de empezar es ponerte manos a la obra y desarrollar algo. Para -empezar construiremos un Blog sencillo. - -.. include:: /tutorials-and-examples/blog/blog.rst -.. include:: /tutorials-and-examples/blog/part-two.rst - -Lectura Adicional -================= - -.. toctree:: - :maxdepth: 1 - - getting-started/a-typical-cakephp-request - getting-started/cakephp-conventions - getting-started/cakephp-folder-structure - getting-started/cakephp-structure diff --git a/es/getting-started/a-typical-cakephp-request.rst b/es/getting-started/a-typical-cakephp-request.rst deleted file mode 100644 index 114b758c2154d4c9d3fe3c47b5661585ba654887..0000000000000000000000000000000000000000 --- a/es/getting-started/a-typical-cakephp-request.rst +++ /dev/null @@ -1,51 +0,0 @@ -Diseccionando un Request típico en CakePHP -########################################## - -Ya hemos cubierto los ingredientes básicos de CakePHP, así que ahora vamos a -ver cómo interactúan sus componentes para completar una petición de usuario -o Request. Continuando con nuestro ejemplo anterior, imaginemos que nuestro -amigo Ricardo acaba de pinchar en el link "Compra un Pastel Personalizado" -en una aplicación CakePHP. - -.. figure:: /_static/img/typical-cake-request.png - :align: center - :alt: Diagrama de flujo que muestra un Request típico en CakePHP - - Diagrama de flujo que muestra un Request típico en CakePHP - -Diagrama: 2. Request típico CakePHP. - -Negro = elemento requerido, Gris = elemento opcional, Azul = retorno (callback) - - -#. Ricardo pincha en el enlace que apunta a - http://www.example.com/cakes/buy, y su navegador realiza una petición - (request) al servidor web. -#. El Router interpreta la URL para extraer los parámetros para esta petición: - el controlador, la acción y cualquier otro argumento que afecte a la lógica - de negocio durante el request. -#. Usando las rutas, se construye una URL objetivo relacionada con una acción - de un controlador (un método específico en una clase controlador). En este - caso se trata del método buy() del controlador CakesController. El callback - beforeFilter() de este controlador es invocado antes de ejecutar ningún otro - método. -#. El controlador puede utilizar uno o varios modelos para acceder a los datos. - En este ejemplo, el controlador utiliza un modelo para recuperar las últimas - compras que ha hecho Ricardo de la Base de Datos. Cualquier callback del - modelo, comportamiento (behavior), o DataSource que sea aplicable puede ser - ejecutado en este momento. Aunque utilizar un modelo no es obligatorio, todos - los controladores de CakePHP requieren inicialmente un modelo. -#. Una vez el modelo ha recuperado los datos, es devuelto al controlador. Se - aplican aquí los callbacks del modelo. -#. El controlador puede utilizar componentes para refinar los datos o realizar - otras operaciones (manipular la sesión, autenticación o enviar emails, por - ejemplo). -#. Una vez el controlador ha empleado los modelos y componentes para preparar - los datos, se envían a la vista utilizando el método set(). Los callback - del controlador pueden ser ejecutados antes de que los datos sean enviados. - La lógica de la vista se realiza en este punto. Esto puede incluír el uso de - elementos (elements) y/o helpers. Por defecto, las vistas son generadas - dentro de una plantilla (layout). -#. Callback adicionales pueden ejecutarse ahora (como afterFilter) en el - controlador. La vista, ya generada por completo, se envía al navegador de - Ricardo, que puede realizar su crítica compra de Pastel Personalizado. diff --git a/es/getting-started/cakephp-conventions.rst b/es/getting-started/cakephp-conventions.rst deleted file mode 100644 index 5aeb7a494a3a1edb1e5358a13a2836e66418c276..0000000000000000000000000000000000000000 --- a/es/getting-started/cakephp-conventions.rst +++ /dev/null @@ -1,179 +0,0 @@ -Convenciones en CakePHP -####################### - -(Nota del Traductor: Posiblemente la traducción de "conventions" sea muy -literal. Queremos expresar el uso por defecto de determinados acuerdos que -nos permiten establecer un marco común de trabajo). - -Preferimos el uso de convenciones sobre la configuración. Aunque ocuparás -algo de tu tiempo aprendiendo las convenciones usadas en CakePHP, ahorrarás -mucho más en el camino. Cuando usas las convenciones, aprovechas funcionalidad -gratuita y te liberas de la pesadilla de mantener los ficheros de configuración. -Trabajar con convenciones también estandariza el proceso de despliegue de tu -aplicación, permitiendo a otros desarrolladores conocer tu estructura más -fácilmente. - -Hemos empleado varios años y toda nuestra experiencia y buenas prácticas en -la creación de estas convenciones. Ya sabes que, aunque te recomendamos que -las sigas, puedes evitarlas con facilidad. Esto te resultará especialmente -útil cuando trates con sistemas legados. - -Convenciones en los Controladores -================================= - -Nombre del Controlador en plural, CamelCased, y colocando ``Controller`` al -final. ``PeopleController`` y ``LatestArticlesController`` son ejemplos que -siguen esta convención. - -El primer método a escribir en el controlador es ``index()``. Cuando una petición -vaya dirigida a este controlador, pero no se especifique acción, CakePHP -ejecutará por defecto el método ``index()``. Por ejemplo, la petición -http://example.com/apples/ será dirigida al método ``index()`` del controlador -``ApplesController``, así como la llamada a http://example.com/apples/view/ se -mapeará al método ``view()`` de este mismo controlador. - -Puedes cambiar la visibilidad de los métodos de CakePHP usando el carácter -subrayado "_" al principio para ocultar su acceso directo desde la web, aunque -será accesible internamente. Por ejemplo: - -:: - - class NewsController extends AppController - { - - function latest() - { - $this->_findNewArticles(); - } - - function _findNewArticles() - { - //Logic to find latest news articles - } - } - -El acceso a la url http://example.com/news/latest podrá realizarse con -normalidad, mientras que al acceder a la url -http://example.com/news/\_findNewArticles/ retornará un error, ya que -este método está precedido por un "_". También puedes usar los modificadores -de visibilidad de PHP (private, protected, public) para esto. Los métodos -que no sean públicos, no podrán ser accedidos. - -Consideraciones para las URL de los controladores -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Como acabas de ver, los controladores que tienen nombres de una sóla palabra -se asignan a una URL en minúscula. Por ejemplo ``ApplesController`` (que se -definirá en el fichero con nombre ApplesController.php) se accederá desde la -URL http://example.com/apples. - -Controladores cuyo nombre tiene varias palabras podrían ser asignados de -cualquiera de estas formas - -- /redApples -- /RedApples -- /Red\_apples -- /red\_apples - -todos ellos resolverían al método index del controlador RedApples. De todos -la convención es que esa url sea minúscula y subrayada, de este modo - -- /red\_apples/go\_pick sería la url correcta para acceder a ``RedApplesController::go_pick`` - -Para más información sobre URLs y parámetros en CakePHP, consulta -:ref:`routes-configuration`. - -.. _file-and-classname-conventions: - -Convenciones sobre nombres de fichero y nombres de clases -========================================================= - -Como regla general, los nombres de fichero y los nombres de clase serán -iguales, en formato CamelCased. Si tienes una clase **MyNiftyClass**, el -fichero que la contiene se llamará **MyNiftyClass.php**. En el listado -siguiente se muestran algunos ejemplos típicos utilizados en una aplicación -CakePHP: - -- El Controlador con nombre **KissesAndHugsController** estará en el - fichero **KissesAndHugsController.php** -- El Componente con nombre **MyHandyComponent** estará en el fichero - **MyHandyComponent.php** -- La Tabla **OptionValuesTable** estará en el fichero **OptionValuesTable.php** -- La Entidad **OptionValue** estará en el fichero **OptionValue.php** -- El Comportamiento (Behavior) **EspeciallyFunkableBehavior** estará en el - fichero **EspeciallyFunkableBehavior.php** -- La Vista **SuperSimpleView** estará en el fichero **SuperSimpleView.php** -- El Ayudante (Helper) **BestEverHelper** estará en el fichero - **BestEverHelper.php** - -Cada uno de estos ficheros estará ubicado en su carpeta correspondiente en tu -directorio app. - -Convenciones para modelos y bases de datos -========================================== - -Los nombres de clase para las Tablas serán CamelCased. Personas (People), -PersonasGrandes (BigPeople) y PersonasSuperGrandes (ReallyBigPeople), son -ejemplos válidos para modelos. - -Los nombres de Tablas correspondientes a modelos CakePHP son plurales y en -formato subrayado (underscored). Los nombres de las tablas para los modelos -mencionados arriba serían ``personas`` (people), ``personas_grandes`` -(big\_people) y ``personas_super_grandes`` (really\_big\_people) respectivamente. - -Puedes utilizar la librería de utilidad :php:class:`Cake\\Utility\\Inflector` -para comprobar el singular/plural de las palabras. Echa un vistazo a -:doc:`/core-utility-libraries/inflector` para más información. - -Los nombres de campos con dos o más palabras serán separados con guiones -bajos (underscored): -first\_name. - -Las claves foráneas o ajenas (foreign keys) en las relaciones 'a muchos' -(hasMany), 'pertenece a' (belongsTo) y 'a uno' (hasOne) se reconocen por -defecto si el nombre del campo se escribe usando el singular de la tabla -con la que se relaciona y terminando en \_id. Así pues, si Bakers hasMany -Cakes, la tabla de los pasteles referirá a la de pasteleros vía una clave -foránea baker\_id. Para una tabla como category\_types cuyo nombre -contiene múltiples palabras, la clave foránea sería category\_type\_id. - -Las tablas relacionales, utilizadas en relaciones 'de muchos a muchos' -(hasAndBelongsToMany o HABTM) entre modelos, deben ser nombradas con los -nombres de ambas tablas relacionadas ordenadas alfabéticamente y underscored -(mejor abejas\_zebras que zebras\_abejas). - -Convenciones en las vistas -========================== - -Los nombres de las vistas son iguales a los del método del controlador al que -hacen referencia, en formato subrayado. Por ejemplo el método getReady() del -controlador PeopleController buscará el fichero de vista en la ruta -/src/Template/People/get\_ready.ctp. - -El patrón para nombrar las vistas es -/src/Template/Controller/nombre\_de\_function\_subrayada.ctp. - -Si usas las convenciones de CakePHP para tu aplicación ganas inmediatamente -funcionalidad, que se mantiene sola y no necesita tocar la configuración. -Sirva para ilustrar esto un ejemplo: - -- Tabla en la base de datos: "people" -- Clase de Tabla: "PeopleTable", hayado en /src/Model/Table/PeopleTable.php -- Clase de Entidad: "Person" (es el singular de people en inglés), hayado - en /src/Model/Entity/Person.php -- Controlador: "PeopleController", hayado en - /src/Controller/PeopleController.php -- Plantilla para la vista, hayado en /src/Template/People/index.ctp - -Si usas estas convenciones, CakePHP sabrá que una llamada a -http://example.com/people/ se mapeará a una llamada al método ``index()`` -del controlador PeopleController, donde el modelo Person será instanciado -automáticamente para su uso (y automáticamente leerá los datos de la tabla -'people' en la base de datos). Ninguna de estas relaciones necesita ser creada -ni configurada si nombras de la forma correcta los ficheros que, de todos modos, -tienes que crear para que tu aplicación funcione. - -Ahora conoces los fundamentos y convenciones que debes utilizar en CakePHP, -te recomendamos que le eches un vistazo al -:doc:`/tutorials-and-examples/blog/blog` para ver cómo encajan estas piezas en -una aplicación completa. diff --git a/es/getting-started/cakephp-folder-structure.rst b/es/getting-started/cakephp-folder-structure.rst deleted file mode 100644 index 9930442ce7350c83fdc3eeea70957e0e811a810f..0000000000000000000000000000000000000000 --- a/es/getting-started/cakephp-folder-structure.rst +++ /dev/null @@ -1,65 +0,0 @@ -Estructura de Directorios de CakePHP -#################################### - -Una vez has descargado y extraído el fichero, estos son los -directorios y ficheros que verás: - -- src -- config -- tests -- plugins -- tmp -- vendor -- webroot -- .htaccess -- composer.json -- index.php -- README - -Verás que tienes varios directorios principales: - -- El directorio *src* que es donde harás tu magia: aquí guardarás - los ficheros de tu aplicación. -- El directorio *config* es donde residen los (pocos) ficheros de - :doc:`/development/configuration` que usa CakePHP, concretamente - la conexión con la base de datos, "bootstrapping" o el fichero - de arranque, la configuración del núcleo y otros ficheros también - de configuración estarán aquí. -- El directorio *tests* que es donde pondrás los tests de tu aplicación. -- El directorio *plugins* donde se guardan los :doc:`/plugins` que utiliza - tu aplicación. -- El directorio *vendor* es donde se instalan CakePHP y otras dependencias. - Anota mentalmente que **no debes** editar ficheros en este directorio. No - podemos ayudarte si has modificado el núcleo. -- El directorio *webroot* es la raíz pública de tu aplicación. Contiene - todos los ficheros que quieres que sean accesibles públicamente. -- El directorio *tmp* es donde CakePHP guarda datos temporales. Los datos - que guarda dependen en cómo hayas configurado CakePHP, pero este directorio - es usualmente ulizado para guardar descripciones de modelos, logs y a veces - información de sesión. - -El Directorio Src -================= - -En este directorio es donde realizarás la mayor parte del desarrollo de tu -aplicación. Veamos el contenido de esta carpeta: - -Console - Contiene los comandos de consola y las tareas de consola para tu - aplicación. Este directorio también contiene una carpeta ``Templates`` - para personalizar la salida de bake. Para más información echa un vistazo - a :doc:`/console-and-shells`. -Controller - Contiene los ficheros donde están definidos los Controladores de tu - aplicación y los componentes. -Locale - Contiene ficheros de cadenas de texto para internacionalización. -Model - Contiene las tablas, entidades y comportamientos (behaviors) de tu - aplicación. -View - Las clases de presentación (vistas) se colocan aquí: celdas (cells), helpers - y ficheros de vistas. -Template - Contiene los ficheros vistas: elementos, páginas de error, plantillas y - ficheros de vista. diff --git a/es/getting-started/cakephp-structure.rst b/es/getting-started/cakephp-structure.rst deleted file mode 100644 index a770006d72989f7039f328d8d09b6f30dc560802..0000000000000000000000000000000000000000 --- a/es/getting-started/cakephp-structure.rst +++ /dev/null @@ -1,103 +0,0 @@ -Estructura de CakePHP -##################### - -CakePHP implementa las clases para controladores, modelos y vistas, pero -también incluye otras clases y objetos que aceleran y facilitan el desarrollo -en un framework MVC y lo hacen más ameno. Componentes, Comportamientos -(Behaviors) y Helpers, son clases que favorecen la extensibilidad y -reutilización de tu código entre proyectos. Empezaremos con una visión de alto -nivel y luego examinaremos los detalles de cada parte. - -.. _application-extensions: - -Extensiones para las Aplicaciones -================================= - -Los controladores, helpers y modelos tienen todos una clase padre que puedes -emplear para definir cambios en toda tu aplicación. AppController, que está -en ``/src/Controller/AppController.php``), AppHelper en -``/src/View/Helper/AppHelper.php`` y AppModel en ``/src/Model/AppModel.php`` -son lugares apropiados para colocar métodos que quieras compartir entre todos -tus controladores, helpers y modelos. - -Aunque no sean clases ni ficheros, las rutas juegan un papel importante en las -peticiones que se realizan a CakePHP. Las definiciones de rutas le indican al -sistema cómo debe mapear las URLs a las acciones de los controladores. El -comportamiento por defecto es asumir que la ruta -``/controller/action/var1/var2`` se mapea a Controller::action($var1, $var2), -pero puedes usar las rutas para personalizar esto y definir cómo quieres que -sea interpretada cada URL. - -Algunas funcionalidades de tu aplicación se merecen ser empaquetadas para ser -usadas como un conjunto. Un plugin es un paquete de modelos, controladores, -vistas, etc. que siguen un objetivo común que puede reutilizarse en otros -proyectos. Un sistema de gestión de usuarios o un blog podrían ser buenos -candidatos para escribir un plugin y utilizarlo en múltiples proyectos. - -Extensiones de Controladores ("Components") -=========================================== - -Un Componente (Component) es una clase que da soporte a la lógica de los -controladores. Si tienes lógica que quieres reutilizar entre controladores, o -proyectos, un componentes es el lugar ideal para hacerlo. Por ejemplo, -EmailComponent es un componente de CakePHP que te permite crear y enviar emails -de forma sencilla. En vez de escribir el código para ello en un controlador o -varios, se ha empaquetado en un componente reutilizable. - -Los controladores poseen "callbacks". Estos callbacks te permiten inyectar -funcionalidad en el proceso normal de CakePHP. Los callbacks disponibles -incluyen: - -- :php:meth:`~Controller::afterFilter()`, ejecutado después de toda la lógica - del controlador, incluida la renderización de la vista. -- :php:meth:`~Controller::beforeFilter()`, ejecutado antes de toda la lógica - del controlador. -- :php:meth:`~Controller::beforeRender()`, ejecutado tras la lógica del - controlador, pero antes de que la vista sea renderizada. - -Extensiones de Tablas ("Behaviors") -=================================== - -De forma similar, los Comportamientos o "Behaviors" son formas de compartir -funcionalidades entre los modelos. Por ejemplo, si guardas datos de usuario -en una estructura tipo árbol, puedes especificar que tu modelo Usuario se -comporte como un árbol, y obtener gratis las funciones para eliminar, añadir, -e intercambiar nodos en tu estructura. - -Los modelos también son potenciados por otra clase llamada fuente de datos o -DataSource. Las fuentes de datos son una abstracción que permite a los modelos -manipular diferentes tipos de datos de manera consistente. La fuente de datos -habitual en una aplicación CakePHP es una base de datos relacional. Puedes -escribir fuentes de datos adicionales para representar "feeds" RSS, ficheros -CSV, servicios LDAP o eventos iCal. Las fuentes de datos te permiten asociar -registros de diferentes orígenes: en vez de estar limitado a consultas SQL, -las fuentes de datos te permitirían decirle a tu modelo LDAP que está -asociado a múltiples eventos iCal. - -Igual que los controladores, los modelos poseen callbacks: - -- beforeFind() -- beforeValidate() -- afterValidate() -- beforeSave() -- afterSave() -- beforeDelete() -- afterDelete() - -Los nombres de estos métodos deberían ser descriptivos por sí mismos. -Encontrarás todos los detalles en el capítulo que habla sobre los modelos. - -Extensiones de Vistas ("Helpers") -================================= - -Un helper es una clase que sirve de apoyo a las vistas. De forma similar a -los componentes y los controladores, los helpers permiten que la lógica que -usas en las vistas se pueda acceder desde otras vistas o en otras aplicaciones. -Uno de los helpers que se distribuye con CakePHP es AjaxHelper, permite que se -realicen llamadas Ajax desde las vistas de forma mucho más sencilla. - -La mayoría de aplicaciones tiene trozos de código que se usan una y otra vez. -CakePHP facilita la reutilización de código con plantillas y elementos. Por -defecto cada vista que se genera por un controlador se incrusta dentro de una -plantilla. Los elementos se usan como un modo sencillo de empaquetar código -para poder ser usado en cualquier vista. diff --git a/es/index.rst b/es/index.rst index eecec6ce13266fcc8583fdcca353a1136f302810..cb748d86e9030bf4fdcc574f2ed3846498b5414a 100644 --- a/es/index.rst +++ b/es/index.rst @@ -1,6 +1,10 @@ Bienvenido ########## +.. warning:: + This version of the documentation is for CakePHP 3.0. Go `here for the + CakePHP 2.x documentation `_. + El manual de CakePHP es un proyecto de documentación abierto, editable y mantenido por la comunidad. Toma en cuenta el botón de "Improve this doc" en la parte superior derecha; te llevará al editor online de Github de la @@ -22,17 +26,17 @@ a la documentación actual. Empezando con CakePHP ===================== -Aprender un nuevo framework puede ser intimidante y divertido al mismo tiempo. +Aprender un nuevo framework puede ser intimidante y divertido al mismo tiempo. Para ayudarte hemos creado un recetario lleno de ejemplos y recetas que te -van a ayudar a realizar tareas básicas. Si eres nuevo, es recomendado que comiences -con el :doc:`/tutorials-and-examples/blog/blog` porque te dará un tour inicial +van a ayudar a realizar tareas básicas. Si eres nuevo, es recomendado que comiences +con el :doc:`/tutorials-and-examples/blog/blog` porque te dará un tour inicial de CakePHP, cómo funciona y lo que puede hacer por ti. Después de terminar el Tutorial del Blog, puedes conocer mejor los elementos claves que conforman una aplicación de CakePHP: -* El :doc:`CakePHP request cycle ` -* Las :doc:`Convenciones ` utilizadas por CakePHP. +* The :ref:`CakePHP request cycle `. +* Las :doc:`Convenciones ` utilizadas por CakePHP. * Los :doc:`Controladores ` que manejan los http requests, coordinan los modelos y generan las respuestas que la aplicación necesita. * Las :doc:`Vistas ` son la capa de presentación de tu aplicación. Proveen @@ -45,7 +49,7 @@ Getting Help ============ Si te atascas, hay muchos sitios en los que :doc:`puedes obtener ayuda -`. +`. .. meta:: diff --git a/es/installation.rst b/es/installation.rst index 58939f3fe55dd111dd06b871a5038874d7f5a119..d1e58a573e0381c7061867285a8e161ff1d21388 100644 --- a/es/installation.rst +++ b/es/installation.rst @@ -36,15 +36,17 @@ Licencia CakePHP está licenciado bajo la `Licencia MIT `_. Esto -signigica que eres libre para modificar, distribuir y republicar el código fuente -con la condición de que las notas de copyright queden intactas. También eres libre -para incorporar CakePHP en cualquier aplicación comercial o de código cerrado. +signigica que eres libre para modificar, distribuir y republicar el código +fuente con la condición de que las notas de copyright queden intactas. También +eres libre para incorporar CakePHP en cualquier aplicación comercial o de código +cerrado. Instalando CakePHP ================== -CakePHP utiliza `Composer `_, una herramienta de manejo de -dependicias para PHP 5.3+, como el método de instalación oficialmente soportado. +CakePHP utiliza `Composer `_, una herramienta de manejo +de dependicias para PHP 5.3+, como el método de instalación oficialmente +soportado. Primero, necesitas descargar e instalar Composer, si no lo has hecho ya. Si tienes instalado cURL, es tan fácil como correr esto en un terminal:: @@ -62,11 +64,11 @@ instrucciones acerca de esto, puedes leer el README del instalador de Windows Ya que has decargado e instalado Composer puedes generar una aplicación CakePHP ejecutando:: - php composer.phar create-project --prefer-dist -s dev cakephp/app [app_name] + php composer.phar create-project --prefer-dist cakephp/app [app_name] O si tienes Composer definido globalmente:: - composer create-project --prefer-dist -s dev cakephp/app [app_name] + composer create-project --prefer-dist cakephp/app [app_name] Una vez que Composer termine de descargar el esqueleto y la librería core de CakePHP, deberías tener una aplicación funcional de CakePHP instalada @@ -83,19 +85,20 @@ Si quieres mantenerte al corriente de los últimos cambios en CakePHP puedes añadir las siguientes líneas al ``composer.json`` de tu aplicación:: "require": { - "cakephp/cakephp": "dev-" + "cakephp/cakephp": "dev-master" } -Donde ```` es el nombre del branch que quieres seguir. Cada vez que ejecutes -``php composer.phar update`` recibirás las últimas actualizaciones del branch seleccionado. +Donde ```` es el nombre del branch que quieres seguir. Cada vez que +ejecutes ``php composer.phar update`` recibirás las últimas actualizaciones del +branch seleccionado. Permisos ======== CakePHP utiliza el directorio ``tmp`` para varias operaciones. Descripciones de -Modelos, el caché de las vistas y la información de la sesión son algunos ejemplos -de lo anterior. El directorio ``logs`` es utilizado para para escribir ficheros -de log por el motor de ``FileLog`` por defecto. +Modelos, el caché de las vistas y la información de la sesión son algunos +ejemplos de lo anterior. El directorio ``logs`` es utilizado para para escribir +ficheros de log por el motor de ``FileLog`` por defecto. Asegúrate de que los directorios ``logs``, ``tmp`` y todos sus subdirectorios tengan permisos de escritura por el usuario del Servidor Web. La instalación @@ -140,37 +143,40 @@ Para ello ejecuta desde el directorio ``src``:: bin/cake server -Por defecto, sin ningún argumento, esto colocará tu aplicación en ``http://localhost:8765/``. +Por defecto, sin ningún argumento, esto colocará tu aplicación en +``http://localhost:8765/``. Si tienes algún conflicto con ``localhost`` o ``port 8765``, puedes indicarle -a la consola de CakePHP que corra el servidor de manera más específica utilizando -los siguientes argumentos:: +a la consola de CakePHP que corra el servidor de manera más específica +utilizando los siguientes argumentos:: bin/cake server -H 192.168.13.37 -p 5673 Esto colocará tu aplicación en ``http://192.168.13.37:5673/``. -Eso es todo! Tu aplicación de CakePHP está corriendo perfectamente sin tener que haber -configurado el servidor web manualmente. +Eso es todo! Tu aplicación de CakePHP está corriendo perfectamente sin tener que +haber configurado el servidor web manualmente. .. warning:: - El servidor de desarrollo *nunca* debe ser utilizado en un ambiente de producción. - Se supone que esto es un servidor básico de desarrollo y nada más. + El servidor de desarrollo *nunca* debe ser utilizado en un ambiente de + producción. Se supone que esto es un servidor básico de desarrollo y nada + más. Producción ========== -Una instalación de producción es una manera más flexible de montar una aplicación de -CakePHP. Utilizando este método, podrás tener un dominio entero actuando como una -sola aplicación de CakePHP. Este ejemplo te ayudará a instalar CakePHP donde quieras -en tu sistema de ficheros y tenerlo disponible en ``http://www.example.com``. Toma -en cuenta que esta instalación requiere que tengas los derechos de cambiar el -directorio raíz (``DocumentRoot``) del servidor web Apache. +Una instalación de producción es una manera más flexible de montar una +aplicación de CakePHP. Utilizando este método, podrás tener un dominio entero +actuando como una sola aplicación de CakePHP. Este ejemplo te ayudará a instalar +CakePHP donde quieras en tu sistema de ficheros y tenerlo disponible en +``http://www.example.com``. Toma en cuenta que esta instalación requiere que +tengas los derechos de cambiar el directorio raíz (``DocumentRoot``) del +servidor web Apache. -Después de instalar tu aplicación utilizando cualquiera de los métodos mencionados -en el directorio elegido - asumiremos que has escogido /cake_install - tu estructura -de ficheros debe ser la siguiente:: +Después de instalar tu aplicación utilizando cualquiera de los métodos +mencionados en el directorio elegido - asumiremos que has escogido /cake_install +- tu estructura de ficheros debe ser la siguiente:: /cake_install/ bin/ @@ -203,11 +209,6 @@ URL Rewriting Si quieres utilizar URL rewriting, entra en la sección dedicada a ello: -.. toctree:: - :maxdepth: 1 - - installation/url-rewriting - A rodar! ======== @@ -217,8 +218,8 @@ o http://localhost:8765/. En este punto, encontrás el home principal de CakePHP y un mensaje que te dice el status actual de tu conexión a la base de datos. -Felicidades! Estás listo para :doc:`Crear tu primera aplicación de CakePHP `. - +Felicidades! Estás listo para +:doc:`Crear tu primera aplicación de CakePHP `. .. _GitHub: http://github.com/cakephp/cakephp .. _Composer: http://getcomposer.org diff --git a/es/installation/url-rewriting.rst b/es/installation/url-rewriting.rst deleted file mode 100644 index 208eeff451f5900df0640d6aa89385bd89a4c3d0..0000000000000000000000000000000000000000 --- a/es/installation/url-rewriting.rst +++ /dev/null @@ -1,230 +0,0 @@ -URL Rewriting -############# - -Apache y mod\_rewrite (y .htaccess) -=================================== - -A pesar de que CakePHP está diseñado para funcionar con mod\_rewrite -por defecto, hemos notado que algunos usuarios sufren con el proceso -de lograr que todo vaya perfectamente bien en sus sistemas. - -Aquí hay un par de cosas que puedes intentar para que funcione correctamente. -Primero, entra en tu http.conf. (Asegúrate de que estás editando el httpd.conf -del sistema general y no uno perteneciente a un sitio o usuario específico). - -Este archivo puede variar dependiendo de tu distribución y versión de Apache. -También puedes echar un vistazo en http://wiki.apache.org/httpd/DistrosDefaultLayout -para más información. - -#. Asegúrate de que un override en .htaccess está permitido y que - AllowOverride está en 'All' para el DocumentRoot deseado. Deberías - entonces ver algo así:: - - # Each directory to which Apache has access can be configured with respect - # to which services and features are allowed and/or disabled in that - # directory (and its subdirectories). - # - # First, we configure the "default" to be a very restrictive set of - # features. - # - - Options FollowSymLinks - AllowOverride All - # Order deny,allow - # Deny from all - - -#. Asegúrate de que mod\_rewrite está siendo cargado correctamente. - Deberías tener algo como:: - - LoadModule rewrite_module libexec/apache2/mod_rewrite.so - - En muchos sistemas, estas líneas estarán comentadas por defecto, así que - debes simplemente remover el símbolo # al principio de la línea. - - Después de hacer los cambios reinicia Apache para cerciorarte de que - los cambios estén activos. - - Verifica que tus ficheros .htaccess están en el directorio correcto. - Algunos sistemas operativos esconden por defecto los archivos que - comienzan con '.' y pueden no copiarlos bajo ciertas circunstancias. - -#. Asegúrate de que tu copia de CakePHP proviene de las secciones de descarga - de la página web o del repositorio de Github y que ha sido desempacado - correctamente chequeando los archivos .htaccess. - - En el directorio 'app' de CakePHP (será copiado en la raíz de tu aplicación - por el comando bake):: - - - RewriteEngine on - RewriteRule ^$ webroot/ [L] - RewriteRule (.*) webroot/$1 [L] - - - En el directorio 'webrot' de CakePHP (será copiado en tu aplicación - por el comando bake):: - - - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^ index.php [L] - - - Si tu sitio CakePHP aún tiene problemas con mod\_rewrite, podrías - intentar modificar los parámetros de tus Hosts Virtuales. En Ubuntu, - edita el fichero /etc/apache2/sites-available/default (la ubicación - depende de tu distribución). En este fichero, asegúrate de que - ``AllowOverride None`` está cambiado por ``AllowOverride All``, así:: - - - Options FollowSymLinks - AllowOverride All - - - Options Indexes FollowSymLinks MultiViews - AllowOverride All - Order Allow,Deny - Allow from all - - - En Mac OSX, otra solución es utilizar la herramienta - `virtualhostx `_ - para hacer que un host virtual apunte a tu aplicación. - - En muchos servicios de hosting (GoDaddy, 1and1), tu servidor web está - en realidad siendo llamado desde un directorio de usuario que ya usa - mod\_rewrite. Si estás instalando CakePHP en un directorio de usuario - (http://example.com/~username/cakephp/), u otra estructura de URL que - ya utiliza mod\_rewrite, necesitarás acceso para introducir reglas RewriteBase - en los ficheros .htaccess utilizados por CakePHP uses (.htaccess, - webroot/.htaccess). - - Esto puede ser añadido a la misma sección con la directiva de RewriteEngine - así que por ejemplo, tu .htaccess del webroot .htaccess se vería así:: - - - RewriteEngine On - RewriteBase /path/to/app - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^ index.php [L] - - - Los detalles de esos cambios dependerán de tu configuración, y pueden - incluir cosas adicionales que no están relacionadas con CakePHP. Por favor - visita la documentación online de Apache para más información. - -#. (Opcional) Para mejorar la configuración de producción, deberías prevenir - que fuentes inválidas sean leídas por CakePHP. Modifica el .htaccess de - webroot para que parezca algo como:: - - - RewriteEngine On - RewriteBase /path/to/app/ - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_URI} !^/(webroot/)?(img|css|js)/(.*)$ - RewriteRule ^ index.php [L] - - - Lo anterior prevendrá que ficheros incorrectos sean enviados a index.php - y desplegará un error 404 de tu servidor web. - - Adicionalmente, puedes crear un archivo 404 de HTML o utilizar el - archivo nativo de CakePHP para errores 404 al añadir la directiva:: - - ErrorDocument 404 /404-not-found - -nginx -===== - -nginx no utiliza los archivos .htaccess como Apache, así que es necesario que -crees las URLs reescritas en la configuración de sites-available. Dependiendo -de tu configuración tendrás que modificar esto, pero en el menor de los casos -tendrás a PHP corriendo como una instancia de FastCGI:: - - server { - listen 80; - server_name www.example.com; - rewrite ^(.*) http://example.com$1 permanent; - } - - server { - listen 80; - server_name example.com; - - # root directive should be global - root /var/www/example.com/public/webroot/; - index index.php; - - access_log /var/www/example.com/log/access.log; - error_log /var/www/example.com/log/error.log; - - location / { - try_files $uri $uri/ /index.php?$args; - } - - location ~ \.php$ { - try_files $uri =404; - include /etc/nginx/fastcgi_params; - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - } - } - -URL Rewrites en IIS7 (Windows hosts) -==================================== - -IIS7 no soporta archivos .htacces de manera nativa. A pesar de que existen -add-ons que pueden añadir esta función, puedes también importar reglas -de htaccess en IIS para que utilicen los rewrites nativos de CakePHP. -Para hacer esto, sigue estos sencillos pasos: - - -#. Utiliza el `Instalador de Plataforma Web de Microsoft `_ para instalar el - `Rewrite Module 2.0 `_ o descárgalo directamente (`32-bit `_ / `64-bit `_). -#. Crea un nuevo fichero llamado web.config en tu raíz de CakePHP. -#. Utilizando un editor de XML confiable, copia lo siguiente en dicho archivo... - -:: - - - - - - - - - - - - - - - - - - - - - - - -Una vez hayas modificado el web.config con las reglas correctas y compatibles -con IIS, podrás ver que los links, archivos CSS, archivos de Javascript y el -rerouting de CakePHP debe funcionar correctamente. - -No me interesa / No puedo usar URL Rewriting -============================================ - -Si no puedes o no quieres utilizar URL Rewriting en tu servidor web -entra en :ref:`configuración de core `. - - -.. meta:: - :title lang=es: URL Rewriting diff --git a/es/intro.rst b/es/intro.rst new file mode 100644 index 0000000000000000000000000000000000000000..4b0511dbcdb170bc9a659cd758568aa40c8edb8f --- /dev/null +++ b/es/intro.rst @@ -0,0 +1,25 @@ +CakePHP at a Glance +################### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +Additional Reading +================== + +.. toctree:: + :maxdepth: 1 + + /intro/where-to-get-help + /intro/conventions + /intro/cakephp-folder-structure + +.. meta:: + :title lang=es: Getting Started + :keywords lang=es: folder structure,table names,initial request,database table,organizational structure,rst,filenames,conventions,mvc,web page,sit diff --git a/es/intro/cakephp-folder-structure.rst b/es/intro/cakephp-folder-structure.rst new file mode 100644 index 0000000000000000000000000000000000000000..8c1fa7b8f868f0362e6485273ccae761a256f5b9 --- /dev/null +++ b/es/intro/cakephp-folder-structure.rst @@ -0,0 +1,15 @@ +CakePHP Folder Structure +######################## + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: CakePHP Folder Structure + :keywords lang=es: internal libraries,core configuration,model descriptions,external vendors,connection details,folder structure,party libraries,personal commitment,database connection,internationalization,configuration files,folders,application development,readme,lib,configured,logs,config,third party,cakephp diff --git a/es/intro/conventions.rst b/es/intro/conventions.rst new file mode 100644 index 0000000000000000000000000000000000000000..9e754538fe4632bb3d61f7dfadd125e5dff1c86d --- /dev/null +++ b/es/intro/conventions.rst @@ -0,0 +1,15 @@ +CakePHP Conventions +################### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: CakePHP Conventions + :keywords lang=es: web development experience,maintenance nightmare,index method,legacy systems,method names,php class,uniform system,config files,tenets,apples,conventions,conventional controller,best practices,maps,visibility,news articles,functionality,logic,cakephp,developers diff --git a/es/intro/where-to-get-help.rst b/es/intro/where-to-get-help.rst new file mode 100644 index 0000000000000000000000000000000000000000..c609c2683acca400274b1d59d6eea077a14c9880 --- /dev/null +++ b/es/intro/where-to-get-help.rst @@ -0,0 +1,16 @@ +Where to Get Help +################# + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. + +.. meta:: + :title lang=es: Where to Get Help + :description lang=es: Where to get help with CakePHP: The official CakePHP website, The Cookbook, The Bakery, The API, in the test cases, the IRC channel, The CakePHP Google Group or CakePHP Questions. + :keywords lang=es: cakephp,cakephp help,help with cakephp,where to get help,cakephp irc,cakephp questions,cakephp api,cakephp test cases,open source projects,channel irc,code reference,irc channel,developer tools,test case,bakery diff --git a/es/migrations.rst b/es/migrations.rst new file mode 100644 index 0000000000000000000000000000000000000000..3c135c3aa825b382ff088c598ee2d2230e062f4b --- /dev/null +++ b/es/migrations.rst @@ -0,0 +1,13 @@ +Migrations +########## + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta + página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón + **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección + superior para obtener información sobre el tema de esta página. diff --git a/es/orm.rst b/es/orm.rst index 371f2140d5d805b98df606b054067011eda929ac..a41dadd7764d5b451127f365f7f9501ed548eccc 100644 --- a/es/orm.rst +++ b/es/orm.rst @@ -2,111 +2,13 @@ Models ###### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Models are the classes that sit as the business layer in your application. -This means that they should be responsible for managing almost everything -that happens regarding your data, its validity, interactions and evolution -of the information workflow in your domain of work. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -In CakePHP your application's domain model gets split into 2 primary object -types. The first are **repositories** or **table objects**. These objects -provide access to collections of data. They allow you to save new records, -modify/delete existing ones, define relations, and perform bulk operations. The -second type of objects are **entities**. Entities represent individual records -and allow you to define row/record level behavior & functionality. - -CakePHP's built-in ORM specializes in relational databases, but can be extended -to support alternative datasources. - -The CakePHP ORM borrows ideas and concepts from both ActiveRecord and Datamapper -patterns. It aims to create a hybrid implementation that combines aspects of -both patterns to create a fast, simple to use ORM. - -Before we get started exploring the ORM, make sure you :ref:`configure your -database connections `. - -.. note:: - - If you are familiar with previous versions of CakePHP, you should read the - :doc:`/appendices/orm-migration` for important differences between CakePHP 3.0 - and older versions of CakePHP. - -Quick Example -============= - -To get started you don't have to write any code. If you've followed the CakePHP -conventions for your database tables you can just start using the ORM. For -example if we wanted to load some data from our ``articles`` table we could do:: - - use Cake\ORM\TableRegistry; - $articles = TableRegistry::get('Articles'); - $query = $articles->find(); - foreach ($query as $row) { - echo $row->title; - } - -Note that we didn't have to create any code or wire any configuration up. -The conventions in CakePHP allow us to skip some boilerplate code, and allow the -framework to insert base classes when your application has not created -a concrete class. If we wanted to customize our ArticlesTable class adding some -associations or defining some additional methods we would add the following to -``src/Model/Table/ArticlesTable.php`` after the ``find(); - - foreach ($query as $row) { - // Each row is now an instance of our Article class. - echo $row->title; - } - -CakePHP uses naming conventions to link the Table and Entity class together. If -you need to customize which entity a table uses you can use the -``entityClass()`` method to set a specific classname. - -See the chapters on :ref:`table-objects` and :ref:`entities` for more information -on how to use table objects and entities in your application. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. More Information ================ @@ -114,10 +16,15 @@ More Information .. toctree:: :maxdepth: 2 + orm/database-basics orm/query-builder orm/table-objects orm/entities + orm/retrieving-data-and-resultsets + orm/validation + orm/saving-data + orm/deleting-data + orm/associations orm/behaviors - orm/database-basics orm/schema-system console-and-shells/orm-cache diff --git a/es/orm/associations.rst b/es/orm/associations.rst new file mode 100644 index 0000000000000000000000000000000000000000..fa8b76ce1aa0ba8979a43f1463379ee51373828f --- /dev/null +++ b/es/orm/associations.rst @@ -0,0 +1,11 @@ +Associations - Linking Tables Together +###################################### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/behaviors.rst b/es/orm/behaviors.rst index 43f61d01a6e49c2cf3ca7aea1768b1ec6647e117..d5b14b228a0e70489f4cd703d00a50502d24ddc8 100644 --- a/es/orm/behaviors.rst +++ b/es/orm/behaviors.rst @@ -2,220 +2,21 @@ Behaviors ######### .. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. + La documentación no es compatible actualmente con el idioma español en esta página. -Behaviors are a way to organize and enable horizontal re-use of Model layer -logic. Conceptually they are similar to traits. However, behaviors are -implemented as separate classes. This allows them to hook into the -life-cycle callbacks that models emit, while providing trait-like features. + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -Behaviors provide a convenient way to package up behavior that is common across -many models. For example, CakePHP includes a ``TimestampBehavior``. Many -models will want timestamp fields, and the logic to manage these fields is -not specific to any one model. It is these kinds of scenarios that behaviors are -a perfect fit for. - -Using Behaviors -=============== - -.. include:: ./table-objects.rst - :start-after: start-behaviors - :end-before: end-behaviors + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. Core Behaviors ============== -.. include:: ../core-libraries/toc-behaviors.rst - :start-after: start-toc - :end-before: end-toc - -Creating a Behavior -=================== - -In the following examples we will create a very simple ``SluggableBehavior``. -This behavior will allow us to populate a slug field with the results of -``Inflector::slug()`` based on another field. - -Before we create our behavior we should understand the conventions for -behaviors: - -- Behavior files are located in ``src/Model/Behavior``, or - ``MyPlugin\Model\Behavior``. -- Behavior classes should be in the ``App\Model\Behavior`` namespace, or - ``MyPlugin\Model\Behavior`` namespace. -- Behavior class names end in ``Behavior``. -- Behaviors extend ``Cake\ORM\Behavior``. - -To create our sluggable behavior. Put the following into -``src/Model/Behavior/SluggableBehavior.php``:: - - namespace App\Model\Behavior; - - use Cake\ORM\Behavior; - - class SluggableBehavior extends Behavior - { - } - -We can now add this behavior to one of our table classes. In this example we'll -use an ``ArticlesTable``, as articles often have slug properties for creating -friendly URLs:: - - namespace App\Model\Table; - - use Cake\ORM\Table; - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->addBehavior('Sluggable'); - } - } - -Our new behavior doesn't do much of anything right now. Next, we'll add a mixin -method and an event listener so that when we save entities we can automatically -slug a field. - -Defining Mixin Methods ----------------------- - -Any public method defined on a behavior will be added as a 'mixin' method on the -table object it is attached to. If you attach two behaviors that provide the -same methods an exception will be raised. If a behavior provides the same method -as a table class, the behavior method will not be callable from the table. -Behavior mixin methods will receive the exact same arguments that are provided -to the table. For example, if our SluggableBehavior defined the following -method:: - - public function slug($value) - { - return Inflector::slug($value, $this->_config['replacement']); - } - -It could be invoked using:: - - $slug = $articles->slug('My article name'); - -Limiting or Renaming Exposed Mixin Methods ------------------------------------------- - -When creating behaviors, there may be situations where you don't want to expose -public methods as mixin methods. In these cases you can use the -``implementedMethods`` configuration key to rename or exclude mixin methods. For -example if we wanted to prefix our slug() method we could do the following:: - - public $_defaultConfig = [ - 'implementedMethods' => [ - 'slug' => 'superSlug', - ] - ]; - -Applying this configuration will make ``slug()`` not callable, however it will -add a ``superSlug()`` mixin method to the table. Notably if our behavior -implemented other public methods they would **not** be available as mixin -methods with the above configuration. - -Since the exposed methods are decided by configuration you can also -rename/remove mixin methods when adding a behavior to a table. For example:: - - // In a table's initialize() method. - $this->addBehavior('Sluggable', [ - 'implementedMethods' => [ - 'slug' => 'superSlug', - ] - ]); - -Defining Event Listeners ------------------------- - -Now that our behavior has a mixin method to slug fields, we can implement -a callback listener to automatically slug a field when entities are saved. We'll -also modify our slug method to accept an entity instead of just a plain value. Our -behavior should now look like:: - - namespace App\Model\Behavior; - - use Cake\Event\Event; - use Cake\ORM\Behavior; - use Cake\ORM\Entity; - use Cake\Utility\Inflector; - - class SluggableBehavior extends Behavior - { - protected $_defaultConfig = [ - 'field' => 'title', - 'slug' => 'slug', - 'replacement' => '-', - ]; - - public function slug(Entity $entity) - { - $config = $this->config(); - $value = $entity->get($config['field']); - $entity->set($config['slug'], Inflector::slug($value, $config['replacement'])); - } - - public function beforeSave(Event $event, Entity $entity) - { - $this->slug($entity); - } - - } - -The above code shows a few interesting features of behaviors: - -- Behaviors can define callback methods by defining methods that follow the - :ref:`table-callbacks` conventions. -- Behaviors can define a default configuration property. This property is merged - with the overrides when a behavior is attached to the table. - -Defining Finders ----------------- - -Now that we are able to save articles with slug values, we should implement -a finder method so we can easily fetch articles by their slug. Behavior finder -methods, use the same conventions as :ref:`custom-find-methods` do. Our -``find('slug')`` method would look like:: - - public function findSlug(Query $query, array $options) - { - return $query->where(['slug' => $options['slug']]); - } - -Once our behavior has the above method we can call it:: - - $article = $articles->find('slug', ['slug' => $value])->first(); - -Limiting or Renaming Exposed Finder Methods -------------------------------------------- - -When creating behaviors, there may be situations where you don't want to expose -finder methods, or you need to rename finders to avoid duplicated methods. In -these cases you can use the ``implementedFinders`` configuration key to rename -or exclude finder methods. For example if we wanted to rename our ``find(slug)`` -method we could do the following:: - - public $_defaultConfig = [ - 'implementedFinders' => [ - 'slugged' => 'findSlug', - ] - ]; - -Applying this configuration will make ``find('slug')`` trigger an error. However -it will make ``find('slugged')`` available. Notably if our behavior implemented -other finder methods they would **not** be available, as they are not included -in the configuration. - -Since the exposed methods are decided by configuration you can also -rename/remove finder methods when adding a behavior to a table. For example:: +.. toctree:: + :maxdepth: 1 - // In a table's initialize() method. - $this->addBehavior('Sluggable', [ - 'implementedFinders' => [ - 'slugged' => 'findSlug', - ] - ]); + /orm/behaviors/counter-cache + /orm/behaviors/timestamp + /orm/behaviors/translate + /orm/behaviors/tree diff --git a/es/orm/behaviors/counter-cache.rst b/es/orm/behaviors/counter-cache.rst new file mode 100644 index 0000000000000000000000000000000000000000..54d9f62ef68861804c6a38305517b8423fc1927d --- /dev/null +++ b/es/orm/behaviors/counter-cache.rst @@ -0,0 +1,11 @@ +CounterCache Behavior +##################### + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/behaviors/timestamp.rst b/es/orm/behaviors/timestamp.rst new file mode 100644 index 0000000000000000000000000000000000000000..8a04850cb6606785f3295a178aff4234d1dd7dfd --- /dev/null +++ b/es/orm/behaviors/timestamp.rst @@ -0,0 +1,15 @@ +Timestamp Behavior +################## + +.. php:namespace:: Cake\Model\Behavior + +.. php:class:: TimestampBehavior + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/behaviors/translate.rst b/es/orm/behaviors/translate.rst new file mode 100644 index 0000000000000000000000000000000000000000..fd63bfffe918839349175303a26f2dc69064fc24 --- /dev/null +++ b/es/orm/behaviors/translate.rst @@ -0,0 +1,15 @@ +Translate +######### + +.. php:namespace:: Cake\Model\Behavior + +.. php:class:: TranslateBehavior + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/behaviors/tree.rst b/es/orm/behaviors/tree.rst new file mode 100644 index 0000000000000000000000000000000000000000..4a0a4def2c900fd4a269d643ddea8d3e358c79ed --- /dev/null +++ b/es/orm/behaviors/tree.rst @@ -0,0 +1,15 @@ +TreeBehavior +############ + +.. php:namespace:: Cake\Model\Behavior + +.. php:class:: TreeBehavior + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/database-basics.rst b/es/orm/database-basics.rst index e68a67b1018db687ec4f449807bd2cefe708dddb..308632c86529cdafab953af208331cd36a7677c9 100644 --- a/es/orm/database-basics.rst +++ b/es/orm/database-basics.rst @@ -1,627 +1,13 @@ Database Basics ############### -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - .. php:namespace:: Cake\Database -The ORM and database access in CakePHP has been totally rebuilt for 3.0. -It features a new fluent API for building queries, improved schema -reflection/generation, a flexible type system and more. - -.. _database-configuration: - -Configuration -============= - -By convention database connections are configured in ``config/app.php``. The -connection information defined in this file is fed into -:php:class:`Cake\\Datasource\\ConnectionManager` creating the connection configuration -your application will be using. Sample connection information can be found in -``config/app.default.php``. A sample connection configuration would look -like:: - - 'Datasources' => [ - 'default' => [ - 'className' => 'Cake\Database\Connection', - 'driver' => 'Cake\Database\Driver\Mysql', - 'persistent' => false, - 'host' => 'localhost', - 'username' => 'my_app', - 'password' => 'sekret', - 'database' => 'my_app', - 'encoding' => 'utf8', - 'timezone' => 'UTC', - 'cacheMetadata' => true, - ] - ], - -The above will create a 'default' connection, with the provided parameters. You -can define as many connections as you want in your configuration file. You can -also define additional connections at runtime using -:php:meth:`Cake\\Datasource\\ConnectionManager::config()`. An example of that -would be:: - - use Cake\Datasource\ConnectionManager; - - ConnectionManager::config('default', [ - 'className' => 'Cake\Database\Connection', - 'driver' => 'Cake\Database\Driver\Mysql', - 'persistent' => false, - 'host' => 'localhost', - 'username' => 'my_app', - 'password' => 'sekret', - 'database' => 'my_app', - 'encoding' => 'utf8', - 'timezone' => 'UTC', - 'cacheMetadata' => true, - ]); - -By default, all Table objects will use the ``default`` connection. To -use a non-default connection, see :ref:`configuring-table-connections`. - -There are a number of keys supported in database configuration. A full list is -as follows: - -className - The fully namespaced class name of the class that represents the connection to a database server. - This class is responsible for loading the database driver, providing SQL - transaction mechanisms and preparing SQL statements among other things. -driver - The class name of the driver used to implements all specificities for - a database engine. This can either be a short classname using :term:`plugin syntax`, - a fully namespaced name, or a constructed driver instance. - Examples of short classnames are Mysql, Sqlite, Postgres, and Sqlserver. -persistent - Whether or not to use a persistent connection to the database. -host - The database server's hostname (or IP address). -username - The username for the account. -password - The password for the account. -database - The name of the database for this connection to use. -port (*optional*) - The TCP port or Unix socket used to connect to the server. -encoding - Indicates the character set to use when sending SQL statements to - the server. This defaults to the database's default encoding for - all databases other than DB2. If you wish to use UTF-8 encoding - with MySQL connections you must use 'utf8' without the - hyphen. -timezone - Server timezone to set. -schema - Used in PostgreSQL database setups to specify which schema to use. -unix_socket - Used by drivers that support it to connect via Unix socket files. If you are - using PostgreSQL and want to use Unix sockets, leave the host key blank. -ssl_key - The file path to the SSL key file. (Only supported by MySQL). -ssl_cert - The file path to the SSL certificate file. (Only supported by MySQL). -ssl_ca - The file path to the SSL certificate authority. (Only supported by MySQL). -init - A list of queries that should be sent to the database server as - when the connection is created. This option is only - supported by MySQL, PostgreSQL, and SQL Server at this time. -dsn - A full PDO compatible data source name. -log - Set to true to enable query logging. When enabled queries will be logged - at a ``debug`` level with the ``queriesLog`` scope. -quoteIdentifiers - Set to true if you are using reserved words or special characters in your - table or column names. Enabling this setting will result in queries built using the - :ref:`query-builder` having identifiers quoted when creating SQL. It should be - noted that this decreases performance because each query needs to be traversed - and manipulated before being executed. -flags - An associative array of PDO constants that should be passed to the - underlying PDO instance. See the PDO documentation for the flags supported - by the driver you are using. -cacheMetadata - Either boolean true, or a string containing the cache configuration to store - meta data in. Having metadata caching disable is not advised and can result - in very poor performance. See the :ref:`database-metadata-cache` section - for more information. - -At this point, you might want to take a look at the -:doc:`/getting-started/cakephp-conventions`. The correct -naming for your tables (and the addition of some columns) can score -you some free functionality and help you avoid configuration. For -example, if you name your database table big\_boxes, your table -BigBoxesTable, and your controller BigBoxesController, everything will -work together automatically. By convention, use underscores, lower case, -and plural forms for your database table names - for example: -bakers, pastry\_stores, and savory\_cakes. - -.. php:namespace:: Cake\Datasource - -Managing Connections -==================== - -.. php:class:: ConnectionManager - -The ``ConnectionManager`` class acts as a registry to access database connections your -application has. It provides a place that other objects can get references to -existing connections. - -Accessing Connections ---------------------- - -.. php:staticmethod:: get($name) - -Once configured connections can be fetched using -:php:meth:`Cake\\Datasource\\ConnectionManager::get()`. This method will -construct and load a connection if it has not been built before, or return the -existing known connection:: - - use Cake\Datasource\ConnectionManager; - - $conn = ConnectionManager::get('default'); - -Attempting to load connections that do not exist will throw an exception. - -Creating Connections at Runtime -------------------------------- - -.. php:staticmethod:: create($name, $config) - -The ``create`` method allows you to define new connections that are not defined -in your configuration files at runtime:: - - $conn = ConnectionManager::create('my_connection', $config); - -See the :ref:`database-configuration` for more information on the configuration -data used when creating connections. - -.. _database-data-types: - -Data Types -========== - -.. php:class:: Type - -Since not every database vendor includes the same set of data types, or -the same names for similar data types, CakePHP provides a set of abstracted -data types for use with the database layer. The types CakePHP supports are: - -string - Generally backed by CHAR or VARCHAR columns. Using the ``fixed`` option - will force a CHAR column. In SQL Server, NCHAR and NVARCHAR types are used. -text - Maps to TEXT types -uuid - Maps to the UUID type if a database provides one, otherwise this will - generate a CHAR(36) field. -integer - Maps to the INTEGER type provided by the database. -biginteger - Maps to the BIGINT type provided by the database. -float - Maps to either DOUBLE or FLOAT depending on the database. The ``precision`` - option can be used to define the precision used. -decimal - Maps to the DECIMAL type. Supports the ``length`` and ``precision`` - options. -boolean - Maps to BOOLEAN except in MySQL, where TINYINT(1) is used to represent - booleans. -binary - Maps to the BLOB or BYTEA type provided by the database. -date - Maps to a timezone naive DATE column type. -datetime - Maps to a timezone naive DATETIME column type. In PostgreSQL, and SQL Server - this turns into a TIMESTAMP type. The default return value of this column - type is :php:class:`Cake\\Utility\\Time` which extends the built-in - ``DateTime`` class and `Carbon `_. -timestamp - Maps to the TIMESTAMP type. -time - Maps to a TIME type in all databases. - -These types are used in both the schema reflection features that CakePHP -provides, and schema generation features CakePHP uses when using test fixtures. - -Each type can also provide translation functions between PHP and SQL -representations. These methods are invoked based on the type hints provided when -doing queries. For example a column that is marked as 'datetime' will -automatically convert input parameters from ``DateTime`` instances into a -timestamp or formatted datestrings. Likewise, 'binary' columns will accept file -handles, and generate file handles when reading data. - -.. _adding-custom-database-types: - -Adding Custom Types -------------------- - -.. php:staticmethod:: map($name, $class) - -If you need to use vendor specific types that are not built into CakePHP you can -add additional new types to CakePHP's type system. Type classes are expected to -implement the following methods: - -* toPHP -* toDatabase -* toStatement - -An easy way to fulfill the basic interface is to extend -:php:class:`Cake\Database\Type`. For example if we wanted to add a JSON type, -we could make the following type class:: - - namespace App\Database\Type; - - use Cake\Database\Driver; - use Cake\Database\Type; - - class JsonType extends Type - { - - public function toPHP($value, Driver $driver) - { - if ($value === null) { - return null; - } - return json_decode($value, true); - } - - public function toDatabase($value, Driver $driver) - { - return json_encode($value); - } - - } - -By default the ``toStatement`` method will treat values as strings which will -work for our new type. Once we've created our new type, we need to add it into -the type mapping. During our application bootstrap we should do the following:: - - use Cake\Database\Type; - - Type::map('json', 'App\Database\Type\JsonType'); - -We can then overload the reflected schema data to use our new type, and -CakePHP's database layer will automatically convert our JSON data when creating -queries. - -Connection Classes -================== - -.. php:class:: Connection - -Connection classes provide a simple interface to interact with database -connections in a consistent way. They are intended as a more abstract interface to -the driver layer and provide features for executing queries, logging queries, and doing -transactional operations. - -.. _database-queries: - -Executing Queries ------------------ - -.. php:method:: query($sql) - -Once you've gotten a connection object, you'll probably want to issue some -queries with it. CakePHP's database abstraction layer provides wrapper features -on top of PDO and native drivers. These wrappers provide a similar interface to -PDO. There are a few different ways you can run queries depending on the type of -query you need to run and what kind of results you need back. The most basic -method is ``query()`` which allows you to run already completed SQL queries:: - - $stmt = $conn->query('UPDATE posts SET published = 1 WHERE id = 2'); - -.. php:method:: execute($sql, $params, $types) - -The ``query`` method does not allow for additional parameters. If you need -additional parameters you should use the ``execute()`` method, which allows for -placeholders to be used:: - - $stmt = $conn->execute( - 'UPDATE posts SET published = ? WHERE id = ?', - [1, 2] - ); - -Without any type hinting information, ``execute`` will assume all placeholders -are string values. If you need to bind specific types of data, you can use their -abstract type names when creating a query:: - - $stmt = $conn->execute( - 'UPDATE posts SET published_date = ? WHERE id = ?', - [new DateTime('now'), 2], - ['date', 'integer'] - ); - -.. php:method:: newQuery() - -This allows you to use rich data types in your applications and properly convert -them into SQL statements. The last and most flexible way of creating queries is -to use the :ref:`query-builder`. This apporach allows you to build complex and -expressive queries without having to use platform specific SQL:: - - $query = $conn->newQuery(); - $query->update('posts') - ->set(['publised' => true]) - ->where(['id' => 2]); - $stmt = $query->execute(); - -When using the query builder, no SQL will be sent to the database server until -the ``execute()`` method is called, or the query is iterated. Iterating a query -will first execute it and then start iterating over the result set:: - - $query = $conn->newQuery(); - $query->select('*') - ->from('posts') - ->where(['published' => true]); - - foreach ($query as $row) { - // Do something with the row. - } - -.. note:: - - When you have an instance of :php:class:`Cake\\ORM\\Query` you can use - ``all()`` to get the result set for SELECT queries. - -Using Transactions -------------------- - -The connection objects provide you a few simple ways you do database -transactions. The most basic way of doing transactions is through the ``begin``, -``commit`` and ``rollback`` methods, which map to their SQL equivalents:: - - $conn->begin(); - $conn->execute('UPDATE posts SET published = ? WHERE id = ?', [true, 2]); - $conn->execute('UPDATE posts SET published = ? WHERE id = ?', [false, 4]); - $conn->commit(); - -.. php:method:: transactional(callable $callback) - -In addition to this interface connection instances also provide the -``transactional`` method which makes handling the begin/commit/rollback calls -much simpler:: - - $conn->transactional(function($conn) { - $conn->execute('UPDATE posts SET published = ? WHERE id = ?', [true, 2]); - $conn->execute('UPDATE posts SET published = ? WHERE id = ?', [false, 4]); - }); - -In addition to basic queries, you can execute more complex queries using either -the :ref:`query-builder` or :ref:`table-objects`. The transactional method will -do the following: - -- Call ``begin``. -- Call the provided closure. -- If the closure raises an exception, a rollback will be issued. The original - exception will be re-thrown. -- If the closure returns ``false``, a rollback will be issued. -- If the closure executes successfully, the transaction will be committed. - -Interacting with Statements -=========================== - -When using the lower level database API, you will often encounter statement -objects. These objects allow you to manipulate the underlying prepared statement -from the driver. After creating and executing a query object, or using -``execute()`` you will have a ``StatementDecorator`` instance. It wraps the -underlying basic statement object and provides a few additional features. - -Preparing a Statement ---------------------- - -You can create a statement object using ``execute()``, or ``prepare()``. The -``execute()`` method returns a statement with the provided values bound to it. While -``prepare()`` returns an incomplete statement:: - - // Statements from execute will have values bound to them already. - $stmt = $conn->execute( - 'SELECT * FROM articles WHERE published = ?', - [true] - ); - - // Statements from prepare will be parameters for placeholders. - // You need to bind parameters before attempting to execute it. - $stmt = $conn->prepare('SELECT * FROM articles WHERE published = ?'); - -Once you've prepared a statement you can bind additional data and execute it. - -Binding Values --------------- - -Once you've created a prepared statement, you may need to bind additional data. -You can bind multiple values at once using the ``bind`` method, or bind -individual elements using ``bindValue``:: - - $stmt = $conn->prepare( - 'SELECT * FROM articles WHERE published = ? AND created > ?' - ); - - // Bind multiple values - $stmt->bind( - [true, new DateTime('2013-01-01')], - ['boolean', 'date'] - ); - - // Bind a single value - $stmt->bindValue(0, true, 'boolean'); - $stmt->bindValue(1, new DateTime('2013-01-01'), 'date'); - -When creating statements you can also use named array keys instead of -positional ones:: - - $stmt = $conn->prepare( - 'SELECT * FROM articles WHERE published = :published AND created > :created' - ); - - // Bind multiple values - $stmt->bind( - ['published' => true, 'created' => new DateTime('2013-01-01')], - ['published' => 'boolean', 'created' => 'date'] - ); - - // Bind a single value - $stmt->bindValue('published', true, 'boolean'); - $stmt->bindValue('created', new DateTime('2013-01-01'), 'date'); - -.. warning:: - - You cannot mix positional and named array keys in the same statement. - -Executing & Fetching Rows -------------------------- - -After preparing a statement and binding data to it, you can execute it and fetch -rows. Statements should be executed using the ``execute()`` method. Once -executed, results can be fetched using ``fetch()``, ``fetchAll()`` or iterating -the statement:: - - $stmt->execute(); - - // Read one row. - $row = $stmt->fetch('assoc'); - - // Read all rows. - $rows = $stmt->fetchAll('assoc'); - - // Read rows through iteration. - foreach ($rows as $row) { - // Do work - } - .. note:: + La documentación no es compatible actualmente con el idioma español en esta página. - Reading rows through iteration will fetch rows in 'both' mode. This means - you will get both the numerically indexed and associatively indexed results. - - -Getting Row Counts ------------------- - -After executing a statement, you can fetch the number of affected rows:: - - $rowCount = count($stmt); - $rowCount = $stmt->rowCount(); - - -Checking Error Codes --------------------- - -If your query was not successful, you can get related error information -using the ``errorCode()`` and ``errorInfo()`` methods. These methods work the -same way as the ones provided by PDO:: - - $code = $stmt->errorCode(); - $info = $stmt->errorInfo(); - -.. todo:: - Possibly document CallbackStatement and BufferedStatement - -.. _database-query-logging: - -Query Logging -============= - -Query logging can be enabled when configuring your connection by setting the -``log`` option to true. You can also toggle query logging at runtime, using -``logQueries``:: - - // Turn query logging on. - $conn->logQueries(true); - - // Turn query logging off - $conn->logQueries(false); - -When query logging is enabled, queries will be logged to -:php:class:`Cake\\Log\\Log` using the 'debug' level, and the 'queriesLog' scope. -You will need to have a logger configured to capture this level & scope. Logging -to ``stderr`` can be useful when working on unit tests, and logging to -files/syslog can be useful when working with web requests:: - - use Cake\Log\Log; - - // Console logging - Log::config('queries', [ - 'className' => 'Console', - 'stream' => 'php://stderr', - 'scopes' => ['queriesLog'] - ]); - - // File logging - Log::config('queries', [ - 'className' => 'File', - 'file' => 'queries.log', - 'scopes' => ['queriesLog'] - ]); - -.. note:: - - Query logging is only intended for debugging/development uses. You should - never leave query logging on in production as it will negatively impact the - performance of your application. - -.. _identifier-quoting: - -Identifier Quoting -================== - -By default CakePHP does **not** quote identifiers in generated SQL queries. The -reason for this is identifier quoting has a few drawbacks: - -* Performance overhead - Quoting identifiers is much slower and complex than not doing it. -* Not necessary in most cases - In non-legacy databases that follow CakePHP's - conventions there is no reason to quote identifiers. - -If you are using a legacy schema that requires identifier quoting you can enable -it using the ``quoteIdentifiers`` setting in your -:ref:`database-configuration`. You can also enable this feature at runtime:: - - $conn->driver()->autoQuoting(true); - -When enabled, identifier quoting will cause additional query traversal that -converts all identifiers into ``IdentifierExpression`` objects. - -.. note:: - - SQL snippets contained in QueryExpression objects will not be modified. - -.. _database-metadata-cache: - -Metadata Caching -================ - -CakePHP's ORM uses database reflection to determine the schema, indexes and -foreign keys your application contains. Because this metadata changes -infrequently and can be expensive to access, it is typically cached. By default, -metadata is stored in the ``_cake_model_`` cache configuration. You can define -a custom cache configuration using the ``cacheMetatdata`` option in your -datasource configuration:: - - 'Datasources' => [ - 'default' => [ - // Other keys go here. - - // Use the 'orm_metadata' cache config for metadata. - 'cacheMetadata' => 'orm_metadata', - ] - ], - -You can also configure the metadata caching at runtime with the -``cacheMetadata()`` method:: - - // Disable the cache - $connection->cacheMetadata(false); - - // Enable the cache - $connection->cacheMetadata(true); - - // Use a custom cache config - $connection->cacheMetadata('orm_metadata'); + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -CakePHP also includes a CLI tool for managing metadata caches. See the -:doc:`/console-and-shells/orm-cache` chapter for more information. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/deleting-data.rst b/es/orm/deleting-data.rst new file mode 100644 index 0000000000000000000000000000000000000000..52234658774864dbfc765d4e6f1f8ea304499858 --- /dev/null +++ b/es/orm/deleting-data.rst @@ -0,0 +1,17 @@ +Deleting Data +############# + +.. php:namespace:: Cake\ORM + +.. php:class:: Table + +.. php:method:: delete(Entity $entity, $options = []) + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/entities.rst b/es/orm/entities.rst index 355b257a452452303ef01a160d22a5573e22a156..9d21b2aba8598d58a0b605005bfc579f3b75e066 100644 --- a/es/orm/entities.rst +++ b/es/orm/entities.rst @@ -3,404 +3,15 @@ Entities ######## -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - .. php:namespace:: Cake\ORM .. php:class:: Entity -While :doc:`/orm/table-objects` represent and provide access to a collection of -objects, entities represent individual rows or domain objects in your -application. Entities contain persistent properties and methods to manipulate and -access the data they contain. - -Entities are created for you by CakePHP each time you use ``find()`` on a table -object. - -Creating Entity Classes -======================= - -You don't need to create entity classes to get started with the ORM in CakePHP. -However, if you want to have custom logic in your entities you will need to -create classes. By convention entity classes live in ``src/Model/Entity/``. If -our application had an ``articles`` table we could create the following entity:: - - // src/Model/Entity/Article.php - namespace App\Model\Entity; - - use Cake\ORM\Entity; - - class Article extends Entity - { - } - -Right now this entity doesn't do very much. However, when we load data from our -articles table, we'll get instances of this class. - .. note:: + La documentación no es compatible actualmente con el idioma español en esta página. - If you don't define an entity class CakePHP will use the basic Entity class. - -Accessing Entity Data -===================== - -Entities provide a few ways to access the data they contain. Most commonly you -will access the data in an entity using object notation:: - - $article->title = 'This is my first post'; - echo $article->title; - -You can also use the ``get()`` and ``set()`` methods:: - - $article->set('title', 'This is my first post'); - echo $article->get('title'); - -When using ``set()`` you can update multiple properties at once using an array:: - - $article->set([ - 'title' => 'My first post', - 'body' => 'It is the best ever!' - ]); - -.. warning:: - - When updating entities with request data you should whitelist which fields - can be set with mass assignment. - -Accessors & Mutators -==================== - -.. php:method:: set($field = null, $value = null) - -In addition to the simple get/set interface, entities allow you to provide -accessors and mutator methods. These methods let you customize how properties -are read or set. For example:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - - class Article extends Entity - { - protected function _getTitle($title) - { - return ucwords($title); - } - } - -Accessors use the convention of ``_get`` followed by the CamelCased version of -the field name. They receive the basic value stored in the ``_properties`` array -as their only argument. You can customize how properties get set by defining -a mutator:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - use Cake\Utility\Inflector; - - class Article extends Entity - { - - protected function _setTitle($title) - { - $this->set('slug', Inflector::slug($title)); - return $title; - } - - } - -Mutator methods should always return the value that should be stored in the -property. As you can see above, you can also use mutators to set other -calculated properties. When doing this, be careful to not introduce any loops, -as CakePHP will not prevent infinitely looping mutator methods. Mutators allow -you easily convert properties as they are set, or create calculated data. -Mutators and accessors are applied when properties are read using object -notation, or using get() and set(). - -Creating Virtual Properties ---------------------------- - -By defining accessors you can provide access to properties that do not -actually exist. For example if your users table has ``first_name`` and -``last_name`` you could create a method for the full name:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - - class User extends Entity - { - - protected function _getFullName() - { - return $this->_properties['first_name'] . ' ' . - $this->_properties['last_name']; - } - - } - -You can access virtual properties as if they existed on the entity. The property -name will be the lower case and underscored version of the method:: - - echo $user->full_name; - -Validation Errors -================= - -.. php:method:: errors($field = null, $errors = null) - -After you :ref:`save an entity ` any validation errors will be -stored on the entity itself. You can access any validation errors using the -``errors()`` method:: - - // Get all the errors - $errors = $user->errors(); - - // Get the errors for a single field. - $errors = $user->errors('password'); - -The ``errors()`` method can also be used to set the errors on an entity, making -it easier to test code that works with error messages:: - - $user->errors('password', ['Password is required.']); - -.. _entities-mass-assignment: - -Mass Assignment -=============== - -While setting properties to entites in bulk is simple and convenient, it can -create signifcant security issues. Bulk assigning user data from the request -into an entity allows the user to modify any and all columns. By default CakePHP -protects against mass-assignment and makes you whitelist which fields -are mass-assignable. - -The ``_accessible`` property allows you to provide a map of properties and -whether or not they can be mass-assigned. The values ``true`` and ``false`` -indicate whether a field can or cannot be mass-assigned:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - - class Article extends Entity - { - protected $_accessible = [ - 'title' => true, - 'body' => true, - ]; - } - -In addition to concrete fields there is a special ``*`` field which defines the -fallback behavior if a field is not specifically named:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - - class Article extends Entity - { - protected $_accessible = [ - 'title' => true, - 'body' => true, - '*' => false, - ]; - } - -If the ``*`` property is not defined it will default to ``false``. - -Modifying the Guarded Fields at Runtime ---------------------------------------- - -You can modify the list of guarded fields at runtime using the ``accessible`` -method:: - - // Make user_id accessible. - $article->accessible('user_id', true); - - // Make title guarded. - $article->accessible('title', false); - -.. note:: - - Modifying accessible fields effects only the instance the method is called - on. - - -Bypassing Field Guarding ------------------------- - -There are sometimes situations when you want to allow mass-assignment to guarded -fields:: - - $article->set($properties, ['guard' => false]); - -By setting the ``guard`` option to false, you can ignore the accessible field -list for a single call to ``set()``. - - -.. _lazy-load-associations: - -Lazy Loading Associations -========================= - -While eager loading associations is generally the most efficient way to access -your associations, there may be times when you need to lazily load associated -data. Before we get into how to lazy load associations, we should discuss the -differences between eager loading and lazy loading associations: - -Eager loading - Eager loading uses joins (where possible) to fetch data from the - database in as *few* queries as possible. When a separate query is required, - like in the case of a HasMany association, a single query is emitted to - fetch *all* the associated data for the current set of objects. -Lazy loading - Lazy loading defers loading association data until it is absolutely - required. While this can save CPU time because possibly unused data is not - hydrated into objects, it can result in many more queries being emitted to - the database. For example looping over a set of articles & their comments - will frequently emit N queries where N is the number of articles being - iterated. - -While lazy loading is not included by CakePHP's ORM, it is not hard to implement -it yourself when and where you need it. When implementing an accessor method you -can lazily load associated data:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - use Cake\ORM\TableRegistry; - - class Article extends Entity - { - - protected function _getComments() - { - $comments = TableRegistry::get('Comments'); - return $comments->find('all') - ->where(['article_id' => $this->id]) - ->all(); - } - - } - -Implementing the above method will enable you to do the following:: - - $article = $this->Articles->findById($id); - foreach ($article->comments as $comment) { - echo $comment->body; - } - -Creating Re-usable Code with Traits -=================================== - -You may find yourself needing the same logic in multiple entity classes. PHP's -traits are a great fit for this. You can put your application's traits in -``src/Model/Entity``. By convention traits in CakePHP are suffixed with -``Trait`` so they are easily discernible from classes or interfaces. Traits are -often a good compliment to behaviors, allowing you to provide functionality for -the table and entity objects. - -For example if we had SoftDeletable plugin, it could provide a trait. This trait -could give methods for marking entities as 'deleted', the method ``softDelete`` -could be provided by a trait:: - - // SoftDelete/Model/Entity/SoftDeleteTrait.php - - namespace SoftDelete\Model\Entity; - - trait SoftDeleteTrait { - - public function softDelete() - { - $this->set('deleted', true); - } - - } - -You could then use this trait in your entity class by importing it and including -it:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - use SoftDelete\Model\Entity\SoftDeleteTrait; - - class Article extends Entity - { - use SoftDeleteTrait; - } - -Converting to Arrays/JSON -========================= - -When building APIs, you may often need to convert entities into arrays or JSON -data. CakePHP makes this simple:: - - // Get an array. - $array = $user->toArray(); - - // Convert to JSON - $json = json_encode($user); - -When converting an entity to an array/JSON the virtual & hidden field lists are -applied. Entities are converted recursively as well. This means that if you -eager loaded entities and their associations CakePHP will correctly handle -converting the associated data into the correct format. - -Exposing Virtual Properties ---------------------------- - -By default virtual properties are not exported when converting entities to -arrays or JSON. In order to expose virtual properties you need to make them -visible. When defining your entity class you can provide a list of virtual -fields that should be exposed:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - - class User extends Entity - { - - protected $_virtual = ['full_name']; - - } - -This list can be modified at runtime using ``virtualProperties``:: - - $user->virtualProperties(['full_name', 'is_admin']); - -Hiding Properties ------------------ - -There are often fields you do not want exported in JSON or array formats. For -example it is often unwise to expose password hashes or account recovery -questions. When defining an entity class, define which properties should be -hidden:: - - namespace App\Model\Entity; - - use Cake\ORM\Entity; - - class User extends Entity - { - - protected $_hidden = ['password']; - - } - -This list can be modified at runtime using ``hiddenProperties``:: - - $user->hiddenProperties(['password', 'recovery_question']); - -Storing Complex Types -===================== + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. -Entities are not intended to contain the logic for serializing and -unserializing complex data coming from the database. Refer to the -:ref:`saving-complex-types` section to understand how your application can store -more complex data types like arrays and objects. + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/query-builder.rst b/es/orm/query-builder.rst index 3dab6d89d435e80fa55b2726010eedcf7a53c358..a2b566ef92a0da91e3c31b48b4b4ac9d52a7f96c 100644 --- a/es/orm/query-builder.rst +++ b/es/orm/query-builder.rst @@ -5,1047 +5,13 @@ Query Builder ############# -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - .. php:class:: Query -The ORM's query builder provides a simple to use fluent interface for creating -and running queries. By composing queries together, you can create advanced -queries using unions and subqueries with ease. - -Underneath the covers, the query builder uses PDO prepared statements which -protect against SQL injection attacks. - -Query objects are lazily evaluated. This means a query is not executed until one -of the following things occur: - -- The query is iterated with ``foreach()``. -- The query's ``execute()`` method is called. This will return the underlying - statement object, and is to be used with insert/update/delete queries. -- The query's ``all()`` method is called. This will return the result set and - can only be used with select statements. -- The query's ``toArray()`` method is called. - -Until one of these conditions are met, the query can be modified with additional -SQL being sent to the database. It also means that if a Query hasn't been -evaluated, no SQL is ever sent to the database. Once executed, modifying and -re-evaluating a query will result in additional SQL being run. - -If you want to take a look at what SQL CakePHP is generating, you can turn -database :ref:`query logging ` on. - -The Query Object -================ - -The easiest way to create a ``Query`` object is to use ``find()`` from a -``Table`` object. This method will return an incomplete query ready to be -modified. You can also use a table's connection object to access the lower level -Query builder that does not include ORM features, if necessary. See the -:ref:`database-queries` section for more information. For the remaining -examples, assume that ``$articles`` is a :php:class:`~Cake\\ORM\\Table`:: - - // Start a new query. - $query = $articles->find(); - -Almost every method in a ``Query`` object will return the same query, this means -that ``Query`` objects are lazy, and will not be executed unless you tell them -to:: - - $query->where(['id' => 1]); // Return the same query object - $query->order(['title' => 'DESC']); // Still same object, no SQL executed - -You can of course chain the methods you call on Query objects:: - - $query = $articles - ->find() - ->select(['id', 'name']) - ->where(['id !=' => 1]) - ->order(['created' => 'DESC']); - -If you try to call ``debug()`` on a Query object, you will see its internal -state and the SQL that will be executed in the database:: - - debug($articles->find()->where(['id' => 1])); - - // Outputs - // ... - // 'sql' => 'SELECT * FROM articles where id = ?' - // ... - -Once you're happy with the Query, you can execute it. The easiest way is to -either call the ``first()`` or the ``all()`` methods:: - - $firstArticle = $articles - ->find() - ->where(['id' => 1]) - ->first(); - - $allResults = $articles - ->find() - ->where(['id >' => 1]) - ->all(); - -In the above example, ``$allResults`` will be an instance of -``Cake\ORM\ResultSet``, an object you can iterate and apply several extracting -and traversing methods on. Often, there is no need to call ``all()``, you are -allowed to just iterate the Query object to get its results:: - - // Iterate the results - foreach ($allResults as $result) { - ... - } - - // That is equivalent to - $query = $articles->find()->where(['id' => 1]); - foreach ($query as $result) { - ... - } - -Query objects can also be used directly as the result object; trying to iterate the query, -calling ``toArray`` or some of the methods inherited from :ref:`Collection`, -will result in the query being executed and results returned to you:: - - // This executes the query and returns an array of results - $resultsIntoAnArray = $articles->find()->where(['id >' => 1])->toArray(); - - // Use the combine() method from the collections library - // This executes the query - $keyValueList = $articles->find()->combine('id', 'title'); - - // Use the extract() method from the collections library - // This executes the query as well - $allTitles = $articles->find()->extract('title'); - -Once you get familiar with the Query object methods, it is strongly encouraged -that you visit the :ref:`Collection` section to improve your skills -in efficiently traversing the data. In short, it is important to remember that -anything you can call on a Collection object, you can also do in a Query object:: - - // An advanced example - $results = $articles->find() - ->where(['id >' => 1]) - ->order(['title' => 'DESC']) - ->map(function($row) { // map() is a collection method, it executes the query - $row->trimmedTitle = trim($row->title); - return $row; - }); - ->combine('id', 'trimmedTitle') // combine() is another collection method - ->toArray(); // Also a collections library method - -The following sections will show you everything there is to know about using and -combining the Query object methods to construct SQL statements and extract data. - -Selecting Data -============== - -Most web applications make heavy use of ``SELECT`` queries. CakePHP makes -building them a snap. To limit the fields fetched, you can use the ``select()`` -method:: - - $query = $articles->find(); - $query->select(['id', 'title', 'body']); - foreach ($query as $row) { - debug($row->title); - } - -You can set aliases for fields by providing fields as an associative array:: - - // Results in SELECT id pk, title aliased_title, body ... - $query = $articles->find(); - $query->select(['pk' => 'id', 'aliased_title' => 'title', 'body']); - -To select distinct fields, you can use the ``distinct()`` method:: - - // Results in SELECT DISTINCT country FROM ... - $query = $articles->find(); - $query->select(['country']) - ->distinct(['country']); - -To set some basic conditions you can use the ``where()`` method:: - - // Conditions are combined with AND - $query = $articles->find(); - $query->where(['title' => 'First Post', 'published' => true]); - - // You can call where() multiple times - $query = $articles->find(); - $query->where(['title' => 'First Post']) - ->where(['published' => true]); - -See the :ref:`advanced-query-conditions` section to find out how to construct -more complex ``WHERE`` conditions. To apply ordering, you can use the ``order`` -method:: - - $query = $articles->find() - ->order(['title' => 'ASC', 'id' => 'ASC']); - -To limit the number of rows or set the row offset you can use the ``limit()`` -and ``page()`` methods:: - - // Fetch rows 50 to 100 - $query = $articles->find() - ->limit(50) - ->page(2); - -As you can see from the examples above, all the methods that modify the query -provide a fluent interface, allowing you to build a query through chained method -calls. - -Using SQL Functions -------------------- - -CakePHP's ORM offers abstraction for some commonly used SQL functions. Using the -abstraction allows the ORM to select the platform specific implementation of the -function you want. For example, ``concat`` is implemented differently in MySQL, -PostgreSQL and SQL Server. Using the abstraction allows your code to be portable:: - - // Results in SELECT COUNT(*) count FROM ... - $query = $articles->find(); - $query->select(['count' => $query->func()->count('*')]); - -A number of commonly used functions can be created with the ``func()`` method: - -- ``sum()`` Calculate a sum. The arguments will be treated as literal values. -- ``avg()`` Calculate an average. The arguments will be treated as literal values. -- ``min()`` Calculate the min of a column. The arguments will be treated as - literal values. -- ``max()`` Calculate the max of a column. The arguments will be treated as - literal values. -- ``count()`` Calculate the count. The arguments will be treated as literal - values. -- ``concat()`` Concatenate two values together. The arguments are treated as - bound parameters unless marked as literal. -- ``coalesce()`` Coalesce values. The arguments are treated as bound parameters - unless marked as literal. -- ``dateDiff()`` Get the difference between two dates/times. The arguments are - treated as bound parameters unless marked as literal. -- ``now()`` Take either 'time' or 'date' as an argument allowing you to get - either the current time, or current date. - -When providing arguments for SQL functions, there are two kinds of parameters -you can use, literal arguments and bound parameters. Literal parameters allow -you to reference columns or other SQL literals. Bound parameters can be used to -safely add user data to SQL functions. For example:: - - $query = $articles->find(); - $concat = $query->func()->concat([ - 'title' => 'literal', - ' NEW' - ]); - $query->select(['title' => $concat]); - -By making arguments with a value of ``literal``, the ORM will know that -the key should be treated as a literal SQL value. The above would generate the -following SQL on MySQL:: - - SELECT CONCAT(title, :c0) FROM articles; - -The ``:c0`` value will have the ``' NEW'`` text bound when the query is -executed. - -Aggregates - Group and Having ------------------------------ - -When using aggregate functions like ``count`` and ``sum`` you may want to use -``group by`` and ``having`` clauses:: - - $query = $articles->find(); - $query->select([ - 'count' => $query->func()->count('view_count'), - 'published_date' => 'DATE(created)' - ]) - ->group('published_date') - ->having(['count >' => 3]); - -Disabling Hydration -------------------- - -While ORMs and object result sets are powerful, hydrating entities is sometimes -unnecessary. For example, when accessing aggregated data, building an Entity may -not make sense. In these situations you may want to disable entity hydration:: - - $query = $articles->find(); - $query->hydrate(false); - .. note:: + La documentación no es compatible actualmente con el idioma español en esta página. - When hydration is disabled results will be returned as basic arrays. - -.. _advanced-query-conditions: - -Advanced Conditions -=================== - -The query builder makes it simple to build complex ``where`` clauses. -Grouped conditions can be expressed by providing combining ``where()``, -``andWhere()`` and ``orWhere()``. The ``where()`` method works similar to the -conditions arrays in previous versions of CakePHP:: - - $query = $articles->find() - ->where([ - 'author_id' => 3, - 'OR' => ['author_id' => 2], - ]); - -The above would generate SQL like:: - - SELECT * FROM articles WHERE (author_id = 2 OR author_id = 3) - -If you'd prefer to avoid deeply nested arrays, you can use the ``orWhere()`` and -``andWhere()`` methods to build your queries. Each method sets the combining -operator used between the current and previous condition. For example:: - - $query = $articles->find() - ->where(['author_id' => 2]) - ->orWhere(['author_id' => 3]); - -The above will output SQL similar to:: - - SELECT * FROM articles WHERE (author_id = 2 OR author_id = 3) - -By combining ``orWhere()`` and ``andWhere()``, you can express complex -conditions that use a mixture of operators:: - - $query = $articles->find() - ->where(['author_id' => 2]) - ->orWhere(['author_id' => 3]) - ->andWhere([ - 'published' => true, - 'view_count >' => 10 - ]) - ->orWhere(['promoted' => true]); - -The above generates SQL similar to:: - - SELECT * - FROM articles - WHERE (promoted = 1 - OR (published = true AND view_count > 10) - AND (author_id = 2 OR author_id = 3)) - -By using functions as the parameters to ``orWhere()`` abd ``andWhere()``, -you can easily compose conditions together with the expression objects:: - - $query = $articles->find() - ->where(['title LIKE' => '%First%']) - ->andWhere(function($exp) { - return $exp->or_([ - 'author_id' => 2, - 'is_highlighted' => true - ]); - }); - -The above would create SQL like:: - - SELECT * - FROM articles - WHERE ((author_id = 2 OR is_highlighted = 1) - AND title LIKE '%First%') - -The expression object that is passed into ``where()`` functions has two kinds of -methods. The first type of methods are **combinators**. The ``and_()`` and -``or_()`` methods create new expression objects that change **how** conditions -are combined. The second type of methods are **conditions**. Conditions are -added into an expression where they are combined with the current combinator. - -For example, calling ``$exp->and_(...)`` will create a new ``Expression`` object -that combines all conditions it contains with ``AND``. While ``$exp->or_()`` -will create a new ``Expression`` object that combines all conditions added to it -with ``OR``. An example of adding conditions with an ``Expression`` object would -be:: - - $query = $articles->find() - ->where(function($exp) { - return $exp - ->eq('author_id', 2) - ->eq('published', true) - ->notEq('spam', true) - ->gt('view_count', 10); - }); - -Since we started off using ``where()``, we don't need to call ``and_()``, as that -happens implicitly. Much like how we would not need to call ``or_()``, had we -started our query with ``orWhere()``. The above shows a few new condition -methods being combined with ``AND``. The resulting SQL would look like:: - - SELECT * - FROM articles - WHERE ( - author_id = 2 - AND published = 1 - AND spam != 1 - AND view_count > 10) - -However, if we wanted to use both ``AND`` & ``OR`` conditions we could do the -following:: - - $query = $articles->find() - ->where(function($exp) { - $orConditions = $exp->or_(['author_id' => 2]) - ->eq('author_id', 5); - return $exp - ->add($orConditions) - ->eq('published', true) - ->gte('view_count', 10); - }); - -Which would generate the SQL similar to:: - - SELECT * - FROM articles - WHERE ( - (author_id = 2 OR author_id = 5) - AND published = 1 - AND view_count > 10) - -The ``or_()`` and ``and_()`` methods also allow you to use functions as their -parameters. This is often easier to read than method chaining:: - - $query = $articles->find() - ->where(function($exp) { - $orConditions = $exp->or_(function ($or) { - return $or->eq('author_id', 2) - ->eq('author_id', 5); - }); - return $exp - ->not($orConditions) - ->lte('view_count', 10); - }); - -You can negate sub-expressions using ``not()``:: - - $query = $articles->find() - ->where(function($exp) { - $orConditions = $exp->or_(['author_id' => 2]) - ->eq('author_id', 5); - return $exp - ->not($orConditions) - ->lte('view_count', 10); - }); - -Which will generate the following SQL looking like:: - - SELECT * - FROM articles - WHERE ( - NOT (author_id = 2 OR author_id = 5) - AND view_count <= 10) - - -When using the expression objects you can use the following methods to create -conditions: - -- ``eq()`` Creates an equality condition. -- ``notEq()`` Create an inequality condition -- ``like()`` Create a condition using the ``LIKE`` operator. -- ``notLike()`` Create a negated ``LIKE`` condition. -- ``in()`` Create a condition using ``IN``. -- ``notIn()`` Create a negated condition using ``IN``. -- ``gt()`` Create a ``>`` condition. -- ``gte()`` Create a ``>=`` condition. -- ``lt()`` Create a ``<`` condition. -- ``lte()`` Create a ``<=`` condition. -- ``isNull()`` Create an ``IS NULL`` condition. -- ``isNotNull()`` Create a negated ``IS NULL`` condition. - -Automatically Creating IN Clauses ---------------------------------- - -When building queries using the ORM, you will generally not have to indicate the -data types of the columns you are interacting with, as CakePHP can infer the -types based on the schema data. If in your queries you'd like CakePHP to -automatically convert equality to ``IN`` comparisons, you'll need to indicate -the column data type:: - - $query = $articles->find() - ->where(['id' => $ids], ['id' => 'integer[]']); - - // Or include IN to automatically cast to an array. - $query = $articles->find() - ->where(['id IN' => $ids]); - -The above will automatically create ``id IN (...)`` instead of ``id = ?``. This -can be useful when you do not know whether you will get a scalar or array of -parameters. The ``[]`` suffix on any data type name indicates to the query -builder that you want the data handled as an array. If the data is not an array, -it will first be cast to an array. After that, each value in the array will -be cast using the :ref:`type system `. This works with -complex types as well. For example, you could take a list of DateTime objects -using:: - - $query = $articles->find() - ->where(['post_date' => $dates], ['post_date' => 'date[]']); - -Automatic IS NULL Creation --------------------------- - -When a condition value is expected to be ``null`` or any other value, you can use -the ``IS`` operator to automatically create the correct expression:: - - $query = $categories->find() - ->where(['parent_id IS' => $parentId]); - - -The above will create ``parent_id` = :c1`` or ``parent_id IS NULL`` depending on the type of ``$parentId`` - - -Raw Expressions ---------------- - -When you cannot construct the SQL you need using the query builder, you can use -expression objects to add snippets of SQL to your queries:: - - $query = $articles->find(); - $expr = $query->newExpr()->add('1 + 1'); - $query->select(['two' => $expr]); - -``Expression`` objects can be used with any query builder methods like -``where()``, ``limit()``, ``group()``, ``select()`` and many other methods. - -.. warning:: - - Using expression objects leaves you vulnerable to SQL injection. You should - avoid interpolating user data into expressions. - -.. _query-count: - -Returning the Total Count of Records ------------------------------------- - -Using a single query object, it is possible to obtain the total number of rows -found for a set of conditions:: - - $total = $articles->find()->where(['is_active' => true])->count(); - -The ``count()`` method will ignore the ``limit``, ``offset`` and ``page`` -clauses, thus the following will return the same result:: - - $total = $articles->find()->where(['is_active' => true])->limit(10)->count(); - -This is useful when you need to know the total result set size in advance, -without having to construct another ``Query`` object. Likewise, all result -formatting and map-reduce routines are ignored when using the ``count()`` -method. - -Moreover, it is possible to return the total count for a query containing group -by clauses without having to rewrite the query in any way. For example, consider -this query for retrieving article ids and their comments count:: - - $query = $articles->find(); - $query->find() - ->select(['Articles.id', $query->func()->count('Comments.id')]) - ->matching('Comments') - ->group(['Articles.id']); - $total = $query->count(); - -After counting, the query can still be used for fetching the associated -records:: - - $list = $query->all(); - -Sometimes, you may want to provide an alternate method for counting the total -records of a query. One common use case for this is providing -a cached value or an estimate of the total rows, or to alter the query to remove -expensive unneeded parts such as left joins. This becomes particularly handy -when using the CakePHP built-in pagination system which calls the ``count()`` -method:: - - $query = $query->where(['is_active' => true])->counter(function($query) { - return 100000; - }); - $query->count(); // Returns 100000 - -In the example above, when the pagination component calls the count method, it -will receive the estimated hard-coded number of rows. - -.. _caching-query-results: - -Caching Loaded Results ----------------------- - -When fetching entities that don't change often you may want to cache the -results. The ``Query`` class makes this simple:: - - $query->cache('recent_articles'); - -Will enable caching on the query's result set. If only one argument is provided -to ``cache()`` then the 'default' cache configuration will be used. You can -control which caching configuration is used with the second parameter:: - - // String config name. - $query->cache('recent_articles', 'dbResults'); - - // Instance of CacheEngine - $query->cache('recent_articles', $memcache); - -In addition to supporting static keys, the ``cache()`` method accepts a function -to generate the key. The function you give it will receive the query as an -argument. You can then read aspects of the query to dynamically generate the -cache key:: - - // Generate a key based on a simple checksum - // of the query's where clause - $query->cache(function($q) { - return 'articles-' . md5(serialize($q->clause('where'))); - }); - -The cache method makes it simple to add cached results to your custom finders or -through event listeners. - -When the results for a cached query are fetched the following happens: - -1. The ``Model.beforeFind`` event is triggered. -2. If the query has results set, those will be returned. -3. The cache key will be resolved and cache data will be read. If the cache data - is not empty, those results will be returned. -4. If the cache misses, the query will be executed and a new ``ResultSet`` will be - created. This ``ResultSet`` will be written to the cache and returned. - -.. note:: - - You cannot cache a streaming query result. - -Loading Associations -==================== - -The builder can help you retrieve data from multiple tables at the same time -with the minimum amount of queries possible. To be able to fetch associated -data, you first need to setup associations between the tables as described in -the :ref:`table-associations` section. This technique of combining queries -to fetch associated data from other tables is called **eager loading**. - -.. include:: ./table-objects.rst - :start-after: start-contain - :end-before: end-contain - -Adding Joins ------------- - -In addition to loading related data with ``contain()``, you can also add -additional joins with the query builder:: - - $query = $articles->find() - ->hydrate(false) - ->join([ - 'table' => 'comments', - 'alias' => 'c', - 'type' => 'LEFT', - 'conditions' => 'c.article_id = articles.id', - ]); - -You can append multiple joins at the same time by passing an associative array -with multiple joins:: - - $query = $articles->find() - ->hydrate(false) - ->join([ - 'c' => [ - 'table' => 'comments', - 'type' => 'LEFT', - 'conditions' => 'c.article_id = articles.id', - ], - 'u' => [ - 'table' => 'users', - 'type' => 'INNER', - 'conditions' => 'u.id = articles.user_id', - ] - ]); - -As seen above, when adding joins the alias can be the outer array key. Join -conditions can also be expressed as an array of conditions:: - - $query = $articles->find() - ->hydrate(false) - ->join([ - 'c' => [ - 'table' => 'comments', - 'type' => 'LEFT', - 'conditions' => [ - 'c.created >' => new DateTime('-5 days'), - 'c.moderated' => true, - 'c.article_id = articles.id' - ] - ], - ], ['a.created' => 'datetime', 'c.moderated' => 'boolean']); - -When creating joins by hand and using array based conditions, you need to -provide the datatypes for each column in the join conditions. By providing -datatypes for the join conditions, the ORM can correctly convert data types into -SQL. - -Inserting Data -============== - -Unlike earlier examples, you should not use ``find()`` to create insert queries. -Instead, create a new ``Query`` object using ``query()``:: - - $query = $articles->query(); - $query->insert(['title', 'body']) - ->values([ - 'title' => 'First post', - 'body' => 'Some body text' - ]) - ->execute(); - -Generally, it is easier to insert data using entities and -:php:meth:`~Cake\\ORM\\Table::save()`. By composing a ``SELECT`` and -``INSERT`` query together, you can create ``INSERT INTO ... SELECT`` style -queries:: - - $select = $articles->find() - ->select(['title', 'body', 'published']) - ->where(['id' => 3]); - - $query = $articles->query() - ->insert(['title', 'body', 'published']) - ->values($select) - ->execute(); - -Updating Data -============= - -As with insert queries, you should not use ``find()`` to create update queries. -Instead, create new a ``Query`` object using ``query()``:: - - $query = $articles->query(); - $query->update() - ->set(['published' => true]) - ->where(['id' => $id]) - ->execute(); - -Generally, it is easier to update data using entities and -:php:meth:`~Cake\\ORM\\Table::patchEntity()`. - -Deleting Data -============= - -As with insert queries, you should not use ``find()`` to create delete queries. -Instead, create new a query object using ``query()``:: - - $query = $articles->query(); - $query->delete() - ->where(['id' => $id]) - ->execute(); - -Generally, it is easier to delete data using entities and -:php:meth:`~Cake\\ORM\\Table::delete()`. - -More Complex Queries -==================== - -The query builder is capable of building complex queries like ``UNION`` queries -and sub-queries. - -Unions ------- - -Unions are created by composing one or more select queries together:: - - $inReview = $articles->find() - ->where(['need_review' => true]); - - $unpublished = $articles->find() - ->where(['published' => false]); - - $unpublished->union($inReview); - -You can create ``UNION ALL`` queries using the ``unionAll`` method:: - - $inReview = $articles->find() - ->where(['need_review' => true]); - - $unpublished = $articles->find() - ->where(['published' => false]); - - $unpublished->unionAll($inReview); - -Subqueries ----------- - -Subqueries are a powerful feature in relational databases and building them in -CakePHP is fairly intuitive. By composing queries together, you can make -subqueries:: - - $matchingComment = $articles->association('Comments')->find() - ->select(['article_id']) - ->distinct() - ->where(['comment LIKE' => '%CakePHP%']); - - $query = $articles->find() - ->where(['id' => $matchingComment]); - -Subqueries are accepted anywhere a query expression can be used. For example, in -the ``select()`` and ``join()`` methods. - -.. _format-results: - -Adding Calculated Fields -======================== - -After your queries, you may need to do some post-processing. If you need to add -a few calculated fields or derived data, you can use the ``formatResults()`` -method. This is a lightweight way to map over the result sets. If you need more -control over the process, or want to reduce results you should use -the :ref:`Map/Reduce ` feature instead. If you were querying a list -of people, you could easily calculate their age with a result formatter:: - - // Assuming we have built the fields, conditions and containments. - $query->formatResults(function($results) { - return $results->map(function($row) { - $row['age'] = $row['birth_date']->diff(new \DateTime)->y; - return $row; - }); - }); - -As you can see in the example above, formatting callbacks will get a -``ResultSetDecorator`` as their first argument. The second argument will be -the Query instance the formatter was attached to. The ``$results`` argument can -be traversed and modified as necessary. - -Result formatters are required to return an iterator object, which will be used -as the return value for the query. Formatter functions are applied after all the -Map/Reduce routines have been executed. Result formatters can be applied from -within contained associations as well. CakePHP will ensure that your formatters -are properly scoped. For example, doing the following would work as you may -expect:: - - // In a method in the Articles table - $query->contain(['Authors' => function ($q) { - return $q->formatResults(function($authors) { - return $authors->map(function($author) { - $author['age'] = $author['birth_date']->diff(new \DateTime)->y; - return $author; - }); - }); - }); - - // Get results - $results = $query->all(); - - // Outputs 29 - echo $results->first()->author->age; - -As seen above, the formatters attached to associated query builders are scoped -to operate only on the data in the association. CakePHP will ensure that -computed values are inserted into the correct entity. - -.. _map-reduce: - -Modifying Results with Map/Reduce -================================== - -More often than not, find operations require post-processing the data that is -found in the database. While entities' getter methods can take care of most of -the virtual property generation or special data formatting, sometimes you -need to change the data structure in a more fundamental way. - -For those cases, the ``Query`` object offers the ``mapReduce()`` method, which -is a way of processing results once they are fetched from the database. - -A common example of changing the data structure is grouping results together -based on certain conditions. For this task we can use the ``mapReduce()`` -function. We need two callable functions the ``$mapper`` and the ``$reducer``. -The ``$mapper`` callable receives the current result from the database as first -argument, the iteration key as second argument and finally it receives an -instance of the ``MapReduce`` routine it is running:: - - $mapper = function ($article, $key, $mapReduce) { - $status = 'published'; - if ($article->isDraft() || $article->isInReview()) { - $status = 'unpublished'; - } - $mapReduce->emitIntermediate($article, $status); - }; - -In the above example ``$mapper`` is calculating the status of an article, either -published or unpublished, then it calls ``emitIntermediate()`` on the -``MapReduce`` instance. The method stores the article in the list of articles -labelled as either published or unpublished. - -The next step in the map-reduce process is to consolidate the final results. For -each status created in the mapper, the ``$reducer`` function will be called so -you can do any extra processing. This function will receive the list of articles -in a particular ``bucket`` as the first parameter, the name of the ``bucket`` it -needs to process as the second parameter, and again, as in the ``mapper()`` -function, the instance of the ``MapReduce`` routine as the third parameter. In -our example, we did not have to do any extra processing, so we just ``emit()`` -the final results:: - - $reducer = function ($articles, $status, $mapReduce) { - $mapReduce->emit($articles, $status); - }; - -Finally, we can put these two functions together to do the grouping:: - - $articlesByStatus = $articles->find() - ->where(['author_id' => 1]) - ->mapReduce($mapper, $reducer); - - foreach ($articlesByStatus as $status => $articles) { - echo sprintf("The are %d %s articles", count($articles), $status); - } - -The above will ouput the following lines:: - - There are 4 published articles - There are 5 unpublished articles - -Of course, this is a simplistic example that could actually be solved in another -way without the help of a map-reduce process. Now, let's take a look at another -example in which the reducer function will be needed to do something more than -just emitting the results. - -Calculating the most commonly mentioned words, where the articles contain -information about CakePHP, as usual we need a mapper function:: - - $mapper = function ($article, $key, $mapReduce) { - if (stripos('cakephp', $article['body']) === false) { - return; - } - - $words = array_map('strtolower', explode(' ', $article['body'])); - foreach ($words as $word) { - $mapReduce->emitIntermediate($article['id'], $word); - } - }; - -It first checks for whether the "cakephp" word in in the article's body, and -then breaks the body into individual words. Each word will create its own -``bucket`` where each article id will be stored. Now let's reduce our results to -only extract the count:: - - $reducer = function ($occurrences, $word, $mapReduce) { - $mapReduce->emit(count($occurrences), $word); - } - -Finally, we put everything together:: - - $articlesByStatus = $articles->find() - ->where(['published' => true]) - ->andWhere(['published_date >=' => new DateTime('2014-01-01')]) - ->hydrate(false) - ->mapReduce($mapper, $reducer); - -This could return a very large array if we don't clean stop words, but it could -look something like like this:: - - [ - 'cakephp' => 100, - 'awesome' => 39, - 'impressive' => 57, - 'outstanding' => 10, - 'mind-blowing' => 83 - ] - -One last example and you will be a map-reduce expert. Imagine you have -a ``friends`` table and you want to find "fake friends" in our database, or -better said, people who do not follow each other. Let's start with our -``mapper`` function:: - - $mapper = function ($rel, $key, $mr) { - $mr->emitIntermediate($rel['source_user_id'], $rel['target_user_id']); - $mr->emitIntermediate($rel['target_user_id'], $rel['source_target_id']); - }; - -We just duplicated our data to have a list of users each other user follows. -Now it's time to reduce it. For each call to the reducer, it will receive a list -of followers per user:: - - // $friends list will look like - // repeated numbers mean that the relationship existed in both directions - [2, 5, 100, 2, 4] - - $reducer = function ($friendsList, $user, $mr) { - $friends = array_count_values($friendsList); - foreach ($friends as $friend => $count) { - if ($count < 2) { - $mr->emit($friend, $user); - } - } - } - -And we supply our functions to a query:: - - $fakeFriends = $friends->find() - ->hydrate(false) - ->mapReduce($mapper, $reducer) - ->toArray(); - -This would return an array similar to this:: - - [ - 1 => [2, 4], - 3 => [6] - ... - ] - -The resulting array means, for example, that user with id ``1`` follows users -``2`` and ``4``, but those do not follow ``1`` back. - - -Stacking Multiple Operations ----------------------------- - -Using `mapReduce` in a query will not execute it immediately. The operation will -be registered to be run as soon as the first result is attempted to be fetched. -This allows you to keep chaining additional methods and filters to the query -even after adding a map-reduce routine:: - - $query = $articles->find() - ->where(['published' => true]) - ->mapReduce($mapper, $reducer); - - // At a later point in your app: - $query->where(['created >=' => new DateTime('1 day ago')]); - -This is particularly useful for building custom finder methods as described in the -:ref:`custom-find-methods` section:: - - public function findPublished(Query $query, array $options]) - { - return $query->where(['published' => true]); - } - - public function findRecent(Query $query, array $options) - { - return $query->where(['created >=' => new DateTime('1 day ago')]); - } - - public function findCommonWords(Query $query, array $options) - { - // Same as in the common words example in the previous section - $mapper = ...; - $reducer = ...; - return $query->mapReduce($mapper, $reducer); - } - - $commonWords = $articles - ->find('commonWords') - ->find('published') - ->find('recent'); - -Moreover, it is also possible to stack more than one ``mapReduce`` operation for -a single query. For example, if we wanted to have the most commonly used words -for articles, but then filter it to only return words that were mentioned more -than 20 times across all articles:: - - $mapper = function ($count, $word, $mr) { - if ($count > 20) { - $mr->emit($count, $word); - } - }; - - $articles->find('commonWords')->mapReduce($mapper); - -Removing All Stacked Map-reduce Operations ------------------------------------------- - -Under some circumstances you may want to modify a ``Query`` object so that no -``mapReduce`` operations are executed at all. This can be easily done by -calling the method with both parameters as null and the third parameter -(overwrite) as true:: + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. - $query->mapReduce(null, null, true); + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/retrieving-data-and-resultsets.rst b/es/orm/retrieving-data-and-resultsets.rst new file mode 100644 index 0000000000000000000000000000000000000000..32e23e042c00969cacd087ec20f5e10a1aacfd61 --- /dev/null +++ b/es/orm/retrieving-data-and-resultsets.rst @@ -0,0 +1,15 @@ +Retrieving Data & Results Sets +############################## + +.. php:namespace:: Cake\ORM + +.. php:class:: Table + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/saving-data.rst b/es/orm/saving-data.rst new file mode 100644 index 0000000000000000000000000000000000000000..09a78c5f36d15554b83fc04c5327030c77af65f7 --- /dev/null +++ b/es/orm/saving-data.rst @@ -0,0 +1,15 @@ +Saving Data +########### + +.. php:namespace:: Cake\ORM + +.. php:class:: Table + +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. + + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. + + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/schema-system.rst b/es/orm/schema-system.rst index e82c879aa5fcfc295d6a02f1057a81b14dfb6e3f..028be86931790e9b689de54d0f36f704d2aa5863 100644 --- a/es/orm/schema-system.rst +++ b/es/orm/schema-system.rst @@ -1,237 +1,13 @@ Schema System ############# -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - .. php:namespace:: Cake\Database\Schema -CakePHP features a schema system that is capable of reflecting and generating -schema information for tables in SQL datastores. The schema system can -generate/reflect a schema for any SQL platform that CakePHP supports. - -The main pieces of the schema system are ``Cake\Database\Schema\Table`` and -``Cake\Database\Schema\Collection``. These classes give you access to -database-wide and individual Table object features respectively. - -The primary use of the schema system is for :ref:`test-fixtures`. However, it -can also be used in your application if required. - -Schema\\Table Objects -===================== - -.. php:class:: Table - -The schema subsystem provides a simple Table object to hold data about a table -in a database. This object is returned by the schema reflection features:: - - use Cake\Database\Schema\Table; - - // Create a table one column at a time. - $t = new Table('posts'); - $t->addColumn('id', [ - 'type' => 'integer', - 'length' => 11, - 'null' => false, - 'default' => null, - ])->addColumn('title', [ - 'type' => 'string', - 'length' => 255, - // Create a fixed length (char field) - 'fixed' => true - ])->addConstraint('primary', [ - 'type' => 'primary', - 'columns' => ['id'] - ]); - - // Schema\Table classes could also be created with array data - $t = new Table('posts', $columns); - -``Schema\Table`` objects allow you build up information about a table's schema. It helps to -normalize and validate the data used to describe a table. For example, the -following two forms are equivalent:: - - $t->addColumn('title', 'string'); - // and - $t->addColumn('title', [ - 'type' => 'string' - ]); - -While equivalent, the 2nd form allows more detail and control. This emulates -the existing features available in Schema files + the fixture schema in 2.x. - -Accessing Column Data ---------------------- - -Columns are either added as constructor arguments, or via `addColumn()`. Once -fields are added information can be fetched using `column()` or `columns()`:: - - // Get the array of data about a column - $c = $t->column('title'); - - // Get the list of all columns. - $cols = $t->columns(); - - -Indexes and Constraints ------------------------ - -Indexes are added using the ``addIndex()``. Constraints are added using -``addConstraint()``. Indexes & constraints cannot be added for columns that do -not exist, as it would result in an invalid state. Indexes are different from -constraints and exceptions will be raised if you try to mix types beween the -methods. An example of both methods is:: - - $t = new Table('posts'); - $t->addColumn('id', 'integer') - ->addColumn('author_id', 'integer') - ->addColumn('title', 'string') - ->addColumn('slug', 'string'); - - // Add a primary key. - $t->addConstraint('primary', [ - 'type' => 'primary', - 'columns' => ['id'] - ]); - // Add a unique key - $t->addConstraint('slug_idx', [ - 'columns' => ['slug'], - 'type' => 'unique', - ]); - // Add index - $t->addIndex('slug_title', [ - 'columns' => ['slug', 'title'], - 'type' => 'index' - ]); - // Add a foreign key - $t->addConstraint('author_id_idx', [ - 'columns' => ['author_id'], - 'type' => 'foreign', - 'references' => ['authors', 'id'], - 'update' => 'cascade', - 'delete' => 'cascade' - ]); - -If you add a primary key constraint to a single integer column it will automatically -be converted into a auto-increment/serial column depending on the database -platform:: - - $t = new Table('posts'); - $t->addColumn('id', 'integer') - ->addConstraint('primary', [ - 'type' => 'primary', - 'columns' => ['id'] - ]); - -In the above example the ``id`` column would generate the following SQL in -MySQL:: - - CREATE TABLE `posts` ( - `id` INTEGER AUTO_INCREMENT, - PRIMARY KEY (`id`) - ) - -If your primary key contains more than one column, none of them will -automatically be converted to an auto-increment value. Instead you will need to -tell the table object which column in the composite key you want to -auto-increment:: - - $t = new Table('posts'); - $t->addColumn('id', [ - 'type' => 'integer', - 'autoIncrement' => true, - ]) - ->addColumn('account_id', 'integer') - ->addConstraint('primary', [ - 'type' => 'primary', - 'columns' => ['id', 'account_id'] - ]); - -The ``autoIncrement`` option only works with ``integer`` and ``biginteger`` -columns. - -Reading Indexes and Constraints -------------------------------- - -Indexes and constraints can be read out of a table object using accessor -methods. Assuming that ``$t`` is a populated Table instance you could do the -following:: - - // Get contraints. Will return the - // names of all constraints. - $constraints = $t->constraints() - - // Get data about a single constraint. - $constraint = $t->constraint('author_id_idx') - - // Get indexes. Will return the - // names of all indexes. - $indexes = $t->indexes() - - // Get data about a single index. - $index = $t->index('author_id_idx') - - -Adding Table Options --------------------- - -Some drivers (primarily MySQL) support & require additional table metadata. In -the case of MySQL the ``CHARSET``, ``COLLATE`` and ``ENGINE`` properties are -required for maintaining a table's structure in MySQL. The following could be -used to add table options:: - - $t->options([ - 'engine' => 'InnoDB', - 'collate' => 'utf8_unicode_ci', - ]); - -Platform dialects only handle the keys they are interested in -and ignore the rest. Not all options are support on all platforms. - -Converting Tables into SQL --------------------------- - -Using the ``createSql()`` or ``dropSql()`` you can get -platform specific SQL for creating or dropping a specific table:: - - $db = ConnectionManager::get('default'); - $schema = new Table('posts', $fields, $indexes); - - // Create a table - $queries = $schema->createSql($db); - foreach ($queries as $sql) { - $db->execute($sql); - } - - // Drop a table - $sql = $schema->dropSql($db); - $db->execute($sql); - -By using a connection's driver the schema data can be converted into platform -specific SQL. The return of ``createSql`` and ``dropSql`` is a list of SQL -queries required to create a table and the required indexes. Some platforms may -require multiple statements to create tables with comments and/or indexes. An -array of queries is always returned. - - -Schema Collections -================== - -.. php:class:: Collection - -``Collection`` provides access to the various tables available on a connection. -You can use it to get the list of tables or reflect tables into -:php:class:`Table` objects. Basic usage of the class looks like:: - - $db = ConnectionManager::get('default'); - - // Create a schema collection. - $collection = $db->schemaCollection(); +.. note:: + La documentación no es compatible actualmente con el idioma español en esta página. - // Get the table names - $tables = $collection->listTables(); + Por favor, siéntase libre de enviarnos un pull request en + `Github `_ o utilizar el botón **Improve this Doc** para proponer directamente los cambios. - // Get a single table (instance of Schema\Table) - $table = $collection->describe('posts') + Usted puede hacer referencia a la versión en Inglés en el menú de selección superior + para obtener información sobre el tema de esta página. diff --git a/es/orm/table-objects.rst b/es/orm/table-objects.rst index 1f3b324317df053a2f2569aa246d9b9331c700af..44d1ae26f7f074ba2656916525330389b055f27c 100644 --- a/es/orm/table-objects.rst +++ b/es/orm/table-objects.rst @@ -5,2250 +5,13 @@ Table Objects ############# -.. note:: - Esta página todavía no ha sido traducida y pertenece a la documentación de - CakePHP 2.X. Si te animas puedes ayudarnos `traduciendo la documentación - desde Github `_. - .. php:class:: Table -Table objects provide access to the collection of entities stored in a specific -table. Each table in your application should have an associated Table class -which is used to interact with a given table. If you do not need to customize -the behavior of a given table CakePHP will generate a Table instance for you to -use. - -Before trying to use Table objects and the ORM, you should ensure that you have -configured your :ref:`database connection `. - -Basic Usage -=========== - -To get started, create a Table class. These classes live in -``src/Model/Table``. Tables are a type model collection specific to relational -databases, and the main interface to your database in CakePHP's ORM. The most -basic table class would look like:: - - namespace App\Model\Table; - - use Cake\ORM\Table; - - class ArticlesTable extends Table - { - } - -Note that we did not tell the ORM which table to use for our class. By -convention table objects will use a table that matches the lower cased and -underscored version of the class name. In the above example the ``articles`` -table will be used. If our table class was named ``BlogPosts`` your table should -be named ``blog_posts``. You can specify the table to using the ``table()`` -method:: - - namespace App\Model\Table; - - use Cake\ORM\Table; - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->table('my_table'); - } - - } - -No inflection conventions will be applied when specifying a table. By convention -the ORM also expects each table to have a primary key with the name of ``id``. -If you need to modify this you can use the ``primaryKey()`` method:: - - namespace App\Model\Table; - - use Cake\ORM\Table; - - class ArticlesTable extends Table - { - public function initialize(array $config) - { - $this->primaryKey('my_id'); - } - } - -As seen in the examples above Table objects have an ``initialize()`` method -which is called at the end of the constructor. It is recommended that you use -this method to do initialization logic instead of overriding the constructor. - -Getting Instances of a Table Class ----------------------------------- - -Before you can query a table, you'll need to get an instance of the table. You -can do this by using the ``TableRegistry`` class:: - - use Cake\ORM\TableRegistry; - - $articles = TableRegistry::get('Articles'); - -The TableRegistry class provides the various dependencies for constructing -a table, and maintains a registry of all the constructed table instances making -it easier to build relations and configure the ORM. See -:ref:`table-registry-usage` for more information. - -Fetching All Entities ---------------------- - -The best way to fetch entities from a table object is to use the ``find`` method. It -allows you to access the various built-in finder methods and your own custom -ones. See :ref:`custom-find-methods` for more information:: - - $query = $articles->find('all'); - foreach ($query as $row) { - // Do work - } - -Entity objects represent a single record or row in your database. Entities allow -you to define custom behavior on a per-record basis and model the domain of your -application. See the :ref:`entities` documentation for more information on -creating your entity objects. - -Customizing the Entity Class a Table Uses ------------------------------------------ - -By default table objects use an entity class based on naming conventions. For -example if your table class is called ``ArticlesTable`` the entity would be -``Article``. If the table class was ``PurchaseOrdersTable`` the entity would be -``PurchaseOrder``. If however, you want to use an entity that doesn't follow the -conventions you can use the ``entityClass`` method to change things up:: - - class PurchaseOrdersTable extends Table - { - public function initialize(array $config) - { - $this->entityClass('App\Model\PO'); - } - } - -.. _table-associations: - -Building Associations -===================== - -Defining relations between different objects in your application should be -a natural process. For example, an article may have many comments, and belong -to an author. Authors may have many articles and comments. CakePHP makes -managing these associations easy. The four association types in CakePHP are: -hasOne, hasMany, belongsTo, and belongsToMany. - -============= ===================== ======================================= -Relationship Association Type Example -============= ===================== ======================================= -one to one hasOne A user has one profile. -------------- --------------------- --------------------------------------- -one to many hasMany A user can have multiple articles. -------------- --------------------- --------------------------------------- -many to one belongsTo Many articles belong to a user. -------------- --------------------- --------------------------------------- -many to many belongsToMany Tags belong to many articles. -============= ===================== ======================================= - -Associations are defined during the ``inititalize()`` method of your table -object. Methods matching the association type allow you to define the -associations in your application. For example if we wanted to define a belongsTo -association in our ArticlesTable:: - - namespace App\Model\Table; - - use Cake\ORM\Table; - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->belongsTo('Authors'); - } - - } - -The simplest form of any association setup takes the table alias you want to -associate with. By default all of the details of an association will use the -CakePHP conventions. If you want to customize how your associations are handled -you can do so with the second parameter:: - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->belongsTo('Authors', [ - 'className' => 'Publishing.Authors', - 'foreignKey' => 'authorid', - 'propertyName' => 'person' - ]); - } - - } - -The same table can be used multiple times to define different types of -associations. For example consider a case where you want to separate -approved comments and those that have not been moderated yet:: - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->hasMany('Comments', [ - 'className' => 'Comments', - 'conditions' => ['approved' => true] - ]); - - $this->hasMany('UnapprovedComments', [ - 'className' => 'Comments', - 'conditions' => ['approved' => false], - 'propertyName' => 'unnaproved_comments' - ]); - } - } - -As you can see, by specifying the ``className`` key, it is possible to use the -same table as different associations for the same table. You can even create -self-associated tables to create parent-child relationships:: - - class CategoriesTable extends Table - { - - public function initialize(array $config) - { - $this->hasMany('SubCategories', [ - 'className' => 'Categories', - ]); - - $this->belongsTo('ParentCategories', [ - 'className' => 'Categories', - ]); - } - } - -HasOne Associations -------------------- - -Let's set up a User model with a hasOne relationship to an Address Table. - -First, your database tables need to be keyed correctly. For a hasOne -relationship to work, one table has to contain a foreign key that points to -a record in the other. In this case the addresses table will contain a field -called ``user_id``. The basic pattern is: - -**hasOne:** the *other* model contains the foreign key. - -====================== ================== -Relation Schema -====================== ================== -Users hasOne Addresses addresses.user\_id ----------------------- ------------------ -Doctors hasOne Mentors mentors.doctor\_id -====================== ================== - -.. note:: - - It is not mandatory to follow CakePHP conventions, you can easily override - the use of any foreignKey in your associations definitions. Nevertheless sticking - to conventions will make your code less repetitive, easier to read and to maintain. - -If we had the ``UsersTable`` and ``AddressesTable`` classes made we could make -the association with the following code:: - - class UsersTable extends Table - { - public function initialize(array $config) - { - $this->hasOne('Addresses'); - } - } - -If you need more control, you can define your associations using -array syntax. For example, you might want to limit the association -to include only certain records:: - - class UsersTable extends Table - { - public function initialize(array $config) - { - $this->hasOne('Addresses', [ - 'className' => 'Addresses', - 'conditions' => ['Addresses.primary' => '1'], - 'dependent' => true - ]); - } - } - -Possible keys for hasOne association arrays include: - -- **className**: the class name of the table being associated to - the current model. If you're defining a 'User hasOne Address' - relationship, the className key should equal 'Addresses'. -- **foreignKey**: the name of the foreign key found in the other - model. This is especially handy if you need to define multiple - hasOne relationships. The default value for this key is the - underscored, singular name of the current model, suffixed with - '\_id'. In the example above it would default to 'user\_id'. -- **conditions**: an array of find() compatible conditions - such as ``['Addresses.primary' => true]`` -- **joinType**: the type of the join to use in the SQL query, default - is INNER. You may want to use LEFT if your hasOne association is optional. -- **dependent**: When the dependent key is set to true, and an - entity is deleted, the associated model records are also deleted. In this - case we set it true so that deleting a User will also delete her associated - Address. -- **cascadeCallbacks**: When this and **dependent** are true, cascaded deletes will - load and delete entities so that callbacks are properly triggered. When false, - ``deleteAll()`` is used to remove associated data and no callbacks are - triggered. -- **propertyName**: The property name that should be filled with data from the associated - table into the source table results. By default this is the underscored & singular name of - the association so ``address`` in our example. -- **finder**: The finder method to use when loading associated records. - -Once this association has been defined, find operations on the Users table can -contain the Address record if it exists:: - - $query = $users->find('all')->contain(['Addresses']); - foreach ($query as $user) { - echo $user->address->street; - } - -The above would emit SQL that is similar to:: - - SELECT * FROM users INNER JOIN addresses ON addresses.user_id = users.id; - -BelongsTo Associations ----------------------- - -Now that we have Address data access from the User table, let's -define a belongsTo association in the Addresses table in order to get -access to related User data. The belongsTo association is a natural -complement to the hasOne and hasMany associations. - -When keying your database tables for a belongsTo relationship, -follow this convention: - -**belongsTo:** the *current* model contains the foreign key. - -========================= ================== -Relation Schema -========================= ================== -Addresses belongsTo Users addresses.user\_id -------------------------- ------------------ -Mentors belongsTo Doctors mentors.doctor\_id -========================= ================== - -.. tip:: - - If a Table contains a foreign key, it belongs to the other - Table. - -We can define the belongsTo association in our Addresses table as follows:: - - class AddressesTable extends Table - { - - public function initialize(array $config) - { - $this->belongsTo('Users'); - } - } - -We can also define a more specific relationship using array -syntax:: - - class AddressesTable extends Table - { - - public function initialize(array $config) - { - $this->belongsTo('Users', [ - 'foreignKey' => 'user_id', - 'joinType' => 'INNER', - ]); - } - } - -Possible keys for belongsTo association arrays include: - -- **className**: the class name of the model being associated to - the current model. If you're defining a 'Profile belongsTo User' - relationship, the className key should equal 'Users'. -- **foreignKey**: the name of the foreign key found in the current model. This - is especially handy if you need to define multiple belongsTo relationships to - the same model. The default value for this key is the underscored, singular - name of the other model, suffixed with ``_id``. -- **conditions**: an array of find() compatible conditions or SQL - strings such as ``['Users.active' => true]`` -- **joinType**: the type of the join to use in the SQL query, default - is LEFT which may not fit your needs in all situations, INNER may - be helpful when you want everything from your main and associated - models or nothing at all. -- **propertyName**: The property name that should be filled with data from the associated - table into the source table results. By default this is the underscored & singular name of - the association so ``user`` in our example. -- **finder**: The finder method to use when loading associated records. - -Once this association has been defined, find operations on the User table can -contain the Address record if it exists:: - - $query = $addresses->find('all')->contain(['Users']); - foreach ($query as $address) { - echo $address->user->username; - } - -The above would emit SQL that is similar to:: - - SELECT * FROM addresses LEFT JOIN users ON addresses.user_id = users.id; - - -HasMany Associations --------------------- - -An example of a hasMany association is "Article hasMany Comments". -Defining this association will allow us to fetch an article's comments -when the article is loaded. - -When creating your database tables for a hasMany relationship, follow -this convention: - -**hasMany:** the *other* model contains the foreign key. - -========================== =================== -Relation Schema -========================== =================== -Article hasMany Comment Comment.article\_id --------------------------- ------------------- -Product hasMany Option Option.product\_id --------------------------- ------------------- -Doctor hasMany Patient Patient.doctor\_id -========================== =================== - -We can define the hasMany association in our Articles model as follows:: - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->hasMany('Comments'); - } - } - -We can also define a more specific relationship using array -syntax:: - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->hasMany('Comments', [ - 'foreignKey' => 'article_id', - 'dependent' => true, - ]); - } - } - -Possible keys for hasMany association arrays include: - -- **className**: the class name of the model being associated to - the current model. If you're defining a 'User hasMany Comment' - relationship, the className key should equal 'Comment'. -- **foreignKey**: the name of the foreign key found in the other - model. This is especially handy if you need to define multiple - hasMany relationships. The default value for this key is the - underscored, singular name of the actual model, suffixed with - '\_id'. -- **conditions**: an array of find() compatible conditions or SQL - strings such as ``['Comments.visible' => true]`` -- **sort** an array of find() compatible order clauses or SQL - strings such as ``['Comments.created' => 'ASC']`` -- **dependent**: When dependent is set to true, recursive model - deletion is possible. In this example, Comment records will be - deleted when their associated Article record has been deleted. -- **cascadeCallbacks**: When this and **dependent** are true, cascaded deletes will - load and delete entities so that callbacks are properly triggered. When false, - ``deleteAll()`` is used to remove associated data and no callbacks are - triggered. -- **propertyName**: The property name that should be filled with data from the associated - table into the source table results. By default this is the underscored & plural name of - the association so ``comments`` in our example. -- **strategy**: Defines the query strategy to use. Defaults to 'SELECT'. The other - valid value is 'subquery', which replaces the ``IN`` list with an equivalent - subquery. -- **finder**: The finder method to use when loading associated records. - -Once this association has been defined, find operations on the Articles table can -contain the Comment records if they exist:: - - $query = $articles->find('all')->contain(['Comments']); - foreach ($query as $article) { - echo $article->comments[0]->text; - } - -The above would emit SQL that is similar to:: - - SELECT * FROM articles; - SELECT * FROM comments WHERE article_id IN (1, 2, 3, 4, 5); - -When the subquery strategy is used, SQL similar to the following will be -generated:: - - SELECT * FROM articles; - SELECT * FROM comments WHERE article_id IN (SELECT id FROM articles); - -You may want to cache the counts for your hasMany associations. This is useful -when you often need to show the number of associated records, but don't want to -load all the records just to count them. For example, the comment count on any -given article is often cached to make generating lists of articles more -efficient. You can use the :doc:`CounterCacheBehavior -` to cache counts of associated -records. - -BelongsToMany Associations --------------------------- - -An example of a BelongsToMany association is "Article BelongsToMany Tags", where -the tags from one article are shared with other articles. BelongsToMany is -often referred to as "has and belongs to many", and is a classic "many to many" -association. - -The main difference between hasMany and BelongsToMany is that the link between -the models in a BelongsToMany association are not exclusive. For example, we are -joining our Articles table with a Tags table. Using 'funny' as a Tag for my -Article, doesn't "use up" the tag. I can also use it on the next article -I write. - -Three database tables are required for a BelongsToMany association. In the -example above we would need tables for ``articles``, ``tags`` and -``articles_tags``. The ``articles_tags`` table contains the data that links -tags and articles together. The joining table is named after the two tables -involved, separated with an underscore by convention. In its simplest form, this -table consists of ``article_id`` and ``tag_id``. - -**belongsToMany** requires a separate join table that includes both *model* -names. - -============================ ================================================================ -Relationship Pivot Table Fields -============================ ================================================================ -Article belongsToMany Tag articles_tags.id, articles_tags.tag_id, articles_tags.article_id ----------------------------- ---------------------------------------------------------------- -Patient belongsToMany Doctor doctors_patients.id, doctors_patients.doctor_id, - doctors_patients.patient_id. -============================ ================================================================ - -We can define the belongsToMany association in our Articles model as follows:: - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->belongsToMany('Tags'); - } - } - -We can also define a more specific relationship using array -syntax:: - - class ArticlesTable extends Table - { - - public function initialize(array $config) - { - $this->belongsToMany('Tags', [ - 'joinTable' => 'article_tag', - ]); - } - } - -Possible keys for belongsToMany association arrays include: - -- **className**: the class name of the model being associated to - the current model. If you're defining a 'Article belongsToMany Tag' - relationship, the className key should equal 'Tags.' -- **joinTable**: The name of the join table used in this - association (if the current table doesn't adhere to the naming - convention for belongsToMany join tables). By default this table - name will be used to load the Table instance for the join/pivot table. -- **foreignKey**: the name of the foreign key found in the current - model. This is especially handy if you need to define multiple - belongsToMany relationships. The default value for this key is the - underscored, singular name of the current model, suffixed with '\_id'. -- **targetForeignKey**: the name of the foreign key found in the target - model. The default value for this key is the underscored, singular name of - the target model, suffixed with '\_id'. -- **conditions**: an array of find() compatible conditions. If you have - conditions on an associated table, you should use a 'through' model, and - define the necessary belongsTo associations on it. -- **sort** an array of find() compatible order clauses. -- **through** Allows you to provide a either the name of the Table instance you - want used on the join table, or the instance itself. This makes customizing - the join table keys possible, and allows you to customize the behavior of the - pivot table. -- **cascadeCallbacks**: When this is true, cascaded deletes will load and delete - entities so that callbacks are properly triggered on join table records. When - false, ``deleteAll()`` is used to remove associated data and no callbacks are - triggered. This defaults to false to help reduce overhead. -- **propertyName**: The property name that should be filled with data from the associated - table into the source table results. By default this is the underscored & plural name of - the association, so ``tags`` in our example. -- **strategy**: Defines the query strategy to use. Defaults to 'SELECT'. The other - valid value is 'subquery', which replaces the ``IN`` list with an equivalent - subquery. -- **saveStrategy**: Either 'append' or 'replace'. Indicates the mode to be used - for saving associated entities. The former will only create new links - between both side of the relation and the latter will do a wipe and - replace to create the links between the passed entities when saving. -- **finder**: The finder method to use when loading associated records. - - -Once this association has been defined, find operations on the Articles table can -contain the Tag records if they exist:: - - $query = $articles->find('all')->contain(['Tags']); - foreach ($query as $article) { - echo $article->tags[0]->text; - } - -The above would emit SQL that is similar to:: - - SELECT * FROM articles; - SELECT * FROM tags - INNER JOIN articles_tags ON ( - tags.id = article_tags.tag_id - AND article_id IN (1, 2, 3, 4, 5) - ); - -When the subquery strategy is used, SQL similar to the following will be -generated:: - - SELECT * FROM articles; - SELECT * FROM tags - INNER JOIN articles_tags ON ( - tags.id = article_tags.tag_id - AND article_id IN (SELECT id FROM articles) - ); - -Using the 'through' Option -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you plan on adding extra information to the join/pivot table, or if you -need to use join columns outside of the conventions, you will need to define the -``through`` option. The ``through`` option provides you full control over how the -belongsToMany association will be created. - -It is sometimes desirable to store additional data with a many to -many association. Consider the following:: - - Student BelongsToMany Course - Course BelongsToMany Student - -A Student can take many Courses and a Course can be taken by many Students. This -is a simple many to many association. The following table would suffice:: - - id | student_id | course_id - -Now what if we want to store the number of days that were attended -by the student on the course and their final grade? The table we'd -want would be:: - - id | student_id | course_id | days_attended | grade - -The way to implement our requirement is to use a **join model**, -otherwise known as a **hasMany through** association. -That is, the association is a model itself. So, we can create a new -model CoursesMemberships. Take a look at the following models. :: - - class StudentsTable extends Table - { - public function initialize(array $config) - { - $this->belongsToMany('Courses', [ - 'through' => 'CourseMemberships', - ]); - } - } - - class CoursesTable extends Table - { - public function initialize(array $config) - { - $this->belongsToMany('Students', [ - 'through' => 'CourseMemberships', - ]); - } - } - - class CoursesMembershipsTable extends Table - { - public function initialize(array $config) - { - $this->belongsTo('Students'); - $this->belongsTo('Courses'); - } - } - -The CoursesMemberships join table uniquely identifies a given -Student's participation on a Course in addition to extra -meta-information. - -Using the 'finder' Option -------------------------- - -The ``finder`` option allows you to use a :ref:`custom finder -` to load associated record data. This lets you encapsulate -your queries better and keep your code DRY'er. There are some limitations when -using finders to load associated records for associations that are loaded using -joins (belongsTo/hasOne). Only the following aspects of the query will be -applied to the root query: - -- WHERE conditions -- Additional joins -- Contained associations -- Map/Reduce functions -- Result formatters - -Other aspects of the query, such as selected columns, order, group by, having and -other sub-statements, will not be applied to the root query. Associations that -are *not* loaded through joins (hasMany/belongsToMany), do not have the above -restrictions. - -Loading Entities -================ - -While table objects provide an abstraction around a 'repository' or collection of -objects, when you query for individual records you get 'entity' objects. While -this section discusses the different ways you can find and load entities, you -should read the :doc:`/orm/entities` section for more information on entities. - -Getting a Single Entity by Primary Key --------------------------------------- - -.. php:method:: get($id, $options = []) - -It is often convenient to load a single entity from the database when editing or -view entities and their related data. You can do this easily by using -``get()``:: - - // Get a single article - $article = $articles->get($id); - - // Get a single article, and related comments - $article = $articles->get($id, [ - 'contain' => ['Comments'] - ]); - -If the get operation does not find any results -a ``Cake\ORM\Error\RecordNotFoundException`` will be raised. You can either -catch this exception yourself, or allow CakePHP to convert it into a 404 error. - -Using Finders to Load Data --------------------------- - -.. php:method:: find($type, $options = []) - -Before you can work with entities, you'll need to load them. The easiest way to -do this is using the ``find`` method. The find method provides an easy and -extensible way to find the data you are interested in:: - - // Find all the articles - $query = $articles->find('all'); - -The return value of any ``find`` method is always -a :php:class:`Cake\\ORM\\Query` object. The Query class allows you to further -refine a query after creating it. Query objects are evaluated lazily, and do not -execute until you start fetching rows, convert it to an array, or when the -``all()`` method is called:: - - // Find all the articles. - // At this point the query has not run. - $query = $articles->find('all'); - - // Iteration will execute the query. - foreach ($query as $row) { - } - - // Calling execute will execute the query - // and return the result set. - $results = $query->all(); - - // Converting the query to an array will execute it. - $results = $query->toArray(); - -Once you've started a query you can use the :doc:`/orm/query-builder` interface -to build more complex queries, adding additional conditions, limits, or include -associations using the fluent interface:: - - $query = $articles->find('all') - ->where(['Articles.created >' => new DateTime('-10 days')]) - ->contain(['Comments', 'Authors']) - ->limit(10); - -You can also provide many commonly used options to ``find()``. This can help -with testing as there are fewer methods to mock:: - - $query = $articles->find('all', [ - 'conditions' => ['Articles.created >' => new DateTime('-10 days')], - 'contain' => ['Authors', 'Comments'], - 'limit' => 10 - ]); - -The list of options supported by find() are: - -- ``conditions`` provide conditions for the WHERE clause of your query. -- ``limit`` Set the number of rows you want. -- ``offset`` Set the page offset you want. You can also use ``page`` to make - the calculation simpler. -- ``contain`` define the associations to eager load. -- ``fields`` limit the fields loaded into the entity. Only loading some fields - can cause entities to behave incorrectly. -- ``group`` add a GROUP BY clause to your query. This is useful when using - aggregating functions. -- ``having`` add a HAVING clause to your query. -- ``join`` define additional custom joins. -- ``order`` order the result set. - -Any options that are not in this list will be passed to beforeFind listeners -where they can be used to modify the query object. You can use the -``getOptions`` method on a query object to retrieve the options used. - -.. _table-find-first: - -Getting the First Result ------------------------- - -The ``first()`` method allows you to fetch only the first row from a query. If -the query has not been executed, a ``LIMIT 1`` clause will be applied:: - - $query = $articles->find('all', [ - 'order' => ['Articles.created' => 'DESC'] - ]); - $row = $query->first(); - -This approach replaces ``find('first')`` in previous versions of CakePHP. You -may also want to use the ``get()`` method if you are loading entities by primary -key. - -Getting a Count of Results --------------------------- - -Once you have created a query object, you can use the ``count()`` method to get -a result count of that query:: - - $query = $articles->find('all', [ - 'where' => ['Articles.title LIKE' => '%Ovens%'] - ]); - $number = $query->count(); - -See :ref:`query-count` for additional usage of the ``count()`` method. - -.. _table-find-list: - -Finding Key/Value Pairs ------------------------ - -It is often useful to generate an associative array of data from your application's -data. For example, this is very useful when creating ` + - + + Ceci peut être désactivé en définissant l'option ``$options['hiddenField'] = false``:: @@ -664,7 +702,7 @@ Les Options de Datetime * ``$options['interval']`` Cette option spécifie l'écart de minutes entre chaque option dans la select box minute:: - echo $this->Form->input('Model.time', [ + echo $this->Form->input('time', [ 'type' => 'time', 'interval' => 15 ]); @@ -675,9 +713,9 @@ Les Options de Datetime dans une direction. Par défaut à null qui arrondit à la moitié supérieure selon `interval`. -* ``$options['monthNames']`` If ``false``, 2 digit numbers will be used instead of text. - Si on lui passe un tableau du style ``['01' => 'Jan', '02' => 'Feb', ...]`` - alors ce tableau sera utilisé. +* ``$options['monthNames']`` If ``false``, 2 digit numbers will be used instead + of text. Si on lui passe un tableau du style + ``['01' => 'Jan', '02' => 'Feb', ...]`` alors ce tableau sera utilisé. Créer des Elements Input ======================== @@ -707,7 +745,7 @@ Créer des Inputs Password .. php:method:: password(string $fieldName, array $options) -Création d'un champ password. :: +Création d'un champ password:: echo $this->Form->password('password'); @@ -737,7 +775,7 @@ Créer des Textareas .. php:method:: textarea(string $fieldName, array $options) -Crée un champ input textarea (zone de texte). :: +Crée un champ input textarea (zone de texte):: echo $this->Form->textarea('notes'); @@ -794,7 +832,7 @@ Créer des Checkboxes Crée un élément de formulaire checkbox. Cette méthode génère également un input de formulaire caché pour forcer la soumission de données pour le champ -spécifié. :: +spécifié:: echo $this->Form->checkbox('done'); @@ -834,7 +872,7 @@ Créer des Boutons Radio Crée un jeu d'inputs radios. -**Options** +**Attributes** * ``value`` - Indique la valeur quand ce bouton radio est coché. * ``label`` - booléen pour indiquer si oui ou non les labels pour les widgets @@ -848,6 +886,33 @@ Crée un jeu d'inputs radios. première option. Quand à ``true``, le label radio sera 'vide'. Définissez cette option pour contrôler la valeur du label. +Generally ``$options`` is a simple key => value pair. However, if you need to +put custom attributes on your radio buttons you can use an expanded format:: + + echo $this->Form->radio( + 'favorite_color', + [ + ['value' => 'r', 'text' => 'Red', 'style' => 'color:red;'], + ['value' => 'u', 'text' => 'Blue', 'style' => 'color:blue;'], + ['value' => 'g', 'text' => 'Green', 'style' => 'color:green;'], + ] + ); + + // Will output + + + + + Créer des Pickers Select ------------------------ @@ -951,7 +1016,7 @@ sélectionnées. Par défaut à ``true``:: * ``$attributes['multiple']`` Si 'multiple' a été défini à ``true`` pour un input select, celui ci autorisera les sélections multiples:: - echo $this->Form->select('Model.field', $options, ['multiple' => true]); + echo $this->Form->select('field', $options, ['multiple' => true]); Vous pouvez également définir 'checkbox' à 'multiple' pour afficher une liste de check boxes reliés:: @@ -960,7 +1025,7 @@ sélectionnées. Par défaut à ``true``:: 'Value 1' => 'Label 1', 'Value 2' => 'Label 2' ]; - echo $this->Form->select('Model.field', $options, [ + echo $this->Form->select('field', $options, [ 'multiple' => 'checkbox' ]); @@ -990,7 +1055,7 @@ sélectionnées. Par défaut à ``true``:: 'Value 1' => 'Label 1', 'Value 2' => 'Label 2' ]; - echo $this->Form->select('Model.field', $options, [ + echo $this->Form->select('field', $options, [ 'multiple' => 'checkbox', 'disabled' => ['Value 1'] ]); @@ -1067,8 +1132,8 @@ les champs ``files``, type d'envodage du formulaire en définissant l'option type à 'file' dans ``$this->Form->create()``. -Crée des Inputs de date et d'heure (date and time inputs) ---------------------------------------------------------- +Crée des Inputs DateTime +------------------------ .. php:method:: dateTime($fieldName, $options = []) @@ -1080,12 +1145,12 @@ un certain nombre d'options: Si c'est un tableau, le tableau passé sera utilisé. * ``minYear`` L'année la plus ancienne à utiliser dans le select de l'année * ``maxYear`` L'année la plus lointaine à utiliser dans le select de l'année -* ``interval`` L'intervale en minutes entre chaque valeur dans le slect des minutes. 1 par défaut. +* ``interval`` L'intervale en minutes entre chaque valeur dans le slect des + minutes. 1 par défaut. * ``empty`` - Si ``true``, une option select vide est affichée. Si c'est une chaine, cette chaine est affichée comme élément vide. * ``round`` - Mettre à ``up`` ou ``down`` pour forcer l'arrondi dans une direction. Par défaut à null. - * ``default`` Le valeur par défaut à utiliser par l'input. Une valeur dans ``$this->request->data`` correspondante au nom du l'input écrasera cette valeur. Si aucune valeur par défaut n'est définie, ``time()`` sera utilisé. @@ -1098,6 +1163,61 @@ vous pouvez remplacer le template ``dateWidget``. Par défaut le template {{year}}{{month}}{{day}}{{hour}}{{minute}}{{second}}{{meridian}} +Créer des Inputs Time +--------------------- + +.. php:method:: time($fieldName, $options = []) + +Crée deux éléments select remplis respectivement avec 24 hours et 60 minutes +pour ``hour`` et ``minute``. +De plus, les attributs HTML peuvent être fournis dans $options pour chaque +``type`` spécifique. Si ``$options['empty']`` est ``false``, le select +n'inclura pas une option vide: + +* ``empty`` - Si ``true``, l'option select vide est montrée. Si c'est une + chaîne, cette chaîne sera affichée en tant qu'élément vide. +* ``default`` | ``value`` La valeur par défaut à utiliser pour l'input. Une + valeur dans ``$this->request->data`` qui correspond au nom du champ va écraser + cette valeur. + Si aucune valeur par défaut n'est fournie, ``time()`` sera utilisée. +* ``timeFormat`` Le format de time à utiliser, soit 12 soit 24. Par défaut à 24. +* ``second`` Défini à ``true`` pour activer les secondes déroulantes. +* ``interval`` L'intervalle pour le select minutes. Par défaut à 1. + +Par exemple, pour créer un intervalle de temps avec des minutes selectionnables +toutes les 15 minutes, et pour l'appliquer aux selects, vous pourriez faire +ceci :: + + echo $this->Form->time('released', [ + 'interval' => 15, + 'hour' => [ + 'class' => 'foo-class', + ], + 'minute' => [ + 'class' => 'bar-class', + ], + ]); + +Ce qui créerait les deux selects suivants: + +.. code-block:: html + + + + Créer des Inputs Year --------------------- @@ -1110,7 +1230,7 @@ Si ``$options['empty']`` est ``false``, le select n'aura pas de choix vide: * ``empty`` - Si ``true``, une option select vide est affichée. Si c'est une chaine, cette chaine est affichée comme élément vide. * ``orderYear`` - Ordre de tri des années dans les options du select. - Les valeurs accepteée sont 'asc', 'desc'. 'desc' par défaut. + Les valeurs acceptées sont 'asc', 'desc'. 'desc' par défaut. * ``value`` La valeur sélectionnée pour l'input. * ``maxYear`` L'année la plus lointaine à utiliser dans le select. * ``minYear`` L'année la plus ancienne à utiliser dans le select de l'année. @@ -1227,8 +1347,8 @@ Créer des Inputs Minute Crée un élément select (menu de sélection) rempli avec les minutes d'une heure. Vous pouvez créer un select qui contient des valeurs spécifiques -en utilisant l'option ``interval``. Par exemple si vous souhaitez une incrémentation -toutes les 10 minutes, vous devez faire:: +en utilisant l'option ``interval``. Par exemple si vous souhaitez une +incrémentation toutes les 10 minutes, vous devez faire:: echo $this->Form->minute('created', [ 'interval' => 10 @@ -1285,10 +1405,6 @@ Options: - 'escape' booléen s'il faut ou non que le HTML échappe le contenu de l'erreur. -- 'wrap' valeur mixte définissant s'il faut ou pas que le message d'erreur - soit enveloppé d'une div. Si c'est une chaîne , sera utilisé comme le - tag HTML à utiliser. -- 'class' chaine contenant le nom de classe du message d'erreur. .. TODO:: Add examples. @@ -1382,11 +1498,11 @@ Fermer le Formulaire .. php:method:: end($secureAttributes = []) -La méthode ``end()`` ferme et complète le marquage du formulaire. Souvent, ``end()`` affiche juste -la base fermante du formulaire, mais l'utilisation de ``end()`` permet -également au FormHelper d'ajouter les champs cachées dont le component -Security :php:class:`Cake\\Controller\\Component\\SecurityComponent` a -besoin: +La méthode ``end()`` ferme et complète le marquage du formulaire. Souvent, +``end()`` affiche juste la base fermante du formulaire, mais l'utilisation de +``end()`` permet également au FormHelper d'ajouter les champs cachées dont le +component Security :php:class:`Cake\\Controller\\Component\\SecurityComponent` +a besoin: .. code-block:: php @@ -1429,11 +1545,11 @@ Créer des Boutons Indépendants et des liens POST Crée une balise ``