0 follower

יצירת קוד אוטומטית

החל מגרסא 1.1.2, Yii מצויידת עם מערכת מבוססת ווב ליצירת קוד בשם Gii. מערכת זו הינה תחליף עבור הכלי הקודם בשם yiic shell שרץ על גבי שורת הפקודות. בחלק זה, אנו נדגים כיצד להשתמש ב-Gii וכיצד להרחיב את Gii כדי לזרז את תהליך הפיתוח.

1. שימוש ב-Gii

Gii מיושמת במונחים של מודול וחייבת להיות בשימוש תחת אפליקצית Yii קיימת. כדי להשתמש ב-Gii, אנו קודם עורכים את הגדרות האפליקציה בצורה הבאה:

return array(
    ......
    'modules'=»array(
        'gii'=»array(
            'class'=»'system.gii.GiiModule',
            'password'=»'סיסמא כלשהי',
            // 'ipFilters'=»array(...רשימה של כתובות אייפי...),
            // 'newFileMode'=»0666,
            // 'newDirMode'=»0777,
        ),
    ),
);

בקוד המוצג למעלה, אנו מגדירים מודול בשם gii שהמחלקה שלו הינה GiiModule. כמו כן אנו מגדירים סיסמא עבור המודול שאנו נצטרך להזין בעת הכניסה ל-Gii.

כברירת מחדל ומטעמי בטחון, Gii מוגדרת ככה שיהיה ניתן לגשת אל המודול רק משרת localhost. אם אנו רוצים לאפשר גישה למחשבים בטוחים נוספים, אנו יכולים להגדיר את המאפיין GiiModule::ipFilters כפי שמוצג בקוד למעלה.

בגלל ש-Gii יוצר קוד ושומר אותו בקבצים חדשים באפליקציה הנוכחית, אנו צריכים לוודא ששרת הווב מכיל את ההרשאות המתאימות לבצע פעולות אלו. בקוד המוצג למעלה המאפיינים GiiModule::newFileMode ו GiiModule::newDirMode שולטים באופן שבו הקבצים החדשים והתיקיות נוצרים.

» Note|הערה: Gii נועד בעיקר ככלי פיתוח. לכן, רצוי להתקינו על סביבת פיתוח. מאחר וכלי זה יכול לייצר קבצי PHP חדשים באפליקציה, אנו צריכים לשים לב לאמצעי האבטחה שבו (לדוגמא סיסמא, כתובות IP).

כעת אנו יכולים לגשת למערכת Gii דרך הקישור http://hostname/path/to/index.php?r=gii. כאן אנו מניחים שהקישור http://hostname/path/to/index.php הוא הקישור לכניסה לאפליקצית ה-Yii הנוכחית.

במידה והאפליקציה הנוכחית משתמשת בפורמט path עבור הקישורים (ראה ניהול קישורים), אנו יכולים לגשת למודול Gii דרך הקישור http://hostnamepath/to/index.php/gii. אנו נצטרך להוסיף את הכללים הבאים לראש הכללים הקיימים באפליקציה:

'components'=»array(
    ......
    'urlManager'=»array(
        'urlFormat'=»'path',
        'rules'=»array(
            'gii'=»'gii',
            'gii/«controller:\w+»'=»'gii/«controller»',
            'gii/«controller:\w+»/«action:\w+»'=»'gii/«controller»/«action»',
            ...כללים נוכחים...
        ),
    ),
)

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

רצף העבודה הבסיסי לשימוש באפשרות יצירת קוד הינה:

  1. כניסה לעמוד יצירת הקוד;
  2. מילוי שדות המגדירות את הפרמטרים עבור יצירת הקוד. לדוגמא, בכדי להשתמש באפשרות יצירת קוד מודול כדי ליצור מודול חדש, יש לציין את המזהה יחודי עבור המודול;
  3. יש ללחוץ על כפתור Preview בכדי לצפות בתצוגה המקדימה עבור הקוד שיווצר. תוכל לראות טבלה המציגה רשימה של קבצים ליצירה. ניתן ללחוץ על כל אחד מהם בכדי לצפות בתצוגה המקדימה של הקוד;
  4. יש ללחוץ על כפתור Generate כדי ליצור את הקבצים;
  5. יש לעיין בהודעות התיעוד של יצירת הקוד.

