Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

माता-पिता बच्चे में पदानुक्रमित डेटा प्रिंट करें अनियंत्रित सूची PHP?

बैकएंड से फ़्रंट-एंड की ओर काम करना ठीक है...

आप अपनी PHP स्क्रिप्ट से एक गैर-पुनरावर्ती संग्रहीत प्रक्रिया (sproc) को कॉल कर सकते हैं जो आपके लिए संदेश पदानुक्रम उत्पन्न करता है। इस दृष्टिकोण का लाभ यह है कि आपको केवल एक एकल . बनाने की आवश्यकता है php से अपने डेटाबेस में कॉल करें, जबकि यदि आप इनलाइन SQL का उपयोग करते हैं तो आप जितने स्तर हैं (कम से कम) उतने कॉल कर रहे होंगे। एक और सलाह यह है कि चूंकि यह एक गैर रिकर्सिव स्पोक है, यह बेहद प्रदर्शन करने वाला है और यह आपके PHP कोड को भी अच्छा और साफ रखता है। अंत में, और मुझे रिकॉर्ड के लिए यह कहना है, कि संग्रहीत प्रक्रियाओं को कॉल करना किसी भी अन्य विधि की तुलना में अधिक सुरक्षित और अधिक कुशल है क्योंकि आपको केवल अपने ऐप उपयोगकर्ता को अनुमतियां निष्पादित करने की आवश्यकता है और संग्रहीत प्रक्रियाओं के लिए डेटाबेस की तुलना में कम राउंड ट्रिप की आवश्यकता होती है। पैरामीटरयुक्त प्रश्नों सहित अन्य विधियाँ जिनके लिए एकल क्वेरी के लिए कम से कम 2 कॉल की आवश्यकता होती है (डीबी में क्वेरी टेम्प्लेट सेट करने के लिए 1, पैरा को पॉप्युलेट करने के लिए दूसरा)

तो यहां बताया गया है कि आप MySQL कमांड लाइन से संग्रहीत कार्यविधि को कैसे कॉल करेंगे।

call message_hier(1);

और यह परिणामसेट बनाता है।

msg_id  emp_msg    parent_msg_id    parent_msg   depth
======  =======    =============    ==========   =====
1        msg 1            NULL          NULL          0
2        msg 1-1             1          msg 1         1
3        msg 1-2             1          msg 1         1
4        msg 1-2-1           3          msg 1-2       2
5        msg 1-2-2           3          msg 1-2       2
6        msg 1-2-2-1         5          msg 1-2-2     3
7        msg 1-2-2-1-1       6          msg 1-2-2-1   4
8        msg 1-2-2-1-2       6          msg 1-2-2-1   4

ठीक है, तो अब हमारे पास एक पूर्ण या आंशिक संदेश ट्री लाने की क्षमता है, बस हमारे स्पोक को कॉल करके जो भी शुरुआती नोड की आवश्यकता है, लेकिन हम परिणामसेट के साथ क्या करने जा रहे हैं ??

खैर इस उदाहरण में मैंने तय किया है कि हम इसके साथ एक एक्सएमएल डोम जेनरेट करने जा रहे हैं, फिर मुझे केवल एक्सएमएल को ट्रांसफॉर्म (एक्सएसएलटी) करना है और हमारे पास नेस्टेड मैसेज वेब पेज होगा।

PHP स्क्रिप्ट

PHP स्क्रिप्ट काफी सरल है, यह सिर्फ डेटाबेस से जुड़ती है, स्पोक को कॉल करती है और एक्सएमएल डोम बनाने के लिए परिणाम को लूप करती है। याद रखें कि हम केवल एक बार db में कॉल कर रहे हैं।

<?php

// i am using the resultset to build an XML DOM but you can do whatever you like with it !

header("Content-type: text/xml");

$conn = new mysqli("localhost", "foo_dbo", "pass", "foo_db", 3306);

// one non-recursive db call to get the message tree !

$result = $conn->query(sprintf("call message_hier(%d)", 1));

$xml = new DomDocument;
$xpath = new DOMXpath($xml);

$msgs = $xml->createElement("messages");
$xml->appendChild($msgs);

// loop and build the DOM

