ongom/dite-orm

一个PHP ORM,用于与不同类型的数据库进行交互。

v1.6.0 2024-09-28 14:58 UTC

This package is auto-updated.

Last update: 2024-09-29 12:12:52 UTC


README

这是一个与关系型数据库交互的PHP ORM。它只支持Sqlite、Mysql、Sqlserver和Postgresql数据库。它允许我们在仅PHP代码中工作,而不是在sql和PHP代码之间切换。

dite-orm的功能。

dite-orm非常接近SQL。它可以轻松地帮助您快速与数据库交互,您只需一行代码就可以获得所有需要的内容。

  • 支持多种DBMS。

  • 配置设置可以直接添加到.env文件或使用设置方法,但不能同时使用。

  • 在后台使用PDO。

  • CRUD的简写。

  • 提供分页、限制、排序、只选择几个字段、WHERE子句等。

  • 获取带有相关数据的记录或记录,例如获取带有其评论的帖子,或获取发布它们的用户。

  • 根据另一张表从一张表中获取数据。例如,获取没有订单表中订单的产品的产品,获取按订单顺序订购次数最多和最少的产品的产品。

  • 关系(一对一、一对多、多对多)在单个函数中支持正向和反向关系。

  • 打印出正在运行的查询以生成提供的记录。

  • 提供编写原始SQL的选项。

  • 创建表及其字段时使用正确的数据类型,可自定义以满足您的需求。

  • 查询的表名与查询它的类名相匹配。也可以使用DB::table()传递表名。

  • 等等。

示例用法

User::create(['user'=>'john doe']); //creating a user

User::update(1,['user'=>'mike doe']); //updating a user with id 1

User::update(['age'=>20],['user'=>'mike doe']); //updating a user with id 20

User::delete(2); //deleting a user with age 20
User::delete(['age'=>20]); //deleting a user with age 20

User::all(['age'=>3]); //getting users with age 3
User::find()->get(); //getting all users

DB::table('blog_post')
  ->limit(3)
  ->select('title, post_body')
  ->get();

安装。

composer require ongom/dite-orm

设置。

要开始,在项目根目录创建一个.env文件,这是您将添加一些用于配置*dite-orm*的设置的地方。

sqlite的设置。

DRIVER = sqlite
DATABASE_NAME = schooldb
RUN_SCHEMA = 1
  • DRIVER 是您正在使用的数据库管理系统。值是sqlite。
  • DATABASE_NAME 是您正在使用的数据库的名称。值是您数据库的名称,例如 'school_database'。

mysql、sqlserver、postgre的设置。

首先创建数据库,例如 'schooldb',然后将以下代码添加到.env。

DRIVER = mysql
DATABASE_NAME = schooldb
SERVER_NAME = localhost
USER_NAME = root
DATABASE_PASSWORD = 1234
RUN_SCHEMA = 1
  • DRIVER 是您正在使用的数据库管理系统的类型。可能的值列表如下;

    • mysql
    • sqlsever
    • postgresql 或 pgsql
  • SERVER_NAME 是服务器名称或端口号,例如 'localhost' 或 3605。

  • USER_NAME 是用户名,例如 'root'。

  • DATABASE_PASSWORD 是数据库密码,例如 '23R42'。

可以添加到.env文件中的其他配置。

IS_DEVMODE = 1
FETCH_MODE = std_array
RUN_SCHEMA = 1
SQL_COLOR = green
  • IS_DEVMODE 用于调试目的。
    • 1表示您想在屏幕上打印查询和消息,这应仅用于开发。
    • 0或任何其他数字表示不在屏幕上打印查询或消息,它用于生产。
  • RUN_SCHEMA. 当您尝试使用模式创建表时,表不会创建,要解决这个问题,请将RUN_SCHEMA = 1添加到.env文件。创建表后,可以将值改为0(RUN_SCHEMA = 0)或完全删除,以避免再次运行创建表的查询。当添加任何新表时,您必须将其再次设置为1并重新运行代码。
  • FETCH_MODE 定义记录将从数据库中如何获取。
    • std_arrays表示记录将以PHP标准数组的形式获取,其值可以按以下方式访问。
$user = ["name"=>"tom", "age"=>36];
$user["name"]; //tom
$user["age"]; //36
  • std_obj 表示检索记录将以 stdClass 对象的形式返回,可以使用以下箭头语法进行访问。
$user = stdClass Object ([name] => tom [email] => tom@gmail.com)
$user->name; //tom
$user->age; //36
  • SQL_COLOR 定义了在屏幕上打印 SQL 关键字时的颜色。默认颜色为紫色。
  • NONSQL_COLOR 定义了在屏幕上打印 SQL 关键字时的颜色。默认颜色为浅色。
  • SQL_BG 定义了在开发模式下打印在屏幕上的 SQL 背景颜色。默认为黑色。
  • FULL_SQL 允许您查看将要执行的预编 SQL 以及其值。FULL_SQL = 0 开启或 FULL_SQL = 1 关闭。如果不添加,默认为写入完整 SQL。

