+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<appendix version="5.0" xmlns="http://docbook.org/ns/docbook"
- xmlns:xl="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xmlns:xhtml="http://www.w3.org/1999/xhtml"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns:ns="http://docbook.org/ns/docbook"
- xmlns:mathml="http://www.w3.org/1998/Math/MathML">
- <title>Coding Guidelines</title>
-
- <para>Coding Standards are an important factor for achieving a high code
- quality. A common visual style, naming conventions and other technical
- settings allow us to produce a homogenous code which is easy to read and
- maintain. However, not all important factors can be covered by rules and
- coding standards. Equally important is the style in which certain problems
- are solved programmatically - it's the personality and experience of the
- individual developer which shines through and ultimately makes the
- difference between technically okay code or a well considered, mature
- solution.</para>
-
- <para>These guidelines try to cover both, the technical standards as well as
- giving incentives for a common development style. These guidelines must be
- followed by everyone who creates code for the FLOW3 core. Because TYPO3 is
- based on FLOW3, it follows the same principles - therefore, whenever we
- mention FLOW3 in the following sections, we equally refer to TYPO3. We hope
- that you feel encouraged to follow these guidelines as well when creating
- your own packages and FLOW3 based applications.</para>
-
- <section>
- <title>Code formatting and layout</title>
-
- <subtitle>aka "beautiful code"</subtitle>
-
- <para>The visual style of programming code is very important. In the TYPO3
- project we want many programmers to contribute, but in the same style.
- This will help us to:</para>
-
- <itemizedlist>
- <listitem>
- <para>Easily read/understand each others code and consequently easily
- spot security problems or optimization opportunities</para>
- </listitem>
-
- <listitem>
- <para>It is a signal about consistency and cleanliness, which is a
- motivating factor for programmers striving for excellence</para>
- </listitem>
- </itemizedlist>
-
- <para>Some people may object to the visual guidelines since everyone has
- his own habits. You will have to overcome that in the case of FLOW3; the
- visual guidelines must be followed along with coding guidelines for
- security. We want all contributions to the project to be as similar in
- style and as secure as possible.</para>
-
- <section>
- <title>General considerations</title>
-
- <itemizedlist>
- <listitem>
- <para>Almost every PHP file in FLOW3 contains exactly one class and
- does not output anything if it is called directly. Therefore you
- start your file with a <code><?php</code> tag and end it with the
- closing <code>?></code>.</para>
- </listitem>
-
- <listitem>
- <para>Every file must contain a header stating encoding, namespace,
- copyright and licensing information</para>
-
- <para><orderedlist>
- <listitem>
- <para>Declare your namespace. The namespace must start with
- "F3"!</para>
- </listitem>
-
- <listitem>
- <para>Because it is likely that more than one person will work
- on a class in the long run, we recommend adding a copyright
- statement like <quote>Copyright belongs to the respective
- authors</quote> and add yourself to the list of authors for
- the methods you implemented or changed (significantly).</para>
- </listitem>
-
- <listitem>
- <para>The copyright header itself must not start with
- <literal>/**</literal>, as this may confuse documentation
- generators!</para>
- </listitem>
- </orderedlist></para>
-
- <example>
- <title>The FLOW3 standard file header</title>
-
- <programlisting language="php"><?php
-declare(ENCODING = 'utf-8');
-namespace F3\Your\Stuff\Here;
-
-/* *
- * This script belongs to the FLOW3 framework. *
- * *
- * It is free software; you can redistribute it and/or modify it under *
- * the terms of the GNU Lesser General Public License as published by the *
- * Free Software Foundation, either version 3 of the License, or (at your *
- * option) any later version. *
- * *
- * This script is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- *
- * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser *
- * General Public License for more details. *
- * *
- * You should have received a copy of the GNU Lesser General Public *
- * License along with the script. *
- * If not, see http://www.gnu.org/licenses/lgpl.html *
- * *
- * The TYPO3 project - inspiring people to share! *
- * */</programlisting>
- </example>
- </listitem>
-
- <listitem>
- <para>Code lines are of arbitrary length, no limitations to 80
- characters or something similar (wake up, graphical displays have
- been available for decades now...)</para>
- </listitem>
-
- <listitem>
- <para>Lines end with a newline a.k.a <code>chr(10)</code> - UNIX
- style</para>
- </listitem>
-
- <listitem>
- <para>Files must be encoded in UTF-8</para>
- </listitem>
- </itemizedlist>
-
- <para>Make sure you use the correct license and mention the correct
- package in the header, See <link
- xl:href="http://forge.typo3.org/wiki/flow3-overview/Licensing_boilerplates_to_use_with_your_code">http://forge.typo3.org/wiki/flow3-overview/Licensing_boilerplates_to_use_with_your_code</link>
- for some boilerplate text.</para>
- </section>
-
- <section>
- <title>Indentation and line formatting</title>
-
- <para>Indentation is done with tabs - and not spaces! The beginning of a
- line is the only place where tabs are used, in all other places use
- spaces. Always trim whitespace off the end of a line.</para>
-
- <para>Here's a code snippet which shows the correct usage of tabs and
- spaces:</para>
-
- <para><example>
- <title>Correct use of tabs and spaces</title>
-
- <programlisting language="php">/**
- * Returns the name of the currently set context.
- *
- * @return string Name of the current context
- */
-public function getContextName() {
-» return $this->contextName;
-}</programlisting>
- </example></para>
-
- <para>There seem to be very passionate opinions about whether TABs or
- spaces should be used for indentation of code blocks in the scripts. If
- you'd like to read more about this religious discussion, you find some
- nice arguments in the <link
- xl:href="http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=3978">Joels
- on Software forum</link>.</para>
- </section>
-
- <section>
- <title>Naming</title>
-
- <para>Naming is a repeatedly undervalued factor in the art of software
- development. Although everybody seems to agree on that nice names are a
- nice thing to have, most developers choose cryptic abbreviations in the
- end (to save some typing). Beware that we TYPO3 core developers are very
- passionate about naming (some people call it fanatic, well ...). In our
- opinion spending 15 minutes (or more ...) just to find a good name for a
- method is well spent time! There are zillions of reasons for using
- proper names and in the end they all lead to better readable,
- manageable, stable and secure code.</para>
-
- <para><itemizedlist>
- <listitem>
- <para>As a general note, english words (or abbreviations if
- neccessary) must be used for all class names, method names,
- comments, variables names, database table and field names.
- Although PHP6 allows for using funny japanese, tibetian or
- don't-know-what characters, the consensus is that english is much
- better to read for the most of us.</para>
- </listitem>
-
- <listitem>
- <para>If acronyms or abbreviations are embedded in names, keep
- them in the case they usually are, i.e. keep
- <acronym>URL</acronym> uppercase, also when used in a method name
- like <methodname>getURLForLink()</methodname>,
- <classname>ACMEManager</classname> etc.</para>
- </listitem>
- </itemizedlist></para>
-
- <section>
- <title>Package names</title>
-
- <para>All package names are written in
- <package>UpperCamelCase</package>. In order to avoid problems with
- different filesystems, only the characters a-z, A-Z and 0-9 are
- allowed for package names – don't use special characters.</para>
- </section>
-
- <section>
- <title>Namespace names</title>
-
- <para>Only the characters a-z, A-Z and 0-9 are allowed for namespace
- names – don't use special characters. All namespace names are written
- in <classname>UpperCamelCase</classname>, all uppercase names are
- allowed for well established abbreviations.</para>
-
- <note>
- <para>When specifying class names to PHP, always reference the
- global namespace inside namespaced code by using a leading
- backslash. When referencing a class name inside a string (e.g. given
- to the <methodname>create</methodname>-Method of the
- <classname>ObjectFactory</classname>, in pointcut expressions or in
- YAML files), never use a leading backslash. This follows the native
- PHP notion of names in strings always being seen as fully
- qualified.</para>
- </note>
- </section>
-
- <section>
- <title>Class names</title>
-
- <para>Only the characters a-z, A-Z and 0-9 are allowed for class names
- – don't use special characters.</para>
-
- <para>All class names are written in
- <classname>UpperCamelCase</classname>, all uppercase names are allowed
- for well established abbreviations. Class names must be nouns, never
- adjectives.</para>
-
- <para>The name of abstract classes should start with the word
- "Abstract".</para>
-
- <para>A few examples follow:</para>
-
- <example>
- <title>Correct naming of classes</title>
-
- <itemizedlist>
- <listitem>
- <para><classname>\F3\FLOW3\Object</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>Tx_Extbase_Object_Manager</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\MyPackage\MyObject\MySubObject</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\MyPackage\MyObject\MyHTMLParser</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\Foo\Controller\DefaultController</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\MyPackage\MyObject\AbstractLogger</classname></para>
- </listitem>
- </itemizedlist>
- </example>
-
- <example>
- <title>Incorrect naming of classes</title>
-
- <itemizedlist>
- <listitem>
- <para><classname>\myClass</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\Urlwrapper</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\someObject\classname</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\MyPackage\MyObjectMySubObject</classname></para>
- </listitem>
- </itemizedlist>
- </example>
- </section>
-
- <section>
- <title>Interface names</title>
-
- <para>Only the characters a-z, A-Z and 0-9 are allowed for interface
- names – don't use special characters.</para>
-
- <para>All interface names are written in
- <classname>UpperCamelCase</classname>, all uppercase names are allowed
- for well established abbreviations. Interface names must be adjectives
- or nouns and have the Interface suffix. A few examples follow:</para>
-
- <example>
- <title>Correct naming of interfaces</title>
-
- <itemizedlist>
- <listitem>
- <para><classname>Tx_Extbase_Object_ObjectInterface</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>Tx_Extbase_Object_ManagerInterface</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\MyPackage\MyObject\MySubObjectInterface</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\MyPackage\MyObject\MyHTMLParserInterface</classname></para>
- </listitem>
- </itemizedlist>
- </example>
-
- <example>
- <title>Incorrect naming of interfaces</title>
-
- <itemizedlist>
- <listitem>
- <para><classname>\myInterface</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\Urlwrapper</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\IsomeObject\classname</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>Tx_Extbase_Object_Manager\Interface</classname></para>
- </listitem>
- </itemizedlist>
- </example>
- </section>
-
- <section>
- <title>Exception names</title>
-
- <para>Exception naming basically follows the rules for naming classes.
- There are two possible types of exceptions: Generic exceptions and
- specific exceptions. Generic exceptions should be named "Exception"
- preceeded by their namespace. Specific exceptions should reside in
- their own sub-namespace and must not contain the word
- <literal>Exception</literal>.</para>
-
- <example>
- <title>Correct naming of exceptions</title>
-
- <itemizedlist>
- <listitem>
- <para><classname>Tx_Extbase_Object_Exception</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>Tx_Extbase_Object_Exception_InvalidClassName</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\MyPackage\MyObject\Exception</classname></para>
- </listitem>
-
- <listitem>
- <para><classname>\F3\MyPackage\MyObject\Exception\OutOfCoffee</classname></para>
- </listitem>
- </itemizedlist>
- </example>
- </section>
-
- <section>
- <title>Method names</title>
-
- <para>All method names are written in lowerCamelCase, all uppercase
- names are allowed for well established abbreviations. In order to
- avoid problems with different filesystems, only the characters a-z,
- A-Z and 0-9 are allowed for method names – don't use special
- characters.</para>
-
- <para>Make method names descriptive, but keep them concise at the same
- time. Constructors must always be called
- <function>__construct()</function>, never use the class name as a
- method name.</para>
-
- <para>A few examples:</para>
-
- <example>
- <title>Correct naming of methods</title>
-
- <itemizedlist>
- <listitem>
- <para><methodname>myMethod()</methodname></para>
- </listitem>
-
- <listitem>
- <para><methodname>someNiceMethodName()</methodname></para>
- </listitem>
-
- <listitem>
- <para><methodname>betterWriteLongMethodNamesThanNamesNobodyUnderstands()</methodname></para>
- </listitem>
-
- <listitem>
- <para><methodname>singYMCALoudly()</methodname></para>
- </listitem>
-
- <listitem>
- <para><methodname>__construct()</methodname></para>
- </listitem>
- </itemizedlist>
- </example>
- </section>
-
- <section>
- <title>Variable names</title>
-
- <para>Variable names are written in <varname>lowerCamelCase</varname>
- and should be</para>
-
- <itemizedlist>
- <listitem>
- <para>self-explaining</para>
- </listitem>
-
- <listitem>
- <para>not shortened beyond recognition, but rather longer if it
- makes their meaning clearer</para>
- </listitem>
- </itemizedlist>
-
- <para>The following example shows two variables with the same meaning
- but different naming. You'll surely agree the longer versions are
- better (don't you ...?).</para>
-
- <example>
- <title>Correct naming of variables</title>
-
- <itemizedlist>
- <listitem>
- <para><varname>$singletonObjectsRegistry</varname></para>
- </listitem>
-
- <listitem>
- <para><varname>$argumentsArray</varname></para>
- </listitem>
-
- <listitem>
- <para><varname>$aLotOfHTMLCode</varname></para>
- </listitem>
- </itemizedlist>
- </example>
-
- <example>
- <title>Incorrect naming of variables</title>
-
- <itemizedlist>
- <listitem>
- <para><varname>$sObjRgstry</varname></para>
- </listitem>
-
- <listitem>
- <para><varname>$argArr</varname></para>
- </listitem>
-
- <listitem>
- <para><varname>$cx</varname></para>
- </listitem>
- </itemizedlist>
- </example>
-
- <para>As a special exception you may use variable names like
- <varname>$i</varname>, <varname>$j</varname> and <varname>$k</varname>
- for numeric indexes in <function>for</function> loops if it's clear
- what they mean on the first sight. But even then you might want to
- avoid them.</para>
- </section>
-
- <section>
- <title>Constant names</title>
-
- <para>All constant names are written in
- <constant>UPPERCASE</constant>. This includes
- <constant>TRUE</constant>, <constant>FALSE</constant> and
- <constant>NULL</constant>. Words can be separated by underscores - you
- can also use the underscore to group constants thematically:</para>
-
- <example>
- <title>Correct naming of constants</title>
-
- <itemizedlist>
- <listitem>
- <para><constant>STUFF_LEVEL</constant></para>
- </listitem>
-
- <listitem>
- <para><constant>COOLNESS_FACTOR</constant></para>
- </listitem>
-
- <listitem>
- <para><constant>PATTERN_MATCH_EMAILADDRESS</constant></para>
- </listitem>
-
- <listitem>
- <para><classname>PATTERN_MATCH_VALIDHTMLTAGS</classname></para>
- </listitem>
- </itemizedlist>
- </example>
-
- <para>It is, by the way, a good idea to use constants for defining
- regular expression patterns (as seen above) instead of defining them
- somewhere in your code.</para>
- </section>
-
- <section>
- <title>File names</title>
-
- <para>These are the rules for naming files:</para>
-
- <itemizedlist>
- <listitem>
- <para>All file names are
- <filename>UpperCamelCase</filename>.</para>
- </listitem>
-
- <listitem>
- <para>Class and interface files are named according to the class
- or interface they represent</para>
- </listitem>
-
- <listitem>
- <para>Each file must contain only one class or interface</para>
- </listitem>
-
- <listitem>
- <para>Names of files containing code for unit tests must be the
- same as the class which is tested, appended with
- "Test.php".</para>
- </listitem>
-
- <listitem>
- <para>Files are placed in a directory structure representing the
- namespace structure.</para>
- </listitem>
- </itemizedlist>
-
- <para>Here are some examples:<example>
- <title>File naming in FLOW3</title>
-
- <para><itemizedlist>
- <listitem>
- <para><filename>TemplateEngine/TemplateEngineInterface.php</filename></para>
-
- <para>Contains the interface
- <classname>\F3\TemplateEngine\TemplateEngineInterface</classname>
- which is part of the package
- <package>\F3\TemplateEngine</package></para>
- </listitem>
-
- <listitem>
- <para><filename>Error/RuntimeException.php</filename></para>
-
- <para>Contains the
- <classname>\F3\Error\RuntimeException</classname> being a
- part of the package <package>\F3\Error</package></para>
- </listitem>
-
- <listitem>
- <para><filename>DataAccess/Manager.php</filename></para>
-
- <para>Contains class
- <classname>\F3\DataAccess\Manager</classname> which is part
- of the package <package>\F3\DataAccess</package></para>
- </listitem>
-
- <listitem>
- <para><filename>FLOW3/Package/Manager.php</filename></para>
-
- <para>Contains the class
- <classname>\F3\FLOW3\Package\Manager</classname> which is
- part of the package <package>\F3\FLOW3</package></para>
- </listitem>
-
- <listitem>
- <para><filename>Package/ManagerTest.php</filename></para>
-
- <para>Contains the class
- <classname>\F3\FLOW3\Package\ManagerTest</classname> which
- is a test case for PHPUnit.</para>
- </listitem>
- </itemizedlist></para>
- </example></para>
- </section>
- </section>
-
- <section>
- <title>PHP code formatting</title>
-
- <section>
- <title>Strings</title>
-
- <para>In general, we use single quotes to enclose literal
- strings:</para>
-
- <example>
- <title>String literals</title>
-
- <programlisting language="php">$vision = 'Inspiring people to share';</programlisting>
- </example>
-
- <para>If the string itself contains single quotes or apostrophes, we
- use double quotes:</para>
-
- <example>
- <title>String literals enclosed by double quotes</title>
-
- <programlisting language="php">$message = "'Kasper' is the name of the friendly ghost.";</programlisting>
- </example>
-
- <para>If you'd like to insert values from variables, we prefer to
- concatenate strings:</para>
-
- <example>
- <title>Variable substitution</title>
-
- <programlisting language="php">$message = 'Hey ' . $name . ', you look ' . $look . ' today!';</programlisting>
- </example>
-
- <para>A space must be inserted before and after the dot for better
- readability:</para>
-
- <example>
- <title>Concatenated strings</title>
-
- <programlisting language="php">$vision = 'Inspiring people ' . 'to share.';</programlisting>
- </example>
-
- <para>You may break a string into multiple lines if you use the dot
- operator. You'll have to indent each following line to mark them as
- part of the value assignment:</para>
-
- <example>
- <title>Multi-line strings</title>
-
- <programlisting language="php">$vision = 'Inspiring' .
- 'people ' .
- 'to ' .
- 'share';</programlisting>
- </example>
- </section>
-
- <section>
- <title>Arrays</title>
-
- <para/>
- </section>
-
- <section>
- <title>Classes</title>
-
- <para>...<example>
- <title>Classes</title>
-
- <programlisting language="php">namespace F3\MyPackage;
-
-class MyObject {
-
-}</programlisting>
- </example></para>
- </section>
-
- <section>
- <title>Functions and methods</title>
-
- <para/>
- </section>
-
- <section>
- <title>if statements</title>
-
- <para><itemizedlist>
- <listitem>
- <para>There needs to be one space between the
- <function>if</function> keyword and the opening brace "(" of the
- test expression</para>
- </listitem>
-
- <listitem>
- <para>After the closing brace ")" of the test expression follows
- one space before the curly brace "{"</para>
- </listitem>
-
- <listitem>
- <para><function>else</function> and <function>elseif</function>
- are on the same line as their corresponding curly braces</para>
- </listitem>
- </itemizedlist><example>
- <title>if statements</title>
-
- <programlisting language="php">if ($something || $somethingElse) {
- doThis();
-} else {
- doSomethingElse();
-}
-
-if (allGoesWrong() === TRUE) throw new \Exception('Hey, all went wrong!', 123);
-
-if (weHaveALotOfCriteria() === TRUE
- && notEverythingFitsIntoOneLine() === TRUE
- || youJustTendToLikeIt() === TRUE) {
- doThis();
-
-} else {
- ...
-}</programlisting>
- </example></para>
- </section>
- </section>
- </section>
-
- <section>
- <title>Documentation</title>
-
- <para>All code must be documented with inline comments. The syntax is that
- known from the Java programming language (JavaDoc). This way code
- documentation can automatically be generated using tools like
- phpDocumentor or Doxygen. The "official" tool used is
- phpDocumentor<footnote>
- <para>We look into Doxygen as well, currently both tools have problems
- with using namespaces in PHP.</para>
- </footnote>, so syntax and documentation usage are chosen to work best
- with it.</para>
-
- <section>
- <title>Documentation blocks</title>
-
- <para>A file can contain different documentation blocks, relating to the
- file itself, the class in the file and finally the members of the class.
- A documentation block is always used for the entity it precedes.</para>
-
- <section>
- <title>File documentation</title>
-
- <para>The first documentation block in the file is essential for
- defining the package the file and it's contents belong to. Although it
- would not be strictly needed to have the file level documentation
- block (because each file contains only one class in FLOW3), we still
- use it because it</para>
-
- <itemizedlist>
- <listitem>
- <para>avoids warnings when rendering the documentation</para>
- </listitem>
-
- <listitem>
- <para>makes sure that even code outside of classes is assigned to
- the correct package and documented correctly</para>
- </listitem>
- </itemizedlist>
-
- <para>That means that each file must contain a documentation block
- like shown below, right below the header stating the license and
- before any
- <methodname>require</methodname>/<methodname>include</methodname>
- calls:</para>
-
- <example>
- <title>Standard file level documentation block</title>
-
- <programlisting language="php">/**
- * @package [packagename]
- * @subpackage [subpackage name if necessary]
- * @version $Id$
- */</programlisting>
- </example>
-
- <para>The package and version tag are mandatory, the subpackage tag is
- optional.</para>
-
- <important>
- <title>$Id$, Subversion and keyword expansion</title>
-
- <para>The $Id$ in the version tag will be expanded with information
- about the file version by Subversion. This so-called keyword
- expansion needs to be explicitly enabled, though! We recommend to
- put this into your <filename>~.subversion/config</filename>
- file:</para>
-
- <example>
- <title>Suggested configuration for Subversion in
- <filename>~/.subversion/config</filename></title>
-
- <para><literallayout>[miscellany]
-global-ignores = #*# *.rej *.orig *.bak *~ .*
-log-encoding = utf-8
-enable-auto-props = yes
-[auto-props]
-*.php = svn:keywords=Id Revision
-*.yaml = svn:keywords=Id Revision</literallayout></para>
- </example>
-
- <para>This does a little more than just enable the keyword
- expansion, it also sets the character encoding for the log messages
- and makes Subversion ignore some standard backup and metadata
- filenames.</para>
- </important>
- </section>
-
- <section>
- <title>Class documentation</title>
-
- <para>Classes have their own documentation block describing the
- classes purpose, assigning a package and subpackage. Very often the
- code within a class is expanded and modified by a number of authors.
- We therefore recommend to add the names of the developers to the
- method documentation. An exception should be the documentation for
- interfaces where you list all authors in the interface documentation.
- Exceptions itself never have an author annotation.</para>
-
- <example>
- <title>Standard class documentation block</title>
-
- <programlisting language="php">/**
- * First sentence is short description. Then you can write more, just as you like
- *
- * Here may follow some detailed description about what the class is for.
- *
- * Paragraphs are seperated by a empty line.
- *
- * @package [packagename]
- * @subpackage [subpackage name if necessary]
- * @version $Id$
- * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public ↩
- License, version 3 or later
- */
-class SomeClass {
- ...</programlisting>
- </example>
-
- <example>
- <title>Standard interface documentation block</title>
-
- <programlisting language="php">/**
- * First sentence is short description. Then you can write more, just as you like
- *
- * Here may follow some detailed description about what the interface is for.
- *
- * Paragraphs are seperated by a empty line.
- *
- * @package [packagename]
- * @subpackage [subpackage name if necessary]
- * @version $Id$
- * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public ↩
- License, version 3 or later
- */
-interface SomeInterface {
- ...</programlisting>
- </example>
-
- <example>
- <title>Standard exception documentation block</title>
-
- <programlisting language="php">/**
- * First sentence is short description. Then you can write more, just as you like
- *
- * Here may follow some detailed description about what the interface is for.
- *
- * Paragraphs are seperated by a empty line.
- *
- * @package [packagename]
- * @subpackage [subpackage name if necessary]
- * @version $Id$
- * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public ↩
- License, version 3 or later
- */
-class SomeException extends \Exception {
- ...</programlisting>
- </example>
-
- <para>Additional tags or annotations, such as @see or @aspect, can be
- added as needed.</para>
- </section>
-
- <section>
- <title>Documenting variables, constants, includes</title>
-
- <para>Properties of a class should be documented as well. We use the
- short version for documenting them:</para>
-
- <example>
- <title>Standard variable documentation block</title>
-
- <programlisting language="php">/**
- * A short description, very much recommended
- * @var string
- */
-protected $title = 'Untitled';</programlisting>
- </example>
- </section>
-
- <section>
- <title>Method documentation</title>
-
- <para>For a method, at least all parameters and the return value must
- be documented. Please also add your name by using the @author tag. The
- @access tag must not be used as it makes no sense (we're using PHP
- >= 5 for some reason, don't we?)</para>
-
- <example>
- <title>Standard method documentation block</title>
-
- <programlisting language="php">/**
- * A description for this method
- *
- * Paragraphs are seperated by a empty line.
- *
- * @param \F3\FLOW3\Log\LoggerInterface $logger A logger
- * @param string $someString This parameter should contain some string
- * @return void
- */
-public function __construct(\F3\FLOW3\Log\LoggerInterface $logger, $someString) {
- ...</programlisting>
- </example>
-
- <para>A special note about the @param tags: The parameter type and
- name are seperated by one space, not aligned. Do not put a colon after
- the parameter name. Always document the return type, even if it is
- void - that way it is clearly visible it hasn't just been
- forgotten.</para>
- </section>
- </section>
-
- <section>
- <title>Documentation tags</title>
-
- <para>There are quite a few documentation tags that can be used. Here is
- a list of tags that can and should be used within the TYPO3
- project:</para>
-
- <itemizedlist>
- <listitem>
- <para>@author</para>
- </listitem>
-
- <listitem>
- <para>@copyright</para>
- </listitem>
-
- <listitem>
- <para>@deprecated</para>
- </listitem>
-
- <listitem>
- <para>@example</para>
- </listitem>
-
- <listitem>
- <para>@filesource</para>
- </listitem>
-
- <listitem>
- <para>@global</para>
- </listitem>
-
- <listitem>
- <para>@ignore</para>
- </listitem>
-
- <listitem>
- <para>@internal</para>
- </listitem>
-
- <listitem>
- <para>@license</para>
- </listitem>
-
- <listitem>
- <para>@link</para>
- </listitem>
-
- <listitem>
- <para>@package</para>
- </listitem>
-
- <listitem>
- <para>@param</para>
- </listitem>
-
- <listitem>
- <para>@return</para>
- </listitem>
-
- <listitem>
- <para>@see</para>
- </listitem>
-
- <listitem>
- <para>@since</para>
- </listitem>
-
- <listitem>
- <para>@subpackage</para>
- </listitem>
-
- <listitem>
- <para>@todo</para>
- </listitem>
-
- <listitem>
- <para>@uses</para>
- </listitem>
-
- <listitem>
- <para>@var</para>
- </listitem>
-
- <listitem>
- <para>@version</para>
- </listitem>
- </itemizedlist>
-
- <para>Some are useless for PHP5 and PHP6, such as the tag for declaring
- a variable or method private:</para>
-
- <itemizedlist>
- <listitem>
- <para>@access</para>
- </listitem>
- </itemizedlist>
-
- <important>
- <para>If you are unsure about the meaning or ose of those tags, look
- them up in the phpDocumentor manual, rather than doing
- guesswork.</para>
- </important>
-
- <note>
- <para>There are more tags which are used in FLOW3, however their
- purpose is not documention but configuration. Currently annotations
- are also used for defining aspects and advices for the AOP framework
- as well as for giving instructions to the Persistence
- framework.</para>
- </note>
- </section>
- </section>
-
- <section>
- <title>Coding</title>
-
- <section>
- <title>Overview</title>
-
- <para>This section gives you an overview of FLOW3's coding rules and
- best practices.</para>
- </section>
-
- <section>
- <title>General PHP best practices</title>
-
- <itemizedlist>
- <listitem>
- <para>All code should be object oriented. This means there should be
- no functions outside classes if not absolutely necessary. If you
- need a "container" for some helper methods, consider creating a
- static class.</para>
- </listitem>
-
- <listitem>
- <para>All code must make use of PHP5 / PHP6 advanced features for
- object oriented programming.<itemizedlist>
- <listitem>
- <para>Use PHP namespaces (see <link
- xl:href="http://www.php.net/manual/language.namespaces.php">http://www.php.net/manual/language.namespaces.php</link>)</para>
- </listitem>
-
- <listitem>
- <para>Always declare the scope (public, protected, private) of
- methods and member variables</para>
- </listitem>
-
- <listitem>
- <para>Make use of iterators and exceptions, have a look at the
- SPL (see <link
- xl:href="http://www.php.net/manual/ref.spl.php">http://www.php.net/manual/ref.spl.php</link>
- and <link
- xl:href="http://www.php.net/~helly/php/ext/spl/">http://www.php.net/~helly/php/ext/spl/</link>)</para>
- </listitem>
-
- <listitem>
- <para>Make use of type-hinting wherever possible (see <link
- xl:href="http://www.php.net/manual/language.oop5.typehinting.php">http://www.php.net/manual/language.oop5.typehinting.php</link>)</para>
- </listitem>
- </itemizedlist></para>
- </listitem>
-
- <listitem>
- <para>Always use <code><?php</code> as opening tags (never only
- <code><?</code>)</para>
- </listitem>
-
- <listitem>
- <para>Add an encoding declaration as the first line of your PHP
- code, followed by the namespace declaration. For TYPO3 the encoding
- must be <acronym>UTF-8</acronym></para>
-
- <example>
- <title>Encoding statement for .php files</title>
-
- <programlisting language="php"><?php
-declare(ENCODING = 'utf-8');
-namespace F3\Your\Stuff\Here;
-
-...</programlisting>
- </example>
- </listitem>
-
- <listitem>
- <para>Prefer strict comparisons whenever possible, to avoid problems
- with truthy and falsy <sidebar>
- <figure>
- <title>Truthy and falsy are fuzzy...</title>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="AppendixCodingGuidelines_TrueFalse.jpg"/>
- </imageobject>
- </mediaobject>
- </figure>
- </sidebar>values that might behave different than what you expect.
- Here are some examples:<example>
- <title>Examples of good and bad comparisons</title>
-
- <para><programlisting language="php">if ($template) // BAD
-if (isset($template)) // GOOD
-if ($template !== NULL)) // GOOD
-if ($template !== '')) // GOOD
-
-if (strlen($template) > 0) // BAD! strlen("-1") is greater than 0
-if (is_string($template) && strlen($template) >0) // BETTER
-
-if ($foo == $bar) // BAD, avoid truthy comparisons
-if ($foo != $bar) // BAD, avoid falsy comparisons
-if ($foo === $bar)) // GOOD
-if ($foo !== $bar)) // GOOD</programlisting></para>
- </example></para>
- </listitem>
-
- <listitem>
- <para>Order of methods in classes. To gain a better overview, it
- helps if methods in classes are always ordered in a certain way. We
- prefer the following:<orderedlist>
- <listitem>
- <para>constructor</para>
- </listitem>
-
- <listitem>
- <para>injection methods</para>
- </listitem>
-
- <listitem>
- <para>initialization methods (including
- initializeObject())</para>
- </listitem>
-
- <listitem>
- <para>public methods</para>
- </listitem>
-
- <listitem>
- <para>protected methods</para>
- </listitem>
-
- <listitem>
- <para>private methods</para>
- </listitem>
-
- <listitem>
- <para>shutdown methods</para>
- </listitem>
-
- <listitem>
- <para>destructor</para>
- </listitem>
- </orderedlist></para>
- </listitem>
-
- <listitem>
- <para>Avoid double-negation. Instead of
- <literal>exportSystemView(..., $noRecurse)</literal> use
- <literal>exportSystemView(..., $recurse)</literal>. It is more
- logical to pass TRUE if you want recursion instead of having to pass
- FALSE. In general, parameters negating things are a bad idea.</para>
- </listitem>
- </itemizedlist>
-
- <section>
- <title>Comments</title>
-
- <para>In general, comments are a good thing and we strive for creating
- a well-documented source code. However, inline comments can often be a
- sign for a bad code structure or method naming.<footnote>
- <para>This is also referred to as a bad "smell" in the theory of
- Refactoring. We highly recommend reading "Refactoring" by Martin
- Fowler - if you didn't already.</para>
- </footnote>As an example, consider the following code:<example>
- <title>Bad coding smell: Comments</title>
-
- <programlisting language="php"> // We only allow valid persons:
-if (is_object($p) && strlen($p->lastN) > 0 && $p->hidden === FALSE && ↩
- $this->environment->moonPhase === MOON_LIB::CRESCENT) {
- $xmM = $thd;
-}</programlisting>
- </example></para>
-
- <para>This is a perfect case for the refactoring technique "extract
- method": In order to avoid the comment, create a new method which is
- as explanatory as the comment:</para>
-
- <example>
- <title>Smells better!</title>
-
- <programlisting language="php">if ($this->isValidPerson($person) {
- $xmM = $thd;
-}</programlisting>
- </example>
-
- <para>Bottom line is: You may (and are encouraged to) use inline
- comments if they support the readability of your code. But always be
- aware of possible design flaws you probably try to hide with
- them.</para>
- </section>
- </section>
-
- <section>
- <title>Error handling and exceptions</title>
-
- <para>FLOW3 makes use of a hierarchy for its exception classes. The
- general rule is to throw preferably specific exceptions and usually let
- them bubble up until a place where more general exceptions are catched.
- Consider the following example:</para>
-
- <para>Some method tried to retrieve an object from the object manager.
- However, instead of providing a string containing the object name, the
- method passed an object (of course not on purpose - something went
- wrong). The object manager now throws an
- <classname>InvalidObjectName</classname> exception. In order to catch
- this exception you can, of course, catch it specifically - or only
- consider a more general <classname>Object</classname> exception (or an
- even more general <classname>FLOW3</classname> exception). This all
- works because we have the following hierarchy:</para>
-
- <literallayout>+ \F3\FLOW3\Exception
- + Tx_Extbase_Object_Exception
- + Tx_Extbase_Object_Exception_InvalidObjectName</literallayout>
-
- <section>
- <title>Throwing an exception</title>
-
- <para>When throwing an exception, make sure to provide a clear error
- message and an error code being the unix timestamp of when you write
- the <function>throw</function> statement. That error code must be
- unique, so watch out when doing copy and paste!</para>
-
- <para>For every exception there should be a page on the TYPO3 wiki, as
- exception messages link to that page, identified by the error code
- (unix timestamp).</para>
- </section>
- </section>
-
- <section>
- <title>Cross platform issues</title>
-
- <para/>
- </section>
- </section>
-</appendix>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<book version="5.0" xmlns="http://docbook.org/ns/docbook"
- xmlns:xl="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xmlns:xhtml="http://www.w3.org/1999/xhtml"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns:ns="http://docbook.org/ns/docbook"
- xmlns:mathml="http://www.w3.org/1998/Math/MathML">
-
- <title>FLOW3 Framework</title>
-
- <!-- Meta information -->
-
- <info>
- <abstract>
- <para>FLOW3 is a modern application framework for enterprise-grade PHP
- applications. This reference describes FLOW3's main features.</para>
- </abstract>
-
- <author>
- <personname>
- <firstname>Robert</firstname>
-
- <surname>Lemke</surname>
- </personname>
-
- <email>robert@typo3.org</email>
- </author>
-
- <author>
- <personname>
- <firstname>Karsten</firstname>
-
- <surname>Dambekalns</surname>
- </personname>
-
- <email>karsten@typo3.org</email>
- </author>
-
- <copyright>
- <year>2007</year>
-
- <year>2008</year>
-
- <year>2009</year>
-
- <holder>Robert Lemke</holder>
-
- <holder>Karsten Dambekalns</holder>
- </copyright>
- </info>
-
- <!-- Chapters -->
-
- <xi:include href="Introduction.xml" />
-
- <xi:include href="MVCFramework.xml" />
-
- <xi:include href="PersistenceFramework.xml" />
-
- <!-- Appendixes -->
-
- <xi:include href="AppendixCodingGuidelines.xml" />
-
-</book>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter version="5.0" xmlns="http://docbook.org/ns/docbook"
- xmlns:ns6="http://www.w3.org/1999/xlink"
- xmlns:ns5="http://www.w3.org/2000/svg"
- xmlns:ns4="http://www.w3.org/1999/xhtml"
- xmlns:ns3="http://www.w3.org/1998/Math/MathML"
- xmlns:ns="http://docbook.org/ns/docbook">
- <title>Introduction</title>
-
- <para>FLOW3 is a PHP-based application framework. It is especially
- well-suited for enterprise-grade applications and explicitly supports
- Domain-Driven Design, a powerful software design philosophy. Convention over
- configuration, Test-Driven Development, Continuous Integration and an
- easy-to-read source code are other important principles we follow for the
- development of FLOW3.</para>
-
- <para>Although we created FLOW3 as the foundation for the TYPO3 Content
- Management System, its approach is general enough to be useful as a basis
- for any other PHP application. We're happy to share the FLOW3 framework with
- the whole PHP community and are looking forward to the hundreds of new
- features and enhancements contributed as packages by other enthusiastic
- developers. In fact most of the packages which will be developed for the
- TYPO3 CMS can be used in any other FLOW3-based application. In essence this
- reflects the vision of the TYPO3 project: "Inspiring People to
- Share".</para>
-
- <para>This reference describes all features of FLOW3 and provides you with
- in-depth information. If you'd like to get a feeling for FLOW3 and get
- started quickly, we suggest that you try out our Getting Started tutorial
- first.</para>
-
- <note>
- <para>Please note that FLOW3 is still under heavy development. Although we
- hope that the documentation is at least accurate and up to date, it is by
- no means complete and most likely not proof-read. If you find errors or
- would like to help us improving the documentation, we're happy to hear
- from you on our mailing list!</para>
- </note>
-
- <section>
- <title>Overview</title>
-
- <para>The FLOW3 framework is composed of the following submodules:</para>
-
- <itemizedlist>
- <listitem>
- <para>The <emphasis>FLOW3</emphasis> bootstrap takes care of
- configuring and initializing the whole framework.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Package</emphasis> Manager allows you to download,
- install, configure and uninstall packages.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Object</emphasis> Manager is in charge of
- building, caching and combining objects.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Configuration Framework</emphasis> reads and
- cascades various kinds of configuration from different sources and
- provides access to it.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Resource</emphasis> Manager contains functions for
- providing, caching, securing and retrieving resources.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>MVC</emphasis> Framework takes care of requests
- and responses and provides you with a powerful, easy-to use
- Model-View-Controller implementation.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Cache</emphasis> framework provides different
- kinds of caches with can be combined with a selection of cache
- backends.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Error</emphasis> module handles errors and
- exceptions and provides utility classes for this purpose.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Log</emphasis> module provides simple but powerful
- means to log any kind of event or signal into different types of
- backends.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Signal Slot</emphasis> module implements the
- event-driven concept of signals and slots through AOP aspects.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Validation</emphasis> module provides a validation
- and filtering framework with built-in rules as well as support for
- custom validation of any object.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Property</emphasis> module implements the concept
- of property editors and is used for setting and retrieving object
- properties.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Reflection</emphasis> API complements PHP's
- built-in reflection support by advanced annotation handling and a
- cached reflection service.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>AOP</emphasis> Framework enables you to use the
- powerful techniques of <firstterm>Aspect Oriented
- Programming</firstterm>.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Persistence</emphasis> module allows you to
- transparently persist your objects following principles of
- <emphasis>Domain Driven Design</emphasis>.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Security</emphasis> Framework enforces security
- policies and provides an API for managing those.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Session</emphasis> Framework takes care of session
- handling and storing session information in different backends</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Locale</emphasis> service manages languages and
- other regional settings and makes them accessible to other packages
- and FLOW3 sub packages.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>Utility</emphasis> module is a library of useful
- general-purpose functions for file handling, algorithms, environment
- abstraction and more.</para>
- </listitem>
- </itemizedlist>
-
- <para>If you are overwhelmed by the amount of information in this
- reference, just keep in mind that you don't need to know all of it to
- write your own FLOW3 packages. You can always come back and look up a
- specific topic once you need to know about it - that's what references are
- for. But even if you don't need to know everything, we recommend that you
- get familiar with the concepts of each module and read the whole manual.
- This way you make sure that you don't miss any of the great features FLOW3
- provides and hopefully feel inspired to produce clean and
- easy-maintainable code.</para>
-
- <tip>
- <para>A strong coffee helps most people over even the longest
- documentation.</para>
- </tip>
- </section>
-</chapter>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter version="5.0" xmlns="http://docbook.org/ns/docbook"
- xmlns:ns52="http://www.w3.org/1998/Math/MathML"
- xmlns:ns5="http://www.w3.org/1999/xlink"
- xmlns:ns4="http://www.w3.org/2000/svg"
- xmlns:ns3="http://www.w3.org/1999/xhtml"
- xmlns:ns="http://docbook.org/ns/docbook">
- <title>MVC Framework</title>
-
- <section>
- <title>Introduction</title>
-
- <section>
- <title>Model-View-Controller</title>
-
- <para>In the design of FLOW3's architecture we have taken great care to
- separate concerns and assign each part of the framework with
- well-defined tasks. The separation of concerns is an important principle
- of good software design and its most prominent representative probably
- is the Model-View-Controller pattern. MVC separates the business logic
- from the presentation by splitting up user interaction into three
- roles:</para>
-
- <itemizedlist>
- <listitem>
- <para>The <emphasis>model</emphasis> is an object which contains
- data and business logic of a certain domain. It doesn't contain any
- information about the presentation of that data, but rather defines
- the behaviour. In the FLOW3 project we prefer a special kind of
- model, the <link
- ns5:href="http://martinfowler.com/eaaCatalog/domainModel.html">Domain
- Model</link>.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>view</emphasis> represents the display of the
- model on the web or another output channel. Views only display data,
- they don't build or modify it.</para>
- </listitem>
-
- <listitem>
- <para>The <emphasis>controller</emphasis> reacts on user input,
- selects and manipulates the model as accordingly, selects a view and
- passes it the prepared model for rendering.</para>
- </listitem>
- </itemizedlist>
-
- <para>This diagram outlines the collaboration between model, view and
- controller:</para>
-
- <figure>
- <title>Model-View-Controller Pattern</title>
-
- <mediaobject>
- <imageobject>
- <imagedata contentdepth="100%"
- fileref="MVCFramework_ModelViewController.png"
- scalefit="1" width="100%"></imagedata>
- </imageobject>
- </mediaobject>
- </figure>
- </section>
-
- <section>
- <title>Other Patterns Used</title>
-
- <para>Design Patterns (and MVC is one of them) are not only great for
- solving reoccuring design problems in a structured manner - they also
- help you communicating software designs. The following patterns play an
- important role in FLOW3's MVC mechanism and might give you a better idea
- of the overall design:</para>
-
- <itemizedlist>
- <listitem>
- <para>Incoming requests are handled by a Request Handler which takes
- the role of a <link ns5:href="???">Front Controller</link>.</para>
- </listitem>
-
- <listitem>
- <para><link ns5:href="???">Template View</link> is the most commonly
- used pattern for views, but <link ns5:href="???">Transform
- Views</link> and <link ns5:href="???">Two-Step Views</link> are
- equally supported.</para>
- </listitem>
-
- <listitem>
- <para>The preferred type of model is the <link ns5:href="???">Domain
- Model</link>.</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Hello World!</title>
-
- <para>Let's start with an example before we go into greater detail of
- request handling and the internals of the MVC framework. The minimal
- approach is to create an Action Controller which just returns
- <quote>Hello World!</quote>. To begin with, we need to create some
- directories which contain the code of our FLOW3 package and eventually
- the controller class:</para>
-
- <literallayout>Packages/
- Demo/
- Classes/
- Controller/
- DefaultController.php</literallayout>
-
- <para>The DefaultController class looks as simple as this (leaving out
- the very recommended comments):</para>
-
- <example>
- <title>Hello World! controller</title>
-
- <programlisting language="PHP">namespace F3\Demo\Controller;
-
-class DefaultController extends \F3\FLOW3\MVC\Controller\ActionController {
- public function indexAction() {
- return "Hello World!";
- }
-}</programlisting>
- </example>
-
- <para>Provided that the document root of your local server points to
- FLOW3's <filename>Public/</filename> directory, you will get the
- following output when calling the URI
- <uri>http://localhost/demo/</uri>:</para>
-
- <screen>Hello World!</screen>
-
- <para>Great, that was easy - but didn't we say that it's the view's
- responsibility to take care of the presentation? Let's create a simple
- PHP-based view for that purpose:</para>
-
- <literallayout>Packages/
- Demo/
- Classes/
- Controller/
- DefaultController.php
- View/
- DefaultIndex.php</literallayout>
-
- <para>The view's code is equally trivial:</para>
-
- <example>
- <title>Hello World! view</title>
-
- <programlisting language="php">namespace F3\Demo\View;
-
-class DefaultIndex extends \F3\FLOW3\MVC\View\AbstractView {
- public function render() {
- return "Hello World!";
- }
-}</programlisting>
- </example>
-
- <para>Finally our action controller needs a little tweak to return the
- rendered view instead of shouting <quote>Hello World!</quote>
- itself:</para>
-
- <example>
- <title>Improved Hello World! controller</title>
-
- <programlisting language="php">namespace F3\Demo\Controller;
-
-class DefaultController extends \F3\FLOW3\MVC\Controller\ActionController {
- public function indexAction() {
- return $this->view->render();
- }
-}</programlisting>
- </example>
- </section>
-
- <section>
- <title>Recommended File Structure</title>
-
- <para>As you have seen in the hello world example, conventions for the
- directory layout simplify your development a lot. There's no need to
- register controllers, actions or views if you follow our recommended
- file structure. These are the rules:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>Controllers</emphasis> are located in their own
- directory <filename>Controller</filename> just below the
- <filename>Classes</filename> directory of your package. They can
- have arbitrary names while the
- <classname>DefaultController</classname> has a special meaning: If
- the package was specified in the request but no controller, the
- <classname>DefaultController</classname> will be used.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>View</emphasis> classes are situated below a
- <filename>View</filename> directory. The classname of the view is a
- combination of the name of the controller and the name of the
- action.</para>
- </listitem>
- </itemizedlist>
-
- <para>This sample directory layout demonstrates the above rules:</para>
-
- <example>
- <title>Sample file structure</title>
-
- <literallayout>Packages/
- Demo/
- Classes/
- Controller/
- DefaultController.php
- CustomerController.php
- OrderController.php
- View/
- DefaultIndex.php
- CustomerIndex.php
- CustomerList.php
- CustomerDetails.php
- OrderList.php</literallayout>
- </example>
-
- <para>Adhering to these conventions has the advantage that the classname
- of the view for example is resolved automatically. However it is
- possible (and not really difficult) to deviate from this layout and have
- a completely different structure.</para>
- </section>
-
- <section>
- <title>From the URI to the view</title>
-
- <caution>
- <para>For the example URIs we assume that the web root directory of
- your local server points to FLOW3's <filename>public/</filename>
- directory. If that's not the case you have to extend the URI
- accordingly.</para>
- </caution>
-
- <para>FLOW3 provides a standard way of resolving the URI to your
- MVC-Objects.</para>
-
- <para>Say, you want to see the list of customers (based on the
- file-structure-example above). The URI to get the list would be:
- <uri>http://localhost/demo/customer/list.html</uri> or just
- <uri>http://localhost/demo/customer/list</uri>.</para>
-
- <para>This URI will be resolved into the package-name
- (<emphasis>Demo</emphasis>), controller-name
- (<emphasis>Customer</emphasis>), action-name(<emphasis>list</emphasis>)
- and format-name (<emphasis>html</emphasis> - which is the default
- format).</para>
-
- <para>Depending on that, the controller
- <classname>\F3\Demo\Controller\CustomerController</classname> (Pattern:
- '<code>F3\@package\Controller\@controllerController'</code>) and its
- method <methodname>listAction()</methodname> will be used. The
- corresponding view is <classname>\F3\Demo\View\CustomerList</classname>
- (Pattern:
- <code>'F3\@package\View\@controller@action@format'</code>).</para>
-
- <para>If you have a look at the view pattern, you see, that you can
- easily add a view that creates an xml-output by creating the class
- <classname>\F3\Demo\View\CustomerListXML</classname>. You will get the
- xml-output by calling the URI
- <uri>http://localhost/demo/customer/list.xml</uri>.</para>
- </section>
- </section>
-
- <section>
- <title>Request and Response</title>
-
- <para>No matter if a FLOW3 application runs in a web context or is
- launched from the command line, the basic workflow is always the same: The
- user request is analyzed and forwarded to an appropriate controller which
- decides on which actions to take and finally returns a response which is
- handed over to the user. This section highlights the flow and the
- collaborators in the request-response machinery.</para>
-
- <section>
- <title>Request Processing Overview</title>
-
- <para>A sequence diagram is worth a thousand words said my grandma, so
- let's take a look at the standard request-response workflow in
- FLOW3:</para>
-
- <figure>
- <title>Example of a Web Request-Response Workflow</title>
-
- <mediaobject>
- <imageobject>
- <imagedata contentdepth="100%"
- fileref="MVCFramework_RequestResponseWorkflow.png"
- scalefit="1" width="100%"></imagedata>
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>As you see, there are a lot of parts of the framework involved for
- answering a request - and the diagram doesn't even consider caching or
- forwarding of requests. But we didn't create this structure just for the
- fun of it - each object plays an important role as you'll see in the
- next sections.</para>
- </section>
-
- <section>
- <title>Request Handler</title>
-
- <para>The request handler takes the important task to handle and respond
- to a request. There exists exactly one request handler for each request
- type. By default web and command line requests are supported, but more
- specialized request handlers can be developed, too.</para>
-
- <para>Before one of the request handlers comes to play, the framework
- needs to determine which of them is the most suitable for the current
- request. The request handler resolver asks all of the registered request
- handlers to rate on a scale how well they can handle the current raw
- request. The resolver then chooses the request handler with the most
- points and passes over the control.</para>
-
- <para>Custom request handlers for special purposes just need to
- implement the
- <interfacename>\F3\FLOW3\MVC\RequestHandlerInterface</interfacename>.
- All classes implementing that interface are automatically registered and
- will be considered while resolving a suitable request handler.</para>
- </section>
-
- <section>
- <title>Request Builder</title>
-
- <para>When a request handler receives a raw request, it needs to build a
- request object which can be passed to the dispatcher and later to the
- controller. The request building delegated to a request builder which
- can build the required request type (ie. web, CLI etc.).</para>
-
- <para>The building process mainly consists of</para>
-
- <procedure>
- <step>
- <para>create a new request object</para>
- </step>
-
- <step>
- <para>set some request-type specific parameters (like the request
- URI for a web request)</para>
- </step>
-
- <step>
- <para>determine and set the responsible controller, action and
- action arguments</para>
- </step>
- </procedure>
-
- <para>Especially the last step is important and requires some more or
- less complex routing in case of web requests.</para>
- </section>
-
- <section>
- <title>Request Processors</title>
-
- <para>Requests which were built by the request builder usually fit the
- most common needs. For special demands it is possible to postprocess the
- request object before it is sent to the dispatcher. Request processors
- can be registered through the Request Processor Chain Manager and are -
- as the name suggests - invoked in a chain.</para>
- </section>
-
- <section>
- <title>Request Dispatcher</title>
-
- <para>The final task of the MVC framework consists in dispatching the
- request to the controller specified in the request object. The request
- dispatcher will try to call the action specified in the request object
- and if none was specified fall back on a default action.</para>
-
- <note>
- <para>There are more features planned for the dispatcher, but at the
- time of this writing they have not yet been implemented.</para>
- </note>
- </section>
-
- <section>
- <title>Request Types</title>
-
- <para>FLOW3 supports the most important request types out of the box.
- Additional request types can easily be implemented by extending the
- <classname>\F3\FLOW3\MVC\Request</classname> class and registering a
- request handling which can handle the new request type (and takes care
- of building the request object). Here are the request types which come
- with the default FLOW3 distribution:</para>
-
- <section>
- <title>Web Request / Response</title>
-
- <para>Web requests are the most common request types. Currently only
- the basic features are implemented, but further options - especially
- for the web response - are in the pipeline.</para>
- </section>
-
- <section>
- <title>CLI Request / Response</title>
-
- <para>Requests from the command line are recognized by the used SAPI
- (Server Application Programming Interface). This request type is
- basically the same as the generic request type and mainly exists as a
- marker.</para>
- </section>
-
- <section>
- <title>AJAX Request / Response</title>
-
- <note>
- <para>This request type has not yet been implemented</para>
- </note>
- </section>
- </section>
- </section>
-
- <section>
- <title>Controller</title>
-
- <para></para>
-
- <section>
- <title>Action Controller</title>
-
- <para>Setting $this->viewObjectName to a view object name overrides
- the automatic resolving of the view name. Can be used for definining a
- standard view, for example \F3\Fluid\View\TemplateView.</para>
-
- <para></para>
-
- <section>
- <title>Initialization Methods</title>
-
- <para>initializeController</para>
-
- <para>initializeAction</para>
-
- <para>initializeView</para>
- </section>
-
- <section>
- <title>Configuration</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Supported Request Types</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Arguments</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Action Methods</title>
-
- <para>$this->indexActionMethodName</para>
-
- <para></para>
- </section>
-
- <section>
- <title>Action View</title>
-
- <para>- $this->initializeView = TRUE | FALSE</para>
- </section>
- </section>
-
- <section>
- <title>Other Controllers</title>
-
- <section>
- <title>Abstract Controller</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Request Handling Controller</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Default Controller</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Not Found Controller</title>
-
- <para>The
- <classname>F3\FLOW3\MVC\Controller\NotFoundController</classname> is
- used whenever no other controller could be resolved which would match
- the current request. It displays a generic "404 Page Not Found"
- message.</para>
-
- <para>It is possible to define your own custom controller which is
- used in these cases. Just specify the object name in the FLOW3
- settings.</para>
- </section>
- </section>
- </section>
-
- <section>
- <title>View</title>
-
- <para></para>
-
- <section>
- <title>Template View</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Special Views</title>
-
- <section>
- <title>Default View</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Empty View</title>
-
- <para></para>
- </section>
- </section>
- </section>
-
- <section>
- <title>Helpers</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Model</title>
-
- <para></para>
- </section>
-
- <section>
- <title>Routing</title>
-
- <para></para>
- </section>
-
- <section>
- <title>CLI request handling</title>
-
- <para>FLOW3's CLI request handling offers a comfortable and flexible way
- of calling code from the command line:</para>
-
- <para><command>php index.php [<replaceable>command</replaceable>]
- [<replaceable>options</replaceable>] [--]
- [<replaceable>arguments</replaceable>]</command></para>
-
- <para><replaceable>command</replaceable>,
- <replaceable>options</replaceable> and
- <replaceable>arguments</replaceable> are optional, with varying results.
- The command structure follows what is commonly accpeted on unixoid systems
- for CLI programs:<variablelist>
- <varlistentry>
- <term>command</term>
-
- <listitem>
- <para>If not given, the default controller of the FLOW3 package is
- used and it's index action is called. While this is an allowed
- call, it hardly makes sense (other than checking if FLOW basically
- works). If command is given then it is defined as
- <emphasis><replaceable>package</replaceable>
- [[<replaceable>sub1..N</replaceable>]
- <replaceable>controller</replaceable>
- <replaceable>action</replaceable>]</emphasis></para>
-
- <para>First part is always the package. If only the package is
- given, it's default controller's index action is called.</para>
-
- <para>If at least three command parts are given, the last two
- sepcify controller and action. Anything in between specifys a sub
- package structure.<example>
- <title>Some FLOW3 CLI command specifications</title>
-
- <para><literal>testing cli run</literal> would call the "run"
- action of the "cli" controller in the "Testing" package</para>
-
- <para><literal>typo3cr admin setup default</literal> would
- call the "setup" controller's "default" action in the
- subpackage "admin" of the package "TYPO3CR"</para>
- </example></para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>options</term>
-
- <listitem>
- <para>Options are either short- or long-style. The first option
- detected ends collecting command parts. Here are some
- examples:<example>
- <title>Giving options to FLOW3 CLI requests</title>
-
- <para><literal>-o -f=value --a-long-option --with-spaces="is
- possible" --input file1 -o=file2 --event-this =
- works</literal></para>
- </example></para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term>arguments</term>
-
- <listitem>
- <para>Arguments can follow and will be available to the called
- controller in the request object. To distinguish between
- <replaceable>command</replaceable> and
- <replaceable>arguments</replaceable> in cases where no
- <replaceable>options</replaceable> are given the seperator
- <literal>--</literal> must be used.</para>
- </listitem>
- </varlistentry>
- </variablelist></para>
-
- <example>
- <title>Some FLOW3 CLI commands</title>
-
- <para>Calling the TYPO3CR setup:</para>
-
- <para><code>php index.php typo3cr admin setup setup
- --dsn=sqlite:/tmp/typo3cr.db --indexlocation=/tmp/lucene/</code></para>
-
- <para>Running FLOW3 unit tests:</para>
-
- <para><code>php index.php testing cli run --package-key=FLOW3
- --output-directory=./</code></para>
-
- <para>Rendering the FLOW3 documentation to HTML:</para>
-
- <para><code>php index.php doctools render render -p FLOW3 -o
- flow3-manual/</code></para>
- </example>
- </section>
-</chapter>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter version="5.0" xmlns="http://docbook.org/ns/docbook"
- xmlns:xl="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude"
- xmlns:xhtml="http://www.w3.org/1999/xhtml"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns:ns="http://docbook.org/ns/docbook"
- xmlns:mathml="http://www.w3.org/1998/Math/MathML">
- <title>Persistence Framework</title>
-
- <section>
- <title>Introductory Example</title>
-
- <para>Let's look at the following example as an introduction to how FLOW3
- handles persistence. We have a domain model of a Blog, consisting of Blog,
- Post, Comment and Tag objects:<figure>
- <title>The objects of the Blog domain model</title>
-
- <mediaobject>
- <imageobject>
- <imagedata contentdepth="100%"
- fileref="PersistenceFramework_BlogDomainModel.png"
- scalefit="1" width="100%"></imagedata>
- </imageobject>
- </mediaobject>
- </figure></para>
-
- <para>Connections between those objects are built by simple references in
- PHP, as a look at the <methodname>addPost()</methodname> method of the
- <classname>Blog</classname> class shows:<example>
- <title>The Blog's addPost() method</title>
-
- <para><programlisting language="php">/**
- * @param \F3\Blog\Domain\Post $post
- * @return void
- */
-public function addPost(\F3\Blog\Domain\Post $post) {
- $this->posts[$post->getIdentifier()] = $post;
-}</programlisting></para>
- </example></para>
-
- <para>The same principles are applied to the rest of the classes,
- resulting in an object tree of a blog object holding several posts, those
- in turn having references to their associated comments and tags. But now
- we need to make sure the Blog and the data in it are still available the
- next time we need them. In the good old days of programming you might have
- added some ugly database calls all over the system at this point. In the
- currently widespread practice of loving Active Record you'd still add
- save() methods to all or most of your objects. But can it be even
- easier?</para>
-
- <para>To access an object you need to hold some reference to it. You can
- get that reference by creating an object or by following some reference to
- it from some object you already have. This leaves you at a point where you
- need to find that "first object". This is done by using a Repository. A
- Repository is the librarian of your system, knowing about all the objects
- it manages. In our model the Blog is the entry point to our object tree,
- so we will add a BlogRepository, allowing us to find Blogs by the criteria
- we need.</para>
-
- <para>Now, before we can find a Blog, we need to create and save one. What
- we do is create the object (using FLOW3's object factory) and add it to
- the BlogRepository. This will automagically persist your Blog and you can
- retrieve it again later. No save() call needed. Oh, and the posts,
- comments and tags in your Blog are persisted as well, of course.</para>
-
- <para>For all that magic to work as expected, you need to give some hints.
- This doesn't mean you need to write tons of XML, a few annotations in your
- code are enough:<example>
- <title>Persistence-related annotations in the Blog class</title>
-
- <para><programlisting language="php">/**
- * A Blog object
- *
- * @package Blog
- * @entity
- */
-class Blog {
-
- /**
- * @var string
- */
- protected $title;
-
- /**
- * @var array
- */
- protected $posts = array();
-
- ...
-
-}</programlisting></para>
- </example>The first annotation to note is the
- <emphasis>@entity</emphasis> annotation, which tells the persistence
- framework it needs to persist Blog instances if they have been added to a
- Repository. In the Blog class we have some member variables, they are
- persisted as well by default. The persistence framework knows their types
- by looking at the <emphasis>@var</emphasis> annotation you use anyway when
- documenting your code (you do document your code, right?). In case of the
- $posts array the persistence framework persists the objects held in that
- array as independent objects. Apart from those annotations your domain
- object's code is completely unaware of the persistence
- infrastructure.</para>
-
- <para>Let's conclude by taking a look at the BlogRepository code:<example>
- <title>Code of a simple BlogRepository</title>
-
- <programlisting language="php">/**
- * A BlogRepository
- *
- * @package Blog
- */
-class BlogRepository extends Tx_Extbase_Persistence_Repository {
-
- /**
- * Finds Blogs with a matching name.
- *
- * @param string $name
- * @return array
- */
- public function findByName($name) {
- $query = $this->createQuery();
- return $query->matching($query->equals('name', $name))->execute();
- }
-}</programlisting>
- </example>As you can see we get away with very little code by simply
- extending the FLOW3-provided repository class. Nice, eh? If you like to do
- things the hard way you can get away with implementing
- <interfacename>Tx_Extbase_Persistence_RepositoryInterface</interfacename>
- yourself.</para>
- </section>
-
- <section>
- <title>On the priciples of DDD</title>
-
- <para>From Evans, the rules we need to enforce include:</para>
-
- <itemizedlist>
- <listitem>
- <para>The root Entity has global identity and is ultimately
- responsible for checking invariants.</para>
- </listitem>
-
- <listitem>
- <para>Root Entities have global identity. Entities inside the boundary
- have local identity, unique only within the Aggregate.</para>
- </listitem>
-
- <listitem>
- <para>Nothing outside the Aggregate boundary can hold a reference to
- anything inside, except to the root Entity. The root Entity can hand
- references to the internal Entities to other objects, but they can
- only use them transiently (within a single method or block).</para>
- </listitem>
-
- <listitem>
- <para>Only Aggregate Roots can be obtained directly with database
- queries. Everything else must be done through traversal.</para>
- </listitem>
-
- <listitem>
- <para>Objects within the Aggregate can hold references to other
- Aggregate roots.</para>
- </listitem>
-
- <listitem>
- <para>A delete operation must remove everything within the Aggregate
- boundary all at once.</para>
- </listitem>
-
- <listitem>
- <para>When a change to any object within the Aggregate boundary is
- committed, all invariants of the whole Aggregate must be
- satisfied.</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Persistence-related annotations</title>
-
- <para>The following table lists all annotations used by the persistence
- framework with their name, scope and meaning:<table>
- <title>Persistence-related code annotations</title>
-
- <tgroup cols="3">
- <colspec colwidth="1*" />
-
- <colspec colwidth="1*" />
-
- <colspec colwidth="4*" />
-
- <thead>
- <row>
- <entry>Annotation</entry>
-
- <entry>Scope</entry>
-
- <entry>Meaning</entry>
- </row>
- </thead>
-
- <tbody>
- <row>
- <entry>@entity</entry>
-
- <entry>Class</entry>
-
- <entry>Declares a class as an Entity.</entry>
- </row>
-
- <row>
- <entry>@valueobject</entry>
-
- <entry>Class</entry>
-
- <entry>Declares a class as a Value Object, allowing the
- persistence framework to reuse an existing object if one
- exists.</entry>
- </row>
-
- <row>
- <entry>@var</entry>
-
- <entry>Variable</entry>
-
- <entry>Is used to detect the type a variable has.</entry>
- </row>
-
- <row>
- <entry>@transient</entry>
-
- <entry>Variable</entry>
-
- <entry>Makes the persistence framework ignore the variable.
- Neither will it's value be persisted, nor will it be touched
- during reconstitution.</entry>
- </row>
-
- <row>
- <entry>@uuid</entry>
-
- <entry>Variable</entry>
-
- <entry>Marks the variable as being the object uuid. This makes
- the persistence backend use the value of this variable as
- identifier for the internal representation of the object.
- <emphasis>You must make sure your identifier is an
- UUID.</emphasis></entry>
- </row>
-
- <row>
- <entry>@identity</entry>
-
- <entry>Variable</entry>
-
- <entry>Marks the variable as being relevant for determining the
- identity of an object in the domain.</entry>
- </row>
- </tbody>
- </tgroup>
- </table></para>
- </section>
-
- <section>
- <title>Inside the Persistence Framework</title>
-
- <para>To the domain code the persistence handling transparent, aside from
- the need to add a few annotations. The custom repositories are a little
- closer to the inner workings of the framework, but still the inner
- workings are very invisible. This is how it is supposed to be, but a
- little understanding of how persistence works internally can help
- understand problems and develop more efficient client code.</para>
-
- <section>
- <title>Persisting a domain object</title>
-
- <para>After an object has been added to a repository it will be seen
- when FLOW3 calls <methodname>persistAll()</methodname> at the end of a
- script run. Internally all instances implementing the
- <interfacename>Tx_Extbase_Persistence_RepositoryInterface</interfacename>
- will be fetched and asked for the objects they hold. Those will then be
- handed to the persistence backend in use and processed by it.</para>
-
- <para>FLOW3 defines interfaces for persistence backends and queries, the
- details of how objects are persisted and queried are up to the
- persistence backend implementation. Have a look at the documentatoin of
- the respective package for more information. The following diagram shows
- (most of) the way an object takes from creation until it is persisted
- when using the TYPO3 Content Repository:</para>
-
- <para><figure>
- <title>Object persistence process</title>
-
- <mediaobject>
- <imageobject>
- <imagedata contentdepth="100%"
- fileref="PersistenceFramework_PersistenceProcess.png"
- scalefit="1" width="100%"></imagedata>
- </imageobject>
- </mediaobject>
- </figure>Keep in mind that the diagram omits some details like dirty
- checking on objects and how exactly objects and their properties are
- stored in the Content Repository.</para>
- </section>
-
- <section>
- <title>Querying the storage backend</title>
-
- <para>As we saw in the introductory example there is a query mechanism
- available that provides easy fetching of objects through the persistence
- framework. You ask for instances of a specific class that match certain
- filters and get back an array of those reconstituted objects. Here is a
- diagram of the internal process when using the TYPO3 Content Repository
- as persistence backend:<figure>
- <title>Object querying and reconstitution process</title>
-
- <mediaobject>
- <imageobject>
- <imagedata contentdepth="100%"
- fileref="PersistenceFramework_QueryProcess.png"
- scalefit="1" width="100%"></imagedata>
- </imageobject>
- </mediaobject>
- </figure>For the developer the complexity is hidden between the
- query's <methodname>execute()</methodname> method and the array of
- objects being returned. The <classname>QOMFactory</classname>, "right"
- <classname>Query</classname> and <classname>QueryResult</classname>
- objects are part of the standard JSR-283 API, whereas
- <classname>QueryFactory</classname>, "left" <classname>Query</classname>
- and <classname>DataMapper</classname> are part of the FLOW3 persistence
- backend implementation that comes with the TYPO3 Content
- Repository.</para>
- </section>
- </section>
-</chapter>