Khắc phục lỗi PHP Fatal error: Uncaught TypeError: Argument 1 passed to processData() must be of type int, string given (Lỗi không khớp gợi ý kiểu dữ liệu PHP 8)

intermediate🐘 PHP2026-03-26

Tóm tắt: Khắc phục nhanh

Lỗi TypeError này chỉ ra rằng mã PHP của bạn đang cố gắng truyền một string vào một hàm mà hàm đó rõ ràng mong đợi một int (hoặc một kiểu dữ liệu vô hướng khác như bool hoặc float).

Để giải quyết vấn đề này, bạn thường có hai phương pháp chính:

  • Ép kiểu dữ liệu đầu vào: Đảm bảo biến bạn đang truyền có kiểu dữ liệu như mong đợi. Ví dụ, ép kiểu một chuỗi thành số nguyên bằng cách sử dụng (int)$myString trước khi gọi hàm. Đây thường là giải pháp đơn giản và chính xác nhất.
  • Điều chỉnh gợi ý kiểu dữ liệu của hàm: Nếu hàm luôn được thiết kế để chấp nhận một chuỗi, hãy cập nhật khai báo kiểu của nó. Thay đổi int thành string trong chữ ký hàm.

Nhanh chóng xác định dòng có vấn đề (ví dụ: /var/www/html/app.php on line 42) và hàm (processData()). Sau đó, áp dụng một trong các cách khắc phục được mô tả ở trên để giải quyết vấn đề ngay lập tức.

Sự cố: Lỗi Uncaught TypeError trong PHP 8

Hãy tưởng tượng là 2 giờ sáng, và một dịch vụ quan trọng bất ngờ gặp sự cố. Bạn kiểm tra nhật ký và phát hiện một thông báo đáng báo động:

Fatal error: Uncaught TypeError: Argument 1 passed to processData() must be of type int, string given, called in /var/www/html/app.php on line 42

Đây không phải là lỗi tràn bộ nhớ (memory leak) hay lỗi thiếu file. Thay vào đó, đây là một TypeError, đặc biệt nhấn mạnh sự không khớp kiểu dữ liệu. Lỗi này cho biết kiểu dữ liệu được cung cấp cho một đối số của hàm không khớp với kiểu dữ liệu mong đợi. PHP 8, theo mặc định, thực thi kiểm tra kiểu vô hướng (scalar type checks) nghiêm ngặt hơn so với các phiên bản trước, làm cho những loại lỗi này trở nên phổ biến hơn nếu cơ sở mã của bạn không hoàn toàn an toàn về kiểu dữ liệu (type-safe).

Tái tạo lỗi

Hãy xem một ví dụ mã đơn giản có thể gây ra lỗi này:

<?php

declare(strict_types=1); // Không bắt buộc nghiêm ngặt cho lỗi NÀY trong PHP 8 (do chuyển đổi mất dữ liệu), nhưng nó nhấn mạnh sự nghiêm ngặt.

function processData(int $data): string
{
    return "Processed: " . ($data * 2);
}

$userInput = "123abc"; // Đây là một chuỗi, nhưng chúng ta muốn xử lý nó như một số.

// Dòng này sẽ gây ra TypeError
echo processData($userInput); // app.php on line 42

?>

Khi script này thực thi, PHP kiểm tra gợi ý kiểu dữ liệu cho $data trong hàm processData(). Nó mong đợi một int, nhưng lại nhận được một string (cụ thể là "123abc"). Vì PHP 8 nghiêm ngặt hơn về các chuyển đổi kiểu dữ liệu có thể dẫn đến mất dữ liệu, nó ngay lập tức ném ra một TypeError và dừng việc thực thi script.

Phân tích nguyên nhân gốc rễ

Về bản chất, vấn đề này bắt nguồn từ việc vi phạm hợp đồng đã định nghĩa của một hàm. Trong PHP 7, các gợi ý kiểu vô hướng (scalar type hints) thường được thực thi một cách lỏng lẻo trừ khi bạn sử dụng rõ ràng declare(strict_types=1);. PHP 8 đã giới thiệu một thay đổi đáng kể.

Bắt đầu từ PHP 8, các khai báo kiểu vô hướng được thực thi nghiêm ngặt hơn. Điều này áp dụng theo mặc định cho các hàm nội bộ và cho các hàm do người dùng định nghĩa khi giá trị không thể được ép kiểu mà không làm mất dữ liệu (như chuyển đổi một chuỗi không phải số thành số nguyên). Nếu phạm vi gọi hàm cũng bật declare(strict_types=1);, thì tất cả các kiểu không khớp, ngay cả những kiểu không mất dữ liệu, cũng sẽ ném ra một TypeError.

