misatotremor/csv-bundle

Symfony2 CSV Bundle

安装次数: 2 787

依赖项: 0

建议者: 0

安全性: 0

星标: 1

关注者: 3

分支: 14

公开问题: 0

类型:symfony-bundle

v1.2.2 2024-04-25 09:55 UTC

README

此捆绑包通过仅使用几个配置参数即可轻松将数据上传到您的数据库,使用csv文件。

这是jdewits 原始代码的分支。

状态

此捆绑包处于开发中,可能会崩溃。

限制

此捆绑包使用php和Doctrine,不是导入大型csv文件的最佳选择。请使用数据库本机的导入/导出解决方案来解决这个问题。

特性

  • 通过csv文件导入数据
  • 将数据导出到csv文件
  • 一些用于读取/写入csv文件的服务

支持

  • Doctrine ORM

安装

此捆绑包列在Packagist上。

下载捆绑包

$ composer require misatotremor/csv-bundle

启用捆绑包以及依赖的AvroCaseBundle

<?php
// config/bundles.php

return [
    // ...
    Avro\CaseBundle\AvroCaseBundle::class => ['all' => true],
    Avro\CsvBundle\AvroCsvBundle::class => ['all' => true],
    // ...
];

配置

添加以下所需配置

# config/packages/avro_csv.yaml
avro_csv:
    db_driver: 'orm' # supports orm
    batch_size: 15 # The batch size between flushing & clearing the doctrine object manager
    tmp_upload_dir: '%kernel.root_dir%/../web/uploads/tmp/' # The directory to upload the csv files to
    sample_count: 5 # The number of sample rows to show during mapping

将路由添加到您的配置中

# config/routes/avro_csv.yaml
avro_csv:
    resource: '@AvroCsvBundle/Resources/config/routing.yml'

添加您想要实现导入/导出的实体/文档

# config/packages/avro_csv.yaml
avro_csv:
    # 
    objects: # the entities/documents you want to be able to import/export data with 
        client:
            class: 'Avro\CrmBundle\Entity\Client' # The entity/document class
            redirect_route: 'avro_crm_client_list' # The route to redirect to after import
        invoice:
            class: 'Avro\CrmBundle\Entity\Invoice'
            redirect_route: 'avro_crm_invoice_list'

要排除某些字段映射,请使用ImportExclude注解,如下所示。

namespace Avro\CrmBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Avro\CsvBundle\Annotation\ImportExclude;

/**
 * Avro\CrmBundle\Entity\Client
 *
 * @ORM\Entity
 */
class Client
{
    /**
     * @var string
     *
     * @ORM\Column(type="string", length=100, nullable=true)
     * @ImportExclude
     */
    protected $password;
    // ...
}

从PHP 8开始,您还可以将其用作属性,如下所示

namespace Avro\CrmBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Avro\CsvBundle\Annotation\ImportExclude;

#[ORM\Entity]
class Client
{
    #[ORM\Column(type: 'string', length: 100, nullable: true)]
    #[ImportExclude]
    protected string $password;
    // ...
}

导入

为尽可能多的实体/文档实现导入。您只需按照前面提到的将它们添加到对象节点即可。

然后只需包含指向特定导入页面的链接,如下所示

<a href="{{ path('avro_csv_import_upload', {'alias': 'client'}) }}">Go to import page</a>

将"client"替换为您在配置中指定的实体/文档别名。

视图

此捆绑包附带一些基本的twitter bootstrap视图,您可以通过扩展捆绑包来覆盖它们。

关联映射

当导入关联字段时,会触发一个事件,以允许实现适合您自己的逻辑

只需在您的应用程序中创建一个自定义监听器来监听AssociationFieldEvent::class事件。

一个简单的实现可能如下所示,通过名称获取关联实体

namespace App\EventListener;

use Avro\CsvBundle\Event\AssociationFieldEvent;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Csv import listener
 */
class ImportListener implements EventSubscriberInterface
{
    private $em;

