TYPO3 Extension Development

By Dmitry Dulepov
  • Instant online access to over 8,000+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies

About this book

TYPO3 is the enterprise-level content management system for the Web. It is large, feature-rich and very flexible—a lot of this flexibility comes through extensions written by the community. Extensions make it possible to use TYPO3 to drive any type of website, including e-commerce, blogs, social networks, catalogs, and many more. TYPO3 can be completely customized using extensions; however creating an extension can be a challenging task.

This book describes TYPO3 extension creation as it should be done. It starts from an overview of the TYPO3 API and provides recommendations on when and how to use this extensive API. Next it describes the TYPO3 extension generation process. It covers all generation options and emphasizes important decisions that extension developers should be aware of.

Since front-end plugins are the most popular TYPO3 extension type, the book has a chapter dedicated to the process of programming front-end plugins. We then move on to back-end plugin programming. All chapters stress best practices and come with unique tips from the author, who wants his experience to be shared with the TYPO3 community. The book finishes with a chapter about improving code and writing documentation.

Publication date:
September 2008
Publisher
Packt
Pages
232
ISBN
9781847192127

 

Chapter 1. About TYPO3 API

Let's get a picture of TYPO3 API before we start to talk about extension creation. There are a lot of files, functions, and function groups in TYPO3 API. Beginners can easily miss the function they should use in a particular part of the code.

This chapter is going to discuss TYPO3 API. We will not go into the details, but will provide pointers to where developers can look. The best way to read this chapter is to keep a copy of each discussed PHP file and read function description inside that file along with the description mentioned in the book.

After completing this chapter, the reader will have a general picture of TYPO3 API, and will be able to find the necessary functions in the API.

Overview of TYPO3 API

TYPO3 is a large system with lots of PHP classes. Trying to learn each class in order to learn the API is time consuming, and will not provide an understanding of the system as a whole. It is much easier to logically split the system into blocks and look at the API from this perspective.

As seen from the user experience, TYPO3 has two main parts: the Frontend (or FE) and the Backend (or BE). Website visitors see the FE of TYPO3. Website editors create and modify the website content from the BE of TYPO3.

The TYPO3 API can be divided approximately the same way: FE API and BE API. The FE API includes classes to create website output, while the BE API includes classes for content manipulation and other functionality to help editors do their work in an effective way. Extensions can extend existing or add new APIs to the system. One of the best examples is TemplaVoila. It adds point-and-click templates to the TYPO3 BE and flexible content elements to the FE.

However, there is one more part, which is not visible to website visitors or editors but used by both FE and BE API. There is no name for it in TYPO3. In this book, we will call it the Common API. An example of such an API is the database API. It would be wrong to use different database layers for BE and FE (otherwise programmers would have to learn more APIs and would tend to use the one most convenient instead of the one "assigned" to Backend or Frontend). So, TYPO3 has only one layer that works with the database. All system classes and extensions are expected to use this API to access and retrieve data from the database.

While we can logically separate the TYPO3 API into three parts, it should be noted that most TYPO3 classes and functions have a very long history. They are constantly updated, but their age is still visible. Most classes are in the same file system directory (t3lib), and it is hard to tell where the class really belongs just by looking at its name. However, this applies only to the file system. Generally, these classes include functions for a single API group only. So logically, they are well-designed and separated from other groups.

The TYPO3 core team makes every effort to keep the API clear, logical, and effective. Extension developers can learn a lot about TYPO3 by looking into the implementation of the TYPO3 API while programming extensions. This is really a good way to become a TYPO3 professional.

In the following sections, we will look at each API group and certain classes inside them. Due to the large number of API classes, it is not possible to cover them all. It would take the whole book alone to cover them all. So, we are going to cover only those classes that extension developers will most likely meet or use during extension development. We are going to start with the most basic and universal classes and move on to more specialized classes. Note that this chapter will provide only an overview of the API, and not a detailed description of each function. We will look deeper into many of these classes later in the book.

But first, we need to discuss certain basic issues about TYPO3 from a developer's view.

 

Overview of TYPO3 API


TYPO3 is a large system with lots of PHP classes. Trying to learn each class in order to learn the API is time consuming, and will not provide an understanding of the system as a whole. It is much easier to logically split the system into blocks and look at the API from this perspective.

As seen from the user experience, TYPO3 has two main parts: the Frontend (or FE) and the Backend (or BE). Website visitors see the FE of TYPO3. Website editors create and modify the website content from the BE of TYPO3.

The TYPO3 API can be divided approximately the same way: FE API and BE API. The FE API includes classes to create website output, while the BE API includes classes for content manipulation and other functionality to help editors do their work in an effective way. Extensions can extend existing or add new APIs to the system. One of the best examples is TemplaVoila. It adds point-and-click templates to the TYPO3 BE and flexible content elements to the FE.

However, there is one more part, which is not visible to website visitors or editors but used by both FE and BE API. There is no name for it in TYPO3. In this book, we will call it the Common API. An example of such an API is the database API. It would be wrong to use different database layers for BE and FE (otherwise programmers would have to learn more APIs and would tend to use the one most convenient instead of the one "assigned" to Backend or Frontend). So, TYPO3 has only one layer that works with the database. All system classes and extensions are expected to use this API to access and retrieve data from the database.

While we can logically separate the TYPO3 API into three parts, it should be noted that most TYPO3 classes and functions have a very long history. They are constantly updated, but their age is still visible. Most classes are in the same file system directory (t3lib), and it is hard to tell where the class really belongs just by looking at its name. However, this applies only to the file system. Generally, these classes include functions for a single API group only. So logically, they are well-designed and separated from other groups.

The TYPO3 core team makes every effort to keep the API clear, logical, and effective. Extension developers can learn a lot about TYPO3 by looking into the implementation of the TYPO3 API while programming extensions. This is really a good way to become a TYPO3 professional.

In the following sections, we will look at each API group and certain classes inside them. Due to the large number of API classes, it is not possible to cover them all. It would take the whole book alone to cover them all. So, we are going to cover only those classes that extension developers will most likely meet or use during extension development. We are going to start with the most basic and universal classes and move on to more specialized classes. Note that this chapter will provide only an overview of the API, and not a detailed description of each function. We will look deeper into many of these classes later in the book.

