עיבוד נתוני API חיצוניים בבלוקים של וורדפרס ב- Back End PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

עיבוד נתוני API חיצוניים בבלוקים של וורדפרס בקצה האחורי

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

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

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

איפה שהפסקנו

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

ובכן, זה עשוי להיות שימושי במצבים שבהם ייתכן שתצטרך להשתמש בפונקציית WordPress או PHP מקורית כדי ליצור בלוקים דינמיים. אבל אם אתה רוצה להשתמש רק במערכת האקולוגית של JavaScript ו-React (JSX, ספציפית) של וורדפרס כדי להציג את ה-HTML הסטטי יחד עם התכונות המאוחסנות במסד הנתונים, אתה רק צריך להתמקד ב- Edit ו Save פונקציות של תוסף הבלוק.

  • אל האני Edit הפונקציה מעבדת את התוכן על סמך מה שאתה רוצה לראות בעורך החסימה. אתה יכול לקבל רכיבי React אינטראקטיביים כאן.
  • אל האני Save הפונקציה מעבדת את התוכן על סמך מה שאתה רוצה לראות בחזית הקצה. אתה לא יכול לקבל את הרכיבים הרגילים של React או את הווים כאן. הוא משמש להחזרת ה-HTML הסטטי שנשמר במסד הנתונים שלך יחד עם התכונות.

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

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

אביזרי הבלוק

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

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

אם נרשום את props אובייקט למסוף, הוא מחזיר רשימה של פונקציות ומשתנים של וורדפרס הקשורים לחסימה שלנו:

עיבוד נתוני API חיצוניים בבלוקים של וורדפרס בקצה האחורי

אנחנו צריכים רק את attributes האובייקט וה setAttributes פונקציה שאני הולך להרוס מה- props אובייקט בקוד שלי. במאמר האחרון, שיניתי את הקוד של RapidAPI כך שאוכל לאחסן את נתוני ה-API דרך setAttributes(). אביזרים ניתנים לקריאה בלבד, כך שאיננו יכולים לשנות אותם ישירות.

אבזרי בלוק דומים למשתני מצב ו setState ב-React, אבל React עובד בצד הלקוח ו setAttributes() משמש לאחסון התכונות לצמיתות במסד הנתונים של וורדפרס לאחר שמירת הפוסט. אז מה שאנחנו צריכים לעשות זה להציל אותם attributes.data ולאחר מכן קרא לזה כערך ההתחלתי של ה useState() משתנה

אל האני edit פונקציה

אני הולך להעתיק ולהדביק את קוד ה-HTML שבו השתמשנו football-rankings.php במאמר האחרון וערוך אותו מעט כדי לעבור לרקע JavaScript. זוכרים איך יצרנו שני קבצים נוספים במאמר האחרון לסגנון החזיתי והתסריטים? עם האופן שבו אנחנו ניגשים לדברים היום, אין צורך ליצור את הקבצים האלה. במקום זאת, נוכל להעביר את כל זה ל- Edit פונקציה.

קוד מלא
import { useState } from "@wordpress/element";
export default function Edit(props) {
  const { attributes, setAttributes } = props;
  const [apiData, setApiData] = useState(null);
    function fetchData() {
      const options = {
        method: "GET",
        headers: {
          "X-RapidAPI-Key": "Your Rapid API key",
          "X-RapidAPI-Host": "api-football-v1.p.rapidapi.com",
        },
      };
      fetch(
        "https://api-football-v1.p.rapidapi.com/v3/standings?season=2021&league=39",
          options
      )
      .then((response) => response.json())
      .then((response) => {
        let newData = { ...response }; // Deep clone the response data
        setAttributes({ data: newData }); // Store the data in WordPress attributes
        setApiData(newData); // Modify the state with the new data
      })
      .catch((err) => console.error(err));
    }
    return (
      
{apiData && (
Rank
Logo
Team name
GP
GW
GD
GL
GF
GA
Pts
Form history
{/* Usage of [0] might be weird but that is how the API structure is. */} {apiData.response[0].league.standings[0].map((el) => { {/* Destructure the required data from all */} const { played, win, draw, lose, goals } = el.all; return (
{el.rank}
Rendering External API Data in WordPress Blocks on the Back End PlatoBlockchain Data Intelligence. Vertical Search. Ai.
{el.team.name}
{played}
{win}
{draw}
{lose}
{goals.for}
{goals.against}
{el.points}
{el.form.split("").map((result) => { return (
{result}
); })}
); } )}
)}
); }

