hindy / orm
Requires
- hindy/application: 0.*
- hindy/di: ^0.1.0
- hindy/logger: ^1.0
- hindy/query: ^0.4
- hindy/storage: ^0.1.4
- hindy/tests: ^0.1.0
- hindy/validation: 0.1.4.*
- imagine/imagine: ^0.6.2
This package is not auto-updated.
Last update: 2024-09-14 18:36:48 UTC
README
又一 个 Django ORM 在 PHP 上的实现。目前处于积极开发阶段,不建议在生产环境中使用直到版本 1.0。
对于文档的不足之处,我们表示歉意。文档仍在开发中。
部分代码基于 yii2 框架,但由于内核的模块化,我们不得不将框架分割成单独的包。在 Mindy ORM
中,Query 从 yii2 得到积极的应用。
支持的数据库类型:sqlite
、mysql
、pgsql
、mssql
(所有 yii2 query 能处理的)。理论上 ORM 能够与 NoSql
存储库一起工作,这是通过实现自己的管理器并重写 Lookup
实现的。
ORM 功能的简要示例
描述数据库连接
Model::setConnection([ 'sqlite::memory' ]);
描述模型
class MyModel extends Model { public function getFields() { return [ // Ключ - название поля при обращении к модели 'name' => [ // Тип поля 'class' => CharField::className(), // Длинна поля 'length' => 100, // NULL|NOT NULL 'null' => false, // "Читабельное" имя модели. Используется в Mindy\Form\ModelForm // для построения форм автоматически. 'verboseName' => 'Продукция', // Пример валидаторов 'validators' => [ function ($value) { if (mb_strlen($value, 'UTF-8') < 3) { return "Minimal length < 3"; } return true; }, new UniqueValidator ] ], 'price' => [ 'class' => CharField::className(), // Значение по умолчанию 'default' => 0 ], 'description' => [ 'class' => TextField::className(), 'default' => '' ], 'category' => [ 'class' => ForeignField::className(), 'modelClass' => Category::className(), 'null' => true ], 'lists' => [ 'class' => ManyToManyField::className(), 'modelClass' => ProductList::className() ] ]; } }
模型描述完成。验证基于模型字段的验证。模型已描述,现在需要将其创建在子数据库中。为此,我们将执行以下代码
$sync = new Sync([ new MyModel() ]); $sync->create();
数据库中将创建所有传入模型的表以及索引和关联(如果可能)。
创建一些记录
// Если модель с идентичными полями найдется, то ORM вернет ее, иначе создаст. $model = MyModel::objects()->getOrCreate(['name' => 'Поросенок петр', 'price' => 1]); $modelTwo = new MyModel; // Массовое присвоение аттрибутов $modelTwo->setData([ 'name' => 'Рубаха', 'price' => 2 ]); // Валидация и сохранение if($modelTwo->isValid() && $modelTwo->save()) { echo 'Модель сохранена'; } $modelThree = new MyModel; $modelThree->name = 'Джинсы'; $modelThree->price = 3; // Валидация и сохранение if($modelThree->isValid() && $modelThree->save()) { echo 'Модель сохранена'; }
查询实现与 Django 框架类似
// SELECT * FROM my_model WHERE price >= 2 $models = MyModel::objects()->filter(['price__gte' => 2])->all(); // SELECT * FROM my_model WHERE name = 'Рубаха' $models = MyModel::objects()->filter(['name' => 'Рубаха'])->all(); // SELECT * FROM my_model WHERE id IN (1, 2, 3) $models = MyModel::objects()->filter(['pk__in' => [1, 2, 3]])->all();
等等。更详细的信息请参阅 Lookups 部分
清空数据库
$sync = new Sync([ new MyModel() ]); $sync->delete();
管理器
管理器是代理到 QuerySet
类的接口,负责处理我们的 Lookup
并执行查询。每个模型默认都有一个 objects()
管理器。
User::objects()
管理器处理 QuerySet。管理器的主要方法是 getQuerySet()
。它返回随后由管理器处理的对象。如果您想更改默认管理器的逻辑,您可以创建自己的管理器。例如,activeUsersManager()
class ActiveUsersManager extends Manager { public function getQuerySet() { $qs = parent::getQuerySet(); return $qs->filter(['status' => User::STATUS_ACTIVE]); } }
具有自定义管理器的模型
class User extends Model { public function getFields() { 'name' => [ 'class' => CharField::className(), ], 'status' => [ 'class' => BooleanField::className(), 'default' => false ] } public static function activeUsersManager($instance = null) { $className = get_called_class(); return new ActiveUsersManager($instance ? $instance : new $className); } }
现在您可以使用 ActiveUsersManager()
通过 User::activeUsers()
。所有查询都将根据您的处理逻辑仅针对活动用户执行。例如,此代码将帮助选择所有以 'A' 开头的活跃用户。
User::activeUsers()->filter(['name__startswith' => 'A'])->all();
Manager/QuerySet 方法
返回结果的方法
获取
选择一个对象。如果存在多个符合条件的结果,则抛出异常,否则返回对象。如果没有找到对象,则返回 null。
找到 pk == 5
的对象。
$model = User::objects()->filter(['pk' => 5])->get();
全部
返回 Model
类的模型数组或调用 asArray()
方法时的关联数组。
选择所有用户。将返回 User
类的模型数组。
User::objects()->all();
选择所有用户。将返回关联数组。
User::objects()->asArray()->all();
计数
返回符合条件的结果的对象数
User::objects()->count();
返回已修改 QuerySet 的方法
您可以连续调用这些方法
User::objects()->filter(['name' => 'Max'])->exclude(['address' => 'New York'])->order(['-address'])->all();
此代码返回所有名为 Max
且不住在 New York
的用户,按地址降序排序。
SELECT * FROM user WHERE name='Max' AND address != 'New York' ORDER BY address DESC
过滤
您可以使用以下代码找到所有属于名为 example
的组的用户
User::objects()->filter(['group__name' => 'example'])->all();
group
在此情况下是到 Group
模型的 m2m
关联
排除
您可以使用以下代码找到所有不属于名为 example
的组的用户
User::objects()->exclude(['group__name' => 'users'])->all();
group
在此情况下是到 Group
模型的 m2m
关联
排序
查找所有用户并按姓名排序
User::objects()->order(['name'])->all();
查找所有用户并按姓名逆序排序
User::objects()->order(['-name'])->all();
查找所有用户并随机排序
User::objects()->order(['?'])->all();
查找
使用查找(lookups)可以过滤QuerySet。查找在经理方法exclude()
和filter()
中应用,并以数组的形式传递给它们,其中数组的键是字段(带查找),值是用于筛选的值。查找示例
'name__exact'
该查找指示字段name
应等于指定的值。应用示例
User::objects()->filter(['name__exact' => 'Max'])->all();
选择所有名字等于'Max'的用户。 实际上,exact
查找是默认查找。也就是说,在这个例子中,我们可以使用条件filter(['name' => 'Max'])
来代替。
SELECT * FROM user WHERE name = 'Max'
isnull
查找用于在数据库中搜索NULL
值。应用示例
User::objects()->filter(['name__isnull' => true])->all();
将选择所有在数据库中名字字段值为NULL
的用户。
SELECT * FROM user WHERE name IS NULL
如果传递false
作为值,SQL查询将如下所示
SELECT * FROM user WHERE name IS NOT NULL
lte, lt
用于搜索小于指定值(lt
)和小于或等于指定值(lte
)的查找。以下lt
查找示例
Product::objects()->filter(['price__lt' => 100.00])->all();
将选择所有价格严格小于100.00
的产品。
以下lte
查找示例
Product::objects()->filter(['price__lte' => 100.00])->all();
$dateTime = new DateTime(); $dateTime->setTimestamp(strtotime('+15 days')) Product::objects()->filter(['created_at__lte' => $dateTime])->all();
将选择所有价格小于或等于100.00
的产品。
lt
生成的SQL
SELECT * FROM user WHERE price < 100.00
lte
生成的SQL
SELECT * FROM user WHERE price <= 100.00
gte, gt
用于搜索大于指定值(gt
)和大于或等于指定值(gte
)的查找。以下gt
查找示例
Product::objects()->filter(['price__gt' => 100.00])->all();
将选择所有价格严格大于100.00
的产品。
以下gte
查找示例
Product::objects()->filter(['price__gte' => 100.00])->all();
将选择所有价格大于或等于100.00
的产品。
gt
生成的SQL
SELECT * FROM user WHERE price > 100.00
gte
生成的SQL
SELECT * FROM user WHERE price >= 100.00
exact
用于搜索严格等于指定值的值。示例
User::objects()->filter(['name__exact' => 'Max'])->all();
将选择所有名字为'Max'的用户。**查找是默认查找,也就是说,在之前的例子中,我们可以简单地使用['name' => 'Max']
**
contains
用于搜索包含指定值的值(类似于SQL LIKE)。大小写敏感搜索。对于不区分大小写的搜索,请使用查找icontains
。示例
User::objects()->filter(['name__contains' => 'ax'])->all();
将选择所有名字中包含'ax'组合的用户。
SELECT * FROM user WHERE name LIKE '%ax%'
icontains
完全重复contains
查找,但执行不区分大小写搜索。
startswith
用于搜索以指定值开始的值:大小写敏感。对于不区分大小写的搜索,请使用查找istartswith
。示例
User::objects()->filter(['name__startswith' => 'M'])->all();
将选择所有名字以'M'开始的用户。
SELECT * FROM user WHERE name LIKE 'M%'
istartswith
完全重复startswith
查找,但执行不区分大小写的搜索。
endswith
用于搜索以指定值结束的值:大小写敏感。对于不区分大小写的搜索,请使用查找iendswith
。示例
User::objects()->filter(['name__endswith' => 'on'])->all();
将选择所有名字以'on'结束的用户。
SELECT * FROM user WHERE name LIKE '%on'
iendswith
完全重复iendswith
查找,但执行不区分大小写的搜索。
in
用于搜索在传递的值列表中的值:示例
User::objects()->filter(['pk__in' => [1, 2]])->all();
将选择所有pk在列表[1, 2]
中的用户。
SELECT * FROM user WHERE id IN (1, 2)
查找可以接受QuerySet作为值
此查找不仅可以接受值数组,还可以接受QuerySet对象。在这种情况下,查询将添加子查询。
示例
$group_qs = Group::objects()->filter(['name__startswith' => 'A']);
$users = User::objects()->filter(['groups__pk__in' => $group_qs->select('id') ])->all();
将选择所有组名以'A'开头的用户。将只执行一次选择用户的查询。
range
此查找允许找到位于指定值之间的值。此查找接受两个元素的数组。
示例
Product::objects()->filter(['price__range' => [10, 20]])
将选择所有价格在10到20之间的产品。
SELECT * FROM product WHERE price BETWEEN 10 AND 20
year
此查找仅适用于类型为DateTimeField
、DateField
的字段。允许找到位于指定年份的所有值。
示例
Product::objects()->filter(['date_added__year' => 2014])
将选择所有在2014年添加的产品。
注意:SQL查询将因不同的数据库而异。
month
此查找仅适用于类型为DateTimeField
、DateField
的字段。允许找到位于指定月份的所有值。
示例
Product::objects()->filter(['date_added__year' => 12])
将选择所有在十二月添加的产品。
注意:SQL查询将因不同的数据库而异。
day
该查找器仅与类型为 DateTimeField
、DateField
的字段一起使用。允许找到位于指定月份某一天的所有值。
示例
Product::objects()->filter(['date_added__day' => 25])
将选择所有在任何月份的25日添加的产品。
注意:SQL查询将因不同的数据库而异。
week_day
该查找器仅与类型为 DateTimeField
、DateField
的字段一起使用。允许找到位于指定星期某一天的所有值。
值:1 - 星期日,2 - 星期一,...,7 - 星期六。天数的顺序由 ORM 确定,并适应当前子数据库的以下原因
Method Range
------ -----
PYTHON
datetime_object.weekday() 0-6 Sunday=6
datetime_object.isoweekday() 1-7 Sunday=7
dt_object.isoweekday() % 7 0-6 Sunday=0 # Can easily add 1 for a 1-7 week where Sunday=1
MYSQL
DAYOFWEEK(timestamp) 1-7 Sunday=1
WEEKDAY(timestamp) 0-6 Monday=0
POSTGRES
EXTRACT('dow' FROM timestamp) 0-6 Sunday=0
TO_CHAR(timestamp, 'D') 1-7 Sunday=1
ORACLE
TO_CHAR(timestamp, 'D') 1-7 Sunday=1 (US), Sunday=6 (UK)
示例
Product::objects()->filter(['date_added__week_day' => 2])
将选择所有在星期一添加的产品。
注意:SQL查询将因不同的数据库而异。
hour
该查找器仅与类型为 DateTimeField
、TimeField
的字段一起使用。允许找到位于指定小时的所有值。示例
Product::objects()->filter(['date_added__hour' => 10])
将选择所有在10小时添加的产品。
注意:SQL查询将因不同的数据库而异。
minute
该查找器仅与类型为 DateTimeField
、TimeField
的字段一起使用。允许找到位于指定分钟的所有值。示例
Product::objects()->filter(['date_added__minute' => 35])
将选择所有在35分钟添加的产品。
注意:SQL查询将因不同的数据库而异。
second
该查找器仅与类型为 DateTimeField
、TimeField
的字段一起使用。允许找到位于指定秒的所有值。示例
Product::objects()->filter(['date_added__minute' => 45])
将选择所有在45秒添加的产品。
注意:SQL查询将因不同的数据库而异。
search
** 未实现 **
regex
按正则表达式搜索。 大小写敏感。对于大小写不敏感,请使用查找器 iregex
。示例
Product::objects()->filter(['name__regex' => '[a-z]'])
将选择所有符合正则表达式 [a-z]
的产品。
注意:SQL查询将因不同的数据库而异。
iregex
完全重复前面的查找器,但执行大小写不敏感的搜索。
注意:SQL查询将因不同的数据库而异。
Q-对象(查询对象)
Q-对象用于方便地形成选择条件。存在两个 Q-对象:OrQ 和 AndQ。
Q-对象是这样形成的
new OrQ([['status' => 1, 'user_id' => 1],['status' => 2, 'user_id' => 4]]);
然后可以将其传递给方法 filter 或 exclude
Requests::objects()->filter([new OrQ([['status' => 1, 'user_id' => 1],['status' => 2, 'user_id' => 4]])])->all()
该查询将选择所有状态为1的用户id为1的申请和状态为2的用户id为4的申请。