注意: 所有颜色代码在 .env 文件中定义如下::fff,而不是 #fff(使用冒号而不是 #)

创建数据库连接的另一种方法 如果您不想将所有连接详细信息直接添加到 .env 文件中,请使用 dite 中的 Model 和 Schema 上的静态方法 setup()。此方法接受一个配置设置数组。

  Model::setup([
  'DRIVER' => 'sqlite',
  'DATABASE_NAME' => 'schooldb',
  'RUN_SCHEMA' => 1,
  'APP_PASSWORD' => 'rqae hrue bili alru',
  'LOGGER' => 1,
  'SQL_COLOR' => ':3f2',
  'NONSQL_COLOR' = ':f3fb',
  'SQL_BG' = 'red',
  'SEPARATOR' = 'white'
])

// And also
  Schema::setup([
  'DRIVER' => 'sqlite',
  'DATABASE_NAME' => 'schooldb',
  'RUN_SCHEMA' => 1,
  'APP_PASSWORD' => 'rqae hrue bili alru',
  'IS_DEVMODE' => 1,
  'SQL_COLOR' => ':3f2',
  'NONSQL_COLOR' = ':f3fb',
  'SQL_BG' = 'red',
  'SEPARATOR' = 'white'
])

创建表。

  • 使用 Dite Schema。
  • 使用现有数据库/使用其他软件(MySQL Workbench、Navicat、DB Browser 等)创建。

1. 使用现有数据库或其他软件创建数据库。

当使用类似 MySQL Workbench 或 PHPmyadmin 的其他软件时,您只需关注主键字段。主键字段名称来自小写形式的表名。例如

  • Users 的主键字段将是 users_id
  • BlogPost 的主键字段将是 blog_post_id
  • Blog_post 的主键字段将是 blog_post_id
  • Prices 的主键字段将是 Prices_id

注意: 名称中间的大写字母会在大写字母前面产生下划线。

创建到数据库的连接。

将数据库连接直接添加到 .env 或使用 setup 方法添加连接。然后定义模型类(代表每个表),如下所示。

use Dite\Model\Model;
require_once "path/to/vendor/autoload.php";

class DB extends Model{
  public function __constructor(){
    self::setup([
      'DRIVER' => 'sqlite',
      'DATABASE_NAME' => 'schooldb',
      'RUN_SCHEMA' => 1,
      'APP_PASSWORD' => 'rqae hrue bili alru',
      'LOGGER' => 1,
      'SQL_COLOR' => ':3f2',
    ]);
  }
}

//users
class Users extends DB{}
//posts
class Posts extends DB{}
// Status
class Status extends DB{}

2. 使用 Dite Schema 创建数据库。

在 require 语句下方添加以下代码。

use Dite\Schema\Schema;
use Dite\Model\Model;
use Dite\Table\Table;

require_once "path/to/vendor/autoload.php";
//users
class Users extends Model{

  public function __construct() {
    Schema::create(Users::class, function(Table $table){
      $table->id();
      $table->string('name');
      $table->enum('gender', ['male','female']);
      $table->string('email')->unique()->notnull();
      $table->int('age')->notnull();
      $table->timestamp();
    });
  }
}

上述代码定义了一个名为 users 的表,具有以下字段。

  • users_id - 整型,主键,自增且非空。
  • name - varchar(255)。
  • gender - 只接受 male 或 female 作为值的枚举。
  • email - 唯一且非空。
  • age - int 且非空。
  • created_at - 默认当前时间戳。
  • updated_at - 默认当前时间戳,当记录更新时更新。

您可以继续添加一个帖子表。以下是如何创建包含外键的三个表(users、posts、status)的完整代码。

//users
class Users extends Model{

  public function __construct() {
    Schema::create(Users::class, function(Table $table){
      $table->id();
      $table->string('name');
      $table->string('email')->unique()->notnull();
      $table->int('age')->notnull();
      $table->timestamp();
    });
  }
}

//posts
class BlogPosts extends Model{

  public function __construct() {
    Schema::create('BlogPosts', function(Table $table){
      $table->id();
      $table->string('title')->notnull();
      $table->string('body')->notnull();
      $table->foreignKey('users_id')->notnull();
      $table->foreignKey('status_id')->cascade();
      $table->timestamp();
    });
  }
}

// Status
class Status extends Model{

  public function __construct() {
    Schema::create(Status::class, function(Table $table){
      $table->id();
      $table->int('status')->notnull();
    });
  }
}

//Instantiating the three classes
$status = new Status()
$users = new Users()
$posts = new BlogPosts()

