2011-12-05 47 views
7

Tôi có một tập lệnh mà tôi đã viết trong khi trả lời các nhận xét, nhưng nó chỉ là một luồng duy nhất. Tôi muốn nó được đa luồng, nhưng chỉ như vậy một người dùng có thể trả lời một bình luận, không phải như vậy một người dùng có thể trả lời một bình luận của một bình luận. Vì vậy, các chủ đề sẽ chỉ có hai sâu.Multi Threaded Comments PHP?

Hiện tại tôi lưu trữ comment_id đối với số user_id trong cơ sở dữ liệu của mình.

Cách duy nhất tôi có thể nghĩ là thực hiện các nhận xét đa luồng, là có trường parent trong bảng nhận xét. Nhưng nếu tôi làm điều này thì khi tôi chọn các bình luận với PHP, tôi sẽ phải thực hiện một lệnh SELECT khác để chọn các chú thích con (nếu có) cho mỗi chú thích. Có vẻ như rất nhiều công việc trên cơ sở dữ liệu.

Có cách nào tốt hơn. Bất kỳ ý tưởng về điều này? Hoặc hướng dẫn?

+0

Nếu không đọc câu hỏi cho bối cảnh, câu hỏi hoàn toàn không có ý nghĩa vì "đa luồng" và "nhận xét" thường đề cập đến một số khác. – Davy8

Trả lời

16

Có ba (bốn) khả năng thay thế:

  1. Một recursive query để chọn tất cả ý kiến ​​dựa trên id cha mẹ của họ. Điều này được hỗ trợ bởi nhiều sản phẩm cơ sở dữ liệu và cú pháp phụ thuộc vào loại cơ sở dữ liệu. Kiểm tra tài liệu để biết thêm thông tin (tìm kiếm 'đệ quy').

  2. Nếu bạn lưu bài viết id trong mỗi nhận xét phụ, bạn chỉ có thể chọn tất cả nhận xét với id bài viết trong một truy vấn chọn thông thường. Bạn có thể sử dụng id cha mẹ để hiển thị đúng các ý kiến ​​trên trang theo nhận xét cha mẹ phải:

    SELECT * FROM comments WHERE article_id = :article_id 
    
  3. Nếu bạn chỉ cần hai cấp độ của ý kiến, bạn có thể sử dụng một mở rộng nơi để bao gồm cả hai cấp độ đầu tiên và thứ hai comments mức:

    SELECT * FROM comments 
    WHERE parent_id = :article_id 
    OR parent_id IN (SELECT id FROM comments WHERE parent_id = :article_id) 
    
  4. Nó cũng có thể sử dụng union all để kết hợp hai truy vấn có các cột giống nhau, nhưng kể từ khi tôi giả định rằng tất cả các dữ liệu từ cùng một bảng, có lẽ không cần cho nó (thấy mở rộng mệnh đề where trên):

    SELECT * FROM comments WHERE parent_id = :article_id 
    UNION ALL 
    SELECT * FROM comments WHERE parent_id IN 
        (SELECT id FROM comments WHERE parent_id = :article_id) 
    

Cá nhân, tôi sẽ đi cho phương án 2 vì nó là đơn giản (không có SQL cấu trúc kỳ lạ bắt buộc), hiệu quả (1 truy vấn) và linh hoạt (hỗ trợ càng nhiều mức độ nhận xét tùy thích).

+0

Xin vui lòng bạn có thể thả một ví dụ thực tế về mã php và kết quả ... tôi đã đọc câu trả lời của bạn hơn và hơn trong nhiều giờ và tôi không thể thực sự tìm cách mã nó ... cảm ơn – jcobhams

+0

@VyrenMedia Tôi giả sử bạn đang cố gắng thực hiện tùy chọn 2. Tôi sẽ không cung cấp cho bạn một hướng dẫn thực hiện đầy đủ, nhưng có lẽ điều này sẽ giúp: http://blog.tcs.de/creating-trees-from-sql-queries-in-javascript/. Nếu bạn cần thêm trợ giúp, hãy đăng câu hỏi SO mới. –

1

Truy vấn này có thể làm việc cho bạn (tôi không biết cấu trúc của bạn, vì vậy tôi đoán vào nó):

SELECT * FROM comments a 
LEFT JOIN comments b ON a.comment_id = b.parent_coment_id 
LEFT JOIN comments c ON b.comment_id = c.parent_coment_id 
WHERE a.comment_id <> b.comment_id 
     AND a.comment_id <> c.comment_id 
     AND b.comment_id <> c.comment_id; 
