Xóa nhiều hàng php

Trong khi thực hiện xóa nhiều hàng, chúng ta cần làm theo một số bước. Tất cả các bước được liệt kê bên dưới đều phù hợp để xóa nhiều hàng

Trước tiên, chúng ta hãy bắt đầu mã hóa để xóa nhiều hàng

Bằng cách chọn hộp kiểm chọn tất cả, bạn sẽ chọn tất cả các hàng và chúng có thể bị xóa một lần

Đối với mọi cột khách hàng, chúng tôi thực sự muốn thêm đầu vào hộp kiểm trong khi nhấn mạnh qua một vòng lặp với kết quả truy vấn. Vì vậy, chúng ta nên tạo một cột khác với chế độ xem danh sách của người dùng để nhập vào hộp kiểm

Vì vậy, trong khi in các đoạn bảng khách hàng mạnh mẽ sang chế độ xem tóm tắt, vòng tròn phải chứa những thứ đi kèm

								
									
								
							

mục lục. php

Xóa nhiều hàng bằng PHP

Xóa cực kỳ đơn giản so với cập nhật. Vì chúng tôi thực sự không muốn hiển thị bất kỳ giao diện người dùng nào và nó chỉ yêu cầu số lượng id cột đã chọn

Ngoài ra, để xóa nhiều dòng, chúng tôi đang gửi các dòng đã chọn bằng cách sử dụng Javascript. Như được hiển thị trong nội dung đi kèm, chúng tôi có thể sử dụng công việc khẳng định () của Javascript để nhận được xác nhận trước khi xóa

Active Record cung cấp giao diện hướng đối tượng để truy cập và thao tác dữ liệu được lưu trữ trong cơ sở dữ liệu. Một lớp Bản ghi Hoạt động được liên kết với một bảng cơ sở dữ liệu, một thực thể Bản ghi Hoạt động tương ứng với một hàng của bảng đó và một thuộc tính của một thực thể Bản ghi Hoạt động biểu thị giá trị của một cột cụ thể trong hàng đó. Thay vì viết các câu lệnh SQL thô, bạn sẽ truy cập các thuộc tính Bản ghi Hoạt động và gọi các phương thức Bản ghi Hoạt động để truy cập và thao tác dữ liệu được lưu trữ trong các bảng cơ sở dữ liệu

Ví dụ: giả sử

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 là một lớp Bản ghi Hoạt động được liên kết với bảng
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
1 và
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
2 là một cột của bảng
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
1. Bạn có thể viết đoạn mã sau để chèn một hàng mới vào bảng
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
1

$customer = new Customer();
$customer->name = 'Qiang';
$customer->save();

Đoạn mã trên tương đương với việc sử dụng câu lệnh SQL thô sau đây cho MySQL, ít trực quan hơn, dễ bị lỗi hơn và thậm chí có thể gặp sự cố tương thích nếu bạn đang sử dụng một loại cơ sở dữ liệu khác

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();

Yii cung cấp hỗ trợ Active Record cho các cơ sở dữ liệu quan hệ sau

Ngoài ra, Yii cũng hỗ trợ sử dụng Active Record với các cơ sở dữ liệu NoSQL sau

  • làm lại 2. 6. 12 hoặc muộn hơn. thông qua yii\redis\ActiveRecord, yêu cầu tiện ích mở rộng
    return [
        'components' => [
            'db' => [
                'class' => 'yii\db\Connection',
                'dsn' => 'mysql:host=localhost;dbname=testdb',
                'username' => 'demo',
                'password' => 'demo',
            ],
        ],
    ];
    
    5
  • MongoDB 1. 3. 0 trở lên. thông qua yii\mongodb\ActiveRecord, yêu cầu tiện ích mở rộng
    return [
        'components' => [
            'db' => [
                'class' => 'yii\db\Connection',
                'dsn' => 'mysql:host=localhost;dbname=testdb',
                'username' => 'demo',
                'password' => 'demo',
            ],
        ],
    ];
    
    6

Trong hướng dẫn này, chúng tôi sẽ mô tả chủ yếu cách sử dụng Active Record cho cơ sở dữ liệu quan hệ. Tuy nhiên, hầu hết nội dung được mô tả ở đây cũng có thể áp dụng cho Bản ghi hoạt động cho cơ sở dữ liệu NoSQL

Khai báo các lớp bản ghi hoạt động

Để bắt đầu, hãy khai báo một lớp Bản ghi Hoạt động bằng cách mở rộng yii\db\ActiveRecord

Đặt tên bảng

Theo mặc định, mỗi lớp Bản ghi Hoạt động được liên kết với bảng cơ sở dữ liệu của nó. Phương thức trả về tên bảng bằng cách chuyển đổi tên lớp thông qua. Bạn có thể ghi đè phương thức này nếu bảng không được đặt tên theo quy ước này

Cũng có thể áp dụng mặc định. Ví dụ: nếu là

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
7, thì
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 trở thành
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
9 và
public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
0 trở thành
public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
1

Nếu tên bảng được đặt là

public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
2, thì ký tự phần trăm
public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
3 sẽ được thay thế bằng tiền tố bảng. Ví dụ,
public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
4 trở thành
public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
5. Các dấu ngoặc xung quanh tên bảng được sử dụng cho

Trong ví dụ sau, chúng tôi khai báo một lớp Bản ghi Hoạt động có tên là

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 cho bảng cơ sở dữ liệu
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
1

Hồ sơ hoạt động được gọi là "mô hình"

Các phiên bản Bản ghi Hoạt động được coi là mô hình. Vì lý do này, chúng tôi thường đặt các lớp Bản ghi Hoạt động dưới không gian tên

public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
8 (hoặc các không gian tên khác để giữ các lớp mô hình)

Bởi vì yii\db\ActiveRecord mở rộng từ yii\base\Model nên nó kế thừa tất cả các tính năng của mô hình, chẳng hạn như thuộc tính, quy tắc xác thực, tuần tự hóa dữ liệu, v.v.

Kết nối với cơ sở dữ liệu

Theo mặc định, Active Record sử dụng thành phần ứng dụng

public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
9 làm kết nối DB để truy cập và thao tác dữ liệu cơ sở dữ liệu. Như đã giải thích trong Đối tượng truy cập cơ sở dữ liệu, bạn có thể định cấu hình thành phần
public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
9 trong cấu hình ứng dụng như bên dưới,

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];

Nếu bạn muốn sử dụng một kết nối cơ sở dữ liệu khác ngoài thành phần

public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}
9, bạn nên ghi đè phương thức

Truy vấn dữ liệu

Sau khi khai báo một lớp Active Record, bạn có thể sử dụng nó để truy vấn dữ liệu từ bảng cơ sở dữ liệu tương ứng. Quá trình này thường có ba bước sau

Như bạn có thể thấy, điều này rất giống với quy trình với trình tạo truy vấn. Điểm khác biệt duy nhất là thay vì sử dụng toán tử

$values = [
    'name' => 'James',
    'email' => '[email protected]',
];

$customer = new Customer();

$customer->attributes = $values;
$customer->save();
2 để tạo một đối tượng truy vấn, bạn gọi để trả về một đối tượng truy vấn mới thuộc lớp yii\db\ActiveQuery

Dưới đây là một số ví dụ cho thấy cách sử dụng Active Query để truy vấn dữ liệu

Ở trên,

$values = [
    'name' => 'James',
    'email' => '[email protected]',
];

$customer = new Customer();

$customer->attributes = $values;
$customer->save();
3 là một đối tượng
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 trong khi
$values = [
    'name' => 'James',
    'email' => '[email protected]',
];

