Understanding Content Types
A content type is a datatype (e.g. 'staff', 'document', 'photo', etc.) that has been ascribed fields. Content types are primarily represented using two database tables: datatypes and typesfields. Datatypes holds macro-level information about content types -- e.g. the name of the datatype, the numeric id of the datatype, etc. Typesfields holds the actual fields that compose an object.
As you may know, fields are recycled on an type-by-type basis, so the dbfields or relationships represented in one content type may well be used by another. (e.g. both documents and staff will probably have an field called 'name').
displayname
This is the text that will appear as a label on forms. This text does not need to be unique -- even within a content type. If you are using internationalized content types, then the displayname is the placeholder text that will serve as the translation look-up text with gettext(). In this case you will want to identify your displayname values early and not change them -- so as not to render text translations impossible.
identifier
This is a unique string that identifies the field. This can be thought of as a pseudo column name. It must be unique within the datatype and it must not contain spaces or any special characters. Unlike dbfields the identifier does not need to be generic because it is not used for any other objects -- this means that you don't need to remember that for document objects 'desc1' is the short description, instead you would just specify 'short_description' as the identifier for the field and access it using 'short_description'. Also, the identifier field applies equally to relationships and dbfields.
dbfield
The dbfield directly maps to the actual column in the database. In many cases this can probably be the same as your identifier (if you want) -- e.g. there is a dbfield called 'fname' or 'lname' or 'url'. Many objects you define won't map easily to the existing dbfields and you'll end up using a dbfield called 'text1' for something like a nickname. Because every dbfield you define is a column in records, it is necessary to have generic dbfields that can be assigned to different attributes in different objects (e.g. 'name' for a person's name and the name of an organization, 'text1' for a person's nickname and the subtitle of a book, etc).
If you plan to be accessing data without using the SyntaxCMS data classes (e.g. directly with SQL queries), then you'll need to know the name of the dbfield assigned to an object field. You can always use the sql_aliased_columns() method of the pxdb_data class to get a list of all dbfields (for the specified object) with their identifier aliases, e.g.:
$data = &new pxdb_data($dbh, DT_DOCUMENT);-
$sql = "SELECT " . $data->sql_aliased_columns() . " FROM records WHERE datatype = " . DT_DOCUMENT; // results in: SELECT name AS name, text1 AS subtitle, ... etc ...