בעת יצירת טפסי HTML, אנו בדרך כלל רואים שאנו כותבים הרבה קוד תצוגה שחוזר על עצמו שקשה להשתמש בו שוב פעם בפרוייקט נוסף. לדוגמא, לכל שדה טקסט, אנו צריכים לשייך אותו עם תוית טקסט ולהציג שגיאות אימות נתונים במידה והם קיימים. בכדי לשפר את השימוש החוזר בקודים אלו, אנו יכולים להשתמש במערכת יצירת הטפסים הקיימת במערכת ה Yii מגרסא 1.1.0.
מערכת יצירת הטפסים משתמשת באובייקט של CForm כדי לייצג את המפרט הדרוש לייצוג טופס HTML, הכולל אילו מודלים קשורים לטופס, אילו שדות נתונים נמצאים בטופס, וכיצד להציג את כל הטופס. מפתחים בעיקר צריכים ליצור ולהגדיר את האובייקט CForm, לאחר מכן לקרוא למתודת התצוגה שלו בכדי להציג את הטופס.
מפרט שדות הטופס מסודרים במונחים של אלמנטים של אובייקט הטופס בהיררכיה. בראש ההיררכיה, נמצא האובייקט CForm. האובייקט הראשי מתחזק את התתים שבו בשני אוספים שונים: CForm::buttons ו CForm::elements. הראשון מכיל את האלמנטים המיוצגים ככפתורים (כמו כפתור שליחה, כפתור איפוס), בזמן שהשני מכיל את שדות הזנת הטקסט, טקסט סטטי, ותתי טפסים. תת-טופס הינו אובייקט של CForm הנמצא באוסף של האלמנטים (CForm::elements) בטופס אחר. הוא יכול להכיל מודל משלו, CForm::buttons ו CForm::elements.
כשמשתמשים שולחים טופס, הנתונים שהוזנו בכל השדות בכל ההיררכיה של הטופס נשלחים, כולל את השדות הנמצאים בתתי-טפסים. CForm מספק מתודות נוחות לשימוש שבעזרתן ניתן לצרף נתונים מסויימים למאפייני המודלים המתאימים ולבצע אימות נתונים על גביהם.
בדוגמא הבאה, אנו מציגים כיצד להשתמש במערכת יצירת הטפסים כדי ליצור טופס התחברות.
קודם כל, אנו כותבים את הפעולה של ההתחברות:
public function actionLogin()
{
$model = new LoginForm;
$form = new CForm('application.views.site.loginForm', $model);
if($form-»submitted('login') && $form-»validate())
$this-»redirect(array('site/index'));
else
$this-»render('login', array('form'=»$form));
}
בקוד למעלה, אנו יוצרים אובייקט של CForm תוך כדי שימוש במפרט המצביע לנתיב application.views.site.loginForm
(הסבר לגבי זה בהמשך).
האובייקט CForm מקושר עם המודל LoginForm
כפי שתואר ביצירת מודל.
כפי שמוצג בקוד, במידה והטופס נשלח וכל השדות אומתו ללא שגיאות, אנו נעביר את המשתמש לעמוד site/index
. אחרת, אנו נציג שוב פעם את קובץ התצוגה login
ביחד עם הטופס.
הנתיב application.views.site.loginForm
מתייחס לקובץ PHP הנמצא תחת התיקיה protected/views/site/loginForm.php
. הקובץ צריך להחזיר מערך המכיל את הגדרות הנחוצות עבור CForm, כפי שמוצג בקוד הבא:
return array(
'title'=»'Please provide your login credential',
'elements'=»array(
'username'=»array(
'type'=»'text',
'maxlength'=»32,
),
'password'=»array(
'type'=»'password',
'maxlength'=»32,
),
'rememberMe'=»array(
'type'=»'checkbox',
)
),
'buttons'=»array(
'login'=»array(
'type'=»'submit',
'label'=»'Login',
),
),
);
ההגדרות הינם מערך המכיל מפתחות וערכים המוגדרים למאפיינים של המחלקה CForm. המאפיינים החשובים ביותר להגדרה, כפי שכבר הזכרנו, CForm::elements ו CForm::buttons. כל אחד מהם מקבל מערך המגדיר רשימה של אלמנטים בטופס. אנו נסביר בהרחבה כיצד יש להגדיר אלמנטים של טופס בחלק הבא.
לבסוף, אנו כותבים את קובץ התצוגה login
, שיכול להיות פשוט כפי שמוצג בקוד הבא,
«h1»Login«/h1»
«div class="form"»
«?php echo $form; ?»
«/div»
» Tip|טיפ: הקוד למעלה, ;echo $render
הוא זהה לקוד ;()echo $form-»render
. וזאת מכיוון שהאובייקט CForm מיישם את המתודה toString__
אשר קוראת למתודה ()render
ומחזירה את התצוגה כסטרינג המייצג את אובייקט הטופס.
בשימוש במערכת יצירת הטפסים, רוב העבודה שלנו משתנה מכתיבת קוד בקבצי התצוגה להגדרת אלמנטים בטופס. בחלק זה, אנו נתאר כיצד להגדיר את האלמנטים מאפיין CForm::elements. אנו לא נתאר אודות CForm::buttons מאחר והגדרותיו הם כמעט זהות ל CForm::elements.
המאפיין CForm::elements מקבל מערך. כל אלמנט במערך מייצג אלמנט אחד בטופס שיכול להיות שדה נתונים, טקסט סטטי, או תת-טופס.
אלמנט שדה נתונים בעיקר מכיל תוית, שדה נתונים, שדה עזרה ותצוגת שגיאה. הוא חייב להיות מקושר למאפיין במודל מסויים. המפרט של אלמנט שדה נתונים מיוצג כאובייקט של CFormInputElement. הקוד הבא במערך CForm::elements מגדיר אלמנט שדה נתונים אחד:
'username'=»array(
'type'=»'text',
'maxlength'=»32,
),
קוד זה מציין שהמאפיין של המודל בשם username
, ושדה הנתונים הוא מסוג text
ושאורכו - maxlength
הוא 32. אנו יכולים לציין אפשרויות נוספות במערך למעלה כל עוד שהם מאפיינים שניתנים לכתיבה במחלקה CFormInputElement. לדוגמא, אנו יכולים להגדיר את האפשרות hint המציגה טקסט עזרה עבור שדה זה, או שניתן להגדיר את האפשרות items במידה והשדה הוא תיבת בחירה, תיבת בחירה מרובה, רשימת כפתורי בחירה, רשימת כפתורי רדיו.
האפשרות type דורשת יותר תשומת לב מהשאר. אפשרות זו מגדירה את סוג שדה הנתונים לתצוגה. לדוגמא, הסוג text
מעיד על כך שיש צורך להציג שדה טקסט רגיל; הסוג password
אומר שיש צורך להציג שדה סיסמא. CFormInputElement מזהה את הסוגים המובנים הבאים:
מלבד הסוגים המובנים, האפשרות type יכולה לקבל שם של מחלקת וידג'ט או נתיב מקוצר עד אל הוידג'ט. המחלקה של הוידג'ט צריכה לירוש מהמחלקה CInputWidget. בעת התצוגה של האלמנט, אובייקט של הוידג'ט של השדה הנוכחי יווצר ויוצג. הוידג'ט יוגדר בהתבסס על המפרט הקיים באלמנט.
בהרבה מקרים, מלבד שדות נתונים טופס מכיל קוד HTML שנועד לעיצוב הטופס. לדוגמא, יהיה צורך בקו אופקי בכדי להפריד בין חלקים בטופס; יש צורך בתמונה במקום מסויים בטופס בכדי לשפר את המראה החיצוני של הטופס. אנו יכולים להגדיר את קוד ה HTML הזה כטקסט סטטי באוסף האלמנטים של CForm::elements. בכדי לבצע זאת, אנו מגדירים אלמנט בתוך המאפיין CForm::elements בתור טקסט סטטי במיקום בו אנו רוצים להציג אותו בטופס. לדוגמא,
return array(
'elements'=»array(
......
'password'=»array(
'type'=»'password',
'maxlength'=»32,
),
'«hr /»',
'rememberMe'=»array(
'type'=»'checkbox',
)
),
......
);
בקוד המוצג למעלה, אנו מוסיפים קו אופקי בין השדה של הסיסמא - password
לבין השדה של זכור אותי - rememberMe
.
השימוש בטקסט סטטי הוא כשהטקסט המיקום שלו אינם רגילים. אם לכל שדה בטופס יהיה צורך בעיצוב באופן פרטני, יהיה צורך בלשנות את אופן התצוגה של הטופס, הסבר לפעולה זו יופיע בהמשך.
תתי-טפסים נועדו בכדי לחלק טופס ארוך לכמה טפסים חלקים הקשורים אחד לשני לוגית. לדוגמא, אנו יכולים לחלק את טופס ההרשמה לשני תת-טפסים: פרטי התחברות ופרטי פרופיל. כל תת-טופס חייב/לא חייב להיות משוייך למודל. בדוגמא של טופס ההרשמה, אם אנו שומרים את פרטי ההתחברות של המשתמש ואת פרטי הפרופיל של המשתמש בשני טבלאות שונות (ולכן שני מודלים נפרדים), לכן כל תת טופס יהיה משוייך למודל שלו. במידה ואנו שומרים את כל הפרטים באותה הטבלה, לכן לאף אחד מתתי-הטפסים לא יהיה מודל מאחר והם משותפים עם המודל של הטופס הראשי.
תת-טופס מיוצג כאובייקט של CForm. בכדי להגדיר תת-טופס, אנו צריכים להגדיר את המאפיין CForm::elements עם אלמנט שסוגו הוא form
:
return array(
'elements'=»array(
......
'user'=»array(
'type'=»'form',
'title'=»'Login Credential',
'elements'=»array(
'username'=»array(
'type'=»'text',
),
'password'=»array(
'type'=»'password',
),
'email'=»array(
'type'=»'text',
),
),
),
'profile'=»array(
'type'=»'form',
......
),
......
),
......
);
כמו בהגדרת הטופס הראשי, אנו בעיקר צריכים להגדיר את המאפיין CForm::elements של תתי-הטפסים. במידה ותת הטופס צריך להיות משוייך עם מודל, ניתן להגדיר את המאפיין CForm::model שלו גם כן.
לפעמים, אנו נרצה לייצג טופס המשתמש במחלקה אחרת ולא ברירת המחדל CForm. לדוגמא, כפי שנציג בעוד רגע בחלק זה, אנו יכולים להרחיב את המחלקה CForm בכדי להתאים אישית את אופן הצגת הטופס.
על ידי הגדרת סוג האלמנט כ form
, תת הטופס אוטומטית מיוצג כאובייקט שהמחלקה שלו היא זהה למחלקה של טופס האב. אם נגדיר את סוג האלמנט למשהו כמו XyzForm
(סטרינג המסתיים ב Form
), אז תת-הטופס יהיה מיוצג על ידי האובייקט של המחלקה XyzForm
.
גישה לאלמנטים בטופס הינה פשוטה כגישה לאלמנטים מערך. המאפיין CForm::elements מחזיר אובייקט של CFormElementCollection, היורש מהמחלקה CMap ומאפשר גישה לאלמנטים שבו כמערך רגיל. לדוגמא, בכדי לגשת לאלמנט username
בדוגמא של טופס ההתחברות שהוצג, אנו יכולים להשתמש בקוד הבא:
$username = $form-»elements['username'];
ובכדי לגשת לאלמנט של email
בדוגמא של טופס ההרשמה, אנו יכולים להשתמש ב
$email = $form-»elements['user']-»elements['email'];
מאחר ו CForm מיישם את הממשק של array access
עבור המאפיין CForm::elements, ניתן לפשט את הקוד למעלה בצורה הבאה:
$username = $form['username'];
$email = $form['user']['email'];
כבר הצגנו את התתי-טפסים. אנו קוראים לטופס עם תתי-טפסים טופס משורשר. בחלק זה, אנו משתמשים בטופס של הרשמת משתמשים בכדי להציג כיצד ליצור טופס משורשר המקושר לכמה מודלים.
אנו מניחים שפרטי המשתמשים מאוחסנים במודל User
, בזמן שמידע אודות פרופיל המשתמש נמצא תחת המודל Profile
.
אנו קודם יוצרים את פעולת ההרשמה register
בצורה הבאה:
public function actionRegister()
{
$form = new CForm('application.views.user.registerForm');
$form['user']-»model = new User;
$form['profile']-»model = new Profile;
if($form-»submitted('register') && $form-»validate())
{
$user = $form['user']-»model;
$profile = $form['profile']-»model;
if($user-»save(false))
{
$profile-»userID = $user-»id;
$profile-»save(false);
$this-»redirect(array('site/index'));
}
}
$this-»render('register', array('form'=»$form));
}
בקוד למעלה, אנו יוצרים את הטופס בעזרת שימוש בהגדרות הנמצאות ב application.views.user.registerForm
.
לאחר השליחה של הטופס ואימות הנתונים עבר בהצלחה, אנו מנסים לשמור את המודלים של User
ו Profile
.
אנו שולפים את המודלים של המשתמש והפרופיל על ידי גישה למאפיין model
תחת האובייקט של תת הטופס.
מאחר ואימות הנתונים נעשה כבר, אנו קוראים ל $user-»save(false)
בכדי לדלג על האימות. אנו עושים את אותו הדבר עם המודל של הפרופיל.
לאחר מכן, אנו כותבים את קובץ הגדרות הטופס תחת הנתיב protected/views/user/registerForm.php
:
return array(
'elements'=»array(
'user'=»array(
'type'=»'form',
'title'=»'Login information',
'elements'=»array(
'username'=»array(
'type'=»'text',
),
'password'=»array(
'type'=»'password',
),
'email'=»array(
'type'=»'text',
)
),
),
'profile'=»array(
'type'=»'form',
'title'=»'Profile information',
'elements'=»array(
'firstName'=»array(
'type'=»'text',
),
'lastName'=»array(
'type'=»'text',
),
),
),
),
'buttons'=»array(
'register'=»array(
'type'=»'submit',
'label'=»'Register',
),
),
);
בקוד המוצג למעלה, בעת הגדרת כל תת-טופס, אנו מגדירים את המאפיין CForm::title השייך לו. לוגיקת התצוגה ברירת המחדל של הטופס תעטוף כל תת-טופס בתוך מעטפת אשר תשתמש במאפיין זה בכדי להציג את הכותרת של הטופס.
לבסוף, אנו כותבים את קובץ התצוגה הפשוט של ההרשמה register
:
«h1»הרשמה«/h1»
«div class="form"»
«?php echo $form; ?»
«/div»
היתרון בשימוש של מערכת יצירת הטפסים היא ההפרדה מהלוגיקה (הגדרות הטופס נמצאות בקובץ נפרד) והתצוגה (מתודת CForm::render). כתוצאה מכך, אנו יכולים להתאים את התצוגה של הטופס באופן אישי על ידי דריסה של המתודה CForm::render או לספק קובץ תצוגה חלקי אשר מציג את הטופס. בשני האפשרויות ניתן להשאיר את הגדרות הטופס ללא שינוי ולהשתמש באותו הקוד בצורה קלה.
כשדורסים את המתודה CForm::render, יש לרוץ על גבי האלמנטים של CForm::elements ו CForm::buttons ולקרוא למתודה CFormElement::render עבור כל כל אלמנט. לדוגמא,
class MyForm extends CForm
{
public function render()
{
$output = $this-»renderBegin();
foreach($this-»getElements() as $element)
$output .= $element-»render();
$output .= $this-»renderEnd();
return $output;
}
}
כמו כן אנו יכולים ליצור קובץ תצוגה form_
בכדי להציג את הטופס:
«?php
echo $form-»renderBegin();
foreach($form-»getElements() as $element)
echo $element-»render();
echo $form-»renderEnd();
בכדי להשתמש בקובץ התצוגה, ניתן פשוט לקרוא:
«div class="form"»
$this-»renderPartial('_form', array('form'=»$form));
«/div»
במידה ותצוגה כללית לא נראית טוב בטופס מסויים (לדוגמא, הטופס צריך דקורציה מיוחדת ולא רגילה עבור אלמנטים מסויימים), אנו יכולים לבצע את הפעולות הבאות בקובץ תצוגה:
אלמנטים של UI מורכבים כאן
«?php echo $form['username']; ?»
אלמנטים של UI מורכבים כאן
«?php echo $form['password']; ?»
אלמנטים של UI מורכבים כאן
בשיטה האחרונה,זה נראה שמערכת יצירת הטפסים לא מועילה לנו כל כך, אנו עדיין צריכים לכתוב כמות קוד דומה לטופס שאנו משתמשים בעת שימוש בקוד רגיל. למרות, שהטופס מוגדר בעזרת קובץ הגדרות בנפרד אשר עוזר למפתחים להתמקד יותר בלוגיקה.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.