Become a member!

Costruire Applicazioni Web Delphi in Pochi Minuti con DMVCFramework e TemplatePro

  • 👉 This article is available in english too.
  • 👉 Este artículo también está disponible en español.
  • 👉 Questo articolo è disponibile anche in italiano.
  • 👉 Este artigo também está disponível em português do Brasil.

Nel mondo frenetico dello sviluppo web, velocità ed efficienza non sono solo vantaggi—sono necessità. Mentre l’industria spesso gravita verso framework JavaScript complessi e toolchain intricate, DMVCFramework si distingue come il progetto Delphi più popolare su GitHub per una ragione convincente: fornisce applicazioni web di livello enterprise con una semplicità e velocità senza precedenti.

Combinato con il potente motore di template TemplatePro e potenziato da strumenti moderni come WebStencils, questo ecosistema rappresenta un cambio di paradigma nel modo in cui le applicazioni web possono essere costruite. Esploriamo come queste tecnologie permettano agli sviluppatori di creare applicazioni web sofisticate in pochi minuti, non mesi.

Il Trio Vincente: DMVCFramework, TemplatePro e WebStencils

DMVCFramework: La Fondazione dello Sviluppo Web Veloce

DMVCFramework è un framework popolare e potente per WEB API in Delphi che supporta lo sviluppo di WEB API RESTful e JSON-RPC. Ciò che lo distingue è la sua straordinaria capacità di trasformare compiti complessi di sviluppo web in operazioni semplici e intuitive.

Ecco cosa rende DMVCFramework eccezionale:

Stabilità Pronta per la Produzione: Utilizzato da progetti piccoli/medi/grandi dal 2010, DMVCFramework ha dimostrato il suo valore in ambienti ad alto traffico. Alcune delle WEB API Delphi con il traffico più pesante (RESTful o JSONRPC) sono alimentate da DMVCFramework.

Sviluppo Istantaneo: Puoi creare un server RESTful completo in un paio di click. Il wizard integrato rende la creazione del progetto quasi istantanea.

Deployment Flessibile: Che tu abbia bisogno di un server standalone, modulo Apache o estensione ISAPI, DMVCFramework si adatta alle tue esigenze infrastrutturali.

Ecosistema Ricco: Con oltre 100 esempi e una documentazione completa, gli sviluppatori possono diventare produttivi immediatamente.

TemplatePro: Template Moderno Reso Semplice

TemplatePro è un motore di template moderno e versatile progettato per semplificare la generazione dinamica di HTML, contenuti email e file di testo. Con una sintassi ispirata a sistemi popolari come Jinja e Smarty, fornisce funzionalità potenti tra cui blocchi condizionali, cicli, ereditarietà dei template e supporto per dati JSON.

Caratteristiche Principali:

  • Sintassi Intuitiva: Utilizza la familiare notazione {{}} per espressioni e logica
  • Ereditarietà dei Template: Costruisci layout e componenti riutilizzabili
  • Filtri Personalizzati: Estendi le funzionalità con trasformazioni di dati specifiche del dominio
  • Integrazione JSON: Gestisci senza sforzo dati API e oggetti complessi
  • Prestazioni: I template compilati garantiscono un’esecuzione veloce

La Documentazione Ufficiale di TemplatePro è disponibile qui

WebStencils: Il Motore di Template di RAD Studio

WebStencils è il motore di template nativo di RAD Studio 12.2 che fornisce capacità di scripting lato server per estendere le applicazioni WebBroker e RAD Server. WebStencils rappresenta il riconoscimento da parte di Embarcadero dell’importanza dei motori di template moderni nello sviluppo web.

Entrambi i motori supportano logica condizionale, cicli, ereditarietà dei template e meccanismi di inclusione. Tuttavia, TemplatePro fornisce alcune caratteristiche uniche come filtri personalizzati, gestione nativa di JSON e compilazione opzionale. L’obiettivo principale di WebStencils è estendere significativamente le tecnologie web esistenti in RAD Studio trasformando qualsiasi motore di Web Service in uno strumento completo per Web Site e Web Service.

