doxygen不记录一个PHP类

发布于 2025-02-07 05:05:06 字数 13653 浏览 1 评论 0原文

我有一个小的Symfony项目,我想用Doxygen记录。应该包括两个.php文件。一个记录在记录下,另一个不是,我无法弄清楚为什么会这样。

文件夹结构是:

project
└--src
   |--Controller
   |  └--FormController.php
   └--Model
      └--Inquiry.php

doxygen正在读取和解析两个文件...

阅读/formandler/src/controller/formcontroller.php ...

解析文件/form handler/src/controller/formcontroller.php ...

阅读/formandler/src/model/inquiry.php ...

解析文件/formhandler/src/model/inquiry.php ...

...但是只有文档form controller.php,而不是exigry> exigry>

为复合应用程序生成文档:: Controller :: FormController ...

由于某些原因,doxygen似乎并未识别exigry> exigry.php是类。 我尝试的是:

  1. 从可能冒犯doxygen的docstrings中删除了装饰师。
  2. 启用/禁用的DocString的格式
  3. 启用/禁用了各种Doxyfile选项

FormController.php:

<?php

declare(strict_types=1);

namespace App\Controller;

use App\Model\Inquiry;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\RateLimiter\RateLimiterFactory;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * Handles incoming requests.
 */
class FormController extends AbstractController
{
    /**
     * Handles POST requests.
     *
     * @return Response contains JSON object with 'message' value
     */
    #[Route('/', methods: ['POST'])]
    public function handleRequest(
        HttpClientInterface $client,
        Inquiry $inquiry,
        LoggerInterface $logger,
        RateLimiterFactory $formApiLimiter,
        Request $request,
    ): Response {
        $logger->debug('Received a POST request');

        // set up a rate limiter by IP
        // rules are defined in /config/packages/rate-limiter.yaml
        $limiter = $formApiLimiter->create($request->getClientIp());

        $limit = $limiter->consume();

        // configure headers exposing rate limit info
        $headers = [
            'Content-Type' => 'application/json',
            'X-RateLimit-Remaining' => $limit->getRemainingTokens(),
            'X-RateLimit-Retry-After' => $limit->getRetryAfter()->getTimestamp(),
            'X-RateLimit-Limit' => $limit->getLimit(),
        ];

        if (false === $limit->isAccepted()) {
            return new Response(
                content: json_encode(['message' => null]),
                status: Response::HTTP_TOO_MANY_REQUESTS,
                headers: $headers
            );
        }

        // make sure all required fields are included in request and not empty
        $requiredFields = ['subject', 'message', 'consent', 'h-captcha-response'];
        $providedFields = $request->request->keys();

        foreach ($requiredFields as $field) {
            if (!in_array($field, $providedFields)) {
                return new Response(
                    content: json_encode(['message' => "Pflichtfeld '".$field."' fehlt."]),
                    status: Response::HTTP_BAD_REQUEST,
                    headers: $headers
                );
            } elseif ('' == filter_var($request->request->get($field), FILTER_SANITIZE_SPECIAL_CHARS)) {
                return new Response(
                    content: json_encode(['message' => "Pflichtfeld '".$field."' darf nicht leer sein."]),
                    status: Response::HTTP_BAD_REQUEST,
                    headers: $headers
                );
            }
        }

        // verify captcha success
        $captcha = filter_var($request->request->get('h-captcha-response'), FILTER_SANITIZE_SPECIAL_CHARS);
        $data = [
            'secret' => $this->getParameter('app.captcha.secret'),
            'response' => $captcha,
        ];

        try {
            $hCaptchaResponse = $client->request(
                method: 'POST',
                url: 'https://hcaptcha.com/siteverify',
                options: [
                    'body' => $data,
                ],
            );

            $hCaptchaResponseJson = json_decode($hCaptchaResponse->getContent(), true);

            if (!$hCaptchaResponseJson['success']) {
                return new Response(
                    content: json_encode(['message' => 'Captcha fehlgeschlagen']),
                    status: Response::HTTP_BAD_REQUEST,
                    headers: $headers
                );
            }
            // exceptions on the side of hCaptcha are logged, but the request is processed anyway
        } catch (TransportExceptionInterface $e) {
            $logger->debug('Could not reach hCaptcha verification server: '.$e);
        } catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $e) {
            $logger->debug('Error when verifying hCaptcha response: '.$e);
        }