while($row = $result->fetch_assoc()){

    $msg = $xml->createElement("message");
    foreach($row as $col => $val) $msg->setAttribute($col, $val); 

    if(is_null($row["parent_msg_id"])){
        $msgs->appendChild($msg);
    }
    else{
        $qry = sprintf("//*[@msg_id = '%d']", $row["parent_msg_id"]);
        $parent = $xpath->query($qry)->item(0);
        if(!is_null($parent)) $parent->appendChild($msg);
    }
}
$result->close();
$conn->close();

echo $xml->saveXML();
?>

XML आउटपुट

यह एक्सएमएल है जो PHP स्क्रिप्ट उत्पन्न करता है। यदि आप इस XML को किसी फ़ाइल में सहेजते हैं और इसे अपने ब्राउज़र में खोलते हैं तो आप स्तरों को विस्तृत और संक्षिप्त करने में सक्षम होंगे।

<messages>
    <message msg_id="1" emp_msg="msg 1" parent_msg_id="" parent_msg="" depth="0">
        <message msg_id="2" emp_msg="msg 1-1" parent_msg_id="1" parent_msg="msg 1" depth="1"/>
        <message msg_id="3" emp_msg="msg 1-2" parent_msg_id="1" parent_msg="msg 1" depth="1">
            <message msg_id="4" emp_msg="msg 1-2-1" parent_msg_id="3" parent_msg="msg 1-2" depth="2"/>
            <message msg_id="5" emp_msg="msg 1-2-2" parent_msg_id="3" parent_msg="msg 1-2" depth="2">
                <message msg_id="6" emp_msg="msg 1-2-2-1" parent_msg_id="5" parent_msg="msg 1-2-2" depth="3">
                    <message msg_id="7" emp_msg="msg 1-2-2-1-1" parent_msg_id="6" parent_msg="msg 1-2-2-1" depth="4"/>
                    <message msg_id="8" emp_msg="msg 1-2-2-1-2" parent_msg_id="6" parent_msg="msg 1-2-2-1" depth="4"/>
                </message>
            </message>
        </message>
    </message>
</messages>

यदि आप चाहें तो अब आप एक्सएमएल डोम बनाने और वेब पेज प्रस्तुत करने के लिए एक्सएसएल का उपयोग कर सकते हैं और शायद परिणाम को लूप कर सकते हैं और सीधे संदेश प्रस्तुत कर सकते हैं। मैंने अपने उदाहरण को यथासंभव व्यापक और सूचनात्मक बनाने के लिए बस इस पद्धति को चुना है।

MySQL स्क्रिप्ट

यह टेबल, स्पॉक्स और टेस्ट डेटा सहित पूरी स्क्रिप्ट है।

drop table if exists messages;
create table messages
(
msg_id smallint unsigned not null auto_increment primary key,
msg varchar(255) not null,
parent_msg_id smallint unsigned null,
key (parent_msg_id)
)
engine = innodb;

insert into messages (msg, parent_msg_id) values
('msg 1',null), 
  ('msg 1-1',1), 
  ('msg 1-2',1), 
      ('msg 1-2-1',3), 
      ('msg 1-2-2',3), 
         ('msg 1-2-2-1',5), 
            ('msg 1-2-2-1-1',6), 
            ('msg 1-2-2-1-2',6);


drop procedure if exists message_hier;

delimiter #

create procedure message_hier
(
in p_msg_id smallint unsigned
)
begin

declare v_done tinyint unsigned default(0);
declare v_dpth smallint unsigned default(0);

create temporary table hier(
 parent_msg_id smallint unsigned, 
 msg_id smallint unsigned, 
 depth smallint unsigned
)engine = memory;

insert into hier select parent_msg_id, msg_id, v_dpth from messages where msg_id = p_msg_id;

/* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */

create temporary table tmp engine=memory select * from hier;

while not v_done do

    if exists( select 1 from messages e inner join hier on e.parent_msg_id = hier.msg_id and hier.depth = v_dpth) then

        insert into hier select e.parent_msg_id, e.msg_id, v_dpth + 1 
            from messages e inner join tmp on e.parent_msg_id = tmp.msg_id and tmp.depth = v_dpth;

        set v_dpth = v_dpth + 1;            

        truncate table tmp;
        insert into tmp select * from hier where depth = v_dpth;

    else
        set v_done = 1;
    end if;

end while;

select 
 m.msg_id,
 m.msg as emp_msg,
 p.msg_id as parent_msg_id,
 p.msg as parent_msg,
 hier.depth
from 
 hier
inner join messages m on hier.msg_id = m.msg_id
left outer join messages p on hier.parent_msg_id = p.msg_id;