But first, we need to discuss certain basic issues about TYPO3 from a developer's view.

 

PHP Classes and Files


There are certain conventions concerning file and class naming in TYPO3. They must be used in extensions too and knowing these conventions helps to locate files quickly.

Each class file starts with class. and is followed by a class name in lower case. The file ends with a .php extension. There are certain exceptions to this rule, and they will be described in this book. These exceptions exist due to historical reasons, and no new class may become an exception.

Classes have a certain prefix that declares where they belong in the TYPO3 class hierarchy. The following system prefixes are defined:

  • t3lib_

  • tslib_

  • tx_

  • ux_

  • user_

Each prefix corresponds to a "library" if it ends with "lib_", and to a "namespace" otherwise. "Library" is just a way to say that a "namespace" belongs to TYPO3. In other words, library classes are TYPO3 classes. Extensions cannot introduce new library classes.

t3lib_

t3lib stands for "TYPO3 library". This name is historical, and everyone just calls it t3lib (tee-three-lib). t3lib is the largest collection of classes in TYPO3. It includes most Common, FE, and BE classes. It is easy to say that a class belongs to t3lib by looking at its name. Here are some examples:

  • t3lib_DB

  • t3lib_div

  • t3lib_TCEmain

We will look at some t3lib classes later in this chapter.

tslib_

tslib stands for "TypoScript Library", The name has historical reasons as well and everyone calls this library tslib (tee-es-lib). It is located in the typo3/sysext/cms/tslib directory (inside the cms system extension). Most of these classes are already included when code runs in FE. So there is no need to include them explicitly in extensions.

The library classes are responsible for the rendering of the website and most of the FE logic. The base class for FE plugins (modules that extend TYPO3 Frontend functionality) is also located here.

We will discuss tslib classes in the Frontend API section.

Here is a list of some classes in tslib:

  • tslib_fe

    This is the main FE class in TYPO3. It represents a page that a website visitor sees in the browser. There is only one instance of this class in TYPO3 FE, and it is available as and generally referred as "TSFE".

  • tslib_cobj

    This is one of the exclusions to generic naming rule mentioned earlier. This class is located in the file named class.tslib_content.php, but the class name is different. This class implements content objects. Content objects is a TYPO3 way of generating different types of content. There are many content objects, for example, TEXT, IMAGE, or HMENU. They are the same content objects as found in TypoScript. FE plugins from extensions are USER or USER_INT content objects. Instances of this class can either be created directly (see later in this chapter), or by calling .

  • tslib_fetce

    This is an attempt to bring some BE functions (such as clear_cacheCmd) to the FE. While this class exists, it is not really updated and should not be used.

  • tslib_feuserauth

    This is an internal class that authenticates website visitors ("Frontend users"). This class is created and used by TSFE. An instance of this class is always available as .

  • tslib_pibase

    This is a base class for FE plugins. We will cover it in detail in Chapter 5.

tx_

This namespace is reserved for extensions ("tx" stands for "TYPO3 Extensions"). All extension classes must begin with tx_ (with the exception of "ux" classes).

ux_

This namespace is reserved for XCLASSes. XCLASS is a way to subclass a class in TYPO3 and make use of the subclass instead of the parent class in a way that is transparent to all the other classes in the system. Normally, XCLASSes are provided by extensions. XCLASSes take the class and file name of the parent class but prepend it with ux_, as in class.ux_tslib_fe.php or class.ux_t3lib_tcemain.php.

While XCLASSes may seem the easiest way to modify system behavior, they should be avoided and used only if there is absolutely no other way to change system behavior. The fundamental limitations of XCLASSes is that there can be only one XCLASS for a given class in the system. If two extensions try to XCLASS the same class, only the last one will succeed.

user_

This namespace is reserved for PHP functions outside of a class. TYPO3 will refuse to call any function outside of a class that is not prefixed with user_. If an extension key has this prefix, it means that the extension is private. Such extensions cannot be sent to the TYPO3 Extension Repository. Typically, such extensions are created for testing purposes.

 

How Data Is Stored in TYPO3


TYPO3 uses a database (typically MySQL) and the file system to store data. The file system keeps configuration files, some cache files, images, and uploaded files. The database stores pages, content elements, and lots of system data (such as TypoScript templates, logs, and so on).

All (to be precise most, but for our purpose, all) tables in TYPO3 roughly follow the same structure. They have a set of predefined (reserved) fields. TYPO3 will not work properly if one or more of the required fields is missing. Examples of predefined fields are uid (unique identifier of the record), pid (id of the page where this record is located), crdate (record creation time), tstamp (last update time), cruser_id (uid of the Backend user, who created this record). A table may also contain other reserved fields. If it does, TYPO3 will automatically provide additional functionality for the table. The best examples of such fields are deleted (indicates whether a record is deleted), starttime (indicates when a record becomes visible in the FE), endtime (indicates when a record stops being visible), and hidden (indicates whether a record is hidden). There are other fields, which will be discussed later. All these fields are managed by the system, and extensions usually do not change them.

TYPO3 comes with several default tables. These main tables are:

  • pages and pages_language_overlay

    The pages table stores page data (uid, title, and so on), while the pages_language_overlay table stores translations of the page data.

  • tt_content

    This table stores information about content elements. This is usually one of the largest tables in the system.

  • be_*

    This table stores information related to BE users.

  • cache_*

    This table stores cache data.

  • fe_*

    This table stores information related to FE users.

  • sys_*

    This tables stores various system data.

  • tx_*

    This table stores tables from extensions.

If an extension provides a new table, it must ensure that the table name has a certain format. The table name must start with tx_, followed first by the extension key without underscores and next by an underscore, and the table name. For example, an extension with the extension key my_ext can have the following valid table names:

  • tx_myext_data

  • tx_myext_elements

The following table names are not valid:

  • data

  • myext_data

  • my_ext_data

  • data_my_ext

  • tx_my_ext_data