注意

  • 我们从 Status 类开始实例化类。这是因为状态表在 Posts 的外键字段中被引用,并且该表必须先于其引用创建。必须先创建被引用的表。被引用的表必须在上方。如果您更改顺序如下,您可能会在 MySQL 中遇到外键错误。
//Instantiating the three classes
$users = new Users()
$posts = new Posts()
$status = new Status()

运行代码,例如通过在浏览器中打开文件。这将创建数据库中的表。

  • 您也可以使用 Users::class 或 'Users' 作为名为 users 的表的表名,以及其他表。

表创建后,您可以打开 .env 并更改 RUN_SCHEMA = 0,否则表将尝试重新创建。

1. 创建一个中间表。

中间表有一个创建规则,以便让 Dite 能够理解。您需要连接两个表名。例如 teacherscourses 表,中间表将是 teachers_coursesTeachersCourses::class,而主键字段将是 teachers_courses_id。中间表必须按照以下方式创建。

//Teachers table
class Teachers extends Model{

public function __construct() {
    Schema::create(Teachers::class, function(Table $table){
      $table->id();
      $table->string('teacher_name');
      $table->string('email');
    });
  }
}
//Courses table
class Courses extends Model{

  public function __construct() {
    Schema::create(Courses::class, function(Table $table){
      $table->id();
      $table->string('course_name');
    });
  }
}
//Intermediate table
class TeachersCourses extends Model{

  public function __construct() {
    Schema::create(TeachersCourses::class, function(Table $table){
      $table->id();
      $table->foriegnKey('courses_id');
      $table->foriegnKey('teachers_id');
    });
    }
}

以下是对构建表所使用的每个方法的含义。

  • id() - 定义一个自增主键字段并设置为非空。您不能在id()上链式调用任何方法。
$table->id();
  • primaryKey() - 定义主键字段。
$table->primaryKey();
  • string() - SQL varchar 字段。它接受两个参数,一个必填字符串参数(字段名如comments),第二个可选整数参数默认为255(接受的字符的最大长度)。
    $table->string('name');
    //OR
    $table->string('name', 50);
  • text() - SQL text 字段。它接受两个参数,一个必填字符串参数(字段名如comments),第二个可选整数参数默认为65535(接受的字符的最大长度)。
    $table->text('name');
    //OR
    $table->text('name', 200);
  • longText() - SQL text 字段。它接受一个必填字符串参数(字段名如Posts)。
    $table->longText('name');
  • int() - SQL 整数字段。它接受一个必填字符串参数(字段名如comments)。
    $table->int('size');
  • bigint() - SQL 大整数字段。它接受一个必填字符串参数(字段名如comments)。
    $table->bigInt('size');
    //OR
    $table->bigInt('size', 6);
  • enum() - 它接受两个必填参数,一个字符串参数(字段名如size),第二个数组参数(只接受值)。
    $table->enum('size', ['small','medium', 'large']);
  • unsigned() - SQL 无符号数据类型字段。它接受字段名。
    $table->unsign('year');
  • boolean() - SQL 布尔数据类型字段(true 或 false)。它接受字段名。
    $table->boolean('is_active');
  • float() - SQL 浮点数据类型字段。它接受字段名。
    $table->float('distance');
  • double() - SQL 双精度数据类型字段。它接受字段名。
    $table->double('distances');
  • decimal() - SQL 小数数据类型字段。它接受字段名。这可能在其他驱动程序中不可用。
    $table->decimal('distance');
  • year() - SQL 年数据类型字段。它接受字段名。
    $table->year('Year_of_birth');
  • timestamp() - SQL 时间戳。它将创建 created_at 和 updated_at 列。
    $table->timestamp();
  • sql() - 这接受一个字符串参数,用于创建表的查询。您不能在该方法上链式调用任何内容。
    $table->sql("CREATE TABLE IF NOT EXISTS Users ( status_id INT AUTO_INCREMENT PRIMARY KEY NOT NULL , status INT NOT NULL , created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP )");
  • foreignKey() - SQL 外键字段。它接受被引用的字段名,由于 Spark 可以解析出来,因此不需要表名。
    $table->foreignKey('users_id');
