如何在 symfony 登录后加载配置
How to load configuration after login in symfony
我有一个可以包含多个公司的 Symfony 3.4 应用程序。
每个公司都有自己的配置,在数据库中有自己的数据,所以我需要每个公司都有自己的数据库。
当任何用户登录时,该应用程序有一个 "core database" 包含用户信息。
用户登录后,应用程序必须更改配置以连接到已保存在 "core database".
中的用户公司数据库
有必要的步骤:
- 一个用户输入他的用户名和密码
- 应用查看中央数据库并获取用户身份验证。
- 应用程序获取要更改的用户配置。
- 应用程序更改配置,现在,sql请求将发送到公司的数据库。
有可能吗?如果没有,还有其他选择吗?
非常感谢!
您必须 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
]);
}
我有一个可以包含多个公司的 Symfony 3.4 应用程序。 每个公司都有自己的配置,在数据库中有自己的数据,所以我需要每个公司都有自己的数据库。 当任何用户登录时,该应用程序有一个 "core database" 包含用户信息。 用户登录后,应用程序必须更改配置以连接到已保存在 "core database".
中的用户公司数据库有必要的步骤:
- 一个用户输入他的用户名和密码
- 应用查看中央数据库并获取用户身份验证。
- 应用程序获取要更改的用户配置。
- 应用程序更改配置,现在,sql请求将发送到公司的数据库。
有可能吗?如果没有,还有其他选择吗?
非常感谢!
您必须 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
]);
}