Query Builder trong yii2

0
517

Tại sao phải dùng query builder trong khi chúng ta có thể viết lệnh Sql 1 .Đơn giản là điều dùng nó sẽ dễ hiểu hơn và an toàn hơn .Nếu đặt 1 đoạn code bằng query builder với 1 đoạn code truy vấn sql đơn thuần bạn sẽ thấy nó tiện dụng biết bao .Dưới đây là 2 đoạn mã bằng sql với query builder mà bạn có thể tham khảo .Đoạn mã query builder

$rows = (new \yii\db\Query())
    ->select(['id', 'email'])
    ->from('user')
    ->where(['last_name' => 'Smith'])
    ->limit(10)
    ->all();

Đoạn mã với sql

SELECT `id`, `email` 
FROM `user`
WHERE `last_name` = :last_name
LIMIT 10

Bạn có thể so sánh để xem mình nên dùng cách nào mình dễ dùng thì dùng

Building Queries

Ta sẽ đi tìm hiểu cách xây dựng các câu truy vấn trong yii2 như thế nào nhé .Yii2 giúp ta phân từng phần ra thành từng đoạn riêng biệt để đạt được yếu tố code sạch sẽ gọn gàng dễ bảo trì .Các yếu tố cần để có thể xây dựng truy vấn là có 1 bảng cớ sở dữ liệu .Dưới đây là đoạn code articel mà mình tạo sẵn bạn chỉ cần copy về cơ sở dữ liệu của mình

-- phpMyAdmin SQL Dump
-- version 4.5.1
-- http://www.phpmyadmin.net
--
-- Host: 127.0.0.1
-- Generation Time: Dec 07, 2016 at 07:07 AM
-- Server version: 10.1.16-MariaDB
-- PHP Version: 5.6.24

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `demoyii2`
--

-- --------------------------------------------------------

--
-- Table structure for table `article`
--

