1.12. Appendix C – PHP include scripts

Introduction

Although you can do very much with TypoScript itself, it can sometimes be a much more flexible solution to include a PHP-script you write on your own. But you must understand and respect some circumstances. For example the caching system: When a page is shown with TYPO3 it's normally cached afterwards in the SQL-database. This is done to ensure a high performance when delivering the same page the next time. But this also means that you can only make custom code from your include files if you differ your output based on the same conditions that the template may include! For example you cannot just return browser-specific code to TypoScript if not the template also distinguishes between the actual browsers. If you do, the cache will cache the page with the browser-specific HTML-code and the next hit by another browser will trigger the cache to return a wrong page. If the condition is correctly setup "another browser"-hit will instead render another page (which will also be cached but tagged with the other browser!) and the two browsers will receive different pages but still the pages will be cached.

TypoScript Configuration

The following objects are related to the direct inclusion of PHP code inside templates.

PHP_SCRIPT

This includes a PHP-script. You should not name the script ".php" but rather ".inc" as it's meant to be included and not executed on it's own.

NOTE: This option is ignored if $TYPO3_CONF_VARS['FE']['noPHPscriptInclude']=1; is set in localconf.php.

Property:

Data type:

Description:

Default:

file

resource /stdWrap

File that will be included. This file must be valid PHP-code! It's included with "include()";

Directions:

1) All content must be put into $content. No output must be echo'ed out!

2) Call $GLOBALS['TSFE']->set_no_cache(), if you want to disable caching of the page. Set this during development! And set it, if the content you create may not be cached.

NOTE: If you have a parsing error in your include script the $GLOBALS['TSFE']->set_no_cache() function is NOT executed and thereby does not disable caching. Upon a parse-error you must manually clear the page-cache after you have corrected your error!

3) the array $conf contains the configuration for the PHP_SCRIPT cObject. Try debug($conf) to see the content printed out for debugging!

See the appendix later in this manual for an introduction to writing your own PHP include-scripts.

stdWrap

->stdWrap

[tsref:(cObject).PHP_SCRIPT]

PHP_SCRIPT_INT

(see PHP_SCRIPT)

Property:

Data type:

Description:

Default:

file

resource /stdWrap

File that will be included. This file must be valid PHP-code! It's included with "include()";

Purpose:

This basically works like PHP_SCRIPT. But the vital difference is that inserting a PHP_SCRIPT_INT (internal opposed to external, see below) merely inserts a divider-string in the code and then serializes the current cObj and puts it in the $GLOBALS['TSFE']->config['INTincScript']-array. This array is saved with the cached page-content.

Now, the point is, that including a script like this lets you avoid disabling pagecaching. The reason is that the cached page contains the divider string and when a "static" page is fetched from cache, it's divided by that string and the dynamic content object is inserted.

This is the compromise option of all three PHP_SCRIPT-cObjects, because the page-data is all cached, but still the pagegen.php script is included, which initializes all the classes, objects and so. What you gain here is an environment for your script almost exactly the same as PHP_SCRIPT because your script is called from inside a class tslib_cObj object. You can work with all functions of the tslib_cObj-class. But still all the "static" page content is only generated once, cached and only your script is dynamically rendered.

Rules:

- calls to $GLOBALS['TSFE']->set_no_cache() and $GLOBALS['TSFE']->set_cache_timeout_default() makes no sense in this situation.

- parsing errors do not interfere with caching

- Be aware that certain global variables may not be set as usual and be available as usual when working in this mode. Most scripts should work out-of-the-box with this option though.

- Dependence and use of LOAD_REGISTER is fragile because the PHP_SCRIPT_INT is not rendered until after the cached content and due to this changed order of events, use of LOAD_REGISTER may not work.

- You can not nest PHP_SCRIPT_INT and PHP_SCRIPT_EXT in PHP_SCRIPT_INT. You may nest PHP_SCRIPT cObjects though.

includeLibs

list of resource

This is a comma-separated list of resources that are included as PHP-scripts (with include_once() function) if this script is included.

This is possible to do because any include-files will be known before the scripts are included. That's not the case with the regular PHP_SCRIPT cObject.

stdWrap

->stdWrap

[tsref:(cObject).PHP_SCRIPT_INT]

PHP_SCRIPT_EXT

(see PHP_SCRIPT)

Property:

Data type:

Description:

Default:

file

resource /stdWrap

File that will be included. This file must be valid PHP-code! It's included with "include()";

Purpose:

This works like PHP_SCRIPT_INT, because a divider string is also inserted in the content for this kind of include-script. But the difference is that the content is divided as the very last thing before it's output to the browser.

