PHP lấy phần tử HTML

Tạo khuôn mẫu làm cho trang web hoạt động. Tổng hợp dữ liệu và cấu trúc thành nội dung. Đó là siêu năng lực thú vị nhất của chúng tôi với tư cách là nhà phát triển — lấy một số dữ liệu, sau đó làm cho dữ liệu đó hoạt động cho chúng tôi, trong bất kỳ bản trình bày nào chúng tôi cần. Mảng đối tượng có thể trở thành bảng, danh sách thẻ, biểu đồ hoặc bất kỳ thứ gì chúng tôi cho là hữu ích nhất cho người dùng. Cho dù dữ liệu là các bài đăng trên blog của riêng chúng tôi trong các tệp Markdown hay tỷ giá hối đoái toàn cầu theo phút, đánh dấu và kết quả UX tùy thuộc vào chúng tôi với tư cách là nhà phát triển giao diện người dùng

PHP là một ngôn ngữ tuyệt vời để tạo khuôn mẫu, cung cấp nhiều cách để hợp nhất dữ liệu với đánh dấu. Hãy đi vào một ví dụ về việc sử dụng dữ liệu để tạo biểu mẫu HTML trong bài đăng này

Bạn muốn bẩn tay ngay lập tức?

Trong PHP, chúng ta có thể biến nội dòng thành chuỗi ký tự sử dụng dấu ngoặc kép, vì vậy nếu chúng ta có biến

$p = $dom->createElement('p');
0, chúng ta có thể viết
$p = $dom->createElement('p');
1 và nó sẽ in ra kết quả mong muốn là
$p = $dom->createElement('p');
2. Để tạo khuôn mẫu phức tạp hơn, chúng ta luôn có thể nối các chuỗi, như.
$p = $dom->createElement('p');
3

Đối với học sinh cũ, có

$p = $dom->createElement('p');
4. Đối với các chuỗi nhiều dòng, bạn có thể sử dụng Heredoc (một chuỗi bắt đầu như
$p = $dom->createElement('p');
5). Và, cuối cùng nhưng không kém phần quan trọng, chúng ta có thể rắc các biến PHP bên trong HTML, như
$p = $dom->createElement('p');
6

Tất cả các tùy chọn này đều tuyệt vời, nhưng mọi thứ có thể trở nên lộn xộn khi cần nhiều logic nội tuyến. Nếu chúng ta cần xây dựng các chuỗi HTML phức hợp, chẳng hạn như một biểu mẫu hoặc điều hướng, độ phức tạp có thể là vô hạn, vì các phần tử HTML có thể lồng vào nhau

Những gì chúng tôi đang cố gắng tránh

Trước khi tiếp tục và làm điều mình muốn, bạn nên dành một phút để xem xét điều mình không muốn làm. Hãy xem xét đoạn văn rút gọn sau đây từ thánh thư của WordPress Core,

$p = $dom->createElement('p');
7, câu 170-270

________số 8_______

Để xây dựng một điều hướng

$p = $dom->createElement('p');
8 trong chức năng này, chúng tôi sử dụng một biến,
$p = $dom->createElement('p');
9, là một chuỗi rất dài mà chúng tôi tiếp tục thêm nội dung vào đó. Loại mã này có thứ tự hoạt động rất cụ thể và giới hạn. Nếu chúng tôi muốn thêm một thuộc tính vào
$p->setAttribute('class', 'headline');
0, chúng tôi phải có quyền truy cập vào
$p->setAttribute('class', 'headline');
1 trước khi điều này chạy. Và nếu chúng tôi muốn tùy chọn lồng một
$p->setAttribute('class', 'headline');
2 hoặc một
$p->setAttribute('class', 'headline');
3 bên trong
$p->setAttribute('class', 'headline');
0, chúng tôi cần tạo một khối mã hoàn toàn mới sẽ thay thế phần giữa của dòng 7 bằng khoảng 4-10 dòng mới, tùy thuộc vào chính xác những gì chúng tôi muốn . Bây giờ, hãy tưởng tượng bạn cần tùy ý thêm
$p->setAttribute('class', 'headline');
2 , sau đó tùy ý thêm
$p->setAttribute('class', 'headline');
3, bên trong
$p->setAttribute('class', 'headline');
2 hoặc sau nó. Chỉ riêng điều đó đã là ba câu lệnh
$p->setAttribute('class', 'headline');
8, làm cho mã thậm chí còn khó đọc hơn

