Helpex - Trao đổi & giúp đỡ Đăng nhập
230

Lỗi di chuyển trên Laravel 5.4 với php artisan make:auth

[Illuminate \ Database \ QueryException] SQLSTATE [42000]: Lỗi cú pháp hoặc vi phạm quyền truy cập: 1071 Khóa được chỉ định quá dài; độ dài khóa tối đa là 767 byte (SQL: alter tabl e usersadd unique users_email_unique( email))

[PDOException] SQLSTATE [42000]: Lỗi cú pháp hoặc vi phạm quyền truy cập: 1071 Khóa được chỉ định quá dài; độ dài khóa tối đa là 767 byte

230 hữu ích 2 bình luận 226k xem chia sẻ
33 trả lời 33
365

Theo tài liệu chính thức của Laravel 7.x , bạn có thể giải quyết vấn đề này khá dễ dàng.

Cập nhật của bạn /app/Providers/AppServiceProvider.phpđể chứa:

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}

Ngoài ra, bạn có thể bật innodb_large_prefixtùy chọn cho cơ sở dữ liệu của mình. Tham khảo tài liệu của cơ sở dữ liệu của bạn để biết hướng dẫn về cách bật tùy chọn này đúng cách.

365 hữu ích 5 bình luận chia sẻ
158

Tôi không biết tại sao giải pháp trên và giải pháp chính thức đang thêm

Schema::defaultStringLength(191);

trong AppServiceProviderkhông làm việc cho tôi. Những gì hiệu quả là chỉnh sửa database.phptệp trong configthư mục. Chỉ cần chỉnh sửa

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',

đến

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',

và nó sẽ hoạt động, mặc dù bạn sẽ không thể lưu trữ các ký tự nhiềubyte mở rộng như biểu tượng cảm xúc .

Đây là một cách hack xấu xí và đừng làm nếu bạn muốn lưu trữ chuỗi bằng ngôn ngữ không phải tiếng Anh, biểu tượng cảm xúc

Tôi đã làm điều đó với Laravel 5.7. Hy vọng nó giúp.

158 hữu ích 5 bình luận chia sẻ
139

Tôi chỉ thêm câu trả lời này ở đây vì nó là quickestgiải pháp cho tôi. Chỉ cần đặt công cụ cơ sở dữ liệu mặc định thành 'InnoDB'bật

/config/database.php

'mysql' => [
    ...,
    ...,
    'engine' => 'InnoDB',
 ]

sau đó chạy php artisan config:cacheđể xóa và làm mới bộ đệm cấu hình

CHỈNH SỬA: Các câu trả lời được tìm thấy ở đây có thể giải thích những gì đằng sau hậu trường của câu hỏi này

139 hữu ích 5 bình luận chia sẻ
28

Sự cố này do phiên bản cơ sở dữ liệu Laravel 5.4 gây ra.

Theo tài liệu (trong Index Lengths & MySQL / MariaDBphần):

Laravel sử dụng bộ utf8mb4ký tự theo mặc định, bao gồm hỗ trợ lưu trữ "biểu tượng cảm xúc" trong cơ sở dữ liệu. Nếu bạn đang chạy phiên bản MySQL cũ hơn bản phát hành 5.7.7 hoặc MariaDB cũ hơn bản phát hành 10.2.2, bạn có thể cần phải định cấu hình theo cách thủ công độ dài chuỗi mặc định được tạo bởi quá trình di chuyển để MySQL tạo chỉ mục cho chúng. Bạn có thể cấu hình điều này bằng cách gọi Schema::defaultStringLengthphương thức trong của bạn AppServiceProvider.

Nói cách khác, trong <ROOT>/app/Providers/AppServiceProvider.php:

// Import Schema
use Illuminate\Support\Facades\Schema;
// ...

class AppServiceProvider extends ServiceProvider
{

public function boot()
{
    // Add the following line
    Schema::defaultStringLength(191);
}

// ...

}

Nhưng như nhận xét về câu trả lời khác nói:

Hãy cẩn thận về giải pháp này. Ví dụ: nếu bạn lập chỉ mục các trường email, các email được lưu trữ chỉ có thể có độ dài tối đa là 191 ký tự. Đây là ít hơn các trạng thái RFC chính thức.

