YMCA - YForm Model Class Accelerator | Keywords: Code-Generator, YOrm, Dataset-Klassen, RESTful API, Getter/Setter, Type-Hints, Dokumentation, OpenAPI

Übersicht: Generiert typsichere YOrm-Dataset-Klassen mit Getter/Setter-Methoden, Field-Konstanten und optionalen Zusatzgeneratoren (RESTful API, PDF-Fragments, Dokumentation, OpenAPI-Specs). Nutzt nette/php-generator für Single Point of Truth und verbesserte IDE-Unterstützung.

Generator-Typen

Typ Beschreibung
YOrm Class Dataset-Klasse mit Getter/Setter
RESTful API API-Routes für CRUD-Operationen
PDF Fragment Fragment für PDF-Generierung
Documentation Markdown-Dokumentation
Dotlang Übersetzungsdateien (.lang)
OpenAPI OpenAPI 3.0 Specification

Field-Konstanten (FIELD_*)

Typ Konstante Beispiel
text FIELD_NAME 'name'
integer FIELD_ID 'id'
be_media FIELD_IMAGE 'image'
be_link FIELD_ARTICLE_ID 'article_id'
datetime FIELD_CREATED_AT 'created_at'
datestamp FIELD_TIMESTAMP 'timestamp'

Unterstützte Feldtypen

YForm-Typ PHP-Typ Return-Type
text string ?string
textarea string ?string
integer int ?int
be_media rex_media ?rex_media
be_link rex_article ?rex_article
be_manager_relation rex_yform_manager_collection rex_yform_manager_collection
datetime DateTime ?DateTime
datestamp int ?int
choice mixed ?string
checkbox bool bool
float float ?float
email string ?string
url string ?string
domain string ?string
ip string ?string

Praxisbeispiele

Beispiel 1: Einfache Klasse generieren

Im Backend unter YForm > Tabellenverwaltung > rex_events:

  • Button “YMCA” klicken
  • Generator: YOrm Class
  • Namespace: App\Models
  • Klasse generieren

Beispiel 2: Generierte Klasse verwenden

// Generierte Klasse: src/models/Event.php
namespace App\Models;

use rex_yform_manager_dataset;

class Event extends rex_yform_manager_dataset
{
    // Field-Konstanten (Single Point of Truth)
    public const FIELD_ID = 'id';
    public const FIELD_NAME = 'name';
    public const FIELD_DATE = 'date';
    public const FIELD_IMAGE = 'image';
    
    // Getter mit Type-Hints
    public function getName(): ?string
    {
        return $this->getValue(self::FIELD_NAME);
    }
    
    public function getDate(): ?DateTime
    {
        $value = $this->getValue(self::FIELD_DATE);
        return $value ? new DateTime($value) : null;
    }
    
    public function getImage(): ?rex_media
    {
        $value = $this->getValue(self::FIELD_IMAGE);
        return $value ? rex_media::get($value) : null;
    }
    
    // Setter mit Type-Hints
    public function setName(?string $value): self
    {
        $this->setValue(self::FIELD_NAME, $value);
        return $this;
    }
    
    public function setDate(?DateTime $value): self
    {
        $this->setValue(self::FIELD_DATE, $value?->format('Y-m-d H:i:s'));
        return $this;
    }
    
    public function setImage(?rex_media $value): self
    {
        $this->setValue(self::FIELD_IMAGE, $value?->getFileName());
        return $this;
    }
}

Beispiel 3: Field-Konstanten nutzen

use App\Models\Event;

// Statt String-Namen:
$event->getValue('name');

// Field-Konstanten verwenden:
$event->getValue(Event::FIELD_NAME);

// IDE-Unterstützung + Single Point of Truth
// Bei Feldänderung nur Konstante anpassen

Beispiel 4: Typisierte Getter

$event = Event::get(1);

// String
$name = $event->getName(); // ?string

// DateTime
$date = $event->getDate(); // ?DateTime
echo $date->format('d.m.Y'); // Type-safe!

// Media
$image = $event->getImage(); // ?rex_media
echo $image?->getUrl();

Beispiel 5: Fluent Setter

$event = Event::create()
    ->setName('Konzert')
    ->setDate(new DateTime('2024-12-31'))
    ->setImage(rex_media::get('concert.jpg'))
    ->save();

// Method-Chaining durch return $this
// YForm-Feld: be_link|article_id|Artikel
// Generierter Getter:

public function getArticle(): ?rex_article
{
    $value = $this->getValue(self::FIELD_ARTICLE_ID);
    return $value ? rex_article::get($value) : null;
}

// Verwendung:
$event = Event::get(1);
$article = $event->getArticle();
echo $article?->getName();

Beispiel 7: be_manager_relation

// YForm-Feld: be_manager_relation|speakers|Speaker|1-n
// Generierter Getter:

public function getSpeakers(): rex_yform_manager_collection
{
    return $this->getRelatedCollection(self::FIELD_SPEAKERS);
}

