使用 Symfony+Doctrine 获得 table 个名字,不包括 table 个由关系制成的名字
Get table names with Symfony+Doctrine excluding tables made from relations
我想使用 Doctrine 从我的 PSQL 数据库中获取所有 table 名称,但我不想要关系 tables,例如:
表格:
- 用户
- 客户
- users_clients <-- 不是这个
我目前正在使用
获取它们
$em->getConnection()->getSchemaManager()->listTables();
有什么方法可以在不使用 strpos()
排除数组结果的情况下做到这一点?
我编写了一个目前适用于我的代码,但尚未完成。如果您来到这里是为了找到我遇到的同一个问题的答案,请随时分析代码。
但请记住,我不是专业人士(远非专业人士)。
我在 ReportController 中有这个:
// Returns an array with my entities
$entities = $em->getMetadataFactory()->getAllMetadata();
//Generate my table names, according to Franz's answer
$tableNames = [
function(ClassMetadata $meta) {
return $meta->getTableName();
},
$entities
];
foreach ($tableNames[1] as $tableKey=>$tableName) {
$table[$tableKey] = $tableName->getTableName();
}
// Generate an array of columns from $table
// Code from generateColumnNames() below
$column[] = $this->getDoctrine()
->getRepository(Chamados::class)
->generateColumnNames($table);
//Since I'm displaying some Entity names in PT-BR, I need to treat them.
//I wish I had a better way to do this without having to treat them one by one
foreach ($entities as $entity) {
$e = explode('\',$entity->getName());
if ($e[2] === "User") {
$e[2] = "Usuários";
}
else if ($e[2] === "Tramite") {
$e[2] = "Trâmites";
}
else if ($e[2] === "Clients") {
$e[2] = "Clientes";
}
$entKey[] = $e[2];
}
//Insert each name into each array value to display them in my form
$entities = array_combine($entKey, $entities);
//Generate the form
$form = $this->createFormBuilder(['aaa'])
->add('entity', ChoiceType::class, [
'required' => true,
'placeholder' => '',
'attr' => [
'style' => 'text-transform:capitalize',
'class' => 'entity-class general-control'
],
'choices' => $entities
])
->add('type', ChoiceType::class, [
'label' => 'Tipo de relatório',
'required' => true,
'placeholder' => '',
'attr' => [
'style' => 'display: none',
'class' => 'type-class general-control'
],
'choices' => [
'Campo' => 0,
'Quantidade' => 1,
'Tudo' => 2,
]
])
->add('select', ChoiceType::class, [
'label' => 'Campos',
'required' => false,
'multiple' => true,
'attr' => [
'style' => 'text-transform:capitalize; display: none',
'class' => 'select-class general-control'
],
'choices' => $column
])
->add('where', ChoiceType::class, [
'label' => 'Onde',
'placeholder' => '',
'attr' => [
'style' => 'text-transform:capitalize; display: none',
'class' => 'where-class general-control'
],
'choices' => $column
])
->add('operator', ChoiceType::class, [
'label' => false,
'attr' => [
'style' => 'display: none',
'class' => 'operator-class general-control'
],
'choices' => [
'Igual a' => '=',
'Diferente de' => '!=',
'Contém' => 'LIKE',
'Entre' => 'BETWEEN',
'Maior ou igual a' => '>=',
'Menor ou igual a' => '<=',
]
])
->add('parameter', TextType::class, [
'label' => false,
'attr' => [
'style' => 'display: none',
'placeholder' => 'Parâmetro',
'readonly' => 'true',
'class' => 'parameter-class general-control'
]
])
->add('submit', SubmitType::class, [
'label' => 'Gerar relatório',
'attr' => [
'class' => 'button-blue submit-class general-control',
'style' => 'display: none'
]
])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//Get each form value to use it on generateReport() (code below)
$entity = $form->get('entity')->getData();
$type = $form->get('type')->getData();
$select = $form->get('select')->getData();
$where = $form->get('where')->getData();
$operator = $form->get('operator')->getData();
$parameter = $form->get('parameter')->getData();
//Generate the report, returning an array
$result = $this->getDoctrine()
->getRepository(Chamados::class)
->generateReport($entity, $type, $select, $where, $operator, $parameter);
return $this->redirectToRoute('generalResult', [
'result' => $result,
'entity' => $entity->getTableName()
]);
}
return [
'form' => $form->createView()
];
generateColumnNames()(在存储库内):
public function generateColumnNames($table){
$em = $this->getEntityManager();
foreach($table as $t) {
foreach ($em->getConnection()->getSchemaManager()->listTableColumns($t) as $v) {
$column[$t][$v->getName()] = $v->getName();
}
}
return $column;
}
generateReport()(在同一个存储库中):
public function generateReport($entity, int $type, array $selectField, string $whereField, string $operator, string $parameter): array
{
//0 = Fields / 1 = Count / * = Everything
if ($type === 0) {
foreach($selectField as $key=>$value) {
$select[$key] = "c." . $value;
}
$select = implode(", ", $select);
}
else if ($type === 1){
$select = "count('id')";
}
else {
$select = "c";
};
$query = $this->_em->createQueryBuilder()
->select($select)
->from($entity->getName(), 'c');
if ($operator === "LIKE") {
$parameter = "%" . $parameter . "%";
$query->andWhere("LOWER (c." . $whereField . ") " . $operator . " :" . $whereField);
}
else {
$query->andWhere("c." . $whereField . " " . $operator . " :" . $whereField);
}
$query->setParameter(":" . $whereField, $parameter);
$result = $query->getQuery()->getArrayResult();
return $result;
}
以下代码应该有效:
public class MyController {
public function listTables(EntityManagerInterface $em) {
$allMetadata = $em->getMetadataFactory()->getAllMetadata();
$tableNames = array_map(
function(ClassMetadata $meta) {
return $meta->getTableName();
},
$allMetadata);
// do something with the table names
}
}
这是我的做法...
public function getTables(): bool|array {
// get connection any way you do
$connection = BasePDO::getInstance()->getEntityManager()->getConnection();
$query = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'";
$statement = $connection->prepare($query);
// First column is the table name
return $statement->executeQuery()->fetchFirstColumn();
}
我想使用 Doctrine 从我的 PSQL 数据库中获取所有 table 名称,但我不想要关系 tables,例如:
表格:
- 用户
- 客户
- users_clients <-- 不是这个
我目前正在使用
获取它们$em->getConnection()->getSchemaManager()->listTables();
有什么方法可以在不使用 strpos()
排除数组结果的情况下做到这一点?
我编写了一个目前适用于我的代码,但尚未完成。如果您来到这里是为了找到我遇到的同一个问题的答案,请随时分析代码。 但请记住,我不是专业人士(远非专业人士)。
我在 ReportController 中有这个:
// Returns an array with my entities
$entities = $em->getMetadataFactory()->getAllMetadata();
//Generate my table names, according to Franz's answer
$tableNames = [
function(ClassMetadata $meta) {
return $meta->getTableName();
},
$entities
];
foreach ($tableNames[1] as $tableKey=>$tableName) {
$table[$tableKey] = $tableName->getTableName();
}
// Generate an array of columns from $table
// Code from generateColumnNames() below
$column[] = $this->getDoctrine()
->getRepository(Chamados::class)
->generateColumnNames($table);
//Since I'm displaying some Entity names in PT-BR, I need to treat them.
//I wish I had a better way to do this without having to treat them one by one
foreach ($entities as $entity) {
$e = explode('\',$entity->getName());
if ($e[2] === "User") {
$e[2] = "Usuários";
}
else if ($e[2] === "Tramite") {
$e[2] = "Trâmites";
}
else if ($e[2] === "Clients") {
$e[2] = "Clientes";
}
$entKey[] = $e[2];
}
//Insert each name into each array value to display them in my form
$entities = array_combine($entKey, $entities);
//Generate the form
$form = $this->createFormBuilder(['aaa'])
->add('entity', ChoiceType::class, [
'required' => true,
'placeholder' => '',
'attr' => [
'style' => 'text-transform:capitalize',
'class' => 'entity-class general-control'
],
'choices' => $entities
])
->add('type', ChoiceType::class, [
'label' => 'Tipo de relatório',
'required' => true,
'placeholder' => '',
'attr' => [
'style' => 'display: none',
'class' => 'type-class general-control'
],
'choices' => [
'Campo' => 0,
'Quantidade' => 1,
'Tudo' => 2,
]
])
->add('select', ChoiceType::class, [
'label' => 'Campos',
'required' => false,
'multiple' => true,
'attr' => [
'style' => 'text-transform:capitalize; display: none',
'class' => 'select-class general-control'
],
'choices' => $column
])
->add('where', ChoiceType::class, [
'label' => 'Onde',
'placeholder' => '',
'attr' => [
'style' => 'text-transform:capitalize; display: none',
'class' => 'where-class general-control'
],
'choices' => $column
])
->add('operator', ChoiceType::class, [
'label' => false,
'attr' => [
'style' => 'display: none',
'class' => 'operator-class general-control'
],
'choices' => [
'Igual a' => '=',
'Diferente de' => '!=',
'Contém' => 'LIKE',
'Entre' => 'BETWEEN',
'Maior ou igual a' => '>=',
'Menor ou igual a' => '<=',
]
])
->add('parameter', TextType::class, [
'label' => false,
'attr' => [
'style' => 'display: none',
'placeholder' => 'Parâmetro',
'readonly' => 'true',
'class' => 'parameter-class general-control'
]
])
->add('submit', SubmitType::class, [
'label' => 'Gerar relatório',
'attr' => [
'class' => 'button-blue submit-class general-control',
'style' => 'display: none'
]
])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//Get each form value to use it on generateReport() (code below)
$entity = $form->get('entity')->getData();
$type = $form->get('type')->getData();
$select = $form->get('select')->getData();
$where = $form->get('where')->getData();
$operator = $form->get('operator')->getData();
$parameter = $form->get('parameter')->getData();
//Generate the report, returning an array
$result = $this->getDoctrine()
->getRepository(Chamados::class)
->generateReport($entity, $type, $select, $where, $operator, $parameter);
return $this->redirectToRoute('generalResult', [
'result' => $result,
'entity' => $entity->getTableName()
]);
}
return [
'form' => $form->createView()
];
generateColumnNames()(在存储库内):
public function generateColumnNames($table){
$em = $this->getEntityManager();
foreach($table as $t) {
foreach ($em->getConnection()->getSchemaManager()->listTableColumns($t) as $v) {
$column[$t][$v->getName()] = $v->getName();
}
}
return $column;
}
generateReport()(在同一个存储库中):
public function generateReport($entity, int $type, array $selectField, string $whereField, string $operator, string $parameter): array
{
//0 = Fields / 1 = Count / * = Everything
if ($type === 0) {
foreach($selectField as $key=>$value) {
$select[$key] = "c." . $value;
}
$select = implode(", ", $select);
}
else if ($type === 1){
$select = "count('id')";
}
else {
$select = "c";
};
$query = $this->_em->createQueryBuilder()
->select($select)
->from($entity->getName(), 'c');
if ($operator === "LIKE") {
$parameter = "%" . $parameter . "%";
$query->andWhere("LOWER (c." . $whereField . ") " . $operator . " :" . $whereField);
}
else {
$query->andWhere("c." . $whereField . " " . $operator . " :" . $whereField);
}
$query->setParameter(":" . $whereField, $parameter);
$result = $query->getQuery()->getArrayResult();
return $result;
}
以下代码应该有效:
public class MyController {
public function listTables(EntityManagerInterface $em) {
$allMetadata = $em->getMetadataFactory()->getAllMetadata();
$tableNames = array_map(
function(ClassMetadata $meta) {
return $meta->getTableName();
},
$allMetadata);
// do something with the table names
}
}
这是我的做法...
public function getTables(): bool|array {
// get connection any way you do
$connection = BasePDO::getInstance()->getEntityManager()->getConnection();
$query = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'";
$statement = $connection->prepare($query);
// First column is the table name
return $statement->executeQuery()->fetchFirstColumn();
}