>  기사  >  PHP 프레임워크  >  TP에 ThinkWechat.php를 도입하고 로그를 인쇄하는 방법에 대한 자세한 설명

TP에 ThinkWechat.php를 도입하고 로그를 인쇄하는 방법에 대한 자세한 설명

藏色散人
藏色散人앞으로
2021-08-09 09:47:072130검색

다음 튜토리얼 칼럼인 thinkphp Framework에서는 ThinkWechat.php를 TP에 도입하는 방법과 로그를 로그 파일로 출력하는 방법을 소개하겠습니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다!

Thinkphp6 기반 위챗 공용 계정용 대화형 메시지 개발

thinkPHP 실습을 본 후 github에서 책에 있는 코드를 다운로드하고 위챗 공용 계정용으로 개발된 프로그램을 실행할 준비를 했습니다.
하지만 책은 ThinkPHP3.2.3을 사용하고 있고, 최신 버전이 이미 6.0.X이기 때문에 어차피 ThinkPHP가 익숙하지 않아서 최신 버전을 다운받아서 사용했습니다. 버전이 다르기 때문에 프로그램 실행에 문제가 있을 것으로 예상했습니다. 제 생각에는 문제를 하나씩 해결해야 한다는 것 같아요. 예상외로 많은 어려움을 겪었고, 프로그램을 실행하는데 이틀이 걸렸습니다. 마지막으로 프레임워크의 코드를 약간 변경했습니다.

더 이상 고민하지 않고 제가 겪은 어려움을 순서대로 나열하겠습니다.

TP에서 ThinkWechat.php를 소개하는 방법

책에서 ThinkWechat.php는 /Application/Home/Library에 위치합니다. 하지만 TP6에는 더 이상 애플리케이션이 없으므로 /app 아래에 새 라이브러리 디렉터리를 만들고 그 안에 파일을 넣었습니다.

이 파일을 Index.php에 추가해야 합니다

use applibraryThinkWechat;use applibraryThinkWechat;

在ThinkWechat.php文件中添加namespace

namespace applibrary;

Class 'applibrarySimpleXMLElement' not found

一开始,百度说是要在环境上安装php7-xml. 我的macmini需要用brew来安装,很久没用brew,brew update慢死了,按照百度的帖子,替换了阿里云的链接。
结果还是不行。弄brew弄了几个小时。后来不知道怎么发现,原来tp6里面用了namespace,所以在使用SimpleXMLElement的时候,要在文件开头写如下语句
use SimpleXMLElement;

TP6怎么打印日志到日志文件

因为是和微信公众号进行交互,我不知道有什么办法方便调试,试过了微信提供的接口调试工具,但是也仅仅能够检查参数设置是否正确。于是我用了最笨的打印日志的方法。
要打印日志需要在TP6中做以下设置:

在config/log.php 中

1.设置日志记录级别

'level'        => ['emergency'],

我调试时几乎把所有的level值都写到这里了。

1.设置日志保存目录

'path'       => App()->getRuntimePath() .'/log',

2.然后在程序中用下面的语句实时写入日志文件

Log::write('index _get session id before set ID '. Session::getId(), 'notice');

关注测试公众号后,输入999,可以收到正常回复。输入1 程序则退出

这个问题卡了我大半天!!

一开始,我以为是返回给微信平台的response 有问题,因为我在ThinkWechat.php中打印了很多日志,发现只要我输入除999以外的信息,data2xml方法总是不能完全执行,日志在
$node = dom_import_simplexml($child);之后就无法打印。

我一直以为是$node->appendChild($node->ownerDocument->createCDATASection($value));
这句代码执行有问题。
因此还从《微信公众平台开发》一书中找到通过设置xml模板中,用sprintf方法替换模板中的变量来生成response的xml。

这样做的结果是,我能在日志中看到response xml 成功生成,但是输入1仍然没有得到我期望的回复,应该是没有任何回复,显示“该公众号暂时无法提供服务,请稍后再试”,并且才程序也是立即退出了。

后来我发现,自己随便写的程序,比如公众号每次都回复用户输入的信息,像应声桶那样,就没有问题,程序也不退出。我突然想着会不会是和session有关?因为源代码中用到了session来实现用户的注册和登录。
我看了下TP6的开发文档,果然,里面写到session默认是没初始化的。这里我有点欲哭无泪。

按照文档说明,我打开了session:

1.在app/middleware.php 中去掉thinkmiddlewareSessionInit::class

ThinkWechat.php 파일에 네임스페이스 추가

namespace applibrary;

'applibrarySimpleXMLElement' 클래스를 찾을 수 없습니다.