Se sei interessato al motore WebStencils, consiglio vivamente la Guida Gratuita WebStencils and HTMX: Free Guide to Fast Web Development del mio amico Antonio Zapater.

Quick Start: Dal Download all’Applicazione Web Funzionante in 2 Minuti

La bellezza di DMVCFramework e TemplatePro risiede nella loro usabilità immediata. Dimentica le complesse procedure di setup—puoi avere un’applicazione web completamente funzionale in esecuzione in meno di 2 minuti.

Passo 1: Scarica ed Esegui

Semplicemente scarica il progetto quickstart e sei pronto per partire:

  • Scarica l’archivio zip QuickStart
  • Decomprimilo in una cartella che ti piace
  • Apri il progetto dmvcframework_templatepro_htmx_quickstart.dproj in Delphi e premi F9
  • Fatto! Il tuo web server è in esecuzione su localhost:8080

Da ora in poi puoi rinominare i file e aggiungere le funzionalità richieste dal tuo progetto.

Il progetto quickstart include un’applicazione web completa con:

  • Server DMVCFramework pre-configurato pronto per l’esecuzione
  • Template TemplatePro già configurati
  • Dati di esempio e controller che dimostrano le best practice
  • Interfaccia web responsive utilizzando Bootstrap
  • Esempi funzionanti di tutte le principali funzionalità

Passo 2: Esplora Ciò che è Già Costruito

Apri il progetto e troverai un sistema di gestione clienti completamente funzionale:

// ControllerU.pas - Already implemented!
unit ControllerU;

interface

uses
  MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons, System.Generics.Collections;

type
  [MVCPath]
  TMyController = class(TMVCController)
  public
    [MVCPath]
    [MVCHTTPMethod([httpGET])]
    [MVCProduces(TMVCMediaType.TEXT_HTML)]
    function Index: String;

    [MVCPath('/reversedstrings')]
    [MVCHTTPMethod([httpGET])]
    [MVCProduces(TMVCMediaType.TEXT_PLAIN)]
    function GetReversedString(const [MVCFromQueryString('value','')] Value: String): String;

  end;

implementation

uses
  System.StrUtils, System.SysUtils, MVCFramework.Logger;


function TMyController.Index: String;
begin
  Result := RenderView('index');
end;

function TMyController.GetReversedString(const Value: String): String;
begin
  ViewData['reversed_string'] := System.StrUtils.ReverseString(Value.Trim);
  Result := RenderView('partials/reversed');
end;

end.

Passo 3: Vedi TemplatePro in Azione

Il quickstart include template funzionanti che puoi esaminare e modificare:

templates/index.html (incluso nel quickstart):

{{extends "_layout.html"}}

{{block "body"}}

<div class="row">
    <div class="col">
        <div class="text-center mt-5">
            <h1>DMVCFramework + TemplatePro + HTMX</h1>
            <p class="lead">A complete project boilerplate built with Bootstrap</p>
            <p>Bootstrap v5.3.3</p>
        </div>
    </div>
</div>

<div class="row mt-5">
    <div class="col col-3 offset-3">
        <div class="mb-3">
            <input type="text" name="value" class="form-control" id="exampleFormControlInput1"
              placeholder="Write something here" value="Hello World">
        </div>
    </div>
    <div class="col col-2">
        <button type="button" hx-get="/reversedstrings" hx-include='input' hx-target="#result"
          class="btn btn-primary">Reverse it!</button>
    </div>
</div>
<div class="row">
    <div class="col col-5 offset-3">
        <div id="result" class="alert alert-primary" role="alert">
            {{include "partials/reversed.html"}}
        </div>
    </div>
</div>

{{endblock}}

Passo 4: Personalizzazione Istantanea