        // get values from request data
        $name = filter_var($request->request->get('name'), FILTER_SANITIZE_SPECIAL_CHARS);
        $email = filter_var($request->request->get('email'), FILTER_SANITIZE_EMAIL);
        $phone = filter_var($request->request->get('phone'), FILTER_SANITIZE_SPECIAL_CHARS);
        $subject = filter_var($request->request->get('subject'), FILTER_SANITIZE_SPECIAL_CHARS);
        $message = filter_var($request->request->get('message'), FILTER_SANITIZE_SPECIAL_CHARS);
        $consent = filter_var($request->request->get('consent'), FILTER_SANITIZE_SPECIAL_CHARS);
        // translate into a boolean (else the string 'false' will be evaluated as true)
        $consent = filter_var($consent, FILTER_VALIDATE_BOOLEAN);

        // populate Inquiry with request data
        $inquiry->createInquiry(
            subject: $subject,
            message: $message,
            consent: $consent,
            name: $name,
            email: $email,
            phone: $phone,
        );

        // validate Inquiry
        $validationResult = $inquiry->validateInquiry();
        // if Inquiry is invalid, return validation violation message(s)
        if (count($validationResult) > 0) {
            $logger->debug($validationResult);

            // assemble list of error messages
            $validationMessages = [];
            foreach ($validationResult as $result) {
                $validationMessages += [$result->getPropertyPath() => $result->getMessage()];
            }

            return new Response(
                content: json_encode([
                    'message' => 'Anfrage enthält ungültige Werte',
                    'errors' => $validationMessages,
                ]),
                status: Response::HTTP_BAD_REQUEST,
                headers: $headers
            );
        }
        // send mail to office
        $emailResult = $inquiry->sendOfficeEmail();
        $logger->debug(implode(' ,', $emailResult));
        $message = 'Die Anfrage war erfolgreich';
        if (!$emailResult['success']) {
            $message = 'Die Anfrage war nicht erfolgreich.';
        }

        // TODO compile email to user

        $data = [
            'message' => $message,
            'officeEmail' => $emailResult,
            'confirmationEmail' => true,
        ];

        return new Response(
            content: json_encode($data),
            status: Response::HTTP_OK,
            headers: $headers
        );
    }

    /**
     * Handles disallowed request methods.
     *
     * @return Response contains JSON object with 'message' value
     */
    #[Route('/', condition: "context.getMethod() not in ['POST']")]
    public function handleDisallowedMethods(LoggerInterface $logger): Response
    {
        $logger->debug('Received a request with a disallowed method.');

        return new Response(
            content: json_encode(['message' => 'Only POST requests allowed']),
            status: Response::HTTP_METHOD_NOT_ALLOWED
        );
    }
}

exigriry.php:

<?php

declare(strict_types=1);

namespace App\Model;

use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

/**
 * Represents an inquiry received from the front end.
 *
 * The required fields 'subject', 'message', and
 * 'consent' must be provided to the constructor.
 */
class Inquiry
{
    private string $name;
    private string $email;
    private string $phone;
    private string $subject;
    private string $message;
    private bool $consent;

    private bool $validated = false;

    /**
     * @param LoggerInterface    $logger
     * @param MailerInterface    $mailer
     * @param array              $officeRecipients configured in services.yaml
     * @param ValidatorInterface $validator
     */
    public function __construct(
        private readonly LoggerInterface $logger,
        private readonly MailerInterface $mailer,
        private readonly array $officeRecipients,
        private readonly ValidatorInterface $validator,
    ) {
    }