Hãy cùng phân tích thông báo lỗi:

  • Fatal error: Uncaught TypeError: Script đã dừng đột ngột do không khớp kiểu dữ liệu.
  • Argument 1 passed to processData(): Vấn đề nằm ở đối số đầu tiên được cung cấp cho hàm processData.
  • must be of type int, string given: Hàm mong đợi một số nguyên, nhưng thay vào đó lại nhận được một chuỗi.
  • called in /var/www/html/app.php on line 42: Điều này chỉ ra chính xác file và số dòng nơi xảy ra lời gọi hàm có vấn đề.

Về cơ bản, hàm processData của bạn được khai báo với gợi ý kiểu int $data, báo hiệu cho PHP rằng giá trị được truyền cho $data phải là một số nguyên. Tuy nhiên, mã của bạn ở dòng 42 cố gắng truyền một chuỗi ("123abc") cho tham số này, dẫn đến lỗi nghiêm trọng.

Các chiến lược giải quyết

Bạn có một số lựa chọn để giải quyết TypeError này, và lựa chọn tốt nhất phụ thuộc vào hành vi dự kiến của mã của bạn.

1. Ép kiểu dữ liệu đầu vào (Phổ biến & Khuyến nghị nhất)

Nếu processData() thực sự được thiết kế để chỉ hoạt động với số nguyên, thì mục tiêu chính của bạn là đảm bảo nó nhận được một int. Kịch bản này thường xuyên phát sinh khi xử lý đầu vào của người dùng, phân tích phản hồi API hoặc xử lý dữ liệu từ các nguồn bên ngoài có thể cung cấp các giá trị số dưới dạng chuỗi.

Ví dụ khắc phục: Ép kiểu sang int

<?php

declare(strict_types=1);

function processData(int $data): string
{
    return "Processed: " . ($data * 2);
}

$userInput = "123abc"; // Vẫn là một chuỗi

// Tùy chọn A: Ép kiểu rõ ràng thành int. "123abc" trở thành 123.
$processedInput = (int)$userInput;
echo processData($processedInput) . "\n";

// Tùy chọn B: Sử dụng intval(). Hiệu ứng tương tự, cũng chuyển đổi thành 123.
// echo processData(intval($userInput)) . "\n";

// Tùy chọn C: Nếu bạn mong đợi một chuỗi chỉ chứa số và muốn xác thực nó
if (is_numeric($userInput)) {
    echo processData((int)$userInput) . "\n";
} else {
    echo "Error: Invalid numeric input provided. Expected a number, got '$userInput'." . "\n";
}

?>

Giải thích: Ép kiểu (int) cố gắng chuyển đổi chuỗi thành số nguyên. Đối với một chuỗi như "123abc", nó sẽ chuyển đổi thành 123, loại bỏ bất kỳ ký tự không phải số nào sau các số ban đầu. Nếu chuỗi không chứa ký tự số nào ở đầu (ví dụ: "hello world"), nó sẽ chuyển đổi thành 0. Luôn lưu ý hành vi chuyển đổi này và xác thực kỹ lưỡng đầu vào của người dùng nếu tính toàn vẹn của dữ liệu là rất quan trọng.

2. Điều chỉnh gợi ý kiểu dữ liệu của hàm (Nếu gợi ý không chính xác)

Có lẽ hàm processData() của bạn luôn được thiết kế để xử lý chuỗi, hoặc thậm chí là một hỗn hợp các kiểu dữ liệu. Trong những trường hợp như vậy, gợi ý kiểu dữ liệu hiện có đơn giản là sai và cần được sửa chữa.

Ví dụ khắc phục: Thay đổi int thành string

<?php

declare(strict_types=1);

// Hàm hiện tại mong đợi một chuỗi một cách chính xác
function processData(string $data): string
{
    // Bây giờ bạn sẽ cần xử lý dữ liệu chuỗi một cách thích hợp trong hàm.
    // Điều này có thể bao gồm xác thực hoặc chuyển đổi nếu vẫn cần xử lý số.
    if (is_numeric($data)) {
        return "Processed numeric string: " . ((int)$data * 2) . "\n";
    } else {
        return "Processed non-numeric string: " . $data . "\n";
    }
}

$userInput = "123abc";
echo processData($userInput);

$anotherInput = "hello world";
echo processData($anotherInput);

?>