$customer = new Customer();

$customer->attributes = $values;
$customer->save();
5 là một mảng của
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 đối tượng. Tất cả chúng đều được điền bằng dữ liệu được lấy từ bảng
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
1

Thông tin. Vì yii\db\ActiveQuery mở rộng từ yii\db\Query nên bạn có thể sử dụng tất cả các phương thức xây dựng truy vấn và phương thức truy vấn như được mô tả trong Trình tạo truy vấn theo mục

Bởi vì nhiệm vụ phổ biến là truy vấn theo các giá trị khóa chính hoặc một tập hợp các giá trị cột, Yii cung cấp hai phương thức phím tắt cho mục đích này

Cả hai phương thức có thể lấy một trong các định dạng tham số sau

  • một giá trị vô hướng. giá trị được coi là giá trị khóa chính mong muốn được tìm kiếm. Yii sẽ tự động xác định cột nào là cột khóa chính bằng cách đọc thông tin lược đồ cơ sở dữ liệu
  • một mảng các giá trị vô hướng. mảng được coi là các giá trị khóa chính mong muốn được tìm kiếm
  • một mảng kết hợp. các khóa là tên cột và các giá trị là các giá trị cột mong muốn tương ứng sẽ được tìm kiếm. Vui lòng tham khảo để biết thêm chi tiết

Đoạn mã sau cho thấy cách sử dụng các phương thức này

Cảnh báo. Nếu bạn cần chuyển đầu vào của người dùng cho các phương thức này, hãy đảm bảo giá trị đầu vào là vô hướng hoặc trong trường hợp điều kiện mảng, hãy đảm bảo cấu trúc mảng không thể thay đổi từ bên ngoài

Ghi chú. Sẽ không thêm

$values = [
    'name' => 'James',
    'email' => '[email protected]',
];

$customer = new Customer();

$customer->attributes = $values;
$customer->save();
8 vào câu lệnh SQL được tạo. Nếu truy vấn của bạn có thể trả về nhiều hàng dữ liệu, bạn nên gọi rõ ràng
$values = [
    'name' => 'James',
    'email' => '[email protected]',
];

$customer = new Customer();

$customer->attributes = $values;
$customer->save();
9 để cải thiện hiệu suất, e. g. ,
$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])])
0

Bên cạnh việc sử dụng các phương pháp xây dựng truy vấn, bạn cũng có thể viết SQL thô để truy vấn dữ liệu và điền kết quả vào các đối tượng Bản ghi Hoạt động. Bạn có thể làm như vậy bằng cách gọi phương thức

Không gọi các phương thức xây dựng truy vấn bổ sung sau khi gọi vì chúng sẽ bị bỏ qua

Truy cập dữ liệu

Như đã đề cập ở trên, dữ liệu được mang về từ cơ sở dữ liệu được đưa vào các phiên bản Bản ghi Hoạt động và mỗi hàng của kết quả truy vấn tương ứng với một phiên bản Bản ghi Hoạt động. Bạn có thể truy cập các giá trị cột bằng cách truy cập các thuộc tính của các phiên bản Bản ghi Hoạt động, ví dụ:

Ghi chú. Các thuộc tính Bản ghi Hoạt động được đặt tên theo các cột trong bảng được liên kết theo cách phân biệt chữ hoa chữ thường. Yii tự động xác định một thuộc tính trong Bản ghi hoạt động cho mọi cột của bảng được liên kết. Bạn KHÔNG nên khai báo lại bất kỳ thuộc tính nào

Vì các thuộc tính Bản ghi Hoạt động được đặt tên theo các cột trong bảng, nên bạn có thể thấy mình đang viết mã PHP như

$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])])
1, sử dụng dấu gạch dưới để phân tách các từ trong tên thuộc tính nếu các cột trong bảng của bạn được đặt tên theo cách này. Nếu bạn lo lắng về tính nhất quán của kiểu mã, bạn nên đổi tên các cột trong bảng của mình cho phù hợp (ví dụ: để sử dụng camelCase)

Chuyển đổi dữ liệu

Thường xảy ra trường hợp dữ liệu được nhập và/hoặc hiển thị ở định dạng khác với định dạng được sử dụng để lưu trữ dữ liệu trong cơ sở dữ liệu. Ví dụ: trong cơ sở dữ liệu, bạn đang lưu trữ ngày sinh nhật của khách hàng dưới dạng dấu thời gian UNIX (mặc dù đây không phải là một thiết kế tốt), trong khi trong hầu hết các trường hợp, bạn muốn thao tác ngày sinh nhật dưới dạng chuỗi ở định dạng

$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])])
2. Để đạt được mục tiêu này, bạn có thể định nghĩa các phương thức chuyển đổi dữ liệu trong lớp Bản ghi Hoạt động
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 như sau

Bây giờ trong mã PHP của bạn, thay vì truy cập vào

$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])])
4, bạn sẽ truy cập vào
$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])])
5, điều này sẽ cho phép bạn nhập và hiển thị ngày sinh của khách hàng ở định dạng
$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])])
2

Mẹo. Ví dụ trên cho thấy một cách chung để chuyển đổi dữ liệu ở các định dạng khác nhau. Nếu bạn đang làm việc với các giá trị ngày tháng, bạn có thể sử dụng và yii\jui\DatePicker, cách này dễ sử dụng hơn và hiệu quả hơn

Truy xuất dữ liệu trong mảng

Mặc dù việc truy xuất dữ liệu dưới dạng các đối tượng Bản ghi Hoạt động rất thuận tiện và linh hoạt, nhưng không phải lúc nào bạn cũng mong muốn khi bạn phải mang về một lượng lớn dữ liệu do dung lượng bộ nhớ lớn. Trong trường hợp này, bạn có thể truy xuất dữ liệu bằng mảng PHP bằng cách gọi trước khi thực hiện phương thức truy vấn

Ghi chú. Mặc dù phương pháp này tiết kiệm bộ nhớ và cải thiện hiệu suất, nhưng nó gần với lớp trừu tượng DB thấp hơn và bạn sẽ mất hầu hết các tính năng của Bản ghi Hoạt động. Một điểm khác biệt rất quan trọng nằm ở kiểu dữ liệu của các giá trị cột. Khi bạn trả về dữ liệu trong các phiên bản Bản ghi Hoạt động, các giá trị cột sẽ được tự động nhập liệu theo các loại cột thực tế;

Truy xuất dữ liệu theo lô

Trong Trình tạo truy vấn, chúng tôi đã giải thích rằng bạn có thể sử dụng truy vấn hàng loạt để giảm thiểu việc sử dụng bộ nhớ khi truy vấn một lượng lớn dữ liệu từ cơ sở dữ liệu. Bạn có thể sử dụng kỹ thuật tương tự trong Active Record. Ví dụ,

Lưu dữ liệu

Sử dụng Active Record, bạn có thể dễ dàng lưu dữ liệu vào cơ sở dữ liệu bằng cách thực hiện các bước sau

  1. Chuẩn bị một phiên bản Bản ghi Hoạt động
  2. Gán các giá trị mới cho các thuộc tính Bản ghi Hoạt động
  3. Gọi để lưu dữ liệu vào cơ sở dữ liệu

Ví dụ,

Phương thức này có thể chèn hoặc cập nhật một hàng dữ liệu, tùy thuộc vào trạng thái của phiên bản Bản ghi Hoạt động. Nếu phiên bản được tạo mới thông qua toán tử

$values = [
    'name' => 'James',
    'email' => '[email protected]',
];

