一键导入
delphimvcframework
Patterns for development with DelphiMVCFramework (DMVC) — controllers, Active Record, JWT, Swagger
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Patterns for development with DelphiMVCFramework (DMVC) — controllers, Active Record, JWT, Swagger
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Pragmatic clean code standards for Delphi — concise, direct, no over-engineering
Delphi code review checklist — quality, security, performance, SOLID, memory
Good memory management practices, memory leak prevention and exception handling in Delphi
SOLID implementation patterns for Delphi projects — Repository, Service, Factory, Strategy with constructor injection and interfaces
Implementation of the 23 GoF (Gang of Four) patterns in Object Pascal / Delphi with interfaces, TInterfacedObject and SOLID principles. Covers Creational, Structural and Behavioral patterns.
Standards for using DevExpress (DEXT) components in Delphi VCL applications
| name | DelphiMVCFramework |
| description | Patterns for development with DelphiMVCFramework (DMVC) — controllers, Active Record, JWT, Swagger |
Use this skill when creating web applications and REST APIs with DelphiMVCFramework.
DelphiMVCFramework is the most complete MVC framework for Delphi, created by Daniele Teti. Supports RESTful APIs, Server-Sent Events, WebSockets, Active Record, JSON/XML serialization and more.
src/
├── MeuApp.dpr ← Projeto principal
├── MeuApp.WebModule.pas ← WebModule com engine DMVC
├── Controllers/
│ ├── MeuApp.Controller.Customer.pas
│ ├── MeuApp.Controller.Product.pas
│ └── MeuApp.Controller.Base.pas
├── Models/
│ ├── MeuApp.Model.Customer.pas ← Active Record
│ ├── MeuApp.Model.Product.pas
│ └── MeuApp.Model.Base.pas
├── Services/
│ └── MeuApp.Service.Customer.pas
├── Middleware/
│ ├── MeuApp.Middleware.Auth.pas
│ └── MeuApp.Middleware.CORS.pas
└── Config/
└── MeuApp.Config.pas
unit MeuApp.WebModule;
interface
uses
System.SysUtils,
System.Classes,
Web.HTTPApp,
MVCFramework,
MVCFramework.Commons;
type
TAppWebModule = class(TWebModule)
procedure WebModuleCreate(Sender: TObject);
procedure WebModuleDestroy(Sender: TObject);
private
FMVCEngine: TMVCEngine;
end;
implementation
uses
MVCFramework.Middleware.CORS,
MVCFramework.Middleware.JWT,
MVCFramework.Middleware.StaticFiles,
MeuApp.Controller.Customer,
MeuApp.Controller.Product;
procedure TAppWebModule.WebModuleCreate(Sender: TObject);
begin
FMVCEngine := TMVCEngine.Create(Self,
procedure(AConfig: TMVCConfig)
begin
AConfig[TMVCConfigKey.DocumentRoot] := 'public';
AConfig[TMVCConfigKey.DefaultContentType] := TMVCMediaType.APPLICATION_JSON;
AConfig[TMVCConfigKey.DefaultViewFileExtension] := 'html';
end
);
// Controllers
FMVCEngine.AddController(TCustomerController);
FMVCEngine.AddController(TProductController);
// Middleware
FMVCEngine.AddMiddleware(TMVCCORSMiddleware.Create);
end;
procedure TAppWebModule.WebModuleDestroy(Sender: TObject);
begin
FMVCEngine.Free;
end;
unit MeuApp.Controller.Customer;
interface
uses
MVCFramework,
MVCFramework.Commons,
MVCFramework.Serializer.Commons;
type
[MVCPath('/api/customers')]
TCustomerController = class(TMVCController)
public
[MVCPath]
[MVCHTTPMethod([httpGET])]
[MVCProduces(TMVCMediaType.APPLICATION_JSON)]
procedure GetAll;
[MVCPath('/($id)')]
[MVCHTTPMethod([httpGET])]
[MVCProduces(TMVCMediaType.APPLICATION_JSON)]
procedure GetById(const AId: Integer);
[MVCPath]
[MVCHTTPMethod([httpPOST])]
[MVCConsumes(TMVCMediaType.APPLICATION_JSON)]
[MVCProduces(TMVCMediaType.APPLICATION_JSON)]
procedure CreateCustomer;
[MVCPath('/($id)')]
[MVCHTTPMethod([httpPUT])]
[MVCConsumes(TMVCMediaType.APPLICATION_JSON)]
procedure UpdateCustomer(const AId: Integer);
[MVCPath('/($id)')]
[MVCHTTPMethod([httpDELETE])]
procedure DeleteCustomer(const AId: Integer);
end;
implementation
uses
System.SysUtils,
MVCFramework.ActiveRecord,
MeuApp.Model.Customer;
procedure TCustomerController.GetAll;
var
LCustomers: TMVCActiveRecordList;
begin
LCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('', 100);
Render<TCustomer>(LCustomers);
end;
procedure TCustomerController.GetById(const AId: Integer);
var
LCustomer: TCustomer;
begin
LCustomer := TMVCActiveRecord.GetByPK<TCustomer>(AId);
if not Assigned(LCustomer) then
begin
Render(HTTP_STATUS.NotFound, 'Customer not found');
Exit;
end;
Render(LCustomer);
end;
procedure TCustomerController.CreateCustomer;
var
LCustomer: TCustomer;
begin
LCustomer := Context.Request.BodyAs<TCustomer>;
try
LCustomer.Insert;
Render201Created('/api/customers/' + LCustomer.Id.ToString);
except
on E: Exception do
begin
LCustomer.Free;
raise;
end;
end;
end;
procedure TCustomerController.UpdateCustomer(const AId: Integer);
var
LCustomer: TCustomer;
begin
LCustomer := Context.Request.BodyAs<TCustomer>;
try
LCustomer.Id := AId;
LCustomer.Update;
Render(HTTP_STATUS.OK, 'Updated');
except
on E: Exception do
begin
LCustomer.Free;
raise;
end;
end;
end;
procedure TCustomerController.DeleteCustomer(const AId: Integer);
var
LCustomer: TCustomer;
begin
LCustomer := TMVCActiveRecord.GetByPK<TCustomer>(AId);
if not Assigned(LCustomer) then
begin
Render(HTTP_STATUS.NotFound, 'Customer not found');
Exit;
end;
try
LCustomer.Delete;
Render(HTTP_STATUS.NoContent, '');
finally
LCustomer.Free;
end;
end;
unit MeuApp.Model.Customer;
interface
uses
MVCFramework.ActiveRecord,
MVCFramework.Serializer.Commons;
type
[MVCTable('customers')]
[MVCNameCase(ncLowerCase)]
TCustomer = class(TMVCActiveRecord)
private
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
FId: Integer;
[MVCTableField('name')]
FName: string;
[MVCTableField('cpf')]
FCpf: string;
[MVCTableField('email')]
FEmail: string;
[MVCTableField('status')]
FStatus: Integer;
[MVCTableField('created_at')]
FCreatedAt: TDateTime;
public
property Id: Integer read FId write FId;
property Name: string read FName write FName;
property Cpf: string read FCpf write FCpf;
property Email: string read FEmail write FEmail;
property Status: Integer read FStatus write FStatus;
property CreatedAt: TDateTime read FCreatedAt write FCreatedAt;
end;
implementation
end.
uses
MVCFramework.Middleware.JWT;
// No WebModule:
FMVCEngine.AddMiddleware(
TMVCJWTAuthenticationMiddleware.Create(
TAuthHandler.Create, // implementa IMVCAuthenticationHandler
'my-secret-key',
'/api/login', // rota pública de login
[TJWTCheckableClaim.ExpirationTime]
)
);
// Filtrar via query string (DMVC interpreta RQL automaticamente)
// GET /api/customers?$filter=contains(name,'João')&$orderby=name&$top=10
LCustomers := TMVCActiveRecord.SelectRQL<TCustomer>(
Context.Request.QueryStringParam('$filter'),
Context.Request.QueryStringParam('$top').ToInteger
);
| Appearance | Convention |
|---|---|
| Controller | Inherits from TMVCController with [MVCPath] attribute |
| Models | Inherits from TMVCActiveRecord with [MVCTable] attribute |
| Routes | Attributes: [MVCPath], [MVCHTTPMethod] |
| Serialization | Automatic via Render() (JSON by default) |
| Parameters | Path: ($id), Query: Context.Request.QueryStringParam |
| Body | Context.Request.BodyAs<T> to deserialize JSON |
| Status | Render(HTTP_STATUS.OK), Render201Created |
| Middleware | Inherits from TMVCCustomMiddleware or uses built-in |
| Swagger | Attributes [MVCSwagSummary], [MVCSwagParam] |
TMVCEngine?AddController?[MVCTable] and [MVCTableField]?Render() used for all answers?BodyAs<T> objects released in case of exception?