Các mảng có được truyền theo giá trị trong php không?

$num_array = [1000 => "một nghìn", 100 => "một trăm", 600 => "sáu trăm"];

$ordered["special"] = "Tuyệt. “;

$num_array = [1000 => "một nghìn", 100 => "một trăm", 600 => "sáu trăm"];

$num_array[] = "Phần tử mới trong \$num_array";

$animals_array = ["gấu trúc"=>"rất dễ thương", "thằn lằn"=>"dễ thương", "gián"=>"không dễ thương lắm"];

array_push($animals_array, "Phần tử mới trong \$animals_array");

Đoạn mã trên in 1, 2, 3, 4, 5. Điều này là do mảng được truyền dưới dạng tham chiếu, nghĩa là hàm (pass_by_reference) không thao tác với bản sao của biến được truyền, mà là chính biến thực tế

Để biến một biến được truyền theo tham chiếu, nó phải được khai báo bằng dấu và (&) ở trước trong phần khai báo của hàm

Trong thời gian dài nhất, tôi đã xem xét rằng các Đối tượng được "chuyển qua tham chiếu" trong PHP và mặc dù điều đó có thể không đúng về mặt kỹ thuật, nhưng đó là một sự đơn giản hóa hữu ích thực hiện công việc trong hầu hết các trường hợp. Vì vậy, nếu bạn đọc tiêu đề và nghĩ "Vâng, đúng là như vậy" thì không cần phải hoảng sợ, mọi thứ có lẽ vẫn ổn, điều đó không có nghĩa là các ứng dụng của bạn sẽ bất ngờ thổi vào mặt bạn. Mặt khác, nếu bạn nghĩ "tham chiếu là cái quái gì vậy?", thì bạn sẽ có một vài điều bất ngờ ẩn giấu trong cơ sở mã của mình và bạn chắc chắn đang ở đúng nơi

Vì vậy, hãy tìm hiểu sâu hơn về các tham chiếu, sau đó chúng ta sẽ xem các đối tượng được truyền qua tham chiếu trông như thế nào, và sau đó tại sao nó thực sự phức tạp hơn thế một chút


Tài liệu tham khảo trong PHP

Tài liệu PHP về các tham chiếu cho chúng ta biết rằng các tham chiếu là "bí danh", có nghĩa là chúng ta có thể nói với PHP rằng chúng ta muốn hai biến trỏ đến cùng một dữ liệu (tài liệu cũng cho chúng ta biết rằng mặc dù chúng không phải là con trỏ, điều này không đặc biệt hữu ích . Ký hiệu để tạo tham chiếu là &

Vì vậy, chúng tôi có thể làm

$a = 'foo'; // $a contains 'foo'
$b = &$a;   // $b is now a reference, or an alias of $a

$b = 'bar' // We're actually changing the content of $a
echo $a    // displays 'bar' (because we just changed the value)
echo $b    // displays 'bar' (because it's still a reference to $a)

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Đây là một điểm kỳ lạ nhỏ, nhưng thực sự không hữu ích trong mã hàng ngày của bạn. Bây giờ, điều hữu ích hơn rất nhiều là bạn có thể chuyển các biến bằng cách tham chiếu đến một hàm, để hàm đó thực sự có thể sửa đổi nội dung của biến bên ngoài phạm vi của chính nó

Điều này được thực hiện bằng cách nối thêm & trước tham số trong khai báo hàm

/**
 * Decrements a number if it's > 0.
 * Returns true if it was decremented, false if it was already 0 or negative;
 */
function decrement(int &$a) {
    if ($a > 0) {
        $a = $a - 1;
        return true;
    }
    return false;
}

$timeLeft = 10;
$wasModified = decrement($timeLeft);

echo $timeLeft; // will output 9

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Như bạn có thể thấy, điều này cho phép chúng tôi trả lại một cái gì đó và sửa đổi trực tiếp những gì đã được chuyển đến chức năng. Điều này đặc biệt được sử dụng trong hàm preg_match() sẽ trả về giá trị true nếu nội dung khớp và chấp nhận tham số $m sẽ được sửa đổi để chứa nội dung khớp. Đây là một tính năng hữu ích, nhưng nó cũng có thể là nguyên nhân gây ra các lỗi khó theo dõi, vì vậy bạn nên thận trọng khi sử dụng tính năng này

Đây là một hình ảnh động đẹp từ bài đăng này minh họa nó một cách độc đáo

Các mảng có được truyền theo giá trị trong php không?


Tại sao các đối tượng trông giống như chúng được chuyển qua tham chiếu

Có thể bạn đã đọc ở đâu đó rằng các đối tượng luôn được truyền qua tham chiếu trong PHP. Và nó chắc chắn trông giống như nó

Lấy ví dụ đơn giản này

function doStuff($object) {
    $object->data = 'newValue';
}

$object = (object)['data' => 'value'];
doStuff($object);

echo $object->data; // displays 'newValue'

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Như bạn có thể thấy, không có & trong phần khai báo hàm của chúng ta, nhưng giờ đây

/**
 * Decrements a number if it's > 0.
 * Returns true if it was decremented, false if it was already 0 or negative;
 */
function decrement(int &$a) {
    if ($a > 0) {
        $a = $a - 1;
        return true;
    }
    return false;
}

$timeLeft = 10;
$wasModified = decrement($timeLeft);

echo $timeLeft; // will output 9
1 lại chứa 'newValue' thay vì 'value'. Vì vậy, chức năng đã sửa đổi đối tượng, mà thực sự trông rất giống như nó đã được chuyển qua tham chiếu

Vấn đề với việc sửa đổi các đối tượng

Đây là một ví dụ cụ thể hơn, đó là nguồn gốc của lỗi trong cơ sở mã sản xuất thực tế. Giả sử chúng tôi muốn gửi cho người dùng một email có biên lai cho tháng tới và chúng tôi muốn tiêu đề hiển thị đầu và cuối kỳ theo cách thân thiện với người dùng như "Từ Thứ Năm ngày 1 tháng Bảy đến Thứ Bảy Tháng Bảy . Chúng tôi sẽ tạo một số chức năng để bắt đầu và kết thúc tháng tương ứng với ngày hiện tại và định dạng chúng, sau đó sử dụng kết quả trong một chuỗi (hoặc thực tế hơn là một mẫu). Nó sẽ trông như thế này

function getFirstDay($date) {
    return $date->modify('first day of this month')->format('l F j');
}

function getLastDay($date) {
    return $date->modify('last day of this month')->format('l F j');
}

$today = new DateTime('2022-07-15');
$firstday = getFirstDay($today);
$lastDay = getLastDay($today);

$emailTitle = "Your receipt for the period from $firstday to $lastDay";
$emailFooter = "Sent on " .  $today->format("l F j");

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Tiêu đề sẽ nói
"Biên nhận của bạn trong khoảng thời gian từ Thứ Năm ngày 1 tháng 7 đến Thứ Bảy ngày 31 tháng 7", đó là điều chúng tôi muốn, nhưng chân trang ghi "Đã gửi vào Thứ Bảy ngày 31 tháng 7", đó chắc chắn không phải là điều chúng tôi muốn. Vấn đề là $today đã thực sự bị sửa đổi bởi các hàm khi chúng tôi gọi ->modify() vào ngày, vì vậy ngay khi chúng tôi sử dụng hàm này vào một ngày, chúng tôi sẽ mất giá trị ban đầu của ngày đó mãi mãi

Có hai cách xung quanh điều này

1- sao chép đối tượng trước khi làm việc với nó

function getFirstDay($today) {
    $date = clone $today;
    return $date->modify('first day of this month')
        ->format('l F j');
}

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

2- Sử dụng thư viện như Carbon 2 cung cấp Đối tượng bất biến, về cơ bản là các đối tượng mà mọi phương thức luôn trả về một bản sao thay vì sửa đổi đối tượng hiện tại


Tại sao các đối tượng không thực sự được chuyển qua tham chiếu

Vì vậy, chúng tôi đã thấy rằng có rất nhiều đối tượng giống như các đối tượng được truyền qua tham chiếu và cách tránh các sự cố tiềm ẩn, nhưng toàn bộ điểm của bài đăng này là để chỉ ra rằng chúng không phải như vậy, vì vậy đây là một vài ví dụ để làm cho nó rõ ràng

ví dụ 1. các đối tượng trong một mảng

Giả sử một lớp Người dùng lấy tên của người dùng trong hàm tạo và gán nó cho một thuộc tính tên. Bây giờ hãy xem điều gì sẽ xảy ra nếu chúng ta đặt một số người dùng đó vào một mảng và chuyển nó cho một hàm đặt tên viết hoa cho mỗi phần tử

Class User
{
    public function __construct(public string $name){}
}

function capitalizeNames(array $users) {
    foreach ($users as $user) {
        $user->name = strtoupper($user->name);
    }
}

$users = [
    new User('John'),
    new User('Jack'),
];

capitalizeNames($users);

echo json_encode($users); // [{"name":"JOHN"},{"name":"JACK"}]

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Như bạn có thể thấy, mỗi người dùng trong mảng đã được sửa đổi bởi hàm capitalizeNames()

Chúng tôi không sử dụng tham chiếu, chúng tôi chưa bao giờ chuyển một đối tượng cho hàm vì chúng tôi đã chuyển một mảng (theo giá trị) nên chúng tôi có thể nghĩ rằng mình an toàn. Và mọi đối tượng bên trong mảng đã được sửa đổi

ví dụ 2. Gán một đối tượng cho một biến khác

Bây giờ hãy xem điều gì sẽ xảy ra nếu chúng ta gán một thể hiện của một đối tượng cho một biến mới


$user1 = new User('name');
$user2 = $user1;

$user1->name = 'Jack';

echo $user1->name; // Jack
echo $user2->name; // Jack

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Vì vậy, về cơ bản, ngay sau khi chúng tôi thực hiện

/**
 * Decrements a number if it's > 0.
 * Returns true if it was decremented, false if it was already 0 or negative;
 */
function decrement(int &$a) {
    if ($a > 0) {
        $a = $a - 1;
        return true;
    }
    return false;
}

$timeLeft = 10;
$wasModified = decrement($timeLeft);

echo $timeLeft; // will output 9
2, chúng tôi có thể sử dụng cả hai thay thế cho nhau và thay đổi cái này sẽ thay đổi cái kia

Vậy chuyện gì đã xảy ra ?

Vấn đề là một biến không bao giờ "chứa" một đối tượng. Bất cứ khi nào chúng ta gọi

/**
 * Decrements a number if it's > 0.
 * Returns true if it was decremented, false if it was already 0 or negative;
 */
function decrement(int &$a) {
    if ($a > 0) {
        $a = $a - 1;
        return true;
    }
    return false;
}

$timeLeft = 10;
$wasModified = decrement($timeLeft);

echo $timeLeft; // will output 9
3, PHP sẽ trả về một handle, đây là một tham chiếu. một con trỏ. vâng, hãy gắn bó với tay cầm. Tay cầm đó về cơ bản là một số xác định đối tượng
Bạn thực sự có thể thấy số nhận dạng đối tượng này khi sử dụng
/**
 * Decrements a number if it's > 0.
 * Returns true if it was decremented, false if it was already 0 or negative;
 */
function decrement(int &$a) {
    if ($a > 0) {
        $a = $a - 1;
        return true;
    }
    return false;
}

$timeLeft = 10;
$wasModified = decrement($timeLeft);

echo $timeLeft; // will output 9
4, đó là số có dấu # phía trước khi kết xuất một đối tượng, ở đây với
/**
 * Decrements a number if it's > 0.
 * Returns true if it was decremented, false if it was already 0 or negative;
 */
function decrement(int &$a) {
    if ($a > 0) {
        $a = $a - 1;
        return true;
    }
    return false;
}

$timeLeft = 10;
$wasModified = decrement($timeLeft);

echo $timeLeft; // will output 9
5 từ ví dụ trước của chúng ta, chúng ta có thể thấy rằng cả hai đều là cùng một đối tượng vì chúng có cùng một tay cầm

Các mảng có được truyền theo giá trị trong php không?

Bạn cũng có thể sử dụng

/**
 * Decrements a number if it's > 0.
 * Returns true if it was decremented, false if it was already 0 or negative;
 */
function decrement(int &$a) {
    if ($a > 0) {
        $a = $a - 1;
        return true;
    }
    return false;
}

$timeLeft = 10;
$wasModified = decrement($timeLeft);

echo $timeLeft; // will output 9
6 để trả về số nhận dạng đối tượng này

Bất cứ khi nào chúng ta sao chép một biến đối tượng, chuyển nó vào một hàm hoặc đặt nó vào một mảng, chúng ta sẽ không chuyển hoặc sao chép thể hiện của đối tượng, mà chỉ xử lý của nó. Vì vậy, một đối tượng sẽ chỉ tồn tại một lần trừ khi chúng ta sử dụng

/**
 * Decrements a number if it's > 0.
 * Returns true if it was decremented, false if it was already 0 or negative;
 */
function decrement(int &$a) {
    if ($a > 0) {
        $a = $a - 1;
        return true;
    }
    return false;
}

$timeLeft = 10;
$wasModified = decrement($timeLeft);

echo $timeLeft; // will output 9
7. Giống như một đối tượng trong cuộc sống thực


Phần kết luận

Mặc dù có thể hữu ích khi nghĩ rằng các đối tượng được truyền theo tham chiếu, nhưng tôi nghĩ tốt hơn hết là bạn nên nhớ rằng khi bạn tạo một đối tượng thì chỉ có một thể hiện tồn tại và thứ bạn đang sử dụng không phải là đối tượng mà chỉ đơn giản là một tay cầm.

Tôi hy vọng điều này có thể hữu ích cho ai đó. Ngoài ra, tôi không có bất kỳ nền tảng nào về C và chỉ hiểu mơ hồ về cách điều này thực sự được triển khai trong lõi PHP. Vì vậy, nếu có điều gì đó sai rõ ràng ở trên, vui lòng cho tôi biết trong phần bình luận

Các mảng có được truyền theo giá trị không?

Giống như tất cả các đối tượng Java, mảng được truyền theo giá trị . nhưng giá trị là tham chiếu đến mảng. Chuyển thực theo tham chiếu liên quan đến việc chuyển địa chỉ của một biến để biến đó có thể được cập nhật. Đây KHÔNG phải là điều xảy ra khi bạn chuyển một mảng trong Java.

Làm cách nào để chuyển mảng trong PHP?

Chuyển mảng PHP sang JavaScript rất dễ dàng bằng cách sử dụng Ký hiệu đối tượng JavaScript (JSON) . Phương pháp 1. Sử dụng hàm json_encode(). Hàm json_encode() được sử dụng để trả về biểu diễn JSON của một giá trị hoặc mảng. Hàm có thể lấy cả mảng một chiều và nhiều chiều.

Mảng có chứa giá trị PHP không?

Hàm in_array() là một hàm có sẵn trong PHP dùng để kiểm tra xem một giá trị đã cho có tồn tại trong một mảng hay không . Nó trả về TRUE nếu tìm thấy giá trị đã cho trong mảng đã cho và FALSE nếu không.

Chúng ta có thể chuyển mảng làm đối số trong PHP không?

Bạn có thể truyền một mảng làm đối số . Nó được sao chép theo giá trị (hoặc COW'd, về cơ bản có nghĩa giống với bạn), vì vậy bạn có thể array_pop() (và tương tự) tất cả những gì bạn thích trên đó và sẽ không ảnh hưởng đến bất kỳ thứ gì bên ngoài. hàm sendemail($id, $userid){ //. }