drop temporary table if exists hier;
drop temporary table if exists tmp;

end #

delimiter ;

-- call this sproc from your php

call message_hier(1);

इस उत्तर का पूरा स्रोत यहां पाया जा सकता है:http://pastie.org/1336407 . जैसा कि आपने पहले ही नोट कर लिया होगा कि मैंने XSLT को छोड़ दिया है लेकिन आप शायद XML रूट पर नहीं जाएंगे और यदि आप ऐसा करते हैं तो वेब पर उदाहरणों के ढेर हैं।

आशा है कि आपको यह मददगार लगा होगा :)

संपादित करें:

थोड़ा और डेटा जोड़ा गया ताकि आपके पास एक से अधिक रूट संदेश (msg_ids 1,9,14) हों।

truncate table messages;

insert into messages (msg, parent_msg_id) values
('msg 1',null), -- msg_id = 1
  ('msg 1-1',1), 
  ('msg 1-2',1), 
      ('msg 1-2-1',3), 
      ('msg 1-2-2',3), 
         ('msg 1-2-2-1',5), 
            ('msg 1-2-2-1-1',6), 
            ('msg 1-2-2-1-2',6),
('msg 2',null), -- msg_id = 9
    ('msg 2-1',9), 
    ('msg 2-2',9), 
    ('msg 2-3',9), 
        ('msg 2-3-1',12),
('msg 3',null); -- msg_id = 14

अब यदि आप केवल उन संदेशों को प्राप्त करना चाहते हैं जो रूट नोड (प्रारंभिक संदेश) के लिए विशिष्ट हैं, तो आप रूट की प्रारंभिक msg_id में गुजरने वाली मूल संग्रहीत प्रक्रिया को कॉल कर सकते हैं जिसकी आपको आवश्यकता है। ऊपर दिए गए नए डेटा का उपयोग करना msg_ids 1,9,14 होगा।

call message_hier(1); -- returns all messages belonging to msg_id = 1

call message_hier(9); -- returns all messages belonging to msg_id = 9

call message_hier(14); -- returns all messages belonging to msg_id = 14

आप अपनी पसंद के किसी भी msg_id में पास कर सकते हैं, इसलिए यदि मुझे msg 1-2-2-1 के नीचे के सभी संदेश चाहिए तो आप msg_id =6:

में पास होंगे
call message_hier(6); -- returns all messages belonging to msg_id = 6

हालाँकि, यदि आप सभी संदेशों को सभी जड़ों के लिए चाहते हैं तो आप इस नए स्पोक को कॉल कर सकते हैं जिसे मैंने इस प्रकार बनाया है:

call message_hier_all(); -- returns all messages for all roots.

इसके साथ मुख्य समस्या यह है कि जैसे-जैसे आपकी संदेश तालिका बढ़ती है, यह बहुत सारे डेटा लौटाने वाली है, इसलिए मैं एक अधिक विशिष्ट स्पोक पर ध्यान केंद्रित कर रहा था जो केवल किसी दिए गए रूट नोड के लिए संदेश प्राप्त करता था या msg_id शुरू करता था।

मैं नया स्पोक कोड पोस्ट नहीं करूंगा क्योंकि यह वस्तुतः मूल जैसा ही है लेकिन आप यहां सभी संशोधन पा सकते हैं:http:// pastie.org/1339618

अंतिम परिवर्तन जो आपको करने की आवश्यकता होगी वह php स्क्रिप्ट में है जो अब नए sproc को निम्नानुसार कॉल करेगा:

//$result = $conn->query(sprintf("call message_hier(%d)", 1)); // recommended call

$result = $conn->query("call message_hier_all()"); // new sproc call

आशा है कि यह मदद करता है :)

call message_hier_all();


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. WAMP स्थानीय नेटवर्क 403 निषिद्ध पर एक्सेस नहीं कर सकता

  2. MySQL में कई स्कीमाओं के बीच क्रॉस जॉइन करें। विशेषाधिकार और प्रदर्शन

  3. MySQL त्रुटि 1449:एक निश्चित के रूप में निर्दिष्ट उपयोगकर्ता मौजूद नहीं है

  4. MySQL में दशमलव विभाजक बदलें

  5. त्रुटि तालिका में परिवर्तन, बाधा विदेशी कुंजी जोड़ने में त्रुटि हो रही है एक बच्चे की पंक्ति को जोड़ या अपडेट नहीं कर सकता