Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

Aufgabe: ein kleines CRUD-Modul Schritt für Schritt bauen

Eine praktische Aufgabe für Framework-Entwickler - eine Erweiterung mit eigener Tabelle, einem Modell auf Basis persistenter Objekte, einer Listen-View und einem Bearbeitungsformular mit Aktionen, Validierung, dem…

Download as PDF

Address: https://doc.exponential.earth/exphelp/viewer/help/web-framework-developers/your-first-module-step-by-step.md

On this page

This page is a translation. Read the English original

Aufgabe: ein kleines CRUD-Modul Schritt für Schritt bauen

Diese Seite richtet sich an Entwickler, die jedes Teil einmal sehen möchten, so wie make:crud, rails generate scaffold oder ein Modell in der Django-Administration sie erzeugen würden. Sie bauen eine Erweiterung expdemo mit einer Tabelle von Einträgen, einer Liste unter /expdemo/list und einem Bearbeitungsformular unter /expdemo/edit/<id>. Setup > RAD kann Ihnen danach einen Großteil dieses Grundgerüsts schreiben; wer es zuerst von Hand macht, sieht, was die Assistenten schreiben (RAD-Werkzeuge).

Zeitbedarf: etwa eine Stunde auf einer Entwicklungsinstallation (./console exp:install --apply richtet in wenigen Minuten eine auf SQLite ein: Installation mit einem Befehl).

Inhalt

  1. Die Dateien
  2. Das Modul registrieren
  3. Die Tabelle und das Modell
  4. Die Listen-View
  5. Die Bearbeitungs-View
  6. Die Templates
  7. Aktivieren, deployen und berechtigen
  8. Prüfen

Die Dateien

extension/expdemo/
├── classes/expdemoitem.php
├── modules/expdemo/module.php
├── modules/expdemo/list.php
├── modules/expdemo/edit.php
├── design/standard/templates/expdemo/list.tpl
├── design/standard/templates/expdemo/edit.tpl
├── settings/module.ini.append.php
├── settings/design.ini.append.php
└── share/db_schema.dba

Das Modul registrieren

# settings/module.ini.append.php
<?php /* #?ini charset="utf-8"?
[ModuleSettings]
ExtensionRepositories[]=expdemo
ModuleList[]=expdemo
*/ ?>
# settings/design.ini.append.php
<?php /* #?ini charset="utf-8"?
[ExtensionSettings]
DesignExtensions[]=expdemo
*/ ?>
<?php
// modules/expdemo/module.php
$Module = array( 'name' => 'Demo' );

$ViewList = array();
$ViewList['list'] = array(
    'script' => 'list.php',
    'functions' => array( 'read' ),
    'unordered_params' => array( 'offset' => 'Offset' ) );
$ViewList['edit'] = array(
    'script' => 'edit.php',
    'functions' => array( 'manage' ),
    'params' => array( 'ItemID' ),
    'single_post_actions' => array( 'StoreButton' => 'Store', 'CancelButton' => 'Cancel' ),
    'post_action_parameters' => array( 'Store' => array( 'Title' => 'ItemTitle' ) ) );

$FunctionList = array();
$FunctionList['read'] = array();
$FunctionList['manage'] = array();

Die Tabelle und das Modell

Legen Sie die Tabelle in Ihrer Entwicklungsdatenbank an, zum Beispiel unter SQLite:

CREATE TABLE expdemo_item ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL DEFAULT 0,
                            title VARCHAR(200) NOT NULL DEFAULT '', created INTEGER NOT NULL DEFAULT 0 );

Exportieren Sie sie anschließend für jede weitere Installation in eine datenbankneutrale Schemadatei (Migrationen und Startdaten):

php bin/php/ezsqldumpschema.php --type=sqlite --table-include=expdemo_item --output-array \
  var/storage/sqlite3/exponential.db extension/expdemo/share/db_schema.dba --allow-root-user

Das Modell ist die Klasse expDemoItem aus ORM: eZPersistentObject, gespeichert als classes/expdemoitem.php, ergänzt um eine Hilfsmethode:

    public static function fetch( $id )
    {
        return eZPersistentObject::fetchObject( self::definition(), null, array( 'id' => (int)$id ) );
    }

Die Listen-View

<?php
// modules/expdemo/list.php
$offset = isset( $Params['Offset'] ) ? max( 0, (int)$Params['Offset'] ) : 0;
$items = eZPersistentObject::fetchObjectList( expDemoItem::definition(), null, null,
                                              array( 'created' => 'desc' ),
                                              array( 'offset' => $offset, 'length' => 20 ) );

$tpl = eZTemplate::factory();
$tpl->setVariable( 'items', $items ?: array() );
$tpl->setVariable( 'offset', $offset );

$Result = array();
$Result['content'] = $tpl->fetch( 'design:expdemo/list.tpl' );
$Result['path'] = array( array( 'text' => 'Items', 'url' => false ) );

Die Bearbeitungs-View