字段约束
  • notnull() - SQL NOT NULL 约束。您不能在 id() 方法上执行此操作。

    $table->foreignKey('user_id')->notnull();
    $table->string('user_name')->notnull();
    $table->id('user_name')->notnull(); // dont do this!!
  • unique() - SQL UNIQUE 约束。

    $table->foreignKey('posts-id')->unique();
    $table->email('user_email')->unique()->notnull();
  • cascade() - 这仅在 foreign key 字段上链式调用,是可选的。它将 ON DELETE 和 ON UPDATE 约束设置为 CASCADE。

    $table->foreignKey('post_id')->cascades();
    $table->foreignKey('user_id')->unique()->notnull()->cascade();
  • cascade() - 这仅在 foreign key 字段上链式调用,是可选的。它将 ON DELETE 和 ON UPDATE 约束设置为 CASCADE。

    $table->foreignKey('post_id')->cascades();
    $table->foreignKey('user_id')->unique()->notnull()->cascade();
  • restrict() - 它将 ON DELETE 和 ON UPDATE 约束设置为 RESTRICT。

    $table->foreignKey('post_id')->restrict();
  • setnull() - 它将 ON DELETE 和 ON UPDATE 约束设置为 SET NULL。

    $table->foreignKey('post_id')->setnull();
  • noaction() - 它将 ON DELETE 和 ON UPDATE 约束设置为 NO ACTION。

      $table->foreignKey('post_id')->noaction();

    您也可以逐个设置此约束,如下所示

  • cascadeDelete() - 它将 ON DELETE 设置为 CASCADE。

    $table->foreignKey('post_id')->cascadeDelete();
  • cascadeUpdate() - 它将 ON UPDATE 设置为 CASCADE。

    $table->foreignKey('post_id')->cascadeUpdate();
  • restrictDelete() - 它将 ON DELETE 设置为 RESTRICT。

    $table->foreignKey('post_id')->restrictDelete();
  • restrictUpdate() - 它将 ON UPDATE 设置为 RESTRICT。

    $table->foreignKey('post_id')->restrictUpdate();
  • setnullDelete() - 它将 ON DELETE 设置为 SET NULL。

    $table->foreignKey('post_id')->setnullDelete();
  • setnullUpdate() - 它将 ON UPDATE 设置为 SET NULL。

    $table->foreignKey('post_id')->setnullUpdate();
  • noactionDelete() - 它将 ON DELETE 设置为 NO ACTION。

    $table->foreignKey('post_id')->noactionDelete();
  • noactionUpdate() - 它将 ON UPDATE 设置为 NO ACTION。

      $table->foreignKey('post_id')->noactionUpdate();

    以下是一个非常有效的链。

     $table->foreignKey('post_id')->noactionUpdate()->setnullDelete();

查询数据库。

本节将教会我们如何创建、读取、更新和删除记录。

创建新记录。

类 BlogPost 查询表格 blog_post,而 ComponyActiveEmployees 查询表格 companry_active_employees。

以下是如何向 users 表中创建新用户。

// creating single user
$user = User::create(["user_name"=>"tom", "age"=>32]);

//creates multiple users at once
$user = User::create([
  ["user_name"=>"tom", "age"=>32],
  ["user_name"=>"mike", "age"=>25],
  ["user_name"=>"loy", "age"=>27],
]);

不要传递主键字段、created_at 和 updated_at 字段,因为这些字段将自动更新。

只有当你创建单个记录时,create 方法才会返回创建的新记录。

更新记录。

静态方法 update() 用于更新记录,它接受两个参数,要更新的记录(id 或 where 子句)以及新的关联数组值。

//updating the user with id 1
$user = User::update(1, ["user_name"=>"tom", "age"=>32]);

//updating the user where age > 10
$user = User::update(["age"=>[":gt"=>10]], ["user_name"=>"john", "age"=>32]);

只有在你传递了 id 时,update 方法才会返回新的更新记录。

删除记录。

静态方法 delete() 将根据其 id 删除记录。

//deleting the user where user_id = 1
$user = User::delete(1);

//deleting the user where user_name = tom
$user = User::delete(["user_name"=>"tom"]);

//deleting the user where IN (1,2)
$user = User::delete([1,2]);

注意:

查询中的 where 子句部分作为参数传递给方法。

计算与查询匹配的记录数量。

使用静态方法 countRows() 来计算与查询匹配的记录数量。

//counting number the users all users
$user = User::countRows();

//updating the user where user_name = tom and age = 30
$user = User::countRows(["user_name"=>"tom", "age" => 30]);

从数据库中读取记录。

这可以通过许多方法完成,以下将详细讨论。所有用于读取记录且不带链式功能的静态方法至少需要两个可选参数:where 子句数组/整数和想要返回的字段。你想要返回的字段可以以逗号分隔的字符串形式传递,表示你想要返回的列,也可以以包含你想要返回的所有字段的数组形式传递。如下所示

//get all the records from the table user
$user = User::all(null, 'name, email');

//get all the records from the  user table where age >  30
$user = User::all(["age"=>[":gt"=>30]], ['name', 'email']);
  • all()。

这是一个静态方法,用于获取所有与查询匹配的记录。

//get all the records from the table user
$user = User::all();

////get all the records from the  user table where age >  30
$user = User::all(["age"=>[":gt"=>30]]);
  • first()。

    这是一个静态方法,用于获取与查询匹配的第一个记录。

