定制 brunocfalcao/zahper 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

brunocfalcao/zahper

Composer 安装命令:

composer require brunocfalcao/zahper

包简介

Zahper MJML Template generator

README 文档

README

About Zahper

Zahper is a Laravel on-steroids Mailable that lets you create beautiful cross-browser email newsletters using MJML.

Why Zahper

Zahper will solve you these problems:

  • Frustration of creating email templates, and at the end verifying they are not browser-compatible.
  • Annoyance of having to recreate email templates without a common base template structure to kick off.
  • Complexity of creating "view in browser" links, like having to create a db/file model for storage.
  • Rebuilding a Laravel package to send emails.

Zahper Features

You get all of this out-of-the-box:

  • Build your MJML template in an eloquent way, directly on your Mailable class, using all the MJML features and components.
  • Automated MJML to Blade view compilation via the MJML Api.
  • Caching mechanism, so you don't make 500 Api calls, when you send 500 emails.
  • Automatic "view in browser" link generation, in case you want to redirect your users to view the email in the browser.
  • High customizable (storage and views cache, image rendering types, etc) via a config file.
  • Automatic image CID / URL rendering.
  • Already being used in masteringnova.com, Laraning and Laraflash.
  • You can also use the full original Mailable class capabilites since Zahper inherits from the Laravel Mailable class.

Installation

You can install Zahper via composer using this command:

composer require brunocfalcao/zahper
The package will automatically register the service provider (using auto-discover).

Next step is to publish your zahper.php configuration.

php artisan vendor:publish --tag=zahper-config

Final step is to install your mjml.io api keys in your .ENV configuration.

ZAHPER_API_URL=https://api.mjml.io/v1/render
ZAHPER_API_APPLICATION_ID=<your application id>
ZAHPER_API_SECRET_KEY=<your secret key>
👉 You need to register for the Api keys for your MJML api application here. It's free.

No time to wait?

After having your api keys in your .ENV file, just do this for a quick email demo:

Run the following artisan command:

php artisan zahper:demo

Navigate in your local laravel app to the url /zahper/demo. Et voilá, you should see a mailable demo.

How it works

Zahper uses the power of MJML syntax to render an HTML email that will be cross-browser compatible. To do this, you first need to learn MJML, and believe me it's pretty straight forward. You can check the documentation here.

Additionally it leverages the full features of the Laravel Mailable that you can use. So, it's 100% compatible with any Mailable-based codebase you did.

How to use Zahper

  1. Start by creating your zahper mailable using the following example:
php artisan zahper:mailable WelcomeMailable

This command will create your new mailable in the app\Mail folder.

  1. Inside your zahper mailable, you have the following methods:
    public function __construct()
    {
        // --- Zahper code ---
        ZahperTemplate::$cache = false;
        // [...]
        // --- /Zahper code ---
    }

The $cache static attribute will allow you to cache your MJML compiled view, so in case you have 500 emails to be sent, you don't call the MJML api 500 times. You should make it false until you tested your newsletter and finally turn it true when you decide to use it in your website. More about the cache later in this readme.

    protected function template()
    {
        $mjml = ZahperComponent::make();

        $head = $mjml->with('mj-head');
        // $head->with(...)

        $body = $mjml->with('mj-body');
        // $body->with(...)

        return $mjml;
    }

This is where the magic happens. You will write your MJML and Zahper will call the MJML api to compile it to a view. As a quick example (more examples later in this readme) the following MJML:

    <mj-section>
        <mj-column>
            <mj-text>Hi there!</mj-text>
        </mj-column>
    </mj-section>

is written in Zahper like this:

    $section = ZahperComponent::make('mj-section')
               ->with('mj-column')
                   ->with('mj-text', 'Hi there!');

and the final method:

    public function build()
    {
        $this
            ->from(
                'you@example.com',
                'You from Example.com'
            )
            ->subject('Nice subject out here!');

        parent::build();
    }

Is used to configure your Mailable "from" recipient and the subject.

☝️ All the Laravel Mailable features are available for you, except the "build" method. As example, you can pass public attributes, and they will also be available in the MJML rendered view!

How do you code the MJML