Rất dễ để kết thúc với mì spaghetti dạng chuỗi khi nối như thế này, điều này thật thú vị khi nói rằng thật khó để duy trì

Bản chất của vấn đề là khi chúng ta cố gắng suy luận về các phần tử HTML, chúng ta không nghĩ về các chuỗi. Nó chỉ xảy ra rằng các chuỗi là những gì trình duyệt sử dụng và các kết quả đầu ra của PHP. Nhưng mô hình tinh thần của chúng ta giống DOM hơn - các phần tử được sắp xếp thành một cây và mỗi nút có nhiều thuộc tính, thuộc tính và con tiềm năng

Sẽ không tuyệt sao nếu có một cách có cấu trúc, biểu cảm để xây dựng cái cây của chúng ta?

Đi vào…

Lớp $p->setAttribute('class', 'headline');9

PHP 5 đã thêm mô-đun

$span = $dom->createElement('span', 'This is a headline'); // The 2nd argument populates the element's textContent $p->appendChild($span);
0 vào danh sách các loại Không được nhập quá nghiêm ngặt™. Điểm vào chính của nó là lớp
$p->setAttribute('class', 'headline');
9, tương tự như JavaScript của API Web API một cách có chủ ý
$span = $dom->createElement('span', 'This is a headline'); // The 2nd argument populates the element's textContent $p->appendChild($span);
0. Nếu bạn đã từng sử dụng
$span = $dom->createElement('span', 'This is a headline'); // The 2nd argument populates the element's textContent $p->appendChild($span);
3 hoặc, đối với những người trong chúng ta ở một độ tuổi nhất định, cú pháp
$span = $dom->createElement('span', 'This is a headline'); // The 2nd argument populates the element's textContent $p->appendChild($span);
4 của jQuery, thì điều này có thể sẽ cảm thấy khá quen thuộc

Chúng tôi bắt đầu bằng cách khởi tạo một

$p->setAttribute('class', 'headline');
9 mới

$dom = new DOMDocument();

Bây giờ chúng ta có thể thêm một

$span = $dom->createElement('span', 'This is a headline'); // The 2nd argument populates the element's textContent $p->appendChild($span);
6 vào nó

$p = $dom->createElement('p');

Chuỗi

$span = $dom->createElement('span', 'This is a headline'); // The 2nd argument populates the element's textContent $p->appendChild($span);
7 đại diện cho loại phần tử chúng tôi muốn, vì vậy các chuỗi hợp lệ khác sẽ là
$span = $dom->createElement('span', 'This is a headline'); // The 2nd argument populates the element's textContent $p->appendChild($span);
8,
$span = $dom->createElement('span', 'This is a headline'); // The 2nd argument populates the element's textContent $p->appendChild($span);
9, v.v.

Khi chúng ta có một phần tử, chúng ta có thể đặt các thuộc tính của nó

$p->setAttribute('class', 'headline');

Chúng ta có thể thêm trẻ em vào nó

$span = $dom->createElement('span', 'This is a headline'); // The 2nd argument populates the element's textContent $p->appendChild($span);

Và cuối cùng, lấy chuỗi HTML hoàn chỉnh trong một lần

$dom->appendChild($p); $htmlString = $dom->saveHTML(); echo $htmlString;

Lưu ý cách mã hóa kiểu này giữ cho mã của chúng tôi được sắp xếp theo mô hình tinh thần của chúng tôi - một tài liệu có các phần tử; . Toàn bộ phần “HTML chỉ là một chuỗi” xuất hiện ở cuối, khi cấu trúc của chúng tôi đã sẵn sàng

