Mastering ThinkPHP 4.0+ Entity Models: A Complete Backend Guide
This guide explains ThinkPHP 4.0+ entity models, covering their layered architecture, installation, entity and model definitions, automatic relation queries, new type casting, accessors, configuration options, virtual and view models, with full code examples and practical tips for backend developers.
Overview
ThinkPHP 4.0+ introduced the concept of an entity model, separating the traditional Model layer into a repository Model for low‑level data operations and an Entity layer for data definition, presentation, business logic, and event handling. This layered design improves clarity, safety, and usability, especially in large projects.
Entity Model Advantages
More intuitive : define fields and relations via properties.
More secure : strong‑typed field definitions with new types.
More usable : view models, virtual models, auto‑relation and other new features simplify usage.
Model layering : Entity handles data display and processing; Model handles database connections, events, and relation definitions.
Current 4.0 version is still in testing; adjustments may occur. Do not use in production.
Installation
To try the 4.0 entity model, install the development version via Composer:
composer require topthink/think-orm:4.0.x-devModel Definition
Entity classes share the same name as their corresponding Model classes but reside in a different namespace. Example:
<?php
namespace app\entity;
use think\Entity;
class Blog extends Entity {}
?>Custom model binding can be achieved by overriding parseModel:
<?php
namespace app\entity;
use think\Entity;
use app\model\Blog as Other;
class Blog extends Entity {
protected function parseModel(): string {
return Other::class;
}
}
?>Properties can be defined explicitly with type hints, e.g.:
<?php
namespace app\entity;
use think\Entity;
use think\model\type\DateTime;
class Blog extends Entity {
protected int $id;
protected string $title;
protected string $content;
protected int $user_id;
protected DateTime $create_time;
protected DateTime $update_time;
protected User $user;
}
?>Fields must match the database column names; relationships are still defined in the Model class.
<?php
namespace app\model;
use think\Model;
class Blog extends Model {
public function user() {
return $this->belongsTo(User::class);
}
}
?>Automatic Relation Query
By configuring auto_relation in the Entity’s getOptions method, related data can be fetched without repeatedly calling with:
protected function getOptions(): array {
return [
'auto_relation' => ['user'],
];
}Then a simple Blog::find(1) automatically loads the associated user.
New Property Types
ThinkPHP adds several built‑in type classes that can be used in the type option to cast fields automatically: \think\model\type\Json – JSON formatted field. \think\model\type\DateTime – DateTime or timestamp field. \think\model\type\Date – Date field.
Even without explicit property definitions, the entity will convert these types after a query.
Accessors (属性器)
Instead of the older setXXXAttr / getXXXAttr methods, an Entity can define a single camel‑cased method that returns an array with get and set closures. Example for a name field:
protected function name() {
return [
'get' => function ($value) {
return strtoupper((string) $value);
},
'set' => function ($value) {
return strtolower($value);
},
];
}Accessors can also be defined for virtual (non‑database) fields.
Entity Options
Most settings are optional. Common options include: type – field‑type map. model_class – associated Model class name. strict – case‑sensitivity flag (default true). disuse, readonly, hidden, visible, append, mapping, auto_relation – various array‑based configurations. virtual, view – flags for virtual or view models. create_time, update_time – automatic timestamp fields.
Options are returned from a protected getOptions(): array method. Setting strict => false makes attribute access case‑insensitive, allowing camelCase property names while the underlying columns remain snake_case.
protected function getOptions(): array {
return [
'strict' => false,
'type' => [
'status' => StatusEnum::class,
],
];
}Virtual Model
A virtual model extends think\entity\Virtual and does not correspond to a database table. It can be created and mutated but cannot be persisted.
<?php
namespace app\entity;
use think\entity\Virtual;
class Blog extends Virtual {}
// Create data
$blog = Blog::create($data);
$blog->name = 'thinkphp';
?>View Model
View models allow you to compose queries that join multiple tables and return a read‑only result set without a backing Model class.
<?php
namespace app\entity;
use think\db\Query;
use think\entity\View;
class Test extends View {
public function query(Query $query) {
$this->view(Blog::class, 'id,title')
->view(User::class, 'name,email', 'Blog.user_id = User.id')
->where('status', '>', 0);
}
}
?>Execution example:
use app\entity\Test;
$result = Test::find(1);
dump($result);If you do not need the entity model, you can continue using the traditional Model layer without any code changes, making migration safe.
Feel free to leave comments with suggestions or feedback about the new ORM and entity model.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