$customer = new Customer();

$customer->attributes = $values;
$customer->save();
2, việc gọi sẽ dẫn đến việc chèn một hàng mới;

Bạn có thể phân biệt hai trạng thái của một phiên bản Bản ghi Hoạt động bằng cách kiểm tra giá trị thuộc tính của nó. Tài sản này cũng được sử dụng bởi nội bộ như sau

public function save($runValidation = true, $attributeNames = null)
{
    if ($this->getIsNewRecord()) {
        return $this->insert($runValidation, $attributeNames);
    } else {
        return $this->update($runValidation, $attributeNames) !== false;
    }
}

Mẹo. Bạn có thể gọi hoặc trực tiếp để chèn hoặc cập nhật một hàng

Xác nhận dữ liệu

Vì yii\db\ActiveRecord mở rộng từ yii\base\Model nên nó có chung tính năng xác thực dữ liệu. Bạn có thể khai báo các quy tắc xác thực bằng cách ghi đè phương thức và thực hiện xác thực dữ liệu bằng cách gọi phương thức

Khi bạn gọi thì mặc định nó sẽ tự động gọi. Chỉ khi vượt qua xác thực, nó mới thực sự lưu dữ liệu;

Mẹo. Nếu bạn chắc chắn rằng dữ liệu của mình không cần xác thực (e. g. , dữ liệu đến từ các nguồn đáng tin cậy), bạn có thể gọi

$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])])
9 để bỏ qua xác thực

nhiệm vụ lớn

Giống như các mô hình thông thường, các phiên bản Bản ghi Hoạt động cũng được hưởng. Sử dụng tính năng này, bạn có thể gán giá trị cho nhiều thuộc tính của một phiên bản Bản ghi Hoạt động trong một câu lệnh PHP, như minh họa bên dưới. Tuy nhiên, hãy nhớ rằng chỉ có thể được chỉ định ồ ạt

$values = [
    'name' => 'James',
    'email' => '[email protected]',
];

$customer = new Customer();

$customer->attributes = $values;
$customer->save();

Cập nhật bộ đếm

Nhiệm vụ phổ biến là tăng hoặc giảm một cột trong bảng cơ sở dữ liệu. Chúng tôi gọi những cột này là "cột truy cập". Bạn có thể sử dụng để cập nhật một hoặc nhiều cột bộ đếm. Ví dụ,

Ghi chú. Nếu bạn sử dụng để cập nhật một cột bộ đếm, bạn có thể nhận được kết quả không chính xác, vì có khả năng cùng một bộ đếm đang được lưu bởi nhiều yêu cầu đọc và ghi cùng một giá trị bộ đếm

Thuộc tính bẩn

Khi bạn gọi để lưu một phiên bản Bản ghi Hoạt động, chỉ các thuộc tính bẩn mới được lưu. Một thuộc tính được coi là bẩn nếu giá trị của nó đã bị sửa đổi kể từ khi nó được tải từ DB hoặc được lưu vào DB gần đây nhất. Lưu ý rằng việc xác thực dữ liệu sẽ được thực hiện bất kể phiên bản Bản ghi Hoạt động có thuộc tính bẩn hay không

Active Record tự động duy trì danh sách các thuộc tính bẩn. Nó làm như vậy bằng cách duy trì phiên bản cũ hơn của các giá trị thuộc tính và so sánh chúng với phiên bản mới nhất. Bạn có thể gọi để lấy các thuộc tính hiện đang bẩn. Bạn cũng có thể gọi để đánh dấu rõ ràng một thuộc tính là bẩn

Nếu bạn quan tâm đến các giá trị thuộc tính trước lần sửa đổi gần đây nhất của chúng, bạn có thể gọi hoặc

Ghi chú. Việc so sánh các giá trị cũ và mới sẽ được thực hiện bằng cách sử dụng toán tử

$customer = Customer::findOne(123);
$customer->delete();
0 vì vậy một giá trị sẽ bị coi là bẩn ngay cả khi nó có cùng giá trị nhưng khác loại. Đây thường là trường hợp khi mô hình nhận đầu vào của người dùng từ các biểu mẫu HTML trong đó mọi giá trị được biểu thị dưới dạng chuỗi. Để đảm bảo đúng loại cho e. g. giá trị số nguyên bạn có thể áp dụng một.
$customer = Customer::findOne(123);
$customer->delete();
1. Điều này hoạt động với tất cả các chức năng đánh máy của PHP như intval(), floatval(), boolval, v.v.

Giá trị thuộc tính mặc định

Một số cột trong bảng của bạn có thể có các giá trị mặc định được xác định trong cơ sở dữ liệu. Đôi khi, bạn có thể muốn điền trước biểu mẫu Web của mình cho một phiên bản Bản ghi Hoạt động với các giá trị mặc định này. Để tránh ghi lại các giá trị mặc định giống nhau, bạn có thể gọi để điền các giá trị mặc định do DB xác định vào các thuộc tính Bản ghi Hoạt động tương ứng

Thuộc tính Typecasting

Được điền bởi các kết quả truy vấn, yii\db\ActiveRecord thực hiện việc đánh máy tự động cho các giá trị thuộc tính của nó, sử dụng thông tin từ. Điều này cho phép dữ liệu được lấy từ cột bảng được khai báo là số nguyên được điền trong phiên bản ActiveRecord với số nguyên PHP, boolean với boolean, v.v. Tuy nhiên, cơ chế typecasting có một số hạn chế

  • Các giá trị float không được chuyển đổi và sẽ được biểu diễn dưới dạng chuỗi, nếu không chúng có thể mất độ chính xác
  • Việc chuyển đổi các giá trị số nguyên phụ thuộc vào dung lượng số nguyên của hệ điều hành bạn sử dụng. Đặc biệt. các giá trị của cột được khai báo là 'số nguyên không dấu' hoặc 'số nguyên lớn' sẽ chỉ được chuyển đổi thành số nguyên PHP ở hệ điều hành 64 bit, trong khi trên các hệ điều hành 32 bit - chúng sẽ được biểu diễn dưới dạng chuỗi

Lưu ý rằng kiểu truyền thuộc tính chỉ được thực hiện trong khi điền phiên bản ActiveRecord từ kết quả truy vấn. Không có chuyển đổi tự động cho các giá trị được tải từ yêu cầu HTTP hoặc được đặt trực tiếp qua quyền truy cập thuộc tính. Lược đồ bảng cũng sẽ được sử dụng trong khi chuẩn bị các câu lệnh SQL để lưu dữ liệu ActiveRecord, đảm bảo các giá trị được liên kết với truy vấn đúng loại. Tuy nhiên, các giá trị thuộc tính của phiên bản ActiveRecord sẽ không được chuyển đổi trong quá trình lưu

Mẹo. bạn có thể sử dụng yii\behaviors\AttributeTypecastBehavior để tạo điều kiện thuận lợi cho việc đánh máy các giá trị thuộc tính khi xác thực hoặc lưu ActiveRecord

kể từ 2. 0. 14, Yii ActiveRecord hỗ trợ các kiểu dữ liệu phức tạp, chẳng hạn như JSON hoặc mảng đa chiều

JSON trong MySQL và PostgreSQL

Sau khi điền dữ liệu, giá trị từ cột JSON sẽ được tự động giải mã từ JSON theo quy tắc giải mã JSON chuẩn

Để lưu giá trị thuộc tính vào cột JSON, ActiveRecord sẽ tự động tạo đối tượng JsonExpression sẽ được mã hóa thành chuỗi JSON ở cấp độ QueryBuilder