CREATE TABLE `article` (
  `article_id` int(11) NOT NULL,
  `article_title` varchar(500) NOT NULL,
  `article_desc` varchar(500) NOT NULL,
  `article_keywords` varchar(500) NOT NULL,
  `article_body` varchar(10000) NOT NULL,
  `article_view` int(11) NOT NULL,
  `article_author` int(5) NOT NULL,
  `slug` varchar(500) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='bảng bài viết ';

--
-- Dumping data for table `article`
--

INSERT INTO `article` (`article_id`, `article_title`, `article_desc`, `article_keywords`, `article_body`, `article_view`, `article_author`, `slug`) VALUES
(1, 'Hello word chinh sua', 'Đây là bài đầu tiên', 'ehehe', 'Đây là bài đầu tiên', 12, 1, 'hello-word-chinh-sua'),
(2, 'Xin chào các bạn bài 2', 'Về những phần 2 thôi mà', 'bài 2,xin chào', 'Hello đây là phần 2 nha các bạn', 0, 1, 'xin-chao-cac-ban-bai-2'),
(3, 'Đây là test slug', 'slug,test slug', 'heheeh.hehehe', '123123123123', 324, 1, 'day-la-test-slug');

--
-- Indexes for dumped tables
--

--
-- Indexes for table `article`
--
ALTER TABLE `article`
  ADD PRIMARY KEY (`article_id`);

--
-- AUTO_INCREMENT for dumped tables
--

--
-- AUTO_INCREMENT for table `article`
--
ALTER TABLE `article`
  MODIFY `article_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

Ok giờ đến phần quan trọng nhất chúng ta cần kết nối đến database trong main.php ở folder common/config

Cách dùng như sau : trong phần controller bạn gọi hàm truy vấn đến cơ sở dữ liệu thông qua component db có sẵn trong yii2

$allpost =(new Query())->select('*')->from('article')->all();

Như vậy ta đã có thể lấy hết dữ liệu trong bảng article 1 cách dễ dàng

Các cách xây dựng 1 câu truy vấn gồm các thành phần sau

Select()

Có nhiệm vụ chọn dữ liệu cần lấy cho chúng ta .Ở phía trên mình chọn tất cả dữ liệu của bảng .giờ mình sẽ hướng dẫn các bạn chọn dữ liệu 1 số trường mà bạn muốn lấy .Ở đây mình chọn 3 trường là :article_id,article_title, article_desc bằng câu lệnh dưới đây

$allpost =(new Query())->select(['article_id','article_title','article_desc '])->from('article')->all();

Như vậy là xong rồi đó cả nhà .1 số trường hợp đặc biệt như dưới đây :

Lồng truy vấn select với nhau 

$subQuery = (new Query())->select('COUNT(*)')->from('user');

// SELECT `article_id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post`
$query = (new Query())->select(['article_id', 'count' => $subQuery])->from('article');

Loại bỏ các bản ghi trùng nhau 

$allpost =(new Query())->select('*')->from('article')->distinct()->all();

Thêm lựa chọn khi select 

Tính năng này mình cảm thấy dư thừa quá trời :v

$query->select(['article_id', 'article_title'])
    ->addSelect(['article_desc']);

From()

Có nhiệm vụ xác định dữ liệu lấy từ bảng ghi nào .Ta có cách lấy từ 1 bảng và nhiều bảng lần lượt như sau

$query->from('article');

hoặc

$query->from(['article', 'catelogy']);

ok giờ đã xong.

Where()

where có nhiệm vụ giúp ta so sánh các điều kiện mà chúng ta cần khi lấy dữ liệu .Ví dụ như những bài viết trước ngày 20/11 hay thỏa mãn 1 số điều kiện nào đó :

Hàm trong whereCách dùngCâu lệnh sql tương ứng
and[‘and’, ‘giatri=1’, ‘giatri=2’]Giatri=1 và giatri=2
[‘and’, ‘type=1’, [‘or’, ‘id=1’, ‘id=2’]]type=1 AND (id=1 OR id=2)
or[‘or’, ‘giatri=1’, ‘giatri=2’]Giatri=1 or giatri=2
between[‘between’, ‘id’, 1, 10]id BETWEEN 1 AND 10
not between[‘not between’,’id’,1,5]Id not between 1 and 5
in[‘in’,’id’,[1,2,5,6]]id IN (1, 2, 5,6)
Not in[‘not in’,’user’,[‘hien’,’nguyen’,’anh’]]User not in(,[‘hien’,’nguyen’,’anh’)
Like[‘like’, ‘name’, ‘hien’]name LIKE ‘%hien%’
[‘like’, ‘name’, [‘test’, ‘sample’]]name LIKE ‘%test%’ AND name LIKE ‘%sample%’
Not likeTương tự với like nhưng với ý nghĩa phủ định
>, <=[‘>’, ‘tuoi’, 10]Tuoi >10

orderBy()

Có nhiệm vụ lọc dữ liệu trong truy vấn có nhiệm vụ lọc dữ liệu .Ví dụ sắp xếp bài viết trong 1 danh mục với thời gian sắp xếp từ ngày publish gần nhất ra đầu tiên

$query->orderBy([
    'publish_time' => SORT_DESC,
    'title' => SORT_ASC,
]);

limit() and offset()

Có nhiệm vụ giới hạn vùng dữ liệu lấy ra .Cái này có nhiệm vụ phân trang rất tốt

// ... LIMIT 10 OFFSET 20
$query->limit(15)->offset(20);

Dưới đây là đoạn mã mình phân trang

$allpost =(new Query())->select('*')->from('article')->distinct()->all();
 var_dump($allpost);die;
 $pages = new Pagination(['totalCount' => $allpost->count()]);
 $allpost = $allpost->offset($pages->offset)
 ->limit($pages->limit)
 ->all();
 return $this->render('index',['allpost'=>$allpost,'pages'=>$pages]);

Các bạn có thể tham khảo để biết cách phân quyền