Vì vậy, tài liệu cũng đề xuất một giải pháp khác:

Ngoài ra, bạn có thể bật innodb_large_prefixtùy chọn cho cơ sở dữ liệu của mình. Tham khảo tài liệu của cơ sở dữ liệu của bạn để biết hướng dẫn về cách bật tùy chọn này đúng cách.

28 hữu ích 0 bình luận chia sẻ
17

Đối với một người không muốn thay đổi AppServiceProvider.php. (Theo ý kiến ​​của tôi, thật tệ khi thay đổi AppServiceProvider.phpchỉ để di chuyển)

Bạn có thể thêm lại độ dài dữ liệu vào tệp di chuyển database/migrations/như sau:

create_users_table.php

$table->string('name',64);
$table->string('email',128)->unique();

create_password_resets_table.php

$table->string('email',128)->index();
17 hữu ích 3 bình luận chia sẻ
13

Tôi đã giải quyết vấn đề này và chỉnh sửa config->database.phptệp của mình để thích cơ sở dữ liệu của tôi ('charset'=>'utf8')('collation'=>'utf8_general_ci'), vì vậy vấn đề của tôi được giải quyết bằng mã như sau:

'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8',
        'collation' => 'utf8_general_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ],
13 hữu ích 1 bình luận chia sẻ
12

Tôi đang thêm hai sollution phù hợp với tôi.

Ô nhiễm đầu tiên là :

  1. Mở tệp database.php trong thư mục config dir /.
  2. Chỉnh sửa 'engine' => null,thành'engine' => 'InnoDB',

    Điều này đã làm việc cho tôi.

Ô nhiễm thứ 2 là:

  1. Mở tệp database.php trong thư mục config dir /.
    2. Chỉnh sửa
    'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
    thành

    'charset' => 'utf8', 'collation' => 'utf8_unicode_ci',


Chúc may mắn

12 hữu ích 0 bình luận chia sẻ
11

Laravel 7.X (cũng hoạt động ở 8X): Giải pháp đơn giản .

Lựa chọn 1:

php artisan db:wipe 

Cập nhật các giá trị này (Bên dưới) của mảng mysql trong /config/database.php

'charset' => 'utf8', 'collation' => 'utf8_general_ci',

Và sau đó

php artisan migrate

Xong rôi! Bảng di chuyển sẽ được tạo thành công .


Lựa chọn 2:

Sử dụng php artisan db:wipe hoặc xóa / bỏ tất cả các bảng trong cơ sở dữ liệu của bạn theo cách thủ công.

Cập nhật AppServiceProvider.php của bạn [ Nằm trong app / Providers /AppServiceProvider.php ]

use Illuminate\Support\Facades\Schema;
/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191); 
}

Và sau đó

php artisan migrate

Xong rôi!

Cạm bẫy: Tôi muốn đề cập đến bình luận của @shock_gone_wild

Hãy cẩn thận về giải pháp này (Tùy chọn-2). Ví dụ: nếu bạn lập chỉ mục các trường email, các email được lưu trữ chỉ có thể có độ dài tối đa là 191 ký tự. Đây là ít hơn các trạng thái RFC chính thức.


Theo tùy chọn, tôi đã thử những cách khả thi này (như bên dưới) nhưng không hiệu quả .

php artisan config:cache php artisan migrate:fresh

php artisan migrate:reset

11 hữu ích 2 bình luận chia sẻ
9

1- Đi tới /config/database.phpvà tìm những dòng này

'mysql' => [
    ...,
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    ...,
    'engine' => null,
 ]

và thay đổi chúng thành:

'mysql' => [
    ...,
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    ...,
    'engine' => 'InnoDB',
 ]

2- Chạy php artisan config:cacheđể cấu hình lại laravel

3- Xóa các bảng hiện có trong cơ sở dữ liệu của bạn và sau đó chạy php artisan migratelại

9 hữu ích 2 bình luận chia sẻ
9

Tôi đã tìm thấy hai giải pháp cho lỗi này

LỰA CHỌN 1:

Mở bảng userpassword_reset của bạn trong thư mục cơ sở dữ liệu / di chuyển

Và chỉ cần thay đổi độ dài của email:

$table->string('email',191)->unique();

LỰA CHỌN 2:

