快乐每一天

自己选择的路,跪着也要走下去...

Linux服务器Nodejs跟Npm 版本健康升级

nodejs版本大全

第一步:npm升级

废话不多说,直接讲步骤。先从容易的开始,升级npm。

npm这款包管理工具虽然一直被人们诟病,很多人都推荐使用yarn,但其使用人数还是不见减少,况且npm都是随node同时安装好的,一时让我抛弃它,还是有点难做到。

npm i -g npm

是的,你没看错。升级npm只需要像安装其它包一样install一下就行,windows和linux下都可以通过此方式进行升级,你还能指定npm的版本。

npm i -g npm@5.0.0

第二步:node升级
node升级相对于npm来说就复杂一点了。

1、首先通过npm安装node的版本管理工具“n“,不用惊讶,名字就是这么简单,就叫n。据了解,n是node下的一个模块,作者是Express框架的开发者。

npm i -g n

2、检查n模块
先查看系统node的安装路径,n模块的默认路径为 ‘/usr/local’。

$ which node

/data/home/server/nodejs/bin/node   #举个例子

如果路径与n模块的默认路径相同可以跳过下面的步骤

3、通过N_PREFIX变量来修改 n 的默认node安装路径。
(1) 编辑环境配置文件

vim ~/.bash_profile   

(2) 将下面两行代码插入到文件末尾

export N_PREFIX=/data/home/server/nodejs #node实际安装位置
export PATH=$N_PREFIX/bin:$PATH

(3) :wq保存退出;

执行source使修改生效。

$ source ~/.bash_profile

(4) 确认一下环境变量是否生效。

echo $N_PREFIX
/data/home/server/nodejs

4、n模块常用命令

Commands:

  n                              Output versions installed
  n latest                       Install or activate the latest node release
  n -a x86 latest                As above but force 32 bit architecture
  n stable                       Install or activate the latest stable node release
  n lts                          Install or activate the latest LTS node release
  n <version>                    Install node <version>
  n use <version> [args ...]     Execute node <version> with [args ...]
  n bin <version>                Output bin path for <version>
  n rm <version ...>             Remove the given version(s)
  n prune                        Remove all versions except the current version
  n --latest                     Output the latest node version available
  n --stable                     Output the latest stable node version available
  n --lts                        Output the latest LTS node version available
  n ls                           Output the versions of node available

(1) 安装node最新版本

n latest

(2) 安装稳定版

n stable

(3) 安装指定版本 (可以对着最上面给出的node大全里面去找一个node版本)

n v9.6.0

(4) 查看已安装版本

n

(5) 删除指定版本

n rm 6.4.0
阅读全文

php过滤微信昵称中的表情

function filterNickname($nickname)
 
{
    $nickname = preg_replace('/[\x{1F600}-\x{1F64F}]/u', '', $nickname);
 
    $nickname = preg_replace('/[\x{1F300}-\x{1F5FF}]/u', '', $nickname);
 
    $nickname = preg_replace('/[\x{1F680}-\x{1F6FF}]/u', '', $nickname);
 
    $nickname = preg_replace('/[\x{2600}-\x{26FF}]/u', '', $nickname);
 
    $nickname = preg_replace('/[\x{2700}-\x{27BF}]/u', '', $nickname);
 
    $nickname = str_replace(array('"','\''), '', $nickname);
 
    return addslashes(trim($nickname));
}
阅读全文

基于ThinkPHP5封装的 微信公众号模板消息发送(第二版)