+0

Điều này có vẻ đúng. Tôi giả định LEFT JOIN thứ hai và thứ hai VÀ là để tham gia bình luận cấp 3? –

+0

@SeanHJenkins yep^_^dùng thử. Nó sẽ hoạt động :-D – Neal

+0

Lưu ý rằng điều này làm việc cho tối đa 3 mức nhận xét và không lọc trên bài viết thực tế mà tôi cho rằng sẽ hữu ích. –

2

1 truy vấn là đủ cho điều này, bạn chỉ cần lặp dữ liệu và lưu trữ nó vào một mảng chính xác, sau đó bạn lặp mảng và hiển thị các chú thích.

+0

Đó là nhiều hơn một truy vấn! Đây là cách tôi exaplain tôi đã có thể làm điều đó anyway, tôi đang tìm cách tốt hơn –

+0

Bạn đã nói về việc sử dụng một tuyên bố SELECT và tôi đã cho bạn một cách tốt hơn. – JanL

+0

Không có giải pháp nào của bạn vẫn sẽ sử dụng nhiều CHỌN. Cảm ơn câu trả lời. –

2

Đây là cách sử dụng phổ biến cho dữ liệu phân cấp hoặc cấu trúc cây. Tôi đã viết một câu trả lời phổ biến cho câu hỏi Stack Overflow này: What is the most efficient/elegant way to parse a flat table into a tree?

Tôi cũng đã viết một bản trình bày mô tả các lựa chọn thay thế cho dữ liệu có cấu trúc cây: Models for Hierarchical Data with SQL and PHP.

Một giải pháp khác không được bao gồm trong bản trình bày của tôi là cách Slashdot thực hiện nhận xét luồng. Họ sử dụng một cột parent như bạn làm, vì vậy mỗi nhận xét tham chiếu đến nhận xét mà nó trả lời. Nhưng sau đó họ cũng bao gồm một cột root để mỗi nhận xét biết bài đăng thuộc về nó. Có rất hiếm khi nhiều hơn một vài trăm bình luận trên một bài đăng nhất định, và thường bạn muốn nhận được toàn bộ cây bình luận cho một bài đăng được bắt đầu ở đầu thread bình luận:

SELECT * FROM comments WHERE root = 1234; 

Sau đó, khi bạn lấy ý kiến, bạn có thể viết mã PHP để xử lý chúng thành các mảng của mảng theo các cột parent (đây là câu trả lời của câu trả lời @ JanL). Tôi đã đăng mã để làm điều này trong câu trả lời của tôi cho một câu hỏi Stack Overflow khác, Convert flat array to the multi-dimentional.

+0

Tôi biết đây là một bài đăng cũ nhưng tôi đã lang thang với phương pháp bạn đã mô tả cách thức này sẽ hoạt động nếu bạn có bài đăng có nhận xét trong hàng nghìn, rõ ràng bạn sẽ không chọn tất cả các hàng, tuy nhiên nếu bạn đã sử dụng LIMIT, bạn sẽ mất cấu trúc cây ... là có một cách xung quanh này? ... Loại liên quan J – jon

+0

@jon, bạn có thể sử dụng LIMIT nhưng đặt hàng theo ngày của bình luận. Vì vậy, bạn sẽ nhận được các chuỗi nhận xét cũ nhất. Sau đó, nếu người dùng muốn mở rộng các chủ đề mà họ có thể yêu cầu, nhưng theo mặc định họ sẽ chỉ thấy một tập hợp con của cuộc thảo luận. Nếu bạn muốn biết thêm chi tiết, hãy tải xuống nguồn Slashdot và xem chúng hoạt động như thế nào. http://slashcode.com/ –

+0

cảm ơn phản hồi của bạn, tuy nhiên nếu tôi hiểu bạn chính xác, điều này sẽ chỉ hiển thị chuỗi nhận xét gốc và sau đó nếu họ muốn mở rộng chuỗi nhận xét để xem bất kỳ câu trả lời nào bạn sẽ chọn trên chuỗi nhận xét đó, tuy nhiên tôi thực sự muốn hiển thị các câu trả lời của các chuỗi nhận xét trong truy vấn đầu tiên, nhưng cũng có thể LIMIT? .. là có thể sử dụng phân cấp kề? .. cảm ơn J. – jon