Coding your MJML is made in a very natural way.

  1. You create the component:
    $body = ZahperComponent::make('mj-section');
  1. You then add all your attributes in 2 ways, as example:
    $body->align('center')
    
    or 
    
    $body = ZahperComponent::make('mj-section', ['align' => 'center');

Let's see another examples, so you can learn it better:

    <mj-section padding="40px" background-color="#FFFFFF">
        <mj-column>
            <mj-text align="center" color="#1a202c" font-size="20px">Hey there!</mj-text>
        </mj-column>
    </mj-section>

is written like:

    $section = ZahperComponent::make('mj-section')
               ->padding('40px')
               ->backgroundColor('#FFFFFF')
                   ->with('mj-column')
                       ->with('mj-text', 'Hey there!')
                           ->align('center')
                           ->color('#1A202C')
                           ->fontSize('20px')

The coding way is "natural". Meaning you create your component, then if you want to add a child component you use the ->with(), and if you want to pass properties, you just keep adding them as methods. You just need to respect that attribute name convention, like "background-color" should be ->backgroundColor(). And that's it ! Zahper then converts it to a pure MJML, calls the MJML Api to convert it to a blade view, and calls the ->build() Mailable method!

❓ What happens if you want to code 2 columns?

Simple. You have a ->parent() method that will point one level up in the MJML hierarchy 😊

    <mj-section padding="40px" background-color="#FFFFFF">
        <mj-column>
            <mj-text>First Column</mj-text>
        </mj-column>
        <mj-column>
            <mj-text>Second Column</mj-text>
        </mj-column>
    </mj-section>

is written like:

    $section = ZahperComponent::make('mj-section')
                   ->with('mj-column')
                       ->with('mj-text', 'First Column')
                           ->parent()
                       ->parent()
                   ->with('mj-column')
                       ->with('mj-text', 'Second Column');

Caching strategy

Zahper needs to have a caching strategy since when you are sending a high volume of emails we cannot just call the MJML Api to convert the same MJML over and over. You can suddenly see your MJML Api account blocked in case spikes occur. So, Zahper allows you to cache your blade view so the next time the same Mailable class is called it doesn't recompile the mjml, but just uses the cached view content.

Things you need to pay attention

Activating the Zahper Mailable cache

The way you turn on, or off the Mailable cache is in your generated Zahper Mailable, in the construct() method:

    public function __construct()
    {
        // --- Zahper code ---
        ZahperTemplate::$cache = false;
        // [...]
        // --- /Zahper code ---
    }

❗ Keep it off until you have your newsletter structure all fine tuned. Then you turn it on and the MJML Api, for this Mailable, will not be called again until you turn it on again.

Using dynamic values on your Zahper Mailable

Let's say you want to have, for instance, a dynamic URL in a Button href attribute with a distinct user id per email.

    <mj-button href="{{ route('welcome', ['user_id' => $id]) }}">Click here to Browse</mj-button>

You then should write it this way:

    $button = ZahperComponent::make('mj-button')
                ->href("{{ route('welcome', ['user_id' => \$id]) }}")

❗ If you write it this way below, the user id will get cached. So you will send 500 emails, to 500 recipients, all of them with the same user id!

    $button = ZahperComponent::make('mj-button')
                ->href(route('welcome', ['user_id' => \$id]))

View in Browser

For each sent email, Zahper stores a copy in your storage folder with a distinct UUID. You can access this UUID only during the lifecycle of the Mailable. After that it's discarded and re-generated again.

The UUID is accessed in your mailable via:

    [...]
    $uuid = $this->zhp_uuid;
    [...]

You can also configure the route and action called directly in the zahper configuration file.

Also, you have a helper that will generate the full url for you, so you can use it on your MJML code:

    [...]
        ->with('mj-button', 'View in Browser')
            ->href("{{ zhp_url_view_in_browser(\$zhp_uuid) }}")
            ->target('_blank');
    [...]

Unsubscribe

Like the View in Browser, the UUID is also used for the unsubscribe. Zahper will have a default route that you can use, but the action doesn't do more than calling an event. So it's up to you to inject a listener.

ZahpController@unsubscribe action:

    public function unsubscribe(string $uuid)
    {
        event(new ZahperUnsubscribeEvent($uuid));

        return response('Thank you, you have been unsubscribed!', 200);
    }

Current development status

  • Finish core development.
  • Finish testing in production environments.
  • Close Beta release.
  • Additional testing in multi-parallelism using job queues.
  • Adding testing scenarios.
  • Release for General Public use.

Contributing

At the moment you don't need to contribute since Zahper is still in early-production release. You can already use it in your production website but still pay attention to my repository for issues that might impact you.

License

Zahper is open-sourced software licensed under the MIT license.

How to follow me

You can follow my work on twitter, @brunocfalcao. :)

brunocfalcao/zahper 适用场景与选型建议

brunocfalcao/zahper 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 35 次下载、GitHub Stars 达 15, 最近一次更新时间为 2020 年 05 月 14 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「mjml」 「brunocfalcao」 「zahper」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 brunocfalcao/zahper 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 brunocfalcao/zahper 我们能提供哪些服务?
定制开发 / 二次开发

基于 brunocfalcao/zahper 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 35
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 15
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 15
  • Watchers: 1
  • Forks: 2
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2020-05-14