Mảng trong PostgreSQL

Sau khi điền dữ liệu, giá trị từ cột Array sẽ được tự động giải mã từ ký hiệu PGSQL sang đối tượng ArrayExpression. Nó triển khai giao diện PHP

$customer = Customer::findOne(123);
$customer->delete();
2, vì vậy bạn có thể sử dụng nó như một mảng hoặc gọi
$customer = Customer::findOne(123);
$customer->delete();
3 để lấy chính mảng đó

Để lưu giá trị thuộc tính vào một cột mảng, ActiveRecord sẽ tự động tạo một đối tượng ArrayExpression sẽ được QueryBuilder mã hóa thành một biểu diễn chuỗi PgSQL của mảng

Bạn cũng có thể sử dụng các điều kiện cho các cột JSON

$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])])

Để tìm hiểu thêm về hệ thống xây dựng biểu thức, hãy đọc bài viết

Cập nhật nhiều hàng

Tất cả các phương pháp được mô tả ở trên đều hoạt động trên các phiên bản Bản ghi Hoạt động riêng lẻ, gây ra việc chèn hoặc cập nhật các hàng trong bảng riêng lẻ. Để cập nhật nhiều hàng đồng thời, thay vào đó, bạn nên gọi phương thức tĩnh

Tương tự, bạn có thể gọi cập nhật cột bộ đếm của nhiều hàng cùng lúc

Xóa dữ liệu

Để xóa một hàng dữ liệu, trước tiên hãy truy xuất phiên bản Bản ghi Hoạt động tương ứng với hàng đó và sau đó gọi phương thức

$customer = Customer::findOne(123);
$customer->delete();

Bạn có thể gọi để xóa nhiều hoặc tất cả các hàng dữ liệu. Ví dụ,

Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);

Ghi chú. Hãy thật cẩn thận khi gọi vì nó có thể xóa hoàn toàn tất cả dữ liệu khỏi bảng của bạn nếu bạn mắc lỗi khi chỉ định điều kiện

Vòng đời bản ghi hoạt động

Điều quan trọng là phải hiểu vòng đời của Active Record khi nó được sử dụng cho các mục đích khác nhau. Trong mỗi vòng đời, một chuỗi các phương thức nhất định sẽ được gọi và bạn có thể ghi đè các phương thức này để có cơ hội tùy chỉnh vòng đời. Bạn cũng có thể phản hồi một số sự kiện Bản ghi đang hoạt động được kích hoạt trong vòng đời để thêm mã tùy chỉnh của mình. Những sự kiện này đặc biệt hữu ích khi bạn đang phát triển các hành vi của Bản ghi Hoạt động cần tùy chỉnh vòng đời của Bản ghi Hoạt động

Trong phần sau đây, chúng tôi sẽ tóm tắt các vòng đời Bản ghi Hoạt động khác nhau và các phương thức/sự kiện liên quan đến vòng đời.

Vòng đời của phiên bản mới

Khi tạo một phiên bản Bản ghi Hoạt động mới thông qua toán tử

$values = [
    'name' => 'James',
    'email' => '[email protected]',
];

$customer = new Customer();

$customer->attributes = $values;
$customer->save();
2, vòng đời sau sẽ xảy ra

Truy vấn vòng đời dữ liệu

Khi truy vấn dữ liệu thông qua một trong các , mỗi Bản ghi hoạt động mới được điền sẽ trải qua vòng đời sau

Lưu vòng đời dữ liệu

Khi gọi để chèn hoặc cập nhật một phiên bản Bản ghi Hoạt động, vòng đời sau sẽ xảy ra

Xóa vòng đời dữ liệu

Khi gọi để xóa một Active Record instance, vòng đời sau sẽ xảy ra

Ghi chú. Việc gọi bất kỳ phương thức nào sau đây sẽ KHÔNG bắt đầu bất kỳ vòng đời nào ở trên vì chúng hoạt động trực tiếp trên cơ sở dữ liệu chứ không phải trên cơ sở bản ghi

Làm mới vòng đời dữ liệu

Khi gọi để làm mới một phiên bản Bản ghi Hoạt động, sự kiện sẽ được kích hoạt nếu quá trình làm mới thành công và phương thức trả về

$customer = Customer::findOne(123);
$customer->delete();
5

Làm việc với các giao dịch

Có hai cách sử dụng khi làm việc với Active Record

Cách đầu tiên là đính kèm rõ ràng các lệnh gọi phương thức Active Record trong một khối giao dịch, như được hiển thị bên dưới,

Ghi chú. trong đoạn mã trên, chúng tôi có hai khối bắt để tương thích với PHP 5. x và PHP7. x.

$customer = Customer::findOne(123);
$customer->delete();
6 triển khai giao diện
$customer = Customer::findOne(123);
$customer->delete();
7 kể từ PHP 7. 0, vì vậy bạn có thể bỏ qua phần với
$customer = Customer::findOne(123);
$customer->delete();
6 nếu ứng dụng của bạn chỉ sử dụng PHP 7. 0 và cao hơn

Cách thứ hai là liệt kê các hoạt động DB yêu cầu hỗ trợ giao dịch trong phương thức. Ví dụ,

Phương thức sẽ trả về một mảng có khóa là tên và giá trị là các hoạt động tương ứng sẽ được đặt trong các giao dịch. Bạn nên sử dụng các hằng số sau để tham khảo các hoạt động DB khác nhau

Sử dụng các toán tử

$customer = Customer::findOne(123);
$customer->delete();
9 để nối các hằng số trên để biểu thị nhiều phép toán. Bạn cũng có thể sử dụng hằng phím tắt để chỉ cả ba thao tác trên

Các giao dịch được tạo bằng phương pháp này sẽ được bắt đầu trước khi gọi và sẽ được cam kết sau khi chạy

Khóa lạc quan

Khóa lạc quan là một cách để ngăn xung đột có thể xảy ra khi một hàng dữ liệu đang được cập nhật bởi nhiều người dùng. Ví dụ: cả người dùng A và người dùng B đều đang chỉnh sửa cùng một bài viết trên wiki cùng một lúc. Sau khi người dùng A lưu các chỉnh sửa của mình, người dùng B nhấp vào nút "Lưu" để lưu các chỉnh sửa của anh ấy. Bởi vì người dùng B thực sự đang làm việc trên một phiên bản lỗi thời của bài viết, nên có cách ngăn anh ta lưu bài viết và hiển thị cho anh ta một số thông báo gợi ý.

Khóa lạc quan giải quyết vấn đề trên bằng cách sử dụng một cột để ghi lại số phiên bản của mỗi hàng. Khi một hàng đang được lưu với số phiên bản đã lỗi thời, một ngoại lệ yii\db\StaleObjectException sẽ được đưa ra, khiến hàng đó không được lưu. Khóa lạc quan chỉ được hỗ trợ khi bạn cập nhật hoặc xóa một hàng dữ liệu hiện có bằng cách sử dụng hoặc , tương ứng

Để sử dụng khóa lạc quan,

  1. Tạo một cột trong bảng DB được liên kết với lớp Bản ghi Hoạt động để lưu trữ số phiên bản của mỗi hàng. Cột phải thuộc loại số nguyên lớn (trong MySQL nó sẽ là
    Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
    
    0)
  2. Ghi đè phương thức để trả về tên của cột này
  3. Triển khai OptimisticLockBehavior bên trong lớp mô hình của bạn để tự động phân tích giá trị của nó từ các yêu cầu nhận được. Xóa thuộc tính phiên bản khỏi quy tắc xác thực vì OptimisticLockBehavior sẽ xử lý nó
  4. Trong biểu mẫu Web nhận đầu vào của người dùng, hãy thêm một trường ẩn để lưu trữ số phiên bản hiện tại của hàng đang được cập nhật
  5. Trong hành động của bộ điều khiển cập nhật hàng bằng Bản ghi Hoạt động, hãy thử và nắm bắt ngoại lệ yii\db\StaleObjectException. Thực hiện logic kinh doanh cần thiết (e. g. hợp nhất các thay đổi, nhắc dữ liệu cũ) để giải quyết xung đột