“Tài liệu” ở đây hơi khác so với DOM thực tế, ở chỗ nó không cần đại diện cho toàn bộ tài liệu mà chỉ là một khối HTML. Trên thực tế, nếu bạn cần tạo hai phần tử giống nhau, bạn có thể lưu chuỗi HTML bằng cách sử dụng

$dom->appendChild($p); $htmlString = $dom->saveHTML(); echo $htmlString;
0, sửa đổi “tài liệu” DOM thêm một chút, sau đó lưu chuỗi HTML mới bằng cách gọi lại
$dom->appendChild($p); $htmlString = $dom->saveHTML(); echo $htmlString;
0

Lấy dữ liệu và thiết lập cấu trúc

Giả sử chúng ta cần tạo một biểu mẫu trên máy chủ bằng cách sử dụng dữ liệu từ nhà cung cấp CRM và đánh dấu của riêng chúng ta. Phản hồi API từ CRM trông như thế này

{ "submit_button_label": "Submit now!", "fields": [ { "id": "first-name", "type": "text", "label": "First name", "required": true, "validation_message": "First name is required.", "max_length": 30 }, { "id": "category", "type": "multiple_choice", "label": "Choose all categories that apply", "required": false, "field_metadata": { "multi_select": true, "values": [ { "value": "travel", "label": "Travel" }, { "value": "marketing", "label": "Marketing" } ] } } ] }

Ví dụ này không sử dụng cấu trúc dữ liệu chính xác của bất kỳ CRM cụ thể nào, nhưng nó khá tiêu biểu

Và giả sử chúng ta muốn đánh dấu của mình trông như thế này

Choose all categories that apply

                            

Cái gì là

$dom->appendChild($p); $htmlString = $dom->saveHTML(); echo $htmlString;
2? . Miễn là đầu vào trống, nó khớp với
$dom->appendChild($p); $htmlString = $dom->saveHTML(); echo $htmlString;
3, nhưng người dùng không thấy bất kỳ văn bản giữ chỗ hiển thị nào. Chỉ là loại điều bạn có thể làm khi chúng tôi kiểm soát đánh dấu

Bây giờ chúng ta đã biết kết quả mong muốn của mình là gì, đây là kế hoạch trò chơi

  1. Nhận định nghĩa trường và nội dung khác từ API
  2. Khởi tạo một
    $p->setAttribute('class', 'headline');
    9
  3. Lặp lại các trường và xây dựng từng trường theo yêu cầu
  4. Nhận đầu ra HTML

Vì vậy, hãy bỏ qua quy trình của chúng tôi và tìm hiểu một số kỹ thuật

fields; // Start building the DOM $dom = new DOMDocument(); $form = $dom->createElement('form'); // Iterate over the fields and build each one foreach ($formFields as $field) { // TODO: Do something with the field data } // Get the HTML output $dom->appendChild($form); $htmlString = $dom->saveHTML(); echo $htmlString; }

Cho đến nay, chúng tôi đã nhận được dữ liệu và phân tích cú pháp, khởi tạo

$p->setAttribute('class', 'headline');
9 của chúng tôi và lặp lại đầu ra của nó. Chúng ta muốn làm gì cho từng lĩnh vực?

` $element = $dom->createElement('label'); $element->setAttribute('class', 'field'); // Reset input values $label = null; // Add a `` for the label if it is set if ($field->label) { $label = $dom->createElement('span', $field->label); $label->setAttribute('class', 'label'); } // Add the label to the `

Choose all categories that apply
0 để nối bên trong nó
                            

Chúng tôi cũng đang thực hiện một số mánh khóe dành riêng cho