처음에 Baidu는 환경에 php7-xml을 설치해야 한다고 말했습니다. 저는 Brew 업데이트를 오랫동안 사용하지 않았습니다. 매우 느립니다. Baidu의 게시물에 따르면 Alibaba Cloud로 링크를 교체했습니다. 🎜결과가 여전히 작동하지 않습니다. 나는 그것을 몇 시간 동안 끓였습니다. TP6에서 네임스페이스가 사용된다는 건 나중에 어떻게 알았는지 모르겠는데 SimpleXMLElement를 사용할 때는 파일 시작 부분에 다음 문장을 써야 한다🎜use SimpleXMLElement;🎜🎜🎜어떻게 TP6에서 로그를 로그 파일로 출력하려면🎜🎜 🎜위챗 공식 계정으로 소통하다보니 어떻게 디버깅을 쉽게 할 수 있을지 모르겠어서 위챗에서 제공하는 인터페이스 디버깅 도구를 사용해봤는데, 확인만 가능하더군요. 매개변수 설정이 정확했습니다. 그래서 나는 로그를 인쇄하는 가장 어리석은 방법을 사용했습니다. 🎜로그를 인쇄하려면 TP6에서 다음 설정을 지정해야 합니다. 🎜🎜config/log.php에서 🎜1 로깅 수준을 설정합니다. 🎜'level' => 🎜🎜 디버깅할 때 거의 모든 레벨 값을 여기에 썼습니다. 🎜1. 로그 저장 디렉터리를 설정합니다 🎜<code>'path' => App()->getRuntimePath() .'/log',🎜2. 그런 다음 다음 명령문을 사용하여 실시간으로 작성합니다. 프로그램 로그 파일🎜Log::write('index _get session id before set ID '. Session::getId(), 'notice');🎜🎜🎜테스트 공식 계정 팔로우 후 입장 999, 정상적인 답변을 받으실 수 있습니다. 1을 입력하면 프로그램이 종료됩니다🎜🎜🎜이 문제는 하루 종일 저를 괴롭혔습니다! ! 🎜🎜처음에는 ThinkWechat.php에 로그를 많이 출력해서 WeChat 플랫폼으로 반환되는 응답에 문제가 있는 줄 알았는데, 999 이외의 정보를 입력하는 한 data2xml 메서드를 사용할 수 없다는 사실을 발견했습니다. 완전히 실행되어야 하며 🎜 $node = dom_import_simplexml($child);에 있던 로그는 그 이후에는 인쇄할 수 없습니다. 🎜🎜저는 항상 $node->appendChild($node->ownerDocument->createCDATASection($value));라고 생각했습니다.🎜이 코드 실행에 문제가 있습니다. 🎜그래서 저는 "WeChat Public Platform Development"라는 책에서 xml 템플릿을 설정하고 sprintf 메소드를 사용하여 템플릿의 변수를 대체하여 응답 xml을 생성한다는 것을 발견했습니다. 🎜🎜결과적으로 응답 xml이 성공적으로 생성되었음을 로그에서 볼 수 있지만 1을 입력해도 예상한 응답을 받지 못했습니다. 응답이 없어야 하며 "이 공식 계정은 일시적으로 사용할 수 없습니다."라고 표시되었습니다. 서비스 제공을 위해 잠시만 기다려주세요." 다시 시도하세요"라는 메시지가 나오며 프로그램이 바로 종료되었습니다. 🎜🎜응답 버킷처럼 사용자가 매번 입력하는 정보에 응답하는 공개 계정과 같이 아무렇게나 프로그램을 작성하면 문제가 없고 프로그램이 종료되지 않는다는 것을 나중에 알게 되었습니다. 갑자기 세션과 관련이 있지 않을까 하는 생각이 들었습니다. 사용자 등록 및 로그인을 구현하기 위해 소스 코드에서 세션이 사용되기 때문입니다. 🎜TP6의 개발 문서를 보니 당연히 세션이 기본적으로 초기화되지 않는다고 나와 있습니다. 여기서 울고 싶은 기분이 든다. 🎜🎜문서 지침에 따라 세션을 열었습니다. 🎜🎜1 app/middleware.php에서 thinkmiddlewareSessionInit::class 주석을 제거했습니다. 🎜🎜2. 그리고 코드에서 session_start()를 제거하세요. TP6은 Session 클래스 메소드와 세션 헬퍼 기능을 통해서만 세션 운영을 지원하기 때문에 모든 session_xx 기능을 지원하지는 않습니다. 🎜🎜세션이 열린 후에는 프로그램이 더 이상 종료되지 않습니다. 그런데 새로운 문제가 발생했습니다. 999를 입력한 후 1을 입력하세요. 공식 계정에서는 사용자 이름을 입력해 주셨는데 사용자 이름을 입력한 후의 응답은 999를 입력한 것과 동일했습니다. 메시지가 표시되면 1을 입력하여 등록하고 2를 입력하여 로그인합니다. 올바른 것은 사용자 이름을 묻는 것입니다. 🎜

이때 런타임/세션 디렉터리에 여러 개의 세션 파일이 생성된 것을 발견했습니다. 동일한 사용자에 대해 올바른 세션 파일은 하나만 있어야 합니다. 이는 사용자가 공식 계정과 상호 작용할 때마다 새로운 세션 파일이 생성되는 것과 동일하므로 사용자가 이전에 입력한 정보를 얻을 수 없습니다.