We will discuss tables in more detail when we generate extensions later in this book. At the moment, it is important to remember two things:

  • There are certain naming conventions for tables.

  • Each table must have a certain set of fields.

 

Common TYPO3 API


As explained earlier, all TYPO3 API functions can be divided into three groups. The Common API group contains classes that are common in the other two groups, FE and BE API. These classes are essential for extension developers because they are either "most used" or "most must-be-used". We will examine these classes in the later sections. Since this chapter is called "About TYPO3 API", its purpose is to provide an overview, and not a fully detailed description. You can use this chapter as a guideline and learn more by looking at the source code of the discussed classes.

Database API

Database API is the most independent class of all the TYPO3 API classes. It contains functions to manipulate data in the MySQL database. The class name is t3lib_DB. There is no TYPO3-specific functionality, only a set of convenient methods to access the database. The instance of this class is available, both in FE and BE, as $GLOBALS['TYPO3_DB'].

All core classes and all extensions must work with the TYPO3 database by using t3lib_DB. This ensures that the database is accessed correctly. Using MySQL PHP functions directly is strongly discouraged and may, in certain cases, interfere with TYPO3 database access, or even break the TYPO3 database.

Besides convenient methods, t3lib_DB has another purpose. Since this is an API class, it can be XCLASSed to provide access to other databases transparent to the rest of TYPO3. This is what the extension DBAL does.

Here is an example of how the TYPO3 database can be accessed using t3lib_DB:

// Select number of non-deleted pages
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
'COUNT(*) AS t', 'pages',
'deleted=0');
if ($res !== false) {
// Fetch array with data
$row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
if ($row !== false) {
$numberOfDeletedPages = $row['t'];
}
// Free resultset (or memory leak will happen)
$GLOBALS['TYPO3_DB']->sql_free_result($res);
}

As you can see, these functions look very similar to MySQL PHP functions. This similarity is not accidental. The default database for TYPO3 is MySQL, and the database API is modeled using MySQL PHP functions.

Generally, all functions can be divided into several groups.

The first group consists of functions that generate various SQL queries. Functions accept certain parameters (such as field names, table name, SQL WHERE condition, and so on) and return a properly constructed SQL query. This is good for extensions that need compatibility with different database types. However, it should be noted that these functions cannot always be used, especially if the query is complex, such as with SQL JOIN constructs, and so on. Functions in this group are:

  • function INSERTquery($table,array $fields_values, $no_quote_fields=FALSE)

  • function UPDATEquery($table,$where,array $fields_values, $no_quote_fields=FALSE)

  • function DELETEquery($table,$where)

  • function SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')

The next group is similar to the first group. It consists of functions that build and execute queries. Most functions in this group are built around functions belonging to the first group. Here you may ask a question: why does the first group exist then? The answer is simple. Sometimes, you want to get a query first, log it somewhere, and then execute it. In that case, you may want to use functions from the first group.

Here is a list of functions from the second group:

  • function exec_INSERTquery($table,array $fields_values, $no_quote_fields=FALSE)

  • function exec_UPDATEquery($table,$where,array $fields_values, $no_quote_fields=FALSE)

  • function exec_DELETEquery($table,$where)

  • function exec_SELECTquery($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='')

  • function exec_SELECT_mm_query($select,$local_table, $mm_table,$foreign_table,$whereClause='',$groupBy='', $orderBy='',$limit='')

  • function exec_SELECT_queryArray($queryParts)

  • function exec_SELECTgetRows($select_fields,$from_table,$where_clause,$groupBy='',$orderBy='',$limit='',$uidIndexField='')

The last three functions may raise questions. Two of them are rarely used. The exec_SELECT_mm_query function is a TYPO3 way to execute a query on tables with many-to-many relations. The exec_SELECT_queryArray function executes a SELECT SQL query, taking parameters from the passed array. This function is rarely used. The last one will perform a SELECT SQL query, fetch rows, and return them in an array. This function should be used with caution; if the result is big, it may exhaust PHP memory easily. But for some results, it is the most convenient way to fetch data from the database.

The next group includes functions to fetch the result, get the number of rows, and so on. They are identical to the corresponding MySQL PHP functions. They are so trivial that we will not discuss them much, only list them here for the sake of completeness:

  • function sql_query($query)

  • function sql_error()

  • function sql_num_rows($res)

  • function sql_fetch_assoc($res)

  • function sql_fetch_row($res)

  • function sql_free_result($res)

  • function sql_insert_id()

  • function sql_affected_rows()

  • function sql_data_seek($res,$seek)

  • function sql_field_type($res,$pointer)

One important note for extension authors: do not forget to call the sql_free_result() function! Though the PHP manual says that MySQL resources are automatically released when the script terminates, in practice, this does not always happen (especially, if persistent connections are enabled). Moreover, if DBAL is enabled, automatic freeing of resources may not always work. It is always better to clean them up in the code.

The last group of functions are the utility functions. While we are looking at it as the last group, functions in this group are used (or must be used) all the time. This group includes functions to escape database parameters and to do query manipulation. Here is a list:

  • function fullQuoteStr($str, $table)

  • function fullQuoteArray($arr, $table, $noQuote=FALSE)

  • function quoteStr($str, $table)

  • function escapeStrForLike($str, $table)

  • function cleanIntArray($arr)

  • function cleanIntList($list)

  • function stripOrderBy($str)

  • function stripGroupBy($str)

  • function splitGroupOrderLimit($str)

  • function listQuery($field, $value, $table)

  • function listQuery($searchWords, $fields, $table)

The fullQuoteStr() function is possibly the most used (or again—the most "must-be-used") function in this group. It escapes all special characters in the string and additionally wraps the string in quotes in a manner compatible with the current database. Therefore, extension developers should use this function for both escaping and quoting parameters, and not use any "home-made" solution. This is a good security-related function. Other functions do more or less the same but in more specialized way. The "strip" and "split" functions are specific for some TYPO3 core calls (but can be called by extensions too).