    /**
     * Populates an inquiry with data.
     *
     * 'subject', 'message', and 'consent are required,
     * all other values are optional.
     *
     * Sets 'validated' to false, in case createInquiry()
     * is called multiple times.
     */
    public function createInquiry(
        string $subject,
        string $message,
        bool $consent,
        string $name = '',
        string $email = '',
        string $phone = '',
    ): void {
        $this->subject = $subject;
        $this->message = $message;
        $this->consent = $consent;
        $this->name = $name;
        $this->email = $email;
        $this->phone = $phone;
        $this->validated = false;
    }

    /**
     * Validates the inquiry.
     *
     * If successful, sets 'validated' to true
     *
     * @return ConstraintViolationListInterface if valid: empty
     *                                          if not valid: list of validation violation messages
     */
    public function validateInquiry(): ConstraintViolationListInterface
    {
        $validationResult = $this->validator->validate($this);
        if (0 == count($validationResult)) {
            $this->validated = true;
        }

        return $validationResult;
    }

    /**
     * Sends an email with the customer inquiry data to the office.
     *
     * @return array containing 'success' boolean and 'message' string
     */
    public function sendOfficeEmail(): array
    {
        if (!$this->validated) {
            return [
                'success' => false,
                'message' => 'Inquiry has not been validated. Use Inquiry->validate() first',
            ];
        }

        // convert 'consent' and empty values in to human-readable format
        $plainTextConsent = $this->consent ? 'Ja' : 'Nein';
        $plainTextName = $this->name ?: 'Keine Angabe';
        $plainTextEmail = $this->email ?: 'Keine Angabe';
        $plainTextPhone = $this->phone ?: 'Keine Angabe';

        $emailBody = <<<END
            Das Kontaktformular hat eine Anfrage erhalten.
            
                Betreff: $this->subject
            
                Nachricht: $this->message
            
                Einwilligung: $plainTextConsent
            
                Name: $plainTextName
            
                Email: $plainTextEmail
            
                Telefon: $plainTextPhone
            END;

        $email = (new Email())
            ->to(...$this->officeRecipients)
            ->subject('Anfrage vom Kontaktformular')
            ->text($emailBody);

        try {
            $this->mailer->send($email);
            $this->logger->debug('Email sent');

            return [
                'success' => true,
                'message' => 'Email wurde gesendet',
            ];
        } catch (TransportExceptionInterface $e) {
            $this->logger->debug('Error sending email: '.$e);

            return [
                'success' => false,
                'message' => 'Email konnte nicht gesendet werden: '.$e,
                ];
        }
    }

    /**
     * @codeCoverageIgnore
     */
    public function sendConfirmationEmail(): string
    {
        return '';
    }

    /**
     * Checks whether Inquiry has been validated.
     */
    public function isValidated(): bool
    {
        return $this->validated;
    }
}

doxyfile(根据 @albert的评论编辑):

# Difference with default Doxyfile 1.9.3 (c0b9eafbfb53286ce31e75e2b6c976ee4d345473)
PROJECT_NAME           = "Form handler"
PROJECT_BRIEF          = "Stand-alone Symfony backend to handle contact forms."
OUTPUT_DIRECTORY       = ./doc/
INPUT                  = ./src/ \
                         README.md
RECURSIVE              = YES
EXCLUDE                = ./src/Kernel.php
USE_MDFILE_AS_MAINPAGE = README.md
GENERATE_LATEX         = NO

I have a small Symfony project I want to document with doxygen. There are two .php files that should be included. One is documented, the other is not, and I cannot figure out why that may be.

Folder structure is:

project
└--src
   |--Controller
   |  └--FormController.php
   └--Model
      └--Inquiry.php

Doxygen is reading and parsing both files...

Reading /form-handler/src/Controller/FormController.php...

Parsing file /form-handler/src/Controller/FormController.php...

Reading /form-handler/src/Model/Inquiry.php...

Parsing file /form-handler/src/Model/Inquiry.php...