// Verwendung:
$event = Event::get(1);
foreach ($event->getSpeakers() as $speaker) {
    echo $speaker->getName();
}

Beispiel 8: RESTful API generieren

Generator: RESTful API Ausgabe:

// routes/api.php

// GET /api/events
rex_api_function::setRoute('GET', 'api/events', function() {
    $events = Event::query()->find();
    return rex_api_response::json($events);
});

// GET /api/events/:id
rex_api_function::setRoute('GET', 'api/events/:id', function($id) {
    $event = Event::get($id);
    return rex_api_response::json($event);
});

// POST /api/events
rex_api_function::setRoute('POST', 'api/events', function() {
    $data = rex_request::post();
    $event = Event::create();
    $event->setData($data);
    $event->save();
    return rex_api_response::json($event, 201);
});

// PUT /api/events/:id
rex_api_function::setRoute('PUT', 'api/events/:id', function($id) {
    $event = Event::get($id);
    $data = rex_request::post();
    $event->setData($data);
    $event->save();
    return rex_api_response::json($event);
});

// DELETE /api/events/:id
rex_api_function::setRoute('DELETE', 'api/events/:id', function($id) {
    $event = Event::get($id);
    $event->delete();
    return rex_api_response::json(null, 204);
});

Beispiel 9: PDF-Fragment generieren

Generator: PDF Fragment Ausgabe:

// fragments/pdf/event.php
<?php
/** @var Event $event */
?>
<h1><?= $event->getName() ?></h1>
<p><strong>Datum:</strong> <?= $event->getDate()?->format('d.m.Y') ?></p>

<?php if ($image = $event->getImage()): ?>
    <img src="<?= $image->getUrl() ?>" alt="">
<?php endif; ?>

<p><?= $event->getDescription() ?></p>

Beispiel 10: Markdown-Dokumentation

Generator: Documentation Ausgabe:

# Event Model

## Fields

- **id** (integer): Primary Key
- **name** (text): Event name
- **date** (datetime): Event date
- **image** (be_media): Event image

## Methods

### getName(): ?string
Returns the event name.

### getDate(): ?DateTime
Returns the event date as DateTime object.

### getImage(): ?rex_media
Returns the event image as rex_media object.

## Usage

```php
$event = Event::get(1);
echo $event->getName();
echo $event->getDate()->format('d.m.Y');

### Beispiel 11: Dotlang-Dateien

Generator: Dotlang
Ausgabe:

de_de.lang

event_field_id = ID event_field_name = Name event_field_date = Datum event_field_image = Bild

en_gb.lang

event_field_id = ID event_field_name = Name event_field_date = Date event_field_image = Image


### Beispiel 12: OpenAPI Specification

Generator: OpenAPI
Ausgabe:
```yaml
openapi: 3.0.0
info:
  title: Event API
  version: 1.0.0
paths:
  /api/events:
    get:
      summary: List all events
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Event'
    post:
      summary: Create event
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Event'
      responses:
        '201':
          description: Created
components:
  schemas:
    Event:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        date:
          type: string
          format: date-time
        image:
          type: string

Beispiel 13: Checkbox/Bool-Felder

// YForm-Feld: checkbox|is_published|Veröffentlicht
// Generierter Code:

public const FIELD_IS_PUBLISHED = 'is_published';

public function isPublished(): bool
{
    return (bool) $this->getValue(self::FIELD_IS_PUBLISHED);
}

public function setIsPublished(bool $value): self
{
    $this->setValue(self::FIELD_IS_PUBLISHED, $value ? 1 : 0);
    return $this;
}

// Verwendung:
if ($event->isPublished()) {
    echo 'Veröffentlicht';
}

Beispiel 14: Choice-Felder

// YForm-Feld: choice|status|Status|draft=Entwurf,published=Veröffentlicht
// Generierter Code:

public const FIELD_STATUS = 'status';
public const STATUS_DRAFT = 'draft';
public const STATUS_PUBLISHED = 'published';

public function getStatus(): ?string
{
    return $this->getValue(self::FIELD_STATUS);
}

public function isDraft(): bool
{
    return $this->getStatus() === self::STATUS_DRAFT;
}

public function isPublished(): bool
{
    return $this->getStatus() === self::STATUS_PUBLISHED;
}

Beispiel 15: Float-Felder

// YForm-Feld: number|price|Preis
// Generierter Code:

public const FIELD_PRICE = 'price';

public function getPrice(): ?float
{
    return $this->getValue(self::FIELD_PRICE) !== null 
        ? (float) $this->getValue(self::FIELD_PRICE) 
        : null;
}

public function setPrice(?float $value): self
{
    $this->setValue(self::FIELD_PRICE, $value);
    return $this;
}

// Verwendung:
echo number_format($event->getPrice(), 2) . ' €';

Beispiel 16: Multiple Relationen