{ "submit_button_label": "Submit now!", "fields": [ { "id": "first-name", "type": "text", "label": "First name", "required": true, "validation_message": "First name is required.", "max_length": 30 }, { "id": "category", "type": "multiple_choice", "label": "Choose all categories that apply", "required": false, "field_metadata": { "multi_select": true, "values": [ { "value": "travel", "label": "Travel" }, { "value": "marketing", "label": "Marketing" } ] } } ] }
8 tại đây. Nếu không có tùy chọn được chọn trước, chúng tôi sẽ thêm một tùy chọn giữ chỗ trống đã được chọn nhưng người dùng không thể chọn. Mục tiêu là đặt
Choose all categories that apply
2 của chúng tôi làm "trình giữ chỗ" bằng cách sử dụng CSS, nhưng kỹ thuật này có thể hữu ích cho tất cả các loại thiết kế. Bằng cách thêm nó vào
                            
Choose all categories that apply
3 trước khi thêm các tùy chọn khác, chúng tôi đảm bảo rằng đó là tùy chọn đầu tiên trong đánh dấu
                            

Bây giờ, hãy xử lý

Choose all categories that apply
4 nút radio và hộp kiểm
                            

$dom = new DOMDocument();
3

Vì vậy, trước tiên, chúng tôi xác định xem bộ trường có dành cho hộp kiểm hoặc nút radio hay không. Sau đó, chúng tôi đặt lớp vùng chứa cho phù hợp và xây dựng

Choose all categories that apply
4. Sau đó, chúng tôi lặp lại các lựa chọn có sẵn và xây dựng một
                            
Choose all categories that apply
6 cho mỗi lựa chọn với một
                            
{ "submit_button_label": "Submit now!", "fields": [ { "id": "first-name", "type": "text", "label": "First name", "required": true, "validation_message": "First name is required.", "max_length": 30 }, { "id": "category", "type": "multiple_choice", "label": "Choose all categories that apply", "required": false, "field_metadata": { "multi_select": true, "values": [ { "value": "travel", "label": "Travel" }, { "value": "marketing", "label": "Marketing" } ] } } ] }
1 và một
$dom->appendChild($p); $htmlString = $dom->saveHTML(); echo $htmlString;
6

Lưu ý rằng chúng tôi sử dụng phép nội suy chuỗi PHP thông thường để đặt lớp vùng chứa trên dòng 21 và để tạo một ID duy nhất cho mỗi lựa chọn trên dòng 30

mảnh vỡ

Một loại cuối cùng mà chúng tôi phải thêm vào hơi phức tạp hơn vẻ ngoài của nó. Nhiều biểu mẫu bao gồm các trường hướng dẫn, không phải là đầu vào mà chỉ là một số HTML mà chúng tôi cần in giữa các trường khác

Chúng ta sẽ cần tiếp cận một phương pháp

$p->setAttribute('class', 'headline');
9 khác,
fields; // Start building the DOM $dom = new DOMDocument(); $form = $dom->createElement('form'); // Iterate over the fields and build each one foreach ($formFields as $field) { // TODO: Do something with the field data } // Get the HTML output $dom->appendChild($form); $htmlString = $dom->saveHTML(); echo $htmlString; }
0. Điều này cho phép chúng tôi thêm HTML tùy ý mà không cần sử dụng cấu trúc DOM

$dom = new DOMDocument();
4

Tại thời điểm này, bạn có thể tự hỏi làm thế nào chúng tôi tìm thấy chính mình với một đối tượng được gọi là

Choose all categories that apply
3, thực sự đại diện cho một phần tử tĩnh
                            
fields; // Start building the DOM $dom = new DOMDocument(); $form = $dom->createElement('form'); // Iterate over the fields and build each one foreach ($formFields as $field) { // TODO: Do something with the field data } // Get the HTML output $dom->appendChild($form); $htmlString = $dom->saveHTML(); echo $htmlString; }
2. Mục tiêu là sử dụng một tên biến chung cho mỗi lần lặp lại vòng lặp trường, vì vậy, cuối cùng, chúng ta luôn có thể thêm nó bằng cách sử dụng
fields; // Start building the DOM $dom = new DOMDocument(); $form = $dom->createElement('form'); // Iterate over the fields and build each one foreach ($formFields as $field) { // TODO: Do something with the field data } // Get the HTML output $dom->appendChild($form); $htmlString = $dom->saveHTML(); echo $htmlString; }
3 bất kể loại trường thực tế là gì. Vì vậy, yeah, đặt tên cho mọi thứ là khó khăn

