פרק 8: להשתעשע בבסיסי נתונים - GUFE - החזית הכללית והשימושיתמעבר על GUFE: חלק 4סוס העבודה של GUFE הוא השגרה resultTable&, שמפצלת את הנתונים שמוחזרים מבסיס הנתונים, ובונה מהכל טבלת HTML. בגלל שהשגרה הזו היא די ארוכה, נעבור עליה בחלקים שנוכל לעכל. sub resultTable { #output SQL statement results into an HTML table my $rowcount=0; my ($dbh,$sth,$queryTable,$returnFields)=@_; my $tableHTML=""; my $labelrow=""; my @fieldNames=(); my $fieldCount=0; #reconstruct the query URL to pass on via hyperlinks my $queryURLa="table=$queryTable&return=$returnFields"; if ($queryCriteria) { my @allparams=$cgiobj->param(); foreach my $param (@allparams) { if ($param=~/criteria/) { $queryURLa.="&$param=".$cgiobj->param($param) } } } נגדיר מספר משתנים חיוניים שישמשו ליצירת ה HTML , כולל: rowcount, $labelRow, $tableHTML$ וכו'. העבודה הממשית הראשונה שנעשה, היא לבנות מחרוזת שאילתה (URL query string). מחרוזת זו היא כל מה שכתוב אחרי ה ? בכתובת הרשת, כמו: http://www.somesite.com/cgi-bin/script.cgi?blah=1&boo=2 בדוגמה שלמעלה, מחרוזת השאילתה היא: "blah=1&boo=2". אנו צריכים לבנות מחרוזת שאילתה שמשקפת את המצב של GUFE כלומר, איזו טבלה נצפית, מהם המפתחות בפעולה, וכן הלאה. אנו עושים זאת כיוון שכשנרצה למיין את הטבלה, ונבנה קישורים (hyperlinks) כמו תוויות שדה. אנו נרצה לשמור מצבים שונים אלו בעמוד שיוחזר. כלומר, אנו רוצים לשמר איזו טבלה נצפית, שדות המפתח שבשימוש וכו'. if ($queryTable){ while (my $row=$sth->fetchrow_hashref) { לולאת while זו אמורה, בכל מעבר, לאחזר את הרשומה הבאה מבסיס הנתונים. וזאת בהנחה שבסיס הנתונים החזיר לפחות רשומה מתאימה אחת-אם הוא לא החזיר, כל לולאת ה while הזו לעולם לא תופעל, ונמשיך הלאה להמשך השגרה. הרשומה מוחזרת מבסיס הנתונים כ "האש" (hash refernce). האש היא קבוצה של זוגות מפתח-נתון, כמו שראינו בחלק הראשון של המאמר. יחד עם DBI, ההאש המוחזר מכיל את כל שמות השדות ביחד עם ערכם. ההפניה להאש זה מאוחסנת ב row$. שימו לב ש row$ הוא משתנה סקלרי, ולא האש (שיתחיל ב %), וזאת בגלל ש row$ בסך הכל מכיל הפניה, או מצביע, להאש, ולא את ההאש עצמו. #retrieve each record row-by-row from the database #build HTML table row-by-row using this data $tableHTML.="<TR>"; @fieldNames=keys %$row; #build a list of field labels $fieldCount=$#fieldNames+1; foreach my $fieldName (@fieldNames) { unless ($rowcount>0) { my $queryURLb=$queryURLa."&sort=$fieldName"; if ($querySortType eq "ASC") { $queryURLb.="&sortType=DESC" } else { $queryURLb.="&sortType=ASC" } #wrap hyperlink around field names, rigged with sort parameters $labelrow.="<TD><A HREF=\"/cgi-bin/gufe.cgi?$queryURLb\">". "<B>$fieldName</B></A></TD>"; } כאן אנו מבצעים מעבר על כל תוויות השדה שיוחזרו מבסיס הנתונים. בזאת, אנו יוצרים את השורה הראשונה בטבלה, והופכים כל תוויות שדה לקישור. הקישור מתוכנת כך שיתחבר מחדש ל GUFE עם הפרמטרים הנוכחיים, בנוסף לפרמטר המיון. סוג המיון מתכוונן להפך של סוג המיון הנוכחי (עולה או יורד). אנו צריכים ליצור את שורת תוויות השדה פעם אחת, ולא כל פעם שנאחזר רשומה. התנאי לסיום הוא (unless $rowcount>0). if ($fieldName eq "Invoice") { #wrap hyperlink around invoice data, rigged to invoice table $tableHTML.="<TD><A HREF=\"/cgi-bin/gufe.cgi?". "table=invoices&criteria_condition_Invoice=%3D". "&criteria_value_Invoice=$row->{$fieldName}\">". "$row->{$fieldName}</A></TD>"; } else { $tableHTML.="<TD>$row->{$fieldName}</TD>"; } המובאה למעלה היא הקוד הכי פחות "כללי" של GUFE. במפורש, היא ממתינה לתווית השדה invoice, והיא עוטפת מידע כזה בתוך קישור שמתוכנת לציין שהרשומה invoice היא בסיס הנתונים invoices. זה לא כללי בגלל שלא נוכל להניח שכל בסיס נתונים מכיל את השדה invoice, או כל שכן מפתח הנמצא בשתי טבלאות. הקוד הוכנס ל GUFE כדי להדגים, בכל אופן, כיצד תוכלו להתאים את בסיס הנתונים שלכם בסגנון זה, על מנת לאפשר למשתמש לעבור במהירות בין רשומות קשורות. אם תווית השדה היא לא "Invoice", מתבצע העיבוד הכללי, הנורמלי. שימו לב לתחביר לאחזור ערך השדה מהאש: $row->{$fieldName} מובן שתוכלו לבקש במפורש גם את הערך של שדה נתון: $row->{ClientEmail} החלק החשוב הוא ש row$ הוא משתנה שאנו בחרנו, ושאליו נכניס את תוצאת התהליך fetchrow_hashref על עוגן הפקודה sth$. } $tableHTML.="</TR>"; $rowcount++; } if ($rowcount==0) { #database did not return any records $tableHTML.="<TR><TD>There is no table view that matches ". "your selected criteria.</TD></TR>"; } } #end if wrapper else { #no table has been selected to view $queryTable="None Selected"; } יתכן שהמשתמש יבחר מפתח שלא יחזיר שום רשומות מבסיס הנתונים, במקרה זה המשתנה rowcount$ לא גדל מעולם, ונוכל להחזיר הודעת "no match" (אין התאמה) במקום הטבלה של בסיס הנתונים שראינו למעלה. משפט ה else שלמעלה הוא החצי השני של משפט ה if הקודם, זה שבדק האם בכלל ביקשנו טבלה כלשהי. אם לא ביקשנו שום טבלה, אנו משימים למשתנה queryTable$ את "None Selected", שבהמשך יופיע ככותרת של הטבלה הריקה שתיווצר. #generate hyperlinks to other tables in this database @tableNames=$dbh->tables; $tableHTML.="<TR><TD COLSPAN=$fieldCount><BR>". "<FONT FACE=\"Arial,Helvetica\">". "Available tables to view: "; foreach $tableName (@tableNames) { unless (($tableName eq $queryTable)&&($rowcount>0)) { $tableHTML.="<A HREF=\"/cgi-bin/gufe.cgi?". "table=$tableName\">$tableName</A> "; } } $tableHTML.="</FONT></TD></TR>"; $tableHTML="<TABLE width='75%' border=0 bgcolor='#FFFFCC'>". "<CAPTION><B><I>Table: $queryTable</I></B>"." "</CAPTION><TR>$labelrow</TR>$tableHTML</TABLE>"; בתחתית של פלט בסיס הנתונים, GUFE מציעה קישורים לכל טבלה זמינה אחרת בבסיס הנתונים. GUFE מוצאת את רשימת הטבלאות הזמינות תוך שימוש בתהליך DBI בשם tables. שימו לב שתהליך זה נתמך רק ע"י הגירסאות החדשות של DBI, ועשוי לא להיתמך ע"י מודול ה DBD של בסיס הנתונים הספציפי שבו אתם משתמשים [הוא נתמך ע"י גרסאות ה DBD האחרונות של ODBC (אקסס) וע"י MySQL]. אם השילוב שלכם בין DBI/DBD לא תומך ב tables לא תופיע שום רשימה של טבלאות, בגלל שהרשימה @tableNames תסתיים ריקה. טבלת ה HTML מסתיימת בקצת קוד HTML להגדרת הטבלה, והכללת שם הטבלה בכותרת. GUFE בנתה עד כאן את ה HTML של הטבלה הצהובה, במילים אחרות, הטבלה שמוחזרת מבסיס הנתונים. אנו מעונינים להציע טופס עם אפשרויות בחירה לבניית שאילתה עבור המשתמש, טופס הידוע בכינויו האזור הכחול. יתכן ויהיה כדאי לבנות טופס זה כחלק נפרד של HTML, ולהכניס אותו לתבנית ה HTML עם עוגן נוסף. אבל כדי לפשט את הדברים פשוט נוסיף גוש HTML זה לתוך המשתנה הקיים tableHTML$. unless (($queryTable eq "None Selected")||($rowcount==0)) { #construct criteria customization form $tableHTML.= "<P><FONT face=\"Arial, Helvetica, sans-serif\" size=\"-1\">". "Customize the table view using the fields below.". "<br>You must put single quotes around text values.". "<br>Click Apply with all set to IGNORE to view whole table.". "</FONT></P>"; $tableHTML.= "<FORM method='get' action='/cgi-bin/gufe.cgi'>"; $tableHTML.= "<TABLE width='75%' border=0 bgcolor='#CCFFFF'>"; foreach $fieldName (@fieldNames) { $tableHTML.= "<TR><TD>$fieldName</TD><TD>"; $tableHTML.= "<select name=\"criteria_condition_$fieldName\">". "<option value=\"0\">IGNORE</option>". "<option value=\"=\">equal to</option>". "<option value=\"like\">like</option>". "<option value=\">=\">greater/equal to</option>". "<option value=\"<=\">less/equal to</option>". "<option value=\">\">greater than</option>". "<option value=\"<\">less than</option></select></TD>"; $tableHTML.= "<TD><INPUT type=text width=10". " name=\"criteria_value_$fieldName\">". "</TD></TR>"; } $tableHTML.= "<TR><TD colspan=3>Combine criteria with ". "<select name=\"criteria_logic\">". "<option value=\"AND\">AND</option>". "<option value=\"OR\">OR</option>". "</select></TD></TR>"; $tableHTML.= "</TABLE><INPUT type=hidden name=\"table\" value=$queryTable>". "<INPUT type=hidden name=\"return\" value=$returnFields>". "<INPUT type=submit value=\"Apply Criteria\"></FORM>"; }#end unless wrapper return $tableHTML } #end resultTable הקטע למעלה נראה מבולבל, אבל הוא כלל לא מסובך. בעיקרון, אנו בונים קוד HTML שמכיל טבלה שמונחת בתוך טופס. הטבלה מכילה שורה עבור כל תווית שדה בטבלה (העליונה) הצהובה. כל שורה מכילה שלשה עמודות: תווית השדה, שדה בחירה מסוג גלילה (drop down), ושדה להכנסת טקסט. זה מאפשר למשתמש לבנות תנאי פשוט עבור כל שדה, כמו לדוגמא "Total>50". השורה האחרונה של הקוד, "return $tableHTML" נראית לכאורה שולית אולם היא חיונית ביותר. היא מחזירה את כל המסה של HTML שיצרנו לפקודה הקוראת. זיכרו שהפקודה הקוראת במקרה זה היא createPage&. בעיקרון, זה כמו להעביר מקל. resultTable& מוסרת את המקל ל createPage&. חלק 3
:GUFI מעבר על
|