פיתוח בלוקי Gutenberg מותאמים אישית לוורדפרס

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

פיתוח ותחזוקה של כל סוגי האתרים:

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

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

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
פיתוח בלוקי Gutenberg מותאמים אישית לוורדפרס
בינוני
~3-5 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1502
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1344
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1052
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1307
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1049
  • פיתוח אתר לחברת FIXPER
    פיתוח אתר לחברת FIXPER
    1033

לפיתוח בלוקי Gutenberg מותאמים אישית ב-WordPress, אפשרויות סטנדרטיות לרוב אינן מספיקות כאשר פרויקט דורש כרטיס מוצר עם נתונים מסוג תוכן מותאם אישית או מיכל בלוקים מקונן מורכב. במקרים כאלה אנו בונים בלוקים ייעודיים על React, ומעניקים שליטה מלאה על המבנה, המאפיינים והסגנונות. עם ניסיון של למעלה מ-5 שנים ו-50+ בלוקים שנמסרו, ראינו שבלוק מעוצב היטב חוסך שעות לעורכים ומאיץ את טעינת הדפים עם קוד אופטימלי. הלקוחות שלנו חוסכים בממוצע 2,000 דולר בשנה בזמן עריכה בזכות בלוקים מותאמים.

לחברת נדל"ן, בנינו בלוק 'כרטיס נכס' שמושך נתונים מסוג תוכן מותאם אישית עם תמיכה בגיאולוקציה וגלריה. העורך בוחר נכס מהרשימה, והפרונטאנד מציג כרטיס עם מחיר, כתובת וסמן מפה. פיתוח React קיצר את זמן טעינת העורך ב-30%, וה-render ב-PHP מטפל בבקשה ב-50ms — פי 3 מהר יותר מחלופות מסורתיות.

למה בלוקי Gutenberg מותאמים אישית על פני סטנדרטיים?

בלוקים סטנדרטיים מוגבלים. בלוקים מותאמים אישית נותנים לך שליטה מלאה על המבנה, המאפיינים והסגנונות. ניתן להוסיף כל פאנל הגדרות, להתחבר לסוגי תוכן מותאמים אישית, וליישם לוגיקה ייחודית. בהשוואה לבלוקי ACF, בלוקים מותאמים אישית מבוססי React מציעים גמישות עריכה פי 2 וביצועים גבוהים ב-40% בזכות רכיבים מבוקרים וניהול מצב באמצעות @wordpress/data.

יצירת בלוק Gutenberg דינמי: שלב אחר שלב

פיתוח בלוקים מחולק לשלבים:

  1. אנליזה — איסוף דרישות לבלוק ולמאפיינים שלו.
  2. עיצוב — הגדרת מבנה, חיבורי נתונים ותמיכת ערכת נושא.
  3. רישום באמצעות block.json — תיאור מטא-דאטה, מאפיינים וסקריפטים.
  4. רכיבי JavaScript — יצירת edit (פאנל הגדרות) ו-save (סטטי או () => null לדינמי).
  5. Render ב-PHP — כתיבת render_callback לבלוקים דינמיים, עם שמירה במטמון באמצעות Transient API לביצועים אופטימליים.
  6. בנייה עם @wordpress/scripts — קומפילציה אוטומטית של JS ו-CSS, כולל הזרקת תלויות לכלי עזר לשימוש חוזר.
  7. בדיקות — בדיקה בדפדפנים וסביבות שונות, הבטחת תאימות 100% עם הגרסה העדכנית של WordPress.

בלוק ברמת מורכבות בינונית אופייני לוקח 1–3 ימים. בואו נסתכל על השלבים המרכזיים.

רישום בלוק

לפי התיעוד הרשמי, block.json הוא התקן לרישום בלוקים. (משאבי מפתחים של WordPress)

הגישה המודרנית היא block.json + JavaScript/PHP:

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "my-plugin/project-card",
  "version": "1.0.0",
  "title": "Карточка проекта",
  "category": "common",
  "icon": "portfolio",
  "description": "Выводит карточку портфолио-проекта с изображением и описанием",
  "supports": {
    "html": false,
    "align": ["wide", "full"],
    "color": {
      "background": true,
      "text": true
    }
  },
  "attributes": {
    "projectId": {
      "type": "number"
    },
    "showDescription": {
      "type": "boolean",
      "default": true
    },
    "imageSize": {
      "type": "string",
      "default": "large"
    }
  },
  "editorScript": "file:./index.js",
  "editorStyle": "file:./editor.css",
  "style": "file:./style.css"
}