Giải thích: Chiến lược này sửa đổi hợp đồng của hàm để phản ánh chính xác dữ liệu mà nó được thiết kế để nhận. Đây là cách khắc phục lý tưởng nếu gợi ý kiểu dữ liệu ban đầu là một lỗi, hoặc nếu các yêu cầu đối với hàm đã thay đổi.

3. Cho phép nhiều kiểu dữ liệu (PHP 8 Union Types)

Nếu hàm của bạn thực sự cần chấp nhận nhiều hơn một kiểu vô hướng – chẳng hạn, nó có thể xử lý một cách linh hoạt cả int hoặc string – thì Union Types của PHP 8 cung cấp một giải pháp rõ ràng và biểu cảm.

Ví dụ khắc phục: Sử dụng Union Types (int|string)

<?php

declare(strict_types=1);

// Hàm hiện tại chấp nhận cả int hoặc string
function processData(int|string $data): string
{
    if (is_int($data)) {
        return "Processed int: " . ($data * 2) . "\n";
    } elseif (is_string($data)) {
        // Xử lý dữ liệu chuỗi, có thể chuyển đổi nếu nó là số
        if (is_numeric($data)) {
            return "Processed numeric string: " . ((int)$data * 2) . "\n";
        } else {
            return "Processed non-numeric string: " . $data . "\n";
        }
    }
    // Dòng này lý tưởng là không nên đạt được với một gợi ý kiểu union được định nghĩa tốt.
    return "Invalid input type encountered." . "\n"; 
}

$userInputString = "123abc";
echo processData($userInputString);

$userInputInt = 456;
echo processData($userInputInt);

?>

Giải thích: Khai báo int|string thông báo cho PHP rằng cả int hoặc string đều là đối số chấp nhận được. Bên trong hàm, bạn sẽ sử dụng các kiểm tra điều kiện như is_int(), is_string() hoặc instanceof để xác định kiểu thực tế và xử lý nó tương ứng.

4. Cho phép giá trị Null (Nullable Types)

Trong các trường hợp mà đối số đôi khi có thể bị bỏ qua hoặc truyền rõ ràng là null, bạn có thể làm cho gợi ý kiểu dữ liệu có thể chấp nhận null. Điều này hữu ích cho các tham số tùy chọn.

Ví dụ khắc phục: Sử dụng kiểu Nullable (?int)

<?php

declare(strict_types=1);

// Hàm có thể chấp nhận một int hoặc null
function processData(?int $data): string
{
    if ($data === null) {
        return "No data provided.\n";
    }
    return "Processed: " . ($data * 2) . "\n";
}

$userInput = null;
echo processData($userInput);

$validInput = 123;
echo processData($validInput);

// Điều này sẽ luôn gây ra TypeError, vì "123abc" không phải là int cũng không phải null,
// và không thể được ép kiểu thành int mà không mất dữ liệu ngay cả khi không có strict_types=1.
// echo processData("123abc"); 

?>

Giải thích: Tiền tố ? trước kiểu dữ liệu (ví dụ: ?int) cho phép đối số có thể là kiểu đã khai báo (trong trường hợp này là int) hoặc null. Điều này cung cấp sự linh hoạt cho dữ liệu tùy chọn.

Các bước xác minh

Sau khi bạn đã áp dụng một trong các cách khắc phục được khuyến nghị, hãy làm theo các bước sau để đảm bảo mọi thứ hoạt động chính xác:

  • Xóa PHP Opcache: Nếu môi trường của bạn sử dụng opcache (như OPcache), hãy đảm bảo rằng nó đã được xóa. Ngoài ra, hãy khởi động lại dịch vụ PHP-FPM hoặc máy chủ web của bạn (ví dụ: sudo systemctl restart php8.2-fpm) để tải mã đã cập nhật.
  • Chạy script: Thực thi lại script app.php của bạn. Nếu nó là một phần của ứng dụng web, hãy làm mới trang liên quan trong trình duyệt của bạn.
  • Kiểm tra lỗi: Xác nhận rằng thông báo Fatal error: Uncaught TypeError không còn xuất hiện. Kiểm tra nhật ký lỗi máy chủ web của bạn (ví dụ: nhật ký lỗi Apache, nhật ký lỗi Nginx) và nhật ký PHP-FPM.
  • Xác minh đầu ra: Cuối cùng, đảm bảo rằng ứng dụng của bạn hoạt động như mong đợi. Xác nhận rằng nó tạo ra đầu ra chính xác hoặc thực hiện các hành động dự định mà không gây ra bất kỳ lỗi mới nào.

Đọc thêm

Related Error Notes