ארכיון הקטגוריה: php

מעבר מ-PHP ל – C# , ומ-Laravel אל ASP.NET MVC – רשמים ראשונים

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

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

ועכשיו לתכלס – ההבדלים העיקרים בין PHP ל- C# .

אז ראשית – צריך להבהיר מספר מושגים, כדי שלכל מי שקורא את הפוסט יהיה קל .

ה-Framework של C# מבית מיקרוסופט, נקרא ASP.NET MVC, וקיימת גם גירסה שונה שלו שמיועדת עבור API ונקראת WebAPI ( ניתנים לשילוב, אך בעיקרון – 2 מוצרים שונים).

והמקבילה בעולם ה-PHP שאיתה עבדתי בעיקר, הייתה ה-Framework המוביל כיום ב-PHP, שנקרא Laravel , גם אצלו קיימת גירסה ל-API שנקראת Lumen.

הבדלים ברמת מחיר :

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

הבדלים ברמת השפה – בין PHP ל- C# .

אז ההבדל העיקרי ביותר – הוא ש-C# מחייבת להצהיר על סוגי המשתנים, בניגוד ל-PHP.

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

  • בהכרזה של namespace, ב-C# ,  צריך להכניס  את כל ה- קלאס תחתיו גם כן בתוך סוגרים מסולסלות { } .
  • המילה use מתחלפת במילה using.
  • אין triats ב-C#
  • יש  ב-C# משתנה מסוג List שעובד די יעיל ולא קיים ב-PHP ( יותר נכון, קיים, אך רק דרך תוספות)
  • יש מתודות מובנות ב- C# למחרוזות, מערכים , ועוד ( בסגנון של JS – שכל משתנה הוא אוביקט … רק הרבה יותר מתודות מובנות ) .
  • מימוש של Interface נעשה ב-C# עם נקודותיים, לעומת implements ב-php
  • במקום final עבור מתודות \ קלאסים שלא יורשים מהם, משתמשים ב-seald ב-c# .
  • קיים מבנה של Enum ב-C# שלא קיים ב-PHP ( למרות שקל מאוד לממש – מפתחים רבים פותחים מחלקה שמכילה Consts בלבד , והיא משמשת בתור enum )
  • שתי השפות יכולות לרוץ על כל מערכת הפעלה
    כן כן, גם למיקרוסופט יש גירסה ל-dot net שנקרא dot net core ורצה היטב על Linux .
  • ב-c# לפני הרצה צריך לבצע תהליך Build (קומפלייר)
    מה שנחסך מאיתנו כשעובדים ב-PHP
    זה יכול לקחת זמן לפעמים….וזה קטע מעצבן.