Ví dụ: giả sử cột phiên bản có tên là

Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
1. Bạn có thể triển khai khóa lạc quan bằng mã như sau

Ghi chú. Vì OptimisticLockBehavior sẽ đảm bảo bản ghi chỉ được lưu nếu người dùng gửi số phiên bản hợp lệ bằng cách phân tích cú pháp trực tiếp , nên có thể hữu ích khi mở rộng lớp mô hình của bạn và thực hiện bước 2 trong mô hình gốc trong khi đính kèm hành vi (bước 3) vào lớp con để bạn . Ngoài ra, bạn có thể triển khai logic của riêng mình bằng cách định cấu hình thuộc tính của nó

Làm việc với dữ liệu quan hệ

Bên cạnh làm việc với các bảng cơ sở dữ liệu riêng lẻ, Active Record cũng có khả năng tập hợp các dữ liệu liên quan lại với nhau, giúp chúng có thể truy cập dễ dàng thông qua dữ liệu chính. Ví dụ: dữ liệu khách hàng có liên quan đến dữ liệu đơn hàng vì một khách hàng có thể đã đặt một hoặc nhiều đơn hàng. Với khai báo phù hợp về mối quan hệ này, bạn sẽ có thể truy cập thông tin đặt hàng của khách hàng bằng cách sử dụng biểu thức

Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
2, biểu thức này trả lại thông tin đặt hàng của khách hàng dưới dạng một mảng gồm
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
3 trường hợp Bản ghi Hoạt động

khai báo quan hệ

Để làm việc với dữ liệu quan hệ bằng Active Record, trước tiên bạn cần khai báo quan hệ trong các lớp Active Record. Nhiệm vụ đơn giản như khai báo một phương thức quan hệ cho mọi quan hệ quan tâm, như sau,

Trong đoạn mã trên, chúng ta đã khai báo một quan hệ

Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
4 cho lớp
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 và một quan hệ
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
1 cho lớp
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
3

Mỗi phương thức quan hệ phải được đặt tên là

Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
8. Ta gọi
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
9 (chữ cái đầu viết thường) là tên quan hệ. Lưu ý rằng tên quan hệ phân biệt chữ hoa chữ thường

Khi khai báo một quan hệ, bạn nên chỉ định các thông tin sau

  • tính đa dạng của quan hệ. được chỉ định bằng cách gọi một trong hai hoặc. Trong ví dụ trên bạn có thể dễ dàng đọc được trong khai báo quan hệ rằng một khách hàng có nhiều đơn hàng trong khi một đơn hàng chỉ có một khách hàng
  • tên của lớp Bản ghi hoạt động có liên quan. được chỉ định làm tham số đầu tiên cho một trong hai hoặc. Một cách thực hành được đề xuất là gọi _______69_______0 để lấy chuỗi tên lớp để bạn có thể nhận được hỗ trợ tự động hoàn thành IDE cũng như phát hiện lỗi ở giai đoạn biên dịch
  • liên kết giữa hai loại dữ liệu. chỉ định (các) cột mà qua đó hai loại dữ liệu có liên quan. Các giá trị mảng là các cột của dữ liệu chính (được đại diện bởi lớp Bản ghi Hoạt động mà bạn đang khai báo quan hệ), trong khi các khóa của mảng là các cột của dữ liệu liên quan

    Một quy tắc dễ nhớ là, như bạn thấy trong ví dụ trên, bạn viết cột thuộc về Bản ghi Hoạt động có liên quan ngay bên cạnh nó. Bạn thấy ở đó

    class Customer extends ActiveRecord
    {
        public function getBigOrders($threshold = 100)
        {
            return $this->hasMany(Order::class, ['customer_id' => 'id'])
                ->where('subtotal > :threshold', [':threshold' => $threshold])
                ->orderBy('id');
        }
    }
    
    1 là tài sản của
    Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
    
    3 và
    class Customer extends ActiveRecord
    {
        public function getBigOrders($threshold = 100)
        {
            return $this->hasMany(Order::class, ['customer_id' => 'id'])
                ->where('subtotal > :threshold', [':threshold' => $threshold])
                ->orderBy('id');
        }
    }
    
    3 là tài sản của
    return [
        'components' => [
            'db' => [
                'class' => 'yii\db\Connection',
                'dsn' => 'mysql:host=localhost;dbname=testdb',
                'username' => 'demo',
                'password' => 'demo',
            ],
        ],
    ];
    
    0

Cảnh báo. Tên quan hệ

class Customer extends ActiveRecord
{
    public function getBigOrders($threshold = 100)
    {
        return $this->hasMany(Order::class, ['customer_id' => 'id'])
            ->where('subtotal > :threshold', [':threshold' => $threshold])
            ->orderBy('id');
    }
}
5 được bảo lưu. Khi sử dụng nó sẽ tạo ra
class Customer extends ActiveRecord
{
    public function getBigOrders($threshold = 100)
    {
        return $this->hasMany(Order::class, ['customer_id' => 'id'])
            ->where('subtotal > :threshold', [':threshold' => $threshold])
            ->orderBy('id');
    }
}
6

Truy cập dữ liệu quan hệ

Sau khi khai báo quan hệ, bạn có thể truy cập dữ liệu quan hệ thông qua tên quan hệ. Điều này giống như truy cập một thuộc tính đối tượng được xác định bởi phương thức quan hệ. Vì lý do này, chúng tôi gọi nó là thuộc tính quan hệ. Ví dụ,

Thông tin. Khi bạn khai báo một quan hệ có tên

Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
9 thông qua phương thức getter
class Customer extends ActiveRecord
{
    public function getBigOrders($threshold = 100)
    {
        return $this->hasMany(Order::class, ['customer_id' => 'id'])
            ->where('subtotal > :threshold', [':threshold' => $threshold])
            ->orderBy('id');
    }
}
8, bạn sẽ có thể truy cập
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
9 giống như một thuộc tính đối tượng. Lưu ý rằng tên có phân biệt chữ hoa chữ thường

Nếu một mối quan hệ được khai báo với , việc truy cập thuộc tính mối quan hệ này sẽ trả về một mảng các phiên bản Bản ghi Hoạt động có liên quan;

Khi bạn truy cập một thuộc tính quan hệ lần đầu tiên, một câu lệnh SQL sẽ được thực thi, như trong ví dụ trên. Nếu cùng một thuộc tính được truy cập lại, kết quả trước đó sẽ được trả về mà không cần thực hiện lại câu lệnh SQL. Để buộc thực hiện lại câu lệnh SQL, trước tiên bạn nên bỏ đặt thuộc tính quan hệ.

class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
1

Ghi chú. Mặc dù khái niệm này có vẻ giống với tính năng thuộc tính đối tượng, nhưng có một sự khác biệt quan trọng. Đối với các thuộc tính đối tượng bình thường, giá trị thuộc tính cùng loại với phương thức getter xác định. Tuy nhiên, một phương thức quan hệ trả về một thể hiện yii\db\ActiveQuery, trong khi truy cập một thuộc tính quan hệ sẽ trả về một thể hiện yii\db\ActiveRecord hoặc một mảng trong số này