<?php
// modules/expdemo/edit.php
$Module = $Params['Module'];
$id = (int)$Params['ItemID'];
$item = $id > 0 ? expDemoItem::fetch( $id ) : null;
if ( $id > 0 && !$item )
    return $Module->handleError( eZError::KERNEL_NOT_FOUND, 'kernel' );

if ( $Module->isCurrentAction( 'Cancel' ) )
    return $Module->redirectTo( '/expdemo/list' );

$errors = array();
$title = $item ? $item->attribute( 'title' ) : '';
if ( $Module->isCurrentAction( 'Store' ) )
{
    $title = $Module->hasActionParameter( 'Title' ) ? trim( (string)$Module->actionParameter( 'Title' ) ) : '';
    if ( $title === '' || mb_strlen( $title ) > 200 )
        $errors['title'] = ezpI18n::tr( 'extension/expdemo', 'Enter a title of at most 200 characters.' );

    if ( $errors === array() )
    {
        if ( !$item )
            $item = new expDemoItem( array( 'user_id' => eZUser::currentUserID(), 'created' => time() ) );
        $item->setAttribute( 'title', $title );
        $item->store();
        return $Module->redirectTo( '/expdemo/list' );   // POST, redirect, GET
    }
}

$tpl = eZTemplate::factory();
$tpl->setVariable( 'item', $item );
$tpl->setVariable( 'title', $title );
$tpl->setVariable( 'errors', $errors );

$Result = array();
$Result['content'] = $tpl->fetch( 'design:expdemo/edit.tpl' );
$Result['path'] = array( array( 'text' => 'Items', 'url' => 'expdemo/list' ),
                         array( 'text' => 'Edit', 'url' => false ) );

/expdemo/edit/0 legt einen neuen Eintrag an.

Die Templates

{* design/standard/templates/expdemo/list.tpl *}
<h1>{'Items'|i18n( 'extension/expdemo' )}</h1>
<p><a href={'expdemo/edit/0'|ezurl}>{'New item'|i18n( 'extension/expdemo' )}</a></p>
<ul>
{foreach $items as $item}
  <li><a href={concat( 'expdemo/edit/', $item.id )|ezurl}>{$item.title|wash}</a></li>
{/foreach}
</ul>
{* design/standard/templates/expdemo/edit.tpl *}
<form method="post" action={concat( 'expdemo/edit/', first_set( $item.id, 0 ) )|ezurl}>
  <label for="expdemo-title">{'Title'|i18n( 'extension/expdemo' )}</label>
  <input id="expdemo-title" type="text" name="ItemTitle" value="{$title|wash}" maxlength="200" />
  {if is_set( $errors.title )}<p class="error">{$errors.title|wash}</p>{/if}
  <button type="submit" name="StoreButton">{'Save'|i18n( 'extension/expdemo' )}</button>
  <button type="submit" name="CancelButton">{'Cancel'|i18n( 'extension/expdemo' )}</button>
</form>

Kein CSRF-Code: Für angemeldete Benutzer fügt ezformtoken das Token in das Formular ein und prüft es beim POST (Formulare und CSRF). Jeder ausgegebene Wert läuft durch |wash.

Aktivieren, deployen und berechtigen

# settings/override/site.ini.append.php
[ExtensionSettings]
ActiveExtensions[]=expdemo
php bin/php/ezpgenerateautoloads.php -e
./console exp:velocity deploy --allow-root-user     # or clear the ini, design_base and template-override caches

Geben Sie unter Benutzer > Rollen der Rolle der Redakteure die Richtlinien expdemo / read und expdemo / manage.

Prüfen

  1. Mit der Rolle angemeldet: /expdemo/list zeigt eine leere Liste; New item öffnet das Formular.
  2. Speichern Sie einen leeren Titel: Der Fehler erscheint neben dem Feld, und das Formular behält Ihre Eingabe.
  3. Speichern Sie einen Titel: Sie werden zur Liste weitergeleitet, die ihn anzeigt.
  4. Angemeldet ohne expdemo / manage: /expdemo/edit/0 antwortet mit „Zugriff verweigert“. Abgemeldet: die Anmeldeseite.
  5. /expdemo/edit/abc wird durch die Typumwandlung als 0 gelesen und zeigt das Formular für einen neuen Eintrag, nie einen Fehler.

Nächste Schritte: eine Fetch-Funktion, damit andere Templates Einträge auflisten können (Fetch-Funktionen), die Klassenform der Views (Controller), ein Installationsbefehl für die Tabelle und Tests für eine Validator-Klasse (Testen).

Verwandte Seiten

Werden Sie Exponential-Partner

Partner teilen ihre Informationen, stellen Mittel bereit, geben Beiträge zurück und entwickeln die Produkte mit uns, und so wächst Exponential. Eine Partner-Website und ein Dashboard sind für Mitte 2027 geplant: Werden Sie noch heute Partner, damit wir schneller wachsen und neue Funktionen früher liefern.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x