// be_manager_relation|categories|Category|n-m

public function getCategories(): rex_yform_manager_collection
{
    return $this->getRelatedCollection(self::FIELD_CATEGORIES);
}

public function addCategory(Category $category): self
{
    $this->addRelation(self::FIELD_CATEGORIES, $category);
    return $this;
}

public function removeCategory(Category $category): self
{
    $this->removeRelation(self::FIELD_CATEGORIES, $category);
    return $this;
}

Beispiel 17: Custom Methods hinzufügen

// Generierte Klasse erweitern
namespace App\Models;

class Event extends rex_yform_manager_dataset
{
    // ... generierte Methoden ...
    
    // Custom Methods
    public function isUpcoming(): bool
    {
        $date = $this->getDate();
        return $date && $date > new DateTime();
    }
    
    public function isPast(): bool
    {
        return !$this->isUpcoming();
    }
    
    public function getFormattedDate(): string
    {
        return $this->getDate()?->format('d.m.Y H:i') ?? '';
    }
}

Beispiel 18: Batch-Generierung

// Alle YForm-Tabellen durchlaufen
$tables = rex_yform_manager_table::getAll();

foreach ($tables as $table) {
    $generator = new \Alexplusde\Ymca\YormGenerator($table);
    $generator->generate();
    
    echo 'Generiert: ' . $table->getTableName() . '<br>';
}

Beispiel 19: Namespace konfigurieren

Im Backend: YForm > YMCA > Einstellungen

  • Namespace: App\Models
  • Output Directory: src/models/
  • Generate API: Ja
  • Generate Docs: Ja

Beispiel 20: Email/URL-Validierung

// YForm-Feld: email|contact_email|E-Mail
// Generierter Code:

public function getContactEmail(): ?string
{
    return $this->getValue(self::FIELD_CONTACT_EMAIL);
}

public function setContactEmail(?string $value): self
{
    if ($value && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
        throw new InvalidArgumentException('Invalid email address');
    }
    $this->setValue(self::FIELD_CONTACT_EMAIL, $value);
    return $this;
}

Beispiel 21: Datestamp zu DateTime

// YForm-Feld: datestamp|created_at|Erstellt am
// Generierter Code:

public function getCreatedAt(): ?DateTime
{
    $timestamp = $this->getValue(self::FIELD_CREATED_AT);
    return $timestamp ? DateTime::createFromFormat('U', $timestamp) : null;
}

public function setCreatedAt(?DateTime $value): self
{
    $this->setValue(self::FIELD_CREATED_AT, $value?->getTimestamp());
    return $this;
}

Beispiel 22: Domain-Feld

// YForm-Feld: domain|website|Website
// Generierter Code:

public function getWebsite(): ?string
{
    return $this->getValue(self::FIELD_WEBSITE);
}

public function getWebsiteUrl(): ?string
{
    $domain = $this->getWebsite();
    return $domain ? 'https://' . $domain : null;
}

Beispiel 23: Alle Konstanten auslesen

// FIELD_CONFIG Konstante enthält alle Felder
class Event extends rex_yform_manager_dataset
{
    public const FIELD_CONFIG = [
        'id' => ['type' => 'integer', 'label' => 'ID'],
        'name' => ['type' => 'text', 'label' => 'Name'],
        'date' => ['type' => 'datetime', 'label' => 'Datum'],
    ];
}

// Verwendung:
foreach (Event::FIELD_CONFIG as $field => $config) {
    echo $config['label'] . ': ' . $event->getValue($field) . '<br>';
}

Beispiel 24: PHPDoc für IDE

// Generierte Klasse mit vollständigem PHPDoc
/**
 * Event Model
 * 
 * @property int $id
 * @property string $name
 * @property string $date
 * @property string $image
 * 
 * @method ?string getName()
 * @method ?DateTime getDate()
 * @method ?rex_media getImage()
 * @method self setName(?string $value)
 * @method self setDate(?DateTime $value)
 * @method self setImage(?rex_media $value)
 */
class Event extends rex_yform_manager_dataset
{
    // ...
}

Beispiel 25: Re-Generierung nach Schema-Änderung

// Nach YForm-Feldänderung neu generieren
// Backend: YForm > Tabelle > YMCA-Button

// Oder via Extension Point:
rex_extension::register('YFORM_DATA_UPDATED', function($ep) {
    $table = $ep->getParam('table');
    
    if ($table->getTableName() == 'rex_events') {
        $generator = new \Alexplusde\Ymca\YormGenerator($table);
        $generator->generate();
    }
});

Integration: YForm (YOrm Datasets, Tabellenverwaltung), nette/php-generator (Code-Generierung), rex_api_function (RESTful API), rex_fragment (PDF-Templates), OpenAPI Standards, IDE Integration (PHPDoc, Type-Hints), Extension Points (YFORM_DATA_UPDATED), Single Point of Truth Pattern (Field-Konstanten)