rjjakes/wordpress-orm

WORM. Doctrine风格的WordPress ORM。

0.1.0 2022-07-14 19:51 UTC

This package is not auto-updated.

Last update: 2024-09-29 04:42:59 UTC


README

正在积极开发中

一个轻量级的、Doctrine风格的WordPress 4.8+ ORM。需要PHP 5.5+。

这个库从Doctrine(用于Symfony)借鉴了很多概念,包括映射器、实体管理器、仓库、一对多实体关系、相关实体的懒加载以及查询构建器。

它作为一个层,位于WordPress内部$wpdb类之上。

所有查询都通过WordPress内部$wpdb->prepare()函数运行,以防止SQL注入攻击。

为什么?

我从Symfony开发背景转到WordPress。我想使用对象而不是手动编写SQL查询。我四处寻找一个好的ORM,但没有找到能满足我要求的任何东西。

使Doctrine与WordPress协同工作很复杂,而且感觉像是过度杀鸡用牛刀,因为这个库非常庞大。

还有:[https://github.com/tareq1988/wp-eloquent](https://github.com/tareq1988/wp-eloquent),这是一个非常好的工具,但它更像是一个现有WordPress表的查询构建器。

版本历史

master分支 = 活跃开发

0.1.0标签 = 之前的master。大多数人可能在2022年左右使用的版本。

安装

composer require rjjakes/wordpress-orm

用法

创建模型

要使用ORM,首先创建一个扩展ORM基模型的类,并添加一些作为受保护变量的属性。属性名必须与所需的SQL列名完全匹配(没有名称映射)。

请注意,当你执行extends BaseModel时,模型中会添加一个$id属性,因此你不需要添加它。

示例

<?php

namespace App\Models;

use Symlink\ORM\Models\BaseModel as Model;

/**
 * @ORM_Type Entity
 * @ORM_Table "product"
 * @ORM_AllowSchemaUpdate True
 */
class Product extends Model {

  /**
   * @ORM_Column_Type TEXT
   */
  protected $title;

  /**
   * @ORM_Column_Type datetime
   */
  protected $time;

  /**
   * @ORM_Column_Type smallint
   * @ORM_Column_Length 5
   * @ORM_Column_Null NOT NULL
   */
  protected $views;

  /**
   * @ORM_Column_Type varchar
   * @ORM_Column_Length 32
   * @ORM_Column_Null NOT NULL
   */
  protected $short_name;

}

类的注解如下

ORM_Type 应始终为 "Entity"

ORM_Table 这是数据库中的实际表名,不带WordPress后缀。因此,在一个默认的WordPress安装中,这将创建一个名为wp_product的表。

ORM_AllowSchemaUpdate 这允许或阻止数据库模式更新,通过updateSchema()函数(见下文)。对于自定义模型,您想将其设置为True。当将模型映射到现有的WordPress表(如wp_posts)时,应将其设置为False,以避免损坏该表。

属性注解如下

ORM_Column_Type MySQL列类型。

ORM_Column_Length MySQL列长度。

ORM_Column_Null MySQL列NULL设置。在这里唯一有效的选项是 'NOT NULL'。对于NULL,只需省略此注解。

更新数据库模式

一旦你有了模型对象,你需要告诉WordPress创建一个与你的模型匹配的表。

使用映射类

use Symlink\ORM\Mapping;

首先,获取ORM映射对象的实例。下面的静态函数确保每个请求只调用一次new Mapping()。对::getMapper()的任何后续调用都将返回相同的对象。这意味着你不需要不断创建新的Mapper()实例并解析注解。

$mapper = Mapping::getMapper();

现在按如下方式更新此类的数据库模式:

$mapper->updateSchema(Product::class);

此函数使用Wordpress的内部dbDelta系统来比较和更新数据库表。如果您的表不存在,则会创建它;否则,它会检查模式是否与模型匹配,并在必要时修改数据库表。

您只能在插件激活时或开发期间您知道您已经对模型模式进行了更改并希望将其应用到数据库中时运行此函数。

将对象持久化到数据库。

使用ORM管理器。

use Symlink\ORM\Manager;

创建您模型的实例。

$product = new Product();
$product->set('title', 'Some title');
$product->set('time', '2017-11-03 10:04:02');
$product->set('views', 34);
$product->set('short_name', 'something_here');

获取ORM管理器类的实例。类似于Mapping类,此静态函数返回管理器类的可重用实例。

$orm = Manager::getManager();

现在将这些更改排队以应用到数据库中。调用此操作不会立即将更改应用到数据库中。这里的想法与Doctrine相同:您可以排队执行许多不同的更改,一旦准备好应用它们,ORM将尽可能地将这些更改组合成单个SQL查询。这有助于减少对数据库的调用次数。

$orm->persist($product);

一旦准备好将所有更改应用到您的数据库中(同步到数据库中持久化的内容),请调用flush()。

$orm->flush();

现在检查您的数据库,您将看到包含您的模型数据的新行。

查询数据库。

使用ORM管理器。

use Symlink\ORM\Manager;

获取ORM管理器类的实例。

$orm = Manager::getManager();

获取对象存储库。存储库是针对特定对象类型的类。它们包含查询特定对象类型的函数。

默认情况下,所有对象类型都有一个基存储库,您可以通过传递对象类型如下方式获取访问权限:

$repository = $orm->getRepository(Product::class);

使用查询构建器。

您可以通过此存储库创建查询,如下所示:

$query = $repository->createQueryBuilder()
  ->where('ID', 3, '=')
  ->orderBy('ID', 'ASC')
  ->limit(1)
  ->buildQuery();

可用的where()运算符包括:

'<', '<=', '=', '!=', '>', '>=', 'IN', 'NOT IN'

可用的orderBy()运算符包括:

'ASC', 'DESC'

要使用“IN”和“NOT IN”子句的->where()函数,可以传递一个值数组,如下所示:

$query = $repository->createQueryBuilder()
  ->where('id', [1, 12], 'NOT IN')
  ->orderBy('id', 'ASC')
  ->limit(1)
  ->buildQuery();

现在您有了查询,您可以使用它从数据库中检索一些对象。

$results = $query->getResults();

请注意,如果有唯一的结果,$results将包含存储库类型的对象。否则,它将包含对象数组。

要强制getResults()始终返回数组(即使只有一个结果),请以这种方式调用它:

$results = $query->getResults(TRUE);

内置存储库查询函数。

每次从数据库中选择对象时都构建查询不是最佳实践。理想情况下,您会创建一些辅助函数,这些函数将查询构建器从控制器中抽象出来。

基存储库中有几个内置函数。

按id返回对象。

$results = Manager::getManager()
            ->getRepository(Product::class)
            ->find($id);

按升序id返回所有对象。

$results = Manager::getManager()
            ->getRepository(Product::class)
            ->findAll();

返回所有匹配属性名称和值的对象。

$results = Manager::getManager()
            ->getRepository(Product::class)
            ->findBy([$property_name_1 => $value_1, $property_name_2 => $value_2]);

要添加更多存储库查询函数,您可以子类化BaseRepository类,并让您的对象使用它而不是BaseRepository。这将在下面的部分中介绍:创建自定义存储库。

将修改后的对象保存回数据库。

要修改对象,从数据库中加载对象,修改一个或多个值,然后调用flush()将更改应用到数据库中。

例如:

$orm = Manager::getManager();
$repository = $orm->getRepository(Product::class);

$product = $repository->find(9);   // Load an object by known ID=9
$product->set('title', 'TITLE HAS CHANGED!');

$orm->flush();

这之所以有效,是因为每当对象被持久化或从数据库中加载时,WordPress ORM都会跟踪对模型数据的任何更改。flush()同步自加载(或最后一次flush())以来所做的更改。

从数据库中删除对象。

要从数据库中删除对象,从数据库中加载一个对象,并将其传递给管理器类的remove()方法。然后调用flush()以同步数据库。

例如:

$orm = Manager::getManager();
$repository = $orm->getRepository(Product::class);

$product = $repository->find(9);   // Load an object by known ID=9

$orm->remove($product);   // Queue up the object to be removed from the database. 

$orm->flush();

从数据库中删除模型表。

当用户卸载插件时清理任何创建的数据是很好的实践。考虑到这一点,ORM有一个用于删除先前创建的表的方法。如果您创建了任何自定义模型,应使用此函数作为卸载钩子的一部分。

使用映射类

use Symlink\ORM\Mapping;

首先,获取ORM映射对象的实例。

$mapper = Mapping::getMapper();

现在将模型类名传递给dropTable()函数,如下所示

$mapper->dropTable(Product::class);

创建自定义仓库

@待办

关系

@待办

异常

WordPress ORM使用异常来处理大多数失败状态。您需要在ORM函数调用周围使用try {} catch() {}块来处理这些异常,并向用户发送错误或警告消息。

例如:

try {
    $query = $repository->createQueryBuilder()
      ->where('ID', 3, '==')  // Equals operator should be '=' not '=='
      ->buildQuery();
} catch (\Symlink\ORM\Exceptions\InvalidOperatorException $e) {
    // ... warn the user about the bad operator or handle it another way. 
}

异常如下。

AllowSchemaUpdateIsFalseException
FailedToInsertException
InvalidOperatorException
NoQueryException
PropertyDoesNotExistException
RepositoryClassNotDefinedException
RequiredAnnotationMissingException
UnknownColumnTypeException

预定义模型

@待办

依赖项

(依赖项由Composer自动处理)。

https://github.com/marcioalmada/annotations

https://github.com/myclabs/deepcopy

致谢

维护者: https://github.com/rjjakes

这个库正在积极开发中,因此我非常欢迎评论、问题和拉取请求。