    /**
     * @param EntityManagerInterface   $em      The entity manager
     */
    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }
    
    public static function getSubscribedEvents()
    {
        return [
            AssociationFieldEvent::class => 'importAssociation',
        ];
    }

    /**
     * Set the objects createdBy field
     *
     * @param AssociationFieldEvent $event
     */
    public function importAssociation(AssociationFieldEvent $event)
    {
        $association = $event->getAssociationMapping();
        switch ($association['type']) {
            case ClassMetadataInfo::ONE_TO_ONE:
            case ClassMetadataInfo::MANY_TO_ONE:
                $relation = $this->em->getRepository($association['targetEntity'])->findOneBy(
                    [
                        'name' => $event->getRow()[$event->getIndex()],
                    ]
                );
                if ($relation) {
                    $event->getObject()->{'set'.ucfirst($association['fieldName'])}($relation);
                }
                break;
        }
    }
}

自定义每行

想要自定义每行的某些字段?没问题。

当添加行时,会触发一个事件,您可以利用这个事件来自定义每行数据。

只需在您的应用程序中创建一个自定义监听器来监听RowAddedEvent::class事件。

例如...

namespace App\EventListener;

use Avro\CsvBundle\Event\RowAddedEvent;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\SecurityContextInterface;

/**
 * Csv import listener
 */
class ImportListener implements EventSubscriberInterface
{
    private $em;
    private $context;

    /**
     * @param EntityManagerInterface   $em      The entity manager
     * @param SecurityContextInterface $context The security context
     */
    public function __construct(EntityManagerInterface $em, SecurityContextInterface $context)
    {
        $this->em = $em;
        $this->context = $context;
    }
    
    public static function getSubscribedEvents()
    {
        return [
            RowAddedEvent::class => 'setCreatedBy',
        ];
    }

    /**
     * Set the objects createdBy field
     *
     * @param RowAddedEvent $event
     */
    public function setCreatedBy(RowAddedEvent $event)
    {
        $object = $event->getObject();

        $user = $this->context->getToken()->getUser();

        $object->setCreatedBy($user);
    }
}

注册您的监听器或使用自动装配

导出

此捆绑包提供了一些简单的导出功能。

导航到"/export/your-alias"将导出所有数据到csv,并允许您从浏览器下载。

您可以通过监听相应的事件(请参阅Avro\CsvBundle\Event命名空间中的事件)来自定义导出查询构建器和导出数据。

如果您想自定义返回的数据,只需创建自己的控制器操作,从导出器中获取queryBuilder,在调用"getContent()"之前添加约束。

示例。

namespace App\Controller;

use Avro\CsvBundle\Event\ExportedEvent;
use Avro\CsvBundle\Event\ExportEvent;
use Avro\CsvBundle\Export\ExporterInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Response;

class ExportController
{
    private ExporterInterface $exporter;
    private EventDispatcherInterface $eventDispatcher;
    /**
     * @psalm-var list<array{class: class-string, redirect_route: string}>
     */
    private array $aliases;

    /**
     * ExportController constructor.
     */
    public function __construct(
        EventDispatcherInterface $eventDispatcher,
        ExporterInterface $exporter,
        array $aliases
    ) {
        $this->eventDispatcher = $eventDispatcher;
        $this->exporter = $exporter;
        $this->aliases = $aliases;
    }

    /**
     * Export a db table.
     *
     * @param string $alias The objects alias
     *
     * @return Response
     */
    public function exportAction(string $alias): Response
    {
        $exporter->init($this->aliases[$alias]['class']);

        $this->eventDispatcher->dispatch(new ExportEvent($this->exporter));

        // customize the query
        $qb = $exporter->getQueryBuilder();
        $qb->where('o.fieldName =? 1')->setParameter(1, false);

        $exportedEvent = new ExportedEvent($this->exporter->getContent());

        $this->eventDispatcher->dispatch($exportedEvent);

        $response = new Response($exportedEvent->getContent());
        $response->headers->set('Content-Type', 'application/csv');
        $response->headers->set('Content-Disposition', sprintf('attachment; filename="%s.csv"', $alias));

        return $response;
    }
}

注册您的控制器或使用已设置的自动装配

待办事项

  • 完成mongodb支持

致谢

感谢jwage的EasyCSV为我们提供了一些基础工作。

欢迎反馈和pull requests!