0 follower

שימוש במערכת יצירת הטפסים

בעת יצירת טפסי HTML, אנו בדרך כלל רואים שאנו כותבים הרבה קוד תצוגה שחוזר על עצמו שקשה להשתמש בו שוב פעם בפרוייקט נוסף. לדוגמא, לכל שדה טקסט, אנו צריכים לשייך אותו עם תוית טקסט ולהציג שגיאות אימות נתונים במידה והם קיימים. בכדי לשפר את השימוש החוזר בקודים אלו, אנו יכולים להשתמש במערכת יצירת הטפסים הקיימת במערכת ה Yii מגרסא 1.1.0.

1. תפיסה בסיסית

מערכת יצירת הטפסים משתמשת באובייקט של CForm כדי לייצג את המפרט הדרוש לייצוג טופס HTML, הכולל אילו מודלים קשורים לטופס, אילו שדות נתונים נמצאים בטופס, וכיצד להציג את כל הטופס. מפתחים בעיקר צריכים ליצור ולהגדיר את האובייקט CForm, לאחר מכן לקרוא למתודת התצוגה שלו בכדי להציג את הטופס.

מפרט שדות הטופס מסודרים במונחים של אלמנטים של אובייקט הטופס בהיררכיה. בראש ההיררכיה, נמצא האובייקט CForm. האובייקט הראשי מתחזק את התתים שבו בשני אוספים שונים: CForm::buttons ו CForm::elements. הראשון מכיל את האלמנטים המיוצגים ככפתורים (כמו כפתור שליחה, כפתור איפוס), בזמן שהשני מכיל את שדות הזנת הטקסט, טקסט סטטי, ותתי טפסים. תת-טופס הינו אובייקט של CForm הנמצא באוסף של האלמנטים (CForm::elements) בטופס אחר. הוא יכול להכיל מודל משלו, CForm::buttons ו CForm::elements.

כשמשתמשים שולחים טופס, הנתונים שהוזנו בכל השדות בכל ההיררכיה של הטופס נשלחים, כולל את השדות הנמצאים בתתי-טפסים. CForm מספק מתודות נוחות לשימוש שבעזרתן ניתן לצרף נתונים מסויימים למאפייני המודלים המתאימים ולבצע אימות נתונים על גביהם.

2. יצירת טופס פשוט

בדוגמא הבאה, אנו מציגים כיצד להשתמש במערכת יצירת הטפסים כדי ליצור טופס התחברות.

קודם כל, אנו כותבים את הפעולה של ההתחברות:

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 ומחזירה את התצוגה כסטרינג המייצג את אובייקט הטופס.

3. הגדרת אלמנטים בטופס

בשימוש במערכת יצירת הטפסים, רוב העבודה שלנו משתנה מכתיבת קוד בקבצי התצוגה להגדרת אלמנטים בטופס. בחלק זה, אנו נתאר כיצד להגדיר את האלמנטים מאפיין 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 מזהה את הסוגים המובנים הבאים:

  • text: שדה טקסט
  • hidden: שדה מוסתר
  • password: שדה סיסמא
  • textarea: תיבת טקסט
  • file: שדה קובץ
  • radio: שדה כפתור רדיו
  • checkbox: שדה כפתור בחירה
  • listbox: שדה בחירה מרובה
  • dropdownlist: שדה תיבת בחירה
  • checkboxlist: שדה רשימת כפתורי בחירה
  • radiolist: שדה רשימת כפתורי רדיו

מלבד הסוגים המובנים, האפשרות 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.

4. גישה לאלמנטים בטופס

גישה לאלמנטים בטופס הינה פשוטה כגישה לאלמנטים מערך. המאפיין 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'];

5. יצירת שרשור טפסים

כבר הצגנו את התתי-טפסים. אנו קוראים לטופס עם תתי-טפסים טופס משורשר. בחלק זה, אנו משתמשים בטופס של הרשמת משתמשים בכדי להציג כיצד ליצור טופס משורשר המקושר לכמה מודלים. אנו מניחים שפרטי המשתמשים מאוחסנים במודל 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»

6. התאמה אישית של תצוגה הטופס

היתרון בשימוש של מערכת יצירת הטפסים היא ההפרדה מהלוגיקה (הגדרות הטופס נמצאות בקובץ נפרד) והתצוגה (מתודת 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 !