鍍金池/ 問(wèn)答/ PHP問(wèn)答
默念 回答

1. 如果只是單純地使用Redis作為cache組件:

'components' => [
    'cache' => [
        'class' => 'yii\redis\Cache',
    ],
],

只需要在配置文件中添加 keyPrefix 屬性即可:

'components' => [
    'cache' => [
        'class' => 'yii\redis\Cache',
        'keyPrefix' => 'webapp:'
    ],
]

2. 如果是直接使用Redis組件:

'components' => [
    'redis' => [
        'class' => 'yii\redis\Connection',
        'hostname' => 'localhost',
        'port' => 6379,
        'database' => 0,
    ],
],

這樣就沒(méi)有辦法實(shí)現(xiàn)自動(dòng)加前綴,只能自己去實(shí)現(xiàn)。

如果是我的話(huà),我會(huì)單獨(dú)寫(xiě)一個(gè)Redis的helper類(lèi),只在這個(gè) Redis helper類(lèi)中調(diào)用 \Yii::$app->redis 組件。

Redis 基礎(chǔ)類(lèi),放一些基礎(chǔ)方法,各個(gè)數(shù)據(jù)類(lèi)型都適用,每個(gè)數(shù)據(jù)類(lèi)型都編寫(xiě)一個(gè)子類(lèi),繼承這個(gè)類(lèi)

class RedisBase
{
    /**
     * 這個(gè)方法中給 key 增加前綴
     * 所有與key相關(guān)的方法都要調(diào)用這個(gè)方法
     * @param $key
     * @return string
     */
    protected static function buildKey($key)
    {
        return \Yii::$app->params['redis.prefix'] . $key;
    }

    /**
     * @return \yii\redis\Connection
     */
    protected static function getRedis()
    {
        return \Yii::$app->redis;
    }

    /**
     * # exists key
     *
     * 檢查key是否存在
     * @param string $key
     * @return bool
     */
    public static function exists($key)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();
        return (bool) $redis->exists($key);
    }

    /**
     * # del key [key2 key3 …]
     *
     * 刪除指定數(shù)據(jù)
     *
     * @param string $key
     * @param bool $strict
     * 是否使用嚴(yán)格模式
     * true: 當(dāng)指定鍵不存在時(shí),返回false
     * false: 當(dāng)指定鍵不存在時(shí),但會(huì)true
     * @return bool
     */
    public static function del($key, $strict = false)
    {
        $key = self::buildKey($key);

        // 非嚴(yán)格模式,當(dāng)指定鍵不存在時(shí),但會(huì)true
        if (! $strict && ! self::exists($key)) return true;

        $redis = self::getRedis();
        return (bool) $redis->del($key);
    }

    /**
     * # expire key seconds
     *
     * 設(shè)置 key在seconds秒后過(guò)期
     *
     * @param $key
     * @param $seconds
     * @return bool
     */
    public static function expire($key, $seconds)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();
        return (bool) $redis->expire($key, $seconds);
    }

    /**
     * # ttl key
     *
     * 大于等于0時(shí),表示剩余過(guò)期秒數(shù)
     * -1 表示key存在,并且沒(méi)有過(guò)期時(shí)間
     * -2 表示key已經(jīng)不存在了
     *
     * 查看key的剩余過(guò)期時(shí)間
     * @param $key
     * @return int
     */
    public static function ttl($key)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();
        return (int) $redis->ttl($key);
    }

    /**
     * # dbsize
     *
     * 當(dāng)前db 鍵的總數(shù)量
     * @return int
     */
    public static function dbSize()
    {
        $redis = self::getRedis();
        return (int) $redis->dbsize();
    }

    // ... 其他redis基礎(chǔ)方法
}

Redis 字符串類(lèi)型的方法,單獨(dú)放置在RedisString類(lèi)中,繼承 RedisBase 方法

class RedisString extends RedisBase
{

    /**
     * # SET key value options
     *
     * 設(shè)置指定 key 的值
     *
     * @param $key
     * @param $value
     * @param array $options
     *
     * EX seconds -- 設(shè)置指定key的過(guò)期時(shí)間,以秒為單位
     * PX milliseconds -- 設(shè)置指定key的過(guò)期時(shí)間,以毫秒為單位
     * NX -- 只有在key不存在的情況下才設(shè)置.
     * XX -- 只有在key存在的情況下才設(shè)置.
     *
     * eg: ['NX', 'EX', '3600']
     *
     * @return bool
     */
    public static function set($key, $value, array $options = [])
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();
        $param = array_merge([$key, $value], $options);
        return (bool) call_user_func_array([$redis, 'set'], $param);
    }

    /**
     * # GET key
     *
     * 獲取指定 key 的值。
     * @param $key
     * @return string
     */
    public static function get($key)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();
        return $redis->get($key);
    }

    // ...其他String類(lèi)型的方法
}

