如何在 symfony 登录后加载配置

How to load configuration after login in symfony

我有一个可以包含多个公司的 Symfony 3.4 应用程序。 每个公司都有自己的配置,在数据库中有自己的数据,所以我需要每个公司都有自己的数据库。 当任何用户登录时,该应用程序有一个 "core database" 包含用户信息。 用户登录后,应用程序必须更改配置以连接到已保存在 "core database".

中的用户公司数据库

有必要的步骤:

有可能吗?如果没有,还有其他选择吗?

非常感谢!

您必须 work here with multiple entity managers and connections 并且想法是使用基于用户检索当前客户的订户。此订户(或其他服务)将设置一个包含实体管理器名称的全局变量。

// A subscriber (high level priority) or a service already set $customerName

// In your controller or in a service
$customerEntityManager = $this->getDoctrine()->getManager($customerName);

另请查看此捆绑包以获取创意 https://github.com/vmeretail/multi-tenancy-bundle

编辑

根据您的需要使用和调整此文件https://github.com/vmeretail/multi-tenancy-bundle/blob/master/Service/TenantResolver.php

这里只需要解析当前用户的租户即可

在你的控制器中:

...

public function index(TenantResolver $tenantResolver)
{
    $customerEntityManager = $this->getDoctrine()->getManager($tenantResolver->getTenant()->getName()); // or getId() or something else
}

在服务中:

...

use Doctrine\Common\Persistence\ManagerRegistry;

private $tenantResolver;
private $managerRegistry;

public function__construct(TenantResolver $tenantResolver, ManagerRegistry $managerRegistry)
{
    $this->tenantResolver = $tenantResolver;
    $this->managerRegistry = $managerRegistry;
}

public function doSomething()
{
    $this->managerRegistry->getManager($this->tenantResolver->getTenant()->getName());  // or getId() or something else
}

就是这个想法,这里必须有更好的办法,比如在 service/controller 构造函数中直接注入正确的管理器。

我找到了以下适用于 Symfony 4 的解决方案,我认为它也适用于 symfony 3.4。

我创建了一个服务,将默认实体管理器复制到连接到另一个数据库的新服务中:

namespace App\Service;

use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Doctrine\ORM\EntityManagerInterface;

class CustomEntityManagerHelper 
{
    private $em;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->em = $entityManager;
    }

    /*
     * get entity manager for another database
     */
    public function getManagerForDatabase($db_name): EntityManagerInterface
    {
        $conn = array(
            'driver' => 'pdo_mysql',
            'user' => 'root',
            'password' => 'mypass',
            'dbname' => $db_name
        );

        return \Doctrine\ORM\EntityManager::create(
            $conn,
            $this->em->getConfiguration(),
            $this->em->getEventManager()
        );
    }
}

到现在为止这很容易,但是存储库 class 仍然使用默认的实体管理器。所以我在存储库中添加了一个方法 setEntityManager:

<?php

namespace App\Repository;

use App\Entity\Product;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;

use Doctrine\ORM\EntityManagerInterface;

class ProductRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Product::class);
    }

    public function setEntityManager(EntityManagerInterface $entityManager): self
    {
        $this->_em = $entityManager;

        return $this;
    }

    // custom methods here
}

现在我可以使用自定义实体管理器并将其设置到存储库:

use App\Service\CustomEntityManagerHelper;

// ...

/**
 * @Route("/products", name="app_product", methods={"GET"})
 */
public function index(CustomEntityManagerHelper $helper): Response
{
    $myManager = $helper->getManagerForDatabase($this->getUser()->getDatabaseName());

    $products = $myManager->getRepository('App:Product')
        ->setEntityManager($myManager)                  // IMPORTANT!
        ->findAll();

    return $this->render('product/index.html.twig', [
        'products' => $products
    ]);
}