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 connectionUnique 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 optionsPage 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 nameDisplayed 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.
TriggersTriggers 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' operationEdit 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 examplesSelect triggersInsert triggersUpdate triggersDelete 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 pageuser asks to view a record['select']['pre'] trigger is included (if defined)if true is returned then continue, else go back to list pageuser is now in the view pageuser asks to edit the record['update']['pre'] trigger is included (if defined)if true is returned then continue, else go back to view pageuser is now in the edit pageuser 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 updatingrecord 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 pageuser is now back to the edit pageuser makes some other changes but asks to cancel them['update']['cancel'] trigger is included (if defined)user is back to the list pageTriggers 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.
LoggingLog 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 variablesUsing 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 variablesJavascript 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 DHTMLCSS 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