This article is produced with scandiweb's eCommerce expertise

Collaborate with our development, PPC, SEO, data & analytics, or customer experience teams to grow your eCommerce business.

Magento Series: Creating CMS Content Programmatically

To create CMS content programmatically, it is recommended to use migration patches. Patches allow you to add migration code across all project environments, automatically executing during deployment or the Create Magento App startup process.

What is a migration patch?

A migration patch is a script that will add or update code on all project environments. CMS content is one of the things a migration patch can add.

A migration patch might eventually run on a local environment, DEV, STAGE, PRELIVE, and LIVE.

Which module to use for a migration patch?

Most projects have a ProjectName_Migration common module, used for migration patches not tied to any custom feature.

CMS content migrations are usually implemented in such a namespace.

How to manage, create, and update CMS content?

CMS content is managed with migration patches: PHP scripts that, in this case, add CMS content data to the database.

How to migrate media files?

scandiweb uses a private migration tool composer package. The migration tool can be used to migrate media, copying it from the module directory to the local media directory (which is usually ignored in GIT). This allows adding the necessary media on all environments without adding a media folder to the repository.

Media migration is done in the patch class’s apply method by using a MediaMigration class. The Media Migration class has a method called copyMediaFiles, which can copy the files from the view folder to the media directory.

The copyMediaFilemethod accepts a string array argument, the patch name (‘<vendor-name>_<module-name>’), and in what directory it will be saved. The string array includes all the media file paths relative to the module’s view\media folder. For CMS content, media is usually saved in the ‘cms’ or ‘wysiwyg’ directories.

// const MEDIA_FILES = ['blocks/lions/lion.jpg']
$this->mediaMigration->copyMediaFiles(
    self::MEDIA_FILES, 
    'Example_Migration',
    'cms'
);

The directory mentioned above is used in the frontend to get the web-server’s file path, because {{media url=<path>}} will get a web URL for the media directory for the current environment.

<!-- url=<directory>/<the relative file path> -->
<img src="{{media url=cms/blocks/lions/lion.jpg}}" alt="Lion Image">

How to re-run a patch locally during QA?

A common occurrence is that during local testing, something goes wrong and there’s a need to re-run the migration patch. However, patches are supposed to be run only once.

A standard solution is to create a new patch, with the dependency on the old patch. However, if at this point the code wasn’t deployed anywhere, there’s no need to create a new patch. Instead, you can delete the flag from the local database that the patch has already been executed.

To re-run a patch locally, it is enough to locate the row with the patch class name inside patch_list database table, delete it, and re-run setup:upgrade in CMA Magento CLI.

# use this command if you need an find the patch's name
SELECT * FROM patch_list;
# delete patch by name
DELETE FROM patch_list WHERE patch_name=@'<vender>\<module>\Setup\Patch\Data\<patch_php_file_name>';
#Example: @'Example\Migration\Setup\Patch\Data\CreateLionBlock'

CMS migration content best practices

  • CMS content is expected to be managed by the client, so it needs to be editable. Make a user guide with instructions on how to edit the content.
  • Add dependencies to make sure that patches get applied in order.
  • Test your CMS content migration patch.
    • Check if it renders in the frontend.
    • Try to open the CMS block or page created through migration in Admin Panel, re-save it, and confirm that it still looks the same as after the initial migration.

Regarding styling, there are multiple approaches that can be used, each with its own advantages.

Styling options include:

  • Avoiding inline styles and class names by using a base template (styling relative to the container)
  • Using inline styles in CMS block content
  • Using widgets instead

CMS content styling: Using a base template

One option is to avoid style definitions on HTML elements inside the CMS content (in situations where Page Builder is not used).

This lets you create a consistent display that is unlikely to change when editing the content in the backend.

This approach tends to be used when expected content managers from the client’s side will not be tech-savvy and are likely to lose the styles and/or class names during editing.

With this approach, it is recommended to have a user guide for content editing that can display what the expected element structures (and classes, if used) of the content are.

  • Re-use elements and classes from the theme’s base template.
  • The CMS content’s style needs to be in line with the project theme’s base template. Structures that are completely different from the base template should be avoided.
  • Add custom styles to the wrappers around CMS blocks instead of on the individual elements inside the CMS content, unless it is unavoidable.
  • If necessary, add custom style rules to React in SCSS files of the Components that render the block.

CMS content styling: using inline styles

This is the approach used by PageBuilder, which is adding all the custom styles as inline content on CMS blocks, but it can also be used for regular CMS content.

The benefits of using inline styles include being able to preview the content in the backend during editing—the preview will be very similar to how it will look on the frontend (aside from any base template/wrapper rules)—and the content manager having more freedom to modify the styles.

One downside of this approach is that it is possible to lose the styles during editing, especially when copy-pasting content in a WYSIWYG editor, and recovering the original version may be difficult for the client.

This approach is more suitable with tech-savvy clients.

When to use widgets instead of regular CMS blocks?

When the styling gets highly customized and complicated, but the client’s content managers are not tech-savvy, it is the safest option to use widgets instead of CMS blocks.

A widget’s render can be specified to a point where the manager only puts in the text and/or images, and all the text rendering and styles are taken care of on the React end, or in a phtml template.

The main benefit of this approach is that an inexperienced content manager cannot break the render. The downside is the extra development time necessary for widgets.

Need help with Magento (Adobe Commerce) development? scandiweb is the most certified Magento team in the world—get your dedicated eCommerce team today or get in touch with one of our experts.

Related articles:

COMPLETE GUIDE TO MAGENTO (ADOBE COMMERCE)

Hire eCommerce experts

Get in touch for a free consultation.

Your request will be processed by

If you enjoyed this post, you may also like