Vuoi vedere i tuoi cambiamenti immediatamente? Il quickstart è progettato per un feedback istantaneo:

  1. Modifica un template - Modifica templates/index.html
  2. Aggiorna il browser - Vedi i cambiamenti immediatamente (nessuna compilazione necessaria per i template!)
  3. Crea nuovi endpoint - Segui i pattern dei controller esistenti

templates/_layout.hmtl (anch’esso incluso):

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta name="description" content="A simple DMVCFramework + TemplatePro + HTMX Template for new projects.">
    <meta name="author" content="Daniele Teti">
    <title>DMVCFramework TemplatePro HTMX Quick Start</title>
    <!-- Latest compiled and minified CSS -->
    <script src="/assets/js/htmx.min.js"></script>
    <link href="/assets/bootstrap-5.3.3/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
    <link rel="stylesheet" href="/assets/css/style.css"/>
    <link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico">
    <link rel="manifest" href="/assets/site.webmanifest" />
</head>
<body>
        <!-- Responsive navbar-->
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <div class="container">
                <a class="navbar-brand" href="#">Start Bootstrap</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
                  data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
                  aria-expanded="false" aria-label="Toggle navigation">
                  <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
                        <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
                        <li class="nav-item"><a class="nav-link" href="#">Link</a></li>
                        <li class="nav-item dropdown">
                            <a class="nav-link dropdown-toggle" id="navbarDropdown" href="#"
                              role="button" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</a>
                            <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
                                <li><a class="dropdown-item" href="#">Action</a></li>
                                <li><a class="dropdown-item" href="#">Another action</a></li>
                                <li><hr class="dropdown-divider" /></li>
                                <li><a class="dropdown-item" href="#">Something else here</a></li>
                            </ul>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
<div class="container">
    {{block "body"}}{{endblock}}
</div>
<!-- Bootstrap core JS-->
<script src="/assets/bootstrap-5.3.3/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<!-- Core theme JS-->
<script src="/assets/js/scripts.js"></script>
</body>
</html>

Ora è il momento per un’altra foto completamente non correlata… 😁

Funzionalità Avanzate di TemplatePro in Azione

Lavorare con Dati JSON

TemplatePro eccelle nella gestione di dati JSON provenienti da API:

function TMyController.GetCustomers: String;
begin
  //Let's create a dataset containing 15 random people we consider as customers.
  //This dataset is generated by the "Delphi Fake Data Utils" project available here https://github.com/danieleteti/delphi_fake_data_utils
  var lDS := ToFree<TDataSet>(GetPeople(15));
  var lJSON := ToFree<TJSONObject>(TJSONObject.Create);

  //calculate customers avg age
  lDS.First;
  var lAgeCumulative := 0;
  _.ForEachRecord(lDS,
    procedure(const DS: TDataSet)
    begin
      lAgeCumulative := lAgeCumulative + YearsBetween(Now, lDS.FieldByName('dob').AsDateTime);
    end);
  var lAvgAge := lAgeCumulative / lDS.RecordCount;
  lDS.First;
  // end - stats

  lJSON.A['customers'] := lDS.AsJDOJSONArray();
  lJSON.F['avg_age'] := lAvgAge;
  ViewData['data'] := lJSON;
  Result := RenderView('index');
end;

Template della Directory Clienti (customers.html):

{{extends "_layout.html"}}