Now, we are ready to see more complex examples of database API functions. Notice that this example is focused on the database API only. You should not use this code in the extension because it lacks certain calls to other APIs, is not effective from the point of view of database performance, and uses echo (TYPO3 uses other ways of showing generated content). But this example gives a good idea of how to use the database API.

/**
* Retrieves all news written by the given author
*
* @param string $authorName Author name
* @return array A list of news items for author
*/
function findNewsByAuthor($authorName) {
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid,title', 'tt_news', 'author=' . $GLOBALS['TYPO3_DB']->fullQuoteStr( $authorName, 'tt_news'));
$news = array();
while (false !== ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))) {
$news[$row['uid']] = $row['title']
}
$GLOBALS['TYPO3_DB']->sql_free_result($res);
return $news;
}
/**
* Marks all news written by the given author as deleted
*
* @param string $authorName
* @return void
*/
function deleteNewsForAuthor($author) {
$news = findNewsForAuthor($author);
$fields = array('deleted' => 1);
foreach ($news as $uid => $title) {
echo 'Deleted news item with id=' . $uid . ' (' . $title . ')' . chr(10);
$GLOBALS['TYPO3_DB']->UPDATEquery('tt_news', 'uid=' . $GLOBALS['TYPO3_DB']->fullQuoteStr(
$uid, 'tt_news'), $fields);
if ($GLOBALS['TYPO3_DB']->sql_affected_rows() == 0) {
echo 'The above news item was already deleted';
}
}
}

Extension Management

Extension management is a class with functions that provides various levels of information about extensions. This class is not to be confused with TYPO3 Extension Manager.

The Extension management class is named t3lib_extMgm. The functions that developers are likely to use are:

  • function isLoaded($key,$exitOnError=0)

    Checks if an extension is loaded. Useful if the extension uses functionality of another extension.

  • function extPath($key,$script='')

    Returns the absolute path to the script $script in the extension identified by $key. The $script variable contains a path relative to the extension directory. This can be used in the require_once PHP function.

  • function extRelPath($key)

    Returns a path to the extension directory relative to the /typo3 directory. This can be used for <a>, <img>, <link>, or <script> tags to include the extension's files in Backend scripts.

  • function siteRelPath($key)

    Returns a path to the extension directory relative to the site root. It is used for the same purpose as extRelPath, but in the FE.

Here are some code examples:

$extkey = 'templavoila';
require_once(t3lib_extMgm::extPath($extkey,
'pi1/class.tx_templavoila_pi1.php'));
// From Backend:
$link = '<a href="' . t3lib_extMgm::extRelPath($extkey) .
'mod1/index.php">Reload</a>';
// From Frontend
$link = '<img src="' . t3lib_extMgm::siteRelPath($extkey) .
'res/image.gif" />';

There are also other functions to use form extensions, but we will discuss them in detail when we meet them because they have very specific usage.

Helper Functions (t3lib_div)

There is a class in TYPO3 that contains the largest collection of various public functions (138 at the time of writing). This class is probably the most used one in TYPO3. The class name is t3lib_div. It is located in t3lib/class.t3lib_div.php.

All functions in this class are divided into several groups. Most popular functions will be described in the forthcoming sections. They all need to be called statically (using t3lib_div::funcName() syntax). The t3lib_div function is always included and available in any extension. There is no need to include this file in your own scripts.

If you think you need a generic function, it is good to check if t3lib_div already has it, before writing your own.

GET/POST Functions

The Get and Post functions should be used in TYPO3 extensions to obtain values of request variables. While PHP contains variables such as $_GET and $_POST that can be used in scripts, TYPO3 coding guidelines require one to use TYPO3 functions to obtain values of request parameters. TYPO3 runs on many different web servers, and some of them have different ways of passing parameters to PHP scripts. Using TYPO3 functions ensures that the script always gets the parameter, regardless of the web server. The TYPO3 core team will fix the core if a new platform is found causing troubles with script parameters. This way extensions become independent of the differences in web server implementation. Extension authors can concentrate on their code instead of making workarounds for web servers.

The following functions are defined:

  • function _GP($var)

    This function retrieves the value from POST and, if not found, from GET request parameters.

  • function _GET($var=NULL)

    Retrieves value from GET request parameter.

  • function _POST($var=NULL)

    Retrieves value from POST request parameter.

  • function _GETset($inputGet,$key='')

    Sets the value of GET request parameter. There is no equivalent for POST.

  • function GParrayMerged($var)

    Many TYPO3 modules pass parameters in URLs as arrays. If PHP finds something like tx_extkey_pi1[param]=123 in the URL, tx_extkey_pi1 will be an array with a key named param and value, 123. This function will merge such an array for POST and GET, with POST taking preference, and returning this array.

String Functions

There are several functions in this group that perform common tasks:

  • function fixed_lgd_cs($string,$chars)

    This function will crop a string and append three dots to the string. The $chars variable indicates the length. If the value is negative, it will crop that amount of characters from the end of the string. This function will work well only if $GLOBALS['LANG'] (see section about localization) is set. So it is generally limited to BE scripts usage.

  • function testInt($var)

    This function checks if the passed variable is an integer. Variables in PHP can be freely converted between types. For example, '2'+'3' gives 5. This function will return true for 3 and '3', but not for '3x'. Thus, it is very convenient to validate some parameters (like database identifiers).

  • function isFirstPartOfStr($str,$partStr)

    The name of this function is self-explanatory.

  • function validEmail($email)

    This function checks if the passed email has the correct syntax. It does not check whether that domain is valid or whether the mail account exists.

Array Functions

Array functions manipulate array data. Here is the list of the most useful functions:

  • function implodeArrayForUrl($name,$theArray,$str='',$skipBlank=0, $rawurlencodeParamName=0)

    This function creates a URL query string from the passed array. Keys become parameter names, values become parameter values. If $name is not empty, each parameter becomes a value in the array with this name (see description of GParrayMerged above). The $str variable must be blank (TYPO3 uses it internally when calling this function recursively).

  • function array_merge_recursive_overrule($arr0,$arr1,$notAddKeys=0, $includeEmtpyValues=true)

    This function recursively merges two arrays. The second array overrides the first. If $notAddKeys is set, key/value pairs from the second array are ignored if the corresponding key does not exist in the first array.

  • function csvValues($row,$delim=',',$quote='"')

    Creates a comma-separated string of values and takes care of new line characters. The result can be imported into a spreadsheet application. Note that it works on a single row of data and should be called as many times as there are rows. Useful for dumping data into CSV files.

