diff options
Diffstat (limited to 'demos/quickstart/protected/pages/Fundamentals')
7 files changed, 409 insertions, 365 deletions
diff --git a/demos/quickstart/protected/pages/Fundamentals/Applications.page b/demos/quickstart/protected/pages/Fundamentals/Applications.page index 8e0b9e9a..71901170 100755 --- a/demos/quickstart/protected/pages/Fundamentals/Applications.page +++ b/demos/quickstart/protected/pages/Fundamentals/Applications.page @@ -7,7 +7,11 @@ An application is an instance of <tt>TApplication</tt> or its derived class. It <p id="160158" class="block-content">
Applications are configured via <a href="?page=Configurations.AppConfig">application configurations</a>. They are usually created in entry scripts like the following,
<com:TTextHighlighter CssClass="source block-content" id="code_160071">
+// load the prado entry script
require_once('/path/to/prado.php');
+// or, if using composer:
+require_once('vendor/autoload.php');
+
$application = new TApplication;
$application->run();
</com:TTextHighlighter>
diff --git a/demos/quickstart/protected/pages/Fundamentals/Architecture.page b/demos/quickstart/protected/pages/Fundamentals/Architecture.page index 10f16c3f..c6bee7de 100755 --- a/demos/quickstart/protected/pages/Fundamentals/Architecture.page +++ b/demos/quickstart/protected/pages/Fundamentals/Architecture.page @@ -2,12 +2,31 @@ <h1 id="601">Architecture</h1>
<p id="100111" class="block-content">
-PRADO is primarily a presentational framework, although it is not limited to be so. The framework focuses on making Web programming, which deals most of the time with user interactions, to be component-based and event-driven so that developers can be more productive. The following class tree depicts some of the major classes provided by PRADO,
+PRADO is primarily a presentational framework, although it is not limited to be so. The framework focuses on making Web programming, which deals most of the time with user interactions, to be component-based and event-driven so that developers can be more productive. The following class tree depicts some of the major classes provided by PRADO:
</p>
<img src="<%~classtree.gif%>" />
<p id="100112" class="block-content">
-When a PRADO application is processing a page request, its static object diagram can be shown as follows,
+When a PRADO application is processing a page request, its static object diagram can be shown as follows:
</p>
<img src="<%~objectdiagram.gif%>" />
-</com:TContent>
+
+<p class="block-content">
+Once the main <tt>Application</tt> object gets created, it load the <a href="?page=Configurations.AppConfig">application configuration</a>.
+The minimal configuration defines a set of basic <a href="?page=Fundamentals.Modules">modules</a> to parse the <tt>Request</tt>, create a proper <tt>Response</tt>, mantain the user <tt>Session</tt>, handle any <tt>Error</tt> and publish the needed <tt>Assets</tt> (images, css, javascript, etc). These helpers module will be available from anywhere inside the application code.
+<br/>
+Additionally, any 3rd-party or <tt>custom module</tt> can be loaded, and external <tt>Parameters</tt> can be loaded from external configurations.
+</p>
+
+<p class="block-content">
+Once the basic infrastructure has been set up, the <tt>Request</tt> module parses the request trying to identify the requested route. Different routes can be handled by different services, but the default route for http requests is the <tt>Page Service</tt>.
+<br/>
+The <a href="?page=Configurations.AppConfig">Page Service</a>'s role is to instanciate the requested <tt>Page</tt>, run it, apply any defined <tt>Theme</tt> and grab the result in order to build the <tt>Response</tt>.
+</p>
+
+<p class="block-content">
+A <a href="?page=Fundamentals.Pages">Page</a> can be a simple script (.php), a <tt>Template</tt> (.page), or both. PRADO uses a very powerful <a href="?page=Configurations.Templates1">template engine</a> where <tt>Controls</tt> can be instanciated directly.
+<br/>
+A <a href="?page=Fundamentals.Controls">Control</a> is an self-contained widget that fullfills a specific task; they can be a simple script (.php), a <tt>Template</tt> (.page), or both.
+</p>
+</com:TContent>
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/Fundamentals/Components.page b/demos/quickstart/protected/pages/Fundamentals/Components.page deleted file mode 100755 index 11235b56..00000000 --- a/demos/quickstart/protected/pages/Fundamentals/Components.page +++ /dev/null @@ -1,360 +0,0 @@ -<com:TContent ID="body" >
-<h1 id="701">Components</h1>
-<p id="110113" class="block-content">
-A component is an instance of <tt>TComponent</tt> or its child class. The base class <tt>TComponent</tt> implements the mechanism of component properties and events.
-</p>
-
-<h2 id="702">Component Properties</h2>
-<p id="110114" class="block-content">
-A component property can be viewed as a public variable describing a specific aspect of the component, such as the background color, the font size, etc. A property is defined by the existence of a getter and/or a setter method in the component class. For example, in <tt>TControl</tt>, we define its <tt>ID</tt> property using the following getter and setter methods,
-<com:TTextHighlighter CssClass="source block-content" id="code_110056">
-class TControl extends TComponent {
- public function getID() {
- ...
- }
- public function setID($value) {
- ...
- }
-}
-</com:TTextHighlighter>
-</p>
-<p id="110115" class="block-content">
-To get or set the <tt>ID</tt> property, do as follows, just like working with a variable,
-<com:TTextHighlighter CssClass="source block-content" id="code_110057">
-$id = $component->ID;
-$component->ID = $id;
-</com:TTextHighlighter>
-This is equivalent to the following,
-<com:TTextHighlighter CssClass="source block-content" id="code_110058">
-$id = $component->getID();
-$component->setID( $id );
-</com:TTextHighlighter>
-</p>
-<p id="110116" class="block-content">
-A property is read-only if it has a getter method but no setter method. Since PHP method names are case-insensitive, property names are also case-insensitive. A component class inherits all its ancestor classes' properties.
-</p>
-
-<h3 id="706">Subproperties</h3>
-<p id="110117" class="block-content">
-A subproperty is a property of some object-typed property. For example, <tt>TWebControl</tt> has a <tt>Font</tt> property which is of <tt>TFont</tt> type. Then the <tt>Name</tt> property of <tt>Font</tt> is referred to as a subproperty (with respect to <tt>TWebControl</tt>).
-</p>
-<p id="110118" class="block-content">
-To get or set the <tt>Name</tt> subproperty, use the following method,
-<com:TTextHighlighter CssClass="source block-content" id="code_110059">
-$name = $component->getSubProperty('Font.Name');
-$component->setSubProperty('Font.Name', $name);
-</com:TTextHighlighter>
-This is equivalent to the following,
-<com:TTextHighlighter CssClass="source block-content" id="code_110060">
-$name = $component->getFont()->getName();
-$component->getFont()->setName( $name );
-</com:TTextHighlighter>
-</p>
-
-<h3 id="26001">Js-friendly properties</h3>
-<p class="block-content">
-A JavaScript-friendly property is a property that can accept both simple strings and raw javascript.
-Prado automatically encodes all properties sent clientside inside javascript blocks to avoid security problems (like injections or cross site scripting).
-If a property is known to always contain only safe javascript code and its value needs to bypass this encoding, that property can be defined in a special way that will make Prado mark its value as "safe".
-Js-friendly properties are identified by their name starting with 'js' (case insensitive):
-<com:TTextHighlighter CssClass="source block-content">
-// getter, defines a readable property 'Text'
-function getJsText() { … }
-// setter, defines a writable property 'Text', with $value being the value to be set to the property
-function setJsText(TJavaScriptLiteral $value) { … }
-</com:TTextHighlighter>
-Js-friendly properties can be accessed using both their Js-less name and their Js-enabled name:
-<com:TTextHighlighter CssClass="source block-content">
-// set some simple text as property value
-$component->Text = 'text';
-// set some javascript code as property value
-$component->JsText = 'raw javascript';
-</com:TTextHighlighter>
-In the first case, the property value will automatically gets encoded when sent clientside inside a javascript block.
-In the second case, the property will be 'marked' as being a safe javascript statement and will not be encoded when rendered inside a javascript block.
-This special handling makes use of the <tt>TJavaScriptLiteral</tt> class.
-</p>
-
-
-<h2 id="703">Component Events</h2>
-<p id="110119" class="block-content">
-Component events are special properties that take method names as their values. Attaching (setting) a method to an event will hook up the method to the places at which the event is raised. Therefore, the behavior of a component can be modified in a way that may not be foreseen during the development of the component.
-</p>
-<p id="110120" class="block-content">
-A component event is defined by the existence of a method whose name starts with the word <tt>on</tt>. The event name is the method name and is thus case-insensitve. For example, in <tt>TButton</tt>, we have
-<com:TTextHighlighter CssClass="source block-content" id="code_110061">
-class TButton extends TWebControl {
- public function onClick( $param ) {
- ...
- }
-}
-</com:TTextHighlighter>
-This defines an event named <tt>OnClick</tt>, and a handler can be attached to the event using one of the following ways,
-<com:TTextHighlighter CssClass="source block-content" id="code_110062">
-$button->OnClick = $callback;
-$button->OnClick->add( $callback );
-$button->OnClick[] = $callback;
-$button->attachEventHandler( 'OnClick' , $callback );
-</com:TTextHighlighter>
-</p>
- The variable <tt>$callback</tt> contains the definition of the event handler that can be either a string referring to a global function name, or an array whose first element refers to an object and second element a method name/path that is reachable by the object, e.g.
- </p>
-<ul>
-<li>'buttonClicked' : buttonClicked($sender,$param);</li>
-<li>array($object,'buttonClicked') : $object->buttonClicked($sender,$param);</li>
-<li>array($object,'MainContent.SubmitButton.buttonClicked') : $object->MainContent->SubmitButton->buttonClicked($sender,$param);</li>
-</ul>
-<com:SinceVersion Version="3.2.3" />
-<h2 id="26001">Global events</h2>
-<p id="130001" class="block-content">
-With the addition of behaviors, a more expansive event model is needed. There
-are two new event types (global and dynamic events) as well as a more comprehensive
-behavior model that includes class wide behaviors.
-</p>
-<p id="130002" class="block-content">
-A global event is defined by all events whose name starts with 'fx'.
-The event name is potentially a method name and is thus case-insensitive. All 'fx' events
-are valid as the whole 'fx' event/method space is global in nature. Any object may patch into
-any global event by defining that event as a method. Global events have priorities
-just like 'on' events; so as to be able to order the event execution. Due to the
-nature of all events which start with 'fx' being valid, in effect, every object
-has every 'fx' global event. It is simply an issue of tapping into the desired
-global event.
-</p>
-<p id="130003" class="block-content">
-A global event that starts with 'fx' can be called even if the object does not
-implement the method of the global event. A call to a non-existing 'fx' method
-will, at minimal, function and return null. If a method argument list has a first
-parameter, it will be returned instead of null. This allows filtering and chaining.
-'fx' methods do not automatically install and uninstall. To install and uninstall an
-object's global event listeners, call the object's <tt>listen</tt> and
-<tt>unlisten</tt> methods, respectively. An object may auto-install its global event
-during <tt>__construct</tt> by overriding <tt>getAutoGlobalListen</tt> and returning true.
-</p>
-<p id="130004" class="block-content">
-As of PHP version 5.3, nulled objects without code references will still continue to persist
-in the global event queue because <tt>__destruct</tt> is not automatically called. In the common
-__destruct method, if an object is listening to global events, then <tt>unlisten</tt> is called.
-<tt>unlisten</tt> is required to be manually called before an object is
-left without references if it is currently listening to any global events. This includes
-class wide behaviors.
-</p>
-<p id="130005" class="block-content">
-An object that contains a method that starts with 'fx' will have those functions
-automatically receive those events of the same name after <tt>listen</tt> is called on the object.
-</p>
-<p id="130006" class="block-content">
-An object may listen to a global event without defining an 'fx' method of the same name by
-adding an object method to the global event list. For example
-</p>
-<com:TTextHighlighter CssClass="source block-content">
-$component->fxGlobalCheck=$callback; // or $component->OnClick->add($callback);
-$component->attachEventHandler('fxGlobalCheck',array($object, 'someMethod'));
-</com:TTextHighlighter>
-<h2 id="26002">Events between Objects and their behaviors, Dynamic Events</h2>
-<p id="130007" class="block-content">
-An intra-object/behavior event is defined by methods that start with 'dy'. Just as with
-'fx' global events, every object has every dynamic event. Any call to a method that
-starts with 'dy' will be handled, regardless of whether it is implemented. These
-events are for communicating with attached behaviors.
-</p>
-<p id="130008" class="block-content">
-Dynamic events can be used in a variety of ways. They can be used to tell behaviors
-when a non-behavior method is called. Dynamic events could be used as data filters.
-They could also be used to specify when a piece of code is to be run, eg. should the
-loop process be performed on a particular piece of data. In this way, some control
-is handed to the behaviors over the process and/or data.
-</p>
-<p id="130009" class="block-content">
-If there are no handlers for an 'fx' or 'dy' event, it will return the first
-parameter of the argument list. If there are no arguments, these events
-will return null. If there are handlers an 'fx' method will be called directly
-within the object. Global 'fx' events are triggered by calling <tt>raiseEvent</tt>.
-For dynamic events where there are behaviors that respond to the dynamic events, a
-<tt>TCallChain</tt> is developed. A call chain allows the behavior dynamic event
-implementations to call further implementing behaviors within a chain.
-</p>
-<p id="130010" class="block-content">
-If an object implements <tt>IDynamicMethods</tt>, all global and object dynamic
-events will be sent to <tt>__dycall</tt>. In the case of global events, all
-global events will trigger this method. In the case of behaviors, all undefined
-dynamic events which are called will be passed through to this method.
-</p>
-<p id="130011" class="block-content">
-<h2 id="26003">Behaviors</h2>
-<p id="130012" class="block-content">
-There are two types of behaviors. There are individual object behaviors and
-there are class wide behaviors. Class behaviors depend upon object behaviors.
-</p>
-<p id="130013" class="block-content">
-When a new class implements <tt>IBehavior</tt> or <tt>IClassBehavior</tt> or
-extends <tt>TBehavior</tt> or <tt>TClassBehavior</tt>, it may be added to an
-object by calling the object's <tt>attachBehavior</tt>. The behaviors associated
-name can then be used to <tt>enableBehavior</tt> or <tt>disableBehavior</tt>
-the specific behavior.
-</p>
-<p id="130014" class="block-content">
-All behaviors may be turned on and off via <tt>enableBehaviors</tt> and
-<tt>disableBehaviors</tt>, respectively. To check if behaviors are on or off
-a call to <tt>getBehaviorsEnabled</tt> will provide the variable.
-</p>
-<p id="130015" class="block-content">
-Attaching and detaching whole sets of behaviors is done using
-<tt>attachBehaviors</tt> and <tt>detachBehaviors</tt>. <tt>clearBehaviors</tt>
-removes all of an object's behaviors.
-</p>
-<p id="130016" class="block-content">
-<tt>asa</tt> returns a behavior of a specific name. <tt>isa</tt> is the
-behavior inclusive function that acts as the PHP operator <tt>instanceof</tt>.
-A behavior could provide the functionality of a specific class thus causing
-the host object to act similarly to a completely different class. A behavior
-would then implement <tt>IInstanceCheck</tt> to provide the identity of the
-different class.
-</p>
-<p id="130017" class="block-content">
-Class behaviors are similar to object behaviors except that the class behavior
-is the implementation for all instances of the class. A class behavior
-will have the object upon which is being called be prepended to the parameter
-list. This way the object is known across the class behavior implementation.
-</p>
-<p id="130018" class="block-content">
-Class behaviors are attached using <tt>attachClassBehavior</tt> and detached
-using <tt>detachClassBehavior</tt>. Class behaviors are important in that
-they will be applied to all new instances of a particular class. In this way
-class behaviors become default behaviors to a new instances of a class in
-<tt>__construct</tt>. Detaching a class behavior will remove the behavior
-from the default set of behaviors created for an object when the object
-is instanced.
-</p>
-<p id="130019" class="block-content">
-Class behaviors are also added to all existing instances via the global 'fx'
-event mechanism. When a new class behavior is added, the event
-<tt>fxAttachClassBehavior</tt> is raised and all existing instances that are
-listening to this global event (primarily after <tt>listen</tt> is called)
-will have this new behavior attached. A similar process is used when
-detaching class behaviors. Any objects listening to the global 'fx' event
-<tt>fxDetachClassBehavior</tt> will have a class behavior removed.
-</p>
-<h2 id="26004">Dynamic Intra-Object Events</h2>
-<p id="130020" class="block-content">
-Dynamic events start with 'dy'. This mechanism is used to allow objects
-to communicate with their behaviors directly. The entire 'dy' event space
-is valid. All attached, enabled behaviors that implement a dynamic event
-are called when the host object calls the dynamic event. If there is no
-implementation or behaviors, this returns null when no parameters are
-supplied and will return the first parameter when there is at least one
-parameter in the dynamic event.
-</p>
-<com:TTextHighlighter CssClass="source block-content">
- null == $this->dyBehaviorEvent();
- 5 == $this->dyBehaviorEvent(5); //when no behaviors implement this dynamic event
-</com:TTextHighlighter>
-<p id="130021" class="block-content">
-Dynamic events can be chained together within behaviors to allow for data
-filtering. Dynamic events are implemented within behaviors by defining the
-event as a method.
-</p>
-<com:TTextHighlighter CssClass="source block-content">
-class TObjectBehavior extends TBehavior {
- public function dyBehaviorEvent($param1, $callchain) {
- //Do something, eg: $param1 += 13;
- return $callchain->dyBehaviorEvent($param1);
- }
-}
-</com:TTextHighlighter>
-<p id="130022" class="block-content">
-This implementation of a behavior and dynamic event will flow through to the
-next behavior implementing the dynamic event. The first parameter is always
-return when it is supplied. Otherwise a dynamic event returns null.
-</p>
-<p id="130023" class="block-content">
-In the case of a class behavior, the object is also prepended to the dynamic
-event.
-</p>
-<com:TTextHighlighter CssClass="source block-content">
-class TObjectClassBehavior extends TClassBehavior {
- public function dyBehaviorEvent($hostobject, $param1, $callchain) {
- //Do something, eg: $param1 += $hostobject->getNumber();
- return $callchain->dyBehaviorEvent($param1);
- }
-}
-</com:TTextHighlighter>
-</p>
-<p id="130024" class="block-content">
-When calling a dynamic event, only the parameters are passed. The host object
-and the call chain are built into the framework.
-</p>
-
-<h2 id="26005">Global Event and Dynamic event catching</h2>
-
-<p id="130025" class="block-content">
-Given that all global 'fx' events and dynamic 'dy' events are valid and
-operational, there is a mechanism for catching events called that are not
-implemented (similar to the built-in PHP method <tt>__call</tt>). When
-a dynamic or global event is called but a behavior does not implement it,
-yet desires to know when an undefined dynamic event is run, the behavior
-implements the interface <tt>IDynamicMethods</tt> and method <tt>__dycall</tt>.
-</p>
-<p id="130026" class="block-content">
-In the case of dynamic events, <tt>__dycall</tt> is supplied with the method
-name and its parameters. When a global event is raised, via <tt>raiseEvent</tt>,
-the method is the event name and the parameters are supplied.
-</p>
-<p id="130027" class="block-content">
-When implemented, this catch-all mechanism is called for event global event event
-when implemented outside of a behavior. Within a behavior, it will also be called
-when the object to which the behavior is attached calls any unimplemented dynamic
-event. This is the fall-back mechanism for informing a class and/or behavior
-of when an global and/or undefined dynamic event is executed.
-</p>
-
-<h2 id="704">Namespaces</h2>
-<p id="110121" class="block-content">
-A namespace refers to a logical grouping of some class names so that they can be differentiated from other class names even if their names are the same. Since PHP does not support namespace intrinsically, you cannot create instances of two classes who have the same name but with different definitions. To differentiate from user defined classes, all PRADO classes are prefixed with a letter 'T' (meaning 'Type'). Users are advised not to name their classes like this. Instead, they may prefix their class names with any other letter(s).
-</p>
-<p id="110122" class="block-content">
-A namespace in PRADO is considered as a directory containing one or several class files. A class may be specified without ambiguity using such a namespace followed by the class name. Each namespace in PRADO is specified in the following format,
-<div class="source">
-PathAlias.Dir1.Dir2
-</div>
-where <tt>PathAlias</tt> is an alias of some directory, while <tt>Dir1</tt> and <tt>Dir2</tt> are subdirectories under that directory. A class named <tt>MyClass</tt> defined under <tt>Dir2</tt> may now be fully qualified as <tt>PathAlias.Dir1.Dir2.MyClass</tt>.
-</p>
-<p id="110123" class="block-content">
-To use a namespace in code, do as follows,
-<com:TTextHighlighter CssClass="source block-content" id="code_110063">
-Prado::using('PathAlias.Dir1.Dir2.*');
-</com:TTextHighlighter>
-which appends the directory referred to by <tt>PathAlias.Dir1.Dir2</tt> into PHP include path so that classes defined under that directory may be instantiated without the namespace prefix. You may also include an individual class definition by
-<com:TTextHighlighter CssClass="source block-content" id="code_110064">
-Prado::using('PathAlias.Dir1.Dir2.MyClass');
-</com:TTextHighlighter>
-which will include the class file if <tt>MyClass</tt> is not defined.
-</p>
-<p id="110124" class="block-content">
-For more details about defining path aliases, see <a href="?page=Configurations.AppConfig">application configuration</a> section.
-</p>
-
-<h2 id="705">Component Instantiation</h2>
-<p id="110125" class="block-content">
-Component instantiation means creating instances of component classes. There are two types of component instantation: static instantiation and dynamic instantiation. The created components are called static components and dynamic components, respectively.
-</p>
-
-<h3 id="707">Dynamic Component Instantiation</h3>
-<p id="110126" class="block-content">
-Dynamic component instantiation means creating component instances in PHP code. It is the same as the commonly referred object creation in PHP. A component can be dynamically created using one of the following two methods in PHP,
-<com:TTextHighlighter CssClass="source block-content" id="code_110065">
-$component = new ComponentClassName;
-$component = Prado::createComponent('ComponentType');
-</com:TTextHighlighter>
-where <tt>ComponentType</tt> refers to a class name or a type name in namespace format (e.g. <tt>System.Web.UI.TControl</tt>). The second approach is introduced to compensate for the lack of namespace support in PHP.
-</p>
-
-<h3 id="708">Static Component Instantiation</h3>
-<p id="110127" class="block-content">
-Static component instantiation is about creating components via <a href="?page=Configurations.Overview">configurations</a>. The actual creation work is done by the PRADO framework. For example, in an <a href="?page=Configurations.AppConfig">application configuration</a>, one can configure a module to be loaded when the application runs. The module is thus a static component created by the framework. Static component instantiation is more commonly used in <a href="?page=Configurations.Templates1">templates</a>. Every component tag in a template specifies a component that will be automatically created by the framework when the template is loaded. For example, in a page template, the following tag will lead to the creation of a <tt>TButton</tt> component on the page,
-<com:TTextHighlighter Language="prado" CssClass="source block-content" id="code_110066">
-<com:TButton Text="Register" />
-</com:TTextHighlighter>
-</p>
-
-</com:TContent>
diff --git a/demos/quickstart/protected/pages/Fundamentals/Components1.page b/demos/quickstart/protected/pages/Fundamentals/Components1.page new file mode 100755 index 00000000..a610045d --- /dev/null +++ b/demos/quickstart/protected/pages/Fundamentals/Components1.page @@ -0,0 +1,157 @@ +<com:TContent ID="body" > +<h1 id="701">Components: Part I</h1> +<p id="110113" class="block-content"> +A component is an instance of <tt>TComponent</tt> or its child class. The base class <tt>TComponent</tt> implements the mechanism of component properties and events. +</p> + +<h2 id="702">Component Properties</h2> +<p id="110114" class="block-content"> +A component property can be viewed as a public variable describing a specific aspect of the component, such as the background color, the font size, etc. A property is defined by the existence of a getter and/or a setter method in the component class. For example, in <tt>TControl</tt>, we define its <tt>ID</tt> property using the following getter and setter methods, +<com:TTextHighlighter CssClass="source block-content" id="code_110056"> +class TControl extends TComponent { + public function getID() { + ... + } + public function setID($value) { + ... + } +} +</com:TTextHighlighter> +</p> +<p id="110115" class="block-content"> +To get or set the <tt>ID</tt> property, do as follows, just like working with a variable, +<com:TTextHighlighter CssClass="source block-content" id="code_110057"> +$id = $component->ID; +$component->ID = $id; +</com:TTextHighlighter> +This is equivalent to the following, +<com:TTextHighlighter CssClass="source block-content" id="code_110058"> +$id = $component->getID(); +$component->setID( $id ); +</com:TTextHighlighter> +</p> +<p id="110116" class="block-content"> +A property is read-only if it has a getter method but no setter method. Since PHP method names are case-insensitive, property names are also case-insensitive. A component class inherits all its ancestor classes' properties. +</p> + +<h3 id="706">Subproperties</h3> +<p id="110117" class="block-content"> +A subproperty is a property of some object-typed property. For example, <tt>TWebControl</tt> has a <tt>Font</tt> property which is of <tt>TFont</tt> type. Then the <tt>Name</tt> property of <tt>Font</tt> is referred to as a subproperty (with respect to <tt>TWebControl</tt>). +</p> +<p id="110118" class="block-content"> +To get or set the <tt>Name</tt> subproperty, use the following method, +<com:TTextHighlighter CssClass="source block-content" id="code_110059"> +$name = $component->getSubProperty('Font.Name'); +$component->setSubProperty('Font.Name', $name); +</com:TTextHighlighter> +This is equivalent to the following, +<com:TTextHighlighter CssClass="source block-content" id="code_110060"> +$name = $component->getFont()->getName(); +$component->getFont()->setName( $name ); +</com:TTextHighlighter> +</p> + +<h3 id="26001">Js-friendly properties</h3> +<p class="block-content"> +A JavaScript-friendly property is a property that can accept both simple strings and raw javascript. +Prado automatically encodes all properties sent clientside inside javascript blocks to avoid security problems (like injections or cross site scripting). +If a property is known to always contain only safe javascript code and its value needs to bypass this encoding, that property can be defined in a special way that will make Prado mark its value as "safe". +Js-friendly properties are identified by their name starting with 'js' (case insensitive): +<com:TTextHighlighter CssClass="source block-content"> +// getter, defines a readable property 'Text' +function getJsText() { … } +// setter, defines a writable property 'Text', with $value being the value to be set to the property +function setJsText(TJavaScriptLiteral $value) { … } +</com:TTextHighlighter> +Js-friendly properties can be accessed using both their Js-less name and their Js-enabled name: +<com:TTextHighlighter CssClass="source block-content"> +// set some simple text as property value +$component->Text = 'text'; +// set some javascript code as property value +$component->JsText = 'raw javascript'; +</com:TTextHighlighter> +In the first case, the property value will automatically gets encoded when sent clientside inside a javascript block. +In the second case, the property will be 'marked' as being a safe javascript statement and will not be encoded when rendered inside a javascript block. +This special handling makes use of the <tt>TJavaScriptLiteral</tt> class. +</p> + + +<h2 id="703">Component Events</h2> +<p id="110119" class="block-content"> +Component events are special properties that take method names as their values. Attaching (setting) a method to an event will hook up the method to the places at which the event is raised. Therefore, the behavior of a component can be modified in a way that may not be foreseen during the development of the component. +</p> +<p id="110120" class="block-content"> +A component event is defined by the existence of a method whose name starts with the word <tt>on</tt>. The event name is the method name and is thus case-insensitve. For example, in <tt>TButton</tt>, we have +<com:TTextHighlighter CssClass="source block-content" id="code_110061"> +class TButton extends TWebControl { + public function onClick( $param ) { + ... + } +} +</com:TTextHighlighter> +This defines an event named <tt>OnClick</tt>, and a handler can be attached to the event using one of the following ways, +<com:TTextHighlighter CssClass="source block-content" id="code_110062"> +$button->OnClick = $callback; +$button->OnClick->add( $callback ); +$button->OnClick[] = $callback; +$button->attachEventHandler( 'OnClick' , $callback ); +</com:TTextHighlighter> +</p> + The variable <tt>$callback</tt> contains the definition of the event handler that can be either a string referring to a global function name, or an array whose first element refers to an object and second element a method name/path that is reachable by the object, e.g. + </p> +<ul> +<li>'buttonClicked' : buttonClicked($sender,$param);</li> +<li>array($object,'buttonClicked') : $object->buttonClicked($sender,$param);</li> +<li>array($object,'MainContent.SubmitButton.buttonClicked') : $object->MainContent->SubmitButton->buttonClicked($sender,$param);</li> +</ul> + +<h2 id="704">Namespaces</h2> +<p id="110121" class="block-content"> +A namespace refers to a logical grouping of some class names so that they can be differentiated from other class names even if their names are the same. Since PHP does not support namespace intrinsically, you cannot create instances of two classes who have the same name but with different definitions. To differentiate from user defined classes, all PRADO classes are prefixed with a letter 'T' (meaning 'Type'). Users are advised not to name their classes like this. Instead, they may prefix their class names with any other letter(s). +</p> +<p id="110122" class="block-content"> +A namespace in PRADO is considered as a directory containing one or several class files. A class may be specified without ambiguity using such a namespace followed by the class name. Each namespace in PRADO is specified in the following format, +<div class="source"> +PathAlias.Dir1.Dir2 +</div> +where <tt>PathAlias</tt> is an alias of some directory, while <tt>Dir1</tt> and <tt>Dir2</tt> are subdirectories under that directory. A class named <tt>MyClass</tt> defined under <tt>Dir2</tt> may now be fully qualified as <tt>PathAlias.Dir1.Dir2.MyClass</tt>. +</p> +<p id="110123" class="block-content"> +To use a namespace in code, do as follows, +<com:TTextHighlighter CssClass="source block-content" id="code_110063"> +Prado::using('PathAlias.Dir1.Dir2.*'); +</com:TTextHighlighter> +which appends the directory referred to by <tt>PathAlias.Dir1.Dir2</tt> into PHP include path so that classes defined under that directory may be instantiated without the namespace prefix. You may also include an individual class definition by +<com:TTextHighlighter CssClass="source block-content" id="code_110064"> +Prado::using('PathAlias.Dir1.Dir2.MyClass'); +</com:TTextHighlighter> +which will include the class file if <tt>MyClass</tt> is not defined. +</p> +<p id="110124" class="block-content"> +For more details about defining path aliases, see <a href="?page=Configurations.AppConfig">application configuration</a> section. +</p> + +<h2 id="705">Component Instantiation</h2> +<p id="110125" class="block-content"> +Component instantiation means creating instances of component classes. There are two types of component instantation: static instantiation and dynamic instantiation. The created components are called static components and dynamic components, respectively. +</p> + +<h3 id="707">Dynamic Component Instantiation</h3> +<p id="110126" class="block-content"> +Dynamic component instantiation means creating component instances in PHP code. It is the same as the commonly referred object creation in PHP. A component can be dynamically created using one of the following two methods in PHP, +<com:TTextHighlighter CssClass="source block-content" id="code_110065"> +$component = new ComponentClassName; +$component = Prado::createComponent('ComponentType'); +</com:TTextHighlighter> +where <tt>ComponentType</tt> refers to a class name or a type name in namespace format (e.g. <tt>System.Web.UI.TControl</tt>). The second approach is introduced to compensate for the lack of namespace support in PHP. +</p> + +<h3 id="708">Static Component Instantiation</h3> +<p id="110127" class="block-content"> +Static component instantiation is about creating components via <a href="?page=Configurations.Overview">configurations</a>. The actual creation work is done by the PRADO framework. For example, in an <a href="?page=Configurations.AppConfig">application configuration</a>, one can configure a module to be loaded when the application runs. The module is thus a static component created by the framework. Static component instantiation is more commonly used in <a href="?page=Configurations.Templates1">templates</a>. Every component tag in a template specifies a component that will be automatically created by the framework when the template is loaded. For example, in a page template, the following tag will lead to the creation of a <tt>TButton</tt> component on the page, +<com:TTextHighlighter Language="prado" CssClass="source block-content" id="code_110066"> +<com:TButton Text="Register" /> +</com:TTextHighlighter> +</p> + +</com:TContent> diff --git a/demos/quickstart/protected/pages/Fundamentals/Components2.page b/demos/quickstart/protected/pages/Fundamentals/Components2.page new file mode 100644 index 00000000..7fc3e010 --- /dev/null +++ b/demos/quickstart/protected/pages/Fundamentals/Components2.page @@ -0,0 +1,207 @@ +<com:TContent ID="body" > +<h1 id="701">Components: Part II</h1> +<com:SinceVersion Version="3.2.3" /> +<h2 id="26001">Global events</h2> +<p id="130001" class="block-content"> +With the addition of behaviors, a more expansive event model is needed. There +are two new event types (global and dynamic events) as well as a more comprehensive +behavior model that includes class wide behaviors. +</p> +<p id="130002" class="block-content"> +A global event is defined by all events whose name starts with 'fx'. +The event name is potentially a method name and is thus case-insensitive. All 'fx' events +are valid as the whole 'fx' event/method space is global in nature. Any object may patch into +any global event by defining that event as a method. Global events have priorities +just like 'on' events; so as to be able to order the event execution. Due to the +nature of all events which start with 'fx' being valid, in effect, every object +has every 'fx' global event. It is simply an issue of tapping into the desired +global event. +</p> +<p id="130003" class="block-content"> +A global event that starts with 'fx' can be called even if the object does not +implement the method of the global event. A call to a non-existing 'fx' method +will, at minimal, function and return null. If a method argument list has a first +parameter, it will be returned instead of null. This allows filtering and chaining. +'fx' methods do not automatically install and uninstall. To install and uninstall an +object's global event listeners, call the object's <tt>listen</tt> and +<tt>unlisten</tt> methods, respectively. An object may auto-install its global event +during <tt>__construct</tt> by overriding <tt>getAutoGlobalListen</tt> and returning true. +</p> +<p id="130004" class="block-content"> +As of PHP version 5.3, nulled objects without code references will still continue to persist +in the global event queue because <tt>__destruct</tt> is not automatically called. In the common +__destruct method, if an object is listening to global events, then <tt>unlisten</tt> is called. +<tt>unlisten</tt> is required to be manually called before an object is +left without references if it is currently listening to any global events. This includes +class wide behaviors. +</p> +<p id="130005" class="block-content"> +An object that contains a method that starts with 'fx' will have those functions +automatically receive those events of the same name after <tt>listen</tt> is called on the object. +</p> +<p id="130006" class="block-content"> +An object may listen to a global event without defining an 'fx' method of the same name by +adding an object method to the global event list. For example +</p> +<com:TTextHighlighter CssClass="source block-content"> +$component->fxGlobalCheck=$callback; // or $component->OnClick->add($callback); +$component->attachEventHandler('fxGlobalCheck',array($object, 'someMethod')); +</com:TTextHighlighter> +<h2 id="26002">Events between Objects and their behaviors, Dynamic Events</h2> +<p id="130007" class="block-content"> +An intra-object/behavior event is defined by methods that start with 'dy'. Just as with +'fx' global events, every object has every dynamic event. Any call to a method that +starts with 'dy' will be handled, regardless of whether it is implemented. These +events are for communicating with attached behaviors. +</p> +<p id="130008" class="block-content"> +Dynamic events can be used in a variety of ways. They can be used to tell behaviors +when a non-behavior method is called. Dynamic events could be used as data filters. +They could also be used to specify when a piece of code is to be run, eg. should the +loop process be performed on a particular piece of data. In this way, some control +is handed to the behaviors over the process and/or data. +</p> +<p id="130009" class="block-content"> +If there are no handlers for an 'fx' or 'dy' event, it will return the first +parameter of the argument list. If there are no arguments, these events +will return null. If there are handlers an 'fx' method will be called directly +within the object. Global 'fx' events are triggered by calling <tt>raiseEvent</tt>. +For dynamic events where there are behaviors that respond to the dynamic events, a +<tt>TCallChain</tt> is developed. A call chain allows the behavior dynamic event +implementations to call further implementing behaviors within a chain. +</p> +<p id="130010" class="block-content"> +If an object implements <tt>IDynamicMethods</tt>, all global and object dynamic +events will be sent to <tt>__dycall</tt>. In the case of global events, all +global events will trigger this method. In the case of behaviors, all undefined +dynamic events which are called will be passed through to this method. +</p> +<p id="130011" class="block-content"> +<h2 id="26003">Behaviors</h2> +<p id="130012" class="block-content"> +There are two types of behaviors. There are individual object behaviors and +there are class wide behaviors. Class behaviors depend upon object behaviors. +</p> +<p id="130013" class="block-content"> +When a new class implements <tt>IBehavior</tt> or <tt>IClassBehavior</tt> or +extends <tt>TBehavior</tt> or <tt>TClassBehavior</tt>, it may be added to an +object by calling the object's <tt>attachBehavior</tt>. The behaviors associated +name can then be used to <tt>enableBehavior</tt> or <tt>disableBehavior</tt> +the specific behavior. +</p> +<p id="130014" class="block-content"> +All behaviors may be turned on and off via <tt>enableBehaviors</tt> and +<tt>disableBehaviors</tt>, respectively. To check if behaviors are on or off +a call to <tt>getBehaviorsEnabled</tt> will provide the variable. +</p> +<p id="130015" class="block-content"> +Attaching and detaching whole sets of behaviors is done using +<tt>attachBehaviors</tt> and <tt>detachBehaviors</tt>. <tt>clearBehaviors</tt> +removes all of an object's behaviors. +</p> +<p id="130016" class="block-content"> +<tt>asa</tt> returns a behavior of a specific name. <tt>isa</tt> is the +behavior inclusive function that acts as the PHP operator <tt>instanceof</tt>. +A behavior could provide the functionality of a specific class thus causing +the host object to act similarly to a completely different class. A behavior +would then implement <tt>IInstanceCheck</tt> to provide the identity of the +different class. +</p> +<p id="130017" class="block-content"> +Class behaviors are similar to object behaviors except that the class behavior +is the implementation for all instances of the class. A class behavior +will have the object upon which is being called be prepended to the parameter +list. This way the object is known across the class behavior implementation. +</p> +<p id="130018" class="block-content"> +Class behaviors are attached using <tt>attachClassBehavior</tt> and detached +using <tt>detachClassBehavior</tt>. Class behaviors are important in that +they will be applied to all new instances of a particular class. In this way +class behaviors become default behaviors to a new instances of a class in +<tt>__construct</tt>. Detaching a class behavior will remove the behavior +from the default set of behaviors created for an object when the object +is instanced. +</p> +<p id="130019" class="block-content"> +Class behaviors are also added to all existing instances via the global 'fx' +event mechanism. When a new class behavior is added, the event +<tt>fxAttachClassBehavior</tt> is raised and all existing instances that are +listening to this global event (primarily after <tt>listen</tt> is called) +will have this new behavior attached. A similar process is used when +detaching class behaviors. Any objects listening to the global 'fx' event +<tt>fxDetachClassBehavior</tt> will have a class behavior removed. +</p> +<h2 id="26004">Dynamic Intra-Object Events</h2> +<p id="130020" class="block-content"> +Dynamic events start with 'dy'. This mechanism is used to allow objects +to communicate with their behaviors directly. The entire 'dy' event space +is valid. All attached, enabled behaviors that implement a dynamic event +are called when the host object calls the dynamic event. If there is no +implementation or behaviors, this returns null when no parameters are +supplied and will return the first parameter when there is at least one +parameter in the dynamic event. +</p> +<com:TTextHighlighter CssClass="source block-content"> + null == $this->dyBehaviorEvent(); + 5 == $this->dyBehaviorEvent(5); //when no behaviors implement this dynamic event +</com:TTextHighlighter> +<p id="130021" class="block-content"> +Dynamic events can be chained together within behaviors to allow for data +filtering. Dynamic events are implemented within behaviors by defining the +event as a method. +</p> +<com:TTextHighlighter CssClass="source block-content"> +class TObjectBehavior extends TBehavior { + public function dyBehaviorEvent($param1, $callchain) { + //Do something, eg: $param1 += 13; + return $callchain->dyBehaviorEvent($param1); + } +} +</com:TTextHighlighter> +<p id="130022" class="block-content"> +This implementation of a behavior and dynamic event will flow through to the +next behavior implementing the dynamic event. The first parameter is always +return when it is supplied. Otherwise a dynamic event returns null. +</p> +<p id="130023" class="block-content"> +In the case of a class behavior, the object is also prepended to the dynamic +event. +</p> +<com:TTextHighlighter CssClass="source block-content"> +class TObjectClassBehavior extends TClassBehavior { + public function dyBehaviorEvent($hostobject, $param1, $callchain) { + //Do something, eg: $param1 += $hostobject->getNumber(); + return $callchain->dyBehaviorEvent($param1); + } +} +</com:TTextHighlighter> +</p> +<p id="130024" class="block-content"> +When calling a dynamic event, only the parameters are passed. The host object +and the call chain are built into the framework. +</p> + +<h2 id="26005">Global Event and Dynamic event catching</h2> + +<p id="130025" class="block-content"> +Given that all global 'fx' events and dynamic 'dy' events are valid and +operational, there is a mechanism for catching events called that are not +implemented (similar to the built-in PHP method <tt>__call</tt>). When +a dynamic or global event is called but a behavior does not implement it, +yet desires to know when an undefined dynamic event is run, the behavior +implements the interface <tt>IDynamicMethods</tt> and method <tt>__dycall</tt>. +</p> +<p id="130026" class="block-content"> +In the case of dynamic events, <tt>__dycall</tt> is supplied with the method +name and its parameters. When a global event is raised, via <tt>raiseEvent</tt>, +the method is the event name and the parameters are supplied. +</p> +<p id="130027" class="block-content"> +When implemented, this catch-all mechanism is called for event global event event +when implemented outside of a behavior. Within a behavior, it will also be called +when the object to which the behavior is attached calls any unimplemented dynamic +event. This is the fall-back mechanism for informing a class and/or behavior +of when an global and/or undefined dynamic event is executed. +</p> + +</com:TContent> diff --git a/demos/quickstart/protected/pages/Fundamentals/Pages.page b/demos/quickstart/protected/pages/Fundamentals/Pages.page index 19900937..d52dccf5 100755 --- a/demos/quickstart/protected/pages/Fundamentals/Pages.page +++ b/demos/quickstart/protected/pages/Fundamentals/Pages.page @@ -5,13 +5,27 @@ Pages are top-most controls that have no parent. The presentation of pages are directly displayed to end-users. Users access pages by sending page service requests.
</p>
<p id="130138" class="block-content">
-Each page must have a <a href="?page=Configurations.Templates1">template</a> file. The file name suffix must be <tt>.page</tt>. The file name (without suffix) is the page name. PRADO will try to locate a page class file under the directory containing the page template file. Such a page class file must have the same file name (suffixed with <tt>.php</tt>) as the template file. If the class file is not found, the page will take class <tt>TPage</tt>.
+Each page can have a <a href="?page=Configurations.Templates1">template</a> file. The file name suffix must be <tt>.page</tt>. The file name (without suffix) is the page name. PRADO will try to locate a page class file under the directory containing the page template file. Such a page class file must have the same file name (suffixed with <tt>.php</tt>) as the template file. If the class file is not found, the page will take class <tt>TPage</tt>.
</p>
<h2 id="902">PostBack</h2>
<p id="130139" class="block-content">
A form submission is called <i>postback</i> if the submission is made to the page containing the form. Postback can be considered an event happened on the client side, raised by the user. PRADO will try to identify which control on the server side is responsible for a postback event. If one is determined, for example, a <tt>TButton</tt>, we call it the postback event sender which will translate the postback event into some specific server-side event (e.g. <tt>OnClick</tt> and <tt>OnCommand</tt> events for <tt>TButton</tt>).
+<br/>
+<tt>TPage</tt> has a <tt>IsPostBack</tt> property exposing whether the current request being handled is the first request for this page or the consequence of a postback.
+</p>
+<h2 id="32008">CallBack</h2>
+<p class="block-content">
+A <i>callback</i> is a special form submission that, instead of requiring a full page reload on the browser, gets executed in the background through an ajax call. So, a callback is considered a postback too, but not vice versa.
+<br/>
+A callback is handled as a normal postback but, instead of re-rendering the entire page, only the specific changes occured on the page gets sent back to the client and merged with the current browser page. A typical callback response consists of:
+<ol>
+ <li>one or more pieces of html code that will replace existing content on the page;</li>
+ <li>the javascript instructions needed to update the page;</li>
+ <li>some specific fields used by prado to mantain the pagestate and add the needed external resources (stylesheets, javascript files, etc..).</li>
+</ol>
+<tt>TPage</tt> has a <tt>IsCallBack</tt> property exposing whether the current request being handled is the consequence of a callback. Since a callback is also a postback, both <tt>IsPostBack</tt> and <tt>IsCallBack</tt> are true during callback requests.
</p>
<h2 id="903">Page Lifecycles</h2>
diff --git a/demos/quickstart/protected/pages/Fundamentals/Services.page b/demos/quickstart/protected/pages/Fundamentals/Services.page index 5e5889df..ee19a159 100755 --- a/demos/quickstart/protected/pages/Fundamentals/Services.page +++ b/demos/quickstart/protected/pages/Fundamentals/Services.page @@ -16,7 +16,7 @@ Developers may implement additional services for their applications. To make a s <h2 id="1102">Page Service</h2>
<p id="150154" class="block-content">
-PRADO implements <tt>TPageService</tt> to process users' page requests. Pages are stored under a directory specified by the <tt>BasePath</tt> property of the page service. The property defaults to <tt>pages</tt> directory under the application base path. You may change this default by configuring the service in the application configuration.
+PRADO implements <tt>TPageService</tt> to process users' page requests. Pages are stored under a directory specified by the <tt>BasePath</tt> property of the page service. The property defaults to <tt>Pages</tt> directory under the application base path. You may change this default by configuring the service in the application configuration.
</p>
<p id="150155" class="block-content">
Pages may be organized into subdirectories under the <tt>BasePath</tt>. In each directory, there may be a page configuration file named <tt>config.xml</tt>, which contains configurations effective only when a page under that directory or a sub-directory is requested. For more details, see the <a href="?page=Configurations.PageConfig">page configuration</a> section.
@@ -30,5 +30,8 @@ http://hostname/index.php?page=Users.Register </com:TTextHighlighter>
where the first example takes advantage of the fact that the page service is the default service and <tt>Home</tt> is the default page.
</p>
+<p class="block-content">
+More advanced url routes, like masking real page names and permitting the use of dynamic parameters can be created using the <a href="?page=Configurations.UrlMapping">Url mapping</a> module.
+</p>
</com:TContent>
|