{{block "body"}}

       <h2 class="mb-4">Customers Directory</h2>

        <!-- TemplatePro Template for Dataset Table -->
        {{if data.customers}}
            <div class="table-container">
                <table class="table table-striped table-hover mb-0">
                    <thead>
                        <tr>
                            <th scope="col">#</th>
                            <th scope="col">Code</th>
                            <th scope="col">First Name</th>
                            <th scope="col">Last Name</th>
                            <th scope="col">Country</th>
                            <th scope="col">Date of Birth</th>
                            <th scope="col">Age</th>
                        </tr>
                    </thead>
                    <tbody>
                        {{for customer in data.customers}}
                        <tr {{if customer.@@odd}}class="table-light"{{endif}}>
                            <th scope="row">{{:customer.@@index}}</th>
                            <td>
                                <span class="badge bg-secondary">{{:customer.code}}</span>
                            </td>
                            <td>{{:customer.first_name|capitalize}}</td>
                            <td>{{:customer.last_name|uppercase}}</td>
                            <td>
                                <span class="badge bg-primary badge-country">{{:customer.country|uppercase}}</span>
                            </td>
                            <td>{{:customer.dob}}</td>
                            <td>
                                {{if customer.dob}}
                                    <small class="text-muted">
                                        <!-- Calculate age - you'd implement this as a custom filter -->
                                        {{:customer.dob|age}} years
                                    </small>
                                {{else}}
                                    <small class="text-muted">N/A</small>
                                {{endif}}
                            </td>
                        </tr>
                        {{endfor}}
                    </tbody>
                </table>
            </div>

            <!-- Dataset Statistics -->
            <div class="row mt-4">
                 <div class="col-md-4">
                    <div class="card text-center">
                        <div class="card-body">
                            <h5 class="card-title">{{:data.customers|count}}</h5>
                            <p class="card-text">Total Customers</p>
                        </div>
                    </div>
                </div>
                <div class="offset-md-4 col-md-4">
                    <div class="card text-center">
                        <div class="card-body">
                            <h5 class="card-title">{{:data.avg_age|round,-2}} years</h5>
                            <p class="card-text">Average Age</p>
                        </div>
                    </div>
                </div>
            </div>

        {{else}}
            <!-- Empty State -->
            <div class="alert alert-info text-center" role="alert">
                <h4 class="alert-heading">No Data Available</h4>
                <p>The employee dataset is empty or not loaded.</p>
                <hr>
                <p class="mb-0">Please check your data source and try again.</p>
            </div>
        {{endif}}

        <!-- Action Buttons -->
        <div class="d-flex justify-content-between mt-4">
            <button class="btn btn-outline-secondary" onclick="window.print()">
                Print Table
            </button>
            <div>
                <button class="btn btn-success me-2" onclick="exportToCSV()">
                    Export CSV
                </button>
                <button class="btn btn-primary" onclick="addEmployee()">
                    Add Employee
                </button>
            </div>
        </div>
    </div>

    <script>
        function exportToCSV() {
            // CSV export functionality
            alert('CSV export would be implemented here');
        }

        function addEmployee() {
            // Add employee functionality
            alert('Add employee form would open here');
        }
    </script>

{{endblock}}

Filtri Personalizzati per Logica di Dominio

Crea filtri specializzati per il tuo dominio di business:

// Custom filter for "age" expressed as in "I'm x years old"
function Age(const Value: TValue; const Parameters: TArray<TFilterParameter>): TValue;
begin
  //DOB is a string formatted as yyyy-mm-dd
  Result := YearsBetween(Now, ISODateToDate(Value.AsString));
end;

// Register filters
procedure TemplateProContextConfigure;
begin
  TTProConfiguration.OnContextConfiguration := procedure(const CompiledTemplate: ITProCompiledTemplate)
  begin
    // These filters will be available to the TemplatePro views as if they were the standard ones
    CompiledTemplate.AddFilter('age', Age);
  end;
end;

Utilizzo nei template:

{{if customer.dob}}
    <small class="text-muted">
        <!-- Calculate age - you'd implement this as a custom filter -->
        {{:customer.dob|age}} years
    </small>
{{else}}
    <small class="text-muted">N/A</small>
{{endif}}

Ecco la pagina di esempio risultante.

Funzioni dei Template per Logica Complessa

Le funzioni forniscono ancora più potenza e possono essere utilizzate per implementare logica complessa.

Integrazione con HTMX

