yii2作为微信小程序后台试验

yii2多应用配置

yii2 advanced模板,添加第3个应用api (可以参考  https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-zh-CN/topic-adding-more-apps.md   注意,替换命名空间比较累人也容易出错,好在我用PhpStorm可以按路径搜索替换)

由于我是使用单一域名放这3个应用的,所以,涉及必要的服务器配置问题

nginx(Ubuntu 18.04)参考配置为:

zime@zime-virtual-machine:~$ cat /etc/nginx/sites-available/gxlq_pig
server	{
	charset utf-8;
	client_max_body_size 128M;

	listen 80 default_server;
	listen [::]:80 default_server;

	server_name _;
	
	access_log /home/zime/PhpstormProjects/gxlq_pig/log/access.log;
	error_log /home/zime/PhpstormProjects/gxlq_pig/log/error.log info;
	#	rewrite_log on;  # use rewrite log

	set $front_root /home/zime/PhpstormProjects/gxlq_pig/frontend/web;
	set $back_root /home/zime/PhpstormProjects/gxlq_pig/backend/web;
	set $api_root /home/zime/PhpstormProjects/gxlq_pig/api/web;
	set $prj_root /home/zime/PhpstormProjects/gxlq_pig;
	root $prj_root;

	location / {
	    #root $front_root;

	    try_files $uri index.php?$args  /frontend/web/index.php?$args;

	    location ~ ^\.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
	        access_log off;
		expires 360d;

		rewrite ^/(.+)$ /web/$1 break;
		rewrite ^/(.+)/(.+)$ /web/$1/$2 break;
		try_files $uri =404;
	    }
	}

	location /api {
	   #alias $api_root;
	   rewrite ^(/api)/$ $1 permanent;
	  # try_files $uri index.php?$args  /api/web/index.php?$args;
	   try_files $uri  /api/web/index.php?$args;
	}

	location ~ ^/api/(.+\.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar))$ {
	    access_log off;
	    expires 360d;

	    rewrite ^/api/(.+)$  /api/web/$1 break;
	    rewrite ^/api/(.+)/(.+)$ /api/web/$1/$2 break;
	    try_files $uri =404;
	}


	location /admin {
	    #alias $back_root;
	    rewrite ^(/admin)/$ $1 permanent;
	    try_files $uri /backend/web/index.php?$args;
	}

	location ~ ^/admin/(.+\.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar|woff2|svg|eot|woff|ttf))$ {
	    access_log off;
	    expires 360d;

	    rewrite ^/admin/(.+)$  /backend/web/$1 break;
	    rewrite ^/admin/(.+)/(.+)$ /backend/web/$1/$2 break;
	    try_files $uri =404;
	}

	

	# deny accessing php files for the /assets directory
	location ~ ^/assets/.*\.php$ {
	    deny all;
	}    

	# pass PHP scripts to FastCGI server
	#
	location ~ \.php$ {

	#	include snippets/fastcgi-php.conf;
	#
	#	# With php-fpm (or other unix sockets):
		fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
	#	# With php-cgi (or other tcp sockets):
	#	fastcgi_pass 127.0.0.1:9000;

		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include  fastcgi_params;
		try_files $uri =404;
	}

	location = /requirements.php {
	    deny all;
	}

	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	#
	location ~ /\.(ht|svn|git) {
		deny all;
	}
}

apache(Windows 2008)参考配置为:

httpd-ssl.conf 如下

<VirtualHost ****.com:8066>
    DocumentRoot "C:/wamp/apps/gxlq_pig"
    ServerName ****.com:8066
    ErrorLog "C:/wamp/logs/gxlq_pig-error.log"
    CustomLog "C:/wamp/logs/gxlq_pig-access.log" common

    # debug rewrite
    # LogLevel alert rewrite:trace8

    SSLEngine on
    SSLCertificateFile "C:/wamp/bin/apache/apache2.4.9/conf/cert.pem"
    SSLCertificateKeyFile "C:/wamp/bin/apache/apache2.4.9/conf/key.pem"

    <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
    </FilesMatch>
    BrowserMatch "MSIE [2-5]" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

    <Directory "C:/wamp/apps/gxlq_pig">