כללתי את וו React useState() החל מ- @wordpress/element במקום להשתמש בו מספריית React. זה בגלל שאם הייתי טוען בדרך הרגילה, זה היה מוריד את React עבור כל בלוק שאני משתמש בו. אבל אם אני משתמש @wordpress/element הוא נטען ממקור יחיד, כלומר, שכבת וורדפרס על גבי React.

הפעם, גם לא עטפתי את הקוד בפנים useEffect() אבל בתוך פונקציה שנקראת רק בלחיצה על כפתור כדי שתהיה לנו תצוגה מקדימה חיה של הנתונים שהובאו. השתמשתי במשתנה מצב שנקרא apiData להעמיד את טבלת הליגה על תנאי. אז, לאחר לחיצה על הכפתור והנתונים מובאים, אני מגדיר apiData לנתונים החדשים בתוך fetchData() ויש עיבוד מחדש עם HTML של טבלת דירוג הכדורגל זמין.

תשימו לב שברגע שהפוסט נשמר ורענון העמוד, טבלת הליגה נעלמה. זה בגלל שאנחנו משתמשים במצב ריק (null) עבור apiDataהערך ההתחלתי של. כאשר הפוסט נשמר, התכונות נשמרות ב- attributes.data אובייקט ואנחנו קוראים לו כערך ההתחלתי של ה- useState() משתנה כזה:

const [apiData, setApiData] = useState(attributes.data);

אל האני save פונקציה

אנחנו הולכים לעשות כמעט את אותו הדבר בדיוק עם save לתפקד, אבל לשנות אותו קצת. לדוגמה, אין צורך בלחצן "אחזר נתונים" בקצה הקדמי, וב- apiData משתנה state הוא גם מיותר כי אנחנו כבר בודקים אותו ב- edit פוּנקצִיָה. אבל אנחנו צריכים אקראי apiData משתנה שבודק attributes.data כדי לבצע עיבוד מותנה של ה-JSX, אחרת הוא יזרוק שגיאות לא מוגדרות וממשק המשתמש של Block Editor ייעלם.

קוד מלא
export default function save(props) {
  const { attributes, setAttributes } = props;
  let apiData = attributes.data;
  return (
    
      {/* Only render if apiData is available */}
      {apiData && (
        
Rank
Logo
Team name
GP
GW
GD
GL
GF
GA
Pts
Form history
{/* Usage of [0] might be weird but that is how the API structure is. */} {apiData.response[0].league.standings[0].map((el) => { const { played, win, draw, lose, goals } = el.all; return (
{el.rank}
Rendering External API Data in WordPress Blocks on the Back End PlatoBlockchain Data Intelligence. Vertical Search. Ai.
{el.team.name}
{played}
{win}
{draw}
{lose}
{goals.for}
{goals.against}
{el.points}
{el.form.split("").map((result) => { return (
{result}
); })}
); })}
)} ); }

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

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

הסיבה לכך היא שהסימון בתוכן השמור שונה מהסימון בחדש שלנו save פוּנקצִיָה. מכיוון שאנו במצב פיתוח, קל יותר להסיר את הבוק מהדף הנוכחי ולהכניס אותו מחדש כחסימה חדשה - כך, נעשה שימוש בקוד המעודכן במקום והדברים חוזרים להסתנכרן.

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

טום נואל מספק הסבר יסודי על מה לא לעשות ב save פונקציה ב Stack Overflow הזה לענות.

עיצוב הבלוק בעורך ובחזית הקצה

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