Baidu는 나중에 그 이유가

세션이 서버 측에 저장되기 때문에 각 사용자의 세션을 구별하기 위해 클라이언트 쿠키를 사용해야 한다는 사실을 발견했습니다. WeChat 서버는 개발자 서버에 쿠키를 보내지 않으므로 세션이 발생합니다. 쿠키 기반은 사용할 수 없습니다.
그러나 각 사용자마다 고유한 session_id가 설정되어 있으면 동일한 효과를 얻을 수 있습니다.
모든 사람의 WeChat ID는 고유하므로 WeChat ID를 사용자의 session_id로 사용하거나 md5 암호화 후 사용할 수 있습니다.

FromUserName 값을 sessionid로 사용할 예정입니다. 즉, 각 사용자 자신의 openid입니다. 그러나 TP6은 sessionid를 설정하는 session_id() 메서드를 지원하지 않습니다. 나중에 문서를 읽고 Session::setId를 사용하여 SessionID를 설정할 수 있다는 것을 알았지만 왜 매번 다른 sessionID가 생성되는지 모르겠습니다.

인터넷에는 openid를 사용할 수 있다고 나와 있습니다. WeChat 공개 계정에서 서버로 보낸 URL에 openid가 포함되어 있을 때마다 TP6가 openid를 사용하기를 바라면서 session.php에서 openid를 구성한 것을 발견했습니다. 매번 세션 ID로 요청합니다. 그러나 여전히 효과가 없었습니다.

TP6의 session.php 구성은 다음과 같습니다.

SESSION_ID의 제출 변수는 도메인 간 플래시 업로드 문제를 해결합니다.
'var_session_id' => 'openid','var_session_id' => 'openid',

查看了下框架的setId,原始代码如下

public function setId($id = null): void
    {
        $this->id = is_string($id) && strlen($id) === 32 && ctype_alnum($id) ? $id : md5(microtime
        (true).session_create_id());
    }

原来sessionid必须为32位包含字母数字的字符串,如果不满足要求(openid长度为28位),就用当前时间作为sessionid,所以我把setId改为下面的样子,然后在index方法中打印sessionid,发现每次都是一样的。

public function setId($id = null): void
    {
        $this->id = is_string($id) && strlen(md5($id)) === 32 && ctype_alnum(md5($id)) ? md5($id) : md5(microtime
        (true).session_create_id());
    }

运行了程序,一切正常,感觉太美好了。

这时,我想之前遇到的那么多问题,应该和xml response没有关系。于是我又用回以前的ThinkWechat.php,却发现runtime/session目录中没有生成session文件。

检查后才发现,原始的ThinkWechat.php的response方法最后是

exit($xml->asXML());

而TP6官方文档有以下提醒:

注意,Session写入数据的操作会在请求结束的时候统一进行本地化存储,所以不要在写入Session数据之后使用exit等中断操作,可能会导致Session没有正常写入。

因此我把exit语句改为return $xml->asXML();

하위의 setId를 확인했습니다. 프레임, 원본 코드는 다음과 같습니다

rrreee

sessionid는 영숫자가 포함된 32비트 문자열이어야 합니다. 요구 사항을 충족하지 않으면(openid 길이는 28비트) 현재 시간이 다음과 같이 사용됩니다. sessionid가 있으므로 setId를 다음과 같이 변경했는데, index 메소드에 sessionid가 출력되어 매번 동일한 것으로 확인되었습니다.
rrreee
프로그램을 실행하면 모든 것이 잘 작동합니다.

이때, 이전에 겪었던 모든 문제는 xml 응답과 관련이 없어야 한다고 생각합니다. 그래서 이전 ThinkWechat.php를 사용했는데, 런타임/세션 디렉터리에 세션 파일이 생성되지 않은 것을 발견했습니다.

확인 결과 원본 ThinkWechat.php의 응답 방식은
🎜exit($xml->asXML());🎜🎜그리고 TP6 공식 문서에는 다음 알림: 🎜🎜 세션에 데이터를 쓰는 작업은 요청이 끝나면 균일하게 로컬에 저장되므로 세션 데이터를 쓴 후 종료와 같은 인터럽트 작업을 사용하지 마세요. 세션이 정상적으로 작성되지 않을 수 있습니다. . 🎜🎜그래서 종료문을 return $xml->asXML();로 변경했습니다. 이때 세션 파일은 정상적으로 생성되었으며, 공식 계정에서 답변한 정보도 정확했습니다. 🎜🎜PS 코드는 github🎜https://github.com/sarawang9012/thinkwechat🎜🎜🎜에서 호스팅되었습니다. 관련 권장 사항: 🎜최신 10개의 thinkphp 비디오 튜토리얼🎜🎜🎜

위 내용은 TP에 ThinkWechat.php를 도입하고 로그를 인쇄하는 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제