#        Options Indexes FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>

</VirtualHost>

项目根目录 gxlq_pig 下的 .htaccess 如下

# prevent directory listigs
Options -Indexes
# follow symbolic links
Options FollowSymlinks
RewriteEngine on

RewriteCond %{REQUEST_URI}  ^/api/$
RewriteRule ^(api)/$  /$1  [R=301,L]
RewriteCond %{REQUEST_URI} ^/api
RewriteRule ^api(/.+)?$  /api/web/$1  [L,PT]


RewriteCond %{REQUEST_URI}  ^/admin/$
RewriteRule ^(admin)/$  /$1  [R=301,L]
RewriteCond %{REQUEST_URI} ^/admin
RewriteRule ^admin(/.+)?$  /backend/web/$1  [L,PT]


RewriteCond %{REQUEST_URI}  ^.*$
RewriteRule ^(.*)$  /frontend/web/$1

gxlq_pig/api/web目录下的.htaccess如下(其他两个应用对应web目录下的.htaccess是一样的)

# use mod_rewrite for pretty URL support
RewriteEngine on

#if a directory or a file exists, use the request directly
RewriteCond %{REQUEST_FILENAME}  !-f
RewriteCond %{REQUEST_FILENAME}  !-d
# otherwise forward the request to index.php
RewriteRule  .  index.php

修改api/config/main.php配置文件(主要是共享单一域名需要修改的一些地方,注意,下面的配置文件中没有禁用csrf,作为API实用角度来说,应该在这里全局禁用csrf)

<?php
$params = array_merge(
    require __DIR__ . '/../../common/config/params.php',
    require __DIR__ . '/../../common/config/params-local.php',
    require __DIR__ . '/params.php',
    require __DIR__ . '/params-local.php'
);