Thẩm định

API chúng tôi đang sử dụng vui lòng cung cấp thông báo xác thực riêng cho từng trường bắt buộc. Nếu có lỗi gửi, chúng tôi có thể hiển thị lỗi nội tuyến cùng với các trường, thay vì thông báo chung chung "rất tiếc, lỗi của bạn" ở dưới cùng

Hãy thêm văn bản xác thực vào từng phần tử

$dom = new DOMDocument();
5

Đó là tất cả những gì nó cần. Không cần phải loay hoay với logic loại trường — chỉ cần xây dựng một phần tử có điều kiện cho từng trường

Mang tất cả lại với nhau

Vậy điều gì sẽ xảy ra sau khi chúng ta xây dựng tất cả các phần tử trường? . Chúng ta cũng có thể tận dụng cơ hội để thêm các thuộc tính phổ biến, chẳng hạn như

fields; // Start building the DOM $dom = new DOMDocument(); $form = $dom->createElement('form'); // Iterate over the fields and build each one foreach ($formFields as $field) { // TODO: Do something with the field data } // Get the HTML output $dom->appendChild($form); $htmlString = $dom->saveHTML(); echo $htmlString; }
7. Sau đó, chúng tôi sẽ thêm nút gửi, nút này tách biệt với các trường trong API này

$dom = new DOMDocument();
6

Tại sao chúng tôi kiểm tra xem

Choose all categories that apply
3 có đúng sự thật không?
                            

Xin chào, một biểu mẫu HTML tùy chỉnh

Điểm thưởng. hàng và cột

Như bạn có thể biết, nhiều trình tạo biểu mẫu cho phép tác giả đặt hàng và cột cho các trường. Ví dụ: một hàng có thể chứa cả trường tên và họ, mỗi trường trong một cột có chiều rộng 50%. Vì vậy, làm thế nào chúng ta sẽ thực hiện điều này, bạn yêu cầu?

Phản hồi API của chúng tôi bao gồm dữ liệu lưới như thế này

$dom = new DOMDocument();
7

Chúng tôi giả định rằng việc thêm thuộc tính

` $element = $dom->createElement('label'); $element->setAttribute('class', 'field'); // Reset input values $label = null; // Add a `` for the label if it is set if ($field->label) { $label = $dom->createElement('span', $field->label); $label->setAttribute('class', 'label'); } // Add the label to the `

Choose all categories that apply
6s lồng vào nhau. Cũng giống như niềm vui, nhưng ngược lại
                            

Vì vậy, cách có cấu trúc để xử lý việc này là gì? . Trước tiên, hãy thêm theo dõi hàng trước vòng lặp của chúng ta và xây dựng một phần tử vùng chứa hàng bổ sung. Sau đó, chúng tôi sẽ đảm bảo nối từng vùng chứa

` $element = $dom->createElement('label'); $element->setAttribute('class', 'field'); // Reset input values $label = null; // Add a `` for the label if it is set if ($field->label) { $label = $dom->createElement('span', $field->label); $label->setAttribute('class', 'label'); } // Add the label to the `

Choose all categories that apply
6 khác xung quanh các trường. Hãy xây dựng một phần tử hàng mới cho mỗi hàng bên trong vòng lặp
                            

$dom = new DOMDocument();
9

Tất cả những gì chúng ta cần làm là ghi đè lên đối tượng

` $element = $dom->createElement('label'); $element->setAttribute('class', 'field'); // Reset input values $label = null; // Add a `` for the label if it is set if ($field->label) { $label = $dom->createElement('span', $field->label); $label->setAttribute('class', 'label'); } // Add the label to the `