Menu
Coddy logo textTech

סיבים (PHP 8.1)

חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 60 מתוך 91.

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

צרו fiber על ידי העברת callable למחלקה Fiber, ואז התחילו אותו באמצעות start():

<?php
$fiber = new Fiber(function(): void {
    echo "Step 1\n";
    Fiber::suspend();
    echo "Step 2\n";
});

$fiber->start();
echo "Between steps\n";
$fiber->resume();

פלט:

Step 1
Between steps
Step 2

הסיב ממשיך לפעול עד שהוא מגיע ל־Fiber::suspend(), ואז השליטה חוזרת לקוד הראשי. קריאה ל־resume() ממשיכה את הביצוע מהמקום שבו הוא נעצר.

סיבים יכולים גם להעביר ערכים בעת השהיה וחידוש:

<?php
$fiber = new Fiber(function(): string {
    $value = Fiber::suspend("paused");
    return "Received: $value";
});

$suspended = $fiber->start();
echo "$suspended\n";

$result = $fiber->resume("hello");
echo $result;

פלט:

paused
Received: hello

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

challenge icon

אתגר

קל

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

תארגנו את הקוד שלכם בשני קבצים:

  • TaskRunner.php: צרו מחלקה בשם TaskRunner שעוטפת את הפונקציונליות של סיבים לצורך הרצת משימות. המחלקה צריכה:
    • להכיל מאפיין פרטי לאחסון מופע של Fiber
    • לקבל שם משימה (מחרוזת) בבנאי שלה, באמצעות קידום מאפיינים בבנאי
    • להכיל מתודה createTask(callable $task) שיוצרת Fiber חדש עם ה-callable הנתון ושומרת אותו
    • להכיל מתודה start() שמתחילה את הסיב ומחזירה כל ערך שהסיב מושהה איתו (או את ערך ההחזרה הסופי)
    • להכיל מתודה continue(mixed $value) שמחדשת את הסיב עם הערך הנתון ומחזירה את הערך הבא שהסיב מושהה איתו (או את ערך ההחזרה הסופי)
    • להכיל מתודה isFinished(): bool שמחזירה אם הסיב הסתיים
  • main.php: כללו את קובץ ה-TaskRunner. תקבלו שתי קלטים: שם משימה והודעה לשליחה לסיב.

    צרו TaskRunner עם שם המשימה הנתון, ואז השתמשו ב-createTask() כדי להגדיר משימה ש:

    1. מושהית תחילה עם המחרוזת "Waiting for input"
    2. מקבלת ערך כשהיא מתחדשת
    3. מחזירה "Completed: [received value]"

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

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

נסו בעצמכם

<?php

require_once 'TaskRunner.php';

// קרא את הקלטים
$taskName = trim(fgets(STDIN));
$message = trim(fgets(STDIN));

// TODO: צור TaskRunner עם שם המשימה שניתן

// TODO: השתמש ב-createTask() כדי להגדיר משימה ש:
// 1. תחילה מושהית עם המחרוזת "Waiting for input"
// 2. מקבלת ערך כשהיא מחודשת
// 3. מחזירה "Completed: [received value]"

// TODO: התחל את המשימה והדפס את מה שהיא מחזירה כשהיא מושהית לראשונה

// TODO: הדפס "Processing..." כדי להראות שמתבצעת עבודה בין ההשהיות של ה-fiber

// TODO: המשך את ה-fiber על ידי העברת קלט ההודעה אליו

// TODO: הדפס את התוצאה הסופית

?>
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר PHP אונליין