2. הרחבת Gii

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

ניתן להרחיב את Gii בשני דרכים: התאמה אישית של התבניות הקיימות ליצירת הקוד, וכתיבת אפשרויות יצירת קוד חדשות.

מבנה אפשרות יצירת קוד

אפשרות יצירת קוד נמצאת בתיקיה ששמה הוא שם אפשרות היצירה עצמה. התיקיה בדרך כלל מכילה את התוכן הבא:

model/                       התיקיה הראשית לאפשרות יצירת המודל
   ModelCode.php             קוד המודל אשר יוצר את הקוד
   ModelGenerator.php        קונטרולר יצירת הקוד
   views/                    מכיל קבצי תצוגה עבור אפשרות יצירת הקוד
      index.php              קובץ תצוגה ברירת המחדל
   templates/                מכיל תבניות קוד
      default/               תבנית ברירת המחדל
         model.php           תבנית הקוד לאפשרות יצירת קוד עבור מחלקת מודל

נתיב חיפוש של אפשרויות היצירה

Gii מחפש אחר אפשרויות יצירה תחת תיקיות מסויימות המוגדרות בעזרת המאפיין GiiModule::generatorPaths. כשיש צורך בהתאמה אישית, אנו יכולים להגדיר מאפיין זה בהגדרות האפליקציה בצורה הבאה,

return array(
    'modules'=»array(
        'gii'=»array(
            'class'=»'system.gii.GiiModule',
            'generatorPaths'=»array(
                'application.gii',   // נתיב מקוצר
            ),
        ),
    ),
);

ההגדרות המוצגות למעלה מורות ל-Gii לחפש אחר אפשרויות יצירת קוד תחת התיקיה בנתיב המקוצר application.gii, בנוסף לתיקית ברירת המחדל system.gii.generators.

ניתן לשמור אפשרויות יצירת קוד באותו השם אך בנתיבי חיפוש שונים. במקרה זה, אפשרות היצירה שצויינה קודם לכן תחת התיקיה שהוגדרה במאפיין GiiModule::generatorPaths תקבל עדיפות.

התאמת תבניות קוד

זוהי הדרך הקלה ביותר והנפוצה ביותר להרחבת Gii. אנו משתמשים בדוגמא בכדי להסביר כיצד להתאים אישית את תבניות הקוד. נניח שאנו רוצים להתאים אישית את הקוד הנוצר על ידי אפשרות יצירת מודל.

אנו קודם יוצרים תיקיה בשם protected/gii/model/templates/compact. כאן model אומר שאנו עומדים לדרוס את אפשרות יצירת המודל המגיעה כברירת מחדל עם המערכת. ו templates/compact אומר שאנו מוסיפים תבנית חדשה בשם compact.

לאחר מכן אנו עורכים את קובץ הגדרות האפליקציה כדי להוסיף application.gii למאפיין GiiModule::generatorPaths, כפי שמוצג בחלק הקודם.

כעת יש לפתוח את עמוד יצירת קוד המודל. לחיצה על שדה Code Template. אנו נוכל לראות רשימה אשר מכילה את תיקית התבנית שהרגע יצרנו בשם compact. אך אם נבחר את התבנית הזו עבור אפשרות יצירת הקוד, אנו נראה שגיאה. זה מכיוון שעדיין לא הוספנו שום קובץ המשמש כתבנית קוד בתיקית התבניות החדשה שהוספנו בשם compact.

יש להעתיק את הקובץ מהנתיב framework/gii/generators/model/templates/default/model.php אל protected/gii/model/templates/compact. כעת אם ננסה ליצור שום פעם עם התבנית compact, זה אמור לעבוד. למרות, שהקוד שיווצר הוא לא שונה מהקוד שנוצר על ידי תבנית ברירת המחדל בשם default מאחר ומשם העתקנו את הקובץ אך לא בצענו בו שינויים כלשהם.

