{"id":1060,"date":"2025-06-12T11:40:55","date_gmt":"2025-06-12T03:40:55","guid":{"rendered":"https:\/\/www.zhaozhao123.cn\/php\/php-application-manual\/symfony\/1060.html"},"modified":"2025-06-12T11:40:55","modified_gmt":"2025-06-12T03:40:55","slug":"%e5%a6%82%e4%bd%95%e5%9c%a8-symfony-%e4%b8%ad%e9%aa%8c%e8%af%81%e8%af%b7%e6%b1%82%e6%95%b0%e6%8d%ae","status":"publish","type":"my1js","link":"https:\/\/www.zhaozhao123.cn\/php\/my1js\/1060.html","title":{"rendered":"\u5982\u4f55\u5728 Symfony \u4e2d\u9a8c\u8bc1\u8bf7\u6c42\u6570\u636e"},"content":{"rendered":"<div class=\"wp-block-columns p-0 border is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-columns px-4 py-3 border-bottom has-background is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\" style=\"background:linear-gradient(243deg,rgb(238,238,238) 0%,rgba(58,166,242,0.15) 100%)\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\r\n<figure class=\"wp-block-image size-thumbnail is-resized is-style-rounded is-style-rounded--1\"><img decoding=\"async\" src=\"https:\/\/www.zhaozhao123.cn\/myitems\/images\/sites16\/2025\/06\/dyA-1-400x300.jpg\" alt=\"Bug&#32534;&#35793;&#29422;\" class=\"wp-image-1842\" style=\"object-fit:cover;width:30px;height:30px\"><\/figure>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading my-0\" style=\"font-size:clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.175), 1rem);\">Bug&#32534;&#35793;&#29422;<\/h2>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n\r\n\r\n\r\n<div class=\"wp-block-columns px-xl-5 px-4 py-xl-4 py-3 is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<p>&#22312; Symfony &#20013;&#65292;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#26159;&#30830;&#20445;&#24212;&#29992;&#31243;&#24207;&#23433;&#20840;&#24615;&#21644;&#27491;&#30830;&#24615;&#30340;&#37325;&#35201;&#27493;&#39588;&#12290;&#20197;&#19979;&#26159;&#19968;&#20123;&#24120;&#35265;&#30340;&#26041;&#27861;&#21644;&#31034;&#20363;&#20195;&#30721;&#26469;&#24110;&#21161;&#20320;&#22312; Symfony &#24212;&#29992;&#20013;&#36827;&#34892;&#39564;&#35777;&#12290;<\/p>\n<h3>1. &#20351;&#29992; <code>Validator<\/code> &#21253;<\/h3>\n<p>Symfony &#25552;&#20379;&#20102; <code>Validator<\/code> &#21253;&#26469;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#12290;&#39318;&#20808;&#65292;&#20320;&#38656;&#35201;&#22312;&#20320;&#30340;&#25511;&#21046;&#22120;&#20013;&#24341;&#20837; <code>ValidatorInterface<\/code>&#12290;<\/p>\n<pre><code class=\"language-php\">use SymfonyComponentValidatorValidatorInterface;<\/code><\/pre>\n<p>&#28982;&#21518;&#65292;&#20320;&#21487;&#20197;&#20351;&#29992; <code>Validator<\/code> &#23545;&#35937;&#26469;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#12290;<\/p>\n<pre><code class=\"language-php\">public function validateRequest(Request $request, ValidatorInterface $validator)\n{\n    \/\/ &#33719;&#21462;&#25152;&#26377;&#21442;&#25968;\n    $data = $request-&gt;request-&gt;all();\n\n    \/\/ &#21019;&#24314;&#39564;&#35777;&#32452;\n    $groups = ['Default'];\n\n    \/\/ &#39564;&#35777;&#25968;&#25454;\n    $errors = $validator-&gt;validate($data, null, $groups);\n\n    if (count($errors) &gt; 0) {\n        \/\/ &#36820;&#22238;&#39564;&#35777;&#38169;&#35823;\n        return new JsonResponse(['errors' =&gt; $errors], 422);\n    }\n\n    \/\/ &#25968;&#25454;&#39564;&#35777;&#36890;&#36807;&#65292;&#21487;&#20197;&#32487;&#32493;&#22788;&#29702;\n    return new JsonResponse(['message' =&gt; 'Data is valid'], 200);\n}<\/code><\/pre>\n<h3>2. &#20351;&#29992; YAML &#37197;&#32622;&#25991;&#20214;<\/h3>\n<p>&#20320;&#20063;&#21487;&#20197;&#20351;&#29992; YAML &#25991;&#20214;&#26469;&#37197;&#32622;&#39564;&#35777;&#35268;&#21017;&#12290;&#39318;&#20808;&#65292;&#21019;&#24314;&#19968;&#20010; YAML &#25991;&#20214;&#65288;&#20363;&#22914; <code>validation.yml<\/code>&#65289;&#65292;&#24182;&#22312;&#20854;&#20013;&#23450;&#20041;&#39564;&#35777;&#35268;&#21017;&#12290;<\/p>\n<pre><code class=\"language-yaml\"># config\/packages\/validation.yaml\nparameters:\n    validator.mapping.class: AppDataDtoUser\n\nservices:\n    AppDataDtoUser:\n        properties:\n            username:\n                -NotBlank\n                -Length(max=50)\n            email:\n                -NotBlank\n                -Email<\/code><\/pre>\n<p>&#28982;&#21518;&#65292;&#22312;&#20320;&#30340;&#25511;&#21046;&#22120;&#20013;&#20351;&#29992; <code>AnnotationReader<\/code> &#26469;&#35835;&#21462;&#36825;&#20123;&#37197;&#32622;&#24182;&#24212;&#29992;&#39564;&#35777;&#12290;<\/p>\n<pre><code class=\"language-php\">use SymfonyComponentValidatorValidationContext;\nuse SymfonyComponentValidatorValidatorInterface;\nuse SymfonyComponentHttpFoundationRequest;\n\nclass UserController extends AbstractController\n{\n    public function validateRequest(Request $request, ValidatorInterface $validator)\n    {\n        \/\/ &#33719;&#21462;&#35831;&#27714;&#25968;&#25454;\n        $data = $request-&gt;request-&gt;all();\n\n        \/\/ &#21019;&#24314;&#39564;&#35777;&#19978;&#19979;&#25991;\n        $context = ValidationContext::create();\n        $context-&gt;setMappingClass(AppDataDtoUser::class);\n\n        \/\/ &#39564;&#35777;&#25968;&#25454;\n        $errors = $validator-&gt;validate($data, $context);\n\n        if (count($errors) &gt; 0) {\n            \/\/ &#36820;&#22238;&#39564;&#35777;&#38169;&#35823;\n            return new JsonResponse(['errors' =&gt; $errors], 422);\n        }\n\n        \/\/ &#25968;&#25454;&#39564;&#35777;&#36890;&#36807;&#65292;&#21487;&#20197;&#32487;&#32493;&#22788;&#29702;\n        return new JsonResponse(['message' =&gt; 'Data is valid'], 200);\n    }\n}<\/code><\/pre>\n<h3>3. &#33258;&#23450;&#20041;&#39564;&#35777;&#22120;<\/h3>\n<p>&#22914;&#26524;&#20320;&#38656;&#35201;&#26356;&#22797;&#26434;&#30340;&#39564;&#35777;&#36923;&#36753;&#65292;&#21487;&#20197;&#33258;&#23450;&#20041;&#39564;&#35777;&#22120;&#12290;&#39318;&#20808;&#65292;&#21019;&#24314;&#19968;&#20010;&#39564;&#35777;&#22120;&#31867;&#65292;&#24182;&#22312;&#20854;&#20013;&#23454;&#29616;&#39564;&#35777;&#35268;&#21017;&#12290;<\/p>\n<pre><code class=\"language-php\">namespace AppValidator;\n\nuse SymfonyComponentValidatorConstraint;\nuse SymfonyComponentValidatorConstraintValidatorInterface;\n\nclass UsernameValidator implements ConstraintValidatorInterface\n{\n    private $maxLength;\n\n    public function __construct(int $maxLength = 50)\n    {\n        $this-&gt;maxLength = $maxLength;\n    }\n\n    public function initialize(Username $constraint): void\n    {\n        $this-&gt;maxLength = $constraint-&gt;maxLength;\n    }\n\n    public function isValid(mixed $value, Constraint $constraint, array $context): bool\n    {\n        if (!is_string($value)) {\n            return false;\n        }\n\n        return mb_strlen($value) &lt;= $this-&gt;maxLength;\n    }\n}<\/code><\/pre>\n<p>&#28982;&#21518;&#65292;&#27880;&#20876;&#36825;&#20010;&#39564;&#35777;&#22120;&#24182;&#20351;&#29992;&#23427;&#12290;<\/p>\n<pre><code class=\"language-php\">\/\/ src\/Data\/Dto\/User.php\nnamespace AppDataDto;\n\nuse SymfonyComponentValidatorConstraints as Assert;\n\nclass User\n{\n    \/**\n     * @AssertNotBlank()\n     * @AssertLength(max=\"50\")\n     *\/\n    private $username;\n\n    \/\/ Getters and setters\n}<\/code><\/pre>\n<pre><code class=\"language-php\">\/\/ config\/services.yaml\nservices:\n    AppValidatorUsernameValidator:\n        arguments: [50]\n        tags:\n            - { name: validator.constraint_validator }<\/code><\/pre>\n<p>&#36890;&#36807;&#20197;&#19978;&#26041;&#27861;&#65292;&#20320;&#21487;&#20197;&#22312; Symfony &#20013;&#26377;&#25928;&#22320;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#65292;&#30830;&#20445;&#24212;&#29992;&#31243;&#24207;&#30340;&#23433;&#20840;&#24615;&#21644;&#27491;&#30830;&#24615;&#12290;<\/p>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n<\/div><div class=\"wp-block-columns p-0 border is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-columns px-4 py-3 border-bottom has-background is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\" style=\"background:linear-gradient(243deg,rgb(238,238,238) 0%,rgba(58,166,242,0.15) 100%)\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\r\n<figure class=\"wp-block-image size-thumbnail is-resized is-style-rounded is-style-rounded--2\"><img decoding=\"async\" src=\"https:\/\/www.zhaozhao123.cn\/myitems\/images\/sites16\/2025\/06\/zp-400x300.jpg\" alt=\"&#40657;&#26495;Bug&#35762;&#24072;\" class=\"wp-image-1849\" style=\"object-fit:cover;width:30px;height:30px\"><\/figure>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading my-0\" style=\"font-size:clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.175), 1rem);\">&#40657;&#26495;Bug&#35762;&#24072;<\/h2>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n\r\n\r\n\r\n<div class=\"wp-block-columns px-xl-5 px-4 py-xl-4 py-3 is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<body><h2>&#20171;&#32461;<\/h2><p>&#25968;&#25454;&#39564;&#35777;&#26159;Web&#24212;&#29992;&#31243;&#24207;&#24320;&#21457;&#20013;&#30340;&#20851;&#38190;&#26041;&#38754;&#65292;&#30830;&#20445;&#31995;&#32479;&#20869;&#25968;&#25454;&#30340;&#23436;&#25972;&#24615;&#21644;&#23433;&#20840;&#24615;&#20197;&#21450;&#29992;&#25143;&#20307;&#39564;&#12290;&#22312;&#27969;&#34892;&#30340;PHP&#26694;&#26550;Symfony&#20013;&#65292;&#39564;&#35777;&#26159;&#26680;&#24515;&#32452;&#20214;&#20043;&#19968;&#65292;&#24110;&#21161;&#24320;&#21457;&#32773;&#36731;&#26494;&#26377;&#25928;&#22320;&#30830;&#35748;&#25509;&#25910;&#21040;&#30340;&#25968;&#25454;&#26159;&#21542;&#31526;&#21512;&#39044;&#23450;&#20041;&#30340;&#26631;&#20934;&#65292;&#22312;&#22788;&#29702;&#25110;&#20445;&#23384;&#21040;&#25968;&#25454;&#24211;&#20043;&#21069;&#36827;&#34892;&#39564;&#35777;&#12290;&#22312;&#36825;&#31687;&#25945;&#31243;&#20013;&#65292;&#25105;&#20204;&#23558;&#25506;&#32034;Symfony&#30340;&#39564;&#35777;&#36807;&#31243;&#65292;&#24182;&#23398;&#20064;&#22914;&#20309;&#39640;&#25928;&#22320;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#12290;<\/p><p>&#22312;&#28145;&#20837;&#23454;&#26045;&#32454;&#33410;&#20043;&#21069;&#65292;&#29702;&#35299;Symfony&#39564;&#35777;&#31995;&#32479;&#30340;&#22522;&#30784;&#30693;&#35782;&#33267;&#20851;&#37325;&#35201;&#12290;Symfony&#21033;&#29992;&#19968;&#20010;Validator&#32452;&#20214;&#65292;&#35813;&#32452;&#20214;&#20381;&#36182;&#20110;&#32422;&#26463;&#26469;&#35268;&#23450;&#24212;&#24212;&#29992;&#20110;&#25968;&#25454;&#23545;&#35937;&#30340;&#39564;&#35777;&#35268;&#21017;&#12290;&#32422;&#26463;&#26159;&#19968;&#32452;&#22768;&#26126;&#24615;&#35268;&#21017;&#65292;&#21487;&#20197;&#24212;&#29992;&#21040;&#23545;&#35937;&#30340;&#23646;&#24615;&#19978;&#12290;<\/p><h2>&#35774;&#32622;&#24744;&#30340;Symfony&#39033;&#30446;<\/h2><p>&#39318;&#20808;&#65292;&#35831;&#30830;&#20445;&#24050;&#32463;&#26377;&#19968;&#20010;Symfony&#39033;&#30446;&#35774;&#32622;&#22909;&#12290;&#22914;&#26524;&#20320;&#27809;&#26377;&#29616;&#26377;&#30340;&#39033;&#30446;&#65292;&#21487;&#20197;&#20351;&#29992;Symfony&#23433;&#35013;&#22120;&#25110;Composer&#26469;&#21019;&#24314;&#19968;&#20010;&#12290;&#35831;&#35760;&#24471;&#22312;&#25191;&#34892;&#20197;&#19979;&#21629;&#20196;&#26102;&#21253;&#21547;Validator&#32452;&#20214;&#65306;<\/p><pre><code>composer require symfony\/validator<\/code><\/pre><p>&#19968;&#26086;&#23433;&#35013;&#20102;&#39564;&#35777;&#22120;&#32452;&#20214;&#65292;&#24744;&#23601;&#21487;&#20197;&#24320;&#22987;&#36827;&#34892;&#39564;&#35777;&#36807;&#31243;&#20102;&#12290;<\/p><h2>&#21019;&#24314;&#19968;&#20010;&#25968;&#25454;&#31867;<\/h2><p>&#22312;Symfony&#20013;&#65292;&#39564;&#35777;&#36890;&#24120;&#26159;&#24212;&#29992;&#20110;&#19968;&#20010;&#31216;&#20026;&#25968;&#25454;&#31867;&#30340;&#29305;&#27530;&ldquo;&#27169;&#22411;&rdquo;&#31867;&#19978;&#30340;&#12290;&#35753;&#25105;&#20204;&#20174;&#21019;&#24314;&#19968;&#20010;&#34920;&#31034;&#25105;&#20204;&#25171;&#31639;&#39564;&#35777;&#30340;&#25968;&#25454;&#30340;&#25968;&#25454;&#31867;&#24320;&#22987;&#12290;&#20986;&#20110;&#28436;&#31034;&#30446;&#30340;&#65292;&#25105;&#20204;&#23558;&#39564;&#35777;&#26032;&#29992;&#25143;&#36134;&#25143;&#30340;&#36755;&#20837;&#65306;<\/p><pre><code>namespace AppEntity;\n\nuse SymfonyComponentValidatorConstraints as Assert;\n\nclass User\n{\n    \/**\n     * @AssertNotBlank(message=\"The email must not be blank.\")\n     * @AssertEmail(message=\"The email '{{ value }}' is not a valid email.\")\n     *\/\n    private $email;\n\n    \/**\n     * @AssertLength(\n     *      min = 6,\n     *      max = 50,\n     *      minMessage = \"Password must be at least {{ limit }} characters long.\",\n     *      maxMessage = \"Password cannot be longer than {{ limit }} characters.\"\n     * )\n     *\/\n    private $password;\n\n    public function getEmail(): ?string\n    {\n        return $this-&gt;email;\n    }\n\n    public function setEmail(string $email): self\n    {\n        $this-&gt;email = $email;\n        return $this;\n    }\n\n    public function getPassword(): ?string\n    {\n        return $this-&gt;password;\n    }\n\n    public function setPassword(string $password): self\n    {\n        $this-&gt;password = $password;\n        return $this;\n    }\n}\n<\/code><\/pre><p>&#22312;&#19978;&#36848;User&#31867;&#20013;&#65292;&#25105;&#20204;&#24050;&#32463;&#23450;&#20041;&#20102;&#20004;&#20010;&#23646;&#24615;&#65306;<code>email<\/code>&#21644;&#25105;&#26377;&#20160;&#20040;&#20107;&#24773;&#21527;&#65311;<code>password<\/code>&#27599;&#20010;&#37117;&#26377;&#33258;&#24049;&#30340;&#32422;&#26463;&#26465;&#20214;&#65292;&#36825;&#20123;&#32422;&#26463;&#26465;&#20214;&#20915;&#23450;&#20102;&#39564;&#35777;&#36923;&#36753;&#12290;<\/p><h2>&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;<\/h2><p>&#22312;&#23450;&#20041;&#25968;&#25454;&#31867;&#20043;&#21518;&#65292;&#19979;&#19968;&#27493;&#26159;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#12290;&#20551;&#35774;&#25105;&#20204;&#26377;&#19968;&#20010;&#22788;&#29702;&#29992;&#25143;&#27880;&#20876;&#30340;&#25511;&#21046;&#22120;&#65292;&#25105;&#20204;&#38656;&#35201;&#30830;&#20445;&#35831;&#27714;&#25968;&#25454;&#26377;&#25928;&#12290;&#25105;&#20204;&#23558;&#20351;&#29992;&ldquo;ValidatorInterface&rdquo;&#20013;&#30340;&ldquo;validate&rdquo;&#26041;&#27861;&#26469;&#39564;&#35777;&#25105;&#20204;&#30340;&#25968;&#25454;&#65306;<\/p><pre><code>namespace AppController;\n\nuse AppEntityUser;\nuse SymfonyComponentHttpFoundationResponse;\nuse SymfonyComponentHttpFoundationRequest;\nuse SymfonyComponentValidatorValidatorValidatorInterface;\nuse SymfonyComponentHttpFoundationJsonResponse;\n\nclass RegistrationController\n{\n    public function register(Request $request, ValidatorInterface $validator): Response\n    {\n        $data = json_decode($request-&gt;getContent(), true);\n\n        $user = new User();\n        $user-&gt;setEmail($data['email']);\n        $user-&gt;setPassword($data['password']);\n\n        $errors = $validator-&gt;validate($user);\n\n        if (count($errors) &gt; 0) {\n            $errorsString = (string) $errors;\n\n            return new JsonResponse(['errors' =&gt; $errorsString], Response::HTTP_BAD_REQUEST);\n        }\n\n        \/\/ Proceed with persisting the user data ...\n\n        return new JsonResponse(['status' =&gt; 'User registered successfully!'], Response::HTTP_OK);\n    }\n}\n<\/code><\/pre><p>&#27491;&#22914;&#24744;&#25152;&#35265;&#65292;&#25105;&#20204;&#30452;&#25509;&#20174;&#35831;&#27714;&#25968;&#25454;&#20013;&#33719;&#21462;&#20449;&#24687;&#12290;<code>Request<\/code>&#23545;&#35937;&#65292;&#22635;&#20805;&#25105;&#20204;&#30340;<code>User<\/code>&#23545;&#35937;&#21253;&#21547;&#23427;&#65292;&#28982;&#21518;&#23558;&#20854;&#20256;&#36882;&#32473;&#25105;&#20204;&#30340;&#27880;&#20837;&#30340;&ldquo;&#39564;&#35777;&rdquo;&#26041;&#27861;&#12290;<code>ValidatorInterface<\/code>&#23454;&#20363;&#12290;&#20219;&#20309;&#39564;&#35777;&#38169;&#35823;&#37117;&#20250;&#20197;JSON&#21709;&#24212;&#30340;&#24418;&#24335;&#36820;&#22238;&#12290;<\/p><h2>&#33258;&#23450;&#20041;&#32422;&#26463;&#39564;&#35777;&#22120;<\/h2><p>&#26377;&#26102;&#20505;&#65292;&#20320;&#38656;&#35201;&#39564;&#35777;&#25968;&#25454;&#26159;&#21542;&#31526;&#21512;&#26356;&#20855;&#20307;&#25110;&#22797;&#26434;&#30340;&#26465;&#20214;&#65292;&#32780;&#36825;&#20123;&#26631;&#20934;&#32422;&#26463;&#26080;&#27861;&#28085;&#30422;&#12290;Symfony&#20801;&#35768;&#20320;&#21019;&#24314;&#33258;&#23450;&#20041;&#30340;&#32422;&#26463;&#12290;&#35753;&#25105;&#20204;&#36890;&#36807;&#19968;&#20010;&#20363;&#23376;&#26469;&#35828;&#26126;&#22914;&#20309;&#26816;&#26597;&#23383;&#31526;&#20018;&#26159;&#21542;&#21482;&#21253;&#21547;&#25968;&#23383;&#21644;&#23383;&#27597;&#65306;<\/p><pre><code>namespace AppValidatorConstraints;\n\nuse SymfonyComponentValidatorConstraint;\n\nclass IsAlphanumeric extends Constraint\n{\n    public $message = 'The string \"{{ string }}\" contains an illegal character: it can only contain letters or numbers.';\n}\n<\/code><\/pre><p>&#28982;&#21518;&#20320;&#38656;&#35201;&#20026;&#32422;&#26463;&#21019;&#24314;&#19968;&#20010;&#39564;&#35777;&#22120;&#65306;<\/p><pre><code>namespace AppValidatorConstraints;\n\nuse SymfonyComponentValidatorConstraint;\nuse SymfonyComponentValidatorConstraintValidator;\n\nclass IsAlphanumericValidator extends ConstraintValidator\n{\n    public function validate($value, Constraint $constraint)\n    {\n        if (!preg_match('\/^[a-zA-Z0-9]+$\/', $value, $matches)) {\n            $this-&gt;context-&gt;buildViolation($constraint-&gt;message)\n                -&gt;setParameter('{{ string }}', $value)\n                -&gt;addViolation();\n        }\n    }\n}\n<\/code><\/pre><p>&#19968;&#26086;&#35774;&#32622;&#20102;&#33258;&#23450;&#20041;&#32422;&#26463;&#21450;&#20854;&#39564;&#35777;&#22120;&#65292;&#23601;&#21487;&#20197;&#20687;&#20351;&#29992;&#26631;&#20934;&#32422;&#26463;&#19968;&#26679;&#65292;&#22312;&#25968;&#25454;&#31867;&#20013;&#20351;&#29992;&#26032;&#30340;&#32422;&#26463;&#20316;&#20026;&#27880;&#35299;&#12290;<\/p><h2>&#22312;API&#35843;&#29992;&#20013;&#22788;&#29702;&#39564;&#35777;&#65288;Validation&#65289;<\/h2><p>&#22312;&#26500;&#24314;API&#26102;&#65292;&#36890;&#24120;&#20250;&#20351;&#29992;&#25511;&#21046;&#22120;&#25509;&#21463;JSON&#25968;&#25454;&#20316;&#20026;&#35831;&#27714;&#20307;&#12290;&#22312;&#36825;&#31181;&#24773;&#20917;&#19979;&#65292;&#20026;&#20102;&#26144;&#23556;&#21644;&#39564;&#35777;&#36825;&#20123;&#25968;&#25454;&#24182;&#23558;&#20854;&#29992;&#20110;&#26356;&#26032;&#27169;&#22411;&#65292;&#21487;&#33021;&#20250;&#21019;&#24314;&#19968;&#20010;&#21517;&#20026;&ldquo;DTO&rdquo;&#65288;&#25968;&#25454;&#20256;&#36755;&#23545;&#35937;&#65289;&#30340;&#29305;&#27530;&#31867;&#12290;<\/p><h2>&#32467;&#35770;&#12290;<\/h2><p>&#32508;&#19978;&#25152;&#36848;&#65292;&#20351;&#29992;Symfony&#30340;Validator&#32452;&#20214;&#36827;&#34892;&#39564;&#35777;&#26159;&#19968;&#31181;&#24378;&#22823;&#30340;&#19988;&#28789;&#27963;&#30340;&#25968;&#25454;&#23436;&#25972;&#24615;&#20445;&#38556;&#26041;&#24335;&#12290;&#36890;&#36807;&#29702;&#35299;&#24182;&#23454;&#26045;&#26412;&#25945;&#31243;&#20013;&#30340;&#39564;&#35777;&#36807;&#31243;&#65292;&#22914;&#35774;&#32622;&#32422;&#26463;&#12289;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#20197;&#21450;&#21019;&#24314;&#33258;&#23450;&#20041;&#32422;&#26463;&#65292;&#24744;&#21487;&#20197;&#22312;&#30830;&#20445;&#24212;&#29992;&#31243;&#24207;&#25968;&#25454;&#23436;&#25972;&#24615;&#21644;&#25552;&#39640;&#25968;&#25454;&#36136;&#37327;&#26041;&#38754;&#21462;&#24471;&#26174;&#33879;&#25104;&#25928;&#12290;&#25105;&#20204;&#40723;&#21169;&#24744;&#36827;&#19968;&#27493;&#25506;&#32034;Symfony&#30340;Validator&#32452;&#20214;&#65292;&#24182;&#25506;&#32034;&#20854;&#20869;&#32622;&#32422;&#26463;&#30340;&#20840;&#37096;&#33539;&#22260;&#21450;&#20854;&#33258;&#23450;&#20041;&#39564;&#35777;&#22120;&#30340;&#24378;&#22823;&#21151;&#33021;&#65292;&#20197;&#28385;&#36275;&#24744;&#30340;&#29305;&#23450;&#19994;&#21153;&#35268;&#21017;&#21644;&#38656;&#27714;&#12290;<\/p><\/body>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n<\/div><div class=\"wp-block-columns p-0 border is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-columns px-4 py-3 border-bottom has-background is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\" style=\"background:linear-gradient(243deg,rgb(238,238,238) 0%,rgba(58,166,242,0.15) 100%)\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-6c531013 wp-block-group-is-layout-flex\">\r\n<figure class=\"wp-block-image size-thumbnail is-resized is-style-rounded is-style-rounded--3\"><img decoding=\"async\" src=\"https:\/\/www.zhaozhao123.cn\/myitems\/images\/sites16\/2025\/06\/xygcfznnzczhsdmwydzhsmzzzmddnq-400x300.jpg\" alt=\"&#38271;&#24037;&#30721;&#22900;1523\" class=\"wp-image-2906\" style=\"object-fit:cover;width:30px;height:30px\"><\/figure>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading my-0\" style=\"font-size:clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.175), 1rem);\">&#38271;&#24037;&#30721;&#22900;1523<\/h2>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n\r\n\r\n\r\n<div class=\"wp-block-columns px-xl-5 px-4 py-xl-4 py-3 is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\r\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\r\n<p>&#22312; Symfony &#20013;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#26159;&#19968;&#31181;&#37325;&#35201;&#30340;&#23454;&#36341;&#65292;&#21487;&#20197;&#24110;&#21161;&#30830;&#20445;&#29992;&#25143;&#36755;&#20837;&#30340;&#23433;&#20840;&#24615;&#24182;&#38450;&#27490;&#28508;&#22312;&#30340; SQL &#27880;&#20837;&#21644; XSS &#25915;&#20987;&#31561;&#23433;&#20840;&#38382;&#39064;&#12290;<\/p>\n<p>&#20197;&#19979;&#26159;&#22312; Symfony &#20013;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#30340;&#22522;&#26412;&#27493;&#39588;&#65306;<\/p>\n<ol>\n<li>\n<p>&#23433;&#35013;&#20381;&#36182;&#65306;&#39318;&#20808;&#65292;&#20320;&#38656;&#35201;&#23433;&#35013; Symfony &#30340; CSRF &#21644; XSRF (X-XSS-Protection) &#20445;&#25252;&#27169;&#22359;&#12290;&#20320;&#21487;&#20197;&#36890;&#36807; composer &#23433;&#35013;&#36825;&#20123;&#27169;&#22359;&#65306;<\/p>\n<pre><code>composer require symfony\/security-csrf\ncomposer require symfony\/xsrf<\/code><\/pre>\n<\/li>\n<li>\n<p>&#37197;&#32622;&#23433;&#20840;&#31574;&#30053;&#65306;&#21019;&#24314;&#19968;&#20010;&#26032;&#30340;&#23433;&#20840;&#31574;&#30053;&#65292;&#20363;&#22914; <code>UserSecurityPolicy<\/code>&#65292;&#24182;&#22312;&#20854;&#20013;&#37197;&#32622;&#30456;&#24212;&#30340;&#35268;&#21017;&#12290;&#36825;&#36890;&#24120;&#21253;&#25324;&#23545;&#29305;&#23450;&#25805;&#20316;&#65288;&#22914;&#30331;&#24405;&#12289;&#27880;&#20876;&#65289;&#36827;&#34892;&#36523;&#20221;&#39564;&#35777;&#12290;<\/p>\n<\/li>\n<li>\n<p>&#20351;&#29992;&#23433;&#20840;&#32422;&#26463;&#65306;&#23558;&#23433;&#20840;&#32422;&#26463;&#28155;&#21152;&#21040;&#25511;&#21046;&#22120;&#26041;&#27861;&#19978;&#12290;&#20363;&#22914;&#65292;&#22914;&#26524;&#20320;&#27491;&#22312;&#22788;&#29702; POST &#35831;&#27714;&#65292;&#21487;&#20197;&#20351;&#29992;&#20197;&#19979;&#32422;&#26463;&#65306;<\/p>\n<pre><code class=\"language-php\">public function register(Request $request): Response {\n   \/\/ ...&#24744;&#30340;&#20195;&#30721;...\n   if ($this-&gt;validator-&gt;validate($data)) {\n       $this-&gt;em-&gt;persist($user);\n       $this-&gt;em-&gt;flush();\n       return new RedirectResponse(\"\/login\");\n   }\n}<\/code><\/pre>\n<\/li>\n<li>\n<p>&#20351;&#29992; Form Validator: &#22312;&#25511;&#21046;&#22120;&#20013;&#20351;&#29992; Form Validator &#26469;&#39564;&#35777;&#34920;&#21333;&#20013;&#30340;&#25968;&#25454;&#12290;Form Validator &#21487;&#20197;&#24110;&#21161;&#20320;&#39564;&#35777;&#34920;&#21333;&#23383;&#27573;&#26159;&#21542;&#31526;&#21512;&#39044;&#26399;&#30340;&#25968;&#25454;&#31867;&#22411;&#21644;&#26684;&#24335;&#12290;<\/p>\n<\/li>\n<li>\n<p>&#20351;&#29992; DataValidator: &#22914;&#26524;&#38656;&#35201;&#39564;&#35777;&#23454;&#20307;&#23545;&#35937;&#65292;&#35831;&#32771;&#34385;&#20351;&#29992; DataValidator&#12290;DataValidator &#25552;&#20379;&#20102;&#26356;&#22810;&#30340;&#25511;&#21046;&#26435;&#65292;&#24182;&#20801;&#35768;&#20320;&#23450;&#20041;&#26356;&#22797;&#26434;&#30340;&#39564;&#35777;&#35268;&#21017;&#12290;<\/p>\n<\/li>\n<li>\n<p>&#20351;&#29992; FormInterface: &#22914;&#26524;&#20320;&#24819;&#35201;&#33258;&#23450;&#20041;&#34920;&#21333;&#39564;&#35777;&#36923;&#36753;&#65292;&#21487;&#20197;&#20351;&#29992; FormInterface &#31867;&#26469;&#23454;&#29616;&#33258;&#23450;&#20041;&#39564;&#35777;&#22120;&#12290;<\/p>\n<\/li>\n<li>\n<p>&#26816;&#26597;&#36755;&#20986;&#65306;&#26368;&#21518;&#65292;&#30830;&#20445;&#36820;&#22238;&#32473;&#29992;&#25143;&#30340;&#20219;&#20309;&#20449;&#24687;&#37117;&#32463;&#36807;&#20102;&#36866;&#24403;&#30340;&#39564;&#35777;&#12290;&#22914;&#26524;&#39564;&#35777;&#22833;&#36133;&#65292;&#24212;&#35813;&#36820;&#22238;&#38169;&#35823;&#28040;&#24687;&#12290;<\/p>\n<\/li>\n<\/ol>\n<p>&#19979;&#38754;&#26159;&#19968;&#20010;&#31616;&#21333;&#30340;&#31034;&#20363;&#65292;&#23637;&#31034;&#20102;&#22914;&#20309;&#22312;&#19968;&#20010;&#25511;&#21046;&#22120;&#26041;&#27861;&#20013;&#20351;&#29992; Form Validator &#36827;&#34892;&#22522;&#26412;&#30340;&#39564;&#35777;&#65306;<\/p>\n<pre><code class=\"language-php\">use SymfonyComponentHttpFoundationRequest;\nuse SymfonyComponentValidatorConstraintViolationListInterface;\n\nclass UserController extends AbstractController\n{\n    private $formValidator;\n\n    public function __construct(FormValidator $formValidator)\n    {\n        $this-&gt;formValidator = $formValidator;\n    }\n\n    public function showAction()\n    {\n        $email = $this-&gt;get('request')-&gt;request-&gt;get('email');\n        $password = $this-&gt;get('request')-&gt;request-&gt;get('password');\n\n        \/\/ &#21019;&#24314; FormValidator &#23454;&#20363;\n        $form = $this-&gt;createForm(UserType::class);\n\n        \/\/ &#39564;&#35777;&#34920;&#21333;&#25968;&#25454;\n        $violations = $this-&gt;formValidator-&gt;validate($form, [\n            'email' =&gt; ['required'],\n            'password' =&gt; ['required', 'min_length:8']\n        ]);\n\n        \/\/ &#22914;&#26524;&#26377;&#39564;&#35777;&#22833;&#36133;&#65292;&#21017;&#36820;&#22238;&#38169;&#35823;&#28040;&#24687;\n        if ($violations-&gt;count()) {\n            $errors = [];\n            foreach ($violations as $violation) {\n                $errors[] = $violation-&gt;getMessage();\n            }\n            throw new BadRequestHttpException(sprintf('Invalid email or password (%s)', implode(', ', $errors)));\n        }\n\n        \/\/ &#22914;&#26524;&#39564;&#35777;&#25104;&#21151;&#65292;&#32487;&#32493;&#25191;&#34892;&#20854;&#20182;&#36923;&#36753;\n\n        return new Response('Hello World!');\n    }\n}<\/code><\/pre>\n<p>&#22312;&#36825;&#20010;&#20363;&#23376;&#20013;&#65292;&#25105;&#20204;&#21019;&#24314;&#20102;&#19968;&#20010;&#21517;&#20026; <code>UserType<\/code> &#30340;&#33258;&#23450;&#20041;&#31867;&#22411;&#65292;&#24182;&#20026;&#34920;&#21333;&#23383;&#27573;&#35774;&#32622;&#20102;&#19968;&#20123;&#32422;&#26463;&#12290;&#28982;&#21518;&#65292;&#25105;&#20204;&#22312; <code>showAction<\/code> &#26041;&#27861;&#20013;&#35843;&#29992; <code>createForm()<\/code> &#26041;&#27861;&#21019;&#24314;&#19968;&#20010; FormValidator &#23454;&#20363;&#65292;&#24182;&#20256;&#20837;&#19968;&#20123;&#39564;&#35777;&#35268;&#21017;&#12290;&#26368;&#21518;&#65292;&#25105;&#20204;&#26816;&#26597;&#39564;&#35777;&#32467;&#26524;&#65292;&#24182;&#26681;&#25454;&#39564;&#35777;&#24773;&#20917;&#20915;&#23450;&#26159;&#21542;&#32487;&#32493;&#25191;&#34892;&#20854;&#20182;&#36923;&#36753;&#12290;<\/p>\r\n<\/div>\r\n<\/div>\r\n<\/div>\r\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Bug&#32534;&#35793;&#29422; &#22312; Symfony &#20013;&#65292;&#39564;&#35777;&#35831;&#27714;&#25968;&#25454;&#26159;&#30830;&#20445;&#24212;&#29992;&#31243;&#038;#2..<\/p>\n","protected":false},"author":1,"featured_media":0,"menu_order":0,"template":"","meta":{"_acf_changed":false},"tags":[],"my1js2nav":[45],"tuisongtax":[],"class_list":["post-1060","my1js","type-my1js","status-publish","hentry","my1js2nav-symfony"],"acf":{"qian_art_seotitle":"","qian_art_seotitle_source":{"label":"SEO\u6807\u9898","type":"text","formatted_value":""},"qian_art_seokws":"","qian_art_seokws_source":{"label":"SEO\u5173\u952e\u8bcd","type":"text","formatted_value":""},"qian_art_stzhong":"","qian_art_stzhong_source":{"label":"\u4e2d | \u77ed\u6807\u9898","type":"text","formatted_value":""}},"_links":{"self":[{"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/my1js\/1060","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/my1js"}],"about":[{"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/types\/my1js"}],"author":[{"embeddable":true,"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/users\/1"}],"wp:attachment":[{"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/media?parent=1060"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/tags?post=1060"},{"taxonomy":"my1js2nav","embeddable":true,"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/my1js2nav?post=1060"},{"taxonomy":"tuisongtax","embeddable":true,"href":"https:\/\/www.zhaozhao123.cn\/php\/wp-json\/wp\/v2\/tuisongtax?post=1060"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}