Điều này hữu ích để tạo các truy vấn tùy chỉnh, được mô tả trong phần tiếp theo

Truy vấn quan hệ động

Vì một phương thức quan hệ trả về một phiên bản của yii\db\ActiveQuery, nên bạn có thể xây dựng thêm truy vấn này bằng cách sử dụng các phương pháp xây dựng truy vấn trước khi thực hiện truy vấn DB. Ví dụ,

Không giống như truy cập một thuộc tính quan hệ, mỗi khi bạn thực hiện một truy vấn quan hệ động thông qua một phương thức quan hệ, một câu lệnh SQL sẽ được thực thi, ngay cả khi cùng một truy vấn quan hệ động đã được thực hiện trước đó

Đôi khi bạn thậm chí có thể muốn tham số hóa một khai báo quan hệ để bạn có thể dễ dàng thực hiện truy vấn quan hệ động hơn. Ví dụ, bạn có thể khai báo một quan hệ

class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
2 như sau,

class Customer extends ActiveRecord
{
    public function getBigOrders($threshold = 100)
    {
        return $this->hasMany(Order::class, ['customer_id' => 'id'])
            ->where('subtotal > :threshold', [':threshold' => $threshold])
            ->orderBy('id');
    }
}

Sau đó, bạn sẽ có thể thực hiện các truy vấn quan hệ sau

Quan hệ thông qua một bảng nối

Trong mô hình hóa cơ sở dữ liệu, khi bội số giữa hai bảng có liên quan là nhiều-nhiều, một bảng nối thường được giới thiệu. Ví dụ: bảng

class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
3 và bảng
class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
4 có thể được liên kết thông qua bảng nối có tên
class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
5. Sau đó, một đơn hàng sẽ tương ứng với nhiều mặt hàng trong đơn hàng, trong khi một mặt hàng sản phẩm cũng sẽ tương ứng với nhiều mặt hàng trong đơn hàng

Khi khai báo các quan hệ như vậy, bạn sẽ gọi một trong hai hoặc để chỉ định bảng nối. Sự khác biệt giữa và là cái trước chỉ định bảng nối theo tên quan hệ hiện có trong khi cái sau trực tiếp sử dụng bảng nối. Ví dụ,

class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}

Hay cách khác,

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
0

Cách sử dụng quan hệ được khai báo với bảng nối giống như cách sử dụng quan hệ thông thường. Ví dụ,

Xâu chuỗi các định nghĩa quan hệ qua nhiều bảng

Ngoài ra, có thể xác định quan hệ thông qua nhiều bảng bằng cách xâu chuỗi các định nghĩa quan hệ bằng cách sử dụng. Xem xét các ví dụ trên, chúng ta có các lớp

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0,
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
3 và
class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
8. Chúng ta có thể thêm một quan hệ vào lớp
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 liệt kê tất cả các mục từ tất cả các đơn đặt hàng mà chúng đã đặt và đặt tên là
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
00, chuỗi quan hệ được thể hiện trong ví dụ mã sau

Tải chậm và tải háo hức

Trong , chúng tôi đã giải thích rằng bạn có thể truy cập thuộc tính quan hệ của phiên bản Bản ghi Hoạt động giống như truy cập thuộc tính đối tượng bình thường. Một câu lệnh SQL sẽ chỉ được thực thi khi bạn truy cập thuộc tính quan hệ lần đầu tiên. Chúng tôi gọi phương thức truy cập dữ liệu quan hệ đó là lazy loading. Ví dụ,

Lazy loading rất thuận tiện để sử dụng. Tuy nhiên, nó có thể gặp sự cố về hiệu suất khi bạn cần truy cập vào cùng một thuộc tính quan hệ của nhiều phiên bản Bản ghi Hoạt động. Hãy xem xét ví dụ mã sau đây. Có bao nhiêu câu lệnh SQL sẽ được thực thi?

Như bạn có thể thấy từ nhận xét mã ở trên, có 101 câu lệnh SQL đang được thực thi. Điều này là do mỗi lần bạn truy cập thuộc tính quan hệ

Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
4 của một đối tượng
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 khác trong vòng lặp for, một câu lệnh SQL sẽ được thực thi

Để giải quyết vấn đề hiệu suất này, bạn có thể sử dụng cái gọi là phương pháp tải háo hức như hình bên dưới,

Bằng cách gọi , bạn hướng dẫn Active Record mang lại các đơn đặt hàng cho 100 khách hàng đầu tiên trong một câu lệnh SQL duy nhất. Kết quả là bạn giảm số câu lệnh SQL đã thực thi từ 101 xuống còn 2

Bạn có thể háo hức tải một hoặc nhiều quan hệ. Bạn thậm chí có thể háo hức tải các quan hệ lồng nhau. Mối quan hệ lồng nhau là mối quan hệ được khai báo trong lớp Bản ghi Hoạt động có liên quan. Ví dụ:

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 có quan hệ với
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
3 thông qua quan hệ
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
4 và
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
3 có quan hệ với
class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
8 thông qua quan hệ
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
08. Khi truy vấn cho
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0, bạn có thể háo hức tải
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
08 bằng cách sử dụng ký hiệu quan hệ lồng nhau
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
11

Đoạn mã sau đây cho thấy cách sử dụng khác nhau của. Chúng ta giả sử lớp

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 có hai quan hệ
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
4 và
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
14, trong khi lớp
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
3 có một quan hệ
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
08

Bạn có thể háo hức tải các mối quan hệ lồng sâu, chẳng hạn như

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
17. Tất cả các mối quan hệ cha mẹ sẽ được háo hức tải. Nghĩa là, khi bạn gọi bằng cách sử dụng
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
17, bạn sẽ háo hức nạp vào
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
19,
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
20,
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
21 và
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
17

Thông tin. Nói chung, khi háo hức tải các mối quan hệ

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
23 trong đó các mối quan hệ
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
24 được xác định bằng a , tổng số câu lệnh SQL
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
25 sẽ được thực thi. Lưu ý rằng một quan hệ lồng nhau
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
17 được tính là 4 quan hệ

Khi háo hức tải một mối quan hệ, bạn có thể tùy chỉnh truy vấn quan hệ tương ứng bằng cách sử dụng hàm ẩn danh. Ví dụ,

Khi tùy chỉnh truy vấn quan hệ cho một quan hệ, bạn nên chỉ định tên quan hệ làm khóa mảng và sử dụng hàm ẩn danh làm giá trị mảng tương ứng. Hàm ẩn danh sẽ nhận một tham số

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
27 đại diện cho đối tượng yii\db\ActiveQuery được sử dụng để thực hiện truy vấn quan hệ cho mối quan hệ. Trong ví dụ mã ở trên, chúng tôi đang sửa đổi truy vấn quan hệ bằng cách nối thêm một điều kiện bổ sung về trạng thái đơn hàng

Ghi chú. Nếu bạn gọi trong khi háo hức tải quan hệ, bạn phải đảm bảo rằng các cột được tham chiếu trong khai báo quan hệ đang được chọn. Nếu không, các mô hình liên quan có thể không được tải đúng cách. Ví dụ,

Tham gia với các mối quan hệ

Ghi chú. Nội dung được mô tả trong tiểu mục này chỉ áp dụng cho cơ sở dữ liệu quan hệ, chẳng hạn như MySQL, PostgreSQL, v.v.