Mở app/Providers/AppServiceProvider.phptệp của bạn và bên trong boot()phương thức đặt độ dài chuỗi mặc định:

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}
9 hữu ích 0 bình luận chia sẻ
6

Thay vì đặt giới hạn về độ dài, tôi sẽ đề xuất những điều sau đây, điều này đã phù hợp với tôi.

Phía trong:

config / database.php

thay thế dòng này cho mysql:

'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

với:

'engine' => null,
6 hữu ích 0 bình luận chia sẻ
6

Giải pháp không ai nói là trong Mysql v5.5 và sau đó InnoDB là công cụ lưu trữ mặc định không gặp vấn đề này nhưng trong nhiều trường hợp như của tôi, có một số tệp cấu hình mysql ini cũ đang sử dụng công cụ lưu trữ MYISAM cũ như bên dưới.

default-storage-engine=MYISAM

đang tạo ra tất cả những vấn đề này và giải pháp là thay đổi công cụ lưu trữ mặc định thành InnoDB trong tệp cấu hình ini của Mysql một lần và mãi mãi thay vì thực hiện các bản hack tạm thời.

default-storage-engine=InnoDB

Và nếu bạn đang sử dụng MySql v5.5 trở lên thì InnoDB là công cụ mặc định nên bạn không cần thiết lập nó một cách rõ ràng như trên, chỉ cần xóa default-storage-engine=MYISAMnếu nó tồn tại khỏi initệp của bạn và bạn đã sẵn sàng.

6 hữu ích 2 bình luận chia sẻ
4

Như đã nêu trong hướng dẫn Migrations để khắc phục điều này, tất cả những gì bạn phải làm là chỉnh sửa app/Providers/AppServiceProvider.phptệp của mình và bên trong phương pháp khởi động đặt độ dài chuỗi mặc định:

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}

Lưu ý: trước tiên bạn phải xóa (nếu có) bảng người dùng , bảng password_resets khỏi cơ sở dữ liệu và xóa người dùng và các mục nhập password_resets khỏi bảng di chuyển .

Để chạy tất cả các lần di chuyển chưa thực hiện của bạn, hãy thực hiện migratelệnh Artisan:

php artisan migrate

Sau đó mọi thứ sẽ hoạt động như bình thường.

4 hữu ích 0 bình luận chia sẻ
4

Như đã chỉ định, chúng tôi thêm vào AppServiceProvider.php trong Ứng dụng / Nhà cung cấp

use Illuminate\Support\Facades\Schema;  // add this

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191); // also this line
}

bạn có thể xem thêm chi tiết trong liên kết bên dưới (tìm kiếm "Độ dài chỉ mục & MySQL / MariaDB") https://laravel.com/docs/5.5/migrations

NHƯNG ĐÓ không phải là những gì tôi đã xuất bản! vấn đề là ngay cả khi thực hiện những điều trên, bạn sẽ có thể gặp phải một lỗi khác (đó là khi bạn chạy php artisan migratelệnh và do vấn đề về độ dài, thao tác có thể sẽ bị kẹt ở giữa. Giải pháp ở bên dưới và bảng người dùng có thể được tạo không có phần còn lại hoặc không hoàn toàn chính xác) chúng ta cần quay trở lại . cuộn lại mặc định sẽ không hoạt động. bởi vì hoạt động di chuyển không thích kết thúc. bạn cần xóa các bảng được tạo mới trong cơ sở dữ liệu theo cách thủ công.

chúng ta có thể làm điều đó bằng cách sử dụng tinker như bên dưới:

L:\todos> php artisan tinker

Psy Shell v0.8.15 (PHP 7.1.10 — cli) by Justin Hileman

>>> Schema::drop('users')

=> null

Bản thân tôi đã gặp sự cố với bảng người dùng.

sau đó bạn tốt để đi

php artisan migrate:rollback

php artisan migrate

4 hữu ích 0 bình luận chia sẻ
3

Nếu bạn muốn thay đổi trong AppServiceProvider thì bạn cần xác định độ dài của trường email trong quá trình di chuyển. chỉ cần thay thế dòng mã đầu tiên thành dòng thứ hai.

create_users_table

$table->string('email')->unique();
$table->string('email', 50)->unique();

