什么叫“降准降息”?我们用水多不多来比喻一下

WHAT

准:存款准备金。息:基准利率。

什么是存款准备金呢?

储户要把钱存到银行里,银行再放贷出去,然后形成企业、个人的各种贷款,支持消费生产。但是,每天都有不同的储户有提现的要求,所以银行必须留存一小部分钱出来应付储户提现的需求,这部分钱就叫做存款准备金,这个留存的比例就叫存款准备金率。

基准利率又是什么呢?

基准利率就是一个市场上利率水平的风向标。各个金融机构,都根据这个标准来确定自己的贷款和存款利率。

WHY

为什么会有降准降息这一说?

国家通过银行体系,调控整个社会的信用规模和经济冷热。

控制存款准备金的比率,就像控制水库的闸门一样,可以控制整个社会的信用规模。

打个比方,银行体系像一个巨大的水利工程,货币资金在里边就是水。那基准利率意味着什么?基准利率就是用水的价格。你想,要是把水的价格提上去了,水太贵了地都浇不起,种地的人就宁可让地荒着,也不去开垦农地种庄稼。要是水的价格很便宜了,农民可能就愿意多开垦一些荒地,多种一些庄稼。所以,通过调整基准利率的水平,实际上就是控制社会资金的价格,然后来影响大家投资消费的意愿。

存款准备金制度主要是控制了资金的量,而基准利率调整的是资金的价格,然后通过量、价同时控制的手段,整个社会的信用规模和经济冷热就能够被国家所控制了。

一般来说,政府如果担心经济过热的话,就会加息,也就是提高利率进行收缩。
加息控制经济过热是正确的,但是这么快速、猛烈的加息幅度就产生了负面后果。

躺赚白日梦之微擎应用开发基础篇

WHAT

微擎是目前市面上比较流行的第三方微信运营管理系统。系统相对成熟,应用全面,能满足绝大部分微信端功能开发。

今天我们来说下如何新建一个微擎应用。

微擎安装后目录结构。

在哪里新建应用呢?addons 目录。

想一个暴富的名字,新建在 addons 中,比如 baofu。

我建了一个基础的应用结构,我们来简单介绍一下。

1.manifest.xml