XML Processing

There are only two very specific functions that we will mention here. They are used to convert XML to a PHP array, and vice versa.

  • function array2xml($array,$NSprefix='',$level=0,$docTag='phparray',$spaceInd=0, $options=array(),$stackData=array())

    This function converts a PHP array into XML. We will not describe it in detail here. but recommend that you refer to the documentation inside this function to see all possible options (there are too many of them).

  • function xml2array($string,$NSprefix='',$reportDocTag=FALSE)

    Converts an XML string into an array.

Before using these functions, you should remember that PHP arrays cannot have multiple values with the same key. So, if there are repeating nodes in your XML, you have to add an attribute named index to them. This attribute becomes a key. Here is an example:

<data>
<node index="1"><value>value 1</value></node>
<node index="2"><value>value 2</value></node>
<node index="3"><value>value 3</value></node>
</data>

Running xml2array produces the following PHP array:

Array
(
[1] => Array
(
[value] => value 1
)
[2] => Array
(
[value] => value 2
)
[3] => Array
(
[value] => value 3
)
)

Without the index attribute, the array becomes:

Array
(
[node] => Array
(
[value] => value 3
)
)

File, Directory, and URL Functions

These functions perform the most common tasks for file, directory, and URLs. Here is the list:

  • function getURL($url, $includeHeader=0)

    This function fetches a URL and returns the result. This function must be used instead of fopen() or file_get_contents() because PHP functions may be disabled by security settings on the server. However, getURL may use other methods to fetch the content of the URL.

  • function writeFileToTypo3tempDir($filepath,$content)

    This function writes a file to the TYPO3 temporary directory.

  • function getFilesInDir($path,$extensionList='', $prependPath=0,$order='')

  • function getAllFilesAndFoldersInPath($fileArr,$path, $extList='',$regDirs=0,$recursivityLevels=99)

  • function fixWindowsFilePath($theFile)

  • function locationHeaderUrl($path)

    This function takes a path and returns a correct URL to be used for redirection using the header() PHP function.

Debug Functions

These functions dump passed variables. Note that the web IP address of website visitors must be included in the devIPmask parameter in the TYPO3 Install tool, so that these functions can be used for urgent debugging on a live site!

  • function print_array($array_in)

  • function debug($var="",$brOrHeader=0)

  • function debug_trail() Returns stack trace with entries separated by //.

  • function debugRows($rows,$header='')

System Functions

These are general-purpose functions. They do not fit into any other group. Therefore we list them here:

  • function getThisUrl()

  • function linkThisScript($getParams=array())

    Returns a link to this script. All the parameters are preserved. It is possible to override the parameters by passing an array with new name/value pairs.

  • function linkThisUrl($url,$getParams=array())

    This function is similar to the previous function except that it returns a link to the URL.

  • function getIndpEnv($getEnvName)

    This function is the way TYPO3 gets server variables such as HTTP_HOST or REMOTE_ADDR. TYPO3 runs on many platforms and under many web servers. Not all these servers return parameters in the same way. This function takes care of the differences, and will always return a server parameter, regardless of the server software. It must be used instead of $_SERVER and $_ENV PHP variables. In addition, this function can return values of TYPO3-defined variables. Here is a list of these variables:

    • TYPO3_HOST_ONLY

      Host name

    • TYPO3_PORT

      Port (blank if 80, taken from host value)

    • TYPO3_REQUEST_HOST

      [scheme]://[host][:[port]]

    • TYPO3_REQUEST_URL

      [scheme]://[host][:[port]][path]?[query]

    • TYPO3_REQUEST_SCRIPT

      [scheme]://[host][:[port]][path_script]

    • TYPO3_REQUEST_DIR

      [scheme]://[host][:[port]][path_dir]

    • TYPO3_SITE_URL

      [scheme]://[host][:[port]][path_dir] of the TYPO3 website Frontend

    • TYPO3_SITE_SCRIPT

      [script / Speaking URL] of the TYPO3 website

    • TYPO3_DOCUMENT_ROOT

      Absolute path of root of documents: TYPO3_DOCUMENT_ROOT.SCRIPT_NAME = SCRIPT_FILENAME (typically)

    • TYPO3_SSL

      Returns TRUE if this session uses SSL/TLS (https)

TYPO3-Specific Functions

There are a lot of functions here that also fall into categories we have already seen. However, the functions discussed earlier are universal. They do not depend on TYPO3 variables and can generally be reused outside TYPO3. Functions from this group take TYPO3 into account. There are lots of them. We list only the ones that are likely to be used in extensions:

  • function validPathStr($theFile)

  • function tempnam($filePrefix)

    Creates a temporary file in the typo3temp/ directory.

  • function loadTCA($table)

    Loads the table configuration array (TCA). We will discuss the TCA later in this book.

  • function callUserFunction($funcName,&$params,&$ref, $checkPrefix='user_',$silent=0)

    Calls the user function. The function name has a certain format (see "TYPO3 File References" section that follows).

  • function &getUserObj($classRef,$checkPrefix='user_',$silent=0)

    Instantiates a class and returns its instance.

  • function &makeInstance($className)

    Creates an instance of the class, given its name. This function must be used instead of the new PHP operator. It takes care of proper XCLASS handling. Use this function even for your internal classes!

  • function makeInstanceClassName($className)

    Checks if XCLASS is available for any given class and returns either the class or XCLASS name. It is useful when instantiating an object with parameters for the constructor. For example, function devLog($msg, $extKey, $severity=0, $dataVar=FALSE) logs messages to the developer log. By default, it does nothing. Requires logging extension (such as cc_devlog or rlmp_filedevlog) and SYS_DLOG enabled in TYPO3 Install tool. It is useful in recording a sequence of events on a production server. Beware of performance decline