create_password_resets_table

$table->string('email')->index();
$table->string('email', 50)->index();

Sau khi thay đổi thành công, bạn có thể chạy quá trình di chuyển.
Lưu ý: trước tiên, bạn phải xóa (nếu có) bảng người dùng , bảng password_resets khỏi cơ sở dữ liệu và xóa người dùng và các mục nhập password_resets khỏi bảng di chuyển.

3 hữu ích 0 bình luận chia sẻ
3

Schema::defaultStringLength(191);sẽ xác định độ dài của tất cả các chuỗi 191 theo mặc định, điều này có thể làm hỏng cơ sở dữ liệu của bạn. Bạn không được đi theo hướng này.

Chỉ cần xác định độ dài của bất kỳ cột cụ thể nào trong lớp di chuyển cơ sở dữ liệu. Ví dụ: tôi đang xác định "tên", "tên người dùng" và "email" trong CreateUsersTablelớp như dưới đây:

public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 191);
            $table->string('username', 30)->unique();
            $table->string('email', 191)->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }
3 hữu ích 1 bình luận chia sẻ
3

Tôi vừa sửa đổi dòng sau trong userspassword_resetstệp di chuyển.

Cũ : $table->string('email')->unique();

Mới : $table->string('email', 128)->unique();

3 hữu ích 0 bình luận chia sẻ
2

Điều này là phổ biến vì Laravel 5.4 đã thay đổi bộ mã cơ sở dữ liệu mặc định được đặt thành utf8mb4. Những gì bạn phải làm là: chỉnh sửa App \ Providers.php của bạn bằng cách đặt mã này trước khai báo lớp

use Illuminate\Support\Facades\Schema;

Ngoài ra, thêm điều này vào chức năng 'khởi động' Schema::defaultStringLength(191);

2 hữu ích 0 bình luận chia sẻ
2

Giải pháp được đề xuất là kích hoạt innodb_large_prefixtùy chọn của MySQL để bạn không gặp phải các vấn đề tiếp theo. Và đây là cách để làm điều đó:

Mở my.initệp cấu hình MySQL và thêm các dòng dưới đây vào [mysqld]dòng như thế này.

[mysqld]
innodb_file_format = Barracuda
innodb_large_prefix = 1
innodb_file_per_table = ON

Sau đó, lưu các thay đổi của bạn và khởi động lại dịch vụ MySQL của bạn.

Khôi phục nếu bạn cần và sau đó chạy lại quá trình di chuyển của bạn.


Chỉ trong trường hợp sự cố của bạn vẫn tiếp diễn, hãy chuyển đến tệp cấu hình cơ sở dữ liệu của bạn và đặt

'engine' => null, đến 'engine' => 'innodb row_format=dynamic'

Hy vọng nó giúp!

2 hữu ích 0 bình luận chia sẻ
2

Nếu bạn chưa có bất kỳ dữ liệu nào được gán cho cơ sở dữ liệu của mình, hãy làm như sau:

  1. Truy cập app / Providers / AppServiceProvide.php và thêm

sử dụng Illuminate \ Support \ ServiceProvider;

và bên trong của phương thức boot ();

Lược đồ :: defaultStringLength (191);

  1. Bây giờ xóa các bản ghi trong cơ sở dữ liệu của bạn, bảng người dùng cho ví dụ.

  2. chạy sau

php Artian config: cache

nghệ nhân php di cư

2 hữu ích 1 bình luận chia sẻ
1

Để tránh thay đổi bất kỳ điều gì trong mã của bạn , chỉ cần cập nhật máy chủ MySQL của bạn lên ít nhất 5.7.7

Tham khảo thông tin này để biết thêm thông tin: https://laravel-news.com/laravel-5-4-key-too-long-error

1 hữu ích 1 bình luận chia sẻ
1

Tôi nghĩ rằng buộc StringLenght đến 191 là một ý tưởng thực sự tồi. Vì vậy, tôi điều tra để hiểu những gì đang xảy ra.

Tôi nhận thấy rằng lỗi thông báo này:

SQLSTATE [42000]: Lỗi cú pháp hoặc vi phạm quyền truy cập: 1071 Khóa được chỉ định quá dài; độ dài khóa tối đa là 767 byte