这个文件就是应用的基础信息配置。我们来看看内容。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns="http://www.we7.cc" versionCode="">
    <application setting="false">
        <name><![CDATA[暴富]]></name>
        <identifie><![CDATA[baofu]]></identifie>
        <version><![CDATA[1.0.0]]></version>
        <type><![CDATA[activity]]></type>
        <ability><![CDATA[营销活动]]></ability>
        <description><![CDATA[何以解忧,唯有暴富]]></description>
        <author><![CDATA[张邦]]></author>
        <url><![CDATA[https://www.zhime.com.cn]]></url>
    </application>
    <platform>
    </platform>
    <bindings>
        <menu>
            <entry title="我要暴富" do="money" state="" direct="false" />
        </menu>
    </bindings>
    <permissions>
    </permissions>
    <install><![CDATA[install.php]]></install>
    <uninstall><![CDATA[uninstall.php]]></uninstall>
    <upgrade><![CDATA[]]></upgrade>
</manifest>

application 内容

name:应用名称

identifie:应用ID

version:版本号

type:应用类型  activity business等等

ability:这个应该是用途

description:应用描述

author:作者

url:官网

platform

这个主要是配置应用与公众号交互的功能权限,暂时不讨论

bindings -> menu

这个是应用后台的菜单,稍后看示例。

<entry title=”我要暴富” do=”money” state=”” direct=”false” />

title:菜单名称

do:这个是对应 site.php 里面的操作,比如这里的值是 money ,那么对应site.php的操作就是 doWebMoney.

install

这个是安装文件名

uninstall

这个是卸载文件名

2.install.php

这里面是安装应用执行的操作,比如新建数据库。

<?php
pdo_query("

CREATE TABLE `ims_bf_test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `number` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `flow_id` (`flow_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


");

3.uninstall.php

这个是卸载应用是执行的操作。比如删除表。

<?php
$sql = "

DROP TABLE ims_bf_test;

";
pdo_run($sql);
?>

3.site.php

下面来讲讲重头戏。

<?php

defined('IN_IA') or exit('Access Denied');
$_M = array();


class baofuModuleSite extends WeModuleSite
{

   


    public function doWebMoney()
    {
        global $_W, $_GPC;

        
        include $this->template("money");
    }


    public function doMobileMember()
    {
        global $_W, $_GPC;

        include $this->template("member");
    }


}

在site.php里面,执行的方法 都是以 doWeb 或者 doMobile 开头。

doWeb 对应的是后台的操作,doMobile 对应的是前台的操作。

$_W 这个是微擎中的全局变量

$_GPC这个则是请求数据

include $this->template("money"); //

这段代码是引入模板,doWeb 和 doMobile 模板位置不一样。doWeb 的模板直接放在 template 下面,而 doMobile 则是在template 下新建mobile来进行存放。

至此,一个简单的示例就说完了,当然了,这个结构不一定就按如此的来,骚年可以发挥想象力大胆去创造。

MySQL存储过程之递归结算多层级奖金

原文书接上一回,上文说了使用MySQL存储过程来结算直推奖 ,今天继续说说使用存储过程来结算多层级奖金,先直接上完整代码。

函数 func。

CREATE FUNCTION `func`(uid int,money decimal) RETURNS int(11)
begin

DECLARE is_empty int default 0;
DECLARE i int default 1;
DECLARE userRank int;
DECLARE pid int;
DECLARE pro decimal(8,4) default 0.005;
DECLARE le int;
DECLARE wallet Decimal(10,2);


while is_empty <> 1 do

select user_rank,parent_id,money_wallet into userRank,pid,wallet from hy_agent_user where id = uid;

//逻辑操作 插入 更新操作

if pid > 0
then set uid = pid;
else set is_empty = 1;
end if;

end while;



return i;
end

存储过程 bonus。

CREATE  PROCEDURE `bonus`()
begin

DECLARE bd decimal;
DECLARE no_more_record int DEFAULT 0;
DECLARE pid int;
DECLARE bid int;

declare userList CURSOR for
SELECT bd_release as br,parent_id,bd.bd_id FROM hy_bonus_day bd LEFT JOIN hy_agent_user au
ON bd.bd_aid = au.id
WHERE release_status = 0;

DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET no_more_record=1;


open userList;

fetch userList into bd,pid,bid;

while no_more_record <> 1 DO

IF pid > 0
then
select func(pid,bd);
END IF;

update hy_bonus_day set release_status = 1 where bd_id = bid;

fetch userList into bd,pid,bid;

end while;

close userList;

end

我们先来简单说说存储过程 bonus。

先定义了一系列的变量,然后从数据库中查询需要结算的记录,并赋值进 userList 这个变量中。

接下来就是while循环了,其中循环中调用了一个自定义函数 func。

select func(pid,bd);

使用 select 来调用自定义函数。

下面我们再来看下 func 这个函数的结构。

其实自定义函数和存储过程结构大致一样,还是不说了。

在这个代码中,存储过程使用了 SQLSTATE 来判断是否有下一条记录,而在 函数 func 中我们使用了 普通的 if 逻辑判断,没有上级时将变量is_empty 设为 1,使 while 不再继续执行。

写这代码的时候我才发现,select … into 设置多个变量的语法….

select aa,bb,cc into is_aa,is_bb,is_cc from user;

 

Mysql存储过程之直分销推荐奖励结算

WHAT

在现在的众多直分销项目中,推荐奖已经是必不可少的,近日有小伙伴提议,使用MySQL的存储过程来进行推荐奖励的结算,所以写了个简单的示例。

至于MySQL存储的优缺点就不再过多赘述,一步到位直接来代码。

create procedure rec()

begin

DECLARE aid int(11);
DECLARE buyPv decimal(10,2);
DECLARE rankPro decimal(10,2);
DECLARE userRank int;
DECLARE parentId int(11);
DECLARE wallet decimal(10,2);
DECLARE no_more_record int DEFAULT 0;
DECLARE account varchar(32);


declare userList CURSOR for
select
au.id,
au.buy_pv,

case au2.user_rank
when 1 then 0.05
when 2 then 0.07
when 3 then 0.09
when 4 then 0.1
when 5 then 0.13
else 0
end as rankPro
 ,au.parent_id,au2.money_wallet,au.account
from aaa au
left join bbb au2 on au.parent_id = au2.id
where au.rec_status = 0;

DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET no_more_record=1;

open userList;

fetch userList into aid,buyPv,rankPro,parentId,wallet,account;

while no_more_record <> 1 DO

........


fetch userList into aid,buyPv,rankPro,parentId,wallet,account;

end while;

close userList;

end

下面我们来简单说下这个代码,只能简单说,说多了我也不会。

create procedure rec()

begin

......

end

使用 create procedure 来创建一个名为 rec 的存储过程。存储过程的执行内容必须包含在 begin end之间。

DECLARE aid int(11);
DECLARE buyPv decimal(10,2);
DECLARE rankPro decimal(10,2);
DECLARE userRank int;
DECLARE parentId int(11);
DECLARE wallet decimal(10,2);
DECLARE no_more_record int DEFAULT 0;
DECLARE account varchar(32);

这段是声明一系列变量,DECLARE 声明的是局部变量,set 声明的话相当于全局变量。

语法

DECLARE 变量名 变量类型;

declare userList CURSOR for
select
au.id,
au.buy_pv,
case au2.user_rank
when 1 then 0.05
when 2 then 0.07
when 3 then 0.09
when 4 then 0.1
when 5 then 0.13
else 0
end as rankPro,
au.parent_id,
au2.money_wallet,
au.account
from hy_agent_user au
left join hy_agent_user au2 on au.parent_id = au2.id
where au.rec_status = 0;

我们不在这深入的探讨 CURSOR 游标,就说下这个用法就好了。

这段代码的意思就是,声明一个变量 userList,这个变量的值从哪里来呢,就从 CURSOR for 的sql语句来,就这么简单。

DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET no_more_record=1;

这个的意思是,当游标的状态是 02000时,将 no_more_record 变量的值设为 1,SQLSTATE 状态值可以百度一下,02000 直白的说,循环没有数据可取了,结束了。

这个结合下面的 fetch 使用

open userList;

是时候要打开这个userList变量了。

fetch userList into aid,buyPv,rankPro,parentId,wallet,account;

打开变量后,从userList里面取出数据,这个数据来源于上面 CURSOR for 的 sql语句。

这里的变量与sql语句查询的字段,位置对应。

while no_more_record <> 1 DO

进行循环,如果变量 no_more_record 不等于 1时,就继续 DO,也就是说userList这里面还有数据可取。

while 内就是一些插入,更新的逻辑操作了。

有点需要说明,while 内还有一个 fetch 语句,这个的意思是 读取userList里面下一行的数据。

while 完事后,记得 end while;

顺便 close userList;

后话

执行以上的存储过程

call rec();

删除存储过程

drop procedure rec;

 

踩坑记之Javascript中使用for-in从入门到放弃

WHAT

Javascript中,个人常用for循环的两种方式分别是,常规的for以及for-in。

两者在使用输出上大致一样,譬如。

var a = [1,2,3];

for (var i = 0;i < a.length;i++) {
    console.info(a[i]); // 输出 1 2 3
}

for (var ii in a) {
    console.info(a[ii]); // 输出 1 2 3
}

但事实上,for-in的坑总是让人防不胜防。

譬如以下两个例子。

for-in 会把某个类型的原型(prototype)中方法与属性给遍历出来。

<ul id="a">
    <li><a href="" class="b">111</a></li>
    <li><a href="" class="b">222</a></li>
    <li><a href="" class="b">333</a></li>
    <li><a href="" class="b">444</a></li>
    <li><a href="" class="b">555</a></li>
</ul>

<script>
    var lis = document.getElementById("a").getElementsByTagName("li");
    for (var i = 0;i < lis.length;i++) {
        console.info(lis[i].getElementsByTagName("a")[0].className); // 输出 b b b b b
    }

    console.info('---------------');

    for (var ii in lis) {
        console.info(lis[ii].getElementsByTagName("a")[0].className); // 报错了
    }
</script>
Array.prototype.myFunction = function () {
    
}

var a = [
    {name:'a',age:12},
    {name:'b',age:13},
    {name:'c',age:14},
];

for (var i = 0;i < a.length;i++) {
    console.info(a[i].name); // 输出 a b c
}
console.info('---------------');
for (var ii in a) {
    console.info(a[ii].name); // 输出 a b c 空格
}

HOW

如何避免这种坑。

1.请使用常规的for循环来遍历。

2.如遇示例中的坑,又非要装逼用 for-in 时,请增加 hasOwnProperty 避坑。

Array.prototype.myFunction = function () {

}

var a = [
    {name: 'a', age: 12},
    {name: 'b', age: 13},
    {name: 'c', age: 14},
];

for (var i = 0; i < a.length; i++) {
    console.info(a[i].name); // 输出 a b c
}
console.info('---------------');
for (var ii in a) {
    if (!a.hasOwnProperty(ii)) {
        continue;
    }
    console.info(a[ii].name); // 输出 a b c
}

 

[PHP Bug]7.0 以下版本 var_export 返回值丢失精度

WHAT

在处理一个将数组写入文件的功能时,使用了 PHP 内置函数 var_export ,传入第二个参数返回数组的结构,并且将内容写入文件时,发现数组内的值部分预期不一样。

执行代码

$data = [
    "a" => 1.1,
    "b" => 0.48,
];

file_put_contents("2.php",var_export($data,true));

2.php 文件内容

array (
  'a' => 1.1000000000000001,
  'b' => 0.47999999999999998,
)

HOW

经过一番折腾终于把问题解决。

1.将值改为字符串类型

执行代码

$data = [
    "a" => 1.1,
    "b" => 0.48,
    "c" => "0.48",
];

file_put_contents("2.php",var_export($data,true));

2.php 文件内容

array (
  'a' => 1.1000000000000001,
  'b' => 0.47999999999999998,
  'c' => '0.48',
)

2.升级PHP版本 7.1

几经切换版本,发现PHP7.0及以下版本都存在这个问题。

PHP 5.6.31 【存在该缺陷】

PHP 7.0.23 【存在该缺陷】

PHP 7.1.9 【已修复】

附带函数使用说明

mixed var_export ( mixed $expression [, bool $return = false] )

参数1:需要打印结构的变量

参数2:若该函数为 true,将不直接打印输出到页面,而是以返回值的形式返回内容

该函数返回变量的结构信息,与 var_dump 类似,但该函数返回的是合法的 PHP结构代码。

该函数本人常用于输出数组的结构信息,并写入PHP文件中作为缓存使用。

后话

据知情人士超仔表示,这是PHP种浮点型精度截取的问题,并非单一函数的问题。

$f = 0.58;
var_dump(intval($f * 100)); //输出57

使用 round 得出正确结果

$f = 0.58;
var_dump(round($f * 100)); //输出58