The custom model is used when no other model suits your requirements. The custom model can be used to generate any type of content including HTLM, XML, CSS and JavaScript. Generally speaking, the custom model should be used for "one off" types of pages, rather than page types that occur frequently. This is because new (specialized) models should be developed to handle page types that are needed on a regular basis. Furthermore, the custom model tends to be used for dynamic or variable content, if the content of your page will be static (and can be predetermined) you might consider using the tags model. Required FunctionThe custom model creates a php class and you are required to define the body of the generate function of the class. This function must return whatever content is to be generated. Here we see an example of a generate function that generates the classic "Hello World!" page. Notice that the entire function declaration is not entered, only the body of the function. The function name is indicated by the Section Id in column 3 and the Location column is set to Replace Body to indicate that only the body portion if the function is being entered. Optional FunctionsThe Example Code button can be clicked to obtain examples of other functions that can be coded. To use one of these functions, change the Function Type column from example to function. Accessing InformationIn most cases the custom page is going to need information from various sources in order to decide what to generate. Here we discuss some of the more common data sources. From Site InformationMost custom pages require access to the site object. In order to gain access to the site object, the custom page class, or one of its parent classes, must define a set_site method. There are several ways that this can be achieved including the following:
This site object contains with a great deal of information about the current environment. For example, consider the following generate code:
Requesting this page in the live site would return the text 'This is the live site'. In the sandbox this would return 'This is the sandbox site'. The site object also exposes all dollar functions programmatically. Here we see a sample generate function that appears in the page called sitemap located in system. This is used to build a sitemap page (as opposed to an xml sitemap) for any site that has a menu or a bootstrap navigation object.
Notice that the first parameter to the site object's dollar_function method is the name of the function that you want to execute. This is followed by the parameters that you would normally pass to the function. Pass in NULL to skip parameters. We will see later that it is also possible to pass the parameters using a keyed array. When there are several parameters that is the preferred approach for increased readability. From Passed ParametersLet's suppose you are building a page that returns employee information and we want to allow the following three parameters to be passed to the page:
There are two main ways to dynamically pass these values:
Let's look at a sample custom page that uses these parameters. Recall that all custom pages are implemented as php classes. Methods of this class will be called at various points in the page building/rendering process so you might want to define some class variables to "remember" information from one call to the next. In our example we are going to define the following class properties (variables): set_parameters MethodNext we will need a way to copy parameters passed into this page over to the class properties we defined. This could be done using the set_parameter method as we see here: Notice this method accepts a parameters object as a parameter. This is the same object that can be accessed from most code via $this->site->parameters. This object offers several ways to extract parameter data. Here we are using the set_if_supplied method to set properties if they have been passed. Other methods that could be used include:
The get_required_parameter method would trigger an error if the requested parameter was not passed. We could also use, this method:
This would set the occupation property to the occupation value that was passed to the program, if no such value was passed it would set it to '*'. Note that it is not necessary to save your parameters in class variables. This is done when using the set_parameters method so that the parameters are available to other methods, such as generate. If you only need these parameters within the generate method you can also access the site's parameters object directly as we show here:
Let's look at some examples of how these parameters can be passed into this page. Passing Parameters Via the QuerystringSuppose our page is called emplist and the page is requested using a url such as www.example.com/emplist?last_name=smith&city=toronto This would have the effect of setting the last_name and city parameters. Passing Parameters Via the $page functionIf you are rendering the page as a component of another page, you can supply parameters to the $page function as in: $page(emplist,last_name=jones&occupation=programmer) It is important to note that parameters passed to the page function in this way cannot be overridden via the querystring. The parameters object will define the union of both sets of parameters but the page parameters will take precedents over the querystring parameters. pre_generate MethodThe pre_generate method should be used if you need to define any custom styles or script or set certain containers. For example, let's suppose that you want to dynamically populate the meta description for the page based on the parameters passed to it. This could not be done in the generate method since the meta description tag would have already been generated by the time the page's generate method is triggered. On the other hand, you can do this in the pre_generate method as we see in this example:
Since this page could be embedded into different layouts, it is unwise to assume that the containing layout even supports meta descriptions. For example, perhaps this page is being rendered as the contents of an email. Meta data would normally not be rendered in such a case. We handle this uncertainty by first asking the layout for the metatags object and we only attempt to update the meta description if the layout returned an object. Other page content, such as title and header tags could be updated dynamically if suitable containers exist within the current layout (codeframe). The following sample code shows how this could be done:
A more convenient method for setting these attributes is to use the trait named dynamic_seo. In so doing you can set these properties as follows:
Setting Styles and Javascript DynamicallyIn most cases, styles and script don't change based on the actual page contents so we can set these "statically" at either the page level or within the layout or site_settings. Nevertheless, there may be situations whereby you want to defer the addition of styles or script until you determine that they are needed. Eliminating unnecessary styles and script is an effective way to improve the speed at which your pages load. Both the javascript object and the styles object are passed a keyed array which contains all of the values needed to configure the script or styles. Adding JavaScript DynamicallyHere we show an example of how to add script programmatically. In the first portion of the code we add a reference to script that has already been saved using the javascript model. In the second part of the code we create some script on-the-fly and define this as inline script within the head section of the current page.
List of JavaScript ParametersIn the above example we only show a subset of the parameters that can be defined when calling the site object's add_script method. Let's review the other parameters that can be passed. Here we see the signature of the method: add_script($identifier,$script_info,$requestor=false,$requestor_detail=false)
Let's review all of the keys that can be set in the array passed in parameter 2.
Adding Styles DynamicallyTo dynamically add styles to the current page, the process is similar to what we have shown for JavaScript above. Here is an example of this:
This signature of the site object's add_styles method is similar to add_script as we see here: add_styles($identifier,$style_info,$requestor=false,$requestor_detail=false) The parameters behave in a similar way except parameter 2 is an array used to configure style behavior. The keys to this array are defined below:
The site's add_script and add_styles methods will be ignored when called from pages using codeframes that don't support the javascript or styles objects, respectively. Extracting Information From an SQL DatabaseIn many cases the data you will be presenting in the generate method will come from a database. Often, you will be able to use the db_table_browse model for this purpose but there will be times when you may want more control over the presentation of the data. There are several ways that a custom generate method can access SQL data.
When using the first option, you may want to utilize the function code builder by clicking on the $function Help button shown here. This will bring up a screen that will help you ascertain what parameters the function needs as we see below: After clicking on the Accept button in the popup page, the suggested code will be returned next to $Function Help button as we see here: Copy and paste the code to use this as part of your generate method. In many cases you will need to adapt the code to cater to special situations. Here we show how the search fields could be dynamically added based on the parameters passed to the page.
Developing Custom SQL QueriesSometimes the queries you need to write may be too complex to be handled by the $dbselect or $dblookup functions. In such a case you can build your query from scratch using supplied base classes provided by the GenHelm framework. In this example, we show a custom query developed using the supplied sql_handler class.
Prevent Parsing of Dollar FunctionsIf you are using the custom model to generate content which may contain dollar functions but you don't want these dollar functions to be parsed you can supply an optional function named get_parse_dollar as shown here:
Since this function returns false, any dollar functions generated by the custom component will remain as dollar functions, they won't be resolved. Keep in mind that if your page is nested inside another page that does parse dollar functions, your page's dollar functions may be parsed as part of the container page's rendering. Using Custom Pages in Combination with Other ModelsAnother potential data source for custom pages may come from components generated by other models. For example, the xml_sitemap model allows you to specify pages from system and other inherited sites to be included in the xml sitemap for the site. The information is saved as a php "snippet" (.inc file). The sitemapindex page (defined in system) is based on the custom model and it uses components generated by the xml_sitemap model to determine what the xml sitemap should contain for the current site. Message HandlingSome of your custom pages may want to render on-page messages within the message area codeframe object. To do so, they should first obtain a copy of the message_area object from the site's layout object to make sure that the layout they are currently running within supports the message object. Here we show how you can check for this.
Once you have determined that your container codeframe supports standard messaging there are a number of ways that your custom page can set a message. One option is to assign the messages directly to the message object as shown here:
The above code defined within the generate method of the custom page would render the following content: Custom pages should generally call upon other objects to implement business logic and processes. In so doing, the business logic becomes more reusable since it is not tightly coupled to a specific custom page. If the objects that your custom page calls extend the standard_base class, you will normally want to capture any messages that your called objects have set. Here we show an example in which the custom generate method calls another "processor" object which may set one or more messages. After calling the object we transfer any messages that it may have set to the message_area object by calling the transfer_your_messages_to_me method. If needed, we can also add more messages to the message_area object.
The transfer_your_messages_to_me method should normally be called after calling any object that inherits standard_base (even if the object does not set a message). By doing so, the caller's code will not have to be changed if the called object is updated at a later date and introduces message assignments. In most cases, the caller will pass itself as a parameter to transfer_your_messages_to_me as in:
The advantage of having a standard approach to message handling is that the object you call can call methods of other objects which call methods of still other objects and if all of these objects handle messaging the same way all messages will percolate up the call chain right back to you without requiring any complex logic. Using TraitsIncluding the trait DefinitionTraits defined using the php_trait model are generated into the trait subfolder of the main classes folder. Therefore, to incorporate traits defined within system you first have to require the trait using: require_once CLASS_PATH.'trait/tname.php'; If the trait is defined within the current site, it should be included using: require_once SITE_CLASS_PATH.'trait/tname.php'; In each case, tname is the name of the trait to be used. The reference should be defined within the Before Class definition as shown. Adding the use StatementWithin the Custom Code section, set the Section Type to be use and set the Location to be After Last Sibling. Enter the full use statement within the Custom Code column as shown: Sorting Properties and FunctionsYou can sort both properties and functions (methods) by using the sort command. To only sort properties you can enter the command sort properties. To only sort functions, enter the command sort functions. |