<?xml version="1.0"?>
<record><wiki id="wiki?page_id=61">
	<page_name>lookup</page_name>
	<page_id>61</page_id>
	<page_title>The Lookup Widget</page_title>
	<content>Return to [[widget:type]] page to see list of all widget types.
Back to [[fields.ini file]] to see other fields.ini directives.

[[toc]]

===Synopsis===

The lookup widget allows users to look a record from another table to insert into the field.  It is like a select widget except that it doesn&apos;t use a vocabulary.  Instead you just specify a table on which it should search using the widget:table directive.  In order to use the lookup widget to edit a field, you should set the [[widget:type]] directive of the [[fields.ini file]] for the field to &apos;&apos;&apos;lookup&apos;&apos;.  I.e.
&lt;code&gt;
[fieldname]
    widget:type=lookup
    widget:table=mytable
&lt;/code&gt;

&apos;&apos;&apos;Note that the lookup widget requires the [[widget:table]] directive to be set to the target table of the lookup or it will not work properly.&apos;&apos;&apos;

===Required Directives===

The following [[fields.ini file]] directives are required to accompany the field definition if a lookup widget is used:

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| widget:table
| The name of the table in which the lookup widget should look up related records.
| 1.0
|}


===Optional Directives===

The following additional optional directives may be used to customize the behaviour of the lookup widget:

{| class=&quot;listing listing2&quot;
|-
! Name
! Description
! Version
|-
| widget:filters:-limit
| Sets the number of records that are shown by default in the lookup widget.  Default is 30 if this is omitted. E.g.&lt;code&gt;widget:filters:-limit=100&lt;/code&gt; to show 100 records at a time.
| 1.0
|-
| widget:filters:-sort
| Specifies the columns to sort the results on. E.g. &lt;code&gt;widget:filters:-sort=category_name asc, year desc&lt;/code&gt;
| 1.0
|-
| widget:filters:*
| Any valid Xataface directive can be used to filter the results by specifying widget:filters:param  (where &quot;param&quot; is a valid Xataface GET parameter, which could include a column name to filter results on, or other filter directives). &lt;code&gt;widget:filters:country=Canada&lt;/code&gt; To only show results with Country=Canada.
| 1.0
|-
| widget:filters:*=$*
| Dynamic filters.  Causes the options in the record browser to be filtered on the value of another field in the form.  e.g. &lt;code&gt;widget:filters:country_id=&quot;$country_id&quot;&lt;/code&gt; would show only results with records having country_id matching the value of the &apos;country_id&apos; field in the current form.
| 1.3.1
|}

See [[URL Conventions]] for an overview of the types of GET parameters Xataface can take.  Any GET parameters that manipulate a query can be used with the widget:filters:* directive to modify the query results that are shown in the lookup widget.


===Example===

In this example we have a field named appointee that is supposed to reference the contacts table.  So in the [[fields.ini file]] we would have:

&lt;pre&gt;
[appointee]
    widget:type=lookup
    widget:table=contacts
&lt;/pre&gt;

Initially we just have a little find icon next to the field. If the user clicks it, a dialog pops up enabling them to search for the contact that they want:

[[Image:http://media.weblite.ca/files/photos/Picture%2023.png?max_width=640]]


===Additional Tips===

Although the lookup widget does not use a vocabulary as indicated in the Synopsis above, it is still useful to define a vocabulary in the fields.ini file for this field. The reason is because the lookup widget is only used with the edit action, where you are inserting or editing data into the field. However, it is not used to the display the data in the view or list actions. Therefore, you must still have a vocabulary defined to properly display these values.

In order to customize the display of the lookup widget&apos;s select list, you must edit the delegate class for the table which is referenced by the widget:table directive. There are two important points to note:

# The items in the selection list are formatted based on the getTitle(&amp;$record) delegate class function if it is defined. However, ...
# The Search box will search on text in VARCHAR and TEXT fields. If you need to search for data in numeric fields, you can create a grafted field using a function such as CONCAT() to display numbers as text.

Links:
* [http://xataface.com/forum/viewtopic.php?f=4&amp;t=6723 Lookup widget on view with compound primary key]</content>
	<keywords>lookup widget, widget:filters, widget:-filters:limit, widget:table</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=62">
	<page_name>Customizing_the_look_and_feel_of_a_row_or_a_cell</page_name>
	<page_id>62</page_id>
	<page_title>Customizing_the_look_and_feel_of_a_row_or_a_cell</page_title>
	<content>==How to customize the look and feel of elements in the list view==

===Create a method in a delegate class===

In the delegate class, the method &apos;&apos;css__tableRowClass&apos;&apos; is implemented, like in this example :

&lt;code&gt;class tables_journal_interventions {
function css__tableRowClass(&amp;$record){
    if ( !$record-&gt;val(&apos;fermeture&apos;)){
        return &apos;intervention_close&apos;;
    }
    else return &apos;&apos;;
} 
}
&lt;/code&gt;

Here the function tests a condition : is there a value in the field &apos;&apos;fermeture&apos;&apos; ?

===Add the class in a CSS stylesheet===

Now the class is created in a CSS stylesheet.

&lt;code&gt;td.intervention_close {
        background-color: #FFE6E6 !important;
    } &lt;/code&gt;

This is a class for each cell, the &lt;td&gt; tag. The &apos;&apos;!important&apos;&apos;  attribute is added to be sure that this information has precedence over all the others. It is better to add this class in a [http://xataface.com/documentation/how-to/custom_javascripts custom CSS stylesheet].

===Remarks===

Beware that some versions of IE don&apos;t respect the background-color property on the &lt;tr&gt; tag, so it is probably better to write:

&lt;code&gt;

    tr.intervention_close td {
        background-color: #FFE6E6;
    }&lt;/code&gt;

i.e. to apply the background color to the individual cells. </content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=63">
	<page_name>How_to_granulate_permissions_on_each_field</page_name>
	<page_id>63</page_id>
	<page_title>How_to_granulate_permissions_on_each_field</page_title>
	<content>==How to granulate permissions on each field==

To reach this aim, there is the method fieldname__permissions to place into the delegate class of the table. 

===Getting the role===

First it is necessary to know the user&apos;s role. For this, the method getUser() is added in the class :
&lt;code&gt;function getUser(&amp;$record){
  $auth =&amp; Dataface_AuthenticationTool::getInstance();
    $user =&amp; $auth-&gt;getLoggedInUser();
return $user;
}&lt;/code&gt;


===Setting up the permissions for each field===

Next, the permissions are built for each column or field where they are needed, like in this example where the method name is formed with the field name, followed by 2 underscores then by &apos;&apos;permissions&apos;&apos; :

&lt;code&gt;function fieldname__permissions(&amp;$record){

$the_user =$this-&gt;getUser($record);
$user=$the_user-&gt;val(&apos;identifiant&apos;);
if ( !$user) return Dataface_PermissionsTool::NO_ACCESS();

    if ( $user==&apos;demande&apos; ){
        return Dataface_PermissionsTool::ALL();
    } elseif ($user==&apos;admin&apos;){
 return Dataface_PermissionsTool::ALL();
}
else {
        return Dataface_PermissionsTool::READ_ONLY();
    }
}&lt;/code&gt;


=== Also See ===

* [[viewable_editable_fields]] - How to make a field editable for some users and only viewable for some other users  
* [[no_access_text]] - Replace the default NO ACCESS permission text with another text.
* [[__field__permissions]] - Returns the default permissions for a field of a given record.
* [[Delegate_class_methods#toc5|Permissions]] - other Delegate class methods</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=64">
	<page_name>How_to_authenticate_users_with_LDAP_or_Active_Directory</page_name>
	<page_id>64</page_id>
	<page_title>How_to_authenticate_users_with_LDAP_or_Active_Directory</page_title>
	<content>==How to authenticate users with LDAP or Active Directory==

</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=65">
	<page_name>LDAP_or_Active_Directory</page_name>
	<page_id>65</page_id>
	<page_title>How to authenticate users with LDAP or Active Directory</page_title>
	<content>[[toc]]

It is often easier to use the existing LDAP or Active Directory to authenticate users in Xataface than to create a new password for every user in the table users.

===In the conf.ini===

In the conf.ini file, in the [auth] part, you need to add your LDAP or AD configuration data :

&lt;code&gt;[_auth]
auth_type=ldap
users_table = xata_users
username_column = id
	ldap_host = &quot;xxx.xxx.xxx.xxx&quot;
	ldap_port = &quot;389&quot;
	ldap_base = &quot;OU=blabla,DC=blablabla&quot;&lt;/code&gt;

Here in the table users, you need the login but the password can be just &apos;&apos;PASS&apos;&apos;, because the password will be fetched into the LDAP base.
You need to add the [http://weblite.ca/svn/dataface/modules/Auth/ldap/trunk/ auth module] in the conf/modules directory.

===See Also===

* [[authentication]] - Overview of Authenthentication features in Xataface</content>
	<keywords>LDAP,Active Directory,Authentication</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=66">
	<page_name>table</page_name>
	<page_id>66</page_id>
	<page_title>table</page_title>
	<content>When using widget:type table, it will store the data as XML.

So the field type must be TEXT (or varchar... but text is better). You can decide which columns you want in the table by creating sub-fields in your fields.ini file as follows:

Suppose you want a column called &apos;name&apos; and a column called &apos;url&apos;

&lt;code&gt;
[myfield]
widget:type=table
[myfield:name]
[myfield:url]
&lt;/code&gt;

Now when you access the stored value using the Dataface API, the value of myfield will be stored as an array of associative arrays. e.g. 

&lt;code&gt;
foreach ( $record-&gt;val(&apos;myfield&apos;) as $vals){ echo $vals[&apos;name&apos;].&apos; -- &apos;.$vals[&apos;url&apos;]; }
&lt;/code&gt;</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=67">
	<page_name>grid</page_name>
	<page_id>67</page_id>
	<page_title>grid</page_title>
	<content>==widget:type = grid==

Suppose we have two tables, tbl_organisation and tbl_individuals, in the edit view for a record in the organisations table (tbl_organisations) we also want to be able to view and edit the individuals within this organisation we can use widget:type=grid

In the /tables/tbl_organisation/fields.ini we create a transient field by adding:

&lt;code&gt;
[Individuals]
widget:label = &quot;Individuals&quot;
transient=1
relationship=individuals
widget:type=grid
widget:columns=&quot;ind_firstname,ind_lastname,ind_tel&quot;
&lt;/code&gt;

The above assumes we have a relationship entry in our /tables/tbl_organisation/relationships.ini that looks like this:

&lt;code&gt;
[individuals]
__sql__ = &quot;SELECT * FROM tbl_individual WHERE org_id=&apos;$org_id&apos;&quot;
&lt;/code&gt;

The fields.ini will show the three columns shown in widget:columns from the table tbl_individual

Correct permissions need to be set to enable editing and deletion etc of these records.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=68">
	<page_name>relationship</page_name>
	<page_id>68</page_id>
	<page_title>The relationship fields.ini directive</page_title>
	<content>[[fields.ini file|Return to fields.ini file directives]]

[[toc]]

===Synopsis===

Certain types of widgets (e.g. grid (v1.0) and checkbox (v1.2)) support the relationship directive which allows them to effectively add/remove records from a specified relationship.  This directive only works with transient fields.

===Example 1: Checkboxes to add/remove categories===

(Note: This example requires Xataface 1.2 or higher to work)

Suppose we have a database that keeps track of courses and the branch of research that they belong to.  A course can be part of multiple branches.  We want to be able to select the branches that a particular course belongs to on the edit form for that course using checkboxes.

Table Structure:
&lt;code&gt;
courses:
   course_id : int (primary key)
   course_title : varchar

branches:
   branch_id : int (primary key)
   branch_name : varchar
   branch_description: text

course_branches:
   course_id : int
   branch_id : int
&lt;/code&gt;

Relationship definition:  (from the tables/courses/[[relationships.ini file]]):
&lt;code&gt;
[branches]
    course_branches.course_id=&quot;$course_id&quot;
    course_branches.branch_id=branches.branch_id
&lt;/code&gt;

Field definitions: (from tables/courses/[[fields.ini file]]):
&lt;code&gt;
[branches]
  transient=1
  relationship=branches
  widget:type=checkbox
&lt;/code&gt;

Things to notice:
# This is a many-to-many relationship (hence the need for the course_branches join table.
# The [branches] field is a transient field.
# The relationship directive from the [[fields.ini file]] references our branches relationship that was defined in the [[relationships.ini file]].
# You can call the field anything that you like.  There is no need for it to have the same name as the relationship.  It just turned out that way in this example.  

===Example 2: Using a grid widget===

Let&apos;s modify example 1 slightly to use a grid widget instead of checkboxes.  The grid widget will allow us edit the records in a relationship using dynamic table.  It automatically uses the correct widget for each column of the table according to the definition in the target table&apos;s [[fields.ini file]].  Most of the definition can remain the same.  We only change the [[fields.ini file]] directive:

&lt;code&gt;
[branches]
  transient=1
  relationship=branches
  widget:type=grid
  widget:columns=&quot;branch_name,branch_description&quot;
&lt;/code&gt;

In this case we are able to edit the branch name and description in each row of the grid.

===See Also===

* [[grid|The grid widget]]
* [[checkbox|The checkbox widget]]
* [[relationships.ini file|The relationships.ini file]]
* [[fields.ini file|The fields.ini file]]</content>
	<keywords>grid widget, relationship, checkbox</keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=69">
	<page_name>checkbox</page_name>
	<page_id>69</page_id>
	<page_title>checkbox</page_title>
	<content>==The checkbox widget==

In the [[fields.ini file]] you can specify a field to be edited using a checkbox widget by setting [[widget:type]] to [[checkbox]].  A checkbox widget can function in 2 different ways depending on the parameters that you assign to the field.

[[toc]]

===Example 1: A TinyInt (boolean) field===

Suppose our table has a tinyint field named &quot;Active&quot; which specifies whether the record is currently in use.  This field will store a value of either 0 or 1.  So we configure this field in our [[fields.ini]] file to use a checkbox widget as follows:

&lt;code&gt;
[Active]
  widget:type=checkbox
&lt;/code&gt;

Results:

[[Image:http://media.weblite.ca/files/photos/Picture%2024.png?max_width=640]]

===Example 2: A repeating field (multiple checkboxes for one field===

Checkboxes can store multiple values in a single field by setting the [[vocabulary]] directive and applying it to a varchar or text field.  In this case there will be one value saved per line.  

In this example, suppose we have a varchar field named &apos;&apos;&apos;categories&apos;&apos;&apos; which uses the &apos;&apos;&apos;categories&apos;&apos;&apos; [[valuelist]] to specify the different categories that can be checked at any given time.  Our [[valuelists.ini file]] might look like:
&lt;code&gt;
[categories]
    __sql__ = &quot;select id,name from categories&quot;
&lt;/code&gt;

And our [[fields.ini file]] looks like:
&lt;code&gt;
[categories]
    widget:type=checkbox
    vocabulary=categories
&lt;/code&gt;
* Note that you don&apos;t need to name the field the same as the valuelist.  It just worked out this way.

Now if we save a record with categories 1, 3, and 5 checked, then the categories column of our row in the database will store something like:
&lt;code&gt;
1
3
5
&lt;/code&gt;
i.e. one category id per line.  Note that using this method, your database will not be normalized because you are storing multiple values in a single field.  However in many applications this is sufficient.

Results:

[[Image:http://media.weblite.ca/files/photos/Picture%2025.png?max_width=640]]

===Example 3: Using a &quot;Categories&quot; relationship===

&quot;&quot;&quot;(Note: This example requires Xataface version 1.2 or higher)&quot;&quot;&quot;

Example 2 above shows how we can easily add and remove a record from multiple categories using checkboxes.  However it required multiple pieces of information to be stored in a single database field which may or may not be advantageous for your database design.  If you&apos;re looking for a more normalized database schema you would probably design your database as follows for this case:

# Books table - Stores all of the books.
# Categories table - Stores all of the categories
# Book_Categories table - Stores mapping of books to categories.

With out table structure we will first want to define a relationship from Books to Categories to reflect the connection between books and categories.  The [[relationships.ini file]] for this might look like:

&lt;code&gt;
[categories]
    Books.Book_ID=&quot;$Book_ID&quot;
    Book_Categories.Category_ID=Categories.Category_ID
&lt;/code&gt;

And our [[fields.ini file]] for the Books table might look like:
&lt;code&gt;
[categories]
    widget:type=checkbox
    transient=1
    relationship=categories
&lt;/code&gt;
* Note that there is no need for our field to be named the same as our relationship.  It just turned out this way.  Also note that we used the transient=1 flag here because the Books table no longer has a categories field in the database.  This field is defined purely for the benefit of the edit form so that we will get a checkbox group to select the book&apos;s categories.

Results:
[[Image:http://media.weblite.ca/files/photos/Picture%2025.png?max_width=640]]

==Related Parameters==

# [[vocabulary]] - Assigns a valuelist to be used as the options for this checkbox group.
# [[repeat]] - A boolean value indicating whether this field should be treated as a &apos;repeating field&apos;.  A repeating field is one with multiple checkboxes.  By default the checkbox widget operates as a single checkbox that controls a boolean value.
# [[relationship]] - (Only applicable to [[transient]] fields).  If the [[relationship]] directive is set then this field can be used to add/remove records from a relationship.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page>0</original_page>
</wiki>
<wiki id="wiki?page_id=70">
	<page_name>documentation_guide</page_name>
	<page_id>70</page_id>
	<page_title>Documentation Guide</page_title>
	<content>Xataface uses a wiki to manage its online documentation which can be edited by anyone.  All you have to do is [http://xataface.com/wiki/index.php?-action=login login with your forum username and password] ([http://xataface.com/forum/profile.php?mode=register register for the forum here]).  Then when you are browsing a page of the wiki, you&apos;ll see an &apos;Edit&apos; tab along the top.  Click on this tab to start editing the page in your browser.  Wiki markup is a little simpler than HTML and a little more complex than plain text.  It is easy to get a handle on once you get started.  If you aren&apos;t sure how to format it exactly how you want, don&apos;t worry.  Someone may come by after you and improve on your formatting.  That&apos;s what the community approach is all about.

==The Documentation Team==

Join the Xataface documentation team to help participate in the planning of the documentation.  If you want to help out, contact [mailto:steve@weblite.ca Steve Hannah] and he&apos;ll add you to the documentation group where you can access the private documentation forums and meet the rest of the team.

==Using the Wiki==

The following is a brief guide in using the Xataface Wiki.  All following instructions assume that you are already [http://xataface.com/wiki/index.php?-action=login logged in] to the wiki.  You can use your forum username and password to login.

===Editing an Existing Page===

# Navigate to the page that you want to edit
# Click on the &quot;Edit&quot; tab along the top.
# Make changes to your page.
# Save the changes.

===Adding a New Page===

====Method 1: Add a link from an existing page===

# Navigate to an existing page that you want to link to your new page.
# Click on the &quot;Edit&quot; tab along the top.
# Somewhere in the content of the page, add a link to your new page (which doesn&apos;t exist yet), by adding the following markup&lt;code&gt;
[[The name of your new page]]
&lt;/code&gt;
# Save your changes.
# Click on the &quot;view&quot; tab along the top and find the place where you added your link.  It should be displayed with a &apos;?&apos; right after it.  Click on the &apos;?&apos; and it will bring you to the &quot;new page form&quot;.
# fill in the form with your page contents and click save.

====Method 2: Accessing new page form directly====

# Access the [http://xataface.com/wiki/index.php?-action=new&amp;-table=wiki new page form] directly.


===Uploading Images===

Image can be uploaded at [http://media.weblite.ca The Web Lite Media Manager].  You&apos;ll need an account to access this site.  If you are a member of the documentation team you can request an account from [mailto:steve@weblite.ca Steve Hannah] so that you can upload images here.

Steps:

# Log into [http://media.weblite.ca the Web Lite Media Manager].
# Click on &quot;Add New File&quot; in the menu on the left.
# Select a name for the file, and browse to the image you want to upload in the file upload field.  You don&apos;t need to check any category boxes.  Press save.
# Click on the &quot;View&quot; tab for your newly uploaded image.
# Copy the embed code for the image from the &quot;Embed Code&quot; field.
# In the wiki page add the embed code where you want your image to appear as follows:&lt;code&gt;
[[Image:EMBED_CODE]]
&lt;/code&gt; Where EMBED_CODE is the URL for the image as you copied and pasted out of the media manager.
# Save your changes.

===Uploading Video===

===Adding Source Code Snippets===</content>
	<keywords>documentation wiki</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=71">
	<page_name>GettingStarted:Introduction</page_name>
	<page_id>71</page_id>
	<page_title>Introduction</page_title>
	<content>Web Lite is a simple framework for building data-driven web applications in PHP and MySQL. This section introduces some of the concepts and applications of Dataface.

To fully understand what Xataface is, we must first define a few key terms:

&apos;&apos;&apos;Framework&apos;&apos;&apos; - A set of software routines that provide a foundation structure for an application. Frameworks take the tedium out of writing an application from scratch. (From Answers.com)

&apos;&apos;&apos;Data-driven design&apos;&apos;&apos;- Designing an application around the data that it will store.

Xataface is a &apos;&apos;Framework&apos;&apos; in the sense that it is a set of classes and libraries that take the tedium out of writing web applications. It provides a simple web interface to a MySQL database enabling users to update, delete, and find data in the underlying database. The interface is targeted at secretaries and end-users as opposed to database administrators.

Xataface enables &apos;&apos;data-driven design&apos;&apos; because it allows developers to develop web sites by first designing the database that will be used to store the data on the website, and then design the pages used to display the data. The developer can focus on the data because he or she does not have to worry about having to build forms to update the data. If the requirements of the application change, the developer can simply add a field to the database table and all associated web forms will be updated automatically (because they are all dynamically generated using the database schema).


===Requirements===

* [http://php.net PHP] &gt;= 4.3
* [http://mysql.com MySQL] &gt;= 3.2.3

===Key Technologies===

* [http://pear.php.net PEAR class libraries] (HTML_QuickForm, etc...)
* [http://smarty.net Smarty Templating Engine]
* [http://plone.org Plone] Javascript and CSS style sheets

===Development Procedures===

# Identify the data that will need to be stored for a web site.
##[[Image:http://xataface.com/documentation/tutorial/getting_started/er-diagram.png]]
# Design the database using your favorite database administration program (e.g., PHPMyAdmin)
##[[Image:http://xataface.com/documentation/tutorial/getting_started/phpMyAdmin-1-small.gif]]
# Tell Xataface some DB connection info, and voila! You have an application:
##[[Image:http://xataface.com/documentation/tutorial/getting_started/new-record-form-1-small.gif]]

===Where to go from here===

This tutorial will teach you the basics of Xataface and how to construct a simple application using the Xataface. After reading this tutorial you will be ready to tackle some medium to large web sites with the help of the Xataface reference documentation. You are also encouraged to mail the [http://xataface.com/forum Xataface forum] if you have questions.</content>
	<keywords>introduction requirements getting started</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=72">
	<page_name>GettingStarted:Why_Use_Xataface</page_name>
	<page_id>72</page_id>
	<page_title>Why Use Xataface</page_title>
	<content>==Why Use Xataface?==

Some simple examples similar to those that are frequently encountered by web developers, and how dataface can be used to acheive a solution.
As a web services developer in the Faculty of Applied Sciences at Simon Fraser University, I am frequently getting requests to build websites that are manageable by the site owner. Most of these requests also specify certain types of content that must be stored on the website, and much of this content needs to be n-ary (i.e., there will be multiple instances of each type of content). Let me give you an example.

===Example 1: Website for Faculty of Widgetry===

The Faculty of Widgetry needs a website to publish information about its undergraduate programs. It is important for them to be able to publish admission requirements, and program overviews for each program. It is also important to have course outlines and timetables for each course. The Faculty of Widgetry has 12 undergraduate programs and over 100 courses offered.

====Solution 1: Static HTML====

To build this web site using only static HTML pages using Dreamweaver or some other HTML editor would require at least 112 pages to be created (one for each course and program). However, once we recognize that there are only 2 types of pages required (one for courses and one for programs), we can reduce the task down to creating 2 templates and filling in the main content for each program and course individually. Most HTML editors have some templating ability so you can make changes to the template and have the changes propogated to all pages that use that template with the click of a button.

This works great, but courses are added frequently, and outlines are changed. Do you really want to receive requests to update all of these pages every time there are changes to make? (If your answer is &apos;yes&apos;, then you probably won&apos;t be interested in reading the rest of this tutorial). Whether the Dean of the faculty knows it or not, it is very important for the program assistants to be able to update these web pages on their own. To acheive these goals you can:

* Install Dreamweaver on the Program Assistants&apos; computers, teach them how to use it, and allow them to perform updates.
* Install Contribute, which is a scaled down version of Dreamweaver to make it easier for the Program Assistants to edit the content.
* Use another solution that is equivalent to one of the above 2 solutions.

Installing Dreamweaver for each Program Assistant is a little overkill, and since it has the ability to do much more than just update content. In addition, Dreamweaver is really a developer&apos;s tool - not a secretary&apos;s tool, so it can be difficult to learn at first. The best reason NOT to install Dreamweaver on the Program Assistant&apos;s computer, however, is that it enables him/her to muck things up by accident (believe me, I has happened to me more times than I care to count).

Admittedly, Contribute is a viable option as it controls access to only certain portions of web pages to be edited, and it is targetted at secretaries (not developers) so it is easier to use. In fact, given the requirements for this web site (as stated above), this is a perfectly good solution. However you better hope that none of the following requirements are added:

* Each program web page should contain an up-to-date list of all of the courses required for the program, along with a link to the course outline for that course.
* Course outlines should be available in PDF format as well as HTML format.
* An index page showing all of the courses available should be added. This page must allow courses to be organized by program, course subject, or course number.
* Any other requirement that would have information formatted in more than one way.

If any of these requirements are likely to be added (EVER) then you would be well-advised to look into solutions that use a database back-end.

====Solution 2: Use a Content Management System (CMS)====

There are hundreds of content management systems available that will allow you to store and update content through the web (TTW). Some of them even have an assortment of add-ons that will allow you to store more specific types of information. Some good CMS&apos;s include Plone, Drupal, and Xoops. Suppose we want to develop the Faculty of Widgetry website using one of these CMS&apos;s. Any good CMS will allow you to create and edit HTML documents easily (without having to write any custom products). However, it is often the case that our documents require the content to be structured. For example, each program has some common data associated with it: Program Name, Admission Deadline, Program Description, Outline, Courses, etc... If we want to properly separate data from presentation, we would need to build a special content-type to store our programs. Most CMS&apos;s allow you to develop custom content-types using the underlying programming language and an API (Application Programming Interface). Some API&apos;s are easier to use than others and some are documented better than others. The common element is that each has its own proprietary interface for writing these add-ons.

If you are using a CMS and you are proficient in the creation of add-on content-types, then you will be able to build the Faculty of Widgetry website without great difficulty. However there are a number of reasons why you may choose NOT to use a CMS:

* Steep learning curve: Depending on the CMS it can be very time consuming and difficult to learn how to use and modify the CMS to suit you purposes.
* It is over-kill: Most CMS&apos;s are filled with features and modules that you will never need. In fact it can even be a pain to turn them off if you don&apos;t want them.
* You can get tied into the CMS: When you are using a CMS, you will start developing for the CMS. With all of your content in the CMS it may be difficult to migrate to a different solution later on. (The truth of this statement will vary for different CMS&apos;s). Choose your CMS carefully.

====Solution 3: Use an existing Application====

OK, OK, let&apos;s not get too carried away with trying to develop the website until we have checked the market to see if someone else has already done it better. Maybe there is already a PHP application that makes websites for Faculties easy. I mean, I can&apos;t be the first person that needed to build a website for a Faculty. In fact if you do a search or go to Hotscripts.com, you will probably find a handful of applications or scripts that almost do what you need. If you&apos;re lucky, maybe you can find an application that does exactly what you need (but frankly, I&apos;ve never been that lucky). If you find one, maybe it&apos;s worth taking it for a test drive. But beware. Using a system that almost does what you need but is difficult to modify to your needs can be worse than building it by scratch. Make sure that you are able to modify the application to suit your needs exactly.

====Solution 4: Use PHP and MySQL====

If all we want to do is separate the data from the presentation and allow the Program Assistants to update data on the website, why not just design a MySQL database with the appropriate tables and fields to store the required data. In our case we will need 2 tables:

&apos;&apos;&apos;Programs&apos;&apos;&apos;: 

* Fields:
** ProgramID : int
** ProgramName : varchar
** ProgramDescription: text
** AdmissionDeadline: date
** Outline_HTML : text
** Outline_PDF : blob


&apos;&apos;&apos;Courses&apos;&apos;&apos;:
* Fields:
** CourseID : int
** CourseSubject : varchar
** CourseTitle : varchar
** CourseNumber : int
** ProgramID : int
** CourseDescription : text
** Outline_HTML : text
** Outline_PDF : blob


Now it&apos;s easy to create a few web pages that extract data from the database and displays it as HTML. In fact if there is an existing page template that you can use for the header and footer, you can develop the entire Faculty website in under an hour (you just have to create 3 pages).

&apos;&apos;&apos;Question&apos;&apos;&apos;: How will the Program Assistants update the information in the database?

&apos;&apos;&apos;Answer&apos;&apos;&apos;: OK, let&apos;s assume that you&apos;re not going to teach them SQL and that a DB Admin tool will also be too difficult to learn. Then you have to create HTML forms to update records in the database.

Ouch! What was easy just became hard. Making HTML forms is a real pain, because you have to validate the input, deal with file uploads, and also make sure that everything is stored to the database OK without losing any information. Such a basic task, but it can be very difficult. This is when it is time to use Xataface.

====Solution 5: Use Xataface====

OK, this isn&apos;t really its own solution. It is more like &quot;Solution 4 Part II&quot;, because Xataface is intended to complement your custom application you built with solution 4, by providing an easy-to-use, configurable user interface that is targeted at secretaries and normal users (as opposed to database administrators). A Xataface application takes only seconds to set up and it will provide you with a full user interface for your users to edit information in the database.</content>
	<keywords>introduction motivation why</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=73">
	<page_name>GettingStarted:Installation</page_name>
	<page_id>73</page_id>
	<page_title>Installation</page_title>
	<content>==Installation==

Download and installation instructions for the Web Lite framework.
Xataface is a 100% PHP Framework that comes with all dependencies as part of the installation. The framework itself lives inside a single directory that should be placed inside the document root of your web server so that it can be accessed from the web. You can install a single copy of Xataface to be used by multiple applications on your web server. Each application just &quot;requires&quot; the key files from the Web Lite framework.

===Downloading===

# Go to the Xataface Sourceforge project file releases page
# Download the latest file release.

===Installing===

# Unpack the gzipped tar archive that you downloaded somewhere in your web server&apos;s document root (i.e., make sure that the &apos;dataface&apos; directory is in a web-accessible location).
# Make the dataface/Dataface/templates_c directory writable by the web server.  An unsafe way to do this is to 
 chmod 777 Dataface/templates_c
But it would be better to just give write access to the web server user.
# Confirm that the installation worked by pointing the web browser to http://yourdomain.com/path/to/dataface/dataface_info.php . If it worked OK, you should receive a web page that says &quot;Dataface is installed correctly&quot;, along with some basic instructions for creating a Xataface Application. (Note: Sometimes this page will give you a false positive. i.e., it may say the installation worked but then your Xataface application receives errors. Check the troubleshooting section below to deal with these issues).

===Troubleshooting===

If your installation is not going as planned, don&apos;t panic. There is a possiblity that your system has a slightly different configuration and you have to make some small adjustments to make the installation work.

The general procedure for troubleshooting the installation is as follows:

# Check the [[Troubleshooting]] page.
# Look through the [http://xataface.com/forum forum] to see if others have experienced the same thing.
# Post your question in the forum if you can&apos;t find the answer already.

</content>
	<keywords>installation troubleshooting downloading </keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=74">
	<page_name>GettingStarted:first_application</page_name>
	<page_id>74</page_id>
	<page_title>Creating your First Application</page_title>
	<content>==Creating Your First Application==

Build a simple Xataface application.

For our first Xataface application we will try to build a web site for Faculty of Widgetry (From the example in the &quot;Why Use Xataface&quot; page). The web site needs to store information about programs and courses. An entity-relationship diagram (ERD) for this website is included below:

[[Image:http://xataface.com/documentation/tutorial/getting_started/er-diagram.png]]

As the ERD shows, our database will need 2 tables (Course and Program). Our next step is to build this database. You can use any MySQL database administration tool to builld the database. My personal tool of choice is PHPMyAdmin.

===Step 1: Creating the database using PHPMyAdmin===

The following steps describe the procedure for creating this database using PHPMyAdmin.

# At the main menu of PHPMyAdmin, type &apos;FacultyOfWidgetry&apos; into the &apos;Create new database field&apos; as follows: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/new_database.gif]] &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;Then click &apos;Create&apos;.
# First we will create the &apos;Course&apos; table to hold course information. In the &apos;FacultyOfWidgetry&apos; page, fill in the &apos;Create new table text field as follows: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/create_table.gif]] &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt; Then click &apos;Go&apos;.
# This should bring up a form to specify the fields for the course table: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/course-table-def-small.gif]] &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt; Then click &quot;Save&quot;. The resulting SQL to create the Course table is as follows:&lt;code&gt;
CREATE TABLE `Course` (
 `CourseID` int(11) NOT NULL auto_increment,
 `ProgramID` int(11),
 `CourseTitle` varchar(64) NOT NULL default &apos;&apos;,
 `CourseDescription` text NOT NULL,
 `HTMLOutline` text NOT NULL,
 `PDFOutline` longblob NOT NULL,
 `PDFOutline_mimetype` varchar(64),
 `Subject` varchar(128) NOT NULL default &apos;&apos;,
 `CourseNumber` varchar(10) NOT NULL default &apos;&apos;,
 `Credits` int(5) NOT NULL default &apos;0&apos;,
 `LastModified` timestamp NOT NULL default CURRENT_TIMESTAMP,
 PRIMARY KEY (`CourseID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT=&apos;Store courses&apos; AUTO_INCREMENT=1 ;
&lt;/code&gt;
#In a similar fashion, create the Program table. The resulting SQL for this table is:&lt;code&gt;
CREATE TABLE `Program` (
 `ProgramID` int(11) NOT NULL auto_increment,
 `ProgramName` varchar(64) NOT NULL default &apos;&apos;,
 `ProgramDescription` text NOT NULL,
 `HTMLOutline` text NOT NULL,
 `PDFOutline` longblob NOT NULL,
 `PDFOutline_mimetype` varchar(32),
 `AdmissionDeadline` date NOT NULL default &apos;0000-00-00&apos;,
 `LastModified` timestamp NOT NULL default CURRENT_TIMESTAMP,
 PRIMARY KEY (`ProgramID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT=&apos;Academic Program&apos; AUTO_INCREMENT=1 ;
&lt;/code&gt;
# The database has been created with 2 tables: Program and Course. We can now move on to building the Xataface application.

===Step 2: Create Xataface Application===

Our Xataface application will provide a user-friendly front-end to our database. A basic application consists of a directory with a configuration file and an entry page (PHP file). Xataface comes with a PHP setup script (called makesite) to create the skeleton for your application. Alternatively you can set up the application manually.

Note: For the following instructions and examples, my Daface installation is located at /Users/shannah/Sites/dataface and the URL for the installation is http://localhost/~shannah/dataface.

====Method 1: Setting up application with the &apos;makesite&apos; script====

# From the command prompt, navigate to the dataface directory. (in my case &apos;&apos;/Users/shannah/Sites/dataface&apos;&apos;).
# This directory contains a file named &apos;makesite&apos;. It is a PHP script that can be used to build a website powered by Xataface. To find out the usage options for this script you can simply call the script with no parameters. E.g.,&lt;code&gt; 
stevepbook:~/Sites/dataface shannah$ ./makesite
&lt;/code&gt;
# This will give you usage instructions for the script as follows:&lt;code&gt;
makesite: invalid options entered.

 Usage: makesite &lt;site_path&gt; &lt;db_user&gt;:&lt;db_pass&gt;@&lt;db_host&gt;/&lt;db_name&gt; &lt;dataface_url&gt;
 or
 php makesite &lt;site_path&gt; &lt;db_user&gt;:&lt;db_pass&gt;@&lt;db_host&gt;/&lt;db_name&gt; &lt;dataface_url&gt;
 where 
 &lt;site_path&gt; = The path (absolute or relative) to your application directory.
 &lt;db_user&gt; = The MySQL username to connect to the database
 &lt;db_pass&gt; = The User&apos;s password to connect to the database
 &lt;db_host&gt; = The MySQL host name.
 &lt;db_name&gt; = The name of the mysql database for the application.
 &lt;dataface_url&gt; = The URL to the Xataface installation

 Examples:

 makesite ../FacultyOfWidgetry root:password@localhost/FacultyOfWidgetry /dataface

 The above command would create a site at ../FacultyOfWidgetry (i.e., the Faculty of 
 Widgetry directory in the parent directory. The database used for this site is 
 located at localhost, and the database name is FacultyOfWidgetry. The username
 to connect to the database is root and his password is password.
&lt;/code&gt;
# We create our FacultyOfWidgetry site using the following command:&lt;code&gt;
./makesite ../FacultyOfWidgetry \
    root@localhost/FacultyOfWidgetry \
    http://localhost/~shannah/dataface
&lt;/code&gt;
# This will create our application in the FacultyOfWidgetry folder if everything worked ok. The contents of the folder will look like: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/directory-structure-1.gif]]

You may be wondering what these files. Here is the short version (Read the next section &quot;Creating applications manually&quot; for more detailed information about the contents of these files.

The index.php file is the entry point for your application (i.e., you point the web browser at this file to use the application. 
The conf.ini file contains database connection settings and some other minor settings, like what should appear in the navigation menu.
The tables/Program (tables/Course) directory can contain configuration files specific to the Program (Course) table. More on that later. 

# Point your web browser to the FacultyOfWidgetry directory to see the application: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/basic-application-1.gif]]
#Your application is now created. It will enable you to add, edit, delete, and find records in either the Course table or the Program table. There will be more on the basics of using this application in the next section.	

====Method 2: Setting up application manually====

Using the makesite script as described above is the recommended way to set up an application because it saves time. However, it is very easy to set up the application manually. Just follow these steps:

# Create a directory for the application somewhere in your web site (preferably outside your xataface directory). We will call our directory &apos;FacultyOfWidgetry&apos;. ):&lt;code&gt;
mkdir FacultyOfWidgetry
&lt;/code&gt;
# Create a PHP file to serve as the access point for the application. Generally we will name this file &apos;index.php&apos;, but you can name it anything. Place the following contents in the index.php file:&lt;code&gt;
&lt;?
require_once &apos;/path/to/dataface/dataface-public-api.php&apos;;
df_init(__FILE__, &apos;http://yourdomain.com/dataface&apos;);
$app =&amp; Dataface_Application::getInstance();
$app-&gt;display();
&lt;/code&gt;&lt;nowiki&gt;&lt;p&gt;OK, I guess some explanations are in order.&lt;/p&gt;&lt;p&gt;
The first line imports the all of the public functions for dataface from the dataface-public-api.php file.&lt;/p&gt;&lt;p&gt;
The second line initializes the application for the current directory and specifies the URL to the dataface installation.&lt;/p&gt;&lt;p&gt;
The third line obtains an instance to the Application object - the core of your Dataface application.&lt;/p&gt;&lt;p&gt;
The fourth line simply displays the application.&lt;/p&gt;&lt;/nowiki&gt;
# Create a file named &apos;conf.ini&apos; to contain database connection information. Its contents should be:&lt;code&gt;
[_database]
	host = &quot;localhost&quot;
	user = &quot;dbuser&quot;
	password = &quot;secret&quot;
	name = &quot;FacultyOfWidgetry&quot;

[_tables]
	Course = &quot;Course&quot;
	Program = &quot;Program&quot;
&lt;/code&gt;&lt;nowiki&gt;&lt;p&gt;&lt;b&gt;Explanations:&lt;/b&gt;&lt;/p&gt;&lt;p&gt;There are 2 sections in this INI file: &apos;_database&apos;, and &apos;_tables&apos;.&lt;/p&gt;&lt;p&gt;
The &apos;_database&apos; section specifies the database connection information for the MySQL database.&lt;/p&gt;&lt;p&gt;
The &apos;_tables&apos; section specifies which tables will be included in the navigation menu for the application.&lt;/p&gt;&lt;/nowiki&gt;
# At this point, the application is functional. However there is one more thing that should be done for security reasons. The conf.ini file contains sensitive password information and should not be served to the web. We will create an .htaccess file to tell Apache NOT to serve this (or any) .ini file. The .htaccess file should contain:&lt;code&gt;
&lt;FilesMatch &quot;\.ini$&quot;&gt;
	Deny from all
&lt;/FilesMatch&gt;&lt;/code&gt;
# The directory structure of your application will now look like: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/basic-app-dir-structure-manual-1.gif]]&lt;nowiki&gt;&lt;p&gt;
Note, however, that there is also an .htaccess file that is hidden from this image.&lt;/p&gt;&lt;p&gt;You may be wondering why there is no &apos;tables&apos; directory like the directory structure that was generated by the makesite script. The &apos;tables&apos; directory is not required for the application to be functional. It will be required later on when we start to decorate the database.&lt;/p&gt;&lt;/nowiki&gt;
# The application is now ready to go. Point your web browser to the index.php file that you created. It will look like:&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/basic-application-1.gif]]

===Download source files===

[[File:http://xataface.com/documentation/tutorial/getting_started/facultyofwidgetry-4-tar.gz|Download the source files]] for this application at a tar.gz archive.
These files reflect the state of the application at this point of the tutorial. As later sections make changes to the application you will be able to download those versions also.</content>
	<keywords>htaccess first application installation</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=75">
	<page_name>GettingStarted:using_first_app</page_name>
	<page_id>75</page_id>
	<page_title>Using Your First Application</page_title>
	<content>==Using Your First Application==

A Web Lite application, at its core, provides 4 standard operations: Add new records, edit existing records, delete records, and find records. This section gives a brief overview of how to use your first Dataface application.
When you first create your Xataface application and there are no records in the database, the application will look quite plain. If you point your web browser to your newly created application it will look something like:

[[Image:http://xataface.com/documentation/tutorial/getting_started/basic-application-1.gif]]

You may be wondering why it says &quot;No records matched your request&quot; when you haven&apos;t even really made a request. This is because the &apos;default&apos; request that is performed if no other request is specified is to show the first record from the first table in the navigation menu. Since there are no records, it is true that there are NO records matching the default request.
So what can you do with this application anyways? Essentially there are 4 operations you will want to perform:

# Create new records
# Edit Existing records
# Find records
# Delete records

==Basic Navigation==

The navigation tabs (aka Navigation menu) at the top left represent the tables in your database. You can navigate to any of the tables in this list by clicking on that table:

[[Image:http://xataface.com/documentation/tutorial/getting_started/navmenu-1.gif]]

There are 3 &quot;views&quot; associated with tables in the database:

* &apos;&apos;&apos;Details&apos;&apos;&apos; - Shows the details of a single record in the table
* &apos;&apos;&apos;List&apos;&apos;&apos; - Shows the records in the current &quot;found set&quot; as a list. (in a table).
* &apos;&apos;&apos;Find&apos;&apos;&apos; - Allows users to find records matching certain criteria.

You can toggle between these 3 views using the tabs at the top of the page:

[[Image:http://xataface.com/documentation/tutorial/getting_started/basic-tabs-1.gif]]

===The &quot;Found Set&quot;===

Throughout this tutorial you will see the phrase &quot;found set&quot; an awful lot, so it is important to understand just what this means. A &quot;found set&quot; is the set of all records in the current table that match the current &quot;find criteria&quot;. This begs the question, &quot;what is &apos;find criteria&apos;?&quot;. By default there is no find criteria. When you perform a search or a find on the current table, you add &quot;find criteria&quot; so that only the records satisfying these criteria will be included in the &quot;found set&quot;.

For example, if you click on the &quot;find&quot; tab, you will get a search form that allows you to search for records that match certain criteria. The &quot;find&quot; tab for the &quot;Course&quot; table in our application looks like:

[[Image:http://xataface.com/documentation/tutorial/getting_started/find-form-1.gif]]

If you type in &quot;English&quot; in the &quot;Subject&quot; field and click &quot;Find&quot;, then the &quot;found set&quot; will consist of only records that contain the word &quot;English&quot; in their subject fields.

On the top left of the application window there will always be a &quot;Found&quot; line that indicates how many records are currently in the found set. e.g., 

This indicates that there are 256 records in the current table (which is the &apos;Groups&apos; table). There are currently only 225 records in the current &quot;found set&quot; (meaning that we have performed a &quot;find&quot; operation and it matched 225 of the records). It also indicates that the currently displayed record is record number 1 out of the 225 found records.

===The Actions Menu===

Just below the view tabs (&apos;details&apos;, &apos;list&apos;, and &apos;find&apos;) there are a few buttons that allow you to perform actions such as create new records, clear find parameters (i.e. Show All), and delete records.

[[Image:http://xataface.com/documentation/tutorial/getting_started/actions-menu-1.gif]]

&apos;&apos;&apos;Descriptions:&apos;&apos;&apos;

* &apos;&apos;&apos;new record&apos;&apos;&apos; - Creates a new record in the current table.
* &apos;&apos;&apos;show all&apos;&apos;&apos; - Clears all find criteria on current table so that all records are shown.
* &apos;&apos;&apos;delete&apos;&apos;&apos; - Deletes the current record in the table.
* &apos;&apos;&apos;delete found records&apos;&apos;&apos; - Deletes all records in the current &quot;found set&quot;. If no find criteria is specified this will delete all records in the table. 

===Creating new records===

The basic FacultyOfWidgetry application that we created in the previous section isn&apos;t very interesting when it doesn&apos;t contain any records, so let&apos;s create some Program records.

# Select the &quot;Program&quot; table by clicking on the &quot;Program&quot; option of the navigation menu.
# Click &quot;new record&quot; in the actions menu (top left).
# This will bring up a form to insert a new record that looks like: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/new-record-1.gif]]
# Fill in the form and click &quot;Save&quot;. If everything went OK, you will see the same form again, but with a &quot;success&quot; message at the top of the page: &lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/successfully-saved-1.gif]]

===Editing an existing record===

The &quot;details&quot; view allows you to view details or edit the current record. There should be at least 2 sub-tabs: &apos;View&apos; and &apos;Edit&apos;. If you click on the &apos;Edit&apos; tab, you will be presented with a form to edit the record. The form is identical to the &quot;create new record&quot; form.

===Deleting records===

If the &apos;list&apos; tab is selected, then you will see a button called &apos;delete found records&apos; in the actions menu (just below the view tabs). Alternatively if the &apos;details&apos; tab is selected, you will see a button called simply &apos;delete&apos;. 

[[Image:http://xataface.com/documentation/tutorial/getting_started/actions-menu-1.gif]]

Select &quot;delete&quot; to delete only the current record you are viewing in the &quot;details&quot; view.

Select &quot;delete found records&quot; to delete all of the records in the current found set. 

In either case, you will be prompted to confirm your decision before the records are actually deleted.

===Interface Overview===

Xataface applications provide an intuitive and consistent interface throughout. The following screenshot contains a map of some comment interface components along with some explanations:

[[Image:http://xataface.com/documentation/tutorial/getting_started/interface-schematic.png]]


Other topics
This short section is only intended to get you acquainted with the basics of Xataface applications. As your application becomes more complex with relationships and value-lists, there will be other usage scenarios of interest.</content>
	<keywords>&quot;find form&quot;,&quot;edit form&quot;,&quot;delete record&quot;,&quot;user interface&quot;,ui,template,look and feel</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=76">
	<page_name>GettingStarted:customizing</page_name>
	<page_id>76</page_id>
	<page_title>Customizing Field labels, descriptions, and widgets</page_title>
	<content>==Customizing Field labels, descriptions, and widgets==

Using simple INI configuration files, you can customize the look and feel of your application. You can change widgets, labels, field descriptions, and more.
In the previous 2 sections we learned how to create a simple application by desiging a database and then installing the basic directory structure to make our application operational. Now it is time to &quot;decorate&quot; the application a little bit. Decoration occurs by way of simple configuration files that are placed in strategic locations in the application. We can customize such things as:

* Widget types (e.g., use a select list for a field rather than a text field)
* Labels (e.g., The ProgramName field&apos;s label can say &quot;Program Name&quot; instead of just &quot;ProgramName&quot;)
* Field Descriptions . You can add descriptions to fields to help explain their meaning and how to use the application.
* HTML attributes. (e.g., Make a text field 50 characters wide)

===Table Configuration Directories===

You will recall, that when we used the &apos;makesite&apos; script to generate the directory structure for our web application, it created a directory named &apos;tables&apos;, with subdirectories named after each of the tables in our database. The directory structure of the application looked like:

[[Image:http://xataface.com/documentation/tutorial/getting_started/directory-structure-1.gif]]

The &apos;tables/Program&apos; and &apos;tables/Course&apos; are refered to as &quot;table configuration directories&quot; . All of the configuration files a table in a Xataface application are stored in its associated table configuration directory. For example all configuration files for the &apos;Program&apos; table are located in the &apos;tables/Program&apos; directory.

There are 4 main files that are generally contained in a table&apos;s configuration directory:

* &apos;&apos;&apos;fields.ini&apos;&apos;&apos; - Contains configuration for the fields of the table (e.g., field labels, descriptions, widget types, etc...)
* &apos;&apos;valuelists.ini&apos;&apos;&apos; - Contains value lists (vocabularies) that can be used in the table to limit input into certain fields like select lists.
* &apos;&apos;&apos;relationships.ini&apos;&apos;&apos; - Defines the relationships between this table and other tables in the application.
* &apos;&apos;&apos;&lt;TableName&gt;.php&apos;&apos;&apos; (where &lt;TableName&gt; is the name of the table. - A delegate PHP class that allows you to further customize the behavior of the application with respect to this table. May contain custom fields, importing/exporting functionality, permissions information, and more...

===Customizing Labels and Descriptions===

We will start off by adding custom labels and descriptions to the &apos;Program&apos; table of our &apos;FacultyOfWidgetry&apos; application. This sort of customization settings are placed in a file named &apos;fields.ini&apos; inside the table&apos;s configuration directory.

# Create the &apos;fields.ini&apos; file in the Program table configuration directory (i.e., tables/Programs/fields.ini).
# Add the following to this file:&lt;code&gt;
[ProgramName]
	widget:label = &quot;Program Name&quot;
	widget:description = &quot;Enter the name of the program&quot;
&lt;/code&gt;&lt;nowiki&gt;&lt;br&gt;&lt;/nowiki&gt;Now look at the &quot;Edit Record&quot; form in the Xataface application:

[[Image:http://xataface.com/documentation/tutorial/getting_started/program-name-label-1.gif]]


Notice how the label for the &quot;ProgramName&quot; now says &quot;Program Name&quot; (note the space between &quot;Program&quot; and &quot;Name&quot;). And its description matches the description specified in the fields.ini file.

The widget:label and widget:description attributes can be defined for any field in any table of the application.

===Using different widgets===

If no widgets are defined in the fields.ini file, a Xataface application will make a best guess at the type of widget that should be used to edit the value in a field. In general, the widgets used by default are as follows:

* VARCHAR, CHAR, INT : html text field
* DATE, DATETIME fields: calendar widget
* TEXT fields : html text area
* BLOB fields : html file upload field
* INT Fields with &quot;AUTO INCREMENT&quot; : html hidden field
* VARCHAR or CHAR fields with &quot;Password&quot; or &quot;password&quot; as part of the name : html password field
* ENUM fields : html select list
* SET fields : html checkbox group (not yet supported as of this writing).

You can change the widget that is used to edit a field by specifying a &quot;widget:type&quot; attribute for the field in the fields.ini file. For more information about the available widgets, see [[widget:type]].

====Example: Using HTML Editor to edit the HTMLOutline field====

Clearly the HTMLOutline field in the Program table is intended to store HTML content. By default our application only provides a text area to do the editing so the user is expected to enter the HTML markup by hand. It would be much better to provide the user with a WYSIWYG (What you see is what you get) HTML editor widget. That is exactly what we are going to do.
We will add a section to the fields.ini file so that it now looks like: &lt;code&gt;
[ProgramName]
	widget:label = &quot;Program Name&quot;
	widget:description = &quot;Enter the name of the program&quot;

[HTMLOutline]
	widget:type = &quot;htmlarea&quot;
&lt;/code&gt;

Now refresh the Xataface application in your web browser and look at the edit form for a record of the Program table:

[[Image:http://xataface.com/documentation/tutorial/getting_started/htmlarea-1.gif]]

As you can see, the HTMLOutline field now has an HTML Editor widget for editing. Most users will find this much nicer to work with than a normal text area. Xataface uses FCKEditor for its html editor widget.

There are a number of widgets that can be specified in the [[widget:type]] parameter:

* &apos;&apos;&apos;[[checkbox]]&apos;&apos;&apos; - An HTML checkbox (or checkbox group depending on context).
* &apos;&apos;&apos;[[date]]&apos;&apos;&apos; - Month/Day/Year select lists for selecting dates.
* &apos;&apos;&apos;[[calendar]]&apos;&apos;&apos; - A text field with a button that opens a small calendar widget when clicked.
* &apos;&apos;&apos;[[group]]&apos;&apos;&apos; - A complex widget type for editing multiple values as a group (useful for XML fields)
* &apos;&apos;&apos;[[hidden]]&apos;&apos;&apos; - a hidden field
* &apos;&apos;&apos;[[password]]&apos;&apos;&apos; - An HTML password widget
* &apos;&apos;&apos;[[select]]&apos;&apos;&apos; - An HTML select list (requires the &apos;vocabulary&apos; attribute)
* &apos;&apos;&apos;[[static]]&apos;&apos;&apos; - an uneditable field
* &apos;&apos;&apos;[[table]]&apos;&apos;&apos; - A complex widget type for editing multiple values in a tabular format (Useful for XML fields)
* &apos;&apos;&apos;[[text]]&apos;&apos;&apos; - an html text field
* &apos;&apos;&apos;[[textarea]]&apos;&apos;&apos; - an html text area

===Changing HTML attributes of widgets===

Sometimes you may want even finer grained control of your widgets&apos; appearance than to just specify the type, label, and desription. Perhaps you want to make a text field 50 characters wide, or to set the CSS class of the html element. This can be done using the &apos;widget:atts:&apos; parameter for a field. A short example is the easiest way to explain how this works.

Modify the fields.ini for the Program table so it looks like:&lt;code&gt;
[ProgramName]
widget:label = &quot;Program Name&quot;
widget:description = &quot;Enter the name of the program&quot;
widget:atts:size = 50
widget:atts:style = &quot;font-size: 24pt; font-family: Apple Chancery&quot;

[HTMLOutline]
widget:type = htmlarea
&lt;/code&gt;

We have added 2 lines:&lt;code&gt;
widget:atts:size = 50
widget:atts:style = &quot;font-size: 24pt; font-family: Apple Chancery&quot;
&lt;/code&gt;

What this does is add the html attributes size=&quot;50&quot; and style=&quot;font-size: 24pt; font-family: Apple Chancery&quot; to the html text field that is used to edit the ProgramName field.
Look at the results:

[[Image:http://xataface.com/documentation/tutorial/getting_started/widget-atts-1.gif]]

The HTML tag for the text field now looks like:&lt;code&gt;
&lt;input class=&quot;default&quot; id=&quot;ProgramName&quot; name=&quot;ProgramName&quot; 
	type=&quot;text&quot; size=&quot;50&quot; 
	style=&quot;font-size: 24pt; 
		font-family: Apple Chancery&quot; 
	value=&quot;Basic Widgetry&quot; 
/&gt;	
&lt;/code&gt;
In fact you can add arbitrary attributes to any of the fields using the same convention. Some useful examples are:

* &apos;&apos;&apos;[[widget:atts:rows]]&apos;&apos;&apos; for text areas to set the number of rows of text they should display.
* &apos;&apos;&apos;[[widget:atts:cols]]&apos;&apos;&apos; for text areas to set the number of columns (1 character = 1 column)
You can even use javascript calls in here if you like:
* &apos;&apos;&apos;[[widget:atts:onclick]]&apos;&apos;&apos; = &quot;doJsFunction();&quot;

===Download source files===

[http://xataface.com/documentation/tutorial/getting_started/facultyofwidgetry-6-tar.gz Download the source files] for this application as a tar.gz archive
These source files reflect the state of the application at the current point of the tutorial. As changes are made to the application in later sections, downloads of those versions are made available for download also.

===Summary===
In this section we learned how to change the labels, descriptions, and widgets for fields. We also learned how to add HTML attributes to the widgets to achieve very fine-grained control over the display of our forms.</content>
	<keywords>widget labels descriptions onclick handlers</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=77">
	<page_name>GettingStarted:valuelists</page_name>
	<page_id>77</page_id>
	<page_title>Using Valuelists</page_title>
	<content>==Using Value-lists==

Value-lists serve as vocabularies that can be used for fields such as select lists, checkbox groups, and auto-complete fields.

So far we have not used any enumerated fields such as select lists, checkbox groups, or auto-completion fields in our examples. This is because we are missing a key ingredient that is required by all of these widget types: a vocabulary. We need a way to define options for these fields.

This is where &apos;valuelists&apos; come into play. A valuelists is essentially a list of key-value pairs that can be used as a vocabulary in enumerated fields like checkbox groups, select lists, and auto-completion fields. Valuelists are defined in the valuelists.ini file in each table&apos;s configuration directory.

===Example 1: Use a select list for the Subject field in the Course table===

The &quot;Subject&quot; field in the &quot;Course&quot; table really shouldn&apos;t be a free-form field that will accept any value. The user should just be able to pick from a finite list of subjects in a select list. To make these changes we will follow these steps:

# Create the configuration directory for the &quot;Course&quot; table if it does not exist yet.
# Create a file named &apos;fields.ini&apos; inside the Course table&apos;s configuration directory (i.e., tables/Course/fields.ini), if it does not already exist.
# Create a file named &apos;valuelists.ini&apos; inside the Course table&apos;s configuration directory (i.e., tables/Course/valuelists.ini) if it does not already exist.
Your application directory structure should now look like:&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/application-structure-valuelists.gif]]
# Edit the valuelists.ini file so that it looks like:&lt;code&gt;
[Subjects]
	ENGL = English
	MATH = Math
	PHYS = Physics
	CHEM = Chemistry
&lt;/code&gt; This defines a valuelist named &apos;Subjects&apos; with values {ENGL, MATH, PHYS, CHEM} and associated labels {English, Math, Physics, Chemistry}. The values (i.e., ENGL, MATH, etc..) represent what will be stored in the database, and the values is a user-friendly representation that will be displayed on the screen.
# Now we edit the fields.ini file so that it looks like:&lt;code&gt;
[Subject]
	widget:type = select
	vocabulary = Subjects
&lt;/code&gt; This tells Xataface that we want to use a select widget to edit the &quot;Subject&quot; field, and its values should be drawn from the &quot;Subjects&quot; valuelist.
#Navigate to the &quot;Course&quot; table in our application and select &quot;new record&quot; from the &quot;Actions to be performed menu&quot; in the top left.&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/actions-menu-1.gif]]&lt;nowiki&gt;&lt;br/&gt;&lt;br/&gt;&lt;/nowiki&gt;This will bring up a form to create a new Course record, so that we can see what the form looks like. It should look like:&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/new-course-form-1.gif]]&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;Notice that the &quot;Subject&quot; field is represented by a select widget, its options are as follows:&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/course-subject-pulldown-1.gif]]&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt; And if you look at the HTML source code for this select list, it would look like:&lt;code&gt;
&lt;select class=&quot;default&quot; id=&quot;Subject&quot; name=&quot;Subject&quot;&gt;
	&lt;option value=&quot;&quot;&gt;Please Select...&lt;/option&gt;
	&lt;option value=&quot;ENGL&quot;&gt;English&lt;/option&gt;
	&lt;option value=&quot;MATH&quot;&gt;Math&lt;/option&gt;
	&lt;option value=&quot;PHYS&quot;&gt;Physics&lt;/option&gt;
	&lt;option value=&quot;CHEM&quot;&gt;Chemistry&lt;/option&gt;
&lt;/select&gt;
&lt;/code&gt;

===Example 2: Using a checkbox group for the &apos;Subject&apos; field===

In Example 1, we showed how to use a select list for the &apos;Subject&apos; field in the &apos;Course&apos; table. This is great if each course can only be one subject. But what if a course can be categorized in 2 subject areas. Then we will need a widget the allows you to select multiple items. Checkbox groups work well for this.
Make a change to the &apos;fields.ini&apos; file for the &apos;Course&apos; table to change the widget:type attribute of the &apos;Subject&apos; field to &apos;checkbox&apos; as follows:&lt;code&gt;
[Subject]
widget:type = checkbox
vocabulary = Subjects
&lt;/code&gt;

Now load the form again and notice that the &apos;Subject&apos; field is now represented by checkboxes.

[[Image:http://xataface.com/documentation/tutorial/getting_started/checkbox-group-1.gif]]

You may be wondering how we store multiple values in a single field. In this case Subject is treated as a &apos;repeat&apos; field where each value is on a separate line. I.e., with the form above, if we clicked &apos;save&apos; and checked the values stored in the database we would see:&lt;code&gt;
PHYS
CHEM
&lt;/code&gt;

As the value in the &apos;Subject&apos; field. Please note that if you are going to use a repeating field like this, you should make sure that the field is &apos;big&apos; enough to store all of the values. E.g., I think my Subject field was a VARCHAR(64) (64 characters long), so the sum of the lengths of all of the values &apos;checked&apos; for &apos;Subject&apos; should be less than 64.

===Example 3: Dynamic Valuelists based on the results of SQL queries===

Example 1 &amp; 2 demonstrated the basic idea of valuelists and how they can be used as values for select lists and checkbox groups. However defining valuelists &quot;statically&quot; inside the valuelists.ini file doesn&apos;t really seem to offer anything over using and ENUM or SET field in the MySQL database. In many cases we want the user to be able to choose from a number of options that are pulled from the database. For example, we may want the user to be able to specify the Program that a Course belongs to, using a pull-down list.

Recall that when we created the &apos;Course&apos; table we included a field named &apos;ProgramID&apos; to store the ID number of the Program that this course belongs to. It would be unreasonable to expect the users of your application to remember the ID number of the Program to which the course belongs when they are filling in the &apos;Course&apos; form. It would be much better if the user could choose the program from a list of available programs. Fortunately, this functionality is simple to add:

# Add a valuelist named &apos;Programs&apos; to the valuelists.ini file for the &apos;Course&apos; table as follows:&lt;code&gt;
[Programs]
	__sql__ = &quot;SELECT ProgramID, ProgramName FROM Program ORDER BY ProgramName&quot;
&lt;/code&gt; &apos;&apos;&apos;Note: Make sure you use two underscores on either side of &apos;sql&apos; in the above example. It should be &apos;__sql__&apos; not &apos;_sql_&apos;.&apos;&apos;&apos;&lt;nowiki&gt;&lt;p&gt;&lt;/nowiki&gt;This valuelist will be a list of the records in the &apos;Program&apos; table in alphabetical order on the program name. Note that this query selects 2 columns. The first column is always taken to be the ID column of the value-list and the 2nd column (if specified) is the Name column of the valuelist. The ID column is what will actually be stored in the database, and the Name column is what will be shown to the user in place of the ID.&lt;nowiki&gt;&lt;/p&gt;&lt;/nowiki&gt;
# Add a field definition for the ProgramID field in the fields.ini file of the &apos;Course&apos; table as follows:&lt;code&gt;
[ProgramID]
	widget:type = select
	vocabulary = Programs
&lt;/code&gt;

Now we can load up our form and see what it looks like:

[[Image:http://xataface.com/documentation/tutorial/getting_started/programid-select-list.gif]]

We can see that the ProgramID field now appears with a select list of all of the programs in the database. The HTML code for the select list is:&lt;code&gt;
&lt;select class=&quot;default&quot; id=&quot;ProgramID&quot; name=&quot;ProgramID&quot;&gt;
	&lt;option value=&quot;&quot;&gt;Please Select...&lt;/option&gt;
	&lt;option value=&quot;2&quot;&gt;Advanced Widgetry&lt;/option&gt;
	&lt;option value=&quot;1&quot;&gt;Basic Widgetry&lt;/option&gt;
	&lt;option value=&quot;3&quot;&gt;International Widgetry&lt;/option&gt;
&lt;/select&gt;&lt;/code&gt;

===Download Source Files===

[http://xataface.com/documentation/tutorial/getting_started/facultyofwidgetry-7-tar.gz Download application source files as tar.gz archive]

These source files reflect the application&apos;s state at this point in the tutorial. As changes are made to the application in later sections, modified source archives will be available to be downloaded.

===Summary===

In this section, we have learned how to use valuelists to add selection lists and checkbox groups to our web forms. We also shows how valuelists can be dynamically defined using SQL. Using valuelists in this way is like defining a many-to-one relationship to our database (in example 3, it was many &apos;Course&apos; records to one &apos;Program&apos; record). In the next section we will learn how to add many-to-many and one-to-many relationships to our database in such a way that records can be easily added and removed from relationships using Xataface.</content>
	<keywords>valuelists, __sql__, select lists, checkbox options,checkbox groups,vocabularies</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=78">
	<page_name>GettingStarted:relationships</page_name>
	<page_id>78</page_id>
	<page_title>Relationships</page_title>
	<content>==Relationships==

Xataface allows you to define relationships between tables using the relationships.ini file.

Xataface applications without relationships between tables can be quite boring. In our FacultyOfWidgetry application, we have implicitly defined a relationship between the Program table and the Course table by adding a ProgramID field to the Course table. In the previous section we saw how to configure this relationship from the context of a &apos;Course&apos; by adding a select list to the Course table form to select the Program that the Course belongs to.

From the &apos;Program&apos; side it is a little bit more complicated. There are no fields in the &apos;Program&apos; table that can be edited to add a &apos;Course&apos; to the list of courses in a &apos;Program&apos;, and it would be highly inconvenient to have to edit a &apos;Course&apos; record in order to add the course to a &apos;Program&apos;. What we want is a sort of &apos;Add Course&apos; button to add a course to a &apos;Program&apos;. 

===Concepts, Definitions, and Terminology===

Before we can delve into examples, it will help to go over some of the concepts and terminology involved in relationships using Xataface. Xataface relationships are always defined in a one-way fashion from the point of view of one table. For example, if you define a one-to-many relationship from the &apos;Program&apos; table to the &apos;Course&apos; table, the mirror (many-to-one) relationship from &apos;Course&apos; to &apos;Program&apos; is not automatically created. This method of defining relationships allows us to unambiguously refer to the source and destination tables of a relationship.

&apos;&apos;&apos;Definition 1:&apos;&apos;&apos; The &apos;&apos;source table&apos;&apos; of a relationship is the table on which a relationship is defined. For example if we define a relationship named &apos;Courses&apos; on the &apos;Program&apos; table to associate courses in a given program, then the &apos;Program&apos; table would be considered the source table of the relationship, and the &apos;Course&apos; table would be a destination table of the relationship.

&apos;&apos;&apos;Definition 2:&apos;&apos;&apos; The &apos;&apos;destination table&apos;&apos; of a relationship a table from which related records are selected.

There may be multiple destination tables in a given relationship but only one source table. If there are multiple destination tables, then one of these tables is designated as the domain table and the remaining destination tables are called join tables. 

&apos;&apos;&apos;Definition 3:&apos;&apos;&apos; A &apos;&apos;domain table&apos;&apos; is a destination table which stores the object of the relationship. For example if we define a many-to-many relationship between the &apos;Program&apos; table and the &apos;Course&apos; table, (i.e., each program can contain multiple courses and each course can be part of multiple programs), then we would need to add a join table to map &apos;Course&apos; records to &apos;Program&apos; records. Let&apos;s call this table &apos;ProgramCourses&apos;. Each record of the &apos;ProgramCourses&apos; table would contain a 2 fields: a &apos;ProgramID&apos; field (to reference the program) and a &apos;CourseID&apos; field to reference the course. If we define the relationship from the point of view of a &apos;Program&apos; then the &apos;Program&apos; table would be the source table, the &apos;ProgramCourses&apos; table would be the join table, and the &apos;Course&apos; table would be the domain table.

Don&apos;t worry if these definitions and terms aren&apos;t clear at this point. Use this section as a reference for when you run across the terms later in the tutorial.

===Defining a relationship===

To define a relationship in Xataface, all you need to do is tell Xataface how to select the related records using SQL. Xataface will be able to figure out how to add/remove records to the relationship from this information. This information is defined inside a the &apos;relationships.ini&apos; file inside the configuration folder for the table.

====Example 1: Adding a &apos;Courses&apos; relationship to the &apos;Program&apos; table====

We want to be able to associate multiple courses with each program. We do this by defining a relationship on the &apos;Program&apos; table as follows:

# Add a file named &apos;relationships.ini&apos; to the &apos;Program&apos; table&apos;s configuration folder (i.e., tables/Program/relationships.ini). Your application&apos;s directory structure should now look like:&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/directory-structure-relationships.gif]]&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;Notice, in particular the addition of the &apos;relationships.ini&apos; file in the &apos;Program&apos; directory.
# Add the following to the &apos;relationships.ini&apos; file:&lt;code&gt;
[Courses]
	Course.ProgramID = &quot;$ProgramID&quot;
&lt;/code&gt;	

This little snippet defines a relationship named &apos;Courses&apos; on the &apos;Program&apos; table. &apos;Program&apos; is the source table. &apos;Course&apos; is the destination table. There are no join tables because this is only a one-to-many relationship. You may be wondering what the $ProgramID means. This is a variable that represents the value of the &apos;ProgramID&apos; field in the source record. This relationship specifies that courses whose &apos;ProgramID&apos; field matches the value of the &apos;ProgramID&apos; field in the source record, are related to the source record. The english language makes this seem more difficult and complex than it really is.

Let&apos;s check out our changes. Since we have defined the relationship on the &apos;Program&apos; table, we will click on the &apos;Program&apos; link in the navigation menu:
[[Image:http://xataface.com/documentation/tutorial/getting_started/course-relationship-defined-1.gif]]

Notice that there is now a &apos;course&apos; tab at the top of the page. Click on this tab to see the courses that are related to this Program (as defined by our &apos;Courses&apos; relationship). If it says that &quot;No records matched the request&quot; or something to that effect, then you don&apos;t have any Course records in the relationship yet. Just click the &quot;Add New Courses Record&quot; button in the upper left to add a course. If there are courses in the relationship, then the Courses tab will look something like:

[[Image:http://xataface.com/documentation/tutorial/getting_started/courses-related-records.gif]]

Currently there is only one course in the program, but we can add more. If you click on the &quot;Add New Courses&quot; button in the upper left, you will be presented with a new course form that will allow you to add a new course in this Program.

===Example 2: Making the &apos;Courses&apos; relationship a Many-to-Many relationship===

Example 1 shows how Xataface can handle a one-to-many relationship. Now we will alter the database a little bit and turn this into a many-to-many relationship.

# Add a table named &apos;ProgramCourses&apos; to the database. The SQL table definition for this table should be something like:&lt;code&gt;
CREATE  TABLE  `ProgramCourses` (
	`ProgramID` INT( 11  )  NOT  NULL ,
	`CourseID` INT( 11  )  NOT  NULL ,
	PRIMARY  KEY (  `ProgramID` ,  `CourseID`  ) 
	) 
&lt;/code&gt;&lt;nowiki&gt;&lt;p&gt;Note that it is important for ALL of your tables to have Primary keys. If a table is missing its primary keys, some strange behavior may occur with relationships involving that table.&lt;/p&gt;
&lt;p&gt;
The above defined table will serve as a join table between &apos;Program&apos; and &apos;Course&apos;
&lt;/p&gt;&lt;/nowiki&gt;
# Since this is now going to be a many-to-many relationship, we no longer need the &apos;ProgramID&apos; field in the &apos;Course&apos; table. (Do not confuse this with the ProgramID field in the &apos;Program&apos; table. That field is important and needed.). Before removing this field, we will transfer the information across so that the existing relationships are maintained. The following SQL query will effectively all of the old one-to-many relationships into equivalent many-to-many relationships:&lt;code&gt;
INSERT  INTO ProgramCourses( ProgramID, CourseID ) 
	SELECT ProgramID, CourseID
	FROM Course
&lt;/code&gt;&lt;nowiki&gt;&lt;p&gt;	
And now we can remove the &apos;ProgramID&apos; field from the &apos;Course&apos; table.
ALTER  TABLE  Course  DROP  ProgramID&lt;/p&gt;&lt;/nowiki&gt;
# Finally, we will need to modify the relationship definition in the relationships.ini file of the &apos;Program&apos; table:&lt;code&gt;
[Courses]
	Course.CourseID = ProgramCourses.CourseID
	ProgramCourses.ProgramID = &quot;$ProgramID&quot; 
&lt;/code&gt;&lt;nowiki&gt;&lt;p&gt;
This means that all courses for which a (ProgramID, CourseID) pair matches the CourseID of the course and the ProgramID of the source Program record are included in the relationship.&lt;/p&gt;&lt;/nowiki&gt;
# Now we can check our application for changes. Go to the &apos;Program&apos; table in your application (using your web browser) and click on the &apos;courses&apos; tab once again:&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://xataface.com/documentation/tutorial/getting_started/multi-relationship.gif]]&lt;nowiki&gt;
&lt;p&gt;
This looks almost the same as before. Notice, however that now there is an &quot;Add Existing Courses Record&quot; button at the top. This is because with a many-to-many relationship, you are able to add related records in 2 ways:&lt;/p&gt;&lt;/nowiki&gt;
## Adding a completely new record that did not exist before.
## Selecting a record that already exists and adding it to the relationship.

===Example 3: Defining Relationships using SQL===

The previous examples used a simple INI file syntax to define relationships. However, some people may be more comfortable defining their relationships using SQL. This is also possible. Let&apos;s look at the relationships.ini file from example 1:&lt;code&gt;
[Courses]
	Course.ProgramID = &quot;$ProgramID&quot;
&lt;/code&gt;

This also could have been defined as follows:&lt;code&gt;
[Courses]
	__sql__ = &quot;SELECT * FROM Course WHERE ProgramID=&apos;$ProgramID&apos;&quot;
&lt;/code&gt;

&apos;&apos;&apos;Note: Make sure you use two underscores on either side of &apos;sql&apos; in the above example. It should be &apos;__sql__&apos; not &apos;_sql_&apos;.&apos;&apos;&apos;

The two syntaxes are equivalent. In fact, the former will be converted into the later by Xataface behind the scenes.

Now let&apos;s look at example 2&apos;s relationships.ini file:&lt;code&gt;
[Courses]
	Course.CourseID = ProgramCourses.CourseID
	ProgramCourses.ProgramID = &quot;$ProgramID&quot; 
&lt;/code&gt;

This could have been written as:&lt;code&gt;
[Courses]
	__sql__ = &quot;SELECT * 
		FROM ProgramCourses, Course 
		WHERE Course.CourseID = ProgramCourses.CourseID 
		AND ProgramCourses.ProgramID = &apos;$ProgramID&apos;&quot;
&lt;/code&gt;

The two are equivalent. This example, however, shows how defining a relationship using SQL can be beneficial. The above SQL query will work but it can be done better using Joins as follows:&lt;code&gt;
[Courses]
	__sql__ = &quot;SELECT * 
		FROM ProgramCourses pc 
		INNER JOIN Course c ON pc.CourseID = c.CourseID 
		WHERE pc.ProgramID = &apos;$ProgramID&apos;&quot;
&lt;/code&gt;

All of these 3 methods will produce the same results, but the last one will probably give a little bit better performance.

===Relationship Restrictions===

Xataface has built-in logic to figure out how to add new and existing records to relationships that you define, as long as your relationships obey a few guidelines.

# All tables must have a Primary key
# The WHERE clause of your SQL definition for the relationship must contain only &apos;=&apos; comparisons, and &apos;AND&apos; conjunctions. i.e., it cannot receive an &apos;OR&apos; conjunction, nor can comparisons be done using &apos;&gt;&apos;, or &apos;&lt;&apos;. This is because given &apos;AND&apos; and &apos;=&apos; conjunctions it is easy for Xataface to be able to add records that will satisfy the relationship. If an &apos;OR&apos; conjunction is used, it makes it ambiguous (though this will probably be corrected in future Xataface releases.

===Download Source Files===

[http://xataface.com/documentation/tutorial/getting_started/facultyofwidgetry-8-tar.gz Download the source files for this application as a tar.gz archive]</content>
	<keywords>relationships</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=79">
	<page_name>GettingStarted:validation</page_name>
	<page_id>79</page_id>
	<page_title>Form Validation</page_title>
	<content>==Form Validation==

Xataface allows you to add validation rules to fields using the fields.ini file
A common requirement for forms is to have some validation rules. Here are some example validation rules:

* The Username field is required.
* The Username must be between 6 and 16 characters long.
* The password must have at least one letter and one digit.
* The Email field must contain a valid email address.

There is no end to the types of things that you will need to validate. Xataface takes care of most of this for you with both client-side (javascript) and server-side validation. All you have to do is define some validation rules in the fields.ini file.

===Example 1: Make &apos;Username&apos; a required field===
&lt;code&gt;
[Username]
	validators:required = true
	validators:required:message = &quot;Username is required&quot;
&lt;/code&gt;

Placing the above inside the fields.ini file will cause the Username field to be a required field.

===Example 2: Username must be between 6 and 16 characters long===

For this rule we will use a regular expression.
&lt;code&gt;
[Username]
	validators:regex = &quot;/^.{6,16}$/&quot;
	validators:regex:message = &quot;Username must be between 6 and 16 characters long&quot;
&lt;/code&gt;

===Example 3: Email field must contain a valid email address===

&lt;code&gt;
[Email]
	validators:email = true
	validators:regex:message = &quot;Email must contain a valid email address&quot;
&lt;/code&gt;

===Available validation rules===

Xataface uses the PEAR library HTML_Quickform for validation, so any of the validators available in this package will be available in Xataface. Some of the available validation rules include:

* required
* maxlength
* rangelength
* regex
* email
* emailorblank
* lettersonly
* alphanumeric
* numeric
* nopunctuation
* nonzero

===Default validation rules===

There are certain validation rules that are automatically applied to fields of with certain characteristics. For example, any field designated NOT NULL in the SQL table definition will automatically be a &apos;required&apos; field. At the time of this writing, that is the only &apos;default&apos; validation rule applied, but more may be added in the future if their addition makes sense.

</content>
	<keywords>form validation,required field,validation rules</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=80">
	<page_name>GettingStarted:delegate_classes</page_name>
	<page_id>80</page_id>
	<page_title>Delegate Classes</page_title>
	<content>==Delegate Classes==

Use Delegate classes to add permissions, custom serialization, display filters, calculated fields, import/export functionality, and other custom functionality to your application.

For many applications, the configuration files provide sufficient to make them fit the requirements. However, in some cases you may feel the need to &quot;extend&quot; or &quot;bend&quot; your application even more. For these situations, there are delegate classes.

===What is a delegate class?===

A delegate class is a PHP class that defines custom behavior, functions, and fields for a table in a Xataface application. A table may have only 1 delegate class.

What kinds of things can a delegate class do?

* Define permission rules for tables, records, and relationships.
* Define calculated fields.
* Define custom serialization/deserialization of fields (useful for XML storage)
* Define custom event handlers (actions to be performed when certain events take place)
* Define import / export filters.
* Define custom titles for records
* more ...

===How to create a delegate class===

I will describe the creation process with an example. 

Referring back to our FacultyOfWidgetry application, let&apos;s add a delegate class for the &apos;Program&apos; table. This is done as follows:

# Create a file named &apos;Program.php&apos; in the Program table configuration directory (i.e., &apos;tables/Program/Program.php). Your application directory structure should now look like:&lt;nowiki&gt;&lt;br/&gt;&lt;/nowiki&gt;[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/delegate-class-fs-1.gif]]
# Add the following contents to your newly created &apos;Program.php&apos; file:&lt;code&gt;&lt;?
class tables_Program {}
&lt;/code&gt;&lt;nowiki&gt;&lt;p&gt;
In other words, you are creating a class named &apos;tables_Program&apos;. The above delegate class doesn&apos;t do anything yet, but it is a start.
The fun part doesn&apos;t start until you start defining methods in your delegate class. There are prescribed interfaces that you will need to implement to make this work.&lt;/p&gt;&lt;/nowiki&gt;


===Example 1: Creating a custom title for records===
The &quot;Title&quot; of a record is a string that represents the record. It is used by Xataface in the navigation controller (forward and back buttons) and in the &quot;Jump&quot; menu as well as various places around the interface for referring to that record. As an example, take a look at this partial screen shot of the &apos;details&apos; tab in a Xataface application.

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/getTitle-1.gif]]

I have circled the parts of the interface that use a record&apos;s title in some way. (1), (2), and (4) show the title of the current record and (3) shows the title of the next record in the found set. You will notice that the title is just the value of the first field in the Program record. In fact, the way that Xataface generates titles is by selecting the first VARCHAR or CHAR field in the table to be the Title for records of that table. In the above example this seems like a good choice, but it may not always be what you want.

We can use our delegate class to customize the way that these titles are generated. By defining a method named getTitle(), we can customize the way that titles are generated. Let&apos;s add such a method to our delegate class as follows:
&lt;code&gt;
&lt;?
class tables_Program {

	function getTitle(&amp;$record){
		return $record-&gt;val(&apos;ProgramName&apos;).&apos; Program&apos;;
	}
}
&lt;/code&gt;

OK, you are probably wondering what this $record object is. The $record object is a Dataface_Record object that represents a record of the &apos;Program&apos; table (if you want to take a look at the source code for this class it can be found in the &apos;Dataface/Record.php&apos; file). This object allows you to access all of the information about the record so that you can generate a title for the record. 

The &apos;val&apos; method simply returns the value of a field in the record.
In the above example, we are telling Xataface that the title of all records of the &apos;Program&apos; table is the value of the ProgramName field with the string &apos;Program&apos; appended to it. For example, if the ProgramName of a record was &apos;Foo&apos;, then its title woud be &apos;Foo Program&apos;.

Lets take a look at our application now to see the changes that we have made.

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/getTitle-2.gif]]

Notice that the (1) now has &apos;Program&apos; appended to the end of the title, but (2) and (3) do not. This is because (2) and (3) are part of the result controller (for navigating through results in the table) and it needs to be able to load hundreds of record titles at a time, but the getTitle() method requires that the entire record be loaded into memory for it to work which would be unfeasible when we need the title of hundreds of records. The result controller titles can also be customized, however, using the titleColumn() method, which simply returns the name of the column that should be used as the title. It can also return MySQL clauses that are equivalent to a column name (e.g., CONCAT(&apos;FirstName&apos;, &apos; &apos;, &apos;LastName&apos;) would be valid).

Okay, let&apos;s add a titleColumn() method to our delegate class so that we can customize the way our records are represented in the result controller:

&lt;code&gt;
&lt;?
class tables_Program {

	function getTitle(&amp;$record){
		return $record-&gt;val(&apos;ProgramName&apos;).&apos; Program&apos;;
	}
	
	function titleColumn(){
		return &apos;AdmissionDeadline&apos;;
	}
}
&lt;/code&gt;


All that the titleColumn method does is return the name of a column to be used as the title for records of the &apos;Program&apos; table. In this case, we making the &apos;AdmissionDeadline&apos; field the title column which results in the result controller looking like this:

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/titleColumn-1.gif]]


This was a simple example, but it is possible to do more with the titleColumn() method than just specify the name of a column. Any valid MySQL calculation that can be placed in a SELECT list can be returned here. For example, we can make use of the MySQL &apos;CONCAT&apos; function to append the string &apos;Program&apos; to the &apos;ProgramName&apos; field and achieve the same results as our previous getTitle() method:

&lt;code&gt;
&lt;?
class tables_Program {

	function getTitle(&amp;$record){
		return $record-&gt;val(&apos;ProgramName&apos;).&apos; Program&apos;;
	}
	
	function titleColumn(){
		return &quot;CONCAT(ProgramName, &apos; Program&apos;)&quot;;
	}
}

&lt;/code&gt;

And now we can see the changes in our application:

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/titleColumn-2.gif]]

It may seem a little bit inconvenient to have to define 2 methods to effectively customize the title of a record. Future versions may attempt to address this issue so that one or the other can be implemented, but for now, both methods must be implemented to effectively customize the title. In addition, future versions will likely add the &apos;titleColumn&apos; functionality to an INI file since it is more or less static.

===Summary===

In this section we learned how to add a delegate class to our tables to customize the behavior of our applications. Delegate class become more important when you need very fine-grained customizations to your application, as you will see in later sections. One important feature of delegate classes is the ability to add security permissions to tables and records to limit who can view, edit, and delete certain records. This will be covered in the next section.

</content>
	<keywords>delegate classes,getTitle,getPermissions</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=81">
	<page_name>GettingStarted:triggers</page_name>
	<page_id>81</page_id>
	<page_title>Triggers</page_title>
	<content>==Triggers==

Triggers are methods that can be defined to carry out custom behaviors when certain events occur in the application (e.g., when records are saved, inserted, or deleted).

Triggers are generally regarded as one of the more advanced features of database applications. Despite the &quot;advanced&quot; status of triggers, however, they are very simple to use and can be leveraged by Xataface developers to add powerful functionality to their applications.

So what can you do with a trigger?

* Send a confirmation email every time a new record is inserted into a table.
* Delete records related to a record that is being deleted (to maintain the consistency of the database).
* Add custom logging functionality.
* Add extra permissions or validation rules (although these are probably better handled with the validation framework).

You can really do just about anything you want with a trigger. A trigger is essentially just a custom PHP method that is called by Xataface when certain events occur.

===What triggers are available?===

As of version 0.5.3 Xataface supports the following triggers:

* &apos;&apos;&apos;beforeSave&apos;&apos;&apos; : called just before a record is saved (either inserted or updated).
* &apos;&apos;&apos;afterSave&apos;&apos;&apos; : called just after a record is saved (either inserted or updated).
* &apos;&apos;&apos;beforeInsert&apos;&apos;&apos; : called just before a record is inserted.
* &apos;&apos;&apos;afterInsert&apos;&apos;&apos; : called just after a record is inserted.
* &apos;&apos;&apos;beforeUpdate&apos;&apos;&apos; : called just before a record is updated.
* &apos;&apos;&apos;afterUpdate&apos;&apos;&apos; : called just after a record is updated.
* &apos;&apos;&apos;beforeDelete&apos;&apos;&apos; : called just before a record is deleted.
* &apos;&apos;&apos;afterDelete&apos;&apos;&apos; : called just after a record is deleted.
* &apos;&apos;&apos;beforeAddRelatedRecord&apos;&apos;&apos; : called just before a related record (new or existing) is added to a relationship.
* &apos;&apos;&apos;afterAddRelatedRecord&apos;&apos;&apos; : called just after a related record (new or existing) is added to a relationship.
* &apos;&apos;&apos;beforeAddNewRelatedRecord&apos;&apos;&apos; : called just before a new related record is added.
* &apos;&apos;&apos;afterAddNewRelatedRecord&apos;&apos;&apos; : called just after a new related record is added.
* &apos;&apos;&apos;beforeAddExistingRelatedRecord&apos;&apos;&apos; : called just before an existing related record is added.
* &apos;&apos;&apos;afterAddExistingRelatedRecord&apos;&apos;&apos; : called just after an existing related record is added.

===How do you define a trigger?===

Triggers are always defined as methods of the delegate class for a table. As an example, suppose we wanted to add a trigger to send a the administrator a notification email every time a new record is inserted into the &apos;Course&apos; table. The steps would be as follows:

# Create a delegate class for the &apos;Course&apos; table (if one does not already exist) by creating a file named &apos;Course.php&apos; inside the &apos;tables/Course&apos; directory.
# Add the following to the Delegate class file to make it a valid delegate class:&lt;code&gt;&lt;?
class tables_Course {}
&lt;/code&gt;
# Okay, we want our trigger to be called every time a record is inserted. There are 2 possible triggers that can be defined, then:&lt;nowiki&gt;
&lt;ul&gt;
&lt;li&gt;beforeInsert&lt;/li&gt;
&lt;li&gt;afterInsert&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this case it is probably more appropriate to define the afterInsert trigger because we really only want to send the notification email after the insert has successfully taken place. Therefore, we will define the afterInsert() method in our delegate class as follows:&lt;/p&gt;
&lt;/nowiki&gt;&lt;code&gt;
&lt;?
class tables_Course {
	....
    /**
     * Trigger that is called after Course record is inserted.
     * @param $record Dataface_Record object that has just been inserted.
     */
    function afterInsert(&amp;$record){
        mail(&apos;admin_email@yourdomain.com&apos;,&apos;Subject Line&apos;, &apos;Message body&apos;); 
    }
}
&lt;/code&gt;
# That&apos;s all for now. The afterInsert() method defined above will automatically be called every time a record is inserted into the Course table. This method, as we have defined it, will send a notification email to the administrator email.

===Sending feedback to the user===

The above example sends the email without any feedback to the application&apos;s user of whether the email succeeded or not. When the user inserts a new Course he will only see that the record was succesfully saved, but no mention is made of the email. The following example does the same thing as the previous one, except that it sends a confirmation to the user when the email has been successfully sent:
&lt;code&gt;
function afterInsert(&amp;$record){
    $response =&amp; Dataface_Application::getResponse();
        // get reference to response array

    if ( mail(&apos;shannah@sfu.ca&apos;, &apos;Subject Line&apos;, &apos;Message Body&apos;) ){
        $response[&apos;--msg&apos;] .= &quot;\nEmail sent to shannah@sfu.ca successfully.&quot;;
    } else {
        $response[&apos;--msg&apos;] .= &quot;\nMail could not be sent at this time.&quot;;
    }
}
&lt;/code&gt;

Now, when the user inserts a new record he will see a confirmation as follows:

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/trigger-after-insert-confirm.gif]]

Notice that we used the Dataface_Application::getResponse() function to obtain a reference to the application&apos;s response array. The response array is just a global array that is shared by the entire application that allows you to pass information easily from one part of the application to another. The &apos;--msg&apos; index of array is where you can place text that you wish to have displayed to the user as a confirmation.

&apos;&apos;&apos;Note&apos;&apos;&apos;: It is important to use &apos;=&amp;&apos; to assign the result of Dataface::getResponse() and not just &apos;=&apos;. e.g.:
&lt;code&gt;
$response =&amp; Dataface_Application::getResponse(); // correct!
$response = Dataface_Application::getResponse(); // WRONG!!
&lt;/code&gt;

This is because we need a reference to the response array, not a copy. That way when we assign a value to the &apos;--msg&apos; index it is applied to the actual response array and not a copy of it.

===Handling Errors===

The above method of sending messages to the user is useful for notifications and confirmations. However, in some cases you want to inform the user that an error occurred and cancel further operations. For example you may want to disallow a record to be inserted if a confirmation email cannot be sent. In this case we define the beforeInsert() trigger and return a PEAR_Error object if the email fails as follows:
&lt;code&gt;
&lt;?
class tables_Course {
    function beforeInsert(&amp;$record){
        $response =&amp; Dataface_Application::getResponse();
        if ( mail(&apos;shannah@sfu.ca&apos;, &apos;Notification&apos;, &apos;Your record was created&apos;)){
            $response[&apos;--msg&apos;] .= &quot;\nEmail sent successfully to shannah@sfu.ca&quot;;
        } else {
            return PEAR::raiseError(
                &quot;Errors occurred while sending email.  Record could not be inserted&quot;,
                 DATAFACE_E_NOTICE
            );
        }
    }
     
}
&lt;/code&gt;

This trigger is called just before a course record is inserted into the database. If the mail succeeds, then the user sees a success message. If it fails, on the other hand, the insert is cancelled, and the user will see a message as follows:

[[Image:http://framework.weblite.ca/documentation/tutorial/getting_started/trigger-error.gif]]


&apos;&apos;&apos;Note&apos;&apos;&apos;: Notice the use of the DATAFACE_E_NOTICE constant as a second parameter for PEAR::raiseError(). This is important as without it Xataface will display a less user-friendly error message complete with stack trace. If the error is such that you want a complete stack trace, you can use the DATAFACE_E_ERROR constant instead.</content>
	<keywords>triggers, beforeSave, afterSave, beforeInsert, afterInsert,sending email</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=82">
	<page_name>Creating_Printable_Reports</page_name>
	<page_id>82</page_id>
	<page_title>Creating a Custom Printable Report</page_title>
	<content>==Creating a Printable Report==

[[toc]]

It is often useful to provide your users with a printable report that is generated from your database.  Although Xataface doesn&apos;t include an explicit reporting module to allow the end users to create their own reports, you (the developer) can still quite easily produce a report by creating a custom action.  

This report will be subject to the user&apos;s sorting and searching preferences.  E.g. if the user searches for only books about &quot;frogs&quot;, then when he clicks on your printable report it will only display those records that match the query (i.e. only books about frogs).

===Requirements for our report===

# Report will be run against the &quot;products&quot; table (using the WebAuction application).
# Report should be accessible by clicking an icon in the top right of the list view (i.e. the resultlist actions).
# Report should display the product ID, product name, photo, and description.  One product per page.


===Adding the Icon to our Application===

We&apos;ll start out by finding an appropriate icon to use for our action.  There are loads of free icons that you can download (please observe and respect the license agreement of any icon library that you use).  Two good free icon libraries include:

# [http://www.famfamfam.com/lab/icons/silk/ FamFamFam Silk Icons]
# [http://tango.freedesktop.org/Tango_Icon_Library Tango Icon Library]

Once you have found the icon you want to use, just upload it somewhere inside your application&apos;s directory.  It might be a good idea to create a directory to store your images if you haven&apos;t already.  An appropriate name might by &apos;&apos;images&apos;&apos;.  For this example, we&apos;ll use the [[Image:http://dev.weblite.ca/phpimageserver/photos/icons/printer.png]] icon from the FamFamFam icon library.  So we upload this icon to
 %APPLICATION_PATH%/images/printer.png

Next we need to create an entry in our application&apos;s [[actions.ini file]] so that Xataface knows about our action, and where we want its icon to be displayed.  We&apos;ll start out with a basic definition that just specifies the icon for the action, and the &apos;&apos;category&apos;&apos; of the action.

&lt;code&gt;
[printable_report]
    icon=&quot;{$site_url}/images/printer.png&quot;
    category=result_list_actions
    description=&quot;See this product list in a printable format&quot;
&lt;/code&gt;

The &apos;&apos;result_list_actions&apos;&apos; category setting means that the icon for our action will be included along with the result list actions, which are located in the top right corner in the list tab.  Now if we reload our application and look at the &quot;list&quot; tab, you&apos;ll see that the icon group in the top right now includes our icon:

[[Image:http://media.weblite.ca/files/photos/Picture%20-5.png?max_width=640]]

If you don&apos;t see this icon, but see the text &quot;printable_report&quot; instead, then you have entered an incorrect path to the icon in the &apos;&apos;icon&apos;&apos; directive.  If you don&apos;t see an icon at all or any text, then your &apos;&apos;category&apos;&apos; directive may be incorrect.  Check that it is exactly &quot;result_list_actions&quot;.

If you mouse over your icon you&apos;ll see the text that you specified as your &apos;&apos;description&apos;&apos; directive for the action:

[[Image:http://media.weblite.ca/files/photos/Picture%20-6.png?max_width=640]]

You&apos;ll notice, if you try to click on your icon, that nothing happens.  This is because we haven&apos;t yet specified a URL for your action.  We&apos;ll wait to specify our URL, until we&apos;ve built the back-end of our action (i.e. the actual report).

===Creating the Actual Report===

Most reports involve the following pieces:

# Fetch the found set of records from the database.
# Loop through the found set and output some information about each record.
# Optionally use a template to integrate the report into your application&apos;s look and feel.

All reports will be placed in the framework of a custom Xataface action.  In our case we add a file to our application &apos;&apos;actions&apos;&apos; directory named after our action:
 %APPLICATION_PATH%/actions/printable_report.php

with the following contents:

&lt;code&gt;
&lt;?php
class actions_printable_report {
    function handle(&amp;$params){
    	echo &quot;Hello world!!!&quot;;
    }
}
&lt;/code&gt;

Please note the following about this snippet:

# The action was placed in a file &apos;&apos;actions/printable_report.php&apos;&apos; because the action is named &apos;&apos;printable_report&apos;&apos; (referring to our definition in the &apos;&apos;[[actions.ini file]]&apos;&apos;.  If the action was named &apos;&apos;foo&apos;&apos;, then we would place our action in file &apos;&apos;actions/foo.php&apos;&apos;.
# The &apos;&apos;printable_report.php&apos;&apos; file contains a single class named &apos;&apos;actions_printable_report&apos;&apos; after the name of the action.
# The action class contains a single method &apos;&apos;handle&apos;&apos; which handles the request for the action (i.e. outputs the report the way we like).  This method must exist and me named exactly &apos;&apos;handle&apos;&apos;.
# The &apos;&apos;handle&apos;&apos; method takes a single &apos;&apos;&amp;$params&apos;&apos; parameter which contains some parameters that may be passed to the action.  We won&apos;t be dealing with these in this example.


Before proceeding, let&apos;s try accessing our action just to make sure that we&apos;re on the right track.  Point your browser to 
 http://example.com/yourapplication/index.php?-action=printable_report

Note that you don&apos;t point our web browser directly to your action php file (in the &apos;&apos;actions&apos;&apos; directory.  Rather you point it to your application&apos;s entry point (index.php file), and specify the action via the &apos;&apos;-action&apos;&apos; GET parameter.  Your web browser should display something like:

[[Image:http://media.weblite.ca/files/photos/Picture%204.png?max_width=640]]

If you get a blank white screen, then you should check your error log to see where the error is occuring.  See [[Troubleshooting]] for general Xataface troubleshooting strategies in this case.

Now that we have all of the formalities out of the way, we can proceed to meat of our report.

====Retrieving the Found Set====

Let&apos;s build onto our action now.  First we will load the found set of records as follows:

&lt;code&gt;
&lt;?php
class actions_printable_report {
    function handle(&amp;$params){
    	$app =&amp; Dataface_Application::getInstance();
    	$query =&amp; $app-&gt;getQuery();
    	
    	if ( $query[&apos;-table&apos;] != &apos;products&apos; ){
    		return PEAR::raiseError(&apos;This action can only be called on the Products table.&apos;);
    	}
    	
    	$products = df_get_records_array(&apos;products&apos;, $query);
    	
    }
}
&lt;/code&gt;

Things to note in this snippet:

# We start be loading a reference to the &apos;&apos;Dataface_Application&apos;&apos; object.
# We then use the &apos;&apos;Dataface_Application&apos;&apos; object to load the current query.  This is essentially an associative array of all of the GET parameters, but with some guaranteed attributes such as &apos;&apos;-table&apos;&apos; and &apos;&apos;-action&apos;&apos;.
# In our particular action we are designing it to only work for the &apos;&apos;products&apos;&apos; table so we do a check on the query parameters to make sure that this is the case.  If someone tries to run this action from outside the products table (e.g. if -action=foo) then an error will be displayed.
# We use the df_get_records_array() function to return all matching records on the products table.  It returns an array of [[Dataface_Record]] objects.


====Overriding -skip and -limit====

Xataface allows the user to specify the number of records to display and the position in the found set to start from by adding the &apos;&apos;-skip&apos;&apos; and &apos;&apos;-limit&apos;&apos; GET parameters to a request.  If these are omitted, then default values of 0 and 30 are used respectively.  You may notice that if you click &quot;Next&quot; in list view, you see &apos;-skip&apos; and &apos;-limit&apos; parameters automatically added to the URL.

&apos;&apos;df_get_records_array&apos;&apos; respects the -limit and -skip parameters that are specified in the query.  I.e. if -skip and -limit are omitted it will return only the first 30 records from the found set.  If -skip=1 and -limit=10 then it will return 10 records starting from the 2nd record (2nd becuase -skip=0 would point to the first record).  This may be desired behavior for your report, but in some reports you may want to print off the entire found set.  If this is the case, you will want to explicitly set the -skip and -limit parameters in the &apos;&apos;$query&apos;&apos; array before passing it to &apos;&apos;df_get_records_array&apos;&apos;.  E.g.:

&lt;code&gt;
$query =&amp; $app-&gt;getQuery();
$query[&apos;-skip&apos;] = 0;
$query[&apos;-limit&apos;] = 10000;
$products = df_get_records_array(&apos;products&apos;, $query);
&lt;/code&gt;


====Looping through and Printing Product Info====

Now comes the fun part.  We&apos;re just going to loop through our found set and print off the product information:

&lt;code&gt;


foreach ($products as $p){
	

	echo &apos;&lt;table&gt;&apos;
		.&apos;&lt;tr&gt;&lt;th&gt;Product ID&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_id&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
		.&apos;&lt;tr&gt;&lt;th&gt;Product Name&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_name&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
		.&apos;&lt;tr&gt;&lt;th&gt;Description&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_description&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
		.&apos;&lt;tr&gt;&lt;th&gt;Photo&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_image&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
		.&apos;&lt;/table&gt;&apos;;
}

&lt;/code&gt;


The entire action at this point will look like:

&lt;code&gt;

&lt;?php
class actions_printable_report {
    function handle(&amp;$params){
    	$app =&amp; Dataface_Application::getInstance();
    	$query =&amp; $app-&gt;getQuery();
    	$query[&apos;-skip&apos;] = 0;
		$query[&apos;-limit&apos;] = 10000;
		
    	if ( $query[&apos;-table&apos;] != &apos;products&apos; ){
    		return PEAR::raiseError(&apos;This action can only be called on the Products table.&apos;);
    	}
    	
    	$products = df_get_records_array(&apos;products&apos;, $query);
    	foreach ($products as $p){
	

			echo &apos;&lt;table&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Product ID&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_id&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Product Name&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_name&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Description&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_description&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Photo&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_image&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;/table&gt;&apos;;
		}
    	
    }
}
&lt;/code&gt;

Now we refresh our action in the web browser, or point the browser again to:
 http://example.com/yourapplication/index.php?-action=printable_report&amp;-table=products
 
It should display something like:

[[Image:http://media.weblite.ca/files/photos/Picture%205.png?max_width=640]]

If you get a blank white screen, please check out the [[Troubleshooting]] section for general Xataface troubleshooting strategies.

====Adding a Little Style====

It is a good idea to at least provide the proper HTML HEAD and BODY tags for your report.  And to help make things a little nicer looking we&apos;re going to add some CSS styles to:

# Make the table field labels vertically aligned to the top.
# Change the font to helvetica.

This is easy to do with simple echo statements:

&lt;code&gt;
echo &apos;&lt;html&gt;&lt;head&gt;&apos;
	.&apos;&lt;title&gt;Printable Report&lt;/title&gt;&apos;
	.&apos;&lt;style type=&quot;text/css&quot;&gt;&apos;
	.&apos;	th { vertical-align: top}&apos;
	.&apos;&lt;/style&gt;&apos;
	.&apos;&lt;/head&gt;&apos;
	.&apos;&lt;body&gt;&apos;;
	
	//...
	


&lt;/code&gt;

So our finished action looks like:


&lt;code&gt;
&lt;?php
class actions_printable_report {
    function handle(&amp;$params){
    	$app =&amp; Dataface_Application::getInstance();
    	$query =&amp; $app-&gt;getQuery();
    	$query[&apos;-skip&apos;] = 0;
		$query[&apos;-limit&apos;] = 10000;
		
    	if ( $query[&apos;-table&apos;] != &apos;products&apos; ){
    		return PEAR::raiseError(&apos;This action can only be called on the Products table.&apos;);
    	}
    	
    	$products = df_get_records_array(&apos;products&apos;, $query);
    	
    	
    	
    	echo &apos;&lt;html&gt;&lt;head&gt;&apos;
			.&apos;&lt;title&gt;Printable Report&lt;/title&gt;&apos;
			.&apos;&lt;style type=&quot;text/css&quot;&gt;&apos;
			.&apos;	th { vertical-align: top}&apos;
			.&apos;&lt;/style&gt;&apos;
			.&apos;&lt;/head&gt;&apos;
			.&apos;&lt;body&gt;&apos;;
    	foreach ($products as $p){
	

			echo &apos;&lt;table&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Product ID&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_id&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Product Name&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_name&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Description&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_description&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;tr&gt;&lt;th&gt;Photo&lt;/th&gt;&lt;td&gt;&apos;.$p-&gt;htmlValue(&apos;product_image&apos;).&apos;&lt;/td&gt;&lt;/tr&gt;&apos;
				.&apos;&lt;/table&gt;&apos;;
		}
		
		echo &apos;&lt;/body&gt;&lt;/html&gt;&apos;;
    	
    }
}
&lt;/code&gt;



===Connecting the Icon to the Action===

FInally it is time to connect our Icon to our Action.  We do this by adding a &apos;&apos;url&apos;&apos; directive for the action in the &apos;&apos;[[actions.ini file]]&apos;&apos;:


&lt;code&gt;
[printable_report]
    icon=&quot;{$site_url}/images/printer.png&quot;
    category=result_list_actions
    description=&quot;See this product list in a printable format&quot;
    url=&quot;{$app-&gt;url(&apos;-action=printable_report&apos;)}&quot;
&lt;/code&gt;

Explanation of the &apos;&apos;url&apos;&apos; directive in this snippet:

* The &apos;&apos;url&apos;&apos; method of the &apos;&apos;[[Dataface_Application]]&apos;&apos; object is used to generate a URL with the user&apos;s current query settings, but with the &apos;&apos;-action&apos;&apos; parameter set to &apos;&apos;printable_report&apos;&apos;.

Now if we reload our application, go to the list tab of the &apos;&apos;products&apos;&apos; table and click on our icon, it should take us to our action:

[[Image:http://media.weblite.ca/files/photos/Picture%207.png?max_width=640]]

===Trying out the action on different found sets with different sort orders===

One of the cool things about this action is that it is tied directly into the Xataface find settings so that th user is able to search for a subset of products and run our report on only those products that were found.  The user can also perform a sort on any column and this sort will be respected by our report.

===Hiding Icon from Other Tables===

Since our action is only intended to operate on the &apos;&apos;products&apos;&apos; table it probably isn&apos;t a good idea to make the icon visible for every other table.  For example, if you go to the list view of the &apos;&apos;users&apos;&apos; table, you&apos;ll see the printer icon in the top right just like it appears for the &apos;&apos;products&apos;&apos; table.  Clicking on it should display our error:

[[Image:http://media.weblite.ca/files/photos/Picture%206.png?max_width=640]]

We will use a &apos;&apos;condition&apos;&apos; directive for our action to hide it from tables other than the &apos;&apos;products&apos;&apos; table as follows:

 condition=&quot;$query[&apos;-table&apos;] == &apos;products&apos;&quot;
 
So our action will now look like:

&lt;code&gt;
[printable_report]
    icon=&quot;{$site_url}/images/printer.png&quot;
    category=result_list_actions
    description=&quot;See this product list in a printable format&quot;
    url=&quot;{$app-&gt;url(&apos;-action=printable_report&apos;)}&quot;
    condition=&quot;$query[&apos;-table&apos;] == &apos;products&apos;&quot;
&lt;/code&gt;

Now if you reload the list for the &apos;&apos;users&apos;&apos; table you&apos;ll notice that the printer icon is now gone.  But returning to the &apos;&apos;products&apos;&apos; table shows our action still alive and well.

===Locking Down our Action with Permissions===

In our case we don&apos;t want our action to be accessible to all users.  Only administrators.  Xataface permissions and all its possibilities are beyond the scope of this tutorial, but we still want to demonstrate how to lock down this action.  The WebAuction application into which this action is being installed defines a permission called &apos;&apos;reports&apos;&apos; which only administrators have.  We will use this permission to limit access to this action as follows in the actions.ini file:
 permission=reports

So the actions.ini file will now look like:
&lt;code&gt;
[printable_report]
    icon=&quot;{$site_url}/images/printer.png&quot;
    category=result_list_actions
    description=&quot;See this product list in a printable format&quot;
    url=&quot;{$app-&gt;url(&apos;-action=printable_report&apos;)}&quot;
    condition=&quot;$query[&apos;-table&apos;] == &apos;products&apos;&quot;
    permission=reports
&lt;/code&gt;

Now only administrators will see our icon, and if non-administrators attempt to access out action by typing in its URL directly, they will receive an &quot;Access Denied&quot; message.

</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=83">
	<page_name>Key</page_name>
	<page_id>83</page_id>
	<page_title>fields.ini Directive: Key</page_title>
	<content>The &apos;&apos;&apos;Key&apos;&apos;&apos; directive is used only when the table is a view and you need to explicitly define which columns are part of the primary key.  For example, if we created a view on the books table to only show books in a given year as follows:
&lt;code&gt;
create view books_2000 as
select * from books where year=&apos;2000&apos;
&lt;/code&gt;

And we wanted to use this view as a table in our Xataface application we would need to tell it that the primary key of this view is the book_id field.  So in the fields.ini file we would add:

&lt;code&gt;
[book_id]
    Key=PRI
&lt;/code&gt;

Note that this is case sensitive.  key=PRI will not work.

===Compound Primary Keys===

For primary keys comprising multiple columns we would add this directive for each field in the key.  E.g. if our books_2000 view had 2 fields in the primary key, say author_id and book_index, we would have in the books_2000 fields.ini file:
&lt;code&gt;
[author_id]
    Key=PRI

[book_index]
    Key=PRI
&lt;/code&gt;

Links:
* [http://xataface.com/forum/viewtopic.php?f=4&amp;t=6723 Lookup widget on view with compound primary key]

Return to [[fields.ini file]]</content>
	<keywords>Key, Views, MySQL Views, Create View, PRI, Primary Keys</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=84">
	<page_name>http://xataface.com/documentation/how-to/site_with_backoffice_How_to_build_a_site_with_a_backoffice_</page_name>
	<page_id>84</page_id>
	<page_title>A site with a backoffice</page_title>
	<content>==A site with a backoffice==
To create a site with a backoffice for the administrator, so that the visitors do not have to log in to read the pages, you add this code in the ApplicationDelegate.php file in the conf directory :
&lt;code&gt;

function getPermissions(&amp;$record){
    if ( isAdmin() ) return Dataface_PermissionsTool::ALL();
    else return Dataface_PermissionsTool::READ_ONLY();
}
 
&lt;/code&gt;
</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=85">
	<page_name>http://xataface.com/documentation/how-to/site_with_backoffice</page_name>
	<page_id>85</page_id>
	<page_title>How to build a site with an optional login form</page_title>
	<content>==How to build a site with an optional login form==
To publish a public site with data without any need to login to access, here is the code :
&lt;code&gt;
function getPermissions(&amp;$record){
    if ( isAdmin() ) return Dataface_PermissionsTool::ALL();
    else return Dataface_PermissionsTool::READ_ONLY();
} 
&lt;/code&gt;
In this way, you still can login to administrate your data.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=86">
	<page_name>site_with_backoffice</page_name>
	<page_id>86</page_id>
	<page_title></page_title>
	<content>==How to build a site with an optional login form==
To publish a public site with data without any need to login to access, here is the code :
&lt;code&gt;
function getPermissions(&amp;$record){
    if ( isAdmin() ) return Dataface_PermissionsTool::ALL();
    else return Dataface_PermissionsTool::READ_ONLY();
} 
&lt;/code&gt;
In this way, you still can login to administrate your data.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=87">
	<page_name>sql_delegate_method</page_name>
	<page_id>87</page_id>
	<page_title>__sql__ Delegate Method</page_title>
	<content>return to [[Delegate class methods]]

===Synopsis===

The __sql__ delegate class method can be defined in any delegate class to specify the SQL query that should be used to fetch records for a given table.  This method overrides the [[__sql__]] directive of the fields.ini file.  This strategy is primarily used to graft columns from another table onto the base table.

=====Use Caution=====

This is an advanced feature and, if used incorrectly, can muck up your application. Make sure that your SQL query includes a superset of the columns in the base table, and is a row-for-row match for the rows in the base table.  I.e. you should never use an internal join.  Always use a left join so that all of the rows of the base table are returned even if the join table doesn&apos;t have a corresponding row.

If you want to simply filter a table&apos;s records, and don&apos;t need to graft any additional columns onto the table, you should use the [[setSecurityFilters]] method.

===Example===

Given the table foo, its delegate class:

&lt;code&gt;
class tables_foo {
    function __sql__(){
        return &quot;select f.*, c.category_name from foo f left join categories c on f.category_id=c.category_id&quot;;
    }
}
&lt;/code&gt;

This effectively grafts a column &quot;category_name&quot; onto the foo table based on a join with the categories table.

</content>
	<keywords>__sql__, SQL queries, delegate class</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=88">
	<page_name>secure</page_name>
	<page_id>88</page_id>
	<page_title>secure fields.ini directive</page_title>
	<content>[[fields.ini file]] directive used only with [[container fields]].  If this flag is set, then the field contents will be treated in a secure manner and will obey the application permissions.  If this directive is not set, then uploaded files in [[container fields]] are served directly by the web server without considering application permissions.  Setting this directive will cause the application use a special get_blob action to serve the uploaded file, and this obeys application permissions.

==Example==

Given a field to upload a PDF report, your [[fields.ini file]] section for this field might be something like:

&lt;code&gt;
[pdf_report]
    Type=container
    allowed_extensions=&quot;pdf&quot;
    savepath=&quot;uploads&quot;
    url=&quot;uploads&quot;
&lt;/code&gt;


Now if we upload a file named &quot;foo.pdf&quot; in this field, it will be uploaded to:
 http://www.example.com/path/to/myapp/uploads/foo.pdf

Now we change the field definition to use the secure directive:

&lt;code&gt;
[pdf_report]
    Type=container
    allowed_extensions=&quot;pdf&quot;
    savepath=&quot;uploads&quot;
    url=&quot;uploads&quot;
    secure=1
&lt;/code&gt;

In this case it will still upload files to the &apos;&apos;uploads&apos;&apos; directory, but all of the links generated in the Xataface interface (and via the &apos;&apos;display()&apos;&apos; and &apos;&apos;htmlValue()&apos;&apos; methods) will be for a URL like:
  http://www.example.com/path/to/myapp/index.php?-action=getBlob&amp;-table=mytable&amp;-field=pdf_report&amp;record_id=10

Which will serve up the PDF file as an attachment.

===Restricting Direct Access to uploads directory===

Note: You still need to restrict access to the uploads directory or it may be possible for users to still guess the absolute URL to files in it.  You can restrict access by placing an .htaccess file in the uploads directory (if you are using Apache) with the following contents:
&lt;code&gt;
deny from all
&lt;/code&gt;

If you are using IIS or another web server you should look into the methods available for you to restrict access to directories.

===HTTP Response Codes===

The [[getBlob action]] will return the following HTTP Response Codes:

* &apos;&apos;&apos;404&apos;&apos;&apos; - If either the record does not exist, or the record&apos;s specified container field is empty.
* &apos;&apos;&apos;403&apos;&apos;&apos; - If the current user doesn&apos;t have permission to access this record.
* &apos;&apos;&apos;500&apos;&apos;&apos; - If there is another error.  The actual error will be written to the error log.</content>
	<keywords>secure,fields.ini file</keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=89">
	<page_name>file</page_name>
	<page_id>89</page_id>
	<page_title></page_title>
	<content>==Dynamic select boxes==

To create two select boxes whose one is dependent (slave) of the other (master), we need to use some javascript with Jason.

Create the valuelists.ini:
&lt;code&gt;

;valuelist for the slave
[slaves_list]
__sql__ = &quot;select slave_id, slave_name, master_id from slaves&quot;

; valuelist for the masters
[masters_list]
__sql__ = &quot;select master_id,master_name from masters&quot;
&lt;/code&gt;

fields.ini:
&lt;code&gt;
[master]
vocabulary=masters_list

[slave]
vocabulary=slaves_list
&lt;/code&gt;

delegate class in the table directory :
&lt;code&gt;
...
function block__after_new_record_form(){
echo &lt;&lt;&lt;END
&lt;script language=&quot;javascript&quot;&gt;&lt;!--
var slave_field= document.getElementById(&apos;slave&apos;);
var master_field = document.getElementById(&apos;master&apos;);
END;
// Let&apos;s get all the slaves available.
$app =&amp; Dataface_Application::getInstance();
$query =&amp; $app-&gt;getQuery();
$table =&amp; Dataface_Table::loadTable($query[&apos;-table&apos;]);
$slaves = $table-&gt;getValuelist(&apos;slaves_list&apos;);
$slave_masters = $table-&gt;getValuelist(&apos;slaves_list__meta&apos;);
// Note that the slaves_list__meta valuelist is automatically created
// because we had three columns in the slaves valuelist.
// The first and third columns effectively create a 2nd valuelist
// named &apos;slaves_list__meta&apos;

// $slaves is an array with keys slave_id and values slave_name
// slave_masters is an array with keys slave_id and values master_id

import(&apos;Services/JSON.php&apos;);
$json =&amp; new Services_JSON(); // A JSON encoder to allow us to easily
// convert PHP arrays to javascript arrays.
echo &apos;
var slaves_options = &apos;.$json-&gt;encode($slaves).&apos;;
var slaves_master = &apos;.$json-&gt;encode($slave_masters).&apos;;
&apos;;

echo &lt;&lt;&lt;END
master_field.onchange = function(){
var selected_master = master_field.options[master_field.selectedIndex].value;
slave_field.options.length = 0;
var index = 0;
for ( slave_id in slaves_options){
if ( selected_master == slaves_master[slave_id] ){
slave_field.options[index++] = new Option(slaves_options[slave_id], slave_id);
}
}
};
//--&gt;&lt;/script&gt;
END;
}

// Also place this javascript after an edit record form...
function block__after_edit_record_form(){
return $this-&gt;block__after_new_record_form();
}


&lt;/code&gt; </content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki>
<wiki id="wiki?page_id=90">
	<page_name>Dynamic_select_boxes</page_name>
	<page_id>90</page_id>
	<page_title></page_title>
	<content>==Dynamic select boxes==

To create two select boxes whose one is dependent (slave) of the other (master), we need to use some javascript with Jason.

Create the valuelists.ini:
&lt;code&gt;

;valuelist for the slave
[slaves_list]
__sql__ = &quot;select slave_id, slave_name, master_id from slaves&quot;

; valuelist for the masters
[masters_list]
__sql__ = &quot;select master_id,master_name from masters&quot;
&lt;/code&gt;

fields.ini:
&lt;code&gt;
[master]
vocabulary=masters_list

[slave]
vocabulary=slaves_list
&lt;/code&gt;

delegate class in the table directory :
&lt;code&gt;
...
function block__after_new_record_form(){
echo &lt;&lt;&lt;END
&lt;script language=&quot;javascript&quot;&gt;&lt;!--
var slave_field= document.getElementById(&apos;slave&apos;);
var master_field = document.getElementById(&apos;master&apos;);
END;
// Let&apos;s get all the slaves available.
$app =&amp; Dataface_Application::getInstance();
$query =&amp; $app-&gt;getQuery();
$table =&amp; Dataface_Table::loadTable($query[&apos;-table&apos;]);
$slaves = $table-&gt;getValuelist(&apos;slaves_list&apos;);
$slave_masters = $table-&gt;getValuelist(&apos;slaves_list__meta&apos;);
// Note that the slaves_list__meta valuelist is automatically created
// because we had three columns in the slaves valuelist.
// The first and third columns effectively create a 2nd valuelist
// named &apos;slaves_list__meta&apos;

// $slaves is an array with keys slave_id and values slave_name
// slave_masters is an array with keys slave_id and values master_id

import(&apos;Services/JSON.php&apos;);
$json =&amp; new Services_JSON(); // A JSON encoder to allow us to easily
// convert PHP arrays to javascript arrays.
echo &apos;
var slaves_options = &apos;.$json-&gt;encode($slaves).&apos;;
var slaves_master = &apos;.$json-&gt;encode($slave_masters).&apos;;
&apos;;

echo &lt;&lt;&lt;END
master_field.onchange = function(){
var selected_master = master_field.options[master_field.selectedIndex].value;
slave_field.options.length = 0;
var index = 0;
for ( slave_id in slaves_options){
if ( selected_master == slaves_master[slave_id] ){
slave_field.options[index++] = new Option(slaves_options[slave_id], slave_id);
}
}
};
//--&gt;&lt;/script&gt;
END;
}

// Also place this javascript after an edit record form...
function block__after_edit_record_form(){
return $this-&gt;block__after_new_record_form();
}


&lt;/code&gt; 

The 2.0 version has a [http://xataface.com/dox/modules/depselect/latest| depselect module] to produce cascading dynamic select boxes very simply.</content>
	<keywords></keywords>
	<language>en</language>
	<original_page></original_page>
</wiki></record>