我有由 slug 标识的实体页面。我还可以在页面控制器中查看页面:
class PageController extends AbstractController
{
/**
* @Route("/{slug}", name="fronend_page")
*/
public function show(Page $page)
{
return $this->render("font_end/page/show.html.twig", [
"page" => $page,
]);
}
}
我正在寻找良好的实践来验证 slug(检查路由中是否存在),然后将其保存在数据库中而不使用前缀 示例:
路线存在:
@route ("/blog")
在创建 slug 之前检查博客是否存在:
/{slug} = /blog
谢谢
您可以使用
UniqueEntity
注释来检查 slug 的唯一性。
例如,在您的实体中添加
UniqueEntity
注释和 slug
字段。
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
* @UniqueEntity("slug")
*/
class Page
{
/**
* @ORM\Column(type="string", length=255, unique=true)
* @Assert\NotBlank
*/
private $slug;
public function __construct(string $slug)
{
$this->slug = $slug;
}
}
然后您可以创建一些服务或在控制器中进行验证。
/**
* @Route("/{slug}")
*/
public function show($slug, ValidatorInterface $validator)
{
$page = new Page($slug);
$errors = $validator->validate($author);
if (count($errors) > 0) {
// handle errors
}
// save entity
}
更新:
为了检查已经存在的路线,你可能可以这样做
public function isRouteExist(string $slug): bool
{
/** @var Symfony\Component\Routing\RouterInterface $router */
$routes = array_filter(array_map(function (\Symfony\Component\Routing\Route $route) {
if (!$route->compile()->getVariables()) {
return $route->getPath();
}
return null;
}, $router->getRouteCollection()->all()));
return in_array(sprintf('/%s', $slug), $routes, true);
}
我创建了一个验证 Symfony :
class ContainsCheckSlugValidator extends ConstraintValidator
{
private $router;
public function __construct(UrlGeneratorInterface $router)
{
$this->router = $router;
}
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof ContainsCheckSlug) {
throw new UnexpectedTypeException($constraint, ContainsCheckSlug::class);
}
// custom constraints should ignore null and empty values to allow
// other constraints (NotBlank, NotNull, etc.) take care of that
if (null === $value || "" === $value) {
return;
}
$routes = $this->router->getRouteCollection()->all();
$routes = array_map(function($route){
return $route->getPath();
},$routes);
if (in_array(sprintf("/{_locale}/%s/", $value), $routes, true)) {
$this->context->buildViolation($constraint->message)
->setParameter("{{ string }}", $value)
->addViolation();
}
}
}
谢谢@Ihor_Kostrov :)