הבדלים מבחינת Enviroment  בין PHP ל- C# :

  • מנהל החבילות המוכר ב-PHP נקרא composer , בסביבת .Net קיים מנהל חבילות שנקרא NuGet
  • "על הנייר" נראה שיש פחות חבילות ל-C# , אבל זו השוואה ממש לא רלוונטית, כיוון שהרבה מאוד ספריות, מובנות כבר בתור השפה, ואין שום צורך בחבילה חיצונית.
    • דוגמא פשוטה לכך : ב-PHP נפוץ מאוד השימוש בספריה Carbon לצורך מניפולציות על תאריכים, לעומת זאת ב-C# , הספריה של DateTime כבר מובנה בשפה, ואין צורך לייבא אותה.
      נכון אומנם שגם ב-PHP יש ספרית DateTime, אך מהניסיון שלי, היא פחות נוחה לעבודה, וכיוון שכך – משתמשים ב-Carbon.
  • בסביבת מיקרוסופט, קיים IDE חזק, ללא תשלום, שנקרא Visual Studio , בא נגיד שאם מקבילים את זה לסביבת ה-PHP, אז זה כמו לקבל בחינם IDE ברמה של PHP Storm ( ואולי יותר מזה )
    • חיסרון מעצבן שלו  בכל זאת – זה שאין לו באופן מובנה ctrl+d לשכפול שורה, אך למרבה המזל, בגיגול פשוט, מוצאים תוספים שעושים זאת.
  • שרת Web – ב-PHP נהוג לעבוד עם Apache או Ngnix , לעומת סביבת dot net , שבה עובדים עם IIS.
  • אפליקציות Mobile – כאן יש יתרון עצום לסביבת מיקרוסופט, עם כלי שנקרא xamarin, ומאפשר לפתח אפליקציות שמתקפלות ל-Native , באותה שפה ( C# ) שבה אתה מפתח כרגיל.
    זה חוסך שימוש בפתרונות כמו PhoneGap \ Cordova וכדומה.
    והביצועים – בשמים.
  • כלי Debug :  ב-PHP נפוץ מאוד השימוש ב-xdebug , שההתקנה שלו עשויה להיות לפעמים סיזיפית ( חפשו ב-Youtube ותראו את כמות המדריכים בנושא ) .
    ה-Xdebug הוא תוספת ל-PHP שמאיטה מאוד את ההרצה.
    ב-C#, כלי ה-Debug מובנה בתוך Visual Studio, גם מאט מעט את ההרצה, אך פחות לעומת Xdbeug בתחושה האישית שלי.
  • הבדלים בתיעוד : 
    • מיקרוסופט מנצחת בגדול, הכל מתועד עד לפרטי פרטים,
      יחד עם זאת, קיים חיסרון של "יותר מדי מידע" ולפעמים קשה להבין איפה נמצא כל דבר בתור הררי התיעוד של מיקרוסופט.
    • לנקודה הזו יש יתרון מסויים נוסף מה קורה כאשר יש משהו לא ברור בתיעוד הרשמי ? – התיעוד של Laravel הוא מעולה בעיני, אך יש קטעים מסויימים בהם הוא כתוב גרו ( למשל ההסברים על IOC וקונספטים אחרים ) ובמקרה כזה – אין הרבה אפשרויות חוץ מלהתחיל לחפש בפורומים – שזה חיסרון .
      במיקרוסופט – בגלל עודף המקורות הרשמיים, אין הרבה צורך בפורומים. כי כמעט כל מה שתחפש כתוב בתיעוד הרשמי.

הבדלים ברמת ה- Framework  בין Laravel אל- ASP.NET MVC:

  • במבט ראשון, יש המון דברים מקבילים בין ASP.NET MVC ל- C#
  • זה מעלה מחשבות קלות של "מי העתיק ממי" אם כי, אני נוטה להניח שמיקרוסופט היו ראשונים, ו-Taylor היוצר של Laravel פשוט מימש את הדברים ב-Laravel כמו שהוא הכיר אותם לפני כן בסביבת מיקרוסופט.
  • לשתיהם יש ORM חזק, המקבילה של Eloquent ב-Laravel נקראת Entity ב-.Net
  • למרות שקיבלתי רושם שמפתחים רבים מסתייגים משימוש ב-Entity, לאחר מחקר קטן, זה כנראה חסר בסיס ( אולי בעבר היא הייתה נחותה מבחינת ביצועים, אך כיום ממש לא כך). מבחינת ביצועים – היא בסדר גמור לכל השאילתות הרגילות והפשוטות, כך שבשיקול עלות-תועלת של מהירות פיתוח מול ביצועים – זה בהחלט אופציה טובה.
  • גודל ההשקעה בפרוייקט – Laravel היא בסופו של דבר יציר כפיו של אדם אחד, עם מעט שותפים. קיימת כמובן קהילת Open Source גדולה וכו', אבל הוא ה-PO שלה חד משמעית (טיילור).
    ב-ASP.NET MVC זה מוצר של חברת ענק, ולפחות מבחינתי האישית זה היווה שיקול משמעותי בהחלטה לעבור, היות ואני לא נסמך על אדם אחד, עם קהילת קוד פתוח ( גדולה, ופעילה ככל שתהיה, כל עוד אין אינטרס כספי, לדעתי האישית, זה סיכון מסוים שצריך להילקח בחשבון).

הבדלים ברמת ביצועים בין C# ל- PHP :

  • אין כלל ספק ש-C# עולה בכמה רמות על PHP מבחינת ביצועים.
  • זה מורגש מעט בקטעי קוד שמבצעים עיבודים רציניים.
  • שפת C# היא שפה חצי-מתקמפלת , זה משליך על הביצועים משמעותית לטובה לעומת PHP.
  • עוד דברים שמשפיעים על ביצועים :
    • ב–C# התוכנה "נשארת" במצב ריצה כל הזמן, לעומת PHP שבה כל Request הוא מופע עצמאי שמתחיל מחדש.
    • החיבור ל-DB הוא קבוע ב-C#, לעומת PHP שבה החיבור נוצר בכל Request מחדש (לפי הצורך כמובן ) .
  • בקטעי קוד קטנים, אין הבדל מורגש בכלל בין השפות.
  • אומנם ב-PHP יש פתרונות לעבודה במקביל, אבל הם לא פשוטים ליישום כמו ב-C#  ( מספר תהליכים יחד).

 

סיכום – PHP לעומת C#

עניינים של בחירת שפה הפכו להיות נושאים "דתיים" לפעמים, אבל תכלס, כשבאים לבחון איזה כלי יותר טוב, בלי לערב שיקולים "כאילו-אידיאולוגים" של קוד פתוח וכו' – אז נראה שמיקרוסופט נותנת יותר ב-C# +ASP.NET MVC  לעומת PHP עם Laravel

יחד עם זאת, חייבים להודות שאם מישהו מחפש ללמוד במהירות שפת Web – אז PHP עדיפה משמעותית ..פשוט פותחים עמוד html, כותבים תגית php וזה רץ….

לדעתי, עקומת הלמידה לא כל כך משמעותית כדי להצדיק להתחיל עם PHP, בוא נגיד שאילו הייתי היום חוזר לאחור, אז הייתי מתחיל מראש עם c# , אבל כדי ללמד את הילדים בבית תיכנות הייתי בוחר ב-PHP .

המנצחת בעיני היא C# .

בהצלחה.

 

 

 

 

 

באגים ב-PHP בטיפול ב-XML באמצעות DomDocument \ SimpleXml

אני לא שותף למלחמות דת על "שפת התיכנות הטובה ביותר"

לרוב, מלחמות כאלו חסרות משמעות.

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

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

והסתבר לי עם הזמן שלספריות ש-PHP מציעה כדי לפענח XML, יש חסרונות עצומים.

  • אם הקובץ לא מגיע בקידוד המצופה ( למשל, הקובץ מוצהר כ-UTF-8 אבל בפועל הוא UTF-16LE )
    אז צריך לאתר זאת מראש, כי הפקודות שטוענות את הקובץ ומפרשות את ה-XML, לא יודעות לפענח את הקידוד השונה בעצמן.
  • שאילתות XPATH, לעיתים לא עובדות – מאוד תלוי "במצב הרוח" של הספריה.
    לדוגמא – DomDocument מסוגלת לבצע שאילתות XPATH בצורה טובה, ואז בלי סיבה מיוחדת – לא לעבוד.
  • לעיתים, ספריה אחרת יודעת לפרש את ה-XML, והספריה השניה לא מצליחה להתמודד איתו, ומחזירה false.

הפתרון שמצאתי בסופו של דבר קורא את הקובץ בספריה אחת ושומר אותו מחדש כדי שהספריה השניה תואיל בטובה לקרוא אותו בכל מצב.

זה אומנם עובד, אך גובה מחיר יקר בזמן עיבוד שבמקרה שלי הוא אקוטי כיוון שהלקוח יושב וממתין…

המצב הזה הוא ממש גרוע. ולצערי במקרה הזה – כל קובץ שהייתי צריך לבצע מניפולציות עליו ב-PHP, כאשר ניסיתי לפרש אותו עם VB , בספריה עתיקה ביותר של מיקרוסופט (MSXML 6 )  – זה הצליח תמיד , הרבה יותר מהיר, וללא שום בעיות.

במקרה הזה, יש לי רק מחמאות למיקרוסופט, הספריה העתיקה שלהם, עובדת מעולה.

מצבים כאלו, יוצרים תיסכול, כיוון שאילו זו הייתה ספריה אחת מתוך כמה – אז הייתי משתמש באחרות. אבל ב-PHP, נוצר מצב ש-2 הספריות העיקריות לא עושות את העבודה. ברוב הקבצים – ברור ששתיהן עובדות כמו שצריך.  אבל כשמגיעים קבצים עם קידוד בעייתי ועוד…כל ספריה מתנהגת בצורה בלתי צפויה בפקודות שלה.

מה המסקנה ?

אז אומנם php היא שפה מאוד כייפית לפיתוח, ומכילה כמות עצומה של פקודות וספריות, קהילה תומכת וכו' וכו'

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

חבל …אבל זה מה יש.

אם יש לכם קבצי xml שאתם הייצרנים שלהם , ו- php היא שפת הפיתוח שלכם, אז תישארו איתה. אבל כשיש קבצי xml שאתם לא שולטים במקור שלהם, ויש סיכוי לקבצים עם בעיות …תבחרו שפה אחרת כדי לקרוא אותם. זו ההמלצה שלי.

שימוש ב-WebApi של SendGrid עבור משלוח מיילים ( לא באמצעות SMTP )

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

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

לצורך כך השתמשתי ב-WebAPI של SendGrid.

מה היתרון של WebAPI על פני שימוש רגיל ב-SMTP ?

כל ספקי האחסון השיתופיים חוסמים מיילים ב-SMTP בצורה זו או אחרת (מגבלה יומית, שעתית, שבועית וכדומה). כאשר שליחת המיילים מנוטרת דרך port 25/26/465 עבור משלוח מיילים ב-Smtp.

אז כדי לעקוף את המגבלה, ל-SendGrid יש WebApi מאוד נוח ומאוד קל לתפעול.

יחד עם זאת התיעוד סביר – אך היה יכול להיות יותר טוב.

אני השתמשתי בגירסה עבור php ( קישור ל-git פה )

התקנת הספריה ב-php באמצעות composer

(אני מניח שאתם משתמשים ב-composer, אם לא, אפשר גם להוריד את הספריה בגיט ולעשות לה require בעצמכם )

בחלק של ה-require בתוך composer.json תוסיפו הפניה לספריה שלהם:

{
  "require": {
    "sendgrid/sendgrid": "~5.0.7"
  }
}

ולאחר מכן להריץ composer update דרך שורת הפקודה (console).

להשיג Api Key בחשבון שלכם ב-SendGrid

כעת – גשו לחשבון שלכם ב-SendGrid והפיקו לעצמכם API KEY , עם ההרשאות שדרושות ( ניתן לשינוי בהמשך , אך הקוד עצמו מופיע רק פעם אחת על המסך ).

והחלק האחרון – המשלוח עצמו.

דוגמא למשלוח מייל באמצעות WebAPI של SendGrid ב-php

הנה דוגמא פשוטה :

הערות : הקוד פה חלקי בלבד .

הקוד מתבסס על use שלא הדבקתי פה.

ואני כותב ב-Laravel ולכן הפונקציה View עם מתודת render().

try {
    $from = new SendGrid\Email(self::SENDER_NAME, self::MANAGER_EMAIL);
    $subject = $e->subject;
    $to = new SendGrid\Email(null, $e->To);
    $body = view('emails.emailWithButton', [
        'body' => $e->body,
        'button' => $e->btn,
        'link' => $e->link,
        'title' => $e->subject])->render();
    $content = new SendGrid\Content("text/html", $body);
    $mail = new SendGrid\Mail($from, $subject, $to, $content);

    $sg = new \SendGrid($apiKey);

    $response = $sg->client->mail()->send()->post($mail);
    echo $response->statusCode();
    echo $response->headers();
    echo $response->body();


ובצורה הזו – שולחים מייל באמצעות API.

התשובה המוחזרת – היא מאוד נוחה ומכילה מידע , שעבורי אומנם לא היה שימושי, אבל אולי לאנשים אחרים הוא יהיה לעזר.

בהצלחה.

 

התקנת yii2 על linux ללא composer

מורידים את הקובץ tar מכאן http://www.yiiframework.com/download/

לאחר מכן,
מעתיקים אותו לתיקית ה-web שלכם.

נותנים לו הרשאות מלאות (אפשר פשוט לתת בעלות ליוזר של apache, באמצעות chown )

ואז גולשים בדפדפן אל התיקיה ו-גמרנו.

http://localhost/basic/web/index.php

הערה : אומנם לפי התיעוד הרשמי, אמורים להיכנס לתיקית config, ולערוך את קובץ web.php – ולרשום בו סיסמא כלשהיא להצפנת ה-cookies , בערך cookieValidationKey, אבל אם אתם מורידים את פרויקט ה-basic/advanced , ולא פריימוורק ריק, אז זה קיים כבר.

אם מסיבה כלשהיא זה לא עובד , ניתן לבצע בדיקה של דרישות ברירת המחדל באמצעות גלישה אל http://localhost/basic/requirements.php

או הפעלה של קובץ זה משורת הפקודה.

הגדרות מומלצות עבור ה-Apache בשביל yii2 בסביבת production

בשרת production, היינו רוצים לגלוש לאפליקציה/אתר שלנו ישירות כך : http://www.example.com/index.php

ולא כך : http://www.example.com/basic/web/index.php

לשם כך נדרש להפנות את ה-Virtual host ישירות אל תיקית  basic/web.

בנוסף נרצה בוודאי להסתיר את index.php משורת הכתובת.

כדי לבצע את הדברים האלו, יש להגדיר בקובץ httpd.conf , או בתוך הקובץ שמגדיר את ה-virtual host, את ההגדרות הבאות :

# Set document root to be "basic/web"
DocumentRoot "path/to/basic/web"

<Directory "path/to/basic/web">
    # use mod_rewrite for pretty URL support
    RewriteEngine on
    # If a directory or a file exists, use the request directly
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    # Otherwise forward the request to index.php
    RewriteRule . index.php

    # ...other settings...
</Directory>

יש לזה יתרונות נוספים, ברגע שמגדירים את bsic/web כתיקית ברירת המחדל של ה-virtual host, מונעים למעשה מהגולשים אפשרות לגשת לתיקיות פנימיות רגישות, שהם אינם צריכים לראות.

זכויות יוצרים : המדריך פורסם לפי התנאים של Yii , והמקור נמצא בקישור הבא :  http://www.yiiframework.com/doc-2.0/guide-start-installation.html

מדריך Yii 2 – אפליקצית "שלום עולם"

המדריך הזה מתאר איך ליצור אפליקצית "שלום עולם"  על מנת לבצע זאת, אנו ניצור action וגם view :

  • האפליקציה תשלח בקשה (request)  לדף אל ה-action
  • ואז ה-action תייצר את ה-view ותציג את המילה Hello אל הגולש.

במסגרת מדריך זה תלמד 3 דברים :

  • איך ליצור action – פעולה שמגיבה לבקשה (=request)
  • איך ליצור view שיציג את תוכן המענה לבקשה (=response)
  • איך האפליקציה שולחת בקשות (requests ) אל actions.

איך ליצור Action ב- Yii

כדי ליישם את אפליקצית שלום עולם ב-Yii אנחנו ניצור action שיקרא say. ה-Action הזה, היא פונקציה של מחלקה, שתקבל פרמטר בשם message מה-request  ותציג את ההודעה לגולש.

אם ה-request נשלחה ללא הפרמטר message , אז ה-action תציג את ברירת המחדל – המילה Hello.

מה זה בעצם Action ב- Yii ?

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

התוצאה של ביצוע Action – היא מה שהגולש מקבל (מכונה גם response).

דוגמא להגדרת Action ב- Yii

כל Action חייבת להיות מוגדרת בתוך Controller. לצורך הפשטות, נגדיר כעת את ה-Action בשם say בתוך Controller שכבר קיים, שנקרא SiteController.

ה-Controller הזה הוא מחלקה שמוגדרת בקובץ controllers/SiteController.php.

כך יש להגדיר את ה-Action בשם say :

<?php

namespace appcontrollers;

use yiiwebController;

class SiteController extends Controller
{
    // ...existing code...

    public function actionSay($message = 'Hello')
    {
        return $this->render('say', ['message' => $message]);
    }
}

הסבר הקוד : ה-Action שנקראת say, הוגדרה כמתודה בשם actionSay בתוך המחלקה SiteCotroller.  כדי להפריד מתודות שהן actions ממתודות אחרות , Yii דורשת שכל action יתחיל במילה action באותיות קטנות. השם שמופיע מייד אחרי המילה action הוא השם המזהה של ה-action, שמכונה גם action ID.

כללים למתן שמות ל-Actions ב- Yii

נפריד בין הצורה שה-action נקרא בתוך המערכת, ובין השם שבו הוא נקרא כאשר מגדירים את המתודה.

שמות של actions בתוך המערכת (=מה שנקרא action's ID )

  1. תמיד באותיות קטנות,.
  2. כאשר אם השם מורכב ממספר מילים, יש להפריד בין המילים באמצעות מקףלמשל create-comment.

המתודה של ה-Action צריכה תמיד להיות

  1. בפורמט CamelCased (=אות ראשונה של כל מילה היא אות גדולה, ללא רווח בין המילים)
  2. עם המילה action באותיות קטנות בתחילת שם המתודה .

למשל : actionCreateComment

במקרה שלנו, ה-Action מקבלת פרמטר במשתנה $message . כאשר הגדרנו ערך ברירת מחדל למשתנה זה – המחרוזת "Hello" (בדיוק בצורה הרגילה שבה מגדירים ערך ברירת מחדל לכל משתנה בפונקציות php).

כאשר האפליקציה תקבל request  ותחליט שהפעולה הנדרשת היא הפעולה say , אז האפליקציה תיקח את הפרמטר שהתקבל ב-request (נניח ב-get בשורת הכתובת) ותעביר אותו את הפונקציה actionSay.

בתוך המתודה actionSay השתמשנו במתודה render() שמה שהיא עושה – היא מחוללת view, על בסיס קובץ view שגם הוא נקרא say.

הפרמטר message מועבר אל ה-view , כדי שנוכל להשתמש בו שם. התוצאה של יצירת ה-view מוחזרת באמצעות ה-Action.

מוחזרת לאן ? – התוצאה מוחזרת לאפליקציה ומוצגת לגולש בדפדפן.

 איך יוצרים View ב- Yii ?

במונח Views מתכוונים לסקריפטים שאתה כותב, כדי לייצר תצוגה של הדף. למשל, במשימה שלנו, אנחנו צריכים לכתוב דף שיציג את הביטוי "שלום עולם" או כל ביטוי אחר שנעביר דרך המשתנה message. לצורך כך אנחנו ניצור view שיקרא בשם say,  שמטרתו להציג את תוכן הפרמטר message. את הפרמטר הוא יקבל מה-action שזה עתה בנינו.

צור קובץ php חדש, ושתול בו את הטקסט הבא :

<?php
use yiihelpersHtml;
?>
<?= Html::encode($message) ?>

הערה חשובה : בדוגמא הזו, נעשה שימוש בקיצור הקוד הבא <?= , והיות והוא לא מוכר לרבים, אז אתן הסבר קצרצר : הקיצור הזה הוא בדיוק כמו לכתוב את הקוד הבא

<?php echo .....bla bla bla

כלומר, במקום לכתוב את תגית הפתיחה המלאה של php, ואת המילה echo, אם משתמשים בקיצור הזה, חוסכים בעצם בכתיבה בכך שרושמים רק 3 תוים.

כדי שזה יעבוד , אז ב-php.ini האפשרות short_open_tag חייבת להיות מאופשרת.

את הקוד ההוא של ה-view שנקרא say עליך לשמור בקובץ /views/site/say.php. ואז, כאשר המתודה render() תופעל בתוך ה-action, היא תחפש קובץ במיקום הבא : views/ControllerID/viewName.php.

שים לב, בקוד פה, עטפנו את הפרמטר message בפקודה HTML-encoded לפני שהדפסנו אותו על המסך.

למה זה טוב ? – זוהי שיטה מקובלת ונחוצה מאוד, כדי למנוע מתקפות XSS באמצעות משלוח של קוד JS זדוני דרך הפרמטר הזה.

בתוך View אתה שם את כל הקוד שמוצג למשתמש, זאת אומרת, תגי Html, טקסט חופשי, וכו' וכו'. מה שקורה בפועל הוא שאחרי שהמתודה render() מופעלת, אז התוכן שמיוצר באמצעות ה-view (שנקראת say בדוגמא שלנו) מוחזר אל האפליקציה ומוצג לגולש, בתור מענה (=response) .

נסה את זה בעצמך !

כעת, הגיע זמן לגלוש אל הכתובת, ולראות שהכל עובד.

הכתובת היא

http://hostname/index.php?r=site/say&message=Hello+World

ואתה צריך לקבל דף שיראה כך :

אפליקצית שלום עולם ב- Yii
אפליקצית שלום עולם ב- Yii

 

הכתובת הזו הובילה לתוצאה של עמוד "Hello World". כאשר העמוד קיבל את אותו Header+fotter של שאר עמודי האפליקציה.

אם תמחק מה-URL את הפרמטר message, ותרענן את הדף, תוכל לראות שתתקבל המילה "Hello". זה מפני שהפרמטר message קיבל את המילה "Hello" בברירת מחדל בפונקציה actionSay.

כדאי לדעת : הדף החדש שיצרנו מקבל את אותו Header+Footer כמו שאר הדפים באפליקציה, כיוון שהמתודה render() מוסיפה אותם באופן אוטומטי לכל view, מתוך מה שנקרא layout, ומאוחסן במקרה שלנו במיקום views/layouts/main.php.

מה משמעות הפרמטר r בכתובת ?

הפרמטר r הוא קיצור של המילה route כלומר – ניתוב. זוהי הצורה ב-Yii לפנות אל action ספציפי. כאשר בכל פעם שנראה לפנות ל-action נציין זאת בתבנית הבאה ControllerID/ActionID.

ואז, כאשר האפליקציה מקבלת request היא בודקת את הפרמטר הזה, ופונה אל המחלקה של ה-ControllerID המתאים, ובתוכה אל המתודה של ה-ActionID המתאים, כדי לבצע את הפעולה שהתבקשה דרך ה-URL. בדוגמא שלנו, היא פנה אל ה-Controller שנקרא SiteController ובתוכו אל ה-Action שנקראת say . וכתוצאה, הפעלנו למעשה את המתודה  SiteController::actionSay() כדי לבצע את הפעולה.

חשוב לדעת : בדיוק כמו הכללים לכתיבת שמות של actions. גם ל-controllers יש כללים מחייבים עבור השמות שלהם. אותם כללים בדיוק. כלומר, שם המחלקה של ה-Controller מורכב ממילים בפורמט CamelCased (כל מילה מתחילה באות גדולה, ללא רווחים). ובסוף הביטוי יש להוסיף את המילה Controller.
לדוגמא : אם ה-Controller ID הוא post-comment, אזי שם המחלקה יקרא PostCommentController.

סיכום – אפליקצית "שלום עולם" ב-Yii.

במדריך הזה :

  • נגעת במושגים controller , view ששיכים לשיטת הפיתוח MVC.
  • יצרת action שהיא חלק מ-controller כדי לטפל ב-request מסוים.

במדריך הזה, לא נעשה שימוש ב-model כלל, והמידע היחיד שהשתמשנו בו, היה הפרמטר message.

בנוסף למדת על ניתוב (route) ב- Yii, שמהווה מעין גשר בין ה-request של המשתמש ובין המתודות (=actions) של ה-Controller.

בפרק הבא תלמד כיצד ליצור model. וכיצד להוסיף דפים חדשים הכוללים טפסי HTML.

 

זכויות יוצרים : המדריך פורסם לפי התנאים של Yii , והמקור נמצא בקישור הזה.

מדריך Yii – עבודה עם טפסים

אחרי המדריך הקודם, בו תיארנו את ה-Actions וה-Views , המדריך  זה מתאר איך ליצור דף חדש באתר,  עם טופס לקבלת נתונים ממשתמשים. בדף שניצור יהיה טופס עם 2 שדות : שם + אימייל. ואחרי שנקבל את הפרטים האלו מהגולש, נבדוק אותם, ונציג אותם חזרה למשתמש.

כדי לבצע את המשימה הזו – יצירת דף עם טופס, צריך ללמוד גם ליצור model (אחרי שלמדנו כבר על view, action ).

במדריך הזה נלמד :

  • ליצור model
  • איך רושמים כללים לאימות/validation של הנתונים במודל
  • לבנות טופס Html באמצעות Yii

יצירת מודל ב- Yii

הגולש יכניס נתונים לתוך טופס, את הנתונים, אנחנו נשמור בתוך מחלקה מסוג model  בקובץ  models/EntryForm.php. (אם אתה עדין לא מכיר את הכללים ליצירת שמות קבצים ומחלקות, עיין בסעיף AutoLoading).

<?php

namespace appmodels;

use yiibaseModel;

class EntryForm extends Model
{
    public $name;
    public $email;

    public function rules()
    {
        return [
            [['name', 'email'], 'required'],
            ['email', 'email'],
        ];
    }
}

 

המחלקה שיצרנו מרחיבה (extends) את המחלקה yiibaseModel , שהיא מחלקה בסיסית ש-Yii מספקת לנו, עבור מודלים.

הערה : המחלקה yiibaseModel משמשת ליצירת מודלים שלא מבוססים על DB, עבור מודלים שמבוססים על DB יש מחלקה אחרת שנקראת yiidbActiveRecord.

המחלקה EntryForm מכילה 2 משתנים ציבוריים : name,email. המשתנים האלו ישמשו לאחסון המידע שהגולש יקליד בטופס.

בנוסף, המודל מכיל גם מערך של כללים , המשמשים לבדיקת הנתונים (validition), יש שם 2 כללים :

  • 2 השדות הם חובה
  • האימייל חייב להיות אימייל תקין

נניח ויש לך אוביקט של EntryForm שמכיל כבר את הנתונים מהגולש, ואתה מעוניין רק לבדוק אותו , לעשות לו וואלידציה, אז הקוד יראה  כך  (אם הוואלידציה לא מצליחה, תקבל hasErrors  = false והשגיאות יופיעו באוביקט errors ) :

<?php
$model = new EntryForm();
$model->name = 'Qiang';
$model->email = 'bad';
if ($model->validate()) {
    // Good!
} else {
    // Failure!
    // Use $model->getErrors()
}

יצירת Action

כעת, צריך ליצור Action שיקרא Entry בתוך ה-Controller , כאשר ה-Action , יעשה שימוש במודל החדש שיצרנו.

<?php

namespace appcontrollers;

use Yii;
use yiiwebController;
use appmodelsEntryForm;

class SiteController extends Controller
{
    // ...existing code...

    public function actionEntry()
    {
        $model = new EntryForm;

        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            // valid data received in $model

            // do something meaningful here about $model ...

            return $this->render('entry-confirm', ['model' => $model]);
        } else {
            // either the page is initially displayed or there is some validation error
            return $this->render('entry', ['model' => $model]);
        }
    }
}

המתודה actionEntry , מתחילה בכך שהיא  יוצרת אובייקט EntryForm.
לאחר מכן, המתודה מנסה להכניס את הנתונים שהגיעו ב-Post אל תוכל המודל, ולשם כך המתודה נעזרת ב yiiwebRequest::post() שמסופק על yii.  אם המתודה מצליחה להכניס את הנתונים למודל היא קוראת לפונקציה validate() כדי לוודא שהנתונים שהוקלדו נכונים.

מידע: הביטוי  Yii::$app הוא מופע (instance) של אוביקט  application  (אוביקט עם מופע יחיד – סינגלטון).  הוא מאפשר לנו לגשת לאוביקטים חשובים, כמו כמו request, response, db. בדוגמא הספציפית שלנו, הוא איפשר לנו לגשת לאוביקט request ולמשוך מתוכו את הנתונים שהגיעו ב-Post.

אם הכל תקין בטופס, אז ה-Action תקרא לפונקציה render() כדי ליצור view בשם entry-confirm .

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

הערה: זוהי דוגמא ממש פשוטה, ולכן רק יצרנו "דף אישור" אחרי שהטופס עובר בהצלחה, אבל ברור שבמקרים אמיתיים, צריך להשתמש בפעולות אחרות, כמו למשל refresh() או redirect() , כדי להימנע מבעיות של שליחה-מחדש של טפסים.

יצירת Views

השלב האחרון במדריך הוא ליצור 2 קבצי view, אחד יקרא בשם entry-confirm  והשני יקרא פשוט entry. ה-view שיקרא entry-confirm פשוט מציג את הנתונים שהוקלדו בטופס.

צור קובץ במיקום views/site/entry-confirm.php :

<?php
use yiihelpersHtml;
?>
<p>You have entered the following information:</p>

<ul>
    <li><label>Name</label>: <?= Html::encode($model->name) ?></li>
    <li><label>Email</label>: <?= Html::encode($model->email) ?></li>
</ul>

הקובץ השני הוא views/site/entry.php והוא יכיל את טופס ה-html עצמו :

<?php
use yiihelpersHtml;
use yiiwidgetsActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, 'name') ?>

    <?= $form->field($model, 'email') ?>

    <div class="form-group">
        <?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
    </div>

<?php ActiveForm::end(); ?>

בקוד של ה-view הזה בטח הבחנת שאנו משתמשים ב-widget עוצמתי של Yii שנקרא ActiveForm כדי לבנות את טופס ה-Html. המתודות begin() ו- end() יוצרות את תגי הפתיחה והסיום של הטופס, והמתודה field() מציגה שדה בודד.

לסיום המתודה yiihelpersHtml::submitButton()  מייצרת כפתור Submit לשליחת הנתונים.

נסה את זה בעצמך

כדי לנסות את הטופס החדש באפליקציה גלוש אל

http://hostname/index.php?r=site/entry

אם תשחק עם הטופס ותנסה להקליד נתונים שגויים וללחוץ submit תראה שתקבל הודעות שגיאה, כמו בתמונה הבאה :

אך לעומת זאת אם תקליד נתונים שעומדים בכלל הוואלידציה תקבל את ה-view שיצרת שנקרא entry-confirm שנראה כך :

 איך הוודליאציה עובדת בלי רענון של הדף (מה הטריק ? )

הרכיב שנקרא yiiwidgetsActiveForm הוא רכיב חכם שמייצר בעצם 2 נדבכים של וואלידציה, הראשון הוא JavaScript , ורק במידה ואצל הגולש – ה-JS לא מופעל בדפדפן, אזי בכל מקרה, תהיה גם וואלידציה בצד השרת (php כמובן).

ותגיות ה-label מיוצרות אוטומטית באמצעות הפונקציה field().

אם אתה מעוניין לשנות את ה-labels, אפשר לשנות אותם בצורה הבאה:

<?= $form->field($model, 'name')->label('Your Name') ?>
<?= $form->field($model, 'email')->label('Your Email') ?>

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

 סיכום – טפסים ב-Yii

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

בנוסף, ראינו איך ליצור טפסי Html ואיך להשתמש ב-widgets של Yii.
במדריך הבא, נראה איך לעבוד עם DBs .

המדריך מפורסם לפי התנאים של Yii , והמקור נמצא כאן .

 

 

 

סיכום מתומצת בעברית CakePHP – חלק 1

מבנה תיקיות:
בתיקיה הראשית יש 3 תיקיות:
app – התיקיה בה אתה יוצר את האפליקציות
lib – תיקית המנוע, בה אסור לגעת
vendors – תיקיה לספריות חיצוניות שבהן משתמשים.
בנוסף התיקיה מכילה קובץ Index.php וגם קובץ htaccess.

מבנה תיקית app :

תיקית app מכילה מספר תיקיות :
config – קבצי הגדרות, קישור לדאטאבייס, bootstarp וכדומה.
console – פקודות ל-Console. וניתן להכיל בתוך התיקיה הזו גם Templates.
תיקיות Controller / Model / View – אין מה לפרט, לפי מודל ה-MVC.
Lib – עוד תיקית לסריות חיצוניות, למה יש גם כאן וגם בתיקית האם ? כדי להפריד ספריות של ספקים חיצונים שיאוחסנו בתוך vendors בתיקית האם, ולעומת זאת ספריות שאתה כותב, יאוחסנו כאן.
locale – קבצי תרגום לשפות שונות.
plugin … ברור.
test – מכילה את כל ה-test cases, פירוט בהמשך.
tmp – לוגים, לפעמים שמירה של Sessions ועוד. התיקיה חייבת להיות קיימת, ועם הרשאות כתיבה.
Vendor – ספריות של ספקים חיצוניים . ברגע ששמים אותם כאן, אפשר לקרוא לפונקציות שלהם בצורה הרגילה
כלומר App::import('vendor','name'); הסיבה לכפילות עם תיקיה דומה בתיקית האם תוסבר בהמשך.

webroot – בסביבת יצור, זו תיקית האם, ובתוכה יהיו גם קבצי CSS, JS, תמונות וכדומה.

מקור : http://book.cakephp.org/2.0/en/getting-started/cakephp-folder-structure.html

מוסכמות במתן שמות ב- CakePhp

מוסכמות של מתן שמות, הן עניין גדול ב-CakePhp שאם שומרים עליו מסייע רבות לכל אורך הדרך.

מוסכמות שמות עבור Controller

– נכתבים בלשון רבים
– מסתיימים במילה Controller
למשל : PeopleController and LatestArticlesController

המתודה הראשונה של קונטרלר היא תמיד index() .
ולכן כאשר מבצעים request לקונטרולר, זו המתודה שמוחזרת כברירת מחדל.
למשל הכתובת http://www.example.com/apples/ מחזירה את המתודה index() של אוביקט ApplesController.
כאשר ה-View של אותו אוביקט יהיה בכתובת http://www.example.com/apples/view/
ויקרא למתודה view() של אוביקט ApplesController.

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

class NewsController extends AppController {

    public function latest() {
        $this->_findNewArticles();
    }

    protected function _findNewArticles() {
        // Logic to find latest news articles
    }
}

אז הגישה למתודה תהיה דרך http://www.example.com/news/latest/ אבל מי שיקליד http://www.example.com/news/_findNewArticles/ יגיע לדף שגיאה.

מבנה URL לפי המוסכמות של קונטרולרים

כל עוד הקונטרולר כתוב לפי המוסכמות, אז מספיקה מילת השם שלו, בלשון רבים, באותיות קטנות בתור URL.
למשל, קונטרולר בשם ApplesController – ניגש אליו באמצעות הכתובת http://example.com/apples.

לגבי ביטויים שמורכבים ממספר מילים, אפשר להשתמש בכל הצורות של החיבור (עם /בלי מקף תחתון בין המילים, וכאשר כל מילה מתחילה באות גדולה או קטנה). אבל יחד עם זאת, ה-URL תמיד יהיה אותיות קטנות, עם מקף תחתון.
למשל אם יש לנו מתודה RedApplesController::go_pick , אז ה-URL שלה יהיה /red_apples/go_pick

מוסכמות לשמות קבצים ושמות Class

שמות קבצים ושמות קלאסים תמיד CamelCased כלומר כל מילה מתחילה באות גדולה. שם הקובץ יהיה אותו דבר בדיוק עם נקודה והסיומת php.

לדוגמא :
הקלאס יקרא MyNiftyClass
אז הקובץ יקרא MyNiftyClass.php

עוד דוגמא לקלאס EspeciallyFunkableBehavior , אז שם הקובץ יהיה EspeciallyFunkableBehavior.php .

אם יש לי קונטרולר אז הוא יקרא KissesAndHugsController
ושם הקובץ יקרא MyHandyComponent.php

אם יש לי מודל שנקרא OptionValue
אז שם הקובץ יהיה OptionValue.php

כל קובץ כמובן בתיקיה שבה הוא צריך להיות.

מוסכמות לגבי שמות מודל ושמות של רכיבים בדאטאבייס

שמות של קלאסים במודל, הם תמיד CamelCased, בלשון יחיד. למשל Person, BigPerson, and ReallyBigPerson.

שמות של טבלאות שתואמות למודלים הן תמיד בלשון רבים, והמילים מופרדות בקו תחתון. למשל people, big_people, and really_big_people.

יש בקישור הזה הסבר על היכולות של יחיד/רבים ב-CakePHP.

שמות שדות שמורכבות מכמה מילים, מופרדות בקו תחתון. my_field

שמות של מפתחות זרים מורכבים משם הטבלה המקורית עם סיומת _id למשל., אם לאופה אחד יש הרבה עוגות, אז המפתח הזר שמתייחס לטבלה bakers יקרא בשם baker_id (מה שמסביר שוב פעם למה שמות הטבלאות הן בלשון רבים).

אם יש טבלאות שעושים להם join בקשר hasAndBelongsToMany , אז קוראים להם בשם טבלאות המודל שהם מצרפות יחד , בסדר אלפביתי, נניח אני עושה join לטבלאות apples וגם zebras אז המודל יקרא apples_zebras כי a הוא לפני z.

כל טבלה ב-CakePHP חייבת מפתח ראשי יחיד, הפריימוורק לא מטפל במפתחות ראשיים מורכבים (כלומר מכמה שדות יחד).
כלומר אם יש לך טבלה שאתה רוצה להשתמש בה עם הפריימוורק אתה חייב שיהיה לה מפתח ראשי יחיד.
(אפשר לעשות שאילתות לעדכון מפתחות מורכבים באמצעות הפונקציה query).

המפתח הראשי יכול להיות מספר רץ (auto-increment ) או char(36) ואז יש מתודה שנקראת String::uuid שנותנת לו מפתח.

מוסכמות לגבי View

שמות של הקבצים שמכילים את ה – view, הם תמיד מורכבים משמות הפונקציות של הקונטרולר שאותו הן מציגות , אבל עם קו תחתון.
למשל הפונקציה getReady() ששייכת לקונטרולר PeopleControler , תחפש את ה-View שלה כאן /app/View/People/get_ready.ctp

דוגמא אחרונה, שמסכמת הכל ומציגה שאפשר להשתמש גם בלשון רבים שמובנה בתוך המילה, ולאו דווקא עם S בסוף :
Database table: “people”
Model class: “Person”, found at /app/Model/Person.php
Controller class: “PeopleController”, found at /app/Controller/PeopleController.php
View template, found at /app/View/People/index.ctp

המבנה הוא תמיד /app/View/Controller/underscored_function_name.ctp

מקור : http://book.cakephp.org/2.0/en/getting-started/cakephp-conventions.html