...but only documents FormController.php, not Inquiry.php:

Generating docs for compound App::Controller::FormController...

For some reason doxygen does not seem to recognizeInquiry.php as a class.
What I have tried:

  1. Removed decorators from docstrings that might offend doxygen.
  2. Checked format of docstrings
  3. Enabled/disabled various Doxyfile options

FormController.php:

<?php

declare(strict_types=1);

namespace App\Controller;

use App\Model\Inquiry;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\RateLimiter\RateLimiterFactory;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

/**
 * Handles incoming requests.
 */
class FormController extends AbstractController
{
    /**
     * Handles POST requests.
     *
     * @return Response contains JSON object with 'message' value
     */
    #[Route('/', methods: ['POST'])]
    public function handleRequest(
        HttpClientInterface $client,
        Inquiry $inquiry,
        LoggerInterface $logger,
        RateLimiterFactory $formApiLimiter,
        Request $request,
    ): Response {
        $logger->debug('Received a POST request');

        // set up a rate limiter by IP
        // rules are defined in /config/packages/rate-limiter.yaml
        $limiter = $formApiLimiter->create($request->getClientIp());

        $limit = $limiter->consume();

        // configure headers exposing rate limit info
        $headers = [
            'Content-Type' => 'application/json',
            'X-RateLimit-Remaining' => $limit->getRemainingTokens(),
            'X-RateLimit-Retry-After' => $limit->getRetryAfter()->getTimestamp(),
            'X-RateLimit-Limit' => $limit->getLimit(),
        ];

        if (false === $limit->isAccepted()) {
            return new Response(
                content: json_encode(['message' => null]),
                status: Response::HTTP_TOO_MANY_REQUESTS,
                headers: $headers
            );
        }

        // make sure all required fields are included in request and not empty
        $requiredFields = ['subject', 'message', 'consent', 'h-captcha-response'];
        $providedFields = $request->request->keys();

        foreach ($requiredFields as $field) {
            if (!in_array($field, $providedFields)) {
                return new Response(
                    content: json_encode(['message' => "Pflichtfeld '".$field."' fehlt."]),
                    status: Response::HTTP_BAD_REQUEST,
                    headers: $headers
                );
            } elseif ('' == filter_var($request->request->get($field), FILTER_SANITIZE_SPECIAL_CHARS)) {
                return new Response(
                    content: json_encode(['message' => "Pflichtfeld '".$field."' darf nicht leer sein."]),
                    status: Response::HTTP_BAD_REQUEST,
                    headers: $headers
                );
            }
        }

        // verify captcha success
        $captcha = filter_var($request->request->get('h-captcha-response'), FILTER_SANITIZE_SPECIAL_CHARS);
        $data = [
            'secret' => $this->getParameter('app.captcha.secret'),
            'response' => $captcha,
        ];

        try {
            $hCaptchaResponse = $client->request(
                method: 'POST',
                url: 'https://hcaptcha.com/siteverify',
                options: [
                    'body' => $data,
                ],
            );

            $hCaptchaResponseJson = json_decode($hCaptchaResponse->getContent(), true);

            if (!$hCaptchaResponseJson['success']) {
                return new Response(
                    content: json_encode(['message' => 'Captcha fehlgeschlagen']),
                    status: Response::HTTP_BAD_REQUEST,
                    headers: $headers
                );
            }
            // exceptions on the side of hCaptcha are logged, but the request is processed anyway
        } catch (TransportExceptionInterface $e) {
            $logger->debug('Could not reach hCaptcha verification server: '.$e);
        } catch (ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $e) {
            $logger->debug('Error when verifying hCaptcha response: '.$e);
        }

        // get values from request data
        $name = filter_var($request->request->get('name'), FILTER_SANITIZE_SPECIAL_CHARS);
        $email = filter_var($request->request->get('email'), FILTER_SANITIZE_EMAIL);
        $phone = filter_var($request->request->get('phone'), FILTER_SANITIZE_SPECIAL_CHARS);
        $subject = filter_var($request->request->get('subject'), FILTER_SANITIZE_SPECIAL_CHARS);
        $message = filter_var($request->request->get('message'), FILTER_SANITIZE_SPECIAL_CHARS);
        $consent = filter_var($request->request->get('consent'), FILTER_SANITIZE_SPECIAL_CHARS);
        // translate into a boolean (else the string 'false' will be evaluated as true)
        $consent = filter_var($consent, FILTER_VALIDATE_BOOLEAN);

        // populate Inquiry with request data
        $inquiry->createInquiry(
            subject: $subject,
            message: $message,
            consent: $consent,
            name: $name,
            email: $email,
            phone: $phone,
        );

        // validate Inquiry
        $validationResult = $inquiry->validateInquiry();
        // if Inquiry is invalid, return validation violation message(s)
        if (count($validationResult) > 0) {
            $logger->debug($validationResult);

            // assemble list of error messages
            $validationMessages = [];
            foreach ($validationResult as $result) {
                $validationMessages += [$result->getPropertyPath() => $result->getMessage()];
            }

            return new Response(
                content: json_encode([
                    'message' => 'Anfrage enthält ungültige Werte',
                    'errors' => $validationMessages,
                ]),
                status: Response::HTTP_BAD_REQUEST,
                headers: $headers
            );
        }
        // send mail to office
        $emailResult = $inquiry->sendOfficeEmail();
        $logger->debug(implode(' ,', $emailResult));
        $message = 'Die Anfrage war erfolgreich';
        if (!$emailResult['success']) {
            $message = 'Die Anfrage war nicht erfolgreich.';
        }

        // TODO compile email to user

        $data = [
            'message' => $message,
            'officeEmail' => $emailResult,
            'confirmationEmail' => true,
        ];

        return new Response(
            content: json_encode($data),
            status: Response::HTTP_OK,
            headers: $headers
        );
    }