TYPO3 File References

TYPO3 has a special syntax to refer files or classes and functions inside files. Typically, it is used for extensions. This syntax is similar to a URL. Check the following code fragment:

$params = array();
$result = t3lib_div::callUserFunction( 'EXT:myext/subdir/class.tx_myext_class.php:' . 'tx_myext_class->main', $params, $this);

The callUserFunction function will read the function name as follows:

  • EXT means that the function has an extension.

  • Extension key follows the EXT: prefix until the first slash.

  • Everything until the colon is the file path.

  • If there is a -> sequence, then the function is a method of the class. The class will be instantiated using t3lib_div::makeInstance() and a method of the class will be called. The class name must start with tx_ or ux_ or user_. If there is no -> sequence, then it is a function without a class, and its name must start with user_. If the class or function name does not start with a proper prefix, then callUserFunction will refuse to call them.

The getUserObj function is similar to the callUserFunction function except that it does not have a function part, but a class name. It returns a class instance and the extension can call methods of this class. Name restrictions apply to getUserObj as well.

Language Support

TYPO3 supports many languages and works very well with them. It has a set of functions and classes that provide access to localized (translated) strings. These strings are stored in XML files. Extensions need not care about finding the right language or parsing XML because TYPO3 has a very good API for it. While using this API, all strings from XML can be referenced by their index. The index is also a string, but it stays non-localized. A string changes, but its index does not. So it is always possible to find the value of the string by its index. To give a short example, the "Click here" string may have a "click_here" index (the code example at the end of this section will make it clearer).

Usually, localization is one of the areas that lacks a developer's attention. It is much easier to hard-code strings in the PHP code than to write them to an XML file and add an extra line to load that string. But supporting translations is one thing that makes a good extension. Do not postpone the creation of language files. Do it properly from the beginning; do not hard-code. Write a string to an XML file and use the API to get its value.

What happens if an extension is not translated to another language (partially or fully)? The labels in the default language (English) will be used instead.

The class that implements localization support for strings is an old class and, as many old classes, it is an exception to the naming rule described earlier in this chapter. The class name is language and it is located in typo3/sysext/lang (system extension lang). In the BE, it is usually available as $GLOBALS['LANG']. In the FE, it is not available directly, but there are similar ways to get localized strings.

The following methods are the most used ones:

  • function init($lang,$altPath='')

    This function initializes the language class for the given language code. Languge code is TYPO3-specific. The special code value default refers to the English language. You will rarely need to use this function. Generally, it is enough to know that you have to call this function if for any reason you need to create an instance of the language class yourself. But if you really have to, it means that you are doing something nontrivial, and you should be an experienced extension writer to use this function.

  • function getLL($index,$hsc=0)

    This function returns a label by its string index. Labels must be included using the includeLLFile function (see below).

  • function getLLL($index,$LOCAL_LANG,$hsc=0)

    Does the same as getLL, but uses the $LOCAL_LANG argument to search for the string.

  • function sL($input,$hsc=0)

    This function is the most complex but also the most powerful among all the functions in this class. It accepts string reference in a special format and returns the string. The string reference format is similar to the format described earlier in the section named "TYPO3 File References", but it must be prepended with the LLL: prefix, for example, LLL:EXT:lang/locallang_general.xml:LGL.image. This reference tells TYPO3 to load a string identified by LGL.image index from the file named locallang_general.xml in lang extension. The $hsc parameter allows automatic application of the htmlspecialchars PHP function to the returned string.

  • function includeLLFile($fileRef,$setGlobal=1, $mergeLocalOntoDefault=0)

    This function loads information from a language file into a global variable for use with the getLL function. It accepts EXT: file referencing format for files as well as the absolute path.

  • function readLLfile($fileRef)

    This function reads a language file and returns labels for the current language to the caller. It also accepts the EXT: syntax for $fileRef.

Here is a full code example:

require_once(t3lib_extMgm::extPath('lang', 'lang.php'));
$lang = t3lib_div::makeInstance('language');
/* @var $lang language */
$lang->init('default');
$fileRef = 'EXT:lang/locallang_general.xml';
$label1 = $lang->sL('LLL:' . $fileRef . ':LGL.image');
$LL = $lang->readLLfile($fileRef);
$label2 = $lang->getLLL('LGL.image', $LL);
$lang->includeLLFile($fileRef);
$label3 = $lang->getLL('LGL.image');

All three labels are identical in this example.

Reference Index

TYPO3 stores data in the database. Often, data records refer to other data records or files in the file system. If a data record is deleted and it has a reference to a file, the file stays in the file system. If another data record refers to the deleted data record, there will be a dead link.

To prevent these kinds of problems, TYPO3 maintains a separate list of references between data records and files in the system. This is called the "reference index". The class name is t3lib_refindex.

When data records are created, modified, or deleted in Backend using TCEmain (described in the Backend API section below), the system will update the reference index automatically. FE is different; TCEmain does not work there. FE plugins usually insert data directly into the database using the database API described earlier in this book. So, extension developers have to take care and update the reference index manually. Unfortunately, very few extensions do. Originally, the reference index was developed for BE usage, but its dependency on BE functions is minimal and solved by including class.t3lib_befunc.php in the FE plugin.

When the reference index is used, the system will show a number of references to the current record in the List module, and a clean-up script will be able to detect hanging files and remove them.

We are interested in the following function:

  • function updateRefIndexTable($table,$uid,$testOnly=FALSE)

This function will examine the record and update the reference index. Here are some code examples:

require_once(PATH_t3lib . 'class.t3lib_befunc.php');
require_once(PATH_t3lib . 'class.t3lib_refindex.php');
$fields = array(
// Fill array with fields
);
$GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_myext_table',
$fields);
$uid = $GLOBALS['TYPO3_DB']->sql_insert_id();
$refIndex = t3lib_div::makeInstance('t3lib_refindex');
/* @var $refIndex t3lib_refindex */
$refIndex->updateRefIndexTable('tx_myext_table', $uid);

