Database connection Various options are configured near the top of the script, most notably the database logon. For security reasons, you may want to copy/paste the logon options to a separate, included file. MySQL logon options host name, user name, password, database, and table appear in the following format. Database connection options Recommended usage is, that the first four options shown above should be moved to a separate, included file. It is a rather common situation to use &name; inside larger project. To prevent &name; from creating an additional persistent database connection, supply the $opts['dbh'] option. In the example below, $your_project_db_handle represents a previously allocated MySQL database handle. When $opts['dbh'] is specified, the first four options appearing above are ignored. Supplying allocated connection Unique key Assuming that 'id' is the name of the MySQL column selected as the unique identifier when phpMyEditSetup.php script was run, the key will appear in the script as: Unique key definition There were problems reported by &name; users regarding the usage of MySQL reserved word as an unique key name (the example for this is "key" name). Thus we recommend using another name of unique key. Usage of "id" or "ID" names should be safe and good idea. The column type for the unique numeric identifier should appear as: Unique key type definition The argument 'int' shown above indicates the column type is an integer. If the column type was a date then 'date' would appear above instead of 'int'. Other possible unique key types are 'real' or 'string'. If you are using 'real' key type and some problems with record manipulaton have occured, it is probably because your MySQL key datatype is 'float'. Comparsions with this datatype is a common problem in most computer languages (including SQL), because floating-point values are not exact values. In most cases, changing the MySQL datatype from 'float' to 'double' and preserving 'real' as &name; key type should solve this problem. For more information about this issue, read Solving Problems with No Matching Rows chapter in the MySQL manual (in version 3.23.47 it was A.5.6). Common options Page name The page name option defines the variable used for constructing page and form links. If not defined, the default value $PHP_SELF will be used. Setting up the page name Displayed records This option controls the number of records displayed on the screen. Change the argument for $opts['inc'] in order to specify the maximum number of rows to display at one time. The default is 15 rows. To display all found records, specify a value of -1 (negative 1). Displayed records Multiple selections This option affects the display of <SELECT MULTIPLE> boxes. If the MySQL column type is "set", the number of lines displayed on multiple selection filters is specified as: Multiple selections option Setting $opts['multiple'] to a large number may adversely affect the appearance of your form. Four (4) is the default. Special page elements There are some special page elements, that may be turned on or off by changing $opts['display'] array. Setting the query or sort values to true will display the current query or sort order near the top of the table. To display the execution time of the query below the table, change the time value from false to true. Setting sort to true is very helpful in understanding how cumulative sorting takes place. Setting num_pages or num_records to false will stop displaying corresponding values next to buttons. These values can be displayed also using $opts['buttons'] configuration array. To display these three page elements use: Special page elements true, 'sort' => true, 'time' => true ); ]]> There is also one special $opts['display']['tabs'] variable, which generally controls the TABs feature. For more information see section. Another special variable is $opts['display']['form'], which controls displaying <FORM> and </FORM> HTML tags. If this variable is not defined, its value is considered as true. By default, form tags are displayed. Images URL If graphic links are selected with navigation (for example by setting $opts['navigation'] to 'GD') then $opts['url'] can be used to specify the folder containing images. The default image location is normally one folder (or directory level) below the location of the phpMyEdit.class.php file. Images URL 'images/'); ]]> Other URLs for another elements may be added into this array in future. Code execution Since version 4.0, &name; automatically starts its execution. You can turn this feature off by setting: Turning off default execution If variable $opts['execute'] is not defined, its value is considered as 1. Permission options Commonly used options include:   A -- add   C -- change   P -- copy   V -- view   D -- delete   F -- filter (search)   I -- initial sort suppressed Table listing is always enabled, since all actions are executed from this screen. But it is possible to get specific behaviours without table listing using appropriate &name; extension. See chapter for more information. Full privileges to manipulate records are configured as: Full permissions To deny the user the ability to delete records use: Full permissions without delete To limit the user to view, sort, list, or filter records use this: Read only permissions In a multi-user environment, it would be wise to only provide the system administrator with the ability to delete records. Sorting &name; offers powerful default and/or additional sorting capabilities via $opts['sort_field'] option. You can define the column name or column field number that you'd prefer to sort on when the script is first loaded. To get descending sort order, prefix the column name or field number with dash (-) sign. Look at the following examples: Sort field option Now, let's assume you want to sort your table according to the 'company' column, but in addition also according to the 'department' column. So the default sort order should be by company first, then department. For this purpose, you can set an array with column names and/or field numbers to $opts['sort_field'] variable. Multiple sort fields Also note that &name;'s sorting feature is cumulative. This means, that if default sort fields are specified and the user selects (clicks) to sort by another column in table listing screen, the resulting screen will be sorted by user selected column first and then by specified default sort fields. Next click on another sort column will again force to sort table by selected column first. Previously selected fields or default ones will follow up in sorting sequence. This feature enables selecting more than one sort field on the fly. To clear sort fields sequence and to initialize the default one, click on Clear link in left upper corner. This link could be enabled by setting $opts['display']['sort'] to true. See subsection for more information. We also recommend you to enable this option to see how this described sorting feature works. Navigation The style and location of navigational links is a combined setting. The generated form will have various buttons, such as Next, Prev, Save, Cancel, etc. Their location relative to the table can be changed. Button positions are:   U -- up / above table   D -- down / below table (default) Button possitions should be combined with navigation styles. The style of navigational links may be text, buttons, or graphic images (icons):   B -- buttons (default)   T -- text links   G -- graphic links Possible combinations include: Navigation possibilities As you can see from the last example in box above, all navigation styles can be mixed up together to fit your needs. There is no functionality difference between navigation with graphic/text links and navigation using radio buttons selection. If you are not satisfied with order of buttons, or you want to remove certain buttons, you can use $opts['buttons'] option. In this option, you can specify exact buttons to be displayed, even with custom ones. There are several common reasons to remove some buttons: when having huge amount of pages, dropdown box creation is too long, display save button only at the bottom of the page to force users to scroll through screeen before adding a new record, and so on. Buttons on phpMyEdit pages can be divided into several groups. These groups then specify keywords which are used when declaring a button in $opts['buttons']. If an element in $opts['buttons'] is not matching a keyword, it is translated using language files. If an element is an array, it is outputed as a custom button, as shown below. navigation   first, <<, prev, <, next, >, last, >> go to   goto, goto_combo, goto_text operation   add, view, change, delete, copy confirmation   save, more, cancel statistics   current_page, total_pages, total_recs Navigation and go to group can be used in list or filter mode to jump several pages ahead or back. Operation group moves user to another mode, namely one of ACPDV. Confirmation buttons are used to confirm actions in ACPDV. While cancel is self explanatory, save and more might be confusing. Save is used to confirm action and return to L mode. More means confirming action and return to current mode. Save button is usually displayed as Save, however in D mode it is as Delete and in A mode as Add. More is displayed as either More or Apply. Keywords in the statistics group display numbers as their names suggest. Default buttons ','>>','goto','goto_combo'); $opts['buttons']['L']['down'] = $opts['buttons']['L']['up']; $opts['buttons']['F']['up'] = array('<<','<','add','view','change','copy','delete', '>','>>','goto','goto_combo'); $opts['buttons']['F']['down'] = $opts['buttons']['F']['up']; $opts['buttons']['A']['up'] = array('save','more','cancel'); $opts['buttons']['A']['down'] = $opts['buttons']['A']['up']; $opts['buttons']['C']['up'] = array('save','more','cancel'); $opts['buttons']['C']['down'] = $opts['buttons']['C']['up']; $opts['buttons']['P']['up'] = array('save', 'cancel'); $opts['buttons']['P']['down'] = $opts['buttons']['P']['up']; $opts['buttons']['D']['up'] = array('save','cancel'); $opts['buttons']['D']['down'] = $opts['buttons']['D']['up']; $opts['buttons']['V']['up'] = array('change','cancel'); $opts['buttons']['V']['down'] = $opts['buttons']['V']['up']; ]]> A button can be disabled for two reasons. A navigation button when there are no next or previous pages or an operation button if certain operation is not permitted to the user. By default, all disabled buttons are displayed and marked as disabled. If you do not want to show disabled buttons at all, prepend '-' to keyword. If you want a disabled button to show as enabled, prepend '+'. This will allow users to successfully push this button, however no meaningfull action will be taken.   next -- show next button and mark disabled if appropriate   -next -- do not show next button if disabled You may also specify custom buttons, which values can be used outside of phpMyEdit. The first way to specify a custom button is to use phpMyEdit htmlSubmit method. In this way, value of this submit button is translated using language files into user specified language. Possible configuration is name, value, css class name, java script and disabled.   name -- name of the submit button   value -- value of submit button   css -- css class name   js -- any other string place within button tags, mostly java script   disabled -- 1 button is disabled, 0 button is not disabled Second way of declaring custom buttons, is to declare actuall html code of the button. Note that using this method, any html entity can be outputted. Custom buttons 'pme_back', 'value' => 'Back to main menu', 'css' => 'pme-backtomenu', 'disabled' => false), 'Go to:', array('code' => ''), ); $opts['buttons']['V']['down'] = $opts['buttons']['V']['up']; ]]> Buttons with large number of pages ', '->>'); ); $opts['buttons']['L']['down'] = $opts['buttons']['L']['up']; $opts['display']['num_pages'] = false; $opts['display']['num_records'] = false; ]]> Filters Table-level filter capability (if set) is included in the WHERE clause of any generated SELECT statement. This gives you ability to work with a subset of data from table. Filter examples 200'; ]]> You can also pass an array to this option. If you do so, than array items are put together with "AND" SQL statement. When generating a query, &name; redefines/aliases the table names for easy accessing of particular table fields in the main table and in the tables used in JOIN clauses as well. The main table name is changed to PMEtable0, tables used in JOIN clauses have their name like PMEjoinN where N is JOIN table order. We recommend that you look at the generated SQL queries in your MySQL log file in order to know how database the table was aliased. Finally, the described approach is needed only if you are accessing a field name which occurs in more than one table of SQL query (thus MySQL cannot exactly determine what is meant by "field_name"). For future development is planned an initialization like the following one. 'value_1', 'col_name_2' => 'value_2' ); ]]> The main advantage of this approach will be that col_name_1 and col_name_2 fields are automatically considered as read-only on display record pages with pre-set value_1, value_2 and without the need to enter them manually. Triggers Triggers overview Triggers provide advanced users with the ability to write their own PHP scripts for such things as validating user input, and to have their code executed at the appropriate time. Triggers are files that are included via an include() statement and conditionally executed by phpMyEdit.class.php. SQL triggers are included before or after insert, update, or delete of record. FORM triggers are included before displaying the form that will allow the corresponding operation, or after the user canceled this form. View form is related to the 'select' operation. Add and Copy forms are related to the 'insert' operation Edit form is related to the 'update' operation. Delete form is related to the 'delete' operation. For SQL triggers, the operation sequence is this: before, main, after. If any operation fails, not only should the next operation(s) not be executed, but the previous ones are 'rolled back' as if they never happened. If a database is not able to do this, it is not 'transaction-safe'. Triggers are risky in basic MySQL as there is no native transaction support. It is not transaction-safe by default. There are transaction-safe table types in MySQL that can be conditionally built (see MySQL-Max), but &name; is currently not set up to support real transactions. What that means is that if an operation fails, the database may be left in an intermediate and invalid state. The programmer must understand and accept these risks prior to using the &name; triggers mechanism. If the triggers are used, they execute within the namespace or scope of the &name; class. Triggers must return true or false to indicate success or failure. Triggers types There are following types of &name; triggers: 'pre' triggers are usually used to check conditions before displaying the operation's page. For example, users may be allowed to View all records but can only Edit a subset of them. Another usage is to lock the record in order to avoid other users to start to change it at the same time. 'before' triggers are usually used to verify conditions prior to executing the main operation. For example, they can be of some use for input validation. 'after' triggers are usually used to perform follow-up operations after the main operation. For example, to update secondary tables to enforce referential integrity or to update aggregate tables. 'cancel' triggers are usually used to perform follow-up operations after users cancel the form. For example, if a record is locked using a 'pre' triggers, then a 'cancel' trigger can unlock it. If 'pre' triggers fail, users are sent back to the list, except for the 'update' case, where users are sent back to view page if the pre-update trigger fails. Trigger examples Select triggers Insert triggers Update triggers Delete triggers Please note that ['select']['after'] and ['select']['before'] triggers currently do not exist. In the following sample are steps during a View, Edit, Apply and Cancel operation described. All involved triggers return true. user starts from the list page user asks to view a record ['select']['pre'] trigger is included (if defined) if true is returned then continue, else go back to list page user is now in the view page user asks to edit the record ['update']['pre'] trigger is included (if defined) if true is returned then continue, else go back to view page user is now in the edit page user makes some changes and asks to apply (save and continue) ['update']['before'] trigger is included (if defined) if true is returned then continue, else, back to list without updating record is updated in the database ['update']['after'] trigger is included (if defined) ['update']['pre'] trigger is included (if defined) if true is returned then continue, else go back to view page user is now back to the edit page user makes some other changes but asks to cancel them ['update']['cancel'] trigger is included (if defined) user is back to the list page Triggers variables In every trigger file you have available following usable variables. Some of them affect only a particular action. $this   object reference $this->dbh   initialized MySQL database handle $this->key   primary key name $this->key_type   primary key type $this->key_delim   primary key deliminator $this->rec   primary key value (update and delete only) $newvals   associative array of new values (update and insert only) $oldvals   associative array of old values (update and delete only) $changed   array of keys with changed values There are also other variables available. For example every class property can be accessed using $this object reference. All variables occur in 'before' triggers as well as in 'after' triggers. Only class properties occurs in 'pre' and 'cancel' triggers currently. It is recommended to use the $this->myQuery() method in order to perform database queries for fetching additional data or doing inserts or updates to other database tables. Chained triggers You may set several triggers for the same operation. This allows to isolate code, to share more easily triggers between multiple calling scripts and to reuse code produced by another &name; users. The order triggers are executed in is important. It is set by the keys of the chained triggers. As soon as one of the chained trigger fail, the overall return value is set to false, and following triggers are not executed. If none of chained triggers failed, then the return value is true. Chained update before triggers In this example, when the user clicks on the Save button during editing a record, check.TUB.inc will be run first. If it returns true, then lock.TUB.inc will be run as well. If one of these triggers fails, update of the database won't be performed, just like if a simple ['update']['before'] trigger failed. Note that although the overall return value of 'cancel' triggers does not inluence &name; behavior, the return value of each chained trigger is important. Logging user actions You can log user actions into a special "changelog" table. You must have table created and specified for &name; using the $opts['logtable'] option. Logging Log table schema &name; provides also the possibility of notifying about performed user actions by sending informational e-mail. This feature configuration is done via $opts['notify'] array with following variables notation. Note that on every place where one e-mail address should be written, it is possible to have array of multiple e-mail addresses there. This feature is provided for informing more than one user about particular performed action. $opts['notify']['from']   sender envelope e-mail address (webmaster@SERVER_NAME by default) $opts['notify']['prefix']   prefix of e-mail messages subject (no prefix by default) $opts['notify']['wrap']   maximum width of e-mail message body (by default 72 will be used) $opts['notify']['insert']   e-mail address for insert action notification $opts['notify']['update']   e-mail address for update action notification $opts['notify']['delete']   e-mail address for delete action notification $opts['notify']['all']   e-mail address for all actions notification In both cases, changelog table and e-mail notyfing are values of "user" extracted from the variables in following order: $_SERVER['REMOTE_USER'], $_SERVER['REMOTE_USER'] and global variable $REMOTE_USER. Similary "host" variable is checked in $_SERVER['REMOTE_ADDR'], than in $_SERVER['REMOTE_ADDR'] and at the end in global variable $REMOTE_ADDR. Languages The default language setting is the user's web browser language setting. Use it if possible. The following example forces the English language version, and the last forces the Slovak language version. Languages selection Available languages are: CZ   czech DE   german (standard) DK   danish EL   greek (hellenic) EN   english EN-US   english (United States) ES   spanish ES-AR   spanish (argentinian) ES-MX   spanish (mexican) EU   basque FR   french (standard) ID   indonesian IT   italian (standard) JP   japanese NL   dutch (standard) PL   polish PT   portuguese (standard) PT-BR   portuguese (brazilian) RU   russian SE   swedish SK   slovak TR   turkish ZH   chinese (traditional) ZH-SG   chinese (Singapore) Language codes are based on ISO-3166 standard, which is available on many places, for example here. You can append encoding strings to your language, such as -UTF8 or -LATIN2. If no encoding is specified, backward compatible default one will be used. Default encoding will be switched in next release to UTF-8 in every available language. CGI variables Using CGI variables You can optionally append or overwrite individual variables returned from the CGI environment (GET/POST HTTP protocol data). Use these two arrays for this purpose, where array key means CGI variable name, and array value means CGI variable value. This will activate the search filter on script initialization. However, it is still possible to turn it off by explicit click on Hide or Clear button. CGI variables appending The next example shows how to cause descending sorting according first field in all cases. Because ['overwrite'] is used, sorting column cannot be altered by the user by clicking on column heading. CGI variables overwriting Using the $opts['cgi']['persist'] option you can tell &name; names and values of CGI variables which should be persistent during various pages reloading and serving. They will be included into all links and also into all forms as appropriate hidden inputs. This feature is provided especially for advanced and experienced users using &name; in their medium-size and large-size projects. If you do not understand what does this thing do, feel free to skip it. You will surely do not need it. Persistent CGI variables $article_id, 'session_id' => $SESSION_ID ); ]]> Prefixing CGI variables The type of performed operation such as Add, Change, Delete and so on, is passed using a CGI variable named operation. When passed through a link, for example when $opts['navigation'] is set to 'G' or 'T', the value is an untranslated label prefixed with PME_op_. This prefix can be changed by setting the $opts['cgi']['prefix']['operation'] variable in the calling script. Custom prefix for operation links If you already use in your project some CGI variables used internally by &name;, like 'operation, you may want to prefix &name;'s variables to avoid collision. For the same reason, you may want to prefix the names of input fields. Custom name prefix for CGI variables Javascript and DHTML CGI sys and data name prefixing may especially be useful if you want to display two instance of &name; on the same page. But you will require to prefix Javascript and DHTML tags as well, to make &name; forms truely independant. Javascript functions are default prefixed by PME_js_ string. DHTML ID tags are defaultly prefixed by PME_dhtml_ string. You may change this using the syntax below. Custom name prefix for JS and DHTML CSS classes policy CSS classes policy in &name; is one from the most complicated and complex features. The goal is to reach almost any possible classification of HTML elements with the possibility to simplify classification to lower number of classes. The &name; CSS class schema is displayed here: CSS class name schema ----- ]]> Particular parts are described here: The prefix part is straighforward. Every &name; CSS class has a user configurable prefix. It can be empty. The element represents the name or type of element. The examples are form, row, value, input and others. In order to distinguish between different types of pages there is a page_type. The possible values for this part are add, view, change, copy, delete. This part is empty for table listing and table filtering pages. There are also some elements, which occur on the top and on the bottom of page as well. For this matter there is position part present with possible values up and down. The divider aim is to provide difference between even and odd table listing rows. This part, if present, is always numeric with values starting from 0. At the end of CSS class name is postfix. This part is related to a particular field. Every field can have its own postfix. See field's for more information. The default separator between parts is dash (-) and can be changed if desired. CSS class names configuration is handled via $opts['css'] associative array. Here are possible configuration options related to this issue. $opts['css']['prefix']   prefix of every &name; CSS class (pme by default) $opts['css']['page_type']   if page type should occur in class name (disabled by default) $opts['css']['position']   if position on the page should occur in class name (disabled by default) $opts['css']['divider']   how many list table rows should have their own number before starting counting again from 0 (by default 2; value of -1 means every row has its own number and value of 0 means disabled) $opts['css']['separator']   separator between CSS class name parts (dash - by default) For concrete names of CSS classes look into HTML source code of your generated page. In the following box are examples of how CSS class names may appear. However your CSS class names can differ according to your fields and configuration respectively. CSS class name examples