Redis 集合類(lèi)型的方法,單獨(dú)放置在RedisSet類(lèi)中,繼承 RedisBase 方法

class RedisSet extends RedisBase
{
    /**
     * # SADD key member1 [member2]
     *
     * 向集合添加一個(gè)或多個(gè)成員
     *
     * @param $key
     * @param $members
     * @return int 成功添加數(shù)量
     */
    public static function sAdd($key, $members)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();

        // php >= 5.6
        return (int) $redis->sadd($key, ...(array) $members);

        // 通用寫(xiě)法
//        $params = array_merge([$key], (array) $members);
//        return (int) call_user_func_array([$redis, 'sadd'], $params);
    }

    /**
     * # SREM key member1 [member2]
     *
     * 移除集合中一個(gè)或多個(gè)成員
     * @param $key
     * @param $members
     * @return int
     */
    public static function sRem($key, $members)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();

        $params = array_merge([$key], (array) $members);
        return (int) call_user_func_array([$redis, 'srem'], $params);
    }

    /**
     * # SISMEMBER key member
     *
     * 判斷 member 元素是否是集合 key 的成員
     * @param $key
     * @param $member
     * @return bool
     */
    public static function sIsMember($key, $member)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();

        return (bool) $redis->sismember($key, $member);
    }

    /**
     * # SMEMBERS key
     *
     * 返回集合中的所有成員
     * @param $key
     * @return array
     */
    public static function sMembers($key)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();

        return $redis->smembers($key);
    }

    /**
     * # SCARD key
     *
     * 獲取集合的成員數(shù)
     * @param $key
     * @return bool
     */
    public static function sCard($key)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();

        return (int) $redis->scard($key);
    }
    
    // ...其他Set類(lèi)型的方法

Redis 有序集合類(lèi)型的方法,單獨(dú)放置在RedisSortedSet類(lèi)中,繼承 RedisBase 方法

class RedisSortedSet extends RedisBase
{
    /**
     * # ZADD key score1 member1 [score2 member2]
     *
     * 向有序集合添加一個(gè)或多個(gè)成員,或者更新已存在成員的分?jǐn)?shù)
     * @param $key
     * @param array $options
     * [
     *     'value1' => score1,
     *     'value2' => score2,
     *     'value3' => score3,
     * ]
     *
     * @return int
     */
    public static function zAdd($key, array $options)
    {
        $key = self::buildKey($key);
        $redis = self::getRedis();
        $param = [$key];

        foreach ($options as $value => $score) {
            $param[] = $score;
            $param[] = $value;
        }

        return (int) call_user_func_array([$redis, 'zadd'], $param);
    }
    
    // ...其他SortedSet類(lèi)型的方法
}

Redis List類(lèi)型的方法,單獨(dú)放置在RedisList類(lèi)中,繼承 RedisBase 方法

class RedisList extends RedisBase
{
    // ...方法省略
}

Redis Hash類(lèi)型的方法,單獨(dú)放置在RedisHash類(lèi)中,繼承 RedisBase 方法

class RedisHash extends RedisBase
{
    // ...方法省略
}

這樣寫(xiě)的好處:

1.在調(diào)用redis的原始方法前,可以對(duì)數(shù)據(jù)進(jìn)行預(yù)處理
2.后期維護(hù)方便,若想修改,只需要修改這里的方法即可
3.方便添加一些注釋信息
4.這種方法對(duì)IDE更友好,可以直接跳轉(zhuǎn)到這個(gè)類(lèi)中的方法,若處處使用 \Yii::$app->redis,則會(huì)比較難維護(hù)

另外,關(guān)于Redis的一些數(shù)據(jù)類(lèi)型,可以查看Redis學(xué)習(xí)筆記 - 數(shù)據(jù)類(lèi)型與API

我以為 回答

set names utf8

設(shè)置一下編碼試試

笨小蛋 回答

JWT 認(rèn)證應(yīng)該帶上時(shí)間戳(或者其他可以表明請(qǐng)求獨(dú)立性的東西),每次發(fā)送請(qǐng)求的時(shí)候都計(jì)算一次 token,后端會(huì)拿到包含時(shí)間戳的參數(shù)列表和 token,然后根據(jù)它們也計(jì)算一個(gè) token,如果兩邊一致,則 token 驗(yàn)證通過(guò)。