Các truy vấn quan hệ mà chúng tôi đã mô tả cho đến nay chỉ tham chiếu đến các cột của bảng chính khi truy vấn dữ liệu chính. Trong thực tế, chúng ta thường cần tham chiếu các cột trong các bảng liên quan. Ví dụ: chúng tôi có thể muốn mang lại những khách hàng có ít nhất một đơn đặt hàng đang hoạt động. Để giải quyết vấn đề này, chúng ta có thể xây dựng truy vấn nối như sau

Ghi chú. Điều quan trọng là phải phân biệt các tên cột khi xây dựng các truy vấn quan hệ liên quan đến THAM GIA các câu lệnh SQL. Một thực tế phổ biến là đặt tiền tố tên cột với tên bảng tương ứng của chúng

Tuy nhiên, một cách tiếp cận tốt hơn là khai thác các khai báo quan hệ hiện có bằng cách gọi

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
1

Cả hai cách tiếp cận đều thực thi cùng một tập hợp các câu lệnh SQL. Tuy nhiên, cách tiếp cận thứ hai sạch hơn và khô hơn nhiều.

Theo mặc định, sẽ sử dụng

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
28 để nối bảng chính với bảng liên quan. Bạn có thể chỉ định một kiểu nối khác (e. g.
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
29) thông qua tham số thứ ba của nó là
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
30. Nếu loại tham gia bạn muốn là
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
31, bạn chỉ cần gọi , thay vào đó

Gọi sẽ là dữ liệu liên quan theo mặc định. Nếu bạn không muốn đưa dữ liệu liên quan vào, bạn có thể chỉ định tham số thứ hai của nó là

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
32 là
$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])])
8

Ghi chú. Ngay cả khi sử dụng hoặc bật tính năng tải háo hức, dữ liệu liên quan sẽ không được điền từ kết quả của truy vấn

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
34. Vì vậy, vẫn còn một truy vấn bổ sung cho mỗi quan hệ được nối như đã giải thích trong phần trên

Giống như , bạn có thể tham gia với một hoặc nhiều quan hệ; . Ví dụ,

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
2

Đôi khi khi nối hai bảng, bạn có thể cần chỉ định một số điều kiện bổ sung trong phần

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
35 của truy vấn THAM GIA. Điều này có thể được thực hiện bằng cách gọi phương thức như sau

Truy vấn trên mang lại tất cả khách hàng và đối với mỗi khách hàng, truy vấn này mang lại tất cả các đơn đặt hàng đang hoạt động. Lưu ý rằng điều này khác với ví dụ trước đây của chúng tôi chỉ mang lại những khách hàng có ít nhất một đơn đặt hàng đang hoạt động

Thông tin. Khi yii\db\ActiveQuery được chỉ định với một điều kiện thông qua , điều kiện sẽ được đưa vào phần

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
35 nếu truy vấn liên quan đến truy vấn THAM GIA. Nếu truy vấn không liên quan đến THAM GIA, điều kiện có sẽ được tự động thêm vào phần
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
37 của truy vấn. Do đó, nó chỉ có thể chứa các điều kiện bao gồm các cột của bảng liên quan

Bí danh bảng quan hệ

Như đã lưu ý trước đó, khi sử dụng THAM GIA trong một truy vấn, chúng ta cần phân biệt các tên cột. Do đó, bí danh thường được xác định cho một bảng. Có thể đặt bí danh cho truy vấn quan hệ bằng cách tùy chỉnh truy vấn quan hệ theo cách sau

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
3

Tuy nhiên, điều này có vẻ rất phức tạp và liên quan đến việc mã hóa cứng tên bảng đối tượng liên quan hoặc gọi _________38. Kể từ phiên bản 2. 0. 7, Yii cung cấp một lối tắt cho việc này. Bây giờ bạn có thể xác định và sử dụng bí danh cho bảng quan hệ như sau

Cú pháp trên hoạt động cho các quan hệ đơn giản. Nếu bạn cần một bí danh cho một bảng trung gian khi tham gia vào các quan hệ lồng nhau, e. g.

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
39, bạn cần lồng lệnh gọi joinWith như trong ví dụ sau

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
4

Quan hệ nghịch đảo

Các khai báo quan hệ thường đối ứng giữa hai lớp Active Record. Ví dụ:

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 có liên quan đến
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
3 thông qua quan hệ ________ 52 _______4 và ________ 52 _______3 có liên quan trở lại với
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 thông qua quan hệ
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
1

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
5

Bây giờ hãy xem xét đoạn mã sau

Chúng ta sẽ nghĩ rằng

$values = [
    'name' => 'James',
    'email' => '[email protected]',
];

$customer = new Customer();

$customer->attributes = $values;
$customer->save();
3 và
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
47 giống nhau, nhưng thực ra không phải vậy. Trên thực tế, chúng chứa cùng một dữ liệu khách hàng, nhưng chúng là các đối tượng khác nhau. Khi truy cập vào
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
48, một câu lệnh SQL bổ sung được thực thi để điền vào một đối tượng mới
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
47

Để tránh việc thực thi thừa câu lệnh SQL cuối cùng trong ví dụ trên, chúng ta nên nói với Yii rằng

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
1 là một quan hệ nghịch đảo của
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
4 bằng cách gọi phương thức như bên dưới

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
6

Với khai báo quan hệ sửa đổi này, chúng tôi sẽ có

Ghi chú. Mối quan hệ nghịch đảo không thể được xác định cho các mối quan hệ liên quan đến một. Nghĩa là, nếu một quan hệ được xác định bằng hoặc , bạn không nên gọi thêm

tiết kiệm quan hệ

Khi làm việc với dữ liệu quan hệ, bạn thường cần thiết lập mối quan hệ giữa các dữ liệu khác nhau hoặc hủy bỏ các mối quan hệ hiện có. Điều này yêu cầu đặt giá trị thích hợp cho các cột xác định quan hệ. Sử dụng Active Record, cuối cùng bạn có thể viết mã như sau

Active Record cung cấp phương pháp cho phép bạn hoàn thành nhiệm vụ này một cách dễ dàng hơn

Phương pháp này yêu cầu bạn chỉ định tên quan hệ và phiên bản Bản ghi Hoạt động đích mà mối quan hệ sẽ được thiết lập với. Phương thức sẽ sửa đổi các giá trị của các thuộc tính liên kết hai phiên bản Bản ghi Hoạt động và lưu chúng vào cơ sở dữ liệu. Trong ví dụ trên, nó sẽ đặt thuộc tính

class Customer extends ActiveRecord
{
    public function getBigOrders($threshold = 100)
    {
        return $this->hasMany(Order::class, ['customer_id' => 'id'])
            ->where('subtotal > :threshold', [':threshold' => $threshold])
            ->orderBy('id');
    }
}
1 của thể hiện
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
3 thành giá trị của thuộc tính
class Customer extends ActiveRecord
{
    public function getBigOrders($threshold = 100)
    {
        return $this->hasMany(Order::class, ['customer_id' => 'id'])
            ->where('subtotal > :threshold', [':threshold' => $threshold])
            ->orderBy('id');
    }
}
3 của thể hiện
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 rồi lưu vào cơ sở dữ liệu

Ghi chú. Bạn không thể liên kết hai phiên bản Bản ghi Hoạt động mới được tạo

Lợi ích của việc sử dụng thậm chí còn rõ ràng hơn khi một quan hệ được xác định thông qua một. Ví dụ: bạn có thể sử dụng đoạn mã sau để liên kết phiên bản

Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
3 với phiên bản
class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
8

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
7

Đoạn mã trên sẽ tự động chèn một hàng trong bảng nối