return [
    'id' => 'app-api',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'controllerNamespace' => 'api\controllers',
    'homeUrl' => '/api',
    'components' => [
        'request' => [
            'csrfParam' => '_csrf-api',
            'csrfCookie' => [
                'httpOnly' => true,
                'path' => '/api',     // share domain
            ],
            'enableCookieValidation' => false,
            'parsers' => [
                'application/json' => 'yii\web\JsonParser',
            ],
            'baseUrl' => '/api',
        ],
        'response' => [
            'format' => \yii\web\Response::FORMAT_JSON,
            'charset' => 'UTF-8',
        ],
        'user' => [
            'identityClass' => 'common\models\User',
            'enableAutoLogin' => true,
            'identityCookie' => ['name' => '_identity-api', 'httpOnly' => true, 'path' => '/api'],  // share domain
        ],
        'session' => [
            // this is the name of the session cookie used for login on the api
            'name' => 'advanced-api',
            'cookieParams' => [
                'path' => '/api',  // share domain
            ]
        ],
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
//*
        'urlManager' => [
            'enablePrettyUrl' => true,
            //'enableStrictParsing' => true,
            'showScriptName' => false,

            'rules' => [
                ['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
                ['class' => 'yii\rest\UrlRule', 'controller' => 'group'],
            ],

        ],
//*/
    ],
    'params' => $params,
];

 

yii2后端测试代码

直接在api/controllers/SiteController.php进行添加修改。先修改actionIndex,访问https://****/api/site/wechat-post测试一下“通不通”

public function actionIndex()
    {
        //return $this->render('index');
        return Json::encode(['msg' => 'hello, site index']);
    }

然后在控制器代码开始处添加以下代码,我们从控制器范围禁用csrf(也可以覆盖父类beforeAction对指定的action禁用csrf),可以参考  https://blog.csdn.net/u012979009/article/details/51791810

public $enableCsrfValidation = false;   // 可以在配置文件、控制器或beforeAction禁用csrf

添加2个action,分别用于form表单测试和文件上传测试

    public function actionWechatPost()
    {
        return Json::encode(['msg' => 'post OK', 'posted_data' => $_POST]);
    }

    public function actionWechatUpload()
    {
        return Json::encode(['msg' => 'upload OK', 'with_posted_data' => $_POST, 'Raw $_FILES' => $_FILES]);
    }

小程序测试代码

用小程序开发工具新建应用gxlq_pig,用自带模拟器可以直接试验。

我们使用微信自己的WeUI框架,所以下载并引入该框架:从  https://github.com/Tencent/weui-wxss  下载zip压缩包,解压后将其中的style目录整个带目录放到项目根目录gxlq_pig下面 (WeUI框架自带了不少examples,所以可以参照学习),然后在小程序项目的全局应用样式表app.wxss头部添加以下代码  (可以参考  https://www.jianshu.com/p/fd423b6e17be )

@import "style/weui.wxss";

我们在项目根目录的pages下新建目录module1,然后在里面建立4个文件(这也是小程序基本“套路”):index.js,index.json,index.wxml,index.wxss

说明:简单理解,wxml对标html,wxss对标css,这两个部分组成了静态的可以看的部分(内容和样式),json文件是一个配置文件,json和wxss是可以覆盖应用的全局配置信息的,js文件相当于本模块的可执行代码。

小程序运行的大致逻辑是:app.json和app.wxss是全局的配置信息,后者是全局样式,前者最值得关心的是路由信息。app.js是应用程序主入口,就是加载启动小程序时需要做的工作,实际我们看到的“第一个画面”,其实是路由信息中的第一个路由到的页面。

现在,我们希望在第一个页面中加入“一点东西”,点击它之后“被动”转向我们新建的模块module1:

首先,必须在app.js的路由表添加module1中需要显示的页面module1/index的路由信息

  "pages":[
    "pages/index/index",
    "pages/logs/logs",
    "pages/module1/index"
  ],

其次,我们 pages/index/index.wxml 的底部添加一点代码(view class="mytest"部分),点击这个链接将路由到module1/index

  <view class="usermotto">
    <text class="user-motto">{{motto}}</text>
  </view>
  <view class="mytest">
    <navigator url="../module1/index">goto My Form</navigator>
  </view>

为了避免这链接和上面的hello挤在一起,我们在 pages/index/index.wxss中添加样式(类mytest的样式)

.mytest {
  margin-top: 20px;
  background-color: pink;
}

最后是编写前面建立的4个文件的内容(可以参考  https://blog.csdn.net/anqingya/article/details/80348877 )

module1/index.wxml文件

<!--index.wxml-->
<form bindsubmit="formSubmit">
<view class="weui-cell weui-cell_input">
  <view class="weui-cell__hd">
    <view class="weui-label">学号</view>
   </view>
    <view class="weui-cell__bd">
    <input class="weui-input" name="no" placeholder="请输入学号" value='1635050131'/>
   </view>
  </view>
  <view class="weui-cell weui-cell_input">
  <view class="weui-cell__hd">
    <view class="weui-label">姓名</view>
   </view>
    <view class="weui-cell__bd">
    <input class="weui-input" name="name" placeholder="请输入姓名" value='安庆雅'/>
   </view>
  </view>
  <view class="weui-cell weui-cell_input">
  <view class="weui-cell__hd">
    <view class="weui-label">性别</view>
   </view>
    <view class="weui-cell__bd">
    <input class="weui-input" name="sex" value="{{sex}}"/>
   </view>
     <view class="weui-cell__ft">
    <switch checked bindchange="switch1Change"/>
  </view>
  </view>
  <view class="weui-cell weui-cell_input">
  <view class="weui-cell__hd">
    <view class="weui-label">年龄</view>
   </view>
    <view class="weui-cell__bd">
    <input class="weui-input" name="age" placeholder="请输入年龄" value='21'/>
   </view>
  </view>
  <view class="weui-cells">
          <view class="weui-cell">
            <view class="weui-cell__bd">
              <view class="weui-uploader">
                <view class="weui-uploader__hd">
                  <view class="weui-uploader__title">个人照片</view>
                  <view class="weui-uploader__info">0/1</view>
                </view>
                <view class="weui-uploader__bd">
                  <view class="weui-uploader__files">
                    <block wx:for="{{imageList}}" wx:for-item="image">
                      <view class="weui-uploader__file">
                        <image class="weui-uploader__img" src="{{image}}" data-src="{{image}}" bindtap="previewImage"></image>
                      </view>
                    </block>
                  </view>
                  <view class="weui-uploader__input-box">
                    <view class="weui-uploader__input" bindtap="chooseImage"></view>
                  </view>
                </view>
              </view>
            </view>
          </view>
        </view>
     <view class="weui-btn-area">
    <button class="weui-btn" type="primary" form-type="submit">确定</button>
     </view>   
</form>

module1/index.js文件(作为测试另外2个文件不关键,不用写内容)

//index.js
//获取应用实例
Page({
  data: {
   sex: '男',
   imageList:[]
  },
  switch1Change:function(e){
    if(e.detail.value){
      this.setData({sex:'男'})
    }else{
      this.setData({sex:'女'})
    }
  },
  //表单提交
  formSubmit: function (e) {
      wx.request({
        url: 'https://****/api/site/wechat-post', //仅为示例,并非真实的接口地址
        data:e.detail.value,
        method:'POST',
        header: {
          'content-type': 'application/x-www-form-urlencoded' // 默认值
        },
        success: (res)=>{
          console.log(res)
          if (res.error) {
            wx.showToast({
              title:res.data.msg,    // 这个可能有问题,见下面 upload 部分
              icon: 'none',
              duration: 2000,
            })
          } else {
            wx.showToast({
              title: '添加成功',
              icon: 'success',
              duration: 2000,
            })
 
            this.upload();
          }
        }
      })
  },
//拍照
  chooseImage: function () {
    var that = this
    wx.chooseImage({
      count: 1, // 默认9
      sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
      success: function (res) {
        console.log(res)
        that.setData({
          imageList: res.tempFilePaths
        })
      }
    })
  },
  //预览照片
  previewImage: function (e) {
    var current = e.target.dataset.src
    wx.previewImage({
      current: current,
      urls: this.data.imageList
    })
  },
 
  //上传
  upload:function(){
    wx.uploadFile({
      url: 'https://****/api/site/wechat-upload', //仅为示例,非真实的接口地址
      filePath: this.data.imageList[0],
      name: 'file',
      formData: {
        'user': 'test'
      },
      success: function (res) {
        console.log(res);
        //var data = res.data
        //console.log(data);
        var json=JSON.parse(res.data);
        console.log(json);
        console.log(typeof json);   // 一次 JSON.parse 后,这里得到的json还是字符串!
        json = JSON.parse(json);
        console.log(json);
        console.log(typeof json);   // 到这里 json 才是Object
        wx.showToast({
          title: json.msg,
          icon: 'none',
          duration: 3000,
        })
      }
    })
  }
})

小程序端的测试

用微信开发工具的模拟器,进入后点击goto My Form,顺利跳转并显示表单页面。在表单里面输入各项信息,性别切换,然后选择电脑中的某个图片作为照片。在选择图片后,调试器console会输出 chooseImage的回调success内console.log语句的输出。

点击“确定”后,仔细观察调试器控制台的输出,确认信息是否正常,流程是否正确。同时,这些信息可以和后面服务端信息进行比对,例如上传的文件的大小是否一致。

服务器yii2端的“测试”(日志信息)

观察 api/runtime/logs/app.log 尾部的信息,可以发现

$_POST = [
    'no' => '20010414'
    'name' => '张三'
    'sex' => '男'
    'age' => '42'
]

$_FILES = []

$_COOKIE = []

$_SERVER = [
// ......
]

//......

$_POST = [
    'user' => 'test'
]

$_FILES = [
    'file' => [
        'name' => 'tmp_ec95aaf90fb6b7892ebbae76035c9981386612c029efcf2a.jpg'
        'type' => 'image/jpeg'
        'tmp_name' => 'C:\\wamp\\tmp\\php4A81.tmp'
        'error' => 0
        'size' => 36299
    ]
]

$_COOKIE = []

$_SERVER = [
//......
]

观察到这些信息,我们可以确信,表单数据提交和文件上传都是“达到了服务器端”的。接下来的工作无非是把上传文件或者处理表单改写成yii2风格的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值