//get all the records from the table user
$user = User::first();

//get the first records from the  user table where age >  30
$user = User::first(["age"=>[":gt"=>30]]);
  • last()。

    这是一个静态方法,用于获取与查询匹配的最后一个记录。

//get the last records from the table user
$user = User::last();

//get the last records from the  user table where age >  30
$user = User::last(["age"=>[":gt"=>30]]);
  • findById()。

    这是一个静态方法,用于通过其主键 id 获取记录。

//get the records from the table user where user_id = 2
$user = User::findById(2);

//get the records from the table user where user_id IN (1,2,3)
$user = User::findById([1,2,3]);
  • findOne()。

这是一个方法,用于获取与查询匹配的记录。

//get the one and first record from the table user where user_id > 10
$user = User::findOne(["user_id"=>[":gt"=>10]]);
  • exist()。

这是一个方法,用于检查记录是否存在。它返回 true 或 false。

//checks if any user record exist
$user = User::exist();

//checks if user with user_id 2 exists
$user = User::exist(2);

//checks if the users with user_id greater than 10 exist
$user = User::exist(["user_id"=>[":gt"=>10]]);

//checks if email tom@gmail.com exist in user table
$user = User::exist(["email"=>"tom@gmail.com"]);
  • sql()。

    这是一个从 Model 类继承的静态方法。它接受两个参数,一个 SQL 查询和要绑定到查询的值。这对于编写复杂的查询非常有用。

$user = User::sql("SELECT * FROM users");
$user = User::sql("SELECT * FROM users", []);
$user = User::sql("SELECT * FROM users WHERE user_name = ? And age > ?", ['tom', 30]);

join

有两种方式可以将两个表格连接起来。所有连接方法都接受两个参数,表格名称和可选的连接条件。如果未传递条件,Dite 将尝试设置以下自己的连接条件:“first_table.first_table_id = second_table.first_table_id”。

$user = User::joins(Post::class, "user.user_id = post.user_id");
  • joins() 和 innerJoins()。

这两个方法执行相同的功能,它们将两个表格进行内连接。

$user = User::joins(Post::class);
//OR
$user = User::joins("Post");
//select * from user join post on user.user_id = post.user_id

还有其他类型的连接方法。

  • leftJoins() 用于左连接。
  • rightJoins() 用于右连接。

到目前为止,我们只讨论了不带链式的静态方法,现在让我们看看其他可用的链式功能。

find().

用于从表中获取数组或其中一个记录。

$users = User::find()->get();
//select * from user

$users = User::find(5)->get();
//select * from user where user_id = 5

可以在 find() 方法上链接其他一些方法,如下所述。

orderBy()。

将结果按降序或升序排序。值可以是 asc 或 desc,分别表示升序和降序。

$users = User::find()->orderBy("user_id, name ASC, created_at DESC")->get();
//select * from user order by user_id asc name asc created_at DESC.
$user =  User::find()->orderBy(['user_id'=> 'asc'])->get();
//select * from user order by user_id desc.

$user =  User::find()->orderBy(['user_id'=> 'asc', 'name'=>'desc'])->get();
//select * from user order by user_id desc age asc.
groupBy()。

这将根据提供的字段对结果进行分组。groupBy() 接受一个字符串参数。

$user = User::find()->groupBy('name')->get();
//select * from user group by name.

$user =  User::find()->groupBy('group_id')->get();
//select * from user group by group_id.

$user =  User::find()->groupBy('username')->get();
//select * from user group by username where name = john doe.
select()。

这将仅选择指定的字段。参数可以是字符串或数组。

$users =  User::find()->select(['name', 'age'])->get();
//select name, age from user.
//OR
$users = User::find()->select('name AS staff_names, age')->get();
//select name, age from user.

$users = User::find()
        ->select(['name as names_of_staffs', 'age', "COUNT(name) * 2 as total"])
        ->get();
limit()。

用于指定要获取的记录数。默认为 12。

$users = User::find()->limit(5)->get();
//select * from user limit 5.
skip() 或 offset()。

这两个方法执行相同的功能。它们用于指定要跳过的记录数。默认为 0。

$users = User::find()->skip(10)->get();
//OR
$users = User::find()->offset(10)->get();

skip 和 limit 的组合可用于分页结果。

$users = Post::find()->skip(5)->limit(10)->get();
//select * from user limit 5,10

分页。

分页可以帮助从数据库中查询记录的一部分。它有两种方法:

  • page() - 接收您想要的页码。
  • perpage() - 接收每页的记录数。
$users = User::find()
        ->page(2)
        ->perpage(10)
        ->get();
  • page() 和 perpage() 方法将激活分页。

上述查询将返回类似以下内容

