telnowedge/freepbx-base

使用 Symfony 组件(如表单验证、依赖注入等)创建模块的辅助工具

v1.1.2 2023-07-28 08:14 UTC

README

版本

  • 2018/05/23 <1.0>: 稳定发布
    • 容器缓存
    • 模板缓存
    • 表单辅助工具,用于在表单中添加目的地块
    • 发送 UserEvent 的辅助工具
    • asterisk 话路计划的新动词
  • 2017/11/28 <0.1>: 第一个可用的工作版本

安装

依赖项要求

目前 FreePBX® 在此版本中包含 symfony/property-access:3.4.19,在此版本中存在一个已知的主要错误 #29340。因此,要安装此模块,您必须更新您的包。

cd /var/www/admin/libraries/Composer
composer update

使用 composer require

cd /var/www/admin/libraries/Composer/composer.json
composer require telnowedge/freepbx-base

使用 git

在 composer 供应商目录内克隆 git

cd /var/www/admin/libraries/Composer/vendor/telnowedge/
git clone freepbx-base

通过在 composer.json 中添加来更新 composer 自动加载

"autoload": {
  "psr-4": {
  "TelNowEdge\\FreePBX\\Base\\": "vendor/telnowedge/freepbx-base"
  }
}

最后运行

composer.phar dump-autoload

了解

  1. 缓存系统

所有缓存的文件都写在了 rootFreePBX/assets/cache/ 目录下。请小心权限。

概述

此 FreepbxBase bundle 提供了一种轻松编写 FreePBX® 模块的方法,就像 MVC 项目一样。它单独工作,无需修改 FreePBX® 核心文件(除了 composer.json)。

FreepbxBase bundle 使用 Symfony® 组件来提高安全性、可访问性和支持。

它注册了自己的命名空间,通过几个辅助工具提供对不同的组件的访问。

FreepbxBase bundle 在 FreePBX® 中引入了 Symfony® 组件的 依赖注入 概念。此组件非常有用,可以防止任何 singleton,并轻松地在您的代码中共享对象。

FreepbxBase bundle 还提供了 Symfony® 的 表单 组件,用于在将表单保存到 SQL 存储之前在服务器端验证表单。

在开始使用之前,您需要了解命名空间和 Symfony 基础开发概念。

Acme 示例模块

编码规范

要检查 编码规范,请将 GrumPHP 包含到您的模块中。

  1. 需要的包

        $ composer require --dev "phpro/grumphp" "nikic/php-parser" "friendsofphp/php-cs-fixer" "jakub-onderka/php-parallel-lint" "phpmd/phpmd" "phpspec/phpspec"
  2. php-cs-fixer 创建配置文件 ./php_cs

        <?php
    
        return PhpCsFixer\Config::create()
            ->setRiskyAllowed(true)
            ->setRules([
                '@Symfony' => true,
                '@Symfony:risky' => true,
                'array_syntax' => true,
                'combine_consecutive_unsets' => true,
                'no_useless_else' => true,
                'no_useless_return' => true,
                'ordered_class_elements' => true,
                'ordered_imports' => true,
                'php_unit_strict' => true,
                'strict_comparison' => true,
                'strict_param' => true,
            ])
            ->setFinder(PhpCsFixer\Finder::create()
                ->exclude('vendor')
                ->in(__DIR__)
            )
        ;
  3. 创建 GrumPHP 配置文件 ./grumphp.yml

       parameters:
         git_dir: .
         bin_dir: ./vendor/bin
         tasks:
           jsonlint: ~
           phpcsfixer2:
             config: "./.php_cs"
             allow_risky: true
             # rules:
             #   - "@@Symfony"
             #   - "@@Symfony:risky"
             #   - array_syntax
             #   - combine_consecutive_unsets
             #   - no_extra_consecutive_blank_lines
             #   - no_useless_else
             #   - no_useless_return
             #   - ordered_class_elements
             #   - ordered_imports
             #   - php_unit_strict
             #   - psr4
             #   - strict_comparison
             #   - strict_param
             using_cache: false
             config_contains_finder: false
           phplint: ~
           phpmd:
             ruleset: ['unusedcode', 'codesize']
           phpparser: ~
           phpspec: ~
           shell: ~
           xmllint: ~
           yamllint:
             parse_custom_tags: true
           xdebugparse: ~

包含的组件

  1. doctrine/annotations
  2. doctrine/cache
  3. guzzlehttp/guzzle
  4. monolog/monolog
  5. symfony/cache
  6. symfony/config
  7. symfony/dependency-injection
  8. symfony/event-dispatcher
  9. symfony/form
  10. symfony/http-foundation
  11. symfony/ldap
  12. symfony/property-access
  13. symfony/security-csrf
  14. symfony/serializer
  15. symfony/twig-bridge
  16. symfony/validator
  17. symfony/yaml

如何使用

启动新的 FreePBX® 模块

像 FreePBX® 一样启动一个新的模块,并仅将 extends 类更改为 TelNowEdge\FreePBX\Base\Module\Module

<?php

namespace FreePBX\modules;

use TelNowEdge\FreePBX\Base\Module\Module;

class Foo extends Module implements \BMO
{

}

这个扩展启动并桥接了所有 Symfony® 组件,并注册了一个新的命名空间。现在您可以在模块内部使用 PSR4 命名空间。

新的注册命名空间是 \TelNowEdge\Module。它与 ./modules 基础目录一起注册。因此,现在您可以使用 \TelNowEdge\Module\foo 命名空间。

注意

请注意您的模块名称的大小写。您的类可以是 Foo.class.php,但文件夹是 ./modules/foo。因此,命名空间是 \TelNowEdge\Module\foo。

将 FreePBX® 类用作入口点