This basically means that PHP_SCRIPT_EXT (external, because it's included in the global space in index_ts.php file!!) can output data directly with echo-statements!

This is a very "raw" version of PHP_SCRIPT because it's not included from inside an object and you have only very few standard functions from TYPO3 to call.

This is the fastest option of all three PHP_SCRIPT-cObjects, because the page-data is all cached and your dynamic content is generated by a raw php-script.

Rules:

- All content can be either 1) echo'ed out directly, or 2) returned in $content.

- calls to $GLOBALS['TSFE']->set_no_cache() and $GLOBALS['TSFE']->set_cache_timeout_default() makes no sense in this situation.

- parsing errors do not interfere with caching

- In the global name-space, the array $REC contains the current record when the file was "inserted" on the page, and $CONF-array contains the configuration for the script.

- Don't mess with the global vars named $EXTiS_*  

includeLibs

list of resource

This is a comma-separated list of resources that are included as PHP-scripts (with include_once() function) if this script is included.

This is possible to do because any include-files will be known before the scripts are included. That's not the case with the regular PHP_SCRIPT cObject.

stdWrap

->stdWrap

[tsref:(cObject).PHP_SCRIPT_EXT]

Including your script

Your script is included by a function, PHP_SCRIPT, inside the class "tslib_cObj" in the "tslib_content.php" script. Thereby your file is a part of this object (tslib_cObj) and function. This is why you must return all content in the variable "$content" and any TypoScript-configuration is available from the array "$conf" (it may not be set at all though so check it with is_array()!)

$conf

The array $conf contains the configuration for the PHP_SCRIPT cObject. Try debug($conf) to see the content printed out for debugging!

$content

Return all content in this variable.

Remember, don't output anything (but debug code) in your script!

White spaces

Because nothing is sent off to the browser before everything is rendered and returned to index_ts.php which originally set of the rendering process, you must ensure that there's no whitespace before and after your <?...?> tags in your include- or library-scripts!

$GLOBALS['TSFE']->set_no_cache()

Call the function $GLOBALS['TSFE']->set_no_cache(), if you want to disable caching of the page. Call this during development! And call it, if the content you create may not be cached.

Note: If you make a syntax error in your script that keeps PHP from executing it, then the $GLOBALS['TSFE']->set_no_cache() function is not executed and the page is cached! So in these situations, correct the error, clear the page-cache and try again. This is true only for PHP_SCRIPT and not for PHP_SCRIPT_INT and PHP_SCRIPT_EXT which are rendered after the cached page!

Example:
$GLOBALS['TSFE']->set_no_cache();

$this->cObjGetSingle(  value  ,  properties  )

   

Gets a content-object from the $conf-array. (See the section below named "Case story" on how to use this!)

Example:
$content = $this->cObjGetSingle($conf['image'], $conf['image.']);

This would return any IMAGE-cObject at the property "image" of the conf-array for the include-script!

$this->stdWrap( value, properties )

stdWrap's the content "value" due to the configuration of the array "properties".

Example:
$content = $this->stdWrap($content, $conf['stdWrap.']);

This will stdWrap the content with the properties of ".stdWrap" of the $conf-array!

Internal Vars in the main frontend object, TSFE (TypoScript Front End)

