Line 125... |
Line 125... |
125 |
</td>
|
125 |
</td>
|
126 |
<td>
|
126 |
<td>
|
127 |
define ( MAX_UPLOAD_FILE_SIZE, 1024*1024*10 );
|
127 |
define ( MAX_UPLOAD_FILE_SIZE, 1024*1024*10 );
|
128 |
</td>
|
128 |
</td>
|
129 |
</tr>
|
129 |
</tr>
|
- |
|
130 |
<tr>
|
- |
|
131 |
<td>
|
- |
|
132 |
CHILD_KEY_INSERT_TAG
|
- |
|
133 |
</td>
|
- |
|
134 |
<td>
|
- |
|
135 |
String
|
- |
|
136 |
</td>
|
- |
|
137 |
<td>
|
- |
|
138 |
This value is used to indicate an insert from an edit of a child table. See note in "children" for a fuller explaination.
|
- |
|
139 |
</td>
|
- |
|
140 |
<td>
|
- |
|
141 |
define ( CHILD_KEY_INSERT_TAG, 'new');
|
- |
|
142 |
</td>
|
- |
|
143 |
</tr>
|
- |
|
144 |
<tr>
|
- |
|
145 |
<td>
|
- |
|
146 |
CHILD_KEY_DELIMITER
|
- |
|
147 |
</td>
|
- |
|
148 |
<td>
|
- |
|
149 |
String
|
- |
|
150 |
</td>
|
- |
|
151 |
<td>
|
- |
|
152 |
This value is used to separate components of INPUT names in an edit of a child table. See note in "children" for a fuller explaination.
|
- |
|
153 |
</td>
|
- |
|
154 |
<td>
|
- |
|
155 |
define ( CHILD_KEY_DELIMITER, '-' );
|
- |
|
156 |
</td>
|
- |
|
157 |
</tr>
|
- |
|
158 |
<tr>
|
- |
|
159 |
<td>
|
- |
|
160 |
CHILD_KEY_TAG
|
- |
|
161 |
</td>
|
- |
|
162 |
<td>
|
- |
|
163 |
String
|
- |
|
164 |
</td>
|
- |
|
165 |
<td>
|
- |
|
166 |
This value is used to indicate an update from an edit of a child table. See note in "children" for a fuller explaination.
|
- |
|
167 |
</td>
|
- |
|
168 |
<td>
|
- |
|
169 |
define ( CHILD_KEY_TAG, 'child_table' );
|
- |
|
170 |
</td>
|
- |
|
171 |
</tr>
|
130 |
</tbody>
|
172 |
</tbody>
|
131 |
</table>
|
173 |
</table>
|
132 |
<p>
|
174 |
<p>
|
133 |
<em>$DATABASE_DEFINITION</em> is a multi-level hash and must be defined as global. Since it is multi-level, this document will work on a per-layer basis
|
175 |
<em>$DATABASE_DEFINITION</em> is a multi-level hash and must be defined as global. Since it is multi-level, this document will work on a per-layer basis
|
134 |
</p>
|
176 |
</p>
|
Line 234... |
Line 276... |
234 |
</td>
|
276 |
</td>
|
235 |
<td>
|
277 |
<td>
|
236 |
'display query' => 'select value,description from _global'
|
278 |
'display query' => 'select value,description from _global'
|
237 |
</td>
|
279 |
</td>
|
238 |
</tr>
|
280 |
</tr>
|
- |
|
281 |
<tr>
|
- |
|
282 |
<td>
|
- |
|
283 |
new record indicator
|
- |
|
284 |
</td>
|
- |
|
285 |
<td>
|
- |
|
286 |
array of columns
|
- |
|
287 |
</td>
|
- |
|
288 |
<td>
|
- |
|
289 |
Array of columns, any one of which would indicate that a new record template had data entered into it. This should be one or more of the required fields, and is used as an indicator in function updateData when processing child tables that the single row used for adding a new entry had been updated and should be processed.
|
- |
|
290 |
</td>
|
- |
|
291 |
<td>
|
- |
|
292 |
'new record indicator' => array('value')
|
- |
|
293 |
</td>
|
- |
|
294 |
</tr>
|
239 |
<tr>
|
295 |
<tr>
|
240 |
<td>
|
296 |
<td>
|
241 |
field info
|
297 |
field info
|
242 |
</td>
|
298 |
</td>
|
243 |
<td>
|
299 |
<td>
|
Line 814... |
Line 870... |
814 |
</td>
|
870 |
</td>
|
815 |
</tr>
|
871 |
</tr>
|
816 |
</tbody>
|
872 |
</tbody>
|
817 |
</table>
|
873 |
</table>
|
818 |
<h3>children</h3>
|
874 |
<h3>children</h3>
|
819 |
<p>children is the way to define one or more child tables. A child table is similar to a lookup table, but it is more complex in that it may have multiple display columns, may be joined to other tables, etc... However, a child table is a direct descendant of the current table, ie it will not join ot another row in the current table.</p>
|
875 |
<p>children is the way to define one or more child tables. A child table is similar to a lookup table, but it is more complex in that it may have multiple display columns, may be joined to other tables, etc... However, a child table is a direct descendant of the current table, ie it will not join to another row in the current table.</p>
|
820 |
<p>children only has two values; the name of the table which is a child, and the column in the child table that is used for the join. If the latter is missing, it is assumed to be the same as the primary key of the current table.</p>
|
876 |
<p>children only has two values; the name of the table which is a child, and the column in the child table that is used for the join. If the latter is missing, it is assumed to be the same as the primary key of the current table.</p>
|
821 |
<p>During edit, all rows in the child table belonging to the current table are displayed in tabular form, using the 'display query' defined in that table.</p>
|
877 |
<p>During edit, all rows in the child table belonging to the current table are displayed in tabular form, using the 'display query' defined in that table. This can cause a more complex setup as we have multiple rows in an HTML table containing data on the same column, but each HTML <INPUT> should have a unique name in order to be processed.</p>
|
- |
|
878 |
<p>To fix this, the library will give a unique name to each item, based on the column name, a constant (global constant CHILD_KEY_TAG), the table name from which the data is drawn, and the unique row-id (ie, a 'key field' entry) for the row being edited. These values are separated by a delimiter (global constant CHILD_KEY_DELIMITER).</p>
|
- |
|
879 |
<p>Additionally, a "blank" row is created in these circumstances to allow the user to enter a new record if they desire. This will take the same form as the previous paragraph, except that the row-id is replaced by a special indicator (global constant CHILD_KEY_INSERT_TAG)</p>
|
- |
|
880 |
<p>The name of the edit for an existing key is therefore calculated as:<br>
|
- |
|
881 |
<em>fieldname</em> . CHILD_KEY_DELIMITER . CHILD_KEY_TAG . CHILD_KEY_DELIMITER . <em>tablename</em> . CHILD_KEY_DELIMITER . <em>primary_key_value_of_row</em> <br>
|
- |
|
882 |
and the name for the single "blank" record is calculated as:<br>
|
- |
|
883 |
<em>fieldname</em> . CHILD_KEY_DELIMITER . CHILD_KEY_TAG . CHILD_KEY_DELIMITER . <em>tablename</em> . CHILD_KEY_DELIMITER . CHILD_KEY_INSERT_TAG
|
- |
|
884 |
</p>
|
- |
|
885 |
<p>
|
- |
|
886 |
This gives rise to entries on the HTML form as follows, the first being an edit of the username field of a child table <em>login</em> whose row id is 5, and the second being a blank record to add a new row.
|
- |
|
887 |
</p>
|
- |
|
888 |
<ul><LI> <td><input type='text' name='<em>username</em>-child_table-<em>login</em>-<em>5</em>' value='jane@example.com'></li><li>
|
- |
|
889 |
<td><input type='text' name='<em>username</em>-child_table-<em>login</em>-<em>new</em>' value=''>
|
- |
|
890 |
</LI></ul>
|
- |
|
891 |
<p>The above example assumes the following definitions in yoru database definition file</p>
|
- |
|
892 |
<pre>
|
- |
|
893 |
define ( CHILD_KEY_INSERT_TAG, 'new');
|
- |
|
894 |
define ( CHILD_KEY_DELIMITER, '-' );
|
- |
|
895 |
define ( CHILD_KEY_TAG, 'child_table' );
|
- |
|
896 |
</pre>
|
- |
|
897 |
<p><strong>Note:</strong> You are responsible for ensuring the CHILD_KEY_DELIMITER is not found within field or table names. If you tend to use underscores in your field or table names (like I do), you can not use them as the delimiter. This needs to be a delimiter which is legitimate as the name of an HTML entity and is not found in the table name, column name or key field value</p>
|
- |
|
898 |
|
822 |
<h3>Example</h3>
|
899 |
<h3>Example</h3>
|
823 |
<p>Following example is based upon a real life application that stores knowledge base articles. Articles can be associated with one or more categories, and the categories table is hierachial in that each entry has a "parent node" column which links it to another entry in the same table</p>
|
900 |
<p>Following example is based upon a real life application that stores knowledge Computer Asset Management Program. This program is set up to have multiple sites per client, with each site having multiple pieces of equipment (devices). Each device can have multiple attributes.</p>
|
824 |
<p>Note the foreign key definition in table categories, and the many-to-many relationship in articles, going into categories.</p>
|
- |
|
825 |
<pre>
|
901 |
<pre>
|
826 |
define ( MAX_INPUT_FIELD_DISPLAY, 80 ); // this is the maximum input field size
|
902 |
define ( MAX_INPUT_FIELD_DISPLAY, 40 ); // this is the maximum input field size
|
827 |
define ( IMAGE_DIRECTORY, '/pictures/' ); // relative URL where pictures are stored
|
903 |
define ( IMAGE_DIRECTORY, '/pictures/' ); // relative URL where pictures are stored
|
828 |
define ( EDIT_IMAGE_HEIGHT, 100 ); // height for thumbnail of pictuers
|
904 |
define ( EDIT_IMAGE_HEIGHT, 100 ); // height for thumbnail of pictures
|
829 |
define ( MAX_UPLOAD_FILE_SIZE, 1024*1024*10 ); // 10 meg
|
905 |
define ( MAX_UPLOAD_FILE_SIZE, 1024*1024*10 ); // 10 meg
|
- |
|
906 |
define ( CHILD_KEY_INSERT_TAG, 'new');
|
- |
|
907 |
define ( CHILD_KEY_DELIMITER, '-' );
|
- |
|
908 |
define ( CHILD_KEY_TAG, 'child_table' );
|
- |
|
909 |
define ( DEFAULT_TEXTAREA_HEIGHT, 5 ); // number of rows a textarea will default to
|
- |
|
910 |
define ( DEFAULT_TABLE, 'client'); // the table that will show up in doAdmin by default
|
830 |
|
911 |
|
831 |
global $DATABASE_DEFINITION;
|
912 |
global $DATABASE_DEFINITION;
|
832 |
$DATABASE_DEFINITION = array(
|
913 |
$DATABASE_DEFINITION = array(
|
833 |
'article' => array(
|
914 |
'client' => array(
|
834 |
'table name' => 'article',
|
915 |
'table name' => 'client',
|
835 |
'key field' => 'article_id',
|
916 |
'key field' => 'client_id',
|
836 |
'display columns' => array('article_id','title'),
|
917 |
'display columns' => array('client_id','name'),
|
837 |
'display query' => 'select article_id,title from article',
|
918 |
'display query' => 'select client_id,name from client',
|
838 |
'field info' => array(
|
919 |
'field info' => array(
|
839 |
'article_id' => array('keyfield' => 1 , 'required' => true , 'readonly' => true , 'type' => 'int' , 'width' => 10),
|
920 |
'client_id' => array('keyfield' => 1 , 'required' => true , 'readonly' => true , 'type' => 'int' , 'width' => 10),
|
840 |
'summary' => array('type' => 'string' , 'width' => 255),
|
921 |
'name' => array('type' => 'string' , 'width' => 64),
|
841 |
'content' => array('type' => 'text', 'width'=> 80 ),
|
922 |
'notes' => array('type' => 'text', 'width'=> 80 ),
|
842 |
'title' => array('type' => 'string' , 'width' => 255)
|
923 |
'internal_notes' => array('type' => 'text', 'width'=> 80 ),
|
843 |
),
|
- |
|
844 |
'complex join' => array(
|
- |
|
845 |
'professionals' => array(
|
- |
|
846 |
'null field' => 'article_category.article_id',
|
- |
|
847 |
'values table' => array( // table that holds the values
|
- |
|
848 |
'table name' => 'category',
|
- |
|
849 |
'join condition' => 'article_category.category_id = category.category_id',
|
- |
|
850 |
'display field' => 'name',
|
- |
|
851 |
'key field' => 'category_id'
|
- |
|
852 |
),
|
- |
|
853 |
'join table' => array( // table that 'joins' this table to values table
|
924 |
'added_date' => array('type' => 'date', 'default' => date('Y-m-d H:i:s')),
|
854 |
'table name' => 'article_category',
|
925 |
'removed_date' => array('type' => 'date', 'default' => 'null')
|
855 |
'values link' => 'category_id',
|
- |
|
856 |
'my link' => 'article_id',
|
- |
|
857 |
'join condition' => 'article_category.article_id = article.article_id' )
|
- |
|
858 |
) // professionals
|
- |
|
859 |
) // complex join
|
- |
|
860 |
|
926 |
)
|
861 |
),
|
927 |
),
|
862 |
'article_category' => array(
|
928 |
'site' => array(
|
863 |
'table name' => 'article_category',
|
929 |
'table name' => 'site',
|
864 |
'key field' => array('article_id','category_id'),
|
930 |
'key field' => 'site_id',
|
865 |
'display columns' => array('category_id','article_id'),
|
931 |
'display columns' => array('site_id','name'),
|
866 |
'display query' => 'select category_id,article_id from article_category',
|
932 |
'display query' => 'select site_id,name from site',
|
867 |
'field info' => array(
|
933 |
'field info' => array(
|
868 |
'category_id' => array('keyfield' => 1 , 'required' => true , 'default' => '0' , 'type' => 'int' , 'width' => 10),
|
934 |
'site_id' => array('keyfield' => 1 , 'required' => true , 'readonly' => true , 'type' => 'int' , 'width' => 10),
|
- |
|
935 |
'client_id' => array( 'type' => 'lookup', // this is the field type, and must be ints
|
- |
|
936 |
'table' => 'client', // remote table name
|
- |
|
937 |
'keyfield' => 'client_id', // keyfield in remote table, ie category.category_id
|
- |
|
938 |
'display_field' => 'name' // this is the column displayed to the user
|
- |
|
939 |
),
|
- |
|
940 |
'name' => array('type' => 'string' , 'width' => 64),
|
- |
|
941 |
'notes' => array('type' => 'text', 'width'=> 80 ),
|
869 |
'article_id' => array('keyfield' => 1 , 'required' => true , 'default' => '0' , 'type' => 'int' , 'width' => 10)
|
942 |
'added_date' => array('type' => 'date', 'default' => date('Y-m-d H:i:s') ),
|
- |
|
943 |
'removed_date' => array('type' => 'date', 'default' => 'null' )
|
870 |
)
|
944 |
)
|
871 |
),
|
945 |
),
|
872 |
'category' => array(
|
946 |
'device' => array(
|
873 |
'table name' => 'category',
|
947 |
'table name' => 'device',
|
874 |
'key field' => 'category_id',
|
948 |
'key field' => 'device_id',
|
875 |
'display columns' => array('name'),
|
949 |
'display columns' => array('name'),
|
876 |
'display query' => 'select category_id,name from category',
|
950 |
'display query' => 'select device_id,name from device',
|
877 |
'field info' => array(
|
951 |
'field info' => array(
|
- |
|
952 |
'device_id' => array('keyfield' => 1 , 'required' => true , 'readonly' => true , 'type' => 'int' , 'width' => 10),
|
- |
|
953 |
'name' => array('required' => true , 'default' => '' , 'type' => 'string' , 'width' => 255),
|
878 |
'parent_category' => array( 'type' => 'lookup', // this is the field type, and must be ints
|
954 |
'part_of' => array( 'type' => 'lookup', // this is the field type, and must be ints
|
879 |
'table' => 'category', // remote table name
|
955 |
'table' => 'device', // remote table name
|
880 |
'keyfield' => 'category_id', // keyfield in remote table, ie category.category_id
|
956 |
'keyfield' => 'device_id', // keyfield in remote table, ie category.category_id
|
- |
|
957 |
'display_field' => 'name', // this is the column displayed to the user
|
- |
|
958 |
'null_ok' => true
|
- |
|
959 |
),
|
- |
|
960 |
'device_type_id' => array( 'type' => 'lookup', // this is the field type, and must be ints
|
- |
|
961 |
'table' => 'device_type', // remote table name
|
- |
|
962 |
'keyfield' => 'device_type_id', // keyfield in remote table, ie category.category_id
|
881 |
'display_field' => 'name' // this is the column displayed to the user
|
963 |
'display_field' => 'name' // this is the column displayed to the user
|
882 |
),
|
964 |
),
|
- |
|
965 |
|
- |
|
966 |
'site_id' => array( 'type' => 'lookup', // this is the field type, and must be ints
|
- |
|
967 |
'query' => "select site_id,concat(client.name, ' - ', site.name) from site join client on site.client_id = client.client_id order by client.name,site.name",
|
- |
|
968 |
'table' => 'site', // remote table name
|
- |
|
969 |
'keyfield' => 'site_id', // keyfield in remote table, ie category.category_id
|
- |
|
970 |
'display_field' => 'name' // this is the column displayed to the user
|
883 |
|
971 |
),
|
884 |
'category_id' => array('keyfield' => 1 , 'required' => true , 'readonly' => true , 'type' => 'int' , 'width' => 10),
|
972 |
'notes' => array('type' => 'text', 'width'=> 80 ),
|
885 |
'name' => array('required' => true , 'default' => '' , 'type' => 'string' , 'width' => 64)
|
973 |
'name' => array('required' => true , 'default' => '' , 'type' => 'string' , 'width' => 64),
|
- |
|
974 |
'added_date' => array('type' => 'date', 'default' => date('Y-m-d H:i:s')),
|
- |
|
975 |
'removed_date' => array('type' => 'date', 'default' => 'null')
|
886 |
)
|
976 |
),
|
- |
|
977 |
'child tables' => array (
|
- |
|
978 |
'device_attrib' => array( 'table name' => 'device_attrib' )
|
- |
|
979 |
)
|
- |
|
980 |
),
|
- |
|
981 |
'device_attrib' => array(
|
- |
|
982 |
'display name' => 'Device Attributes',
|
- |
|
983 |
'table name' => 'device_attrib',
|
- |
|
984 |
'key field' => 'device_attrib_id',
|
- |
|
985 |
'new record indicator' => array('value'),
|
- |
|
986 |
'display columns' => array('name'),
|
- |
|
987 |
'display query' => 'select device_attrib_id,attrib.name, device_attrib.value from device_attrib join attrib using (attrib_id)',
|
- |
|
988 |
'field info' => array(
|
- |
|
989 |
'device_attrib_id' => array('keyfield' => 1 ,
|
- |
|
990 |
'required' => true ,
|
- |
|
991 |
'readonly' => true ,
|
- |
|
992 |
'type' => 'int' ,
|
- |
|
993 |
'width' => 10,
|
- |
|
994 |
'display name' => 'ID'
|
- |
|
995 |
),
|
- |
|
996 |
'device_id' => array ( 'type' => 'lookup', // this is the field type, and must be ints
|
- |
|
997 |
'table' => 'device', // remote table name
|
- |
|
998 |
'keyfield' => 'device_id', // keyfield in remote table, ie category.category_id
|
- |
|
999 |
'display_field' => 'name', // this is the column displayed to the user
|
- |
|
1000 |
'null_ok' => false,
|
- |
|
1001 |
'display name' => 'Device'),
|
- |
|
1002 |
'attrib_id' => array( 'type' => 'lookup', // this is the field type, and must be ints
|
- |
|
1003 |
'table' => 'attrib', // remote table name
|
- |
|
1004 |
'keyfield' => 'attrib_id', // keyfield in remote table, ie category.category_id
|
- |
|
1005 |
'display_field' => 'name', // this is the column displayed to the user
|
- |
|
1006 |
'null_ok' => false,
|
- |
|
1007 |
'display name' => 'Attribute'
|
- |
|
1008 |
),
|
- |
|
1009 |
'value' => array('type' => 'text', 'required' => true, 'width'=> 40, 'height' => 1, 'display name' => 'Value' ),
|
- |
|
1010 |
'added_date' => array('type' => 'date', 'default' => date('Y-m-d H:i:s'), 'display name' => 'Date Added'),
|
- |
|
1011 |
'removed_date' => array('type' => 'date', 'default' => 'null', 'display name' => 'Date Removed')
|
- |
|
1012 |
)
|
887 |
)
|
1013 |
)
|
888 |
);
|
1014 |
);
|
889 |
</pre>
|
1015 |
</pre>
|
890 |
<p>Modification required for update to new naming convention. In old source code, do the following search and replaces:</p>
|
1016 |
<p>Modification required for update to new naming convention. In old source code, do the following search and replaces:</p>
|
891 |
<ul><LI>s/foreignkey/lookup/</li>
|
1017 |
<ul><LI>s/foreignkey/lookup/</li>
|
892 |
<li>s/one to many/complex join/
|
1018 |
<li>s/one to many/complex join/
|