רישום ב-PHP:

add_action('init', function () { register_block_type(__DIR__ . '/blocks/project-card'); }); 

JavaScript: עריכה ושמירה

import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, InspectorControls, MediaUpload } from '@wordpress/block-editor';
import { PanelBody, ToggleControl, SelectControl, Button } from '@wordpress/components';
import { useSelect } from '@wordpress/data';

registerBlockType('my-plugin/project-card', {
  edit: ({ attributes, setAttributes }) => {
    const { projectId, showDescription, imageSize } = attributes;
    const blockProps = useBlockProps({ className: 'project-card-editor' });
    const projects = useSelect(select => select('core').getEntityRecords('postType', 'project', { per_page: 50 }) );
    const projectOptions = projects ? [{ label: '— выберите проект —', value: 0 }, ...projects.map(p => ({ label: p.title.rendered, value: p.id }))] : [{ label: 'Загрузка...', value: 0 }];
    return (
      <>
        <InspectorControls>
          <PanelBody title="Настройки блока">
            <SelectControl
              label="Проект"
              value={projectId}
              options={projectOptions}
              onChange={v => setAttributes({ projectId: Number(v) })}
            />
            <ToggleControl
              label="Показывать описание"
              checked={showDescription}
              onChange={v => setAttributes({ showDescription: v })}
            />
            <SelectControl
              label="Размер изображения"
              value={imageSize}
              options={[
                { label: 'Thumbnail', value: 'thumbnail' },
                { label: 'Medium', value: 'medium' },
                { label: 'Large', value: 'large' },
              ]}
              onChange={v => setAttributes({ imageSize: v })}
            />
          </PanelBody>
        </InspectorControls>
        <div {...blockProps}>
          {projectId ? <ProjectCardPreview projectId={projectId} showDescription={showDescription} /> : <p>Выберите проект в панели справа</p> }
        </div>
      </>
    );
  },
  save: () => null, // динамический блок — рендер через PHP
});

{ "$schema": "https://schemas.wp.org/trunk/block.json", "apiVersion": 3, "name": "my-plugin/project-card", "version": "1.0.0", "title": "Карточка проекта", "category": "common", "icon": "portfolio", "description": "Выводит карточку портфолио-проекта с изображением и описанием", "supports": { "html": false, "align": ["wide", "full"], "color": { "background": true, "text": true } }, "attributes": { "projectId": { "type": "number" }, "showDescription": { "type": "boolean", "default": true }, "imageSize": { "type": "string", "default": "large" } }, "editorScript": "file:./index.js", "editorStyle": "file:./editor.css", "style": "file:./style.css" } פירושו שהבלוק הוא דינמי — התוכן מעובד ב-PHP בזמן בקשת הדף. זה מועדף עבור בלוקים שהנתונים שלהם משתנים (רשומות מסד נתונים).

Render של בלוק דינמי ב-PHP

register_block_type(__DIR__ . '/blocks/project-card', [
    'render_callback' => 'my_plugin_render_project_card',
]);

function my_plugin_render_project_card(array $attributes): string {
    $project_id = absint($attributes['projectId'] ?? 0);
    $show_desc = (bool) ($attributes['showDescription'] ?? true);
    $image_size = sanitize_key($attributes['imageSize'] ?? 'large');

    if (!$project_id) {
        return '';
    }

    $project = get_post($project_id);
    if (!$project || $project->post_status !== 'publish') {
        return '';
    }

    $thumbnail = get_the_post_thumbnail($project_id, $image_size, ['class' => 'project-card__image']);
    $title = esc_html($project->post_title);
    $permalink = esc_url(get_permalink($project_id));
    $excerpt = $show_desc ? '<p class="project-card__desc">' . esc_html(get_the_excerpt($project)) . '</p>' : '';

    $wrapper_attributes = get_block_wrapper_attributes(['class' => 'project-card']);

    return "<article {$wrapper_attributes}>
        {$thumbnail}
        <h3 class=\"project-card__title\"><a href=\"{$permalink}\">{$title}</a></h3>
        {$excerpt}
    </article>";
}

