How could/should you realize this and that with Phenotype?
This page list typical challenges of any webapplication and how you could/should realize them with Phenotype. We hope it will inspire you and deepens your understanding of the Phenotype architecture:
Simple Website
For a simple website you just need one layout.
Create two pagegroups. One pagegroup holds all standard pages, the other group is ment for those pages not linked into the site tree, like imprint, terms & conditions…
If you want to have a dynamic navigation, code one navigation include and link it to your layout. Within that include you can access the current page (global $myPage) and use the NavigationHelper class to collect all necessary information for arbitrary complex navigation printouts. Caching will reduce the database load automatically for you.
For editing the page content you just need one component, a richtext component. Maybe you can add a style selector, if you want to have different looking paragraphs.
That’s it. Everything mentioned here is enclosed in the PT_DEMO example application.
Contact Form
To realize a contact form you can create an include for displaying the form and validating the user input. You must put that include onto a page with the include component. You must turn off the cache for that include or for the whole page (first proposal recommended).
Additionally you should create a contentobject class for storing the user feedback into the database. That leaves open the opportunity to postprocess the user feedback for whatever reason (see guestbook description).
Be sure to escape any data entered by your users when printing it out, either using the abilities of the smarty template engine (e.g. {$value|escape} or using the special getters on any phenotype object (e.g. $myRequest→getH(“comment”)).
Special (HTML) Content
If you have to deal with special html content, like complex tables, charts or other things like that, it’s probably not necessary to code specific page components or includes for that.
A simple approach is to use the html page component (contained in PT_CORE and PT_DEMO).
If you have lots of special content and/or the content is used on more than one page, you should create a content object class for html fragments and a page component to select and place these fragments.
News
News are a typical use case for content object classes. Create a content object class for editing news. It’s recommend to manage some metadata, too (like categories, importance, keywords, date ranges).
Then create two includes:
The first include contains a script, reading all current news from the database and displaying an overview. Place that include with the include component and use the cache settings of the containing page. Whenever something is edited within the backend the cache gets flushed, so you don’t have to worry about old content!. If you need a pager on your overview, your include cannot use the page cache. Turn it’s cache of or set it to “include cache”.
The second include is for displayment of your news. Create a page, name it to determine it’s url, and place the second include onto it (Cache setting: “include cache”). Identifiy the news to be displayed out of the url ($myRequest), grab the belonging content object out of the database (using methods of PhenotypePeer class) and display the news. You should consider to use the permalink feature of content objects (→buildUrl()) to achieve nice SEO-Urls.
Image Gallery
You can realize an image gallery just like the news written above:
- one content object class for managing/editing the galleries
- some meta data for seo optimization and ordering
- →form_textarea or →form_richtext for description of every image
- one include for displayment of the gallery
- maybe another include for a gallery overview
Or you can realize a simple gallery with just one page component. This component just has to consist of a number of media selectors within the initForm-method and render them out within the render-method.
When realizing a gallery you should consider the possibility of using image versions (for teaser and zoom displayment), especially the ability of Phenotype to create that versions on demand.
You can enhance the editing experience, if you offer to upload some images directly to the content object via drag & drop (→form_ddupload). That also enables you to enforce a specific order structure when importing the images into the mediabase ($myMB→import…).
Site Analytics
Quite a simple use case. Create an include, embed into all of your layouts. Since you can access the containing page ($myPage), you can determine name and path of the displayed page. If you need some categorization, you should think about the usage of page variables. After you have gathered all relevant information, just print out the google analytics (or whatever tracker your are using) javascript code. Page caching will reduce your load for retrieving that information automatically.
Downloads (e.g. press releases)
Solution 1 (download teaser box):
Create a page component, which offers your editor the ability to select a document from mediabase and describe it.
Create a download page which determines the asset to be downloaded out of the request (e.g. download/xyz - xyz could be the id of the asset. Access request by $myRequest→get(“smartUID”)). That include cannot be cached, since it has to sender the appropriate download http headers. Assign the script to a page as preinclude (include must support that insertion, configurable in config mode!). The page itself doesn’t need a layout.
Solution 2 (more complex downloads):
If you have to provide download overviews, or if you have to print out more information about a download, you should create content object class for managing/editing the downloads and specific includes for displayments. You won’t benefit from page components then.
Job Offers
Typical use case for content class objects with includes for displaying (just like news and galleries).
You may additionally realize an include for an online application. If you do so, you should store the applications in an extra content object, meaning another class. When importing documents from the aspirant into the mediabase, you should import them into a non-world-accesible mediagroup ($myMB→setGroup()). You can realize that by creating a group and putting a fitting .htacces file into the corresponding root folder (media\x).
Guestbook
A guest book is more or less an extension of a contact form. Just write another include to display the records of the content object with the customer feedbacks. You can use the the status of a record ($myCO→status respectively dat_status in table content_data) to determine which entry should be displayed and which not, so you get a moderated guestbook.
Blog
To realize a blog, you should create content object classes for blog entries and comments. Furthermore you need includes for blog overview and blog detail view. If you integrate the blog into a surrounding website, you should write includes for “latest blog entries” and a “tag cloud”. Finally you should create a page without an layout and integrate an include for the RSS-Feed rendering.
Quite much stuff for a blog, why not use a specific open source blog solution like Wordpress? Well, you should in 95% of all blog projects! But if your needs are to specific to be integrated into standard blog, you should consider to do it on your own. Let’s suggest you’re doing a sport blog, and you want you entries to be related to matches and teams, you want to single out specific players and you want to sell content related tickets for future sport events. Nothing of that is a problem if your blog entry is a typical content object record. You just add new fields to manage the extra information and create additional content object classes for managing/editing teams, matches and player information. So your blog easily expands to a sport portal and you can create and code includes for team overviews (with all related blog entries), a “player of the month” features (with all related blog entries) and so on.
One final word for the tag cloud. Since the tag cloud needs to collect and weight information of all recent blog entries, the tag cloud calculation shouldn’t occur to often. You should use a non-permanent data-object for that, which is calculated on-demand and only once (until next editor change).
Forum
Well, a forum is a little bit like an extension of a blog. We did a forum with Phenotype, but that’s a border case, normally we wouldn’t recommend that. Requirements are to specific and fine specific solutions are available.
Shop
… same goes for shops, if they’re huge and complex payment processes are attached.
But if you consider a shop more like a big product catalog with an attached shopping basket, Phenotype does great.
You should create three content object classes:
- one for the product itself (and all additional information about it)
- one for orders
- one for customers
To present a product you could create a “product box” page component or you could write includes for (category based) product overviews and for the product detail view.
Furthermore you need an include for managing the shopping basket (adding products, removing products, entering customer data and so on) and maybe one for permanent displayment of the current shopping basket status.
The content of the basket itself should be stored in a default PHP-Session, or you can create a order content object record as soon, as the customer adds his first product.
Basically that’s all. Just as described for the blog, doing it on your own, gives you control of your application, and you can expand it as you wish. The utility of this approach really depends on the projects requirements.
Frontend Users
Phenotype doesn’t know fronted users. If you need frontend users, you should create a content object classe for managing/editing them.
You should apply specific user management processes (like locking them, resending password and so on) directly to the form of the content object (→form_button and →buttonPressed()).
Don’t forget to turn on session management, since the frontend doesn’t support sessions as a default (PT_FRONTENDSESSION =1 in _config.inc.php).
(News) Portal Site
If you have to manage lots of articles, you should not regard them as single pages. You should create an article content object class instead.
Usally such a website is organized in categories, like “news”,”sports”,”politics”,”business” and so on … Create a page for every category and provide page components to link to current news articles. For displayment of an article you need a separate page, that holds an article detail view include. This include must be set to “include caching”, to have it’s own caching depending on which article it displays.
That is basicly all to realize a portal site with Phenotype. Of course the article itself should have plenty possibilites like embedding videos, paragraphes, charts, tables and so on. Therefore Phenotype offers the ability to use page components within content object records (→form_sequence). That means, your editors can edit the content of an article, just like they would edit the content of a page. Additionally they can edit meta data, add resources on separate tabs, determine the category of an article. They don’t have to worry, about how the article is integrated into the portal, you code the fitting includes and use permalinks of the articles (→buildURL()) for nice SEO-urls.
One last hint: If you have to manage really many articles, create on abstract content object class and additionally inherative content object classes for different article types, so the backend is more clear.
Rate calculator
If you have to promote a rate base product (e.g. call rates, electricity or transportation services …) your website needs a rate calculator. With Phenotype you would create a reasonable content object class, one record would represent a rate. Additionaly you would create an include, that does the calculation based on the parameters of the appropriate rates. Just combine two Phenotype components to develop an editable rate calculator with no effort!
Site Search
You can do a fulltextsearch over all pages and all content object records. For pages use the field pag_fullsearch from table pages, for content records use the field dat_fullsearch from table content_data.
If you want to do a fulltext search on pages, you must implement the method →setFullSearch() for all your page components. The output of this method is aggregated into the field pag_fullsearch.
If you want to do a fulltext search on content records, you may implement the method →buildFullText() (not quite consistent …). If you don’t implement the method automatically the values of all properties of a record are combined into the field dat_fullsearch.
SEO
SEO optimization is basically a question of html design and elaborate linking. The Phenotype smarturls help you to realize good, readable URLs. Always use the linking helpers(url_for_page($pag_id)) to use them continuous.
You can change the title of a page from any include (e.g. $myPage→setTitle($myCO→get(“title”));) as long as you have the right title tag in your layout (<title>{$title|escape}</title>).
If you want to realize a Google Sitemap create a page, write a pagescript (an Include isn’t really necessary here). Select all relevant pages from table page and list em (with linking helpers). If you additionally want include dynamic urls, get all relevant records from content_data and use the permalink of those records (→getUrl() - if you implemented it), e.g. for displayment of news, job offers as explained above.
If you want to configure the priority within the backend, you could use page variables for that.
Content Syndication
If you want to integrate content from different sources, you may do that with specific page components or includes.
Since feeds may be unavailabe some time, you could think about an ajax solution. Create a page without an layout, that serves
the ajax request or use the print view of a page. Assuming you want to display news on your homepage, you would give your homepage a 24h caching. Your ajax serving
page only gets a 5 minute caching time, so you can easily balance the load and still be up-to-date. Consider the usage of smartActions insted of default include behavioural here.
If you have lot’s of external sources you may write an Phenotype Action and install a cronjob executing those action. The action could collect external content into data objects or create editable content records for you.
Content Integration
Last, but not least your job could be the integration of content managed with Phenotype into other websites/systems. You can use the XML view of Phenotype, which is an additionally front controller serving your whole application as XML. This controller keeps a session, so you can browse the website just as you would do in HTML view. Could be e.g. used for XSLT transformations.
Additionally Phenotype offers RSS feeds for all content classes. Adapt them by overwriting the related methods of PhenotypeContentStandard.
Hope this short descriptions helped you to understand the way, how Phenotype works. Of course it’s unlikely that you understood every detail… :), but I bet you realized, that it’s always a combination of page components, includes and content object classes. If you combine them in a smart way, you can realize many typical web application use cases in a very fast and convenient way. And they’re always editable/mangable from the beginning, because frontend and backend are tied together in Phenotype in a unique, productive way.
You think Phenotype Wiki/Documentation could be better?
We too. Please contribute: Edit this page
Recent Blog Posts
- Finally Multibyte - Phenotype 3.0
- Phenotype 2.9 explained
- Integration of PHPIDS (PHP-Intrusion Detection System)
- New Release: Phenotype 2.8 Ready for Download
- Restart: New Phenotype Website Live
- Phenotype worth: 2 Million $
- New Feature: Automatic Image Version Creation
- Additional smartURL variable: smartPATH