This is all that has to be done to update the reference index. The @var comment helps modern PHP IDEs show code assist for the variable.

Hooks

Hooks in TYPO3 are special functions that the system calls while it performs some actions. Using hooks, extensions can modify a process in the middle, observe system state, pre- and post-process data, and do many other things.

Typically, a hook function is defined either as a regular function with user_ prefix or as a class prefixed with tx_extkey_. Hooks are registered in the extension's ext_localconf.php file (see Chapter 2) in the following way:

$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']
['cms/layout/class.tx_cms_layout.php']
['list_type_Info']['extkey_pi1'][] =
'EXT:extkey/class.tx_extkey_cms_layout.php
:tx_extkey_cms_layout->getExtensionSummary';

This particular hook will provide additional information to the page module to display near the extension's instance.

 

Backend API


This part of the API is used in the Backend. It is not well known to developers because TYPO3 lacks documentation about this part of the API. We will cover the major parts of the Backend API code in this section.

TCEforms

TCEforms is visually familiar to anyone who has used TYPO3.

From a developer's viewpoint, TCEforms is an automated way of presenting the content of a database table to the user in a form suitable for editing. TCEforms reads the table configuration array (or TCA) for the table and builds controls dynamically according to the information in the TCA. The TCA for each TYPO3 core table is stored in the TYPO3 core. Extensions provide additional TCA entries for each extension table. If a TCA entry is not provided for the table, the TYPO3 Install tool will complain about it.

TCEforms is the most complex TYPO3 class you can use from. Its API was never meant for external use, but it is still possible to do it. Though this will not be described in this book, developers can figure it out by looking at the file typo3/mod/user/ws/workspaceforms.php. This file makes use of TCEforms to create custom rendering of workspace records.

TCEmain

TCEmain is the TYPO3 record processor. It handles the following tasks:

  • Record creation, deletion, updation, copying, and moving

  • Clearing the cache

  • Version creation, updating, and publishing

Though this list does not contain all the functions, the class contains over 100 functions and nearly 5500 lines of code. The class name for TCEmain is t3lib_TCEmain.

Most extension developers are interested in the first two entries from the list above. We will review these in the later sections.

Record Manipulation

Record manipulation happens through two functions:

  • process_datamap()

  • process_cmdmap()

These functions do not take any parameters. Parameters must be passed to TCEmain's start() function. If both functions need to be executed, then process_datamap() should be called first.

The process_datamap() function takes care of record creation and updates. The process_cmdmap() function moves, deletes, undeletes, localizes, and creates versions for records.

Both functions expect their data to be in a certain format. As often in TYPO3, data consists of arrays.

The process_cmdmap() function uses the following format for data:

$datamap = array(
$tableName => array(
$recordUid => array(
$fieldName => $fieldValue
)
)
);

Here, $tableName is the database table name. There can be any number of tables in the $datamap. The $recordUid variable is the unique identifier of the record (uid field in the database table). If $recordUid is a string and starts from NEW (followed by a random string), then a new record will be created in the database. $fieldName is a database field name (uid cannot be passed as a field). The $fieldValue variable is an unescaped (raw) field value. The process_cmdmap() function has additional useful features. For example, it is possible to create a page and its content elements at once. The $recordUid variable for the pages table will start with NEW, and pid field for each content element should have the same identifier. TCEmain will substitute pid values automatically. But do not try it with other fields, it will not work as it does with pid. You can also insert a record before another record. In this case, pid field should be a negative value of the other record's uid attribute.

After a record is created, it is possible to obtain record uid values from TCEmain. TCEmain's substNEWwithIDs attribute is an array where keys are NEW-style identifiers, and values are uid values for new database records.

The process_cmdmap() function has similar data format:

$cmdmap = array(
TCEmain, BE APIrecord, manipulating$tableName => array(
$recordUid => array(
$command => $command_data
)
)
);

The next table shows values for $command and the format of $command_data.

Command

Command data format

Move

uid of the page where the record will be moved

copy

uid of the page where the record will be copied

localize

uid of the record from the sys_language table

version

Complex;.beyond the purpose of this book.

delete

empty

undelete

empty

The following code example will create a page with a single text element and delete this page with the element.

require_once(PATH_t3lib . 'class.t3lib_tcemain.php');
$pid = 'NEW' . uniqid('');
$content_uid = 'NEW' . uniqid('');
$tstamp = time();
// Datamap for page and content
$datamap = array(
'pages' => array(
$pid => array(
'pid' => 1,
'title' => $GLOBALS['LANG']->getLL('my_page_title'),
'hidden' => 0,
// Next line says that page is "Standard"
'doktype' => 1,
'crdate' => $tstamp,
'tstamp' => $tstamp,
// Next line says what user created the page
'cruser_id' => $GLOBALS['BE_USER']->user['uid'],
// Set some permissions. See TSConfig document
'perms_userid' =>
$GLOBALS['BE_USER']->user['uid'],
'perms_groupid' => 0, // No group
'perms_user' => 31, // See TSConfig
'perms_group' => 27,
'perms_everyone' => 0,
)
),
'tt_content' => array(
$content_uid => array(
'pid' => $pid,
'header' =>
$GLOBALS['LANG']->getLL('content_title'),
'CType' => 'text',
'bodytext' => 'Hello, TYPO3!',
'crdate' => $tstamp,
'tstamp' => $tstamp,
'cruser_id' => $GLOBALS['BE_USER']->user['uid'],
'colPos' => 0
)
)
);
// Create TCEmain instance
$tce = t3lib_div::makeInstance('t3lib_TCEmain');
/* @var $tce t3lib_TCEmain */
$tce->start($datamap, null);
$tce->process_datamap();
if (count($tce->errorLog) != 0) {
// $tce->errorLog is an array of error messages
}
// Prepare cmdmap to delete created records.
// BE user must have 'recursive delete' enabled
// for this example!
$cmdmap = array();
foreach ($tce->substNEWwithIDs as $new => $uid) {
// $tce->substNEWwithIDs_table is like
// $tce->substNEWwithIDs but contains
// table names
$cmdmap[$tce->substNEWwithIDs_table[$new]][$uid] = array('delete' => '');
}
$tce = t3lib_div::makeInstance('t3lib_TCEmain');
/* @var $tce t3lib_TCEmain */
$tce->start(null, $cmdmap);
$tce->process_cmdmap();
if (count($tce->errorLog) != 0) {
// Process error messages
}