[
  'num_records' => 15; //total number of records
  'num_pages' => 2; //total number of pages
  'has_next' => false; //if it has next page or not
  'current_page' => 2; //the current page showing
  'has_prev' => true; //if it has previous page or not
  'next_page' => null; //what next page is, null for no next page
  'prev_page' => 1; //what next page is, null for no next page
  'per_page' => 10; //number of records per page
  'position' => 1; //position of the first record of a page in the entire result
  'data' = [...]; // records for each page
]

使用模型类查询数据。

如果您想使用模型类查询,请将表名传递给模型构造函数。

  class DB extends Model{}
  $Post = DB::table('Post')->get();
  // OR
  $Posts = Model::table('Post')->get();
  // 
  $users = DB::table('user')->select('name')->get()
  // find
  $users = Model::table('user')
          ->limit(10)
          ->offset(5)
          ->select('name')
          ->get();

  // paginating
  $users = Model::table('post')
          ->page(10)
          ->perpage(5)
          ->select('title')
          ->get();
// OR
$users = DB::table('post')
          ->page(10)
          ->perpage(5)
          ->select('title')
          ->get();

您可以连接任何有效的方法,如 select、join、group 等。

另外

$user = DB::table('user')::all();
$user = DB::table('user')::findById(4);

其他连接方法。

还有其他连接方法。

- withAll()

它接受三个参数;表名、可选的 where 子句和选择的字段。它检索用户及其所有帖子。适用于一对一和多对一关系。

$user = User::find()
        ->withAll(Post::class, ['status'=>'active'],'username, age')
        ->get();
// 
$user = User::find(5)
        ->withAll(Post::class, ['status'=>'active'],'username, age')
        ->get();

//You can chain it many time like
$user = Product::find(5)
        ->withAll(Order::class)
        ->withAll(Status::class)
        ->get();
- withOne()

它接受三个参数;表名、可选的 where 子句和选择的字段。它检索用户及其所有帖子。适用于一对一和多对一关系。

$user = User::find()
        ->withOne(Post::class, ['status'=>'active'],'title')
        ->get();
//returns users post where you can paginate, each having there post appended to 

$user = User::find(3)
        ->withOne(Post::class, ['status'=>'active'],'title')
        ->get();
//returns on post by its id together with one of his post

//you can chain it many time like
$user = Product::find(5)
        ->withOne(Order::class)
        ->withOne(Status::class)
        ->withOne(Owner::class)
        ->get();
attach()

它接受三个参数;表名、可选的 where 子句和选择的字段。它检索帖子或发帖人及其帖子。适用于一对一关系。

$user = Post::find()
        ->attach(User::class)
        ->get();
//returns posts together with the user wo posted it. 
$user = Post::find()
        ->attach(User::class)
        ->get();
//returns a post together with the user wo posted it. 


//you can chain it many time like
$user = User::find(5)
        ->attach(Department::class)
        ->withOne(City::class)
        ->get();
withMost()

它从第一个表中获取记录,其 id 在第二个表中出现的次数最多,在多对一关系中。它接受一个参数;表名。通过连接 limit() 限制结果数量。

$user = User::find()
        ->withMost(Post::class)
        ->limit(5)
        ->get();
//returns 5 users that has posted the most.
//  
$user = User::find()
        ->withMost(Post::class)
        ->withAll(Post::class)
        ->attach(City::class)
        ->limit(5)
        ->get();
withLeast()

它从第一个表中获取记录,其 id 在第二个表中出现的次数最少,在多对一关系中。它接受一个参数;表名。通过连接 limit() 限制结果数量。

$user = User::find()
        ->withLeast(Post::class)
        ->withAll(Post::class)
        ->attach(City::class)
        ->limit(5)
        ->get();
//returns 5 users that has least number of post. 
withOut()

它从第一个表中获取记录,其 id 在第二个表中没有出现,在多对一关系中。它接受一个参数;表名。通过连接 limit() 限制结果数量。您还可以限制、分页等。

$user = User::find()
        ->withOut(Post::class)
        ->get();
//returns users that has no post. 
withThrough()

它接受三个参数;表名。它将为具有 post 表中 user_id 的所有记录添加结果中的相应记录。这在多对多关系中发生。

$user = Teacher::find()
        ->withThrough(Course::class)
        ->get();
attachThrough()

它接受三个参数;表名。它将为教授特定课程的教师添加所有记录。这在多对多关系中发生。

$user = Course::find()
        ->attachThrough(Teacher::class)
        ->get();
//returns users that has no post. 

连接表。

join().

之前我们看到了连接,但我们只能使用静态方法连接两个表,现在让我们连接超过两个表。以下是可用的不同类型的连接:

  • join()
  • innerJoin()
  • leftJoin()
  • rightJoin()
  • letftOuterJoin()
  • rightOuterJoin()
  • leftOuterJoin()
  • rightJoin()
  • leftJoin()
