TYPO3 Extbase:如何在没有原始 sql-query 的情况下获取禁用的相关对象?
TYPO3 Extbase: How to get disabled related Object, without raw sql-query?
场景:
我有以下型号:
ContactPerson 与 FrontendUser 有关系并且是关系的拥有方。现在我有以下问题:
我是 activating/deactivating 任务中的 FrontendUsers,基于活跃的 ContactPersons。当 FrontendUser 被禁用或删除时,contactPerson->getFrontendUser() 的结果为空,即使两个存储库都 ignoreEnableFields:
/** @var Typo3QuerySettings $querySettings */
$querySettings = $this->objectManager->get(Typo3QuerySettings::class);
$querySettings->setIgnoreEnableFields(true);
$querySettings->setRespectStoragePage(false);
$this->frontendUserRepository->setDefaultQuerySettings($querySettings);
$debugContactPerson = $this->contactPersonRepository->findOneByContactPersonIdAndIncludeDeletedAndHidden('634');
$debugFrontendUser = $this->frontendUserRepository->findOneByUid(7);
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump(
array(
'$debugContactPerson' => $debugContactPerson,
'$debugFrontendUser' => $debugFrontendUser,
)
);
结果:
P.s.: $this->frontendUserRepository->findByUid(7);
也不起作用,因为它没有使用查询,但是 persistenceManager->getObjectByIdentifier(...
当然忽略了查询设置。
问题是,在我的真实代码中,我无法使用 findOneByUid(),因为我无法在 contact_person 的 frontend_user 字段中获取整数值 (uid) .
有什么方法可以在不使用原始查询获取 contact_person 行的情况下解决这个问题?
我的(是原始查询)解决方案:
因为我不想编写自己的 QueryFactory 并且我不想向我的 contactPerson 添加冗余字段我现在用原始语句解决了它。也许它可以帮助遇到同样问题的人:
class FrontendUserRepository extends \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
{
/**
* @param \Vendor\ExtKey\Domain\Model\ContactPerson $contactPerson
* @return Object
*/
public function findByContactPersonByRawQuery(ContactPerson $contactPerson){
$query = $this->createQuery();
$query->statement(
"SELECT fe_users.* FROM fe_users" .
" LEFT JOIN tx_extkey_domain_model_contactperson contact_person ON contact_person.frontend_user = fe_users.uid" .
" WHERE contact_person.uid = " . $contactPerson->getUid()
);
return $query->execute()->getFirst();
}
}
直接调用存储库
tablefe_users
的启用字段有两个方面:
$querySettings->setIgnoreEnableFields(true);
$querySettings->setEnableFieldsToBeIgnored(['disable']);
看看一些 overview in the wiki page - 它说 6.2,但它在 7.6 和 8 的大多数部分仍然有效。但是,这仅在直接调用存储库时有效,但如果实体作为另一个实体的一部分被检索则无效 - 在这种情况下,存储库不用于嵌套实体。
修改嵌套实体的查询设置
隐式检索嵌套实体 - 这发生在 DataMapper::getPreparedQuery(DomainObjectInterface $parentObject, $propertyName)
中。要调整子实体的查询设置,必须重载 QueryFactoryInterface
实现。
在 ext_localconf.php
中注册替代实现(将 \Vendor\ExtensionName\Persistence\Generic\QueryFactory
替换为扩展程序的真实 class 名称):
$extbaseObjectContainer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
\TYPO3\CMS\Extbase\Object\Container\Container::class
);
$extbaseObjectContainer->registerImplementation(
\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface::class,
\Vendor\ExtensionName\Persistence\Generic\QueryFactory::class
);
对于新的 Typo3 版本 (v8+),registerImplementation 方法不再适用于 QueryFactory。相反,必须使用 XCLASS 来 overwrite/extend class:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory::class] = [
'className' => \Vendor\ExtensionName\Persistence\Generic\QueryFactory::class,
];
然后里面实现:
<?php
namespace \Vendor\ExtensionName\Persistence\Generic;
use TYPO3\CMS\Extbase\Domain\Model\FrontendUser;
class QueryFactory extends \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory {
public function create($className) {
$query = parent::create($className);
if (is_a($className, FrontendUser::class, true)) {
// @todo Find a way to configure that more generic
$querySettings = $query->getQuerySettings();
$querySettings->setIgnoreEnableFields(true);
// ... whatever you need to adjust in addition ...
}
return $query;
}
}
我对这个问题的解决方案是在 TCA 定义中禁用 "enablecolumns" 并自己在存储库中处理它。
这里有一个 findAll 方法的例子:
public function findAll($ignoreEnableFields = false) {
$query = $this->createQuery();
if (!$ignoreEnableFields) {
$currTime = time();
$query->matching(
$query->logicalAnd(
$query->equals("hidden", 0),
$query->logicalOr(
$query->equals("starttime", 0),
$query->lessThanOrEqual("starttime", $currTime)
),
$query->logicalOr(
$query->equals("endtime", 0),
$query->greaterThanOrEqual("endtime", $currTime)
)
)
);
}
return $query->execute();
}
场景:
我有以下型号:
ContactPerson 与 FrontendUser 有关系并且是关系的拥有方。现在我有以下问题:
我是 activating/deactivating 任务中的 FrontendUsers,基于活跃的 ContactPersons。当 FrontendUser 被禁用或删除时,contactPerson->getFrontendUser() 的结果为空,即使两个存储库都 ignoreEnableFields:
/** @var Typo3QuerySettings $querySettings */
$querySettings = $this->objectManager->get(Typo3QuerySettings::class);
$querySettings->setIgnoreEnableFields(true);
$querySettings->setRespectStoragePage(false);
$this->frontendUserRepository->setDefaultQuerySettings($querySettings);
$debugContactPerson = $this->contactPersonRepository->findOneByContactPersonIdAndIncludeDeletedAndHidden('634');
$debugFrontendUser = $this->frontendUserRepository->findOneByUid(7);
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump(
array(
'$debugContactPerson' => $debugContactPerson,
'$debugFrontendUser' => $debugFrontendUser,
)
);
结果:
P.s.: $this->frontendUserRepository->findByUid(7);
也不起作用,因为它没有使用查询,但是 persistenceManager->getObjectByIdentifier(...
当然忽略了查询设置。
问题是,在我的真实代码中,我无法使用 findOneByUid(),因为我无法在 contact_person 的 frontend_user 字段中获取整数值 (uid) .
有什么方法可以在不使用原始查询获取 contact_person 行的情况下解决这个问题?
我的(是原始查询)解决方案:
因为我不想编写自己的 QueryFactory 并且我不想向我的 contactPerson 添加冗余字段我现在用原始语句解决了它。也许它可以帮助遇到同样问题的人:
class FrontendUserRepository extends \TYPO3\CMS\Extbase\Domain\Repository\FrontendUserRepository
{
/**
* @param \Vendor\ExtKey\Domain\Model\ContactPerson $contactPerson
* @return Object
*/
public function findByContactPersonByRawQuery(ContactPerson $contactPerson){
$query = $this->createQuery();
$query->statement(
"SELECT fe_users.* FROM fe_users" .
" LEFT JOIN tx_extkey_domain_model_contactperson contact_person ON contact_person.frontend_user = fe_users.uid" .
" WHERE contact_person.uid = " . $contactPerson->getUid()
);
return $query->execute()->getFirst();
}
}
直接调用存储库
tablefe_users
的启用字段有两个方面:
$querySettings->setIgnoreEnableFields(true);
$querySettings->setEnableFieldsToBeIgnored(['disable']);
看看一些 overview in the wiki page - 它说 6.2,但它在 7.6 和 8 的大多数部分仍然有效。但是,这仅在直接调用存储库时有效,但如果实体作为另一个实体的一部分被检索则无效 - 在这种情况下,存储库不用于嵌套实体。
修改嵌套实体的查询设置
隐式检索嵌套实体 - 这发生在 DataMapper::getPreparedQuery(DomainObjectInterface $parentObject, $propertyName)
中。要调整子实体的查询设置,必须重载 QueryFactoryInterface
实现。
在 ext_localconf.php
中注册替代实现(将 \Vendor\ExtensionName\Persistence\Generic\QueryFactory
替换为扩展程序的真实 class 名称):
$extbaseObjectContainer = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
\TYPO3\CMS\Extbase\Object\Container\Container::class
);
$extbaseObjectContainer->registerImplementation(
\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactoryInterface::class,
\Vendor\ExtensionName\Persistence\Generic\QueryFactory::class
);
对于新的 Typo3 版本 (v8+),registerImplementation 方法不再适用于 QueryFactory。相反,必须使用 XCLASS 来 overwrite/extend class:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory::class] = [
'className' => \Vendor\ExtensionName\Persistence\Generic\QueryFactory::class,
];
然后里面实现:
<?php
namespace \Vendor\ExtensionName\Persistence\Generic;
use TYPO3\CMS\Extbase\Domain\Model\FrontendUser;
class QueryFactory extends \TYPO3\CMS\Extbase\Persistence\Generic\QueryFactory {
public function create($className) {
$query = parent::create($className);
if (is_a($className, FrontendUser::class, true)) {
// @todo Find a way to configure that more generic
$querySettings = $query->getQuerySettings();
$querySettings->setIgnoreEnableFields(true);
// ... whatever you need to adjust in addition ...
}
return $query;
}
}
我对这个问题的解决方案是在 TCA 定义中禁用 "enablecolumns" 并自己在存储库中处理它。 这里有一个 findAll 方法的例子:
public function findAll($ignoreEnableFields = false) {
$query = $this->createQuery();
if (!$ignoreEnableFields) {
$currTime = time();
$query->matching(
$query->logicalAnd(
$query->equals("hidden", 0),
$query->logicalOr(
$query->equals("starttime", 0),
$query->lessThanOrEqual("starttime", $currTime)
),
$query->logicalOr(
$query->equals("endtime", 0),
$query->greaterThanOrEqual("endtime", $currTime)
)
)
);
}
return $query->execute();
}