Le pagine HTMX possono beneficiare della generazione di codice lato server e integrarsi con i server REST per quanto riguarda gli aggiornamenti dei contenuti. Le tecnologie web Delphi possono offrire generazione di pagine e API REST a un livello di qualità molto elevato.

<!-- HTMX-powered dynamic content -->
<div id="customer-list">
    {{include "partials/customer-list.html"}}
</div>

<button hx-get="/api/customers"
        hx-target="#customer-list"
        hx-swap="innerHTML">
    Refresh Customers
</button>

<form hx-post="/api/customers"
      hx-target="#customer-list"
      hx-swap="innerHTML">
    <input name="name" placeholder="Customer Name" required>
    <input name="email" placeholder="Email" required>
    <button type="submit">Add Customer</button>
</form>

TemplatePro supporta funzionalità enterprise come:

  • Template Compilati per massime prestazioni e minor carico CPU
  • Autenticazione e Autorizzazione i template possono avere accesso ai ruoli utente
  • Gestione degli Errori in caso di errori non gestiti viene attivata la gestione degli errori predefinita (controlla l’esempio \samples\custom_exception_handling_using_controller)

Risorse di Apprendimento e Prossimi Passi

Iniziare Immediatamente

Il modo più veloce per iniziare è utilizzare il wizard DMVCFramework nell’IDE Delphi. DMVCFramework permette di creare potenti server RESTful senza sforzo. Puoi creare un server RESTful completo in un paio di click.

Comunità e Supporto

Su WebStencils

Per una copertura completa di WebStencils e dell’integrazione HTMX, raccomandiamo vivamente di scaricare il White Paper gratuito di Antonio Zapater disponibile sul blog di Embarcadero. Questa guida fornisce una copertura approfondita di:

  • Tecniche avanzate di scripting WebStencils
  • Pattern di integrazione HTMX
  • Strategie di deployment enterprise
  • Ottimizzazione delle prestazioni
  • Best practice di sicurezza

Conclusione

La combinazione di DMVCFramework e TemplatePro (o WebStencils) rappresenta un paradigma potente per lo sviluppo web rapido. Mentre altri framework richiedono processi di build complessi, conoscenza estensiva di JavaScript e procedure di deployment intricate, questo stack basato su Delphi fornisce:

Velocità: Dal concetto alla produzione in minuti, non settimane Semplicità: Sintassi intuitiva che gli sviluppatori possono padroneggiare rapidamente Potenza: Funzionalità di livello enterprise senza complessità di livello enterprise Flessibilità: Deploy ovunque, integra con qualsiasi cosa Stabilità: Testato in battaglia in ambienti di produzione in tutto il mondo

Come rivelato da un’analisi di Embarcadero, DMVCFramework è il progetto Delphi più popolare per WebAPI e WebApp su GitHub dal 2017, e la sua integrazione con motori di template moderni come TemplatePro e WebStencils rafforza solo la sua posizione come soluzione di riferimento per lo sviluppo web rapido.

Che tu stia costruendo strumenti interni, applicazioni rivolte ai clienti o API enterprise, questo stack fornisce il perfetto equilibrio tra produttività e professionalità. La curva di apprendimento è dolce, la documentazione è completa e la comunità è di supporto.

Per gli sviluppatori stanchi di toolchain complesse e soluzioni sovra-ingegnerizzate, DMVCFramework con TemplatePro offre un ritorno rinfrescante alla semplicità senza sacrificare le capacità. In un mondo dove lo sviluppo web spesso sembra inutilmente complicato, questi strumenti dimostrano che a volte la soluzione migliore è anche quella più semplice.

Pronto a sperimentare la velocità e la semplicità di persona? Inizia con il wizard DMVCFramework, esplora gli esempi, e immergiti nelle risorse gratuite disponibili. La tua prossima applicazione web è a pochi minuti di distanza.

Comments

comments powered by Disqus