$users = User::find()
        ->join('post')
        ->join('comments', 'user.user_id = comment.user_id')
        ->get();

在此连接中涉及三个表,用户、帖子评论。您可以使用上述任何类型的连接将 20 多个不同的表连接起来,并应用分页、选择、排序等,如下所示。

请记住,所有连接都接受一个可选参数,即连接条件。

$users = User::find()
        ->join('post')
        ->leftJoin('comments')
        ->page(1)
        ->perpage(10)
        ->orderBy('user.name'=>'desc')
        ->select(['user.name', 'post.title', 'count(*) As total'])
        ->where(["first_name" = "mike"])
        ->get();

Where 子句。

Where 子句在以下方法中作为参数传递。

  • ::all()
  • ::findOne()
  • ::findbyId()
  • ::first()
  • ::last()
  • ::delete()
  • ::deleteMany()
  • ::countRecords()
  • ::exist()
  • ::find()

您还可以在以下方法上连接 where() 方法

  • ::find()
  • ::table()

它可以以下方式传递。

1. 通过传递一个整数。

当您将整数传递给类似 findById()delete() 的方法时,该整数是您将获取的记录的主键。

$result = User::findById(2);
//OR
$post = Post::find(2)->get();

上述代码将返回一个主键为 2 的单个记录。

2. 通过传递关联数组。

当您将关联数组传递给类似 findOne()all() 的方法时,该数组将生成如下查询

   $result = User::all(["user_id"=>5]);
   //sql = SELECT * FROM user WHERE user_id = 5
   //OR
   $result = User::all(["user_id"=>5, "name"=>"tom"]);
   //sql = SELECT * FROM user WHERE user_id = 5 AND name = tom
   //OR
   $result = Posts::find()
            ->where(["user_id"=>5, "name"=>"tom"])
            ->get();
   //sql = SELECT * FROM user WHERE user_id = 5 AND name = tom
3. 通过传递嵌套关联数组。

有时您想应用一些运算符,如 <、>、<=、>=、=、like 等。这可以通过以下方式完成:

   $result = User::all(["user_id"=>['$lt'=>5]]);
   //sql = SELECT * FROM user WHERE user_id < 5
   //OR
   $result = User::all([
       "user_id"=>[':lt'=>5],
       "age"=>[':gt'=>30],
    ]);
   //OR
   $result = User::all([
       "email"=>"tom@gmail.com"
       "user_id"=>[':lt'=>5],
       "age"=>[':gt'=>30],
    ]);
   //sql = SELECT * FROM users WHERE email = tom@gmail.com AND user_id < 5 AND age > 30

您可以使用 '$' 代替 ':', 例如,这段代码的输出是相同的。

   $result = User::all(["user_id"=>['$lt'=>5]]);
   $result = User::all(["user_id"=>[':lt'=>5]]);
   //Both will output
   //sql = SELECT * FROM user WHERE user_id < 5
4. 传递一个关联数组,其中键为 $and 或 :and。

这将仅写入具有 AND 分隔的 WHERE 子句的查询。

   $result = User::all([
       ':and'=>[
           "user_id"=>['$lt'=>5],
           'age'=>[':gt'=>30],
           'phone'=>3 333 333 333
          ]
        ]);
   //sql = SELECT * FROM user WHERE user_id < 5 AND age >30 AND phone = 3 333 333 333
5. 传递一个关联数组,其中键为 $or 或 :or。

这将仅写入具有 OR 分隔的 WHERE 子句的查询。

  $result = User::all([
       ':or'=>[
          "user_id"=>['$lt'=>5],
          'age'=>[':gt'=>30],
          'phone'=>3 333 333 333
        ]
      ]);
   //sql = SELECT * FROM user WHERE user_id < 5 OR age > 30 OR phone = 3 333 333 333
   
   $result = User::all([
       ':or'=>[
            ['name'=>'tom', 'email'=>'tom@gmai.com'],
           "user_id"=>['$lt'=>5],
           'age'=>[':gt'=>30],
           'phone'=>3 333 333 333
          ]
        ]);
   /*
   sql = SELECT * FROM user 
    WHERE (name = tom AND email = tom@gmai.com) 
        OR user_id < 5 
        OR age > 30 
        OR phone = 3 333 333 333
   */
6. 传递一个关联数组,其中键为 $nand 或 :nand。

这将否定整个 :and。

   $result = User::all([
       ':nand'=>[
           "user_id"=>['$lt'=>5],
           'age'=>[':gt'=>30],
           'phone'=>3 333 333 333
           ]
        ]);
    /*
   sql = SELECT * FROM user 
    WHERE NOT (
    user_id < 5 
    AND age > 30 
    AND phone = 3 333 333 333)
   */
  
   $result = User::all([
       ':nand'=>[
          "name" => "tom",
          "user_id"=>['$lt'=>5],
        ]
      ]);
    /*
   sql = SELECT * FROM user 
    WHERE NOT (name = tom AND user_id < 5 )
   */