    /**
     * Handles disallowed request methods.
     *
     * @return Response contains JSON object with 'message' value
     */
    #[Route('/', condition: "context.getMethod() not in ['POST']")]
    public function handleDisallowedMethods(LoggerInterface $logger): Response
    {
        $logger->debug('Received a request with a disallowed method.');

        return new Response(
            content: json_encode(['message' => 'Only POST requests allowed']),
            status: Response::HTTP_METHOD_NOT_ALLOWED
        );
    }
}

Inquiry.php:

<?php

declare(strict_types=1);

namespace App\Model;

use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;

/**
 * Represents an inquiry received from the front end.
 *
 * The required fields 'subject', 'message', and
 * 'consent' must be provided to the constructor.
 */
class Inquiry
{
    private string $name;
    private string $email;
    private string $phone;
    private string $subject;
    private string $message;
    private bool $consent;

    private bool $validated = false;

    /**
     * @param LoggerInterface    $logger
     * @param MailerInterface    $mailer
     * @param array              $officeRecipients configured in services.yaml
     * @param ValidatorInterface $validator
     */
    public function __construct(
        private readonly LoggerInterface $logger,
        private readonly MailerInterface $mailer,
        private readonly array $officeRecipients,
        private readonly ValidatorInterface $validator,
    ) {
    }

    /**
     * Populates an inquiry with data.
     *
     * 'subject', 'message', and 'consent are required,
     * all other values are optional.
     *
     * Sets 'validated' to false, in case createInquiry()
     * is called multiple times.
     */
    public function createInquiry(
        string $subject,
        string $message,
        bool $consent,
        string $name = '',
        string $email = '',
        string $phone = '',
    ): void {
        $this->subject = $subject;
        $this->message = $message;
        $this->consent = $consent;
        $this->name = $name;
        $this->email = $email;
        $this->phone = $phone;
        $this->validated = false;
    }