כעת זה הזמן לבצע את עבודת ההתאמה האמיתית. פתח את הקובץ protected/gii/model/templates/compact/model.php כדי לערוך אותו. זכור שקובץ זה יהיה בשימוש כקובץ תצוגה, שאומר שהוא יכול להכיל ביטויים ב-PHP. הבא ונערוך את התבנית כדי שהמתודה ()attributeLabels בקוד שנוצר תשתמש ב-()Yii::t כדי לתרגם את תוויות המאפיינים:

public function attributeLabels()
{
    return array(
«?php foreach($labels as $name=»$label): ?»
            «?php echo "'$name' =» Yii::t('application', '$label'),\n"; ?»
«?php endforeach; ?»
    );
}

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

הוספת אפשרות יצירת קוד

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

אנו קודם יוצרים תיקיה בשם protected/gii/widget. תחת תיקיה זו, אנו ניצור את הקבצים הבאים:

  • WidgetGenerator.php: מכיל את מחלקת הקונטרולר WidgetGenerator. זהו הקובץ הראשי של אפשרות יצירת הוידג'ט.

  • WidgetCode.php: מכיל את מחלקת המודל WidgetCode. מחלקה זו מכילה את הלוגיקה העיקרית ליצירת קוד.

  • views/index.php: קובץ התצוגה המציג את טופס אפשרות יצירת הקוד.

  • templates/default/widget.php: קובץ הקוד ברירת המחדל ליצירת מחלקת הוידג'ט.

יצירת WidgetGenerator.php

קובץ ה-WidgetGenerator.php הוא פשוט מאוד. הוא מכיל את הקוד הבא בלבד:

class WidgetGenerator extends CCodeGenerator
{
    public $codeModel='application.gii.widget.WidgetCode';
}

בקוד המוצג למעלה, אנו מציינים שאפשרות היצירה תשתמש במחלקת מודל שהנתיב שלה הוא application.gii.widget.WidgetCode. המחלקה WidgetGenerator מרחיבה את CCodeGenerator אשר מיישמת הרבה אפשרויות ופונקציונליות, הכוללות את פעולות הקונטרולר הדרושות לתיאום תהליך יצירת הקוד.

יצירת WidgetCode.php

קובץ WidgetCode.php מכיל את מחלקת המודל WidgetCode המכילה את הלוגיקה העיקרית ליצירת מחלקת וידג'ט המבוססת על נתוני ההזנה של המשתמש. בדוגמא זו, אנו מניחים שהנתונים שאנו מצפים מהמשתמש הם רק שם המחלקה של הוידג'ט. הקוד עבור WidgetCode נראה כך:

class WidgetCode extends CCodeModel
{
    public $className;
 
    public function rules()
    {
        return array_merge(parent::rules(), array(
            array('className', 'required'),
 
            array('className', 'match', 'pattern'=»'/^\w+$/'), 
 
        ));
    }
 
    public function attributeLabels()
    {
        return array_merge(parent::attributeLabels(), array(
            'className'=»'Widget Class Name',
        ));
    }
 
    public function prepare()
    {
        $path=Yii::getPathOfAlias('application.components.' . $this-»className) . '.php';
        $code=$this-»render($this-»templatepath.'/widget.php');
 
        $this-»files[]=new CCodeFile($path, $code);
    }
}

מחלקת הקוד WidgetCode מרחיבה את המחלקה CCodeModel. בדומה למחלקת מודל רגילה, במחלקה זו אנו יכולים להגדיר מתודות ()rules ו ()attributeLabels כדי לאמת את הנתונים שהמשתמש מזין ולהציג תוויות עבור המאפיינים במחלקה, בהתאמה. יש לזכור שמאחר והמחלקה הבסיסית CCodeModel כבר מגדירה כמה כללים ותוויות, אנו צריכים לאחד אותם עם הכללים והתוויות שאנו מגדירים במחלקה זו.