7. 传递一个关联数组,其中键为 $nor 或 :nor。

这将否定整个 :nor。

   $result = User::all([
       ':nor'=>[
           "user_id"=>['$lt'=>5],
           'age'=>[':gt'=>30],
           'phone'=>3 333 333 333
          ]
        ]);
    /*
   sql = SELECT * FROM user 
    WHERE NOT (
        OR user_id < 5 
        OR age > 30 
        OR phone = 3 333 333 333)
   */
  
   $result = User::all([
       ':nor'=>[
          "name" => "tom",
          "user_id"=>['$lt'=>5],
        ]
      ]);
    /*
   sql = SELECT * FROM user 
    WHERE NOT (name = tom OR user_id < 5 )
   */

同样,在操作符后仅放置 $ 或 : 也会否定查询的这一部分。

     $result = Users::all(["name" => "tom","user_id"=>['$nlt'=>5]]);
    /*
   sql = SELECT * FROM users
    WHERE name = tom AND NOT (user_id < 5 ))
   */
多次传递相同的列名。

如果同一键将出现多次,通常关联数组只会拾取最后写入的键。为了处理这种行为,您必须在数组键中的列名前附加一个前导下划线 (_),以下是一个示例。

$result = Users::all(["name" => "joyce","_name"=>"tom"])
// sql = SELECT * FROM users WHERE name = tom AND name = tom ))
$result = Users::all([':or'=>[
                    "name" => "tom",
                    "_name"=>"daniel", 
                    "__name"=>"loy"]]);
// sql = SELECT * FROM users WHERE name = tom OR name = deniel OR name = loy))

//Alternatively
$result = Users::find()
                ->where([':or'=>[
                    "name" => "tom",
                    "_name"=>"daniel", 
                    "__name"=>"loy"]])
                    ->get();
// sql = SELECT * FROM users WHERE name = tom OR name = deniel OR name = loy))

如果列名在同一关联数组中多次重复,您将需要附加多个下划线。

WHERE 子句中可用的运算符列表。

关系。

这将在一些表之间建立连接,例如,如果您有一个帖子,您可以轻松地获取其评论,或者如果您有一个用户,您可以获取他所有的帖子。您可以使用以下三种类型的关系:

  • 一对一关系。
  • 一对多关系。
  • 多对多关系。

1. 一对一关系。

一个用户有一张信用卡,而一张信用卡属于一个用户。为了在这里建立 一对一关系,您必须在 Users 类和 CreditCards 类定义中创建一个函数,如下所示。

 $card = User::find(4)
        ->hasOne(CreditCard::class)
        ->get();
// returns one creditcard or false

//and also
 $card = CreditCards::find(4)
        ->belongsToOne(User::class)
        ->get();
// returns one user or false

2. 一对多关系。

代码如下。

$card = User::find(4)
        ->hasMany(Post::class)
        ->get();
// returns array of post records

// and also
$Post = Post::find(4)
        ->belongsToOne(User::class)
        ->get();
// returns a user or false

3. 多对多关系。

这仅在您为两个表创建了一个中间表的情况下才有效。中间表必须按照 Dite 理解的约定创建。您必须连接两个表名。例如 teacherscourses 表,中间表将是 teachers_courses,主键字段将是 teachers_courses_id。中间表必须创建如下。

//Teachers table
class Teachers extends Model{

  public function __construct() {
    Schema::create(Teachers::class, function(Table $table){
      $table->id();
      $table->string('teacher_name');
      $table->string('email');
    });
  }
}
//Courses table
class Courses extends Model{

public function __construct() {
    Schema::create(Courses::class, function(Table $table){
      $table->id();
      $table->string('course_name');
    });
  }
}

//Intermediate table
class TeachersCourses extends Model{

  public function __construct() {
    Schema::create(TeachersCourses::class, function(Table $table){
      $table->id();
      $table->foriegnKey('courses_id');
      $table->foriegnKey('teachers_id');
    });
  }
}

每次创建一个教师或一个课程时,请记得更新中间表。

让我们定义关系。

 $card = Teacher::find(4)
        ->hasManyMany(Courses::class)
        ->get();
// returns one user or false

注意 在任何关系上,您可以链式调用任何有效方法,但不能是 ->find() 方法。

$post = Users::find(2)
        ->hasMany(Post::class)
        ->select('post_id,title, post')
        ->orderBy('age')
        ->where(['title'=>['$like'=>'%computer']])
        ->limit(10)
        ->get();

删除数据库表

这可以通过以下方式使用静态方法 drop() 完成。它返回一个布尔值,成功删除返回 true,删除失败返回 false。

Users::drop();

感谢 Dite