סגנונות עורך
/* Target all the blocks with the data-title="Football Rankings" */
.block-editor-block-list__layout 
.block-editor-block-list__block.wp-block[data-title="Football Rankings"] {
  /* By default, the blocks are constrained within 650px max-width plus other design specific code */
  max-width: unset;
  background: linear-gradient(to right, #8f94fb, #4e54c8);
  display: grid;
  place-items: center;
  padding: 60px 0;

  /* Button CSS - From: https://getcssscan.com/css-buttons-examples - Some properties really not needed :) */
  button.fetch-data {
    align-items: center;
    background-color: #ffffff;
    border: 1px solid rgb(0 0 0 / 0.1);
    border-radius: 0.25rem;
    box-shadow: rgb(0 0 0 / 0.02) 0 1px 3px 0;
    box-sizing: border-box;
    color: rgb(0 0 0 / 0.85);
    cursor: pointer;
    display: inline-flex;
    font-family: system-ui, -apple-system, system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-size: 16px;
    font-weight: 600;
    justify-content: center;
    line-height: 1.25;
    margin: 0;
    min-height: 3rem;
    padding: calc(0.875rem - 1px) calc(1.5rem - 1px);
    position: relative;
    text-decoration: none;
    transition: all 250ms;
    user-select: none;
    -webkit-user-select: none;
    touch-action: manipulation;
    vertical-align: baseline;
    width: auto;
    &:hover,
    &:focus {
      border-color: rgb(0, 0, 0, 0.15);
      box-shadow: rgb(0 0 0 / 0.1) 0 4px 12px;
      color: rgb(0, 0, 0, 0.65);
    }
    &:hover {
      transform: translateY(-1px);
    }
    &:active {
      background-color: #f0f0f1;
      border-color: rgb(0 0 0 / 0.15);
      box-shadow: rgb(0 0 0 / 0.06) 0 2px 4px;
      color: rgb(0 0 0 / 0.65);
      transform: translateY(0);
    }
  }
}
סגנונות חזיתיים
/* Front-end block styles */
.wp-block-post-content .wp-block-football-rankings-league-table {
  background: linear-gradient(to right, #8f94fb, #4e54c8);
  max-width: unset;
  display: grid;
  place-items: center;
}

#league-standings {
  width: 900px;
  margin: 60px 0;
  max-width: unset;
  font-size: 16px;
  .header {
    display: grid;
    gap: 1em;
    padding: 10px;
    grid-template-columns: 1fr 1fr 3fr 4fr 3fr;
    align-items: center;
    color: white;
    font-size: 16px;
    font-weight: 600;
    background-color: transparent;
    background-repeat: no-repeat;
    background-size: contain;
    background-position: right;

    .stats {
      display: flex;
      gap: 15px;
      & > div {
        width: 30px;
      }
    }
  }
}
.league-table {
  background: white;
  box-shadow:
    rgba(50, 50, 93, 0.25) 0px 2px 5px -1px,
    rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
  padding: 1em;
  .position {
    width: 20px;
  }
  .team {
    display: grid;
    gap: 1em;
    padding: 10px 0;
    grid-template-columns: 1fr 1fr 3fr 4fr 3fr;
    align-items: center;
  }
  .team:not(:last-child) {
    border-bottom: 1px solid lightgray;
  }
  .team-logo img {
    width: 30px;
    top: 3px;
    position: relative;
  }
  .stats {
    display: flex;
    gap: 15px;
    & > div {
      width: 30px;
      text-align: center;
    }
  }
  .last-5-games {
    display: flex;
    gap: 5px;
    & > div {
      width: 25px;
      height: 25px;
      text-align: center;
      border-radius: 3px;
      font-size: 15px;
    & .result-W {
      background: #347d39;
      color: white;
    }
    & .result-D {
      background: gray;
      color: white;
    }
    & .result-L {
      background: lightcoral;
      color: white;
    }
  }
}

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


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

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

בול זמן:

עוד מ טריקים של CSS