因此 token 本身就是要每次都重新計(jì)算一次的,你在前端存儲(chǔ) token 是沒(méi)有太大價(jià)值的,當(dāng)然可以用于記錄日志,但這并沒(méi)有太多意義。

涼汐 回答

把rbac數(shù)據(jù)整理好之后,用Treeview的js插件去渲染出來(lái)。

選擇 回答

采用直接替換修改字符的方式解決問(wèn)題,這樣就不涉及排序問(wèn)題了

@echo off & color 3a & setlocal enabledelayedexpansion
title 批量替換文件(文件夾)名
echo 此批處理可批量替換本文件所在文件夾下所有文件(文件夾)名。
echo.
set /p str1= 請(qǐng)輸入要替換的文件(文件夾)名字符串(可替換空格):
set /p str2= 請(qǐng)輸入替換后的文件(文件夾)名字符串(去除則直接回車(chē)):
echo.
echo 正在替換文件名……
for /f "delims=" %%a in ('dir /a-d /s /b') do (
if "%%~nxa" neq "%~nx0" (
set "f=%%~na"
set "f=!f:%str1%=%str2%!"
if not exist "%%~dpa!f!%%~xa" ren "%%a" "!f!%%~xa"
)
)
echo 替換文件名完成
echo.
echo 正在替換文件夾名……
:folder
set n=0
for /f "delims=" %%i in ('dir /ad /s /b ^|find "%str1%"') do (
set t=%%~ni
set t=!t:%str1%=%str2%!
if not exist "%%~dpi!t!" ren "%%i" "!t!" 2>nul
set /a n+=1
)
if "!n!" neq "0" goto folder
echo 替換文件夾名完成
pause
心悲涼 回答

你建一張表, 注冊(cè)成功之后存入ip。 下次注冊(cè)的時(shí)候檢測(cè)一下60分鐘內(nèi)是否已經(jīng)注冊(cè), 如果沒(méi)有就可以注冊(cè)。

兔寶寶 回答

分頁(yè)方式應(yīng)由數(shù)據(jù)提供方定義
需要請(qǐng)對(duì)方開(kāi)出對(duì)應(yīng)的分頁(yè)串接方式才行

尐懶貓 回答

瀏覽器緩存問(wèn)題,試試CTRL+F5刷新一下。 還有就是。。修改配置文件后有沒(méi)有 nginx -s reload

還吻 回答

犯了個(gè)非常愚蠢的錯(cuò)誤,因?yàn)槎x的post應(yīng)該合理的用post進(jìn)行請(qǐng)求(laravel是個(gè)好框架:)

1,自己生成6位的短信驗(yàn)證碼,生成一個(gè)rediskey,保存這個(gè)短信驗(yàn)證碼,并給個(gè)有效時(shí)間,這時(shí)也把rediskey告訴客戶(hù)端;
2,調(diào)用短信服務(wù)商api發(fā)送短信,
3,客戶(hù)端提交時(shí),post攜帶rediskey,輸入的短信驗(yàn)證碼,后臺(tái)根據(jù)rediskey調(diào)出redis存儲(chǔ)的短信驗(yàn)證碼與輸入的驗(yàn)證碼比對(duì),通過(guò),刪除這個(gè)rediskey。

假灑脫 回答

提示不是很明顯了嗎, 你不是該紅包發(fā)送者....

瘋子范 回答

編碼問(wèn)題
標(biāo)題欄右鍵,選擇options
clipboard.png

神曲 回答

Connection: Close表示當(dāng)前連接的請(qǐng)求處理完畢后斷掉。不是直接斷開(kāi)


head有2種
1.request的head是給服務(wù)端看的,php通過(guò)get_header()獲取
2.response的head是給客戶(hù)端看的,php通過(guò)header()設(shè)置

所以header('Connection: Close');關(guān)php-fpm什么事

Connection可能不常用
常用的是header('Location:http://xxxxx.com/');
服務(wù)端是沒(méi)有跳轉(zhuǎn)這種行為的,只能通過(guò)head告知客戶(hù)端我要跳轉(zhuǎn)。

要注意的是header不代表結(jié)束執(zhí)行,所以用header進(jìn)行跳轉(zhuǎn)時(shí)要使用exit。
代碼如下:

header('Location:http://xxxxx.com/');exit;
未命名 回答

暫時(shí)沒(méi)有,官方應(yīng)該是為了保護(hù)用戶(hù),所以才移到button上的

前后端分離,項(xiàng)目不大的話(huà)就是直接調(diào)用后端API,只要能提供API,用什么語(yǔ)言無(wú)所謂。

互擼娃 回答

你只需要一個(gè)webstorm IDE就行了