המתודה ()prepare מכינה מראש את הקוד שיווצר. המטרה העיקרית שלו היא להכין רשימת אובייקטים של CCodeFile, כל אחד מייצג קובץ קוד שנוצר. בדוגמא שלנו, אנו צריכים רק ליצור אובייקט CCodeFile אחד המייצג את קובץ המחלקה של הוידג'ט הנוצר. מחלקת הוידג'ט החדשה שתווצר תמוקם תחת התיקיה protected/components. אנו קוראים למתודה CCodeFile::render כדי ליצור את הקוד עצמו. מתודה זו מכילה את תבנית הקוד כסקריפט PHP ומחזירה את תוצאת הפלט המווה את הקוד שנוצר.

יצירת views/index.php

כשברשותנו הקונטרולר (WidgetGenerator) והמודל (WidgetCode), הגיע הזמן ליצור את קובץ התצוגה views/index.php.

«h1»אפשרות יצירת וידג'ט«/h1»
 
«?php $form=$this-»beginWidget('CCodeForm', array('model'=»$model)); ?»
 
    «div class="row"»
        «?php echo $form-»labelEx($model,'className'); ?»
        «?php echo $form-»textField($model,'className',array('size'=»65)); ?»
        «div class="tooltip"»
           שם מחלקת המודל חייבת להכיל אותיות בלבד
        «/div»
        «?php echo $form-»error($model,'className'); ?»
    «/div»
 
«?php $this-»endWidget(); ?»

בקוד המוצג למעלה, אנו בעיקר מציגים טופס בעזרת הוידג'ט CCodeForm. בטופס זה, אנו מציגים את שדה הטקסט המהווה את הערך עבור המאפיין className במחלקה WidgetCode.

בעת יצירת הטופס, אנו יכולים לנצל שני אפשרויות אשר נמצאות בוידג'ט CCodeForm. האחד הוא טקסט עזרה קטן (tooltip). האחר הוא שדה טקסט דביק.

אם כבר התנסת באחד מאפשרויות יצירת הקוד הנמצאות במערכת, תוכל לשים לב שבעת קביעת פוקוס בשדה טקסט כלשהו, יופיע טקסט עזרה קטן ליד השדה. ניתן לבצע זאת בצורה פשוטה על ידי הוספת DIV עם הגדרת האלמנט 'classבשםtooltip` ליד השדה בו רוצים להציג את ההודעה הקטנה.

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

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

ראשית, אנו צריכים להגדיר כלל אימות בשם sticky עבור המאפיין המקביל במודל. לדוגמא, אפשרות יצירת קונטרולרים המגיע עם המערכת מכילה את הכללים הבאים המגדירים את המאפיינים baseClass ו actions כמאפיינים דביקים:

public function rules()
{
    return array_merge(parent::rules(), array(
        ......
        array('baseClass, actions', 'sticky'),
    ));
}

שנית, אנו צריכים להוסיף מאפיין class בשם sticky לתג div של שדה הטקסט בתצוגה, בצורה הבאה:

«div class="row sticky"»
   ..שדה טקסט כאן...
«/div»

יצירת templates/default/widget.php

לבסוף, אנו יוצרים את תבנית הקוד templates/default/widget.php. כפי שהסברנו קודם לכן, השימוש של קובץ זה הוא בדומה לקובץ תצוגה המכיל פקודות וביטויים ב PHP. בתבנית קוד, אנו תמיד יכולים לגשת למשתנה this$ המתייחס לאובייקט של המודל. בדוגמא שלנו, this$ מתייחס לאובייקט של WidgetModel. לכן אנו יכולים לשלוף את שם המחלקה שהמשתמש הזין בטופס בעזרת this-»className$.

«?php echo '«?php'; ?»
 
class «?php echo $this-»className; ?» extends CWidget
{
    public function run()
    {
 
    }
}

זה מסכם את החלק לגבי יצירת אפשרות יצירת קוד חדשה. כעת אנו יכולים לגשת לאפשרות יצירת הקוד שהרגע יצרנו על ידי כניסה לקישור http://hostname/path/to/index.php?r=gii/widget.

Found a typo or you think this page needs improvement?
Edit it on github !