class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
5 để liên kết thứ tự với mặt hàng

Thông tin. Phương pháp này sẽ KHÔNG thực hiện bất kỳ xác thực dữ liệu nào trong khi lưu phiên bản Bản ghi Hoạt động bị ảnh hưởng. Bạn có trách nhiệm xác thực mọi dữ liệu đầu vào trước khi gọi phương thức này

Hoạt động ngược lại là phá vỡ mối quan hệ hiện có giữa hai phiên bản Bản ghi Hoạt động. Ví dụ,

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
8

Theo mặc định, phương thức này sẽ đặt (các) giá trị khóa ngoại xác định mối quan hệ hiện tại là

class Order extends ActiveRecord
{
    public function getItems()
    {
        return $this->hasMany(Item::class, ['id' => 'item_id'])
            ->viaTable('order_item', ['order_id' => 'id']);
    }
}
0. Tuy nhiên, bạn có thể chọn xóa hàng của bảng chứa giá trị khóa ngoại bằng cách chuyển tham số
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
60 dưới dạng
$customer = Customer::findOne(123);
$customer->delete();
5 cho phương thức

Khi một bảng nối có liên quan đến một quan hệ, việc gọi sẽ khiến các khóa ngoại trong bảng nối bị xóa hoặc xóa hàng tương ứng trong bảng nối nếu

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
60 là
$customer = Customer::findOne(123);
$customer->delete();
5

Quan hệ cơ sở dữ liệu chéo

Bản ghi Hoạt động cho phép bạn khai báo mối quan hệ giữa các lớp Bản ghi Hoạt động được cung cấp bởi các cơ sở dữ liệu khác nhau. Các cơ sở dữ liệu có thể thuộc các loại khác nhau (e. g. MySQL và PostgreSQL hoặc MS SQL và MongoDB) và chúng có thể chạy trên các máy chủ khác nhau. Bạn có thể sử dụng cú pháp tương tự để thực hiện các truy vấn quan hệ. Ví dụ,

Bạn có thể sử dụng hầu hết các tính năng truy vấn quan hệ đã được mô tả trong phần này

Ghi chú. Việc sử dụng bị giới hạn đối với cơ sở dữ liệu cho phép truy vấn THAM GIA cơ sở dữ liệu chéo. Vì lý do này, bạn không thể sử dụng phương pháp này trong ví dụ trên vì MongoDB không hỗ trợ THAM GIA

Tùy chỉnh các lớp truy vấn

Theo mặc định, tất cả các truy vấn Bản ghi Hoạt động đều được hỗ trợ bởi yii\db\ActiveQuery. Để sử dụng lớp truy vấn tùy chỉnh trong lớp Bản ghi Hoạt động, bạn nên ghi đè phương thức và trả về một phiên bản của lớp truy vấn tùy chỉnh của bạn. Ví dụ,

Bây giờ bất cứ khi nào bạn đang thực hiện một truy vấn (e. g.

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
64,
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
65) hoặc định nghĩa một quan hệ (e. g.
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
66) với
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
67, bạn sẽ gọi một thể hiện của
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
68 thay vì
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
69

Bây giờ bạn phải xác định lớp

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
68, lớp này có thể được tùy chỉnh theo nhiều cách sáng tạo để cải thiện trải nghiệm xây dựng truy vấn của bạn. Ví dụ,

Ghi chú. Thay vì gọi , thông thường bạn nên gọi hoặc nối thêm các điều kiện bổ sung khi xác định các phương pháp xây dựng truy vấn mới để mọi điều kiện hiện có không bị ghi đè

Điều này cho phép bạn viết mã xây dựng truy vấn như sau

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
9

Mẹo. Trong các dự án lớn, bạn nên sử dụng các lớp truy vấn tùy chỉnh để giữ hầu hết các mã liên quan đến truy vấn để các lớp Bản ghi Hoạt động có thể được giữ sạch sẽ

Bạn cũng có thể sử dụng các phương pháp xây dựng truy vấn mới khi xác định quan hệ về

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
67 hoặc thực hiện truy vấn quan hệ

Thông tin. Trong Yii 1. 1, có một khái niệm gọi là phạm vi. Phạm vi không còn được hỗ trợ trực tiếp trong Yii 2. 0 và bạn nên sử dụng các lớp truy vấn và phương thức truy vấn tùy chỉnh để đạt được cùng một mục tiêu

Khi phiên bản Bản ghi Hoạt động được điền từ kết quả truy vấn, các thuộc tính của nó được lấp đầy bởi các giá trị cột tương ứng từ tập dữ liệu đã nhận

Bạn có thể tìm nạp các cột hoặc giá trị bổ sung từ truy vấn và lưu trữ nó bên trong Bản ghi Hoạt động. Ví dụ: giả sử chúng ta có một bảng tên là

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
72, bảng này chứa thông tin về các phòng có sẵn trong khách sạn. Mỗi phòng lưu trữ thông tin về kích thước hình học của nó bằng cách sử dụng các trường
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
73,
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
74,
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
75. Hãy tưởng tượng chúng ta cần truy xuất danh sách tất cả các phòng có sẵn với số lượng theo thứ tự giảm dần. Vì vậy, bạn không thể tính toán khối lượng bằng PHP, vì chúng tôi cần sắp xếp các bản ghi theo giá trị của nó, nhưng bạn cũng muốn
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
76 được hiển thị trong danh sách. Để đạt được mục tiêu, bạn cần khai báo một trường bổ sung trong lớp Bản ghi Hoạt động
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
77 của mình, trường này sẽ lưu trữ giá trị
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
76

Sau đó, bạn cần soạn một truy vấn tính toán thể tích của căn phòng và thực hiện sắp xếp

Khả năng chọn các trường bổ sung có thể đặc biệt hữu ích cho các truy vấn tổng hợp. Giả sử bạn cần hiển thị danh sách khách hàng với số lượng đơn hàng họ đã thực hiện. Trước hết, bạn cần khai báo một lớp

return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'demo',
            'password' => 'demo',
        ],
    ],
];
0 với quan hệ
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);
4 và trường bổ sung để lưu trữ số đếm

Sau đó, bạn có thể soạn một truy vấn, tham gia các đơn đặt hàng và tính toán số lượng của chúng

Một nhược điểm của việc sử dụng phương pháp này là nếu thông tin không được tải trên truy vấn SQL - nó phải được tính riêng. Do đó, nếu bạn đã tìm thấy bản ghi cụ thể thông qua truy vấn thông thường mà không có câu lệnh chọn bổ sung, nó sẽ không thể trả về giá trị thực cho trường bổ sung. Điều tương tự sẽ xảy ra đối với bản ghi mới được lưu

Sử dụng các phương thức và phép thuật, chúng ta có thể mô phỏng hành vi của một thuộc tính

Khi truy vấn chọn không cung cấp âm lượng, mô hình sẽ có thể tự động tính toán nó bằng cách sử dụng các thuộc tính của mô hình

Bạn cũng có thể tính toán các trường tổng hợp bằng cách sử dụng các quan hệ đã xác định

Với mã này, trong trường hợp 'orderCount' có trong câu lệnh 'select' -

$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
81 sẽ được điền bởi kết quả truy vấn, nếu không, nó sẽ được tính toán theo yêu cầu bằng cách sử dụng quan hệ
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [
    ':name' => 'Qiang',
])->execute();
82

Cách tiếp cận này cũng có thể được sử dụng để tạo các phím tắt cho một số dữ liệu quan hệ, đặc biệt là cho tập hợp. Ví dụ