Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Mối quan hệ thuộc về ToMany trong Laravel trên nhiều cơ sở dữ liệu

Rất đơn giản:

public function bs()
{
    $database = $this->getConnection()->getDatabaseName();
    return $this->belongsToMany('B', "$database.a_bs", 'a_id', 'b_id');
}

Tôi đang lấy tên cơ sở dữ liệu động vì kết nối của tôi được định cấu hình dựa trên một biến môi trường. Laravel dường như giả định bảng tổng hợp tồn tại trong cùng một cơ sở dữ liệu với quan hệ đích, do đó, điều này sẽ buộc nó trông giống với cơ sở dữ liệu tương ứng với mô hình mà phương pháp này đang sử dụng, lĩnh vực 'A' của bạn.

Nếu bạn không lo lắng về cơ sở dữ liệu SQLite, tức là trong phạm vi kiểm thử đơn vị, thì đó là tất cả những gì bạn cần. Nhưng nếu bạn đang có, hãy tiếp tục đọc.

Thứ nhất, ví dụ trước không đủ. Giá trị của $ database cuối cùng sẽ là một đường dẫn tệp, vì vậy bạn cần đặt bí danh cho nó thành một thứ gì đó sẽ không phá vỡ câu lệnh SQL và làm cho nó có thể truy cập được với kết nối hiện tại. "ATTACH DATABASE '$database' AS $name" là cách bạn làm điều đó:

public function bs()
{
    $database = $this->getConnection()->getDatabaseName();
    if (is_file($database)) {
        $connection = app('B')->getConnection()->getName();
        $name = $this->getConnection()->getName();
        \Illuminate\Support\Facades\DB::connection($connection)->statement("ATTACH DATABASE '$database' AS $name");
        $database = $name;
    }
    return $this->belongsToMany('B', "$database.a_bs", 'a_id', 'b_id');
}

Cảnh báo:Các giao dịch làm hỏng điều này: Nếu kết nối hiện tại đang sử dụng các giao dịch, câu lệnh ATTACH DATABASE sẽ không thành công. Bạn có thể sử dụng các giao dịch trên đó sau thực hiện câu lệnh đó.

Trong khi, nếu liên quan kết nối sử dụng các giao dịch, dữ liệu kết quả sẽ được hiển thị âm thầm ẩn đối với dữ liệu hiện tại. Điều này khiến tôi phát điên trong thời gian dài hơn tôi muốn thừa nhận, bởi vì các truy vấn của tôi chạy mà không có lỗi, nhưng tiếp tục trống. Có vẻ như chỉ dữ liệu thực sự được ghi vào cơ sở dữ liệu đính kèm mới thực sự có thể truy cập được vào cơ sở dữ liệu được đính kèm.

Vì vậy, sau khi bị buộc phải ghi vào cơ sở dữ liệu đính kèm, bạn vẫn có thể muốn bài kiểm tra của mình tự dọn dẹp. Một giải pháp đơn giản chỉ cần sử dụng $this->artisan('migrate:rollback', ['--database' => $attachedConnectionName]); . Nhưng nếu bạn có nhiều bài kiểm tra cần các bảng giống nhau, điều này không hiệu quả lắm vì nó buộc họ phải xây dựng lại chúng mỗi lần.

Một lựa chọn tốt hơn sẽ là cắt bớt các bảng, nhưng vẫn giữ nguyên cấu trúc của chúng:

//Get all tables within the attached database
collect(DB::connection($database)->select("SELECT name FROM sqlite_master WHERE type = 'table'"))->each(function ($table) use ($name) {
        //Clear all entries for the table
        DB::connection($database)->delete("DELETE FROM '$table->name'");
        //Reset any auto-incremented index value
        DB::connection($database)->delete("DELETE FROM sqlite_sequence WHERE name = '$table->name'");
    });
}

Thao tác này sẽ xóa tất cả dữ liệu khỏi kết nối đó , nhưng không có lý do gì bạn không thể áp dụng một số loại bộ lọc mà bạn thấy phù hợp. Ngoài ra, bạn có thể tận dụng thực tế là SQLite DBs là các tệp dễ truy cập và chỉ cần sao chép tệp đính kèm vào tệp tạm thời và sử dụng nó để ghi đè lên nguồn sau khi quá trình kiểm tra được thực hiện xong. Kết quả sẽ giống về mặt chức năng với một giao dịch.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysql chọn để trả về khoảng trống cho tất cả trừ hàng đầu tiên của cột lặp lại

  2. Mã hóa lưu lượng truy cập MySQL trong tập lệnh

  3. Ví dụ về WEEKDAY () - MySQL

  4. Định tuyến với AngularJS và Slim PHP

  5. Tìm kiếm với giá trị được phân tách bằng dấu phẩy mysql