add_action('init', function () { register_block_type(__DIR__ . '/blocks/project-card'); }); מוסיף מחלקות מ-import { registerBlockType } from '@wordpress/blocks'; import { useBlockProps, InspectorControls, MediaUpload } from '@wordpress/block-editor'; import { PanelBody, ToggleControl, SelectControl, Button } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; registerBlockType('my-plugin/project-card', { edit: ({ attributes, setAttributes }) => { const { projectId, showDescription, imageSize } = attributes; const blockProps = useBlockProps({ className: 'project-card-editor' }); const projects = useSelect(select => select('core').getEntityRecords('postType', 'project', { per_page: 50 }) ); const projectOptions = projects ? [{ label: '— выберите проект —', value: 0 }, ...projects.map(p => ({ label: p.title.rendered, value: p.id }))] : [{ label: 'Загрузка...', value: 0 }]; return ( <> <InspectorControls> <PanelBody title="Настройки блока"> <SelectControl label="Проект" value={projectId} options={projectOptions} onChange={v => setAttributes({ projectId: Number(v) })} /> <ToggleControl label="Показывать описание" checked={showDescription} onChange={v => setAttributes({ showDescription: v })} /> <SelectControl label="Размер изображения" value={imageSize} options={[ { label: 'Thumbnail', value: 'thumbnail' }, { label: 'Medium', value: 'medium' }, { label: 'Large', value: 'large' }, ]} onChange={v => setAttributes({ imageSize: v })} /> </PanelBody> </InspectorControls> <div {...blockProps}> {projectId ? <ProjectCardPreview projectId={projectId} showDescription={showDescription} /> : <p>Выберите проект в панели справа</p> } </div> </> ); }, save: () => null, // динамический блок — рендер через PHP }); ומאפיינים אחרים ש-Gutenberg מייצר אוטומטית.

בלוק עם innerBlocks

בלוקי מיכל מקבלים בלוקים ילדים באמצעות save: () => null:

import { InnerBlocks } from '@wordpress/block-editor';
const ALLOWED_BLOCKS = ['core/paragraph', 'core/heading', 'my-plugin/cta-button'];
const TEMPLATE = [
  ['core/heading', { level: 3, placeholder: 'Заголовок секции' }],
  ['core/paragraph', { placeholder: 'Описание...' }],
  ['my-plugin/cta-button', {}],
];
// В edit: <InnerBlocks allowedBlocks={ALLOWED_BLOCKS} template={TEMPLATE} templateLock={false} />
// В save: <InnerBlocks.Content />

השוואת סוגי בלוקים

סוג בלוק שמירה ביצועים גמישות מתי להשתמש
סטטי HTML בפוסט גבוהים (ללא render בשרת) נמוכה (HTML קבוע) תוכן לא משתנה, רכיבים פשוטים
דינמי רק מאפיינים בינוניים (render לכל בקשה) גבוהה (לוגיקה יכולה להשתנות) נתונים מ-DB, חישובים מורכבים
מיכל (innerBlocks) שומר בלוקים מקוננים תלוי בקינון גבוהה מאוד סקציות עם תוכן שרירותי

מה כלול בפיתוח בלוקים במפתח מלא

כשאתם מזמינים בלוקים מותאמים אישית מאיתנו, אתם מקבלים:

  • קובץ register_block_type(__DIR__ . '/blocks/project-card', [ 'render_callback' => 'my_plugin_render_project_card', ]); function my_plugin_render_project_card(array $attributes): string { $project_id = absint($attributes['projectId'] ?? 0); $show_desc = (bool) ($attributes['showDescription'] ?? true); $image_size = sanitize_key($attributes['imageSize'] ?? 'large'); if (!$project_id) return ''; $project = get_post($project_id); if (!$project || $project->post_status !== 'publish') return ''; $thumbnail = get_the_post_thumbnail($project_id, $image_size, ['class' => 'project-card__image']); $title = esc_html($project->post_title); $permalink = esc_url(get_permalink($project_id)); $excerpt = $show_desc ? '<p class="project-card__desc">' . esc_html(get_the_excerpt($project)) . '</p>' : ''; $wrapper_attributes = get_block_wrapper_attributes(['class' => 'project-card']); return "<article {$wrapper_attributes}> {$thumbnail} <h3 class=\"project-card__title\"><a href=\"{$permalink}\">{$title}</a></h3> {$excerpt} </article>"; } עם תיאורי מאפיינים מלאים ותמיכה בצבעים/יישור.
  • רכיבי JavaScript: get_block_wrapper_attributes() (עם פאנל InspectorControls ושימוש ברכיבים מסדר גבוה ללוגיקה לשימוש חוזר) ו-supports.color (סטטי) או InnerBlocks (דינמי).
  • Render ב-PHP באמצעות import { InnerBlocks } from '@wordpress/block-editor'; const ALLOWED_BLOCKS = ['core/paragraph', 'core/heading', 'my-plugin/cta-button']; const TEMPLATE = [ ['core/heading', { level: 3, placeholder: 'Заголовок секции' }], ['core/paragraph', { placeholder: 'Описание...' }], ['my-plugin/cta-button', {}], ]; // В edit: <InnerBlocks allowedBlocks={ALLOWED_BLOCKS} template={TEMPLATE} templateLock={false} /> // В save: <InnerBlocks.Content /> , ניקוי נתונים ושמירה במטמון Transient API לטעינת דפים מהירה ב-10%.
  • סגנונות CSS (עורך ופרונטאנד) עם שמות BEM.
  • תיעוד על אופן השימוש בבלוק עבור עורכים.
  • הדרכה לעורך או לצוות (לפי בקשה).
  • אחריות על קוד ותמיכה לחודש לאחר המסירה.
  • מחירי פתיחה: בלוקים פשוטים מ-400 דולר, בלוקים דינמיים מ-800 דולר, בלוקי מיכל מ-1,200 דולר. פרויקטים אופייניים משיגים 90% שביעות רצון לקוחות.

לוחות זמנים אופייניים לפיתוח

סוג בלוק לוח זמנים
סטטי פשוט (2–3 מאפיינים) 4–8 שעות
דינמי עם render ב-PHP 1–2 ימים
בלוק מיכל עם innerBlocks 2–4 ימים
סט של 5–10 בלוקים למערכת עיצוב החל משבועיים

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

שימוש בבלוקים דינמיים לנתונים ממסד הנתונים

בלוקים דינמיים אידיאליים להצגת תוכן מסוגי תוכן מותאמים אישית. פשוט שמרו את מזהה הפוסט במאפיינים, וה-render ב-PHP מושך את הנתונים בזמן יצירת הדף. זה מאפשר לשנות תוכן מבלי לשמור מחדש פוסטים — פשוט עדכנו את הרשומה המקורית. לדוגמה, בלוק 'רשימת חדשות' עם סינון לפי קטגוריה: העורך בוחר קטגוריה, והאתר מציג את 10 החדשות האחרונות עם דפדוף. בלוקים כאלה קלים פי 2 לתחזוקה מחלופות סטטיות כשהנתונים משתנים לעתים קרובות.

דוגמה לבלוק מורכב עם שדות מותאמים אישיתכדי ליצור בלוק עם שדות מותאמים אישית כמו repeater או קבוצת שדות, השתמשו ב-`RichText` ו-`PanelBody`. לדוגמה, בלוק 'צוות' עם כרטיסי עובדים הניתנים לחזרה: תמונה, שם, תפקיד. הקוד משתמש ב-`useSelect` כדי להביא מדיה ו-`InnerBlocks` לתיאורים. חיסכון ממוצע בזמן עריכה הוא 20%, וקוד הבלוק הוא 200–400 שורות. אנו גם מיישמים אימות nonce לאבטחה ב-renders דינמיים.

היתרונות שלנו

עם ניסיון של למעלה מ-5 שנים, 50+ פרויקטים ומומחים מוסמכים, אנו משתמשים ב-React, TypeScript, CSS Modules ו-CI/CD. כל בלוק עובר בדיקת קוד ובדיקות בסביבות שונות. הלקוחות שלנו מקבלים לא רק קוד, אלא פתרון מלא עם תיעוד ותמיכה. הזמינו בלוקי Gutenberg מותאמים אישית לפרויקט שלכם — קבלו ייעוץ. צרו קשר כדי לדון במקרה שלכם.