您的 Foo.class.php 是 FreePBX® 的第一个文件。现在使用它来调用您的逻辑控制器。

<?php

namespace FreePBX\modules;

use TelNowEdge\FreePBX\Base\Module\Module;
use TelNowEdge\Module\foo\Controller\FooBarController;

class Foo extends Module implements \BMO
{
    public function install()
    {
        $this
            ->get('TelNowEdge\Module\foo\Resources\Migrations\TableMigration')
            ->migrate()
            ;
    }

    public static function myGuiHooks()
    {
        return array('core');
    }

    public function doGuiHook(&$cc)
    {
        $this
            ->processDeviceGui($cc)
            ;
    }

    private function processDeviceGui(&$cc)
    {
        $request = $this->get('request');

        if ('devices' === $request->query->get('display')) {
            if (true === $request->isMethod('POST')) {
                if ('edit' === $request->request->get('action')) {
                    $this->get(FooBarController::class)
                         ->updateAction($request, $cc)
                        ;
                }

                if ('add' === $request->request->get('action')) {
                    $this->get(FooBarController::class)
                         ->createAction($request, $cc)
                        ;
                }
            } else {
                $this->get(FooBarController::class)
                     ->showAction($request, $cc)
                    ;
            }
        }
    }
}

您的控制器 ./modules/foo/Controller/FooBarController.php

<?php

namespace TelNowEdge\Module\foo\Controller;

use TelNowEdge\FreePBX\Base\Controller\AbstractController;

class FooBarController extends AbstractController
{
    [...]
}

参考

模块

作为 FreepbxBase 的启动入口点。

FreePBX® 模块必须扩展 TelNowEdge\FreePBX\Base\Module\Module

控制器

您的控制器必须扩展 TelNowEdge\FreePBX\Base\Controller\AbstractController

protected $container;

FormFactory function createForm(FormInterface $type, $data = null, array $options = array());

string function render(string $templatePath, array $data = array());

mixed function get(string $service);
  1. createForm()

  2. render()

    render() 返回从模板编译的 HTML。按照 FreePBX® 的做法附加到 FreePBX® 上。

    $html = $this->render('foo.html.twig', array(
        'form' => $form->createView(),
    ));
    
    $cc->addguielem(_('Foo'), new \gui_html('Foo', $html), 1, null, _('TelNowEdge'));
  3. get()

模型

注意

此包不使用 Doctrine ORM。但方式相同。

模型 是数据库表示。此类不应扩展任何内容。

在各个属性上,您可以添加一个验证器。

<?php

namespace TelNowEdge\Module\foo\Model;

use Symfony\Component\Validator\Constraints as Assert;

class Foo
{
    protected $id;

    /**
     * @Assert\NotBlank()
     */
    protected $name;

    public function getId()
    {
        return $this->id;
    }

    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }
}

存储库

存储库 从 sql 存储中获取信息,并将其与模型映射。ORM 非常轻量。

您的存储库必须扩展 TelNowEdge\FreePBX\Base\Repository\AbtractRepository

array sqlToArray(array $sqlRes);

\Doctrine\DBAL\Statement fetch(\Doctrine\DBAL\Statement $stmt);

\Doctrine\DBAL\Statement fetchAll(\Doctrine\DBAL\Statement $stmt);

Model objectFromArray(string $modelClass, array $sqlToArrayRes);
  1. sqlToArray() 将 sql 结果集转换为数组以供 objectFromArray() 使用

    sqlToArray() 需要格式化的输入。

    SELECT t.id t__id, t.name t__name, t.long_name t__long_name, t2.id t2__id
    FROM table t INNER JOIN table2 t2 ON (t2.id = t1.id)

    sqlToArray() 返回一个关联数组,例如

    array(
        't' => array('id' => '1', 'name' => 'foo', 'longName' => 'foobar'),
        't2' => array('id' => 1)
    )

    注意

    删除了 __ 以创建表键,并将 _ 转换为驼峰式。

  2. objectFromArray() 将 sqlToArray() 映射到模型。在各个属性上,它尝试调用设置器。

    private function mapModel(array $res)
    {
        $foo = $this->objectFromArray(Foo::class, $res['t']);
        $fooBar = $this->objectFromArray(FooBar::class, $res['t2']);
    
        return $foo->setFooBar($fooBar);
    }

DbHandler

DbHandler模型 保存数据到 sql。

您的存储库必须扩展 TelNowEdge\FreePBX\Base\Handler\AbtractDbHandler

<?php

namespace TelNowEdge\Module\foo\Handler\DbHandler;

use TelNowEdge\FreePBX\Base\Handler\AbstractDbHandler;
use TelNowEdge\Module\foo\Model\Foo;

class PhoneProvisionDbHandler extends AbstractDbHandler
{
    public function create(Foo $foo)
    {
        $sql = "INSERT INTO Foo (`id`, `name`, `value`) VALUES (:id, :name, :value)";
        $stmt = $this->connection->prepare($sql);
        $stmt->bindParam('id', $foo->getId());
        $stmt->bindParam('name', $foo->getName());
        $stmt->bindParam('value', $foo->getValue());

        $stmt->execute();
    }

表单

表单 提供了一种简单的方法来构建和验证您的表单。

此组件的使用方法与 Symfony 完全相同。

验证器

验证器表单 一起工作,在服务器端对其进行验证。

此组件的使用方法与 Symfony 完全相同。

依赖注入

依赖注入 创建一个服务容器来处理您的代码。

此组件的使用方法与 Symfony 完全相同。

Twig

Twig 是一个模板组件。对于渲染 Symfony® 表单非常有用。

此组件的使用方法与 Symfony 完全相同。

待办事项

  1. 在 service.yml 中提高安全性,使用公共/私有服务