Clearing Cache

If an extension's work affects the content of the page in the FE, the extension must take care of clearing cache for the page. For example, if an extension generates new content, modifies existing content, or creates a record that should be displayed on the page, the page cache has to be cleared.

TCEmain is strictly BE code. But cache pages are written in the way that allows one to use them from FE as well.

There are several functions that can be used to clear cache. As extension developers, we are mostly interested in one. It is named clear_cacheCmd. This function accepts a single parameter. For our purpose, it should be page uid value.

A code example:

require_once(PATH_t3lib . 'class.t3lib_tcemain.php');
// Create TCEmain instance
$tce = t3lib_div::makeInstance('t3lib_TCEmain');
/* @var $tce t3lib_TCEmain */
$tce->clear_cacheCmd(123);

If more than one page has to be cleared, it has to be done in a loop.

 

Frontend API


This part of the API is used in the Frontend. The number of files is relatively small, but the number of functions is very large. We will review only major functions.

TSFE

TSFE (historically stands for "TypoScript Frontend") is the main FE class. It is sometimes called "page" object among developers. This class contains methods that determine page ID, parse TypoScript templates, execute templates, process output and cache it. Also, TSFE is responsible for managing FE user object. TSFE is located in the class tslib_fe (exercise: see if you can guess the path to the file name).

Normally, extensions do not call TSFE methods but use some TSFE class attributes. We will describe the most important attributes here:

  • additionalHeaderData

    This is an array where FE plugins can add HTML tags that should appear between <head> and </head> on the page. It is a good practice to start with tx_yourextkey_ prefix. Do not add inline <script> (<script> tag without src attribute) here!

  • additionalJavaScript

    An array where FE plugins may add inline JavaScript, if necessary. It is a good practice to start with tx_yourextkey_ prefix.

  • config

    This is an array. It is the only member with the config key corresponding to the parsed config object from the current TypoScript setup. This array contains merged entries from config and page.config.

  • fe_user

    An object of the class, tslib_feUserAuth, which represents a FE user. The user attribute of this class contains a record from the fe_users table. If FE user is logged in, $GLOBALS['TSFE']->fe_user->user['uid'] will be set, and t3lib_div::testInt will return true for it.

  • id

    This is the current page ID. It is very often used in FE plugins as $GLOBALS['TSFE']->id.

  • lang

    This attribute is the current language code (string value). This is not the same as the ISO language code. It is TYPO3 code to be used with language files. The value default means English. A full list of codes can be found in typo3/sysext/setup/mod/locallang.xml as a set of lang_* entries.

  • page

    This is a record from the pages table that corresponds to the current page. If the page is loaded in a nondefault language, this record will have that language applied (all fields like title or navigation title will be taken from pages_language_overlay and applied to this record).

  • pSetup

    This is a parsed TypoScript setup for the plugin. This is useful in certain cases. For example, you may want to examine the setup of another plugin. It is a parsed TypoScript array.

  • register

    This is an array of registers (see LOAD_REGISTER in TSRef). FE plugins can set registers, and they will be available to other objects on the page (plugins or TypoScript objects from TypoScript setup). The key is register name, value is register value.

  • rootLine

    This is an array of records from the pages table that represents the path to the current page from the root of the website.

  • sys_language_content

    This is a uid field value for the record in the sys_language table. TYPO3 will select content from the tt_content table with sys_language_uid that matches this value.

  • sys_language_uid

    This is a uid field value for the record in the sys_language table. It corresponds to config.sys_language_uid in TypoScript setup.

  • sys_language_mode

    See config.sys_language_mode in TSRef.

Content Objects

Content objects display information on the page. All content object types are described in TSRef and they are implemented by the class named tslib_cObj, which is located in typo3/sysext/cms/tslib/class.tslib_content.php. A quick look at this class reveals familiar names such as TEXT, HTML, USER, or stdWrap.

This class is used very often in FE plugins. It has lots of very well-documented methods. We will describe many of them in due course when we have to use them in our real extension.

Plugin API

Last but not the least in its importance is the tslib_pibase class. This is a base class for the FE plugins. While it is not mandatory to use it, most plugins do because this class provides many helpful methods. We will discuss this class in detail in Chapter 5 of the book. For now, we should know that this class provides the following function groups:

  • Link generation

    These functions allow plugins to create links with plugin parameters in them.

  • Handling of localized labels

    These functions help to retrieve translated labels from the language files.

  • Frontend editing

    These functions help to add FE editing capabilities to plugins (rarely used by plugins).

  • Database queries

    These functions do specialized database queries. Most of them are equivalents of the t3lib_DB functions.

  • Flexform handling functions

    Flexform is a TYPO3 way of having forms inside forms. They are often used for plugin configuration. These functions initialize flexform data and extract information from flexforms.

 

Summary


In this chapter, we had a very brief overview of TYPO3 API. TYPO3 API is large, and it contains functions that cover almost every need of a typical extension developer. We will actively use TYPO3 API in our own extension in the forthcoming chapters of this book.

About the Author

  • Dmitry Dulepov

    Dmitry Dulepov is a TYPO3 core team member and developer of several popular extensions (such as RealURL, TemplaVoila, comments, ratings, and others). He is known by his active support of the TYPO3 community through TYPO3 mailing lists. In 2008 Dmitry won the contest to appear on the first TYPO3 playing cards. He runs a popular blog where he regularly publishes original tips and articles about various TYPO3 features. In addition to his continuous TYPO3 core and extension development, Dmitry provides support for the TYPO3 translation team on behalf of the core team.

    Browse publications by this author
Book Title
Access this book, plus 8,000 other titles for FREE
Access now