    /**
     * Validates the inquiry.
     *
     * If successful, sets 'validated' to true
     *
     * @return ConstraintViolationListInterface if valid: empty
     *                                          if not valid: list of validation violation messages
     */
    public function validateInquiry(): ConstraintViolationListInterface
    {
        $validationResult = $this->validator->validate($this);
        if (0 == count($validationResult)) {
            $this->validated = true;
        }

        return $validationResult;
    }

    /**
     * Sends an email with the customer inquiry data to the office.
     *
     * @return array containing 'success' boolean and 'message' string
     */
    public function sendOfficeEmail(): array
    {
        if (!$this->validated) {
            return [
                'success' => false,
                'message' => 'Inquiry has not been validated. Use Inquiry->validate() first',
            ];
        }

        // convert 'consent' and empty values in to human-readable format
        $plainTextConsent = $this->consent ? 'Ja' : 'Nein';
        $plainTextName = $this->name ?: 'Keine Angabe';
        $plainTextEmail = $this->email ?: 'Keine Angabe';
        $plainTextPhone = $this->phone ?: 'Keine Angabe';

        $emailBody = <<<END
            Das Kontaktformular hat eine Anfrage erhalten.
            
                Betreff: $this->subject
            
                Nachricht: $this->message
            
                Einwilligung: $plainTextConsent
            
                Name: $plainTextName
            
                Email: $plainTextEmail
            
                Telefon: $plainTextPhone
            END;

        $email = (new Email())
            ->to(...$this->officeRecipients)
            ->subject('Anfrage vom Kontaktformular')
            ->text($emailBody);

        try {
            $this->mailer->send($email);
            $this->logger->debug('Email sent');

            return [
                'success' => true,
                'message' => 'Email wurde gesendet',
            ];
        } catch (TransportExceptionInterface $e) {
            $this->logger->debug('Error sending email: '.$e);

            return [
                'success' => false,
                'message' => 'Email konnte nicht gesendet werden: '.$e,
                ];
        }
    }

    /**
     * @codeCoverageIgnore
     */
    public function sendConfirmationEmail(): string
    {
        return '';
    }

    /**
     * Checks whether Inquiry has been validated.
     */
    public function isValidated(): bool
    {
        return $this->validated;
    }
}

Doxyfile (EDITED as per @albert's comment):

# Difference with default Doxyfile 1.9.3 (c0b9eafbfb53286ce31e75e2b6c976ee4d345473)
PROJECT_NAME           = "Form handler"
PROJECT_BRIEF          = "Stand-alone Symfony backend to handle contact forms."
OUTPUT_DIRECTORY       = ./doc/
INPUT                  = ./src/ \
                         README.md
RECURSIVE              = YES
EXCLUDE                = ./src/Kernel.php
USE_MDFILE_AS_MAINPAGE = README.md
GENERATE_LATEX         = NO

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

自我难过 2025-02-14 05:05:06

从PHP版本7.3.0开始,此处文档的语法略有更改,请参见 https://www.php.net/manual/manual/en/language.types.string.php#language.types.string.string.syntax.string.syntax.heredoc

可以通过空间或选项卡将关闭标识符缩进,在这种情况下,缩进将从DOC字符串中的所有行中剥离。在PHP 7.3.0之前,关闭标识符必须从行的第一列开始。

现在在拟议的补丁中纠正了这一点,请拉请求: https://github.com/doxygen /doxygen/pull/9398

orkarounds

  • 将此文档的最终标识符放在行的开头,
  • 放置一个doxygen条件块/** \ cond ///////// / em> * \ endcond */在此处的文档周围。

As of PHP version 7.3.0 the syntax of the here document changed slightly, see https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc

The closing identifier may be indented by space or tab, in which case the indentation will be stripped from all lines in the doc string. Prior to PHP 7.3.0, the closing identifier must begin in the first column of the line.

This has now been corrected in the proposed patch, pull request: https://github.com/doxygen/doxygen/pull/9398

Workarounds:

  • place the end identifier of the here document at the beginning of the line
  • place a doxygen conditional block /** \cond / / /* \endcond */ around the here document.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文