// 获取TOKEN,一天就2000条,用一次少一次,跟获取用户信息的access_token 不一样。
    public static function getToken(){
        $appid = config('appid');
        $secret = config('secret');
        $urla = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" .$appid . "&secret=" . $secret;
        $outputa = self::curlGet($urla);
        $result = json_decode($outputa, true);
        return $result['access_token'];
    }

    /**
     * 发送get请求
     * @param string $url 链接
     * @return bool|mixed
     */
    private static function curlGet($url){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        if(curl_errno($curl)){
            return 'ERROR ' . curl_error($curl);
        }
        curl_close($curl);
        return $output;
    }

    /**
     * 发送post请求
     * @param string $url 链接
     * @param string $data 数据
     * @return bool|mixed
     */
    private static function curlPost($url, $data = null){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        if(!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    /**
     * pushMessage 发送自定义的模板消息
     * @param  array  $data          模板数据
        $data = [
            'openid' => '', 用户openid
            'url' => '', 跳转链接
            'template_id' => '', 模板id
            'data' => [ // 消息模板数据
                'first'    => ['value' => urlencode('黄旭辉'),'color' => "#743A3A"],
                'keyword1' => ['value' => urlencode('男'),'color'=>'blue'],
                'keyword2' => ['value' => urlencode('1993-10-23'),'color' => 'blue'],
                'remark'   => ['value' => urlencode('我的模板'),'color' => '#743A3A']
            ]
        ];
     * @param  string $topcolor 模板内容字体颜色,不填默认为黑色
     * @return array
     */
    public static function pushMessage($data = [],$topcolor = '#0000'){
        $template = [
            'touser'      => $data['openid'],
            'template_id' => $data['template_id'],
            'url'         => $data['url'],
            'topcolor'    => $topcolor,
            'data'        => $data['data']
        ];
        $json_template = json_encode($template);
        $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . self::getToken();
        $result = self::curlPost($url, urldecode($json_template));
        $resultData = json_decode($result, true);
        return $resultData;
    }

    /*我的openid: oIMlh5g0X1KSVIinZk4yhu31N7xs*/

    // 模板  1    g-HwvvOhxt5uAjHjb4li0uDPSpacNUnJePm6bvHEAEc    测试模板    {{first.DATA}} 姓名:{{toName.DATA}} 礼物:{{gift.DATA}} 时间:{{time.DATA}} {{remark.DATA}}    

    public function sendMsg(){
        $weiwei_token=self::getToken();
        $data=[
            'openid' => 'oIMlh5gBzdhUOYEdYcc3WRObs-uQ', // 用户openid
            // 'openid' => 'oIMlh5g0X1KSVIinZk4yhu31N7xs', // 用户openid
            'access_token' => $weiwei_token,
            'template_id' => "g-HwvvOhxt5uAjHjb4li0uDPSpacNUnJePm6bvHEAEc", // 填写你自己的消息模板ID
            'data' => [ // 模板消息内容,根据模板详情进行设置
                'first'    => ['value' => urlencode("尊敬的某某某先生,您好,您太帅了"),'color' => "#743A3A"],
                'toName' => ['value' => urlencode("2019必胜猪"),'color'=>'blue'],
                'gift' => ['value' => urlencode("2019必胜猪"),'color'=>'blue'],
                'time' => ['value' => urlencode("2019必胜猪"),'color' => 'green'],
                'remark'   => ['value' => urlencode("请收下我的膝盖"),'color' => '#743A3A']
            ],
            'url'=>'http://cssnb.com'
        ];
        // 'url_link' => 'http://cssnb.com' // 消息跳转链接
        echo "<pre>";
        var_dump(self::pushMessage($data));
        echo "</pre>";
        echo "<hr>";
        echo "<pre>";
        var_dump($data);
        echo "</pre>";

    }

    /*执行
    http://yycard.cssnb.com/index/test/sendMsg

    返回结果:
    array(3) {
      ["errcode"]=>
      int(0)
      ["errmsg"]=>
      string(2) "ok"
      ["msgid"]=>
      int(774234127473180673)
    }
    array(5) {
      ["openid"]=>
      string(28) "oIMlh5g0X1KSVIinZk4yhu31N7xs"
      ["access_token"]=>
      string(157) "20_TwEAN5XflLOjPEDCx9F2RUnxvkZHDIVQYoK206TVq_gdoaH7EeFJ_Am2DM_IyaJnQ3q7qK2PHVI1hSKogPXA2h1k2K7_7QCXxL6pUsAejCK-s-yKApLYd97VnfhwLjc7tndKmCAVDayLgogdQVMbAAAUZQ"
      ["template_id"]=>
      string(43) "g-HwvvOhxt5uAjHjb4li0uDPSpacNUnJePm6bvHEAEc"
      ["data"]=>
      array(5) {
        ["first"]=>
        array(2) {
          ["value"]=>
          string(144) "%E5%B0%8A%E6%95%AC%E7%9A%84%E6%9F%90%E6%9F%90%E6%9F%90%E5%85%88%E7%94%9F%EF%BC%8C%E6%82%A8%E5%A5%BD%EF%BC%8C%E6%82%A8%E5%A4%AA%E5%B8%85%E4%BA%86"
          ["color"]=>
          string(7) "#743A3A"
        }
        ["keyword1"]=>
        array(2) {
          ["value"]=>
          string(31) "2019%E5%BF%85%E8%83%9C%E7%8C%AA"
          ["color"]=>
          string(4) "blue"
        }
        ["keyword2"]=>
        array(2) {
          ["value"]=>
          string(31) "2019%E5%BF%85%E8%83%9C%E7%8C%AA"
          ["color"]=>
          string(4) "blue"
        }
        ["keyword3"]=>
        array(2) {
          ["value"]=>
          string(31) "2019%E5%BF%85%E8%83%9C%E7%8C%AA"
          ["color"]=>
          string(5) "green"
        }
        ["remark"]=>
        array(2) {
          ["value"]=>
          string(63) "%E8%AF%B7%E6%94%B6%E4%B8%8B%E6%88%91%E7%9A%84%E8%86%9D%E7%9B%96"
          ["color"]=>
          string(7) "#743A3A"
        }
      }
      ["url"]=>
      string(16) "http://cssnb.com"
    }
    */
阅读全文

基于ThinkPHP5微信H5授权登录获取用户信息(改进版)

不需要在网上找什么乱七八糟的东西,直接来之即用岂不是很完美。

只需要有一台服务器即可,没备案都可以玩这个功能。不需要拥有服务号,看完全文你就明白了。

数据库篇:

-- Adminer 4.6.3 MySQL dump

SET NAMES utf8;
SET time_zone = '+00:00';
SET foreign_key_checks = 0;
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';

DROP TABLE IF EXISTS `yy_wxuser`;
CREATE TABLE `yy_wxuser` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `nickname` varchar(255) DEFAULT '' COMMENT '昵称',
  `openid` varchar(255) DEFAULT '' COMMENT 'openid',
  `avatar` varchar(255) DEFAULT '' COMMENT '头像',
  `gender` tinyint(1) unsigned DEFAULT '1' COMMENT '性别',
  `province` varchar(20) DEFAULT '0' COMMENT '省',
  `city` varchar(20) DEFAULT '0' COMMENT '市',
  `county` varchar(20) DEFAULT '0' COMMENT '县',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='用户表';


-- 2019-04-20 03:13:42

基本库,用于调起授权授权获取用户信息 Wxgetuserinfo.php

<?php
/**
 * Created by PhpStorm.
 * User: wudi
 * Date: 2019/1/28
 * Time: 10:31
 */

namespace app\card\controller;
use think\Db;

class Wxgetuserinfo
{
    /**
     * 调用方法
     * 具体参考tp5的命名空间  https://www.kancloud.cn/manual/thinkphp5/118014
     * $class = new \app\card\controller\Wxgetuserinfo();
     * $class->index();
     */

    /**
     * 1、获取用户信息
     */

    public function delsession(){
        session('userinfo', null);
        session(null);
    }

    public function index(){
        $appid = config('appid');
        $secret = config('secret');

        if(!session('?userinfo')){
            if (!isset($_GET['code'])){//没有code,去微信接口获取code码
                $request = request();
                $callback = $request->url(true);//微信服务器回调url,这里是本页url
//                $this->get_code($callback);
                $redirect_uri=urlencode($callback);
                $url='https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$appid.'&redirect_uri='.$redirect_uri.'&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect';
                header("location:$url");exit();

            } else {//获取code后跳转回来到这里了
                $code = $_GET['code'];
                $data = $this->get_access_token($code);//获取网页授权access_token和用户openid
                $data_all = $this->get_user_info($data['access_token'],$data['openid']);//获取微信用户信息
                session('userinfo',$data_all);
                $this->checkuser($data_all['openid'],$data_all);
                return json($data_all);
            }
        }else{
            $ret=session('userinfo');
            return json($ret);             //返回的获取到的微信用户信息
        }
    }

    /**
     * 3、使用code换取access_token
     * @param string 用于换取access_token的code,微信提供
     * @return array access_token和用户openid数组
     */
    private function get_access_token($code){
        $appid = config('appid');
        $appsecret = config('secret');
        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $appid . '&secret=' . $appsecret . '&code=' . $code . '&grant_type=authorization_code';
        $user = json_decode(file_get_contents($url));
        if (isset($user->errcode)) {
            echo 'error:' . $user->errcode.'<hr>msg  :' . $user->errmsg;exit;
        }
        $data = json_decode(json_encode($user),true);//返回的json数组转换成array数组
        return $data;
    }

    /**
     * 4、使用access_token获取用户信息
     * @param string access_token
     * @param string 用户的openid
     * @return array 用户信息数组
     */
    private function get_user_info($access_token,$openid){
        $url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $openid . '&lang=zh_CN';
        $user = json_decode(file_get_contents($url));
        if (isset($user->errcode)) {
//            echo 'error:' . $user->errcode.'<hr>msg  :' . $user->errmsg;exit;
        }
        $data = json_decode(json_encode($user),true);//返回的json数组转换成array数组
        return $data;
    }

    /**
     * 检查用户信息
     * TODO 在这个地方如果在用户表加一个时间字段,就可以每隔多少次对数据库进行一次操作,而不是一直更新操作。
     */
    public function checkuser($openid,$data){
        $check=Db::name('wxuser')->where(array('openid'=>$openid))->find();
        if($check){
            /*更新用户信息*/
            $updata=array();
            $updata['avatar']=$data['headimgurl'];
            $updata['createtime']=time();
            $updata['nickname']=$data['nickname'];
            Db::name('wxuser')->where('openid',$openid)->update($updata);

            /*获取最新用户信息并存入缓存*/
            $newinfo=Db::name('wxuser')->where(array('id'=>$check['id']))->find();
            session('userinfo',$newinfo);

        }else{
            /*新增用户信息*/
            $intdata=array();
            $intdata = ['nickname' =>$data['nickname'], 'avatar' => $data['headimgurl'],'createtime'=>time(),'openid' => $data['openid'],'gender' => $data['sex'],'city' => $data['city'],'province' => $data['province'],'county' => $data['country']];
            Db::name('wxuser')->insert($intdata);
            $userId = Db::name('wxuser')->getLastInsID();
            /*获取最新用户信息并存入缓存*/
            if(!session('?userinfo')){
                $newinfo=Db::name('wxuser')->where(array('id'=>$userId))->find();
//                $newinfo=Db::name('wxuser')->where('id',$userId)->find();array('openid'=>$openid,'delstatus'=>1)
                session('userinfo',$newinfo);
            }
        }
    }


/*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
    /*检测是否关注公众号*/
    /*subscribe    用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。*/
    /*https://www.cnblogs.com/mracale/p/9318349.html*/
    public function checkisgz(){
        $request = request();
        $callback = $request->url(true);//微信服务器回调url,这里是本页url

        $appid = config('appid');
        $secret = config('secret');

//微信网页授权获取openid
        $web_url=$callback;

        if (!isset($_GET['code'])) {
            $redirect_uri=urlencode($web_url);
            $url='https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$appid.'&redirect_uri='.$redirect_uri.'&response_type=code&scope=snsapi_base&state=1#wechat_redirect';
            header("location:$url");exit();
        }
        $code=trim($_GET['code']);
        $url='https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$appid.'&secret='.$secret.'&code='.$code.'&grant_type=authorization_code';
        $access=file_get_contents($url);
        $data=json_decode($access,true);
        $access_token=$data['access_token'];
        $url='https://api.weixin.qq.com/sns/userinfo?access_token='.$access_token.'&openid=OPENID&lang=zh_CN';
        $user=file_get_contents($url);
        $arr=json_decode($user,true);
//获取用户的openid
        $openid=$arr['openid'];

        $url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret;
        $access=file_get_contents($url);
        $access_arr=json_decode($access,true);
//非网页的access_token
        $access_token=$access_arr['access_token'];

        $url="https://api.weixin.qq.com/cgi-bin/user/info?access_token=".$access_token."&openid=".$openid."&lang=zh_CN";
        $res=file_get_contents($url);
//        var_dump($res);
        return $res['subscribe'];
    }




}

中间库:Basesdns.php

<?php
/**
 * Created by PhpStorm.
 * User: wudi
 * Date: 2019/1/28
 * Time: 14:37
 */

namespace app\card\controller;
use think\Controller;
use think\Db;
use think\Request;

class Basesdns extends Controller
{
    /**
     * 检测是否授权登录
     * 初始化方法,可以控制用户权限、获取菜单等等,只要是继承base类的其它业务类就不需要再重写
     */
    public function _initialize()
    {
        parent::_initialize();
        $class = new \app\card\controller\Wxgetuserinfo();
        $class->index();

        $userinfo=session('userinfo');
        if(!$userinfo){
            $class = new \app\card\controller\Wxgetuserinfo();
            $class->index();
        }


        $this->userinfo=session('userinfo');
    }
}

应用库,写日常逻辑的,需要继承中间库,个人认为前面所有的缓存只需要存一个openid就可以了。
Index.php

<?php
namespace app\card\controller;
use think\Db;
use think\Request;

class Index  extends Basesdns
{


    /*首页*/
    public function index()
    {
        $userinfo=session('userinfo');
        $userinfo=Db::name('wxuser')->where('openid',$userinfo['openid'])->find();
        session('userinfo',$userinfo);
        $this->assign('userinfo',$userinfo);
        return $this->fetch();
       
    }

}

config.php 用来配置 微信的appid跟secret。

2019-04-20T03:28:00.png

另外需要注意的是,公众号必须要加上对应服务器的ip白名单,以及网页授权回调域名配置。

这里再说一个很多人不知道的小消息,就是即使你没有服务号,也可以完成这个代码测试,只要你有一台服务器就可以了,没备案都没关系,那就是微信测试号。

注册微信测试号的地址是:
http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

2019-04-20T03:33:02.png

推进观看的链接:http://www.cnblogs.com/hui9527/p/8473982.html 这个代码还不错。

阅读全文

Thinkphp5导出Excel功能

  1. 网上下载PHPExcel包,http://www.php.cn/xiazai/leiku/1491 下载后只需要Classes目录下的文件即可
  2. 放在Thinkphp/vendor/下面,前端直接跳转到该控制器
  3. 前台直接跳到该控制器方法下
<?php

namespace app\admin\controller;

use think\Controller;
use think\Request;
use think\Db;
class Excel extends Controller
{
   public function index()
   {
       $time = time();
       $xlsData = Db::table('oa_attendance')->where("morning", "=", "1")->where("afternoon", "=", "1")
           ->alias('a')
           ->join('oa_user u', 'a.uid = u.uid')
           ->join('oa_com c', 'u.factory = c.cid')
           ->select();
        //这里引入PHPExcel文件注意路径修改
       vendor("PHPExcel");                                     
       vendor("PHPExcel.Writer.Excel5");
       vendor("PHPExcel.Writer.Excel2007");
       vendor("PHPExcel.IOFactory");
       $objExcel = new \PHPExcel();                   
       $objWriter = \PHPExcel_IOFactory::createWriter($objExcel, 'Excel2007');
       $objActSheet = $objExcel->getActiveSheet();
       $key = ord("A");
       $letter =explode(',',"A,B,C,D,E,F,G");
       $arrHeader = array('ID','姓名','工作单位','电话','职位','上班打卡时间','下班打卡时间');
       $lenth =  count($arrHeader);
       for($i = 0;$i < $lenth;$i++) {
           $objActSheet->setCellValue("$letter[$i]1","$arrHeader[$i]");
       };
       foreach($xlsData as $k=>$v){
           $k +=2;
           $objActSheet->setCellValue('A'.$k, $v['id']);
           $objActSheet->setCellValue('B'.$k, $v['name']);
           $objActSheet->setCellValue('C'.$k, $v['com_name']);
           $objActSheet->setCellValue('D'.$k, $v['phone']);
           $objActSheet->setCellValue('E'.$k, $v['job']);
           $objActSheet->setCellValue('F'.$k, date("m-d H:i",$v['morningtime']));
           $objActSheet->setCellValue('G'.$k, date("m-d H:i",$v['afternoontime']));
           $objActSheet->getRowDimension($k)->setRowHeight(20);
       }
       $width = array(20,20,15,10,10,30,10,15);
       //设置表格的宽度
       $objActSheet->getColumnDimension('A')->setWidth($width[3]);
       $objActSheet->getColumnDimension('B')->setWidth($width[1]);
       $objActSheet->getColumnDimension('C')->setWidth($width[0]);
       $objActSheet->getColumnDimension('D')->setWidth($width[5]);
       $objActSheet->getColumnDimension('E')->setWidth($width[5]);
       $objActSheet->getColumnDimension('F')->setWidth($width[5]);
       $objActSheet->getColumnDimension('G')->setWidth($width[5]);

       $outfile = "员工考勤表.xls";
       ob_end_clean();
       header("Content-Type: application/force-download");
       header("Content-Type: application/octet-stream");
       header("Content-Type: application/download");
       header('Content-Disposition:inline;filename="'.$outfile.'"');
       header("Content-Transfer-Encoding: binary");
       header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
       header("Pragma: no-cache");
       $objWriter->save('php://output');    //这里直接导出文件

   }

}
  1. 这里是目录结构,这是下载出来的,只需要Classes文件下的

2019-04-20T03:07:32.png
2019-04-20T03:07:43.png

阅读全文