Bắt đầu hiển thị sau khi tôi cập nhật phiên bản MySQL của mình. Vì vậy, tôi đã kiểm tra các bảng bằng PHPMyAdmin và tôi nhận thấy rằng tất cả các bảng mới được tạo đều có đối chiếu utf8mb4_unicode_ci thay vì utf8_unicode_ci cho các bảng cũ.

Trong tệp cấu hình học thuyết của tôi, tôi nhận thấy rằng bộ mã được đặt thành utf8mb4, nhưng tất cả các bảng trước đó của tôi đã được tạo trong utf8, vì vậy tôi đoán đây là một số phép thuật cập nhật để nó bắt đầu hoạt động trên utf8mb4.

Bây giờ, cách khắc phục dễ dàng là thay đổi bộ ký tự dòng trong tệp cấu hình ORM của bạn. Sau đó, để thả các bảng bằng utf8mb4_unicode_ci nếu bạn đang ở chế độ nhà phát triển hoặc sửa bộ ký tự nếu bạn không thể thả chúng.

Đối với Symfony 4

thay đổi charset: utf8mb4 thành charset: utf8 trong config / pack / doct.yaml

Bây giờ những cuộc di cư theo học thuyết của tôi đang hoạt động tốt trở lại.

1 hữu ích 0 bình luận chia sẻ
1

trước tiên hãy xóa tất cả các bảng của cơ sở dữ liệu trong localhost

Thay đổi thuộc tính cơ sở dữ liệu mặc định của Laravel (utf8mb4) trong tệp config / database.php thành:

'charset' => 'utf8', 'collation' => 'utf8_unicode_ci',

sau đó Thay đổi thuộc tính cơ sở dữ liệu cục bộ của tôi utf8_unicode_ci. Di chuyển nghệ nhân php nó là ok.

1 hữu ích 0 bình luận chia sẻ
1

hoạt động như một sự quyến rũ đối với tôi!

Thêm cái này vào config / database.php

'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

thay vì

'engine' => 'null',
1 hữu ích 0 bình luận chia sẻ
0

Đối với bất kỳ ai khác có thể gặp phải vấn đề này, vấn đề của tôi là tôi đang tạo một cột kiểu stringvà cố gắng tạo nó ->unsigned()khi tôi muốn nó là một số nguyên.

0 hữu ích 0 bình luận chia sẻ
0

Cách tiếp cận mà công việc ở đây đã vượt qua thông số thứ hai với tên khóa (một tên ngắn gọn):

$table->string('my_field_name')->unique(null,'key_name');
0 hữu ích 0 bình luận chia sẻ
0

Tôi đã gặp lỗi này mặc dù tôi đã mắc phải (thực sự là tôi đã có) Schema :: defaultStringLength (191); trong tệp AppServiceProvider.php của tôi.

Lý do là vì tôi đã cố gắng đặt giá trị chuỗi trong một trong những lần di chuyển của mình thành giá trị cao hơn 191:

Schema::create('order_items', function (Blueprint $table) {
    $table->primary(['order_id', 'product_id', 'attributes']);
    $table->unsignedBigInteger('order_id');
    $table->unsignedBigInteger('product_id');
    $table->string('attributes', 1000); // This line right here
    $table->timestamps();
});

Xóa 1000 hoặc đặt nó thành 191 đã giải quyết được vấn đề của tôi.

0 hữu ích 0 bình luận chia sẻ
0

Việc thay đổi loại máy chủ cơ sở dữ liệu cục bộ của tôi từ "mariadb" thành "mysql" đã sửa lỗi này cho tôi mà không cần phải chỉnh sửa bất kỳ tệp Laravel nào.

Tôi đã làm theo hướng dẫn này để thay đổi loại máy chủ db của mình: https://odan.github.io/2017/08/13/xampp-replacing-mariadb-with-mysql.html

0 hữu ích 0 bình luận chia sẻ
0

Bạn có thể đặt độ dài chuỗi của trường được lập chỉ mục như sau:

  $table->string('email', 200)->unique();
0 hữu ích 0 bình luận chia sẻ
0

Đối với Lumen:

Thêm vào .envtệp

DB_ENGINE=InnoDB
0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ mysql laravel pdo laravel-5 laravel-5.4 , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading