Bộ câu hỏi phỏng vấn PHP phần 5

Chính xác thì các liên kết tĩnh trễ trong PHP là gì?


Về cơ bản, thực tế là từ khóa self không tuân theo các quy tắc kế thừa giống nhau. self luôn phụ thuộc vào lớp mà nó được sử dụng. Điều này có nghĩa là nếu bạn tạo một phương thức trong một lớp cha và gọi nó từ một lớp con, thì self sẽ không tham chiếu đến con như bạn mong đợi. Liên kết tĩnh trễ (late static binding) giới thiệu một cách sử dụng mới cho từ khóa static, giải quyết sự thiếu sót cụ thể trên. Khi bạn sử dụng static, nó đại diện cho lớp mà bạn sử dụng nó lần đầu tiên, tức là, nó 'liên kết' với lớp trong runtime.

class Car {
   public static
   function run() {
      return static::getName();
   }

   private static
   function getName() {
      return 'Car';
   }
}
class Toyota extends Car {
   public static
   function getName() {
      return 'Toyota';
   }
}

echo Car::run(); // Output: Car
echo Toyota::run(); // Output: Toyota

Phương pháp nào là tốt nhất để hợp nhất hai đối tượng PHP?


Vấn đề:

//We have this:
$objectA->a;
$objectA->b;
$objectB->c;
$objectB->d;

//We want the easiest way to get:
$objectC->a;
$objectC->b;
$objectC->c;
$objectC->d;

Giải pháp:

$obj_merged = (object) array_merge((array) $obj1, (array) $obj2);

Bạn cũng có thể sử dụng array_merge_recursive để sao chép sâu (deep copy). Một cách nữa để làm điều đó là:

foreach($objectA as $k => $v) $objectB->$k = $v;

Cách này nhanh hơn cách đầu tiên trong các phiên bản PHP < 7 (ước tính nhanh hơn 50%). Nhưng trong PHP >= 7, cách đầu tiên nhanh hơn 400%.

So sánh MySQLi hoặc PDO?


  • PDO là tiêu chuẩn, hầu hết các nhà phát triển sử dụng PDO.
  • Di chuyển một ứng dụng từ cơ sở dữ liệu này sang cơ sở dữ liệu khác không phải là rất phổ biến, nhưng sớm hay muộn bạn có thể thấy mình đang làm việc trên một dự án khác bằng cách sử dụng RDBMS khác biệt. Nếu bạn đang làm việc với PDO thì sẽ có ít điều để học hơn vào thời điểm đó.
  • Một điều thực sự thú vị với PDO là bạn có thể tìm nạp dữ liệu, tự động đưa nó vào một đối tượng.
  • PDO có một số tính năng giúp tăng SQL injection.
  • Về tốc độ thực thi MySQLi thắng, nhưng trừ khi bạn có một trình bao bọc tốt sử dụng MySQLi, các chức năng của nó xử lý các câu lệnh đã chuẩn bị sẵn rất tệ. Các lệch insert - gần như bằng nhau, các lệch select - MySQLi nhanh hơn 2,5% cho các câu lệnh không chuẩn bị trước / nhanh hơn 6,7% cho các câu lệnh đã chuẩn bị sẵn.

Toán tử <=> dùng để làm gì?


Toán tử <=> (Spaceship operator) cung cấp so sánh kết hợp trong đó nó sẽ:

Trả về 0 nếu giá trị ở hai bên bằng nhau. Trả về 1 nếu giá trị bên trái lớn hơn. Trả về -1 nếu giá trị ở bên phải lớn hơn.

//Comparing Integers
echo 1 <=> 1; //outputs 0
echo 3 <=> 4; //outputs -1
echo 4 <=> 3; //outputs 1

//String Comparison
echo "x" <=> "x"; // 0
echo "x" <=> "y"; //-1
echo "y" <=> "x"; //1

Sự khác biệt quan trọng giữa việc sử dụng trait và interface là gì?


Một trait về cơ bản là việc PHP thực hiện một mixin, và thực sự là một tập hợp các phương thức mở rộng có thể được thêm vào bất kỳ lớp nào thông qua việc bổ sung trait. Sau đó các phương thức này trở thành một phần của quá trình thực thi lớp đó, mà không cần sử dụng tính năng kế thừa. Một interface định nghĩa một tập hợp các phương thức mà lớp thực thi phải thực hiện.

trait myTrait {
   function foo() { return "Foo!"; }
   function bar() { return "Bar!"; }
}

class MyClass extends SomeBaseClass {
   use myTrait; // Inclusion of the trait myTrait
}

PHP, giống như nhiều ngôn ngữ khác, sử dụng mô hình kế thừa đơn - nghĩa là một lớp có thể dẫn xuất từ nhiều interface, nhưng chỉ kế thừa từ một lớp. Tuy nhiên, một lớp PHP có thể bao gồm nhiều trait - điều này cho phép lập trình viên có thẻ include các phần có thể tái sử dụng - giống như việc có thể kế thừa từ nhiều lớp cơ sở.

Làm thế nào để biến error thành exception trong PHP?


Vấn đề: tôi cần bắt giữ một số warning được đưa ra từ một số hàm gốc của php và sau đó xử lý chúng. try / catch không hoạt động vì warning không phải là exception. Bạn có thể giúp biến error thành exception trong PHP không?

Giải pháp: bạn có thể sử dụng set_error_handler() và lớp ErrorException để biến tất cả các php error thành exception.

set_error_handler(function($errno, $errstr, $errfile, $errline, $errcontext) {
   // error was suppressed with the @-operator
   if (0 === error_reporting()) {
      return false;
   }

   throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

try {
   dns_get_record();
} catch (ErrorException $e) {
   // ...
}

Điều quan trọng cần lưu ý khi sử dụng trình xử lý error của riêng bạn là nó sẽ bỏ qua cài đặt error_reporting và chuyển tất cả các error (notice, warning, v.v.) cho trình xử lý error của bạn. Bạn có thể đặt đối số thứ hai trên set_error_handler() để xác định loại error nào bạn muốn nhận hoặc truy cập cài đặt hiện tại bằng cách sử dụng ... = error_reporting() bên trong trình xử lý error.

Sử dùng cái nào là tốt hơn khi giải phóng bộ nhớ trong PHP: unset() hay $var = null?


  • unset() thực hiện đúng những gì tên của nó nói - unset a variable. Nó không buộc giải phóng bộ nhớ ngay lập tức. Bộ thu gom rác của PHP sẽ thực hiện điều đó khi nó thấy phù hợp - theo chủ ý, ngay khi các chu kỳ CPU đó không cần thiết, hoặc muộn nhất là trước khi tập lệnh hết bộ nhớ.
  • Nếu bạn đang làm $whatever = null; thì bạn đang viết lại dữ liệu của biến. Bạn có thể được giải phóng / thu hẹp bộ nhớ nhanh hơn, nhưng nó có thể lấy cắp chu kỳ CPU từ mã thực sự cần chúng sớm hơn, dẫn đến thời gian thực thi tổng thể lâu hơn.
  • unset($a) cũng xóa $a khỏi bảng ký hiệu (symbol table) và có vẻ như $a = null nhanh hơn một chút so với bản đối chiếu unset() của nó: việc cập nhật một mục trong bảng ký hiệu dường như nhanh hơn việc xóa nó.

yield có nghĩa là gì trong PHP?


Vấn đề: giải thích đoạn mã bên dưới và yield có chức năng gì:

function a($items) {
   foreach ($items as $item) {
      yield $item + 1;
   }
}

Giải pháp: Từ khóa yield trả về dữ liệu từ một generator function. Một generator function thực sự là một cách thức nhỏ gọn và hiệu quả hơn để viết một Iterator. Nó cho phép bạn xác định một hàm sẽ tính toán và trả về các giá trị trong khi bạn đang lặp nó. Vì vậy, function trong câu hỏi trên gần giống như function này mà không có yield:

function b($items) {
   $result = [];
   foreach ($items as $item) {
      $result[] = $item + 1;
   }
   return $result;
}

Chỉ với một sự khác biệt rằng a() trả về một generator và b() chỉ là một mảng đơn giản. Bạn có thể lặp trên cả hai. Phiên bản generator của hàm không phân bổ một mảng đầy đủ và do đó ít đòi hỏi bộ nhớ hơn. Generator có thể được sử dụng để giải quyết các giới hạn bộ nhớ. Bởi vì generator chỉ tính toán các giá trị thu được của chúng theo yêu cầu, chúng rất hữu ích để biểu diễn các trình tự tốn kém hoặc không thể tính toán cùng một lúc.

$$ có nghĩa là gì?


Một cú pháp như $$variable được gọi là Variable Variable. $ bên trong chuyển một biến thành một chuỗi và cái $ bên ngoài phân giải một biến theo chuỗi đó.

$real_variable = 'test';
$name = 'real_variable';
echo $$name;

// output: test

PHP có phân luồng không?


Standard PHP không cung cấp bất kỳ đa luồng nào nhưng có một phần mở rộng (đang thử nghiệm) thực sự có - pthreads. Điều tốt nhất tiếp theo là chỉ cần một tập lệnh thực thi một tập lệnh khác thông qua CLI, nhưng điều đó hơi thô sơ. Tùy thuộc vào những gì bạn đang cố gắng thực hiện và mức độ phức tạp của nó, đây có thể là một tùy chọn cho bạn.

PHP là đơn luồng hay đa luồng?


Về bản chất, PHP không phải là một đơn luồng. Tuy nhiên, trường hợp cài đặt phổ biến nhất của PHP trên hệ thống unix là thiết lập một đơn luồng, cũng như cài đặt Apache phổ biến nhất là nginx không có kiến trúc dựa trên luồng nào. Trong thiết lập Windows phổ biến nhất và một số thiết lập unix nâng cao hơn, PHP có thể và vận hành nhiều luồng thông dịch trong một quy trình. PHP như một trình thông dịch đã hỗ trợ đa luồng kể từ năm 2000.

Giải thích thứ tự ưu tiên cho trait trong PHP?


trait bị ghi đè nếu phương thức có cùng tên được định nghĩa trong lớp sử dụng trait. Thứ tự ưu tiên là các thành viên từ lớp hiện tại ghi đè các phương thức Trait, đến lượt nó sẽ ghi đè các phương thức kế thừa.

class BaseClass {
   function SomeMethod() { /* Do stuff here */ }
}

interface IBase {
   function SomeMethod();
}

trait myTrait {
   function SomeMethod() { /* Do different stuff here */ }
}

class MyClass extends BaseClass implements IBase {
   use myTrait;

   function SomeMethod() { /* Do a third thing */ }
}

Khi tạo một instant của MyClass ở trên, những điều sau sẽ xảy ra:

  • IBase interface yêu cầu cung cấp một hàm không tham số gọi là SomeMethod().
  • Lớp cơ sở BaseClass cung cấp việc triển khai phương thức này - đáp ứng nhu cầu.
  • trait myTrait cũng cung cấp một hàm không tham số được gọi là SomeMethod(), được ưu tiên hơn so với SomeMethod() của BaseClass.
  • Lớp MyClass cung cấp phiên bản SomeMethod() của riêng nó - được ưu tiên hơn phiên bản của trait.

Các câu lệnh được chuẩn bị sẵn trong PDO có đủ để ngăn chặn SQL injection không?


Vấn đề: giả sử chúng ta có đoạn mã như sau:

$dbh = new PDO("blahblah");

$stmt = $dbh->prepare('SELECT * FROM users where username = :username');
$stmt->execute( array(':username' => $_REQUEST['username']) );

Đó có thực sự là tất cả những gì chúng ta cần làm để tránh SQL injections không? Nó có thực sự dễ dàng như vậy không?

Giải pháp: câu trả lời ngắn gọn là KHÔNG, các câu lệnh được chuẩn bị sẵn (prepared statements) trong PDO không bảo vệ bạn khỏi tất cả các cuộc tấn công SQL-Injection có thể xảy ra. Ví dụ:

$pdo->query('SET NAMES gbk');
$var = "\xbf\x27 OR 1=1 /_";
$query = 'SELECT _ FROM test WHERE name = ? LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute(array($var));

Query sẽ trả về nhiều hơn 1 hàng:

SELECT \* FROM test WHERE name = '' OR 1=1 // LIMIT 1

$$$ có nghĩa là gì trong PHP?


Một cú pháp như $$variable được gọi là Variable Variable.

$real_variable = 'test';
$name = 'real_variable'; // variable variable for real variable
$name_of_name = 'name'; // variable variable for variable variable

echo $name_of_name . '<br />';
echo $$name_of_name . '<br />';
echo $$$name_of_name . '<br />';

Và đây là kết quả:

name
real_variable
test
Avatar Techmely Team
VIẾT BỞI

Techmely Team