Es werden nur ein paar grundlegende Bausteine in diesem Tutorial erklärt. Dazu zählen die Repository bzw. Model Klassen des Extbase Systems sowie einfache Templates mit dem Fluid System.
Verwendete Versionen:
- Typo3 4.5.3
- Extbase 1.3.0
- Fluid 1.3.0
In dem Ordner typo3conf/ext
erstellt man ein Verzeichnis image_gallery
mit folgenden Unterordnern:
Verzeichnisstruktur der Extension:
image_gallery
+-- Classes
| +-- Controller
| +-- Domain
| +-- Model
| +-- Repository
+-- Configuration
| +-- TCA
| +-- TypoScript
| +-- DefaultStyles
+-- Resources
+-- Private
| +-- Language
| +-- Layouts
| +-- Templates
| +-- Image
+-- Public
+-- Css
+-- Icons
Direkt in dem Ordner image_gallery
muss für jede Extension eine grundlegende Konfiguration (ext_emconf.php
) abgelegt werden. Diese enthält Angaben über den Titel der Extension, der Version, die Autorenangaben und auch Abhängigkeiten von anderen Extensions. In diesem Fall ist unsere kleine Bildergalerie abhängig von den beiden Extensions extbase und fluid.
<?php
$EM_CONF[$_EXTKEY] = array(
'title' => 'Image Gallery',
'description' => 'A simple image gallery.',
'category' => 'plugin',
'author' => 'Karsten Hachmeister',
'author_email' => 'webmaster@hachmeister.org',
'dependencies' => 'extbase,fluid',
'uploadfolder' => 1,
'clearCacheOnLoad' => 1,
'version' => '0.0.0',
'constraints' => array(
'depends' => array(
'extbase' => '',
'fluid' => '',
),
),
);
Die beiden Dateien ext_localconf.php
und ext_tables.php
sind entscheidend für die Ausführung der Extension. ext_localconf.php
wird sowohl im Frontend als auch im Backend geladen, ext_tables.php
wird nur im Backend geladen.
Die Methode configurePlugin
fügt dem Typo3 System ein Stück generiertes Typoscript hinzu, dass den Dispatcher des Extbase Systems einbindet und ihn für diese Extension konfiguriert.
In dem Array werden einem Controller Actions zugewiesen. In diesem Fall wäre Image
der Controller Name und index
sowie show
die Actions.
Die Datei ext_localconf.php
:
<?php
if (!defined('TYPO3_MODE')) {
die ('Access denied.');
}
Tx_Extbase_Utility_Extension::configurePlugin(
$_EXTKEY,
'Pi1',
array(
'Image' => 'index,show'
)
);
Die Methode registerPlugin
fügt die Extension in das Typo3 System, zur Nutzung im Backend, ein.
Hier wird die Extension auch im TCA (Table Configuration Array) eingebunden. Diese Informationen werden verwendet, um Typo3 zu sagen, in welchen Spalten dieser Tabelle die relevanten Informationen für Typo3 gespeichert werden.
Z.B. wird mit dem label
Eintrag angegeben, dass die Spalte title
zur Anzeige für einen Datensatz verwendet werden soll.
Eine komplette Auflistung aller möglichen Angaben kann man der Table Configuration Array Referenz entnehmen.
Die Datei ext_tables.php
:
<?php
if (!defined('TYPO3_MODE')) {
die ('Access denied.');
}
Tx_Extbase_Utility_Extension::registerPlugin(
$_EXTKEY,
'Pi1',
'Image Gallery'
);
$TCA['tx_imagegallery_domain_model_image'] = array (
'ctrl' => array (
'title' => 'LLL:EXT:image_gallery/Resources/Private/Language/locallang_db.xml:tx_imagegallery_domain_model_image',
'label' => 'title',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'sortby' => 'sorting',
'delete' => 'deleted',
'enablecolumns' => array (
'disabled' => 'hidden',
),
'dynamicConfigFile' => t3lib_extMgm::extPath($_EXTKEY) . 'Configuration/TCA/tca.php',
'iconfile' => t3lib_extMgm::extRelPath($_EXTKEY) . 'Resources/Public/Icons/icon_tx_imagegallery_domain_model_image.gif'
),
);
t3lib_extMgm::allowTableOnStandardPages('tx_imagegallery_domain_model_image');
t3lib_extMgm::addStaticFile($_EXTKEY, 'Configuration/TypoScript/DefaultStyles', 'ImageGallery CSS Styles (optional)');
In der Datei tca.php
wird das TCA Array weiter geführt. Diese Informationen werden dazu verwendet um Formulare zu generieren, mit denen sich die Datensätze erstellen und bearbeiten lassen. Auch hier gibt es den Verweis auf die Table Configuration Array Referenz.
Die Datei Configuration/TCA/tca.php
:
<?php
if (!defined('TYPO3_MODE')) {
die ('Access denied.');
}
$TCA['tx_imagegallery_domain_model_image'] = array (
'ctrl' => $TCA['tx_imagegallery_domain_model_image']['ctrl'],
'interface' => array (
'showRecordFieldList' => 'hidden,title,image'
),
'feInterface' => $TCA['tx_imagegallery_domain_model_image']['feInterface'],
'columns' => array (
'hidden' => array (
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.hidden',
'config' => array (
'type' => 'check',
'default' => '0'
)
),
'title' => array (
'exclude' => 0,
'label' => 'LLL:EXT:image_gallery/Resources/Private/Language/locallang_db.xml:tx_imagegallery_domain_model_image.title',
'config' => array (
'type' => 'input',
'size' => '30',
'eval' => 'required',
)
),
'image' => array (
'exclude' => 0,
'label' => 'LLL:EXT:image_gallery/Resources/Private/Language/locallang_db.xml:tx_imagegallery_domain_model_image.image',
'config' => array (
'type' => 'group',
'internal_type' => 'file',
'allowed' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],
'max_size' => $GLOBALS['TYPO3_CONF_VARS']['BE']['maxFileSize'],
'uploadfolder' => 'uploads/tx_imagegallery',
'show_thumbs' => 1,
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
)
),
),
'types' => array (
'0' => array('showitem' => 'hidden;;1;;1-1-1, title;;;;2-2-2, image;;;;3-3-3')
),
'palettes' => array (
'1' => array('showitem' => '')
)
);
Das SQL Schema für die Extension um die Bilder in die Datenbank einzufügen. Alle Spalten von uid
bis hin zu hidden
sind Spalten, die Typo3 zur Verwaltung braucht. Es gibt noch weitere, es müssen aber nicht immer alle verwendet werden. Diese Spalten wurden auch in der Datei ext_tables.php
für Typo3 konfiguriert, so dass das System weiß, in welcher Spalte welche Information enthalten ist.
Die Datei ext_tables.sql
:
#
# Table structure for table 'tx_imagegallery_domain_model_image'
#
CREATE TABLE tx_imagegallery_domain_model_image (
uid int(11) NOT NULL auto_increment,
pid int(11) DEFAULT '0' NOT NULL,
tstamp int(11) DEFAULT '0' NOT NULL,
crdate int(11) DEFAULT '0' NOT NULL,
cruser_id int(11) DEFAULT '0' NOT NULL,
sorting int(10) DEFAULT '0' NOT NULL,
deleted tinyint(4) DEFAULT '0' NOT NULL,
hidden tinyint(4) DEFAULT '0' NOT NULL,
title tinytext,
image text,
PRIMARY KEY (uid),
KEY parent (pid)
);
Die Datei locallang_db.xml
enthält alle Begriffe, die für das Backend übersetzt werden müssen um in unterschiedlichen Sprachversionen von Typo3 korrekt dargestellt werden zu können. Diese Begriffe werden hier im Beispiel in dem TCA verwendet.
Die default Sprache ist immer Englisch, in diesem Beispiel wurde nur noch Deutsch hinzugefügt, es sind natürlich auch weitere Sprachen möglich.
Die Datei Resources/Private/Language/locallang_db.xml
:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<T3locallang>
<meta type="array">
<type>database</type>
<description>Language labels for database tables/fields belonging to extension 'image_gallery'</description>
</meta>
<data type="array">
<languageKey index="default" type="array">
<label index="tx_imagegallery_domain_model_image">Image</label>
<label index="tx_imagegallery_domain_model_image.title">Title</label>
<label index="tx_imagegallery_domain_model_image.image">Image</label>
</languageKey>
<languageKey index="de" type="array">
<label index="tx_imagegallery_domain_model_image">Bild</label>
<label index="tx_imagegallery_domain_model_image.title">Titel</label>
<label index="tx_imagegallery_domain_model_image.image">Bild</label>
</languageKey>
</data>
</T3locallang>
Das Model für die Bilder Datensätze. Models müssen immer von der Klasse Tx_Extbase_DomainObject_AbstractEntity
angeleitet werden. Dieses Model enthält nur die beiden Attribute title
und image
, die den Titel des Bildes und den Dateipfad zu dem Bild enthalten.
Die Getter und Setter sind mitels CamelCase aus dem Spaltennamen zu bilden. Für eine Spalte namens title
müssen sie getTitle()
bzw. setTitle()
heißen und für eine Spalte namens user_name
müssen sie getUserName()
bzw. setUserName()
genannt werden.
Die Datei Classes/Domain/Model/Image.php
:
<?php
/**
* The image model
*/
class Tx_ImageGallery_Domain_Model_Image extends Tx_Extbase_DomainObject_AbstractEntity {
/**
* The image title.
* @var string
*/
protected $title = '';
/**
* The image file.
* @var string
*/
protected $image = '';
/**
* Gets the image title.
* @return string The image title
*/
public function getTitle() {
return $this->title;
}
/**
* Sets the image title.
* @param string $title The image title
* @return void
*/
public function setTitle($title) {
$this->title = $title;
}
/**
* Gets the image file.
* @return string The image title
*/
public function getImage() {
return $this->image;
}
/**
* Sets the image file.
* @param string $image The image file
* @return void
*/
public function setFile($image) {
$this->image = $image;
}
}
DAO Klassen werden in dem Extbase System von der Tx_Extbase_Persistence_Repository
Klasse abgeleitet. Standardmäßig bringt diese Klasse schon die wichtigsten Methoden mit um die Datenbank zu manipulieren. Zu nennen wären hier vor allem add($object)
, update($object)
, remove($object)
, findAll()
sowie findByUid($uid)
.
Die Datei Classes/Domain/Repository/ImageRepository.php
:
<?php
/**
* The image repository
*/
class Tx_ImageGallery_Domain_Repository_ImageRepository extends Tx_Extbase_Persistence_Repository {
/**
* Finds all images by pid
*
* @param int $pid The pid to search for images in
* @return Tx_Extbase_Persistence_QueryResultInterface The images
*/
public function findAllByPid($pid) {
$query = $this->createQuery();
$query->getQuerySettings()->setStoragePageIds(array($pid));
return $query->execute();
}
}
Controller Klassen werden von Tx_Extbase_MVC_Controller_ActionController
abgeleitet. Hier werden die beiden Methoden indexAction()
und showAction()
definiert, die in der configurePlugin()
Methode von oben angegeben wurden.
Die Datei Classes/Controller/ImageController.php
<?php
/**
* The image controller
*/
class Tx_ImageGallery_Controller_ImageController extends Tx_Extbase_MVC_Controller_ActionController {
/**
* The image repository.
*
* @var Tx_ImageGallery_Domain_Model_ImageRepository
*/
protected $imageRepository;
/**
* Dependency injection of the image repository.
*
* @param Tx_ImageGallery_Domain_Repository_ImageRepository $imageRepository
* @return void
*/
public function injectImageRepository(Tx_ImageGallery_Domain_Repository_ImageRepository $imageRepository) {
$this->imageRepository = $imageRepository;
}
/**
* Index action for this controller.
*
* @return void
*/
public function indexAction() {
$images = $this->imageRepository->findAllByPid($GLOBALS["TSFE"]->id);
$imagesCount = $images->count();
$rowsCount = ($imagesCount % 3 == 0) ? $imagesCount / 3 : intval($imagesCount / 3) + 1;
$rows = array();
for ($i = 0; $i < $rowsCount; $i++) {
$row = array();
for ($j = 0; $j < 3; $j++) {
if ($images->valid()) {
$row[] = $images->current();
$images->next();
} else {
$row[] = null;
}
}
$rows[] = $row;
}
$this->view->assign('rows', $rows);
}
/**
* Show action for this controller.
*
* @param int $id The uid of the image.
* @return void
*/
public function showAction($id) {
$this->view->assign('image', $this->imageRepository->findByUid($id));
}
}
Templates in dem Fluid System sind auch vererbbar. In der Datei default.html wird das grundlegende Template definiert. Der Bereich <f:render section="content" />
wird durch ein vererbtes Templates ersetzt.
Die Datei Resources/Private/Layouts/default.html
:
<div class="tx-imagegallery">
<f:render section="content" />
</div>
Das Template um die Bilderübersicht darzustellen. Mit <f:layout name="default" />
wird das übergeordnete Template angegeben.
Die Datei Resources/Private/Templates/Image/index.html
:
<f:layout name="default" />
<f:section name="content">
<h1>Image Gallery</h1>
<table cellspacing="0" cellpadding="0" border="0">
<f:for each="{rows}" as="images">
<tr>
<f:for each="{images}" as="image">
<td>
<f:if condition="{image}">
<f:then>
<f:link.action action="show" arguments="{id : image}">
<img src="<f:uri.image src='uploads/tx_imagegallery/{image.image}' width='160' />" />
</f:link.action>
<div class="title">{image.title}</div>
</f:then>
<f:else>
</f:else>
</f:if>
</td>
</f:for>
</tr>
</f:for>
</table>
</f:section>
Das Template zur Darstellung eines einzelnen Bilder, wie oben auch wird hier vom default.html
Template geerbt.
Die Datei Resources/Private/Templates/Image/show.html
:
<f:layout name="default" />
<f:section name="content">
<h1>{image.title}</h1>
<p><img src="<f:uri.image src='uploads/tx_imagegallery/{image.image}' width='540' />" /></p>
</f:section>
Und noch etwas CSS um alles etwas hübscher zu machen.
Die Datei Resources/Public/Css/ImageGallery.css
:
.tx-imagegallery table { margin-bottom: 20px; width: 100%; }
.tx-imagegallery table td {
padding: 10px 0; width: 33%; text-align: center;
vertical-align: top;
}
.tx-imagegallery table td a { border: 0; }
.tx-imagegallery table td img { border: 5px solid #CCC; }
.tx-imagegallery table td .title { margin-top: 4px; }
Nach dem Einbinden der Extension in das Typo3 System sollte man etwas ähnliches wie oben auf den Bildern gezeigt sehen können.