There are some variables in the global object, TSFE, you might need to know about. These ARE ALL READ-ONLY!! (Read: Don't change them!) See the class tslib_fe for the full descriptions.

If you for instance want to access the variable "id", you can do so by writing: $GLOBALS['TSFE']->id

Var:

PHP-Type:

Description:

Default:

id

int

The page id

type

int

The type

page

array

The pagerecord

fe_user

object

The current front-end user.

Userrecord in $GLOBALS['TSFE']->fe_user->user, if any login.

loginUser

boolean

Flag indicating that a front-end user is logged in.

0

rootLine

array

The rootLine (all the way to tree root, not only the current site!). Current site root line is in $GLOBALS['TSFE']->tmpl->rootLine

sys_page

object

The object with pagefunctions (object) See t3lib/page.php

gr_list

string (list)

The group list, sorted numerically. Group -1 = no login

beUserLogin

boolean

Flag that indicates if a Backend user is logged in!

0

Global vars

Var:

PHP-Type:

Description:

Default:

BE_USER

object

The back-end user object (if any).

not set

TYPO3_CONF_VARS

array

TYPO3 Configuration.

TSFE

object

Main frontend object.

Case story

This is a case story of how to use include-scripts.

In this situation we would like to use some libraries of our very own, not part of TYPO3. Therefore we use the feature of including a library at the very beginning of the page-parsing.

First we put this TypoScript line in the "Setup"-field of the template:

config.includeLibrary = fileadmin/scripts/include.inc

The file include.inc is now included (in typo3/sysext/cms/tslib/pagegen.php). In this case it looks like this:

file:   fileadmin/scripts/include.inc

<?
...
include('fileadmin/scripts/hello_world.inc');
include('fileadmin/scripts/other_library.inc');
...
?>

As you can see, this file includes our library "hello_world" and some other libraries too!

The file hello_world.inc looks like this:

file:   fileadmin/scripts/hello_world.inc

<?
class hello_world {
function theMessage() {
return "Hello World";
}
}
?>

So far nothing has happened, except our libraries are included, ready for use.

Now we need to use the outcome of the class hello_world somewhere on a page. So in the TypoScript code we setup a content-object that includes the third script:

page.100 = PHP_SCRIPT
page.100.file = fileadmin/scripts/surprise.inc

surprise.inc looks like this:

file:   fileadmin/scripts/surprise.inc

<?
$hello_world_object = new hello_world;// New instance is created
$contentBefore = $this->cObjGetSingle($conf['cObj'], $conf['cObj.']);
$content = $contentBefore . $hello_world_object->theMessage();
$content = $this->stdWrap($content, $conf['stdWrap.']);
?>

Line 1: The PHP-object $hello_world_object is created.

Line 2: This fetches the content of a cObject, "cObj", we defined

Line 3: The result of line 2 is concatenated with the result of the "theMessage"-function of the $hello_world_object object

Line 4: Finally the content is stdWrap'ed with the properties of ".stdWrap" of the $conf-array.

The output:

With this configuration -

page.100 = PHP_SCRIPT
page.100.file = fileadmin/scripts/surprise.inc

- the output will look like this:

Hello World

With this configuration -

page.100 = PHP_SCRIPT
page.100 {
file = fileadmin/scripts/surprise.inc
cObj = TEXT
cObj.value = Joe says:&nbsp;
}

- the output will look like this:

 Joe says: Hello World

With this configuration -

page.100 = PHP_SCRIPT
page.100 {
file = fileadmin/scripts/surprise.inc
cObj = TEXT
cObj.value = Joe says:&nbsp;
stdWrap.wrap = <font color="red"> | </font>
stdWrap.case = upper
}

- the output will look like this:

JOE SAYS: HELLO WORLD

End of lesson.

Storing user-data or session-data

Doing so is quite simple with TYPO3.

Userdata is data, that follows login users. As soon as a user, who is logged in, logs out, this data is no more accessible and cannot be altered.

Session data is data, that follows the user currently browsing the site. This user may be a logged in user, but his session-data is bound to the "browsing-session" and not to the user-id of his. This means, that the very same person will carry this data still, even if he logs out. As soon as he closes his browser, his data will be gone though.

Also you should know, that session-data has a default expire-time of 24 hours.

Retrieving and storing user-/session-data is done by these functions:

$GLOBALS['TSFE']->fe_user->getKey(type, key)

"type" is either "user" or "ses", which defines the data-space, user-data or session-data

"key" is the "name" under which your data is stored. This may be arrays or normal scalars.

Note that the key "recs" is reserved for the built-in "shopping-basket". As is "sys" (for TYPO3 standard modules and code)

Example:
if ($GLOBALS['TSFE']->loginUser) {
$myData = $GLOBALS['TSFE']->fe_user->getKey('user', 'myData');
} else {
$myData = $GLOBALS['TSFE']->fe_user->getKey('ses', 'myData');
}

This gets the stored data with the key "myData" from the user-data, but if no user is logged in, it's fetched from the session data instead.

$GLOBALS['TSFE']->fe_user->setKey(type, key, data)

"type" is either "user" or "ses", which defines the data-space, user-data or session-data

"key" is the "name" under which your data is stored.

Note that the key "recs" is reserved for the built-in "shopping-basket". As is "sys" (for TYPO3 standard modules and code)

"data" is the variable, you want to store. This may be arrays or normal scalars.

Example:
$myConfig['name'] = 'paul';
$myConfig['address'] = 'Main street';
$GLOBALS['TSFE']->fe_user->setKey('ses', 'myData', $myConfig);

This stores the array $myConfig under the key "myData" in the session-data. This lasts as long as "paul" is surfing the site!

Using the built in "shopping basket"

TYPO3 features a shopping basket for the session-data.

When you submit data from forms (or by querystring) (post/get-method) in the array "recs" it's stored in the session-data under the key recs.

The syntax is like this:

recs[table_name][uid_of_record]

Example:

This form-element will change the registered value of record with uid=345 from the "tt_products" table in typo3. Please note, that the record itself is NOT in any way modified, only the "counter" in the session-data indicating the "number of items" from the table is modified.

<input name="recs[tt_products][345]">

Note on checkboxes:

When you are creating forms with checkboxes, the value of the checkbox is sent by MSIE/Netscape ONLY if the checkbox is checked! If you want a value sent in case of a disabled checkbox, include a hidden formfield of the same name just before the checkbox!

Example:

<INPUT type="hidden" name="recs[tt_content][345]" value="0">
<INPUT type="checkbox" name="recs[tt_content][345]" value="1">

Clearing the "basket"

This will clear the basket:

 <INPUT type="hidden" name="recs[clear_all]" value="1">