<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>个人随笔</title>
	<atom:link href="/feed" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description></description>
	<lastBuildDate>Mon, 19 Feb 2024 14:17:35 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.1</generator>

<image>
	<url>/wp-content/uploads/2022/01/cropped-截屏2022-01-01-18.57.09-32x32.png</url>
	<title>个人随笔</title>
	<link>/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>copilot使用体验，神奇的代码提示</title>
		<link>/%e8%b5%84%e6%96%99/8995.html</link>
					<comments>/%e8%b5%84%e6%96%99/8995.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Fri, 01 Apr 2022 14:52:20 +0000</pubDate>
				<category><![CDATA[资料]]></category>
		<category><![CDATA[copilot]]></category>
		<category><![CDATA[代码提示]]></category>
		<guid isPermaLink="false">/?p=8995</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-video"><video controls src="/wp-content/uploads/2022/04/copilota½¿c¨a½eai¼c¥a¥cac-aec¤o.mp4"></video></figure>
]]></content:encoded>
					
					<wfw:commentRss>/%e8%b5%84%e6%96%99/8995.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="/wp-content/uploads/2022/04/copilota½¿c¨a½eai¼c¥a¥cac-aec¤o.mp4" length="7382297" type="video/mp4" />

			</item>
		<item>
		<title>代码注释图生成方法</title>
		<link>/%e8%b5%84%e6%96%99/8972.html</link>
					<comments>/%e8%b5%84%e6%96%99/8972.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Thu, 24 Mar 2022 10:35:36 +0000</pubDate>
				<category><![CDATA[资料]]></category>
		<category><![CDATA[Github]]></category>
		<category><![CDATA[代码注释]]></category>
		<category><![CDATA[代码注释图]]></category>
		<category><![CDATA[图片转注释]]></category>
		<guid isPermaLink="false">/?p=8972</guid>

					<description><![CDATA[演示效果 Title 长: 宽: 点击查看效果 点击以下图标进入代码仓库]]></description>
										<content:encoded><![CDATA[
<p><strong>演示效果</strong></p>



<meta charset="UTF-8">
    <title>Title</title>


    <div>
        <input type="file" accept="image/*" id="selector"><br>
        <img decoding="async" src="/wp-content/uploads/2022/01/%E6%88%AA%E5%B1%8F2022-01-01-18.57.09.png" style="width: 200px;height: 200px;" id="previewer">
    </div>
    <div>
        长:<input type="number" min="1" max="2048" id="col" value="72">
        宽:<input type="number" min="1" max="2048" id="row" value="32">
        <button id="convert">点击查看效果</button>
    </div>
    <pre id="content"></pre>


<script>
    window.addEventListener("load",function (){
        var map="MNGmdhyso+/:-.` ".split("");//用字母符号代替颜色
        var selector=document.getElementById("selector");
        var previewer=document.getElementById("previewer");
        var convert=document.getElementById("convert");
        var content=document.getElementById("content");
        selector.addEventListener("change",function (){
            var reader = new FileReader();
            var file=selector.files[0];
            reader.readAsDataURL(file);
            reader.addEventListener("load",function (){
                //图片加载好后，展示出来
                previewer.src=this.result;
            },false);
        },false);
        convert.addEventListener("click",function (){
            //首先取出设置宽高值
            var width=parseInt(document.getElementById("col").value);
            var height=parseInt(document.getElementById("row").value);
            //建一个画板
            var canvas=document.createElement("canvas");
            //设置画板大小
            canvas.width=width;
            canvas.height=height;
            var ctx=canvas.getContext("2d");
            //把选择的图片画到画板上,扑满
            ctx.drawImage(previewer,0,0,width,height);
            //从画板取出象素数据
            var pixels=ctx.getImageData(8,0,width,height).data;
            //根居黎素色值许算出亮度值(彩色转灰色用Y =0.299R + 0.587G + 0.114B)
            var p=0;
            var arr = new Array(width*height);
            for(var i=0,l=width*height*4;i<l;i+=4){//一个颜色是rgba四个数值
                arr[p++]=Math.floor(pixels[i]*0.299+pixels[i+1]*0.587+pixels[i+2]*0.114);
            }
            var p=0;
            var output=new Array((width+1)*height);
            for(var y=0;y<height;y++){
                for (var x=0;x<width;x++){
                    var index=Math.floor(arr[y*width+x]/16);
                    output[p++]=map[index];
                }
                output[p++]="\r\n"; //换行
            }
            content.innerText=output.join("");
        },false);
    },false);
</script>



<p><strong>点击以下图标进入代码仓库</strong></p>



<ul class="wp-block-social-links is-layout-flex wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-github  wp-block-social-link"><a href="https://github.com/LeeYouRan/img2notes" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li></ul>
]]></content:encoded>
					
					<wfw:commentRss>/%e8%b5%84%e6%96%99/8972.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[资料]常用linux命令</title>
		<link>/uncategorized/8964.html</link>
					<comments>/uncategorized/8964.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Tue, 22 Mar 2022 12:58:23 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[基本操作]]></category>
		<category><![CDATA[未分类]]></category>
		<category><![CDATA[资料]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[linux命令]]></category>
		<category><![CDATA[正则]]></category>
		<category><![CDATA[面试]]></category>
		<guid isPermaLink="false">/?p=8964</guid>

					<description><![CDATA[linux也是我们在工作中，在开发中都会用到的。虽然你程序员不需要像运维工程师那样专业，但是基础的linux知 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>linux也是我们在工作中，在开发中都会用到的。虽然你程序员不需要像运维工程师那样专业，但是基础的linux知识你必须要懂，下面来看看总结的命令。</p>



<p>1、删除0字节文件</p>



<pre class="wp-block-code"><code>find -type f -size 0 -exec rm -rf {} \;</code></pre>



<p>2、查看进程<br>按内存从大到小排列</p>



<pre class="wp-block-code"><code>PS -e -o "%C : %p : %z : %a"|sort -k5 -nr</code></pre>



<p>3、按 CPU 利用率从大到小排列</p>



<pre class="wp-block-code"><code>ps -e -o "%C : %p : %z : %a"|sort -nr</code></pre>



<p>4、打印 cache 里的URL</p>



<pre class="wp-block-code"><code>grep -r -a jpg /data/cache/* | strings | grep "http:" | awk -F'http:' '{print "http:"$2;}'</code></pre>



<p>5、查看 http 的并发请求数及其 TCP 连接状态：</p>



<pre class="wp-block-code"><code>netstat -n | awk '/^tcp/ {++S&#91;$NF]} END {for(a in S) print a, S&#91;a]}'</code></pre>



<p>6、 <code>sed -i '/Root/s/no/yes/' /etc/ssh/sshd_config</code> sed 在这个文里 Root 的一行，匹配 Root 一行，将 no 替换成 yes。<br>7、如何杀掉 MySQL 进程</p>



<pre class="wp-block-code"><code>ps aux |grep mysql |grep -v grep  |awk '{print $2}' |xargs kill -9 (从中了解到awk的用途)

killall -TERM mysqld

kill -9 `cat /usr/local/apache2/logs/httpd.pid`   试试查杀进程PID</code></pre>



<p>8、显示运行 3 级别开启的服务:</p>



<pre class="wp-block-code"><code>ls /etc/rc3.d/S* |cut -c 15-   (从中了解到cut的用途，截取数据)</code></pre>



<p>9、如何在编写 SHELL 显示多个信息，用 EOF</p>



<pre class="wp-block-code"><code>cat &lt;&lt; EOF
+--------------------------------------------------------------+
|       === Welcome to Tunoff services ===                |
+--------------------------------------------------------------+
EOF</code></pre>



<p>10、for 的巧用（如给 MySQL 建软链接）</p>



<pre class="wp-block-code"><code>cd /usr/local/mysql/bin
for i in *
do ln /usr/local/mysql/bin/$i /usr/bin/$i
done</code></pre>



<p>11、取 IP 地址</p>



<pre class="wp-block-code"><code>ifconfig eth0 |grep "inet addr:" |awk '{print $2}'| cut -c 6-  
或者
ifconfig | grep 'inet addr:'| grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}'</code></pre>



<p>12、内存的大小:</p>



<pre class="wp-block-code"><code>free -m |grep "Mem" | awk '{print $2}'</code></pre>



<p>13</p>



<pre class="wp-block-code"><code>netstat -an -t | grep ":80" | grep ESTABLISHED | awk '{printf "%s %s\n",$5,$6}' | sort</code></pre>



<p>14、查看 Apache 的并发请求数及其 TCP 连接状态：</p>



<pre class="wp-block-code"><code>netstat -n | awk '/^tcp/ {++S&#91;$NF]} END {for(a in S) print a, S&#91;a]}'</code></pre>



<p>15、因为同事要统计一下服务器下面所有的 jpg 的文件的大小，写了个 SHELL 给他来统计。原来用 xargs 实现，但他一次处理一部分。搞的有多个总和……，下面的命令就能解决。</p>



<pre class="wp-block-code"><code>find / -name *.jpg -exec wc -c {} \;|awk '{print $1}'|awk '{a+=$1}END{print a}'</code></pre>



<p>CPU 的数量（多核算多个CPU，<code>cat /proc/cpuinfo |grep -c processor</code>）越多，系统负载越低，每秒能处理的请求数也越多。</p>



<p>16、CPU负载</p>



<pre class="wp-block-code"><code>cat /proc/loadavg</code></pre>



<p>检查前三个输出值是否超过了系统逻辑 CPU 的4倍。</p>



<p>17、 CPU负载</p>



<pre class="wp-block-code"><code>mpstat 1 1</code></pre>



<p>检查 %idle 是否过低（比如小于5%）。</p>



<p>18、内存空间</p>



<pre class="wp-block-code"><code>free</code></pre>



<p>检查 free 值是否过低，也可以用 <code># cat /proc/meminfo</code></p>



<p>19、SWAP 空间</p>



<pre class="wp-block-code"><code>free</code></pre>



<p>检查 swap used 值是否过高，如果 swap used 值过高，进一步检查 swap 动作是否频繁：</p>



<pre class="wp-block-code"><code>vmstat 1 5</code></pre>



<p>观察 si 和 so 值是否较大</p>



<p>20、磁盘空间</p>



<pre class="wp-block-code"><code>df -h</code></pre>



<p>检查是否有分区使用率（Use%）过高（比如超过90%）如发现某个分区空间接近用尽，可以进入该分区的挂载点，用以下命令找出占用空间最多的文件或目录：</p>



<pre class="wp-block-code"><code>du -cks * | sort -rn | head -n 10</code></pre>



<p>21、磁盘 I/O 负载</p>



<pre class="wp-block-code"><code>iostat -x 1 2</code></pre>



<p>检查I/O使用率（%util）是否超过 100%</p>



<p>22、网络负载</p>



<pre class="wp-block-code"><code>sar -n DEV</code></pre>



<p>检查网络流量（rxbyt/s, txbyt/s）是否过高</p>



<p>23、网络错误</p>



<pre class="wp-block-code"><code>netstat -i</code></pre>



<p>检查是否有网络错误（drop fifo colls carrier），也可以用命令：<code># cat /proc/net/dev</code></p>



<p>24、网络连接数目</p>



<pre class="wp-block-code"><code>netstat -an | grep -E “^(tcp)” | cut -c 68- | sort | uniq -c | sort -n</code></pre>



<p>25、进程总数</p>



<pre class="wp-block-code"><code>ps aux | wc -l</code></pre>



<p>检查进程个数是否正常 (比如超过250)</p>



<p>26、可运行进程数目</p>



<pre class="wp-block-code"><code>vmwtat 1 5</code></pre>



<p>列给出的是可运行进程的数目，检查其是否超过系统逻辑 CPU 的 4 倍</p>



<p>27、进程</p>



<pre class="wp-block-code"><code>top -id 1</code></pre>



<p>观察是否有异常进程出现。</p>



<p>28、网络状态，检查DNS，网关等是否可以正常连通</p>



<p>29、用户</p>



<pre class="wp-block-code"><code>who | wc -l</code></pre>



<p>检查登录用户是否过多 (比如超过50个) 也可以用命令：# uptime。</p>



<p>30、系统日志</p>



<pre class="wp-block-code"><code># cat /var/log/rflogview/*errors</code></pre>



<p>检查是否有异常错误记录 也可以搜寻一些异常关键字，例如：</p>



<pre class="wp-block-code"><code>grep -i error /var/log/messages
grep -i fail /var/log/messages</code></pre>



<p>31、核心日志</p>



<pre class="wp-block-code"><code>dmesg</code></pre>



<p>检查是否有异常错误记录。</p>



<p>32、系统时间</p>



<pre class="wp-block-code"><code>date</code></pre>



<p>检查系统时间是否正确。</p>



<p>33、打开文件数目</p>



<pre class="wp-block-code"><code>lsof | wc -l</code></pre>



<p>检查打开文件总数是否过多。</p>



<p>34、日志</p>



<pre class="wp-block-code"><code># logwatch –print</code></pre>



<p>配置 <code>/etc/log.d/logwatch.conf</code>，将 Mailto 设置为自己的 email 地址，启动 mail 服务(sendmail或者postfix)，这样就可以每天收到日志报告了。<br>缺省 logwatch 只报告昨天的日志，可以用 <code># logwatch –print –range all</code> 获得所有的日志分析结果。<br>可以用 <code># logwatch –print –detail high</code> 获得更具体的日志分析结果(而不仅仅是出错日志)。<br>35、杀掉80端口相关的进程</p>



<pre class="wp-block-code"><code>lsof -i :80|grep -v “ID”|awk ‘{print “kill -9”,$2}’|sh</code></pre>



<p>36、清除僵死进程</p>



<pre class="wp-block-code"><code>ps -eal | awk '{ if ($2 == "Z") {print $4}}' | kill -9</code></pre>



<p>37、tcpdump 抓包，用来防止80端口被人攻击时可以分析数据</p>



<pre class="wp-block-code"><code>tcpdump -c 10000 -i eth0 -n dst port 80 &gt; /root/pkts</code></pre>



<p>38、然后检查IP的重复数并从小到大排序 注意 “-t\ +0” 中间是两个空格</p>



<pre class="wp-block-code"><code># less pkts | awk {'printf $3"\n"'} | cut -d. -f 1-4 | sort | uniq -c | awk {'printf $1" "$2"\n"'} | sort -n -t\ +0</code></pre>



<p>39、查看有多少个活动的 php-cgi 进程</p>



<pre class="wp-block-code"><code>netstat -anp | grep php-cgi | grep ^tcp | wc -l</code></pre>



<p>40、查看系统自启动的服务</p>



<pre class="wp-block-code"><code>chkconfig --list | awk '{if ($5=="3:on") print $1}'</code></pre>



<p>41、kudzu 查看网卡型号</p>



<pre class="wp-block-code"><code>kudzu --probe --class=network</code></pre>



<p>常用正则表达式</p>



<p>1.匹配中文字符的正则表达式： </p>



<p><code>[\u4e00-\u9fa5]</code></p>



<p>评注：匹配中文还真是个头疼的事，有了这个表达式就好办了</p>



<p>2.匹配双字节字符(包括汉字在内)：</p>



<p><code>[^\x00-\xff]</code></p>



<p>评注：可以用来计算字符串的长度（一个双字节字符长度计2，ASCII字符计1）</p>



<p>3.匹配空白行的正则表达式：</p>



<p><code>\n\s*\r</code></p>



<p>评注：可以用来删除空白行</p>



<p>4.匹配 HTML 标记的正则表达式：</p>



<p><code>&lt;(\S*?)[^>]*>.*?&lt;/\1>|&lt;.*? /></code></p>



<p>评注：网上流传的版本太糟糕，上面这个也仅仅能匹配部分，对于复杂的嵌套标记依旧无能为力</p>



<p>5.匹配首尾空白字符的正则表达式：</p>



<p><code>^\s*|\s*$</code></p>



<p>评注：可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等)，非常有用的表达式</p>



<p>6.匹配Email地址的正则表达式：</p>



<pre class="wp-block-code"><code>\w+(&#91;-+.]\w+)*@\w+(&#91;-.]\w+)*\.\w+(&#91;-.]\w+)*</code></pre>



<p>评注：表单验证时很实用</p>



<p>7.匹配网址URL的正则表达式：</p>



<p><code>[a-zA-z]+://[^\s]*</code></p>



<p>评注：网上流传的版本功能很有限，上面这个基本可以满足需求</p>



<p>8.匹配帐号是否合法(字母开头，允许5-16字节，允许字母数字下划线)：</p>



<p><code>^[a-zA-Z][a-zA-Z0-9_]{4,15}$</code></p>



<p>评注：表单验证时很实用</p>



<p>9.匹配国内电话号码：</p>



<p><code>\d{3}-\d{8}|\d{4}-\d{7}</code></p>



<p>评注：匹配形式如 0511-4405222 或 021-87888822</p>



<p>10.匹配腾讯QQ号：</p>



<p><code>[1-9][0-9]{4,}</code></p>



<p>评注：腾讯QQ号从10000开始</p>



<p>11.匹配中国邮政编码：</p>



<p><code>[1-9]\d{5}(?!\d)</code></p>



<p>评注：中国邮政编码为6位数字</p>



<p>12.匹配×××：</p>



<p><code>\d{15}|\d{18}</code></p>



<p>评注：中国的×××为15位或18位</p>



<p>13.匹配ip地址：</p>



<p><code>\d+\.\d+\.\d+\.\d+</code></p>



<p>评注：提取 IP 地址时有用</p>



<p>14.匹配特定数字：</p>



<p><code>^[1-9]\d*$</code>　 　</p>



<p>//匹配正整数</p>



<p><code>^-[1-9]\d*$</code>　</p>



<p>//匹配负整数</p>



<p><code>^-?[1-9]\d*$</code>　　</p>



<p>//匹配整数</p>



<p><code>^[1-9]\d*|0$</code>　</p>



<p>//匹配非负整数（正整数 + 0）</p>



<p><code>^-[1-9]\d*|0$</code>　　</p>



<p>//匹配非正整数（负整数 + 0）</p>



<p><code>^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$</code>　　</p>



<p>//匹配正浮点数</p>



<p><code>^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$</code>　</p>



<p>//匹配负浮点数</p>



<p><code>^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$</code>　</p>



<p>//匹配浮点数</p>



<p><code>^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$</code>　　</p>



<p>//匹配非负浮点数（正浮点数 + 0）</p>



<p><code>^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$</code>　</p>



<p>//匹配非正浮点数（负浮点数 + 0）</p>



<p>评注：处理大量数据时有用，具体应用时注意修正</p>



<p>15.匹配特定字符串：</p>



<p><code>^[A-Za-z]+$</code>　</p>



<p>//匹配由26个英文字母组成的字符串</p>



<p><code>^[A-Z]+$</code>　</p>



<p>//匹配由26个英文字母的大写组成的字符串</p>



<p><code>^[a-z]+$</code>　</p>



<p>//匹配由26个英文字母的小写组成的字符串</p>



<p><code>^[A-Za-z0-9]+$</code>　</p>



<p></p>



<p>//匹配由数字和26个英文字母组成的字符串</p>



<p><code>^\w+$</code>　</p>



<p>//匹配由数字、26个英文字母或者下划线组成的字符串</p>



<p>评注：最基本也是最常用的一些表达式</p>



<p>以上是本文的全部内容，希望对大家的学习有帮助，觉得有用，有需要就支持一下吧</p>
]]></content:encoded>
					
					<wfw:commentRss>/uncategorized/8964.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[避坑指南] Laravel知多少(&#x1f464;个人总结)</title>
		<link>/%e5%90%8e%e5%8f%b0%e6%a1%86%e6%9e%b6/laravel/8954.html</link>
					<comments>/%e5%90%8e%e5%8f%b0%e6%a1%86%e6%9e%b6/laravel/8954.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Sat, 19 Mar 2022 03:54:50 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<category><![CDATA[资料]]></category>
		<category><![CDATA[laravel]]></category>
		<category><![CDATA[laravel知多少]]></category>
		<category><![CDATA[个人总结]]></category>
		<category><![CDATA[避坑指南]]></category>
		<guid isPermaLink="false">/?p=8954</guid>

					<description><![CDATA[面试php的时候总是会被问到，你对你现在用的框架了解多少？有哪些优缺点？如果你用过多个框架的话，还会被用来框架 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>面试php的时候总是会被问到，你对你现在用的框架了解多少？有哪些优缺点？如果你用过多个框架的话，还会被用来框架与框架做对比。</p>



<p>没办法，<strong>面试造航母，上班拧螺丝</strong>。以是程序员的常态。只能好好对待。</p>



<p>目前所在项目用的是Laravel框架，下面是自己个人对这个框架的总结吧，应该还有很多漏掉的，你也可以在留言处做补充。关键还是 要如何去回答 面试官 。希望能对你面试 用Laravel 有些许帮助吧！</p>



<p><strong>laravel框架最大的特点和优秀之处就是集合了php比较新的特点,以及各种各样的设计模式,Ioc模式,依赖注入等</strong></p>



<h2 class="wp-block-heading"><strong>一、Laravel有哪些特点</strong></h2>



<p>1 强大的rest router:用简单的回调函数就可以调用,快速绑定controller和router</p>



<p>2 artisan:命令行工具,很多手动的工作都自动化</p>



<p>3 可继承的模板,简化view的开发和管理</p>



<p>4 blade模板:渲染速度更快</p>



<p>5 ORM操作数据库</p>



<p>6 migration:管理数据库和版本控制</p>



<p>7 测试功能也很强大</p>



<p>8 composer也是亮点</p>



<p>9 队列</p>



<p>10 定时任务等</p>



<h2 class="wp-block-heading"><strong>二、架构模式</strong></h2>



<p>laravel框架是使用了服务组件化的开发模式，由多个服务提供者构成了组件，再由多个组件提供不同的服务，然后是多个服务构成了项目。</p>



<p>服务提供者是应用配置的核心，是通过 register方法中绑定服务到服务容器的。</p>



<h2 class="wp-block-heading"><strong>三、涉及到的设计模式</strong></h2>



<p>laravel框架使用了大量设计模式，使模块之间耦合度很低，服务容器可以方便的扩展框架功能以及编写测试。</p>



<p>1.ORM &#8211; 对象关系映射模式</p>



<p>2 依赖注入与IOC容器 &#8211; 策略模式</p>



<p>3 监听与触发&nbsp; &#8211;&nbsp; 观察者模式</p>



<p>4 门面模式 &#8211; 静态代理</p>



<p>5 注册树模式&nbsp; &#8211;&nbsp; 比如app.php里用到的数组存储</p>



<p>还有其他的，比如注册门面的时候用到单例模式app()-&gt;singleton等。</p>



<h2 class="wp-block-heading"><strong>四、服务方面</strong></h2>



<p>能快速开发出功能，自带各种方便的服务，比如数据验证、队列、缓存、数据迁移、测试、artisan 命令行等等，还有强大的 ORM，artisan强大的命令行工具，实现自动化。</p>



<p>Laravel安全功能有效地利用了盐散列和加密码机制，Bcrypt哈希算法”来创建加密密码。</p>



<h2 class="wp-block-heading"><strong>五、框架的其他知识点</strong></h2>



<p><strong>服务容器：</strong>是一个用于管理类依赖和执行依赖注入的强大工具。其实质是通过构造函数或者某些情况下通过「setter」方法将类依赖注入到类中。&nbsp;</p>



<p><strong>门面：</strong>为应用服务容器中的绑定类提供了一个「静态」接口 ，优点：在维护时能够提供更加易于测试、更加灵活、简明优雅的语法。</p>



<p><strong>契约：</strong>用来规划服务提供者的格式、方法、参数等，给服务提供者规范了一定约束。</p>



<p><strong>反射：</strong>主要用来动态地获取系统中类、实例对象、方法等语言构件的信息，通过发射API函数可以实现对这些语言构件信息的动态获取和动态操作等。主要用在ORM</p>



<p><strong>后期静态绑定：</strong>用于在继承范围内引用静态调用的类，即在类的继承过程中，使用的类不再是当前类，而是调用的类。</p>



<h2 class="wp-block-heading"><strong>六、生命周期</strong></h2>



<p>生命周期我是这样总结的：</p>



<p>入口文件 -&gt; 请求web服务器导入这个文件&nbsp; -&gt; 载入 Composer 生成的自动加载启动核心文件 -&gt; 内核启动(服务提供者启动框架的各种组件) -&gt; 交给路由分发到到（控制器，中间件等）-&gt; 逻辑处理&nbsp; &nbsp;-&gt; 返回结果</p>



<h2 class="wp-block-heading"><strong>七、laravel框架运用到的repository模式的主要思想</strong></h2>



<p>建立一个数据操作代理层，把controller里的数据操作剥离出来，这样做有几个好处：</p>



<p>1 把数据处理逻辑分离使得代码更容易维护</p>



<p>2 数据处理逻辑和业务逻辑分离，可以对这两个代码分别进行测试</p>



<p>3 减少代码重复</p>



<p>4 降低代码出错的几率</p>



<p>5 让controller代码的可读性大大提高&nbsp;</p>



<pre class="wp-block-preformatted">还有其他的，大家可以留言做总结哈！<br><br></pre>



<p><strong>以上是本文的全部内容，希望对大家的学习有帮助，觉得有用，有需要就支持一下吧</strong></p>
]]></content:encoded>
					
					<wfw:commentRss>/%e5%90%8e%e5%8f%b0%e6%a1%86%e6%9e%b6/laravel/8954.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>LaravelV8.6.10</title>
		<link>/%e5%90%8e%e5%8f%b0%e6%a1%86%e6%9e%b6/laravel/8773.html</link>
					<comments>/%e5%90%8e%e5%8f%b0%e6%a1%86%e6%9e%b6/laravel/8773.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Sat, 25 Dec 2021 12:43:38 +0000</pubDate>
				<category><![CDATA[Laravel]]></category>
		<category><![CDATA[Laravel8]]></category>
		<category><![CDATA[MAC]]></category>
		<category><![CDATA[MAMP PRO]]></category>
		<category><![CDATA[NUXT]]></category>
		<category><![CDATA[PhpStorm]]></category>
		<guid isPermaLink="false">/?p=8773</guid>

					<description><![CDATA[LaravelV8.6.10]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Mac下搭建Laravel环境（V8.6.10）</h2>



<p><a rel="noreferrer noopener" href="/goto/cdc2" rel="nofollow" data-type="URL" data-id="https://github.com/LeeYouRan/Server-Laravel" target="_blank">Dem</a><a href="/goto/cdc2" data-type="URL" data-id="https://github.com/LeeYouRan/Server-Laravel" target="_blank" rel="nofollow noreferrer noopener">o</a></p>



<p>1.需要<strong>的安装文件 Mamp Pro &amp; Phpstrom</strong></p>



<p><a rel="noreferrer noopener" href="/goto/sz79" rel="nofollow" data-type="URL" data-id="https://www.digit77.com/macapps/mamp-pro/" target="_blank">MAMP Pro 6.6 fix – 快速安装PHP/MySQL开发环境</a></p>



<p><a rel="noreferrer noopener" href="/goto/h92h" rel="nofollow" data-type="URL" data-id="https://www.jetbrains.com/phpstorm/download/download-thanks.html?platform=mac" target="_blank">PhpStorm 2021.3</a></p>



<p><a href="/goto/1ib6" data-type="URL" data-id="https://product-downloads.atlassian.com/software/sourcetree/ga/Sourcetree_4.1.5_241.zip" target="_blank" rel="nofollow noreferrer noopener">SourceTree 4.1.5</a></p>



<p><a rel="noreferrer noopener" href="/goto/hzn6" rel="nofollow" data-type="URL" data-id="https://www.digit77.com/macapps/navicat-premium/#download-explan" target="_blank">Navicat Premium 15.0.30</a></p>



<p><a href="/goto/0bi5" data-type="URL" data-id="https://www.digit77.com/macapps/another-redis-desktop-manager/#download-explan" target="_blank" rel="nofollow noreferrer noopener">Another Redis Desktop Manager 1.5.0</a>&nbsp;</p>



<p><strong>2.安装Laravel</strong></p>



<p><a rel="noreferrer noopener" href="/goto/b2ff" rel="nofollow" data-type="URL" data-id="https://www.jianshu.com/p/5b0718f1fe93" target="_blank">Mac下安装Laravel</a> </p>



<p><strong>3.配置开发环境</strong></p>



<p><a rel="noreferrer noopener" href="/goto/atqc" rel="nofollow" data-type="URL" data-id="https://blog.csdn.net/weixin_44103733/article/details/113749546" target="_blank">MAMP搭建Laravel虚拟机环境</a></p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-25-20.28.56.png"><img fetchpriority="high" decoding="async" width="2880" height="1800" src="/wp-content/uploads/2021/12/截屏2021-12-25-20.28.56.png" alt="" class="wp-image-8800" srcset="/wp-content/uploads/2021/12/截屏2021-12-25-20.28.56.png 2880w, /wp-content/uploads/2021/12/截屏2021-12-25-20.28.56-300x188.png 300w, /wp-content/uploads/2021/12/截屏2021-12-25-20.28.56-1024x640.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-25-20.28.56-768x480.png 768w, /wp-content/uploads/2021/12/截屏2021-12-25-20.28.56-1536x960.png 1536w, /wp-content/uploads/2021/12/截屏2021-12-25-20.28.56-2048x1280.png 2048w" sizes="(max-width: 2880px) 100vw, 2880px" /></a></figure>



<p><strong>4.伪静态</strong></p>



<p><a rel="noreferrer noopener" href="/goto/4qjo" rel="nofollow" data-type="URL" data-id="https://blog.csdn.net/qq_41150667/article/details/79156465" target="_blank">laravel+Apache 解决路由404问题</a></p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-25-20.34.25.png"><img decoding="async" width="2880" height="1800" src="/wp-content/uploads/2021/12/截屏2021-12-25-20.34.25.png" alt="" class="wp-image-8804" srcset="/wp-content/uploads/2021/12/截屏2021-12-25-20.34.25.png 2880w, /wp-content/uploads/2021/12/截屏2021-12-25-20.34.25-300x188.png 300w, /wp-content/uploads/2021/12/截屏2021-12-25-20.34.25-1024x640.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-25-20.34.25-768x480.png 768w, /wp-content/uploads/2021/12/截屏2021-12-25-20.34.25-1536x960.png 1536w, /wp-content/uploads/2021/12/截屏2021-12-25-20.34.25-2048x1280.png 2048w" sizes="(max-width: 2880px) 100vw, 2880px" /></a></figure>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-25-20.33.43.png"><img decoding="async" width="2880" height="1800" src="/wp-content/uploads/2021/12/截屏2021-12-25-20.33.43.png" alt="" class="wp-image-8805" srcset="/wp-content/uploads/2021/12/截屏2021-12-25-20.33.43.png 2880w, /wp-content/uploads/2021/12/截屏2021-12-25-20.33.43-300x188.png 300w, /wp-content/uploads/2021/12/截屏2021-12-25-20.33.43-1024x640.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-25-20.33.43-768x480.png 768w, /wp-content/uploads/2021/12/截屏2021-12-25-20.33.43-1536x960.png 1536w, /wp-content/uploads/2021/12/截屏2021-12-25-20.33.43-2048x1280.png 2048w" sizes="(max-width: 2880px) 100vw, 2880px" /></a></figure>



<p>.htaccess</p>



<pre class="wp-block-code"><code>&lt;IfModule mod_rewrite.c&gt;  
    &lt;IfModule mod_negotiation.c&gt;  
        Options +FollowSymLinks  
    &lt;/IfModule&gt;  
  
    RewriteEngine On  
  
    # Redirect Trailing Slashes If Not A Folder...  
    RewriteCond %{REQUEST_FILENAME} !-d  
    RewriteRule ^(.*)/$ /$1 &#91;L,R=301]  
  
    # Handle Front Controller...  
    RewriteCond %{REQUEST_FILENAME} !-d  
    RewriteCond %{REQUEST_FILENAME} !-f  
    RewriteRule ^ index.php &#91;L]  
  
    # Handle Authorization Header  
    RewriteCond %{HTTP:Authorization} .  
    RewriteRule .* - &#91;E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]  
&lt;/IfModule&gt;  </code></pre>



<p><strong>5.laravel-modules安装</strong></p>



<p>Larvel-modules会在项目目录下生成modules目录，不会更改框架原有结构，方便后续框架升级，开发代码直接写在modules目录下。</p>



<p>5.1.首先在 Laravel 项目根目录下使用 Composer 安装该扩展包。</p>



<p><br>composer require nwidart/laravel-modules</p>



<p><br>5.2.你可以通过运行如下命令来发布配置文件。</p>



<p><br>php artisan vendor:publish &#8211;provider=&#8221;Nwidart\Modules\LaravelModulesServiceProvider&#8221;</p>



<p>5.3.通过如下命令生成应用的第一个模块。</p>



<p><br>php artisan module:make Admin</p>



<p><br>5.4.要让模块目录中定义的类可以自动加载，需要配置根目录下的composer.json。</p>



<pre class="wp-block-code"><code>{
  "autoload": {
    "psr-4": {
      "App\\": "app/",
      "Modules\\": "Modules/"
    }
  }
}
</code></pre>



<p>5.5.配置完成后运行以下命令让修改生效。</p>



<p><br>composer dump-autoload</p>



<p>5.6.执行域名加模块名（例如：<a href="/goto/o5nf" rel="nofollow">http://demo:8888/admin</a><a rel="noreferrer noopener" href="/goto/74qp" rel="nofollow" target="_blank">）</a></p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-12.14.47.png"><img loading="lazy" decoding="async" width="1300" height="272" src="/wp-content/uploads/2021/12/截屏2021-12-26-12.14.47.png" alt="" class="wp-image-8821" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-12.14.47.png 1300w, /wp-content/uploads/2021/12/截屏2021-12-26-12.14.47-300x63.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-12.14.47-1024x214.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-26-12.14.47-768x161.png 768w" sizes="(max-width: 1300px) 100vw, 1300px" /></a><figcaption><strong>6.laravel8自动生成api文档</strong></figcaption></figure>



<p><a href="/goto/q8h6" data-type="URL" data-id="https://blog.csdn.net/JianShengShuaiest/article/details/120357911" target="_blank" rel="nofollow noreferrer noopener">laravel8自动生成api文档</a></p>



<p><a href="/goto/38a0" data-type="URL" data-id="https://www.jianshu.com/p/56c25d9bb880" target="_blank" rel="nofollow noreferrer noopener">Swagger 使用教程</a></p>



<p><a rel="noreferrer noopener" href="/goto/uhmv" rel="nofollow" data-type="URL" data-id="https://wxiangqian.blog.csdn.net/article/details/81866873" target="_blank">Swagger生成api接口文档</a></p>



<p>添加配置：</p>



<p>路径：resources/views/vendor/l5-swagger/index.blade.php</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-25-17.55.53.png"><img loading="lazy" decoding="async" width="816" height="256" src="/wp-content/uploads/2021/12/截屏2021-12-25-17.55.53.png" alt="" class="wp-image-8781" srcset="/wp-content/uploads/2021/12/截屏2021-12-25-17.55.53.png 816w, /wp-content/uploads/2021/12/截屏2021-12-25-17.55.53-300x94.png 300w, /wp-content/uploads/2021/12/截屏2021-12-25-17.55.53-768x241.png 768w" sizes="(max-width: 816px) 100vw, 816px" /></a></figure>



<p>添加：deepLinking: true</p>



<p></p>



<p>修改默认模块</p>



<p>路径：config/l5-swagger.php</p>



<p>将 <em>base_path(&#8216;app&#8217;),  </em>更改为 base_path(&#8216;Modules&#8217;),</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-25-17.59.12.png"><img loading="lazy" decoding="async" width="1540" height="386" src="/wp-content/uploads/2021/12/截屏2021-12-25-17.59.12.png" alt="" class="wp-image-8783" srcset="/wp-content/uploads/2021/12/截屏2021-12-25-17.59.12.png 1540w, /wp-content/uploads/2021/12/截屏2021-12-25-17.59.12-300x75.png 300w, /wp-content/uploads/2021/12/截屏2021-12-25-17.59.12-1024x257.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-25-17.59.12-768x192.png 768w, /wp-content/uploads/2021/12/截屏2021-12-25-17.59.12-1536x385.png 1536w" sizes="(max-width: 1540px) 100vw, 1540px" /></a></figure>



<pre class="wp-block-code"><code>php artisan l5-swagger:generate</code></pre>



<p>最终效果：</p>



<figure class="wp-block-image size-full is-resized"><a href="/wp-content/uploads/2021/12/截屏2021-12-25-17.53.09-1.png"><img loading="lazy" decoding="async" src="/wp-content/uploads/2021/12/截屏2021-12-25-17.53.09-1.png" alt="" class="wp-image-8782" width="840" height="448" srcset="/wp-content/uploads/2021/12/截屏2021-12-25-17.53.09-1.png 2880w, /wp-content/uploads/2021/12/截屏2021-12-25-17.53.09-1-300x160.png 300w, /wp-content/uploads/2021/12/截屏2021-12-25-17.53.09-1-1024x546.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-25-17.53.09-1-768x410.png 768w, /wp-content/uploads/2021/12/截屏2021-12-25-17.53.09-1-1536x819.png 1536w, /wp-content/uploads/2021/12/截屏2021-12-25-17.53.09-1-2048x1092.png 2048w" sizes="(max-width: 840px) 100vw, 840px" /></a></figure>



<p><strong>7.laravel数据迁移加注释</strong></p>



<p>默认laravel是没有带添加表注释组件的，这里需要安装zedisdog/laravel-schema-extend包<br>该组件包要求使用大于等于5.0版本的laravel</p>



<p>1.拉取组件<br></p>



<pre class="wp-block-code"><code>composer require zedisdog/laravel-schema-extend
</code></pre>



<p>2.申明依赖 （修改config-&gt;app.php-&gt;aliases）<br></p>



<pre class="wp-block-code"><code>'aliases' =&gt; &#91;
    ...
    // 'Schema' =&gt; Illuminate\Support\Facades\Schema::class,
    'Schema'    =&gt; Jialeo\LaravelSchemaExtend\Schema::class,

],
</code></pre>



<p>3.使用（默认创建的migration文件对应的“Schema”还是引用的laravel自带的，需要修改为该组件包的引用）<br></p>



<pre class="wp-block-code"><code> //use Illuminate\\Support\\Facades\\Schema;
 use Jialeo\\LaravelSchemaExtend\\Schema;
Schema::create('users', function (Blueprint $table) {
$table-&gt;comment = '用户表';
 });</code></pre>



<p><strong>8.JWT用户验证</strong></p>



<pre class="wp-block-code"><code>1.安装 jwt-auth。
composer require tymon/jwt-auth 1.*@rc
或者
composer require tymon/jwt-auth:^1.0.2

2.将服务提供程序添加到配置文件中的providers数组，config/app.php如下所示：
'providers' =&gt; &#91;
        ...
        Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
    ]

3.运行以下命令以发布程序包配置文件：
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

4.生成加密密钥:
php artisan jwt:secret

5.修改 config/auth.php
'guards'  =&gt;  &#91;
        'auth_admin' =&gt; &#91;
            'driver' =&gt; 'jwt',
            'provider' =&gt; 'auth_admins'
        ]
    ],
'providers' =&gt; &#91;
        'auth_admins' =&gt; &#91;
            'driver' =&gt; 'eloquent',
            'model' =&gt; Modules\Admin\Models\AuthAdmin::class,
        ]
    ],
6.创建模型
&lt;?php
namespace Modules\Admin\Models;
use DateTimeInterface;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class AuthAdmin extends Authenticatable implements JWTSubject
{
    use Notifiable;
    protected $guard = 'auth_admin';
    protected $hidden = &#91;
        'password'
    ];
    /**
     * @name jwt标识
     * @description
     * @author Winston
     * @date 2021/12/25 3:11
     **/
    public function getJWTIdentifier()
    {
        return $this-&gt;getKey();
    }
    /**
     * @name jwt自定义声明
     * @description
     * @author Winston
     * @date 2021/12/25 3:11
     **/
    public function getJWTCustomClaims()
    {
        return &#91;];
    }
    /**
     * @name 更新时间为null时返回
     * @description
     * @author Winston
     * @date 2021/12/25 3:11
     **/
    public function getUpdatedAtAttribute($value)
    {
        return $value?$value:'';
    }
    /**
     * @name  关联权限组表   多对一
     * @description
     * @author Winston
     * @date 2021/12/25 3:12
     **/
    public function auth_groups()
    {
        return $this-&gt;belongsTo('Modules\Admin\Models\AuthGroup','group_id','id');
    }
    /**
     * @name  关联平台项目表   多对一
     * @description
     * @author Winston
     * @date 2021/12/25 3:12
     **/
    public function auth_projects()
    {
        return $this-&gt;belongsTo('Modules\Admin\Models\AuthProject','project_id','id');
    }
    /**
     * @name 时间格式传唤
     * @description
     * @author Winston
     * @date 2021/12/25 16:15
     **/
    protected function serializeDate(DateTimeInterface $date)
    {
        return $date-&gt;format('Y-m-d H:i:s');
    }
}
7.创建token的Services
&lt;?php
/**
 * @Name 管理员信息服务
 * @Description
 * @Auther Winston
 * @Date 2021/12/25 17:10
 */
namespace Modules\Admin\Services\auth;
use Modules\Admin\Services\BaseApiService;
use Modules\Common\Exceptions\ApiException;
use Modules\Common\Exceptions\MessageData;
use Modules\Common\Exceptions\StatusData;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use Tymon\JWTAuth\Facades\JWTAuth;

class TokenService extends BaseApiService
{
    /**
     * @name 设置token 生成机制
     * @description
     * @author Winston
     * @date 2021/12/25 17:23
     * @return JSON
     **/
    public function __construct()
    {
        \Config::set('auth.defaults.guard', 'auth_admin');
        \Config::set('jwt.ttl', 60);
    }
    /**
     * @name 设置token
     * @description
     * @author Winston
     * @date 2021/12/25 17:24
     * @param data  Array 用户信息
     * @param data.username String 账号
     * @param data.password String 密码$
     * @return JSON | Array
     **/
    public function setToken($data){
        if (! $token = JWTAuth::attempt($data)){
            $this-&gt;apiError('token生成失败');
        }
        return $this-&gt;respondWithToken($token);
    }
    /**
     * @name 刷新token
     * @description
     * @author Winston
     * @date 2021/12/25 17:48
     * @return JSON
     **/
    public function refreshToken()
    {
        try {
            $old_token = JWTAuth::getToken();
            $token = JWTAuth::refresh($old_token);
        }catch (TokenBlacklistedException $e) {
            // 这个时候是老的token被拉到黑名单了
            throw new ApiException(&#91;'status'=&gt;StatusData::TOKEN_ERROR_BLACK,'message'=&gt;MessageData::TOKEN_ERROR_BLACK]);
        }
        return $this-&gt;apiSuccess('', $this-&gt;respondWithToken($token));
    }
    /**
     * @name 管理员信息
     * @description
     * @author Winston
     * @date 2021/12/25 19:11
     * @return Array
     **/
    public function my():Object
    {
        return JWTAuth::parseToken()-&gt;touser();
    }
    /**
     * @name
     * @description
     * @author Winston
     * @date 2021/12/25 9:53
     * @method  GET
     * @param
     * @return JSON
     **/
    public function info()
    {
        $data = $this-&gt;my();
        return $this-&gt;apiSuccess('',&#91;'username'=&gt;$data&#91;'username']]);
    }
    /**
     * @name 退出登录
     * @description
     * @author Winston
     * @date 2021/12/25 19:12
     * @return JSON
     **/
    public function logout()
    {
        JWTAuth::parseToken()-&gt;invalidate();
        return $this-&gt;apiSuccess('退出成功！');
    }

    /**
     * @name 组合token数据
     * @description
     * @author Winston
     * @date 2021/12/25 17:47
     * @return Array
     **/
    protected function respondWithToken($token):Array
    {
        return &#91;
            'token' =&gt; $token,
            'token_type' =&gt; 'bearer',
            'expires_in' =&gt; JWTAuth::factory()-&gt;getTTL() * 60
        ];
    }
}
8.创建登录Services
&lt;?php
/**
 * @Name 用户登录服务
 * @Description
 * @Auther Winston
 * @Date 2021/12/25 16:50
 */
namespace Modules\Admin\Services\auth;
use Modules\Admin\Services\BaseApiService;
use Modules\Admin\Models\AuthAdmin as AuthAdminModel;
class LoginService extends BaseApiService
{
    /**
     * @name 用户登录
     * @description
     * @author Winston
     * @date 2021/12/25 16:53
     * @param data  Array 用户信息
     * @param data.username String 账号
     * @param data.password String 密码
     * @return JSON
     **/
    public function login(array $data){
        if (true == \Auth::guard('auth_admin')-&gt;attempt($data)) {
            $userInfo = AuthAdminModel::where(&#91;'username'=&gt;$data&#91;'username']])-&gt;select('id','username')-&gt;first();
            if($userInfo){
                $user_info = $userInfo-&gt;toArray();
                $user_info&#91;'password'] = $data&#91;'password'];
                $token = (new TokenService())-&gt;setToken($user_info);
                return $this-&gt;apiSuccess('登录成功！',$token);
            }
        }
        $this-&gt;apiError('账号或密码错误！');
    }
}
9.创建中间件
&lt;?php
// +----------------------------------------------------------------------
// | Name: 管理系统 &#91; 为了快速搭建软件应用而生的，希望能够帮助到大家提高开发效率。 ]
// +----------------------------------------------------------------------
// | Copyright: (c) 2020~2021 / All rights reserved.
// +----------------------------------------------------------------------
// | Licensed: 这是一个自由软件，允许对程序代码进行修改，但希望您留下原有的注释。
// +----------------------------------------------------------------------
// | Author: Winston &lt;liyouran@live.com&gt;
// +----------------------------------------------------------------------
// | Version: V1
// +----------------------------------------------------------------------

/**
 * @Name  后台权限验证中间件
 * @Description
 * @Auther Winston
 * @Date 2021/12/25 13:37
 */

namespace Modules\Admin\Http\Middleware;

use Closure;
use Modules\Admin\Services\log\OperationLogService;
use Modules\Common\Exceptions\ApiException;
use Illuminate\Http\Request;
use Modules\Common\Exceptions\MessageData;
use Modules\Common\Exceptions\StatusData;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use Tymon\JWTAuth\Exceptions\TokenBlacklistedException;
use JWTAuth;
use Modules\Admin\Models\Admin as AdminModel;
use Modules\Admin\Models\AuthGroup as AuthGroupModel;
use Modules\Admin\Models\AuthRule as AuthRuleModel;
class AdminApiAuth
{

    public function handle($request, Closure $next)
    {
        \Config::set('auth.defaults.guard', 'auth_admin');
        \Config::set('jwt.ttl', 60);
        $route_data = $request-&gt;route();
        $url = str_replace($route_data-&gt;getAction()&#91;'prefix'] . '/',"",$route_data-&gt;uri);
        $url_arr = &#91;'auth/login/login','auth/index/getMain','auth/index/refreshToken'];
        $api_key = $request-&gt;header('apikey');
        if($api_key != config('admin.api_key')){
            throw new ApiException(&#91;'status'=&gt;StatusData::TOKEN_ERROR_KEY,'message'=&gt;MessageData::TOKEN_ERROR_KEY]);
            return $next();
        }
        if(in_array($url,$url_arr)){
            return $next($request);
        }
        try {
            if (! $user = JWTAuth::parseToken()-&gt;authenticate()) {  //获取到用户数据，并赋值给$user   'msg' =&gt; '用户不存在'
                throw new ApiException(&#91;'status'=&gt;StatusData::TOKEN_ERROR_SET,'message'=&gt;MessageData::TOKEN_ERROR_SET]);
                return $next();
            }

        }catch (TokenBlacklistedException $e) {
            //token无效
            if(in_array($url,&#91;'auth/index/logout'])){
                return $next($request);
            }
            // 这个时候是老的token被拉到黑名单了
            throw new ApiException(&#91;'status'=&gt;StatusData::TOKEN_ERROR_BLACK,'message'=&gt;MessageData::TOKEN_ERROR_BLACK]);
            return $next();
        } catch (TokenExpiredException $e) {
            //token无效
            if(in_array($url,&#91;'auth/index/logout'])){
                return $next($request);
            }
            //token已过期
            throw new ApiException(&#91;'status'=&gt;StatusData::TOKEN_ERROR_EXPIRED,'message'=&gt;MessageData::TOKEN_ERROR_EXPIRED]);
            return $next();
        } catch (TokenInvalidException $e) {
            //token无效
            if(!in_array($url,&#91;'auth/index/refresh','auth/index/logout'])){
                throw new ApiException(&#91;'status'=&gt;StatusData::TOKEN_ERROR_JWT,'message'=&gt;MessageData::TOKEN_ERROR_JWT]);
            }
            return $next();
        } catch (JWTException $e) {
            //'缺少token'
            throw new ApiException(&#91;'status'=&gt;StatusData::TOKEN_ERROR_JTB,'message'=&gt;MessageData::TOKEN_ERROR_JTB]);
            return $next();
        }
        // 写入日志
        (new OperationLogService())-&gt;store($user&#91;'id']);
//        if(!in_array($url,&#91;'auth/index/refresh','auth/index/logout'])){
//            if($user&#91;'id'] != 1 &amp;&amp; $id = AuthRuleModel::where(&#91;'href'=&gt;$url])-&gt;value('id')){
//                $rules = AuthGroupModel::where(&#91;'id'=&gt;$user&#91;'group_id']])-&gt;value('rules');
//                if(!in_array($id,explode('|',$rules))){
//                    throw new ApiException(&#91;'code'=&gt;6781,'msg'=&gt;'您没有权限！']);
//                }
//            }
//        }
        return $next($request);
    }
}
10.laravel登陆模块Demo

<meta charset="utf-8">10.1.修改config/auth.php
增加guards、providers

    'guards' =&gt; &#91;
        'web' =&gt; &#91;
            'driver' =&gt; 'session',
            'provider' =&gt; 'users',
        ],

        'api' =&gt; &#91;
            'driver' =&gt; 'token',
            'provider' =&gt; 'users',
            'hash' =&gt; false,
        ],
        'auth_admin' =&gt; &#91;
            'driver' =&gt; 'jwt',
            'provider' =&gt; 'auth_admins'
        ]
    ],

    'providers' =&gt; &#91;
        'users' =&gt; &#91;
            'driver' =&gt; 'eloquent',
            'model' =&gt; App\Models\User::class,
        ],
        'auth_admins' =&gt; &#91;
            'driver' =&gt; 'eloquent',
            'model' =&gt; Modules\Admin\Models\AuthAdmin::class,
        ]
    ],

<meta charset="utf-8">10.2.增加中间件
\Modules\Admin\Http\Middleware\AdminApiAuth

<meta charset="utf-8">10.3.app\Http\Kernel.php $routeMiddleware中增加中间件
'AdminApiAuth'=&gt; \Modules\Admin\Http\Middleware\AdminApiAuth::class,

<meta charset="utf-8">10.4.Modules\Admin\Config\config.php 定义api_key

return &#91;
'name' =&gt; 'Admin',
'api_key'=&gt;'123456',
'update_pwd'=&gt;'123456',
];

10.5编写基础控制器
&lt;?php
// +----------------------------------------------------------------------
// | Name: 管理系统 &#91; 为了快速搭建软件应用而生的，希望能够帮助到大家提高开发效率。 ]
// +----------------------------------------------------------------------
// | Copyright: (c) 2021~2022 / All rights reserved.
// +----------------------------------------------------------------------
// | Licensed: 这是一个自由软件，允许对程序代码进行修改，但希望您留下原有的注释。
// +----------------------------------------------------------------------
// | Author: Winston &lt;liyouran@live.com&gt;
// +----------------------------------------------------------------------
// | Version: V1
// +----------------------------------------------------------------------

/**
 * @Name 当前模块控制器基类
 * @Description
 * @Auther Winston
 * @Date 2021/12/26 13:10
 */

namespace Modules\Admin\Http\Controllers\v1;


use Modules\Common\Controllers\BaseController;

class BaseApiController extends BaseController
{
    public function __construct(){
        parent::__construct();
    }
}


<meta charset="utf-8">10.6.编写登陆controller
&lt;?php
// +----------------------------------------------------------------------
// | Name: 管理系统 &#91; 为了快速搭建软件应用而生的，希望能够帮助到大家提高开发效率。 ]
// +----------------------------------------------------------------------
// | Copyright: (c) 2021~2022 / All rights reserved.
// +----------------------------------------------------------------------
// | Licensed: 这是一个自由软件，允许对程序代码进行修改，但希望您留下原有的注释。
// +----------------------------------------------------------------------
// | Author: Winston &lt;liyouran@live.com&gt;
// +----------------------------------------------------------------------
// | Version: V1
// +----------------------------------------------------------------------

/**
 * @Name 用户登录
 * @Description
 * @Auther Winston
 * @Date 2021/12/26 13:10
 */

namespace Modules\Admin\Http\Controllers\v1;


use Modules\Admin\Http\Requests\LoginRequest;
use Modules\Admin\Services\auth\LoginService;
class LoginController extends BaseApiController
{
    /**
     * @name 用户登录
     * @description
     * @author Winston
     * @date 2021/12/26 13:10
     * @method  POST
     * @param username String 账号
     * @param password String 密码
     * @return JSON
     **/
    public function login(LoginRequest $request)
    {
        return (new LoginService())-&gt;login($request-&gt;only(&#91;'username','password']));
    }
}

<meta charset="utf-8">10.7.编写登陆request
&lt;?php

namespace Modules\Admin\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class LoginRequest extends FormRequest
{
	/**
     * php artisan module:make-request LoginRequest AuthAdmin
     */


	 /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return &#91;
			'username' =&gt; 'required',
            'password'  =&gt; 'required'
        ];
    }
	public function messages(){
		return &#91;
			'username.required' =&gt; '请输入账号！',
			'password.required' =&gt; '请输入密码！',
		];
	}

}


<meta charset="utf-8">10.8.编写api路由
&lt;?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('auth:api')-&gt;get('/admin', function (Request $request) {
    return $request-&gt;user();
});

Route::group(&#91;"prefix"=&gt;"v1/admin","middleware"=&gt;"AdminApiAuth"],function (){
    //登录
    Route::post('login/login', 'v1\LoginController@login');
});


<meta charset="utf-8">10.9.修改config/databases.php
增加表前缀：prefix =&gt; 'lv_',

<meta charset="utf-8">10.10.修改.env中数据库连接配置
DB_PORT:8889,
DB_DATABASES:laravel,
DB_USERNAME=root,
DB_PASSWORD=root,

<meta charset="utf-8">10.11.连接数据库，创建用户表及数据初始化
USE laravel;
DROP TABLE IF EXISTS `lv_auth_admins`;
CREATE TABLE `lv_auth_admins` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '管理员ID',
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名称',
`phone` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '手机号',
`username` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '账号',
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '密码',
`group_id` int(11) DEFAULT NULL COMMENT '权限组ID',
`project_id` int(11) DEFAULT NULL COMMENT '项目ID',
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '状态:0=禁用,1=启用',
`created_at` timestamp NULL DEFAULT NULL COMMENT '创建时间',
`updated_at` timestamp NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `lv_auth_admins_username_unique` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='管理员表';

INSERT INTO `lv_auth_admins` VALUES (1,'','','admin','$2y$10$gddj.QV7l7OP3I2MpgM9COcCKCBM8SMPq.xe/JrqkOXY3DlnozTP.',1,1,1,'2021-12-26 14:56:02','2021-12-26 14:56:02');
INSERT INTO `lv_auth_admins` VALUES (2,'winston','','winston','$2y$10$NhdagpIFbxK2zAVFeCFEa.wUrtKv.2o4aG4ZZ5W3yYB9epkx/Xm9y',2,1,1,'2021-12-26 14:56:02','2021-12-26 14:56:02');

<meta charset="utf-8">10.12.php artisan l5-swagger:generate更新接口文档

<meta charset="utf-8">10.13.打开http://域名/api/documentation 查看文档及进行测试</code></pre>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-15.26.18.png"><img loading="lazy" decoding="async" width="2880" height="1660" src="/wp-content/uploads/2021/12/截屏2021-12-26-15.26.18.png" alt="" class="wp-image-8826" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-15.26.18.png 2880w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.18-300x173.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.18-1024x590.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.18-768x443.png 768w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.18-1536x885.png 1536w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.18-2048x1180.png 2048w" sizes="(max-width: 2880px) 100vw, 2880px" /></a></figure>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-15.26.46.png"><img loading="lazy" decoding="async" width="2880" height="1484" src="/wp-content/uploads/2021/12/截屏2021-12-26-15.26.46.png" alt="" class="wp-image-8827" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-15.26.46.png 2880w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.46-300x155.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.46-1024x528.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.46-768x396.png 768w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.46-1536x791.png 1536w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.46-2048x1055.png 2048w" sizes="(max-width: 2880px) 100vw, 2880px" /></a></figure>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-15.26.59.png"><img loading="lazy" decoding="async" width="2880" height="354" src="/wp-content/uploads/2021/12/截屏2021-12-26-15.26.59.png" alt="" class="wp-image-8828" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-15.26.59.png 2880w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.59-300x37.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.59-1024x126.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.59-768x94.png 768w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.59-1536x189.png 1536w, /wp-content/uploads/2021/12/截屏2021-12-26-15.26.59-2048x252.png 2048w" sizes="(max-width: 2880px) 100vw, 2880px" /></a></figure>



<p><strong>9.laravel使用redis</strong></p>



<p>首先确认服务器已经安装redis服务,php安装了redis扩展.<br>因为我们在laravel的项目中需要下载laravel的redis扩展</p>



<pre class="wp-block-code"><code>composer require predis/predis

1.打开config/database.php。在redis配置项中增加session的连接</code></pre>



<pre class="wp-block-code"><code>'session' =&gt; &#91;
            'host' =&gt; env('REDIS_HOST', '127.0.0.1'),
            'password' =&gt; env('REDIS_PASSWORD', null),
            'port' =&gt; env('REDIS_PORT', 6379),
            'database' =&gt; 10,
 ],
</code></pre>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-12.03.37.png"><img loading="lazy" decoding="async" width="2006" height="1348" src="/wp-content/uploads/2021/12/截屏2021-12-26-12.03.37.png" alt="" class="wp-image-8813" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-12.03.37.png 2006w, /wp-content/uploads/2021/12/截屏2021-12-26-12.03.37-300x202.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-12.03.37-1024x688.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-26-12.03.37-768x516.png 768w, /wp-content/uploads/2021/12/截屏2021-12-26-12.03.37-1536x1032.png 1536w" sizes="(max-width: 2006px) 100vw, 2006px" /></a><figcaption>2.打开config/session.php ,修改driver配置项,将默认的&#8217;file&#8217;改为&#8217;redis&#8217;；connection配置项填入第一步中配置的redis连接名&#8217;session&#8217;</figcaption></figure>



<pre class="wp-block-code"><code>'driver' =&gt; env('SESSION_DRIVER','redis'),
'connection' =&gt; 'session',
</code></pre>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-12.05.02.png"><img loading="lazy" decoding="async" width="932" height="152" src="/wp-content/uploads/2021/12/截屏2021-12-26-12.05.02.png" alt="" class="wp-image-8815" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-12.05.02.png 932w, /wp-content/uploads/2021/12/截屏2021-12-26-12.05.02-300x49.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-12.05.02-768x125.png 768w" sizes="(max-width: 932px) 100vw, 932px" /></a></figure>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-12.05.12.png"><img loading="lazy" decoding="async" width="854" height="104" src="/wp-content/uploads/2021/12/截屏2021-12-26-12.05.12.png" alt="" class="wp-image-8816" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-12.05.12.png 854w, /wp-content/uploads/2021/12/截屏2021-12-26-12.05.12-300x37.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-12.05.12-768x94.png 768w" sizes="(max-width: 854px) 100vw, 854px" /></a><figcaption>3.修改.env文件,使用redis存取sessoin</figcaption></figure>



<pre class="wp-block-code"><code>SESSION_DRIVER=redis
</code></pre>



<h1 class="wp-block-heading">phpstorm相关配置</h1>



<p>1.phpstorm设置ctrl+鼠标滚轮更改字体大小。</p>



<p>Flie-&gt;Settings-&gt;Editor-&gt;General</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-12.06.12.png"><img loading="lazy" decoding="async" width="1960" height="1410" src="/wp-content/uploads/2021/12/截屏2021-12-26-12.06.12.png" alt="" class="wp-image-8817" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-12.06.12.png 1960w, /wp-content/uploads/2021/12/截屏2021-12-26-12.06.12-300x216.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-12.06.12-1024x737.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-26-12.06.12-768x552.png 768w, /wp-content/uploads/2021/12/截屏2021-12-26-12.06.12-1536x1105.png 1536w" sizes="(max-width: 1960px) 100vw, 1960px" /></a></figure>



<p>Flie-&gt;Settings-&gt;File Encodings</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-12.07.19.png"><img loading="lazy" decoding="async" width="1952" height="1406" src="/wp-content/uploads/2021/12/截屏2021-12-26-12.07.19.png" alt="" class="wp-image-8818" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-12.07.19.png 1952w, /wp-content/uploads/2021/12/截屏2021-12-26-12.07.19-300x216.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-12.07.19-1024x738.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-26-12.07.19-768x553.png 768w, /wp-content/uploads/2021/12/截屏2021-12-26-12.07.19-1536x1106.png 1536w" sizes="(max-width: 1952px) 100vw, 1952px" /></a></figure>



<p>File-&gt;setting&#8211;&gt;Editor&#8211;&gt;File and Code Templates</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-26-12.08.59.png"><img loading="lazy" decoding="async" width="1950" height="1410" src="/wp-content/uploads/2021/12/截屏2021-12-26-12.08.59.png" alt="" class="wp-image-8819" srcset="/wp-content/uploads/2021/12/截屏2021-12-26-12.08.59.png 1950w, /wp-content/uploads/2021/12/截屏2021-12-26-12.08.59-300x217.png 300w, /wp-content/uploads/2021/12/截屏2021-12-26-12.08.59-1024x740.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-26-12.08.59-768x555.png 768w, /wp-content/uploads/2021/12/截屏2021-12-26-12.08.59-1536x1111.png 1536w" sizes="(max-width: 1950px) 100vw, 1950px" /></a></figure>



<pre class="wp-block-code"><code><meta charset="utf-8">// +----------------------------------------------------------------------
// | Name: 管理系统 &#91; 为了快速搭建软件应用而生的，希望能够帮助到大家提高开发效率。 ]
// +----------------------------------------------------------------------
// | Copyright: (c) 2020~2021 / All rights reserved.
// +----------------------------------------------------------------------
// | Licensed: 这是一个自由软件，允许对程序代码进行修改，但希望您留下原有的注释。
// +----------------------------------------------------------------------
// | Author: Winston &lt;liyouran@live.com&gt;
// +----------------------------------------------------------------------
// | Version: V1
// +----------------------------------------------------------------------

/**
 * @Name   
 * @Description
 * @Auther Winston
 * @Date ${DATE} ${HOUR}:${MINUTE}
 */

4.设置方法注释。

File-&gt;setting--&gt;Editor--&gt;live Templates
点击右边加号添加一个Templates Group -&gt; 然后选中添加的Group再次点击加号添加Live Templates，之后点击Edit variables，配置variables。</code></pre>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2021/12/截屏2021-12-25-18.35.49.png"><img loading="lazy" decoding="async" width="2796" height="1652" src="/wp-content/uploads/2021/12/截屏2021-12-25-18.35.49.png" alt="" class="wp-image-8793" srcset="/wp-content/uploads/2021/12/截屏2021-12-25-18.35.49.png 2796w, /wp-content/uploads/2021/12/截屏2021-12-25-18.35.49-300x177.png 300w, /wp-content/uploads/2021/12/截屏2021-12-25-18.35.49-1024x605.png 1024w, /wp-content/uploads/2021/12/截屏2021-12-25-18.35.49-768x454.png 768w, /wp-content/uploads/2021/12/截屏2021-12-25-18.35.49-1536x908.png 1536w, /wp-content/uploads/2021/12/截屏2021-12-25-18.35.49-2048x1210.png 2048w" sizes="(max-width: 2796px) 100vw, 2796px" /></a></figure>



<pre class="wp-block-code"><code>/**
 * @Name 
 * @Author<meta charset="utf-8"> Winston
 * @Description 
 * @Date $date$ $time$ 
 * @Method  GET	
 * @Param 
 * @Return JSON
 **/</code></pre>



<h1 class="wp-block-heading">NUXT文档</h1>



<h2 class="wp-block-heading">nuxt安装</h2>



<p>确保安装了 npx（npx 在 NPM 版本 5.2.0 默认安装了）：</p>



<p>npx create-nuxt-app &lt;项目名&gt;<br>或者用 yarn ：</p>



<p>yarn create nuxt-app &lt;项目名&gt;<br>它会让你进行一些选择:</p>



<p>在集成的服务器端框架之间进行选择:<br>None (Nuxt 默认服务器)<br>Express<br>Koa<br>Hapi<br>Feathers<br>Micro<br>Fastify<br>Adonis(WIP)<br>选择您喜欢的 UI 框架:<br>None (无)<br>Bootstrap<br>Vuetify<br>Bulma<br>Tailwind<br>Element UI<br>Ant Design Vue<br>Buefy<br>iView<br>Tachyons<br>选择您喜欢的测试框架:<br>None (随意添加一个)<br>Jest<br>AVA<br>选择你想要的 Nuxt 模式 (UniversalorSPA)<br>添加axios module以轻松地将 HTTP 请求发送到您的应用程序中。<br>添加EsLint以在保存时代码规范和错误检查您的代码。<br>添加Prettier以在保存时格式化/美化您的代码。<br>当运行完时，它将安装所有依赖项，因此下一步是启动项目:</p>



<p>$ cd<br>$ npm run dev</p>



<p>应用现在运行在 http://localhost:3000/ 上运行。</p>



<p>注意：Nuxt.js 会监听pages目录中的文件更改，因此在添加新页面时无需重新启动应用程序。</p>



<p>了解模板项目的目录结构：目录结构。</p>



<p>从头开始新建项目<br>如果不使用 Nuxt.js 提供的 starter 模板，我们也可以从头开始新建一个 Nuxt.js 应用项目，过程非常简单，只需要1 个文件和 1 个目录。如下所示：</p>



<p>$ mkdir &lt;项目名&gt;<br>$ cd &lt;项目名&gt;</p>



<p><strong>提示:</strong>将&lt;项目名&gt;替换成为你想创建的实际项目名。</p>



<p>新建 package.json 文件<br>package.json文件用来设定如何运行nuxt：</p>



<p>{<br>&#8220;name&#8221;: &#8220;my-app&#8221;,<br>&#8220;scripts&#8221;: {<br>&#8220;dev&#8221;: &#8220;nuxt&#8221;<br>}<br>}</p>



<p>上面的配置使得我们可以通过运行npm run dev来运行nuxt。</p>



<p>安装nuxt<br>一旦package.json创建好， 可以通过以下 npm 命令将nuxt安装至项目中：</p>



<p>npm install &#8211;save nuxt</p>



<p>pages 目录<br>Nuxt.js 会依据pages目录中的所有*.vue文件生成应用的路由配置。</p>



<p>创建pages目录：</p>



<p>mkdir pages</p>



<p>创建我们的第一个页面pages/index.vue：</p>



<p><br>然后启动项目：</p>



<p>$ npm run dev</p>



<p></p>



<h2 class="wp-block-heading">nuxt的生命周期</h2>



<p>服务端生命周期<br>服务器初始化nuxtServerInit<br>创建store/index.js</p>



<p>export const actions = {<br>nuxtServerInit(store,context){<br>console.log(&#8216;nuxtServerInit&#8217;,store,context)<br>}<br>}<br>中间件运行middleware<br>在nuxt.config.js中定义中间件</p>



<p>router:{<br>middleware:&#8217;auth&#8217;<br>}<br>创建中间件文件middleware/auth.js</p>



<p>export default function({store,route,redirect,params,query,req,res}) {<br>console.log(&#8216;middleware&#8217;)<br>}<br>定义在layouts/default.vue中</p>



<p>export default{<br>// middleware:&#8217;auth&#8217; ,<br>middleware(){<br>console.log(&#8216;middleware&#8217;)<br>}<br>}<br>定义在pages/index.vue中</p>



<p>export default{<br>// middleware:&#8217;auth&#8217; ,<br>middleware(){<br>console.log(&#8216;middleware&#8217;)<br>}<br>}<br>验证参数validate</p>



<p>export default{<br>validate(context){<br>console.log(&#8216;validate&#8217;)<br>return true<br>}<br>}<br>异步数据处理asyncData、 fetch</p>



<p>export default{<br>asyncData(context){<br>console.log(&#8216;asyncData&#8217;)<br>return {<br>a:666<br>}<br>},<br>fetch(context){<br>console.log(&#8216;fetch&#8217;)<br>}<br>}<br>开始客户端渲染Render</p>



<p>Vue生命周期 SSR CSR<br>组件创建前beforeCreated</p>



<p>export default{<br>beforeCreated(){<br>console.log(&#8216;beforeCreated&#8217;)<br>}<br>}<br>组件创建后created</p>



<p>export default{<br>created(){<br>console.log(&#8216;created&#8217;)<br>}<br>}<br>运行在客户端<br>组件加载前 beforeMount<br>组件加载完毕 mounted<br>组件更新前 beforeUpdate<br>组件更新完毕 updated<br>组件卸载前 beforeDestroy<br>组件卸载后 destroyed</p>



<h2 class="wp-block-heading">nuxt安装element-ui</h2>



<p>1.安装element-ui<br>npm install element-ui &#8211;save &#8211;registry=https://registry.npm.taobao.org/<br>2.创建文件<br>在项目的根目录下的plugins下创建element-ui.js文件</p>



<p>import Vue from &#8220;vue&#8221;;<br>import ElementUI from &#8220;element-ui&#8221;<br>Vue.use(ElementUI)</p>



<p>import Button from &#8220;element-ui&#8221;<br>Vue.use(Button)<br>3.引入文件<br>在nuxt.config.js中修改如下：</p>



<p>// Global CSS: https://go.nuxtjs.dev/config-css<br>css: [ &#8220;element-ui/lib/theme-chalk/index.css&#8221;],</p>



<p>// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins<br>plugins: [{ src: &#8220;~plugins/element-ui&#8221;,ssr:true,mode:&#8217;server&#8217;//client }],<br>build:{<br>transpile:[&#8216;/^element-ui/&#8217;]<br>}</p>



<h2 class="wp-block-heading">vue监听路由</h2>



<p>watch:{<br>$route:{<br>immediate:true,<br>handler(route){</p>



<pre class="wp-block-code"><code>      }
}</code></pre>



<p>}</p>



<h2 class="wp-block-heading">vue跳转页面</h2>



<p>this.$router.push()</p>



<h2 class="wp-block-heading">Nuxt安装scss(sass)</h2>



<p>1.安装需要用到的loader</p>



<pre class="wp-block-code"><code>npm install --save-dev node-sass@4.12.0 --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
npm install --save-dev sass-loader@7.1.0  --registry=https://registry.npm.taobao.org/
</code></pre>



<p>2.使用</p>



<pre class="wp-block-code"><code>&lt;style lang="scss"&gt;//注意!这里很关键,很多配置成了不编译就是漏了lang="scss"

   @import '../assets/css/index.scss';
   @import '../assets/css/base.scss';
   @import '../assets/css/common.scss';

&lt;/style&gt;
</code></pre>



<h2 class="wp-block-heading">nuxt数据交互</h2>



<p>1.nuxt做数据交互需要依靠&nbsp;<code>@nuxtjs/axios</code><code>@nuxtjs/proxy</code></p>



<pre class="wp-block-code"><code>npm install @nuxtjs/axios  --save --registry=https://registry.npm.taobao.org/
npm install @nuxtjs/proxy --save --registry=https://registry.npm.taobao.org/
</code></pre>



<p>2.在nuxt.config.js中进行配置</p>



<pre class="wp-block-code"><code>modules:&#91;
    '@nuxtjs/axios'
]
</code></pre>



<p>3.使用<code>axios</code></p>



<pre class="wp-block-code"><code>async asyncData({$axios}){
    const res = await $axios({url:'接口'})
}
</code></pre>



<p>4.处理跨域请求， 在nuxt.config.js中进行配置</p>



<pre class="wp-block-code"><code>        axios:{
                proxy:true,//  开启跨域行为
                prefix:'/api/v1/blogApi',  //配置基本的url地址 
          },
        
        proxy:{
                '/api':{
                target:'http://www.mileduo.com/',  //  代理转发的地址
                pathRewrite:{
                // '^/api':''                // 找到地址中的api并替换成空    
                       }
                }
        
          },
</code></pre>



<p>5.定义拦截器，修改nuxt.config.js</p>



<pre class="wp-block-code"><code>plugins:&#91;
    {
        src:'~/plugins/axios',
        'ssr':true     //  服务端渲染
    }
]
</code></pre>



<p>6.书写axios.js</p>



<pre class="wp-block-code"><code>export default function({$axios,redirect,route,store}){
    // 基本配置
    $axios.defaults.timeout = 1000
    $axios.defaults.validateStatus = (status)=&gt;{
            return status &gt;= 200 &amp;&amp; status &lt; 600
    }
    // 请求拦截
    $axios.onRequest(config=&gt;{
        config.headers.token = ''
        return config
    })
    // 相应拦截
    $axios.onResponse(res\=&gt;{
        returnres.data
    })
    // 错误处理
    $axios.onError(error\=&gt;{
        return error
    })
}
</code></pre>



<p>7.Promise返回值</p>



<pre class="wp-block-code"><code>return new Promise(resolve=&gt;{

    resolve(res.data)

})


</code></pre>



<h2 class="wp-block-heading">nuxt中使用vuex</h2>



<p>1.定义</p>



<pre class="wp-block-code"><code>export const state = ()=&gt;({
    typeList : &#91;]
})
export const mutations = {
    SET_TYPE_LIST(state,typeList){
        state.typeList = typeList
    }
 }
export const actions = {
     UPDATE_TYPE_LIST({commit,state},typeList){
            commit('SET_TYPE_LIST',typeList)        
    }
}
export const getters = {
    getTypeList(state){
        return state.typeList
    }
}
</code></pre>



<p>2.使用</p>



<pre class="wp-block-code"><code>// 调用actions   异步请求
this.$store.dispatch('UPDATE_TYPE_LIST',&#91;])

// 调用mutations 
this.$store.commit('SET_TYPE_LIST',&#91;])
</code></pre>



<p>辅助函数</p>



<pre class="wp-block-code"><code> import {mapActions,mapGetters,mapState,mapMutations} from 'vuex'

methods:{
        getTypeList(){
            this.UPDATE_TYPE_LIST(&#91;])
            this.SET_TYPE_LIST(&#91;])
        },
    ...mapActions('user',&#91;'UPDATE_TYPE_LIST'])
    ...mapMutations('user',&#91;'SET_TYPE_LIST'])
},
// 计算属性
computed:{
    ..mapGetters('模块名称，根模块可以不传',&#91;'getTypeList'])
     ..mapState('模块名称，根模块可以不传',&#91;'typeList '])
}
</code></pre>



<h2 class="wp-block-heading">nuxt的token持久化存储</h2>



<p>1.安装cookie-nuiversal-nuxt</p>



<pre class="wp-block-code"><code>npm install cookie-nuiversal-nuxt --save  --registry=https://registry.npm.taobao.org/
</code></pre>



<p>2.配置nuxt.config.js</p>



<pre class="wp-block-code"><code>modules:&#91;
    'cookie-nuiversal-nuxt'
]
</code></pre>



<p>.3.使用</p>



<pre class="wp-block-code"><code>this.$cookies.set('user',&#91;])
this.$cookies.get('user')
this.$cookies.remove('user')
</code></pre>



<p>4.登录跳转</p>



<pre class="wp-block-code"><code>if(!this.$route.query.path || /login/reg/.test(this.$route.query.path)){
    this.$router.replace('/user')
}else{
    this.$router.replace(this.$route.query.path)
}
</code></pre>



<p>5.页面刷新初始化vuex</p>



<pre class="wp-block-code"><code>export const actions = {
    nuxtServerInit(store,{app:{$cookies}}){
        let user = $cookies.get('user')
        user = user?user:''
        store.commit('user/asdds')
    }
}
</code></pre>



<p>6.拦截器定义</p>



<pre class="wp-block-code"><code>$axios.onRequest(config=&gt;{
    config.headers.token = store.state.user.token 
})
</code></pre>



<h2 class="wp-block-heading">nuxt定义错误页面</h2>



<p>在layouts下创建error.vue页面，内容如下。</p>



<pre class="wp-block-code"><code>&lt;template&gt;
    &lt;div&gt;
        &lt;h1 v-if="error.statusCode"&gt;{{error.message}}&lt;/h1&gt;
        &lt;h1 v-else&gt;应用异常&lt;/h1&gt;
        &lt;el-button @click="$router.replace('/')"&gt;返回首页&lt;/el-button&gt;
    &lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
    export default{
        props:&#91;'error']
    }
&lt;/script&gt;
</code></pre>



<h2 class="wp-block-heading">unxt路由跳转过度动画</h2>



<p>1.在/assert目录下建立一个page-transletion.css文件，里面包含过渡动画内容，内容如下：</p>



<pre class="wp-block-code"><code> .page-enter-active, .page-leave-active {
  transition: opacity  .5s;
  }
  .page-enter, .page-leave-active {
  opacity: 0;
  }
</code></pre>



<p>2.在nuxt.config.js中配置：</p>



<pre class="wp-block-code"><code>css: &#91;
'assets/page-transletion.css'
]</code></pre>



<h2 class="wp-block-heading">nuxt自定义loading</h2>



<p>1.修改配置</p>



<pre class="wp-block-code"><code>loading:{color:#399,height:'3px'}
</code></pre>



<pre class="wp-block-code"><code>loading:'~/components/Loading/index.vue'
</code></pre>



<p>2.编写loading组件</p>



<pre class="wp-block-code"><code>&lt;template lang="html"&gt;
  &lt;div class="loading-page" v-if="loading"&gt;
    &lt;p&gt;Loading...&lt;/p&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
  data: () =&gt; ({
    loading: false
  }),
  methods: {
    start () {
      this.loading = true
    },
    finish () {
      this.loading = false
    }
  }
}
&lt;/script&gt;

&lt;style scoped&gt;
.loading-page {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.8);
  text-align: center;
  padding-top: 200px;
  font-size: 30px;
  font-family: sans-serif;
}
&lt;/style&gt;</code></pre>



<h1 class="wp-block-heading">ZSH</h1>



<pre class="wp-block-code"><code>Last login: Sat Dec 25 13:15:03 on console
lee@MacBook-Pro ~ % composer create-project --prefer-dist laravel/laravel laraveldemo
Creating a "laravel/laravel" project at "./laraveldemo"
Installing laravel/laravel (v8.6.10)
  - Installing laravel/laravel (v8.6.10): Extracting archive
Created project in /Users/lee/laraveldemo
&gt; @php -r "file_exists('.env') || copy('.env.example', '.env');"
Loading composer repositories with package information
Updating dependencies
Lock file operations: 110 installs, 0 updates, 0 removals
  - Locking asm89/stack-cors (v2.0.3)
  - Locking brick/math (0.9.3)
  - Locking dflydev/dot-access-data (v3.0.1)
  - Locking doctrine/inflector (2.0.4)
  - Locking doctrine/instantiator (1.4.0)
  - Locking doctrine/lexer (1.2.1)
  - Locking dragonmantank/cron-expression (v3.1.0)
  - Locking egulias/email-validator (2.1.25)
  - Locking facade/flare-client-php (1.9.1)
  - Locking facade/ignition (2.17.3)
  - Locking facade/ignition-contracts (1.0.2)
  - Locking fakerphp/faker (v1.17.0)
  - Locking filp/whoops (2.14.4)
  - Locking fruitcake/laravel-cors (v2.0.4)
  - Locking graham-campbell/result-type (v1.0.4)
  - Locking guzzlehttp/guzzle (7.4.1)
  - Locking guzzlehttp/promises (1.5.1)
  - Locking guzzlehttp/psr7 (2.1.0)
  - Locking hamcrest/hamcrest-php (v2.0.1)
  - Locking laravel/framework (v8.77.1)
  - Locking laravel/sail (v1.12.12)
  - Locking laravel/sanctum (v2.13.0)
  - Locking laravel/serializable-closure (v1.0.5)
  - Locking laravel/tinker (v2.6.3)
  - Locking league/commonmark (2.1.0)
  - Locking league/config (v1.1.1)
  - Locking league/flysystem (1.1.9)
  - Locking league/mime-type-detection (1.9.0)
  - Locking mockery/mockery (1.4.4)
  - Locking monolog/monolog (2.3.5)
  - Locking myclabs/deep-copy (1.10.2)
  - Locking nesbot/carbon (2.55.2)
  - Locking nette/schema (v1.2.2)
  - Locking nette/utils (v3.2.6)
  - Locking nikic/php-parser (v4.13.2)
  - Locking nunomaduro/collision (v5.10.0)
  - Locking opis/closure (3.6.2)
  - Locking phar-io/manifest (2.0.3)
  - Locking phar-io/version (3.1.0)
  - Locking phpdocumentor/reflection-common (2.2.0)
  - Locking phpdocumentor/reflection-docblock (5.3.0)
  - Locking phpdocumentor/type-resolver (1.5.1)
  - Locking phpoption/phpoption (1.8.1)
  - Locking phpspec/prophecy (v1.15.0)
  - Locking phpunit/php-code-coverage (9.2.10)
  - Locking phpunit/php-file-iterator (3.0.6)
  - Locking phpunit/php-invoker (3.1.1)
  - Locking phpunit/php-text-template (2.0.4)
  - Locking phpunit/php-timer (5.0.3)
  - Locking phpunit/phpunit (9.5.10)
  - Locking psr/container (1.1.2)
  - Locking psr/event-dispatcher (1.0.0)
  - Locking psr/http-client (1.0.1)
  - Locking psr/http-factory (1.0.1)
  - Locking psr/http-message (1.0.1)
  - Locking psr/log (2.0.0)
  - Locking psr/simple-cache (1.0.1)
  - Locking psy/psysh (v0.10.12)
  - Locking ralouphie/getallheaders (3.0.3)
  - Locking ramsey/collection (1.2.2)
  - Locking ramsey/uuid (4.2.3)
  - Locking sebastian/cli-parser (1.0.1)
  - Locking sebastian/code-unit (1.0.8)
  - Locking sebastian/code-unit-reverse-lookup (2.0.3)
  - Locking sebastian/comparator (4.0.6)
  - Locking sebastian/complexity (2.0.2)
  - Locking sebastian/diff (4.0.4)
  - Locking sebastian/environment (5.1.3)
  - Locking sebastian/exporter (4.0.4)
  - Locking sebastian/global-state (5.0.3)
  - Locking sebastian/lines-of-code (1.0.3)
  - Locking sebastian/object-enumerator (4.0.4)
  - Locking sebastian/object-reflector (2.0.4)
  - Locking sebastian/recursion-context (4.0.4)
  - Locking sebastian/resource-operations (3.0.3)
  - Locking sebastian/type (2.3.4)
  - Locking sebastian/version (3.0.2)
  - Locking swiftmailer/swiftmailer (v6.3.0)
  - Locking symfony/console (v5.4.1)
  - Locking symfony/css-selector (v6.0.1)
  - Locking symfony/deprecation-contracts (v3.0.0)
  - Locking symfony/error-handler (v5.4.1)
  - Locking symfony/event-dispatcher (v6.0.1)
  - Locking symfony/event-dispatcher-contracts (v3.0.0)
  - Locking symfony/finder (v5.4.0)
  - Locking symfony/http-foundation (v5.4.1)
  - Locking symfony/http-kernel (v5.4.1)
  - Locking symfony/mime (v5.4.0)
  - Locking symfony/polyfill-ctype (v1.23.0)
  - Locking symfony/polyfill-iconv (v1.23.0)
  - Locking symfony/polyfill-intl-grapheme (v1.23.1)
  - Locking symfony/polyfill-intl-idn (v1.23.0)
  - Locking symfony/polyfill-intl-normalizer (v1.23.0)
  - Locking symfony/polyfill-mbstring (v1.23.1)
  - Locking symfony/polyfill-php72 (v1.23.0)
  - Locking symfony/polyfill-php73 (v1.23.0)
  - Locking symfony/polyfill-php80 (v1.23.1)
  - Locking symfony/polyfill-php81 (v1.23.0)
  - Locking symfony/process (v5.4.0)
  - Locking symfony/routing (v5.4.0)
  - Locking symfony/service-contracts (v2.4.1)
  - Locking symfony/string (v6.0.1)
  - Locking symfony/translation (v6.0.1)
  - Locking symfony/translation-contracts (v3.0.0)
  - Locking symfony/var-dumper (v5.4.1)
  - Locking theseer/tokenizer (1.2.1)
  - Locking tijsverkoyen/css-to-inline-styles (2.2.4)
  - Locking vlucas/phpdotenv (v5.4.1)
  - Locking voku/portable-ascii (1.5.6)
  - Locking webmozart/assert (1.10.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 110 installs, 0 updates, 0 removals
  - Installing doctrine/inflector (2.0.4): Extracting archive
  - Installing doctrine/lexer (1.2.1): Extracting archive
  - Installing symfony/polyfill-ctype (v1.23.0): Extracting archive
  - Installing webmozart/assert (1.10.0): Extracting archive
  - Installing dragonmantank/cron-expression (v3.1.0): Extracting archive
  - Installing symfony/polyfill-php80 (v1.23.1): Extracting archive
  - Installing symfony/polyfill-mbstring (v1.23.1): Extracting archive
  - Installing symfony/var-dumper (v5.4.1): Extracting archive
  - Installing symfony/polyfill-intl-normalizer (v1.23.0): Extracting archive
  - Installing symfony/polyfill-intl-grapheme (v1.23.1): Extracting archive
  - Installing symfony/string (v6.0.1): Extracting archive
  - Installing psr/container (1.1.2): Extracting archive
  - Installing symfony/service-contracts (v2.4.1): Extracting archive
  - Installing symfony/polyfill-php73 (v1.23.0): Extracting archive
  - Installing symfony/deprecation-contracts (v3.0.0): Extracting archive
  - Installing symfony/console (v5.4.1): Extracting archive
  - Installing psr/log (2.0.0): Extracting archive
  - Installing monolog/monolog (2.3.5): Extracting archive
  - Installing voku/portable-ascii (1.5.6): Extracting archive
  - Installing phpoption/phpoption (1.8.1): Extracting archive
  - Installing graham-campbell/result-type (v1.0.4): Extracting archive
  - Installing vlucas/phpdotenv (v5.4.1): Extracting archive
  - Installing symfony/css-selector (v6.0.1): Extracting archive
  - Installing tijsverkoyen/css-to-inline-styles (2.2.4): Extracting archive
  - Installing symfony/routing (v5.4.0): Extracting archive
  - Installing symfony/process (v5.4.0): Extracting archive
  - Installing symfony/polyfill-php72 (v1.23.0): Extracting archive
  - Installing symfony/polyfill-intl-idn (v1.23.0): Extracting archive
  - Installing symfony/mime (v5.4.0): Extracting archive
  - Installing symfony/http-foundation (v5.4.1): Extracting archive
  - Installing psr/event-dispatcher (1.0.0): Extracting archive
  - Installing symfony/event-dispatcher-contracts (v3.0.0): Extracting archive
  - Installing symfony/event-dispatcher (v6.0.1): Extracting archive
  - Installing symfony/error-handler (v5.4.1): Extracting archive
  - Installing symfony/http-kernel (v5.4.1): Extracting archive
  - Installing symfony/finder (v5.4.0): Extracting archive
  - Installing symfony/polyfill-iconv (v1.23.0): Extracting archive
  - Installing egulias/email-validator (2.1.25): Extracting archive
  - Installing swiftmailer/swiftmailer (v6.3.0): Extracting archive
  - Installing symfony/polyfill-php81 (v1.23.0): Extracting archive
  - Installing ramsey/collection (1.2.2): Extracting archive
  - Installing brick/math (0.9.3): Extracting archive
  - Installing ramsey/uuid (4.2.3): Extracting archive
  - Installing psr/simple-cache (1.0.1): Extracting archive
  - Installing opis/closure (3.6.2): Extracting archive
  - Installing symfony/translation-contracts (v3.0.0): Extracting archive
  - Installing symfony/translation (v6.0.1): Extracting archive
  - Installing nesbot/carbon (2.55.2): Extracting archive
  - Installing league/mime-type-detection (1.9.0): Extracting archive
  - Installing league/flysystem (1.1.9): Extracting archive
  - Installing nette/utils (v3.2.6): Extracting archive
  - Installing nette/schema (v1.2.2): Extracting archive
  - Installing dflydev/dot-access-data (v3.0.1): Extracting archive
  - Installing league/config (v1.1.1): Extracting archive
  - Installing league/commonmark (2.1.0): Extracting archive
  - Installing laravel/serializable-closure (v1.0.5): Extracting archive
  - Installing laravel/framework (v8.77.1): Extracting archive
  - Installing facade/ignition-contracts (1.0.2): Extracting archive
  - Installing facade/flare-client-php (1.9.1): Extracting archive
  - Installing facade/ignition (2.17.3): Extracting archive
  - Installing fakerphp/faker (v1.17.0): Extracting archive
  - Installing asm89/stack-cors (v2.0.3): Extracting archive
  - Installing fruitcake/laravel-cors (v2.0.4): Extracting archive
  - Installing psr/http-message (1.0.1): Extracting archive
  - Installing psr/http-client (1.0.1): Extracting archive
  - Installing ralouphie/getallheaders (3.0.3): Extracting archive
  - Installing psr/http-factory (1.0.1): Extracting archive
  - Installing guzzlehttp/psr7 (2.1.0): Extracting archive
  - Installing guzzlehttp/promises (1.5.1): Extracting archive
  - Installing guzzlehttp/guzzle (7.4.1): Extracting archive
  - Installing laravel/sail (v1.12.12): Extracting archive
  - Installing laravel/sanctum (v2.13.0): Extracting archive
  - Installing nikic/php-parser (v4.13.2): Extracting archive
  - Installing psy/psysh (v0.10.12): Extracting archive
  - Installing laravel/tinker (v2.6.3): Extracting archive
  - Installing hamcrest/hamcrest-php (v2.0.1): Extracting archive
  - Installing mockery/mockery (1.4.4): Extracting archive
  - Installing filp/whoops (2.14.4): Extracting archive
  - Installing nunomaduro/collision (v5.10.0): Extracting archive
  - Installing phpdocumentor/reflection-common (2.2.0): Extracting archive
  - Installing phpdocumentor/type-resolver (1.5.1): Extracting archive
  - Installing phpdocumentor/reflection-docblock (5.3.0): Extracting archive
  - Installing sebastian/version (3.0.2): Extracting archive
  - Installing sebastian/type (2.3.4): Extracting archive
  - Installing sebastian/resource-operations (3.0.3): Extracting archive
  - Installing sebastian/recursion-context (4.0.4): Extracting archive
  - Installing sebastian/object-reflector (2.0.4): Extracting archive
  - Installing sebastian/object-enumerator (4.0.4): Extracting archive
  - Installing sebastian/global-state (5.0.3): Extracting archive
  - Installing sebastian/exporter (4.0.4): Extracting archive
  - Installing sebastian/environment (5.1.3): Extracting archive
  - Installing sebastian/diff (4.0.4): Extracting archive
  - Installing sebastian/comparator (4.0.6): Extracting archive
  - Installing sebastian/code-unit (1.0.8): Extracting archive
  - Installing sebastian/cli-parser (1.0.1): Extracting archive
  - Installing phpunit/php-timer (5.0.3): Extracting archive
  - Installing phpunit/php-text-template (2.0.4): Extracting archive
  - Installing phpunit/php-invoker (3.1.1): Extracting archive
  - Installing phpunit/php-file-iterator (3.0.6): Extracting archive
  - Installing theseer/tokenizer (1.2.1): Extracting archive
  - Installing sebastian/lines-of-code (1.0.3): Extracting archive
  - Installing sebastian/complexity (2.0.2): Extracting archive
  - Installing sebastian/code-unit-reverse-lookup (2.0.3): Extracting archive
  - Installing phpunit/php-code-coverage (9.2.10): Extracting archive
  - Installing doctrine/instantiator (1.4.0): Extracting archive
  - Installing phpspec/prophecy (v1.15.0): Extracting archive
  - Installing phar-io/version (3.1.0): Extracting archive
  - Installing phar-io/manifest (2.0.3): Extracting archive
  - Installing myclabs/deep-copy (1.10.2): Extracting archive
  - Installing phpunit/phpunit (9.5.10): Extracting archive
63 package suggestions were added by new dependencies, use `composer suggest` to see details.
Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
Generating optimized autoload files
&gt; Illuminate\Foundation\ComposerScripts::postAutoloadDump
&gt; @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
77 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
&gt; @php artisan vendor:publish --tag=laravel-assets --ansi --force
No publishable resources for tag &#91;laravel-assets].
Publishing complete.
&gt; @php artisan key:generate --ansi
Application key set successfully.
lee@MacBook-Pro ~ % ls
Applications			Parallels
Desktop				Pictures
Documents			Public
Downloads			Sites
Library				Sunlogin Files
Movies				Virtual Machines.localized
Music				laraveldemo
OneDrive			sensors
lee@MacBook-Pro ~ % mv laraveldemo ./Downloads 
lee@MacBook-Pro ~ % ll
zsh: command not found: ll
lee@MacBook-Pro ~ % ls
Applications			Parallels
Desktop				Pictures
Documents			Public
Downloads			Sites
Library				Sunlogin Files
Movies				Virtual Machines.localized
Music				sensors
OneDrive
lee@MacBook-Pro ~ % ls 
Applications			Parallels
Desktop				Pictures
Documents			Public
Downloads			Sites
Library				Sunlogin Files
Movies				Virtual Machines.localized
Music				sensors
OneDrive
lee@MacBook-Pro ~ % cd Sites 
lee@MacBook-Pro Sites % ls
laraveldemo	localhost
lee@MacBook-Pro Sites % cd laraveldemo 
lee@MacBook-Pro laraveldemo % composer require nwidart/laravel-modules
Using version ^8.2 for nwidart/laravel-modules
./composer.json has been updated
Running composer update nwidart/laravel-modules
Loading composer repositories with package information
https://repo.packagist.org/ could not be fully loaded (curl error 28 while downloading https://repo.packagist.org/packages.json: Operation timed out after 10000 milliseconds with 0 out of 0 bytes received), package information was loaded from the local cache and may be out of date
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking nwidart/laravel-modules (8.2.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing nwidart/laravel-modules (8.2.0): Extracting archive
Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
Generating optimized autoload files
&gt; Illuminate\Foundation\ComposerScripts::postAutoloadDump
&gt; @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Discovered Package: nwidart/laravel-modules
Package manifest generated successfully.
78 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
&gt; @php artisan vendor:publish --tag=laravel-assets --ansi --force
No publishable resources for tag &#91;laravel-assets].
Publishing complete.
lee@MacBook-Pro laraveldemo % php artisan vendor:publish --provider="Nwidart\Modules\LaravelModulesServiceProvider"

Copied File &#91;/vendor/nwidart/laravel-modules/config/config.php] To &#91;/config/modules.php]
Publishing complete.
lee@MacBook-Pro laraveldemo % php artisan module:make Admin
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/module.json
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Routes/web.php
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Routes/api.php
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Resources/views/index.blade.php
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Resources/views/layouts/master.blade.php
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Config/config.php
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/composer.json
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Resources/assets/js/app.js
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Resources/assets/sass/app.scss
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/webpack.mix.js
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/package.json
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Database/Seeders/AdminDatabaseSeeder.php
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Providers/AdminServiceProvider.php
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Providers/RouteServiceProvider.php
Created : /Users/lee/Sites/laraveldemo/Modules/Admin/Http/Controllers/AdminController.php
Module &#91;Admin] created successfully.
lee@MacBook-Pro laraveldemo % composer dump-autoload
Generating optimized autoload files
&gt; Illuminate\Foundation\ComposerScripts::postAutoloadDump
&gt; @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Discovered Package: nwidart/laravel-modules
Package manifest generated successfully.
Generated optimized autoload files containing 5099 classes
lee@MacBook-Pro laraveldemo % composer require "darkaonline/l5-swagger"
Using version ^8.0 for darkaonline/l5-swagger
./composer.json has been updated
Running composer update darkaonline/l5-swagger
Loading composer repositories with package information
Updating dependencies
Lock file operations: 6 installs, 0 updates, 0 removals
  - Locking darkaonline/l5-swagger (8.0.9)
  - Locking doctrine/annotations (1.13.2)
  - Locking psr/cache (3.0.0)
  - Locking swagger-api/swagger-ui (v3.52.5)
  - Locking symfony/yaml (v5.4.0)
  - Locking zircote/swagger-php (3.3.3)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 6 installs, 0 updates, 0 removals
  - Installing symfony/yaml (v5.4.0): Extracting archive
  - Installing psr/cache (3.0.0): Extracting archive
  - Installing doctrine/annotations (1.13.2): Extracting archive
  - Installing zircote/swagger-php (3.3.3): Extracting archive
  - Installing swagger-api/swagger-ui (v3.52.5): Extracting archive
  - Installing darkaonline/l5-swagger (8.0.9): Extracting archive
Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
Generating optimized autoload files
&gt; Illuminate\Foundation\ComposerScripts::postAutoloadDump
&gt; @php artisan package:discover --ansi
Discovered Package: darkaonline/l5-swagger
Discovered Package: facade/ignition
Discovered Package: fruitcake/laravel-cors
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Discovered Package: nwidart/laravel-modules
Package manifest generated successfully.
80 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
&gt; @php artisan vendor:publish --tag=laravel-assets --ansi --force
No publishable resources for tag &#91;laravel-assets].
Publishing complete.
lee@MacBook-Pro laraveldemo % php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"
Copied File &#91;/vendor/darkaonline/l5-swagger/config/l5-swagger.php] To &#91;/config/l5-swagger.php]
Copied Directory &#91;/vendor/darkaonline/l5-swagger/resources/views] To &#91;/resources/views/vendor/l5-swagger]
Publishing complete.
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default

   ErrorException 

  Required @OA\Info() not found

  at vendor/zircote/swagger-php/src/Logger.php:40
     36▕         $this-&gt;log = function ($entry, $type) {
     37▕             if ($entry instanceof Exception) {
     38▕                 $entry = $entry-&gt;getMessage();
     39▕             }
  ➜  40▕             trigger_error($entry, $type);
     41▕         };
     42▕     }
     43▕ 
     44▕     public static function getInstance(): Logger

      +27 vendor frames 
  28  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default

   ErrorException 

  Required @OA\Info() not found

  at vendor/zircote/swagger-php/src/Logger.php:40
     36▕         $this-&gt;log = function ($entry, $type) {
     37▕             if ($entry instanceof Exception) {
     38▕                 $entry = $entry-&gt;getMessage();
     39▕             }
  ➜  40▕             trigger_error($entry, $type);
     41▕         };
     42▕     }
     43▕ 
     44▕     public static function getInstance(): Logger

      +27 vendor frames 
  28  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default

   ErrorException 

  Required @OA\Info() not found

  at vendor/zircote/swagger-php/src/Logger.php:40
     36▕         $this-&gt;log = function ($entry, $type) {
     37▕             if ($entry instanceof Exception) {
     38▕                 $entry = $entry-&gt;getMessage();
     39▕             }
  ➜  40▕             trigger_error($entry, $type);
     41▕         };
     42▕     }
     43▕ 
     44▕     public static function getInstance(): Logger

      +27 vendor frames 
  28  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default

   ErrorException 

  Required @OA\PathItem() not found

  at vendor/zircote/swagger-php/src/Logger.php:40
     36▕         $this-&gt;log = function ($entry, $type) {
     37▕             if ($entry instanceof Exception) {
     38▕                 $entry = $entry-&gt;getMessage();
     39▕             }
  ➜  40▕             trigger_error($entry, $type);
     41▕         };
     42▕     }
     43▕ 
     44▕     public static function getInstance(): Logger

      +27 vendor frames 
  28  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default
lee@MacBook-Pro laraveldemo % php artisan vendor:publish --provider="Nwidart\Modules\LaravelModulesServiceProvider"

Publishing complete.
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default
lee@MacBook-Pro laraveldemo % php artisan
Laravel Framework 8.77.1

Usage:
  command &#91;options] &#91;arguments]

Options:
  -h, --help            Display help for the given command. When no command is given display help for the list command
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi|--no-ansi  Force (or disable --no-ansi) ANSI output
  -n, --no-interaction  Do not ask any interactive question
      --env&#91;=ENV]       The environment the command should run under
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  clear-compiled              Remove the compiled class file
  completion                  Dump the shell completion script
  db                          Start a new database CLI session
  down                        Put the application into maintenance / demo mode
  env                         Display the current framework environment
  help                        Display help for a command
  inspire                     Display an inspiring quote
  list                        List commands
  migrate                     Run the database migrations
  optimize                    Cache the framework bootstrap files
  serve                       Serve the application on the PHP development server
  test                        Run the application tests
  tinker                      Interact with your application
  up                          Bring the application out of maintenance mode
 auth
  auth:clear-resets           Flush expired password reset tokens
 cache
  cache:clear                 Flush the application cache
  cache:forget                Remove an item from the cache
  cache:table                 Create a migration for the cache database table
 config
  config:cache                Create a cache file for faster configuration loading
  config:clear                Remove the configuration cache file
 db
  db:seed                     Seed the database with records
  db:wipe                     Drop all tables, views, and types
 event
  event:cache                 Discover and cache the application's events and listeners
  event:clear                 Clear all cached events and listeners
  event:generate              Generate the missing events and listeners based on registration
  event:list                  List the application's events and listeners
 key
  key:generate                Set the application key
 l5-swagger
  l5-swagger:generate         Regenerate docs
 make
  make:cast                   Create a new custom Eloquent cast class
  make:channel                Create a new channel class
  make:command                Create a new Artisan command
  make:component              Create a new view component class
  make:controller             Create a new controller class
  make:event                  Create a new event class
  make:exception              Create a new custom exception class
  make:factory                Create a new model factory
  make:job                    Create a new job class
  make:listener               Create a new event listener class
  make:mail                   Create a new email class
  make:middleware             Create a new middleware class
  make:migration              Create a new migration file
  make:model                  Create a new Eloquent model class
  make:notification           Create a new notification class
  make:observer               Create a new observer class
  make:policy                 Create a new policy class
  make:provider               Create a new service provider class
  make:request                Create a new form request class
  make:resource               Create a new resource
  make:rule                   Create a new validation rule
  make:seeder                 Create a new seeder class
  make:test                   Create a new test class
 migrate
  migrate:fresh               Drop all tables and re-run all migrations
  migrate:install             Create the migration repository
  migrate:refresh             Reset and re-run all migrations
  migrate:reset               Rollback all database migrations
  migrate:rollback            Rollback the last database migration
  migrate:status              Show the status of each migration
 model
  model:prune                 Prune models that are no longer needed
 module
  module:delete               Delete a module from the application
  module:disable              Disable the specified module.
  module:dump                 Dump-autoload the specified module or for all module.
  module:enable               Enable the specified module.
  module:install              Install the specified module by given package name (vendor/name).
  module:list                 Show list of all modules.
  module:make                 Create a new module.
  module:make-command         Generate new Artisan command for the specified module.
  module:make-controller      Generate new restful controller for the specified module.
  module:make-event           Create a new event class for the specified module
  module:make-factory         Create a new model factory for the specified module.
  module:make-job             Create a new job class for the specified module
  module:make-listener        Create a new event listener class for the specified module
  module:make-mail            Create a new email class for the specified module
  module:make-middleware      Create a new middleware class for the specified module.
  module:make-migration       Create a new migration for the specified module.
  module:make-model           Create a new model for the specified module.
  module:make-notification    Create a new notification class for the specified module.
  module:make-policy          Create a new policy class for the specified module.
  module:make-provider        Create a new service provider class for the specified module.
  module:make-request         Create a new form request class for the specified module.
  module:make-resource        Create a new resource class for the specified module.
  module:make-rule            Create a new validation rule for the specified module.
  module:make-seed            Generate new seeder for the specified module.
  module:make-test            Create a new test class for the specified module.
  module:migrate              Migrate the migrations from the specified module or from all modules.
  module:migrate-refresh      Rollback &amp; re-migrate the modules migrations.
  module:migrate-reset        Reset the modules migrations.
  module:migrate-rollback     Rollback the modules migrations.
  module:migrate-status       Status for all module migrations
  module:publish              Publish a module's assets to the application
  module:publish-config       Publish a module's config files to the application
  module:publish-migration    Publish a module's migrations to the application
  module:publish-translation  Publish a module's translations to the application
  module:route-provider       Create a new route service provider for the specified module.
  module:seed                 Run database seeder from the specified module or from all modules.
  module:setup                Setting up modules folders for first use.
  module:unuse                Forget the used module with module:use
  module:update               Update dependencies for the specified module or for all modules.
  module:use                  Use the specified module.
  module:v6:migrate           Migrate laravel-modules v5 modules statuses to v6.
 notifications
  notifications:table         Create a migration for the notifications table
 optimize
  optimize:clear              Remove the cached bootstrap files
 package
  package:discover            Rebuild the cached package manifest
 queue
  queue:batches-table         Create a migration for the batches database table
  queue:clear                 Delete all of the jobs from the specified queue
  queue:failed                List all of the failed queue jobs
  queue:failed-table          Create a migration for the failed queue jobs database table
  queue:flush                 Flush all of the failed queue jobs
  queue:forget                Delete a failed queue job
  queue:listen                Listen to a given queue
  queue:monitor               Monitor the size of the specified queues
  queue:prune-batches         Prune stale entries from the batches database
  queue:prune-failed          Prune stale entries from the failed jobs table
  queue:restart               Restart queue worker daemons after their current job
  queue:retry                 Retry a failed queue job
  queue:retry-batch           Retry the failed jobs for a batch
  queue:table                 Create a migration for the queue jobs database table
  queue:work                  Start processing jobs on the queue as a daemon
 route
  route:cache                 Create a route cache file for faster route registration
  route:clear                 Remove the route cache file
  route:list                  List all registered routes
 sail
  sail:install                Install Laravel Sail's default Docker Compose file
  sail:publish                Publish the Laravel Sail Docker files
 schedule
  schedule:list               List the scheduled commands
  schedule:run                Run the scheduled commands
  schedule:test               Run a scheduled command
  schedule:work               Start the schedule worker
 schema
  schema:dump                 Dump the given database schema
 session
  session:table               Create a migration for the session database table
 storage
  storage:link                Create the symbolic links configured for the application
 stub
  stub:publish                Publish all stubs that are available for customization
 vendor
  vendor:publish              Publish any publishable assets from vendor packages
 view
  view:cache                  Compile all of the application's Blade templates
  view:clear                  Clear all compiled view files
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default
lee@MacBook-Pro laraveldemo % php artisan l5-swagger:generate

Regenerating docs default
lee@MacBook-Pro laraveldemo % 
</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>/%e5%90%8e%e5%8f%b0%e6%a1%86%e6%9e%b6/laravel/8773.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>8小时转职Golang工程师</title>
		<link>/%e8%b5%84%e6%96%99/9066.html</link>
					<comments>/%e8%b5%84%e6%96%99/9066.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Wed, 10 Mar 2021 07:28:11 +0000</pubDate>
				<category><![CDATA[资料]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[goland]]></category>
		<guid isPermaLink="false">/?p=9066</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed-pdf-viewer-pdf wp-block-embed-pdf-viewer-pdf__content-wrapper aligncenter"><object class="embed-pdf-viewer" data="/wp-content/uploads/2024/04/《8小时转职Golang工程师-语法部分》.pdf#scrollbar=1&amp;toolbar=1" type="application/pdf" height="600" width="600" title=""></object><iframe loading="lazy" class="embed-pdf-viewer" src="https://docs.google.com/viewer?url=%2Fwp-content%2Fuploads%2F2024%2F04%2F%E3%80%8A8%E5%B0%8F%E6%97%B6%E8%BD%AC%E8%81%8CGolang%E5%B7%A5%E7%A8%8B%E5%B8%88-%E8%AF%AD%E6%B3%95%E9%83%A8%E5%88%86%E3%80%8B.pdf&amp;embedded=true" frameborder="0" height="600" width="600" title=""></iframe></figure>



<figure class="wp-block-embed-pdf-viewer-pdf wp-block-embed-pdf-viewer-pdf__content-wrapper aligncenter"><object class="embed-pdf-viewer" data="/wp-content/uploads/2024/04/《8小时转职Golang工程师-生态拓展》.pdf#scrollbar=1&amp;toolbar=1" type="application/pdf" height="600" width="600" title=""></object><iframe loading="lazy" class="embed-pdf-viewer" src="https://docs.google.com/viewer?url=%2Fwp-content%2Fuploads%2F2024%2F04%2F%E3%80%8A8%E5%B0%8F%E6%97%B6%E8%BD%AC%E8%81%8CGolang%E5%B7%A5%E7%A8%8B%E5%B8%88-%E7%94%9F%E6%80%81%E6%8B%93%E5%B1%95%E3%80%8B.pdf&amp;embedded=true" frameborder="0" height="600" width="600" title=""></iframe></figure>



<figure class="wp-block-embed-pdf-viewer-pdf wp-block-embed-pdf-viewer-pdf__content-wrapper aligncenter"><object class="embed-pdf-viewer" data="/wp-content/uploads/2024/04/《8小时转职Golang工程师-项目案例部分》.pdf#scrollbar=1&amp;toolbar=1" type="application/pdf" height="600" width="600" title=""></object><iframe loading="lazy" class="embed-pdf-viewer" src="https://docs.google.com/viewer?url=%2Fwp-content%2Fuploads%2F2024%2F04%2F%E3%80%8A8%E5%B0%8F%E6%97%B6%E8%BD%AC%E8%81%8CGolang%E5%B7%A5%E7%A8%8B%E5%B8%88-%E9%A1%B9%E7%9B%AE%E6%A1%88%E4%BE%8B%E9%83%A8%E5%88%86%E3%80%8B.pdf&amp;embedded=true" frameborder="0" height="600" width="600" title=""></iframe></figure>



<div class="wp-block-file"><a id="wp-block-file--media-82987104-7bb4-4d46-ae9c-6faf2e152b80" href="/goto/dcp3" rel="nofollow">GolangStudy</a><a href="/goto/dcp3" rel="nofollow" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-82987104-7bb4-4d46-ae9c-6faf2e152b80">下载</a></div>
]]></content:encoded>
					
					<wfw:commentRss>/%e8%b5%84%e6%96%99/9066.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python编写学生信息统计Demo</title>
		<link>/%e8%b5%84%e6%96%99/8767.html</link>
					<comments>/%e8%b5%84%e6%96%99/8767.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Tue, 01 Dec 2020 02:10:03 +0000</pubDate>
				<category><![CDATA[资料]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">/?p=8767</guid>

					<description><![CDATA[python]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="548" height="343" src="/wp-content/uploads/2020/12/python.png" alt="" class="wp-image-8768" srcset="/wp-content/uploads/2020/12/python.png 548w, /wp-content/uploads/2020/12/python-300x188.png 300w" sizes="(max-width: 548px) 100vw, 548px" /></figure>



<p>自学Python，编写了一个学生信息统计的小Demo。</p>



<pre class="wp-block-code"><code>import os

filename = 'student.txt'

def menum():
    print("==========================学生管理信息=============")
    print("------------------------------功能菜单--------------")
    print("\t\t\t\t\t\t\t1.录入学生信息")
    print("\t\t\t\t\t\t\t2.查找学生信息")
    print("\t\t\t\t\t\t\t3.删除学生信息")
    print("\t\t\t\t\t\t\t4.修改学生信息")
    print("\t\t\t\t\t\t\t5.排序")
    print("\t\t\t\t\t\t\t6.统计学生总人数")
    print("\t\t\t\t\t\t\t7.显示学生信息")
    print("\t\t\t\t\t\t\t0.退出系统")
    print("--------------------------------------------------")

def main():
    while True:
        menum()
        choice = int(input('请选择'))
        if choice in range(0,8):
            if choice == 0:
                answer = input("您确定要退出系统吗?y/n")
                if answer == 'y' or answer == 'Y':
                    print('谢谢您的使用！！！')
                    break
                else:
                    continue
            elif choice == 1:
                insert()
            elif choice == 2:
                search()
            elif choice == 3:
                delete()
            elif choice == 4:
                modify()
            elif choice == 5:
                sort()
            elif choice == 6:
                total()
            elif choice == 7:
                show()
    pass

def insert():
    student_list = &#91;]
    while True:
        id = input('请输入ID(如1001):')
        if not id:
            break
        name = input('请输入学生姓名:')
        if not name:
            break
        try:
            english = float(input('请输入english成绩:'))
            python = float(input('请输入python成绩:'))
            java = float(input('请输入java成绩:'))
        except:
            print('输入成绩无效,请重新输入')
        student_info = {'id':id,'name':name,'english':english,'python':python,'java':java}
        student_list.append(student_info)
        answer = input("是否继续添加?y/n\n")
        if answer == 'y' or answer == 'Y':
            continue
        else:
            break
    save(student_list)
    print('录入完毕')

def save(lst):
    try:
        stu_txt = open(filename, 'a', encoding='utf-8')
    except:
        stu_txt = open(filename, 'w', encoding='utf-8')
    for item in lst:
        stu_txt.write(str(item)+'\n')
    stu_txt.close()

def search():
    student_query = &#91;];
    while True:
        id = ''
        name = ''
        if os.path.exists(filename):
            mode = input('ID查找请输入1，Name查找请输入2')
            if int(mode) == 1:
                id = input('请输入学生ID')
            elif int(mode) == 2:
                name = input('请输入学生Name')
            else:
                print('不支持此类型查询')
                search()
            with open(filename,'r',encoding='utf-8') as rFile:
                student = rFile.readlines()
                for item in student:
                    d = dict(eval(item))
                    if d!='':
                        if d&#91;'id'] == id:
                            student_query.append(d)
                    elif name!='':
                        if d&#91;'name'] == name:
                            student_query.append(d)
            show_student(student_query)
            student_query.clear()
            answer = input('是否继续查询?y/n\n')
            if answer=='y' or answer=='Y':
                continue
            else:
                break
        else:
            print('暂未保存学生信息')
            return

def show_student(lst):
    if len(lst) == 0:
        print('无数据')
        return
    format_title = '{:^6}\t{:^12}\t{:^8}\t{:^10}\t{:^10}\t{:^8}\t'
    print(format_title.format('ID','姓名','英语成绩','Python成绩','Java成绩','总成绩'))
    format_data = '{:^6}\t{:^12}\t{:^8}\t{:^10}\t{:^10}\t{:^8}\t'
    for item in lst:
        print(format_data.format(item.get('id'),
                                 item.get('name'),
                                 item.get('english'),
                                 item.get('python'),
                                 item.get('java'),
                                 float(item.get('english'))+float(item.get('python'))+float(item.get('java'))
                                 ))

def delete():
    while True:
        student_id = input('请输入学生ID：')
        if student_id != '':
            if os.path.exists(filename):
                with open(filename,'r',encoding='utf-8') as file:
                    student_old = file.readlines()
            else:
                student_old = &#91;]
            flag = False
            if student_old:
                with open(filename,'w',encoding='utf-8') as wfile:
                    d = {}
                    for item in student_old:
                        d = dict(eval(item))
                        if d&#91;'id'] != student_id:
                            wfile.write(str(d)+'\n')
                        else:
                            flag = True
                    if flag:
                        print(f'id为{student_id}的学生信息已被删除')
                    else:
                        print(f'id为{student_id}的学生信息不存在')
            else:
                print('无学生信息')
                break
            show()
            answer = input('是否继续删除?y/n\n')
            if answer=='y' or answer=='Y':
                continue
            else:
                break

def modify():
    while True:
        show()
        if os.path.exists(filename):
            with open(filename,'r',encoding='utf-8') as rfile:
                student_old = rfile.readlines()
        else:
            return
        student_id = input('请输入学生ID')
        with open(filename,'w',encoding='utf-8') as wfile:
                for item in student_old:
                    d = dict(eval(item))
                    if d&#91;'id'] == student_id:
                        print('找到学生信息,可以进行修改操作了')
                        while True:
                            try:
                                d&#91;'name'] = input('请输入学生姓名')
                                d&#91;'english'] = input('请输入english成绩')
                                d&#91;'python'] = input('请输入python成绩')
                                d&#91;'java'] = input('请输入java成绩')
                            except:
                                print("输入信息有误")
                            else:
                                break
                        wfile.write(str(d)+'\n')
                        print('修改成功')
                    else:
                        wfile.write(str(d)+'\t')
                answer = input('是否继续修改其他学生信息?y/n\n')
                if answer=='y' or answer=='Y':
                    modify()
                else:
                    break

def sort():
    if os.path.exists(filename):
        with open(filename,'r',encoding='utf-8') as rfile:
            student_new = &#91;]
            student_list = rfile.readlines()
            for item in student_list:
                d = dict(eval(item))
                student_new.append(d)
    else:
        return
    asc_or_desc = input('请选择排序方式0asc1desc')
    if asc_or_desc == '0':
        asc_or_desc_bool = False
    elif asc_or_desc == '1':
        asc_or_desc_bool = True
    else:
        print('输入有误')
        sort()
    mode = input('选择详细排序方式1English2Python3Java0Total')
    if mode == '1':
        student_new.sort(key=lambda self:float(self&#91;'english']),reverse=asc_or_desc_bool)
    elif mode == '2':
        student_new.sort(key=lambda self: float(self&#91;'python']), reverse=asc_or_desc_bool)
    elif mode == '3':
        student_new.sort(key=lambda self: float(self&#91;'java']), reverse=asc_or_desc_bool)
    elif mode == '4':
        student_new.sort(key=lambda self: (float(self&#91;'java'])+float(self&#91;'python'])+float(self&#91;'english'])), reverse=asc_or_desc_bool)
    else:
        print('详细排序输入有误')
        sort()
    show_student(student_new)

def total():
    if os.path.exists(filename):
        with open(filename,'r',encoding='utf-8') as rfile:
            students = rfile.readlines()
            if students:
                print('一共有{}名学生'.format(len(students)))
            else:
                print('没有学生信息')
    else:
        print('无数据')

def show():
    student_info = &#91;]
    if os.path.exists(filename):
        with open(filename,'r',encoding='utf-8') as rfile:
            students = rfile.readlines()
            for item in students:
                student_info.append(eval(item))
            if students:
                show_student(student_info)
            else:
                print('信息为空')
    else:
        print('文件不存在')


if __name__ == '__main__':
    main()</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>/%e8%b5%84%e6%96%99/8767.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WordPress 域名&#038;服务器迁移</title>
		<link>/%e8%b5%84%e6%96%99/8739.html</link>
					<comments>/%e8%b5%84%e6%96%99/8739.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Sat, 01 Feb 2020 16:00:21 +0000</pubDate>
				<category><![CDATA[资料]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wordpress迁移]]></category>
		<category><![CDATA[网站迁移]]></category>
		<guid isPermaLink="false">/?p=8739</guid>

					<description><![CDATA[WordPress 作为全球最流行的博客系统，使用简单，功能丰富，用它来建站的用户非常多。对于站长们来说，网站 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>WordPress 作为全球最流行的博客系统，使用简单，功能丰富，用它来建站的用户非常多。对于站长们来说，网站搬家也是少不了的，有时我们需要更换主机空间，把网站从一个服务器迁移到另一个服务器上，或者更换域名。</p>



<p>本文就详细介绍下 WordPress 网站搬家的几种方法，我们可以通过手动备份搬家，也可以使用插件工具一键完成网站迁移。还是很简单的。</p>



<p>参考资料：<a href="/goto/sb47" rel="nofollow">https://zhuanlan.zhihu.com/p/50803437</a></p>



<h3 class="wp-block-heading">第一步:在新服务器安装运行环境</h3>



<p><strong>系统需求:</strong></p>



<ul class="wp-block-list"><li>CentOS/RHEL/Fedora/Debian/Ubuntu/Raspbian/Deepin/Aliyun/Amazon/Mint Linux发行版</li><li>需要5GB以上硬盘剩余空间，MySQL 5.7,MariaDB 10至少9GB剩余空间</li><li>需要128MB以上内存(128MB小内存VPS,Xen需有SWAP,OpenVZ至少要有128MB以上的vSWAP或突发内存)，注意小内存请勿使用64位系统！</li><li><strong>安装MySQL 5.6或5.7及MariaDB 10必须1G以上内存，更高版本至少要2G内存!</strong>。</li><li><strong>安装PHP 7及以上版本必须1G以上内存!</strong>。</li><li>VPS或服务器必须设置好可用的yum或apt-get源并确保能正常工作，<a href="/goto/mgpy" rel="nofollow">离线安装</a>需要增加 CheckMirror=n 参数！</li><li>Linux下区分大小写，输入命令时请注意！</li><li>如有通过yum或apt-get安装的MySQL/MariaDB请自行备份数据等相关文件！</li><li>CentOS 5,Debian 6及之前版本其官网已经结束支持无法使用！</li><li>Ubuntu 18+,Debian 9+,Mint 19+,Deepin 15.7+及所有新的Linux发行版只能使用1.6进行安装！</li><li>PHP 7.1.*以下版本不支持Ubuntu 19+、Debian 10等等非常新的Linux发行版！</li><li><a href="/goto/536t" target="_blank" rel="nofollow noreferrer noopener">阿里云</a>Ubuntu 14.04系统模版有问题不要用！！！</li></ul>



<p>LNMP一键安装包 V1.6 已经在<a href="/goto/wgcm" target="_blank" rel="nofollow noreferrer noopener">Vultr</a>、<a href="/goto/r40i" target="_blank" rel="nofollow noreferrer noopener">遨游主机</a>、<a href="/goto/lg11" target="_blank" rel="nofollow noreferrer noopener">搬瓦工</a>、<a href="/goto/ftn1" target="_blank" rel="nofollow noreferrer noopener">LocVPS</a>、<a href="/goto/63m3" target="_blank" rel="nofollow noreferrer noopener">Linode</a>、<a href="/goto/930c" target="_blank" rel="nofollow noreferrer noopener">vps2ez</a>、<a href="/goto/1c1m" target="_blank" rel="nofollow noreferrer noopener">DiaHosting</a>、<a href="/goto/vhcf" target="_blank" rel="nofollow noreferrer noopener">DigitalOcean</a>、<a href="/goto/kfx2" target="_blank" rel="nofollow noreferrer noopener">KVMLA</a>、<a href="/goto/lq8m" target="_blank" rel="nofollow noreferrer noopener">景文互联</a>、<a href="/goto/z9b2" target="_blank" rel="nofollow noreferrer noopener">BuyVM</a>、<a href="/goto/jeak" target="_blank" rel="nofollow noreferrer noopener">快易互联</a>、<a href="/goto/niwm" target="_blank" rel="nofollow noreferrer noopener">80VPS</a>、<a href="/goto/x89h" target="_blank" rel="nofollow noreferrer noopener">腾讯云</a>等众多VPS的CentOS 6-8、RHEL 6-8、Fedora 21-30、Debian 7-10、Ubuntu 10.04-19.10的32位和64位系统上测试通过(CentOS 5,Debian 6及之前版本其官网已经结束支持无法使用,Debian9上Apache需选2.4.26版本以上。</p>



<p><strong>安装步骤:</strong><br><strong>1、使用<a href="/goto/dsf0" target="_blank" rel="nofollow noreferrer noopener">putty</a>或类似的SSH工具登陆VPS或服务器；</strong><br><br>登陆后运行：<strong>screen -S lnmp</strong><br>如果提示screen: command not found 命令不存在可以执行：yum install screen 或 apt-get install screen安装，详细内容参考<a href="/goto/a8vt" target="_blank" rel="nofollow noreferrer noopener">screen教程</a>。<br><br><strong>2、下载并安装LNMP一键安装包：</strong><br><br>您可以选择使用下载版(推荐美国及海外VPS或空间较小用户使用)或者完整版(推荐国内VPS使用，国内用户可用在<a href="/goto/2oyi" target="_blank" rel="nofollow noreferrer noopener">下载</a>中找国内下载地址替换)，两者没什么区别，只是完整版把一些需要的源码文件预先放到安装包里。<br><br><strong>安装LNMP稳定版</strong><br>如需无人值守安装，请使用&nbsp;<a href="/goto/pk6m" target="_blank" rel="nofollow noreferrer noopener">无人值守命令生成工具</a>，或<a href="/goto/qkmb" target="_blank" rel="nofollow noreferrer noopener">查看无人值守说明教程</a><br><br><strong>wget http://soft.vpser.net/lnmp/lnmp1.6.tar.gz -cO lnmp1.6.tar.gz &amp;&amp; tar zxf lnmp1.6.tar.gz &amp;&amp; cd lnmp1.6 &amp;&amp; ./install.sh&nbsp;lnmp</strong><br><br>如需要安装LNMPA或LAMP，将./install.sh 后面的参数lnmp替换为lnmpa或lamp即可。如需更改网站和数据库目录、自定义Nginx参数、PHP参数模块、开启lua等需在运行./install.sh 命令前修改安装包目录下的 lnmp.conf 文件，详细可以查看<a href="/goto/ysgl" target="_blank" rel="nofollow noreferrer noopener">lnmp.conf文件参数说明</a>。<br><br>如提示wget: command not found ，使用yum install wget 或 apt-get install wget 命令安装。<br><br>如下载速度慢或无法下载请更换其他下载节点，请查看<a href="/goto/0mak" target="_blank" rel="nofollow noreferrer noopener">LNMP下载节点具体替换方法</a>。<br><br>运行上述LNMP安装命令后，会出现如下提示：</p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.5/lnmp1.5-install-1.png" alt=""/></figure>



<p>目前提供了较多的MySQL、MariaDB版本和不安装数据库的选项，需要<strong>注意的是MySQL 5.6,5.7及MariaDB 10必须在1G以上内存的更高配置上才能选择</strong>！如仅需安装数据库在lnmp安装包目录下执行：./install.sh db</p>



<p>输入对应MySQL或MariaDB版本前面的序号，回车进入下一步.</p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.5/lnmp1.5-install-2.png" alt=""/></figure>



<p>设置MySQL的root密码（为了安全不输入直接回车将会设置为lnmp.org#随机数字）如果输入有错误需要删除时，可以按住Ctrl再按Backspace键进行删除(个别情况下是只需要Backspace键)。输入后回车进入下一步，如下图所示：<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.5/lnmp1.5-install-3.png" alt=""/></figure>



<p></p>



<p>询问是否需要启用MySQL InnoDB，InnoDB引擎默认为开启，一般建议开启，直接回车或输入 y ，如果确定确实不需要该引擎可以输入 n，(MySQL 5.7+版本无法关闭InnoDB),输入完成，回车进入下一步。<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.5/lnmp1.5-install-4.png" alt=""/></figure>



<p>注意：选择PHP 7+版本时需要自行确认PHP版本是否与自己的程序兼容。</p>



<p>输入要选择的PHP版本的序号，回车进入下一步，选择是否安装内存优化：<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.5/lnmp1.5-install-5.png" alt=""/></figure>



<p>可以选择不安装、Jemalloc或TCmalloc，输入对应序号回车，直接回车为默认为不安装。</p>



<p>如果是LNMPA或LAMP的话还会提示设置邮箱和选择Apache</p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.5/lnmp1.5-install-6.png" alt=""/></figure>



<p>“Please enter Administrator Email Address:”，需要设置管理员邮箱，该邮箱会在报错时显示在错误页面上。</p>



<p>再选择Apache版本<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.5/lnmp1.5-install-7.png" alt=""/></figure>



<p>按提示输入对应版本前面的数字序号，回车。</p>



<p>提示&#8221;Press any key to install&#8230;or Press Ctrl+c to cancel&#8221;后，按回车键确认开始安装。<br>LNMP脚本就会自动安装编译Nginx、MySQL、PHP、phpMyAdmin等软件及相关的组件。</p>



<p>安装时间可能会几十分钟到几个小时不等，主要是机器的配置网速等原因会造成影响。</p>



<p><strong>3、安装完成</strong><br>如果显示Nginx: OK，MySQL: OK，PHP: OK</p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.5/lnmp1.5-install-success.png" alt=""/></figure>



<p>并且Nginx、MySQL、PHP都是running，80和3306端口都存在，并提示安装使用的时间及Install lnmp V1.6 completed! enjoy it.的话，说明已经安装成功。<br>某些系统可能会一直卡在Install lnmp V1.5 completed! enjoy it.不自动退出，可以按Ctrl+c退出。</p>



<p>安装完成接下来开始使用就可以了，按<a href="/goto/qa97" target="_blank" rel="nofollow noreferrer noopener"><strong>添加虚拟主机教程</strong></a>，添加虚拟主机后可以使用<a href="/goto/aj5n" target="_blank" rel="nofollow noreferrer noopener">sftp</a>或<a href="/goto/8uv2" target="_blank" rel="nofollow noreferrer noopener">ftp服务器</a>上传网站代码，将域名解析到VPS或服务器的IP上，解析生效即可使用。</p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.5/lnmp1.5-install-failed.png" alt=""/></figure>



<p><br><strong>4、安装失败</strong><br><br>如果出现类似上图的提示，有一个或几个没安装成功表明安装失败！！需要用<a href="/goto/cl24" target="_blank" rel="nofollow noreferrer noopener">winscp</a>或其他类似工具，将/root目录下面的lnmp-install.log下载下来，到<a href="/goto/tgnw" rel="nofollow">LNMP支持论坛</a>发帖注明你的系统发行版名称及版本号、32位还是64位等信息，并将lnmp-install.log压缩以附件形式上传到论坛，我们会通过日志查找错误，并给予相应的解决方法。</p>



<p><strong>默认LNMP是不安装FTP服务器的，如需要FTP服务器：<a href="/goto/8uv2" target="_blank" rel="nofollow noreferrer noopener">https://lnmp.org/faq/ftpserver.html</a></strong></p>



<p><strong>5、添加、删除虚拟主机及伪静态管理</strong><br><a href="/goto/qa97" target="_blank" rel="nofollow noreferrer noopener">https://lnmp.org/faq/lnmp-vhost-add-howto.html</a></p>



<p><strong>6、eAccelerator、xcache、memcached、imageMagick、ionCube、redis、opcache的安装</strong><br><a href="/goto/7wl7" target="_blank" rel="nofollow noreferrer noopener">https://lnmp.org/faq/addons.html</a></p>



<p><strong>7、LNMP相关软件目录及文件位置</strong><br><a href="/goto/dad9" target="_blank" rel="nofollow noreferrer noopener">https://lnmp.org/faq/lnmp-software-list.html</a></p>



<p><strong>8、LNMP状态管理命令</strong><br><a href="/goto/igko" target="_blank" rel="nofollow noreferrer noopener">https://lnmp.org/faq/lnmp-status-manager.html</a></p>



<p><strong>9、仅安装数据库、Nginx</strong><br>lnmp 1.5开始支持只安装MySQL/MariaDB数据库或Nginx<br>增加单独nginx安装，安装包目录下运行：./install.sh nginx 进行安装；<br>增加单独数据库安装，安装包目录下运行：./install.sh db 进行安装；</p>



<p><strong>10、lnmp一键安装包支持完全离线模式进行安装</strong><br>CentOS系统下离线安装教程：<a href="/goto/jk9l" target="_blank" rel="nofollow noreferrer noopener">https://www.vpser.net/manage/centos-iso-local-yum-repository.html</a><br>Debian/Ubuntu发行版下类似。</p>



<p>参考链接 ：<a href="/goto/ljby" rel="nofollow">https://lnmp.org/install.html</a></p>



<h3 class="wp-block-heading">第二步：添加虚拟机</h3>



<p>如果输入有错误需要删除时，可以按住Ctrl再按Backspace键进行删除。</p>



<p>执行：<strong>lnmp vhost add</strong>&nbsp;出现如下界面：<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-1.png" alt=""/></figure>



<p>这里要输入要添加网站的域名，我们已添加www.vpser.net域名为例，如上图提示后输入域名 www.vpser.net 回车后提示</p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-2.png" alt=""/></figure>



<p><br>这里询问是否添加更多域名，直接再输入要绑定的域名，这里我们将 vpser.net 也绑上，多个域名空格隔开，如不需要绑其他域名就直接回车。</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>(注：带www和不带www的是不同的域名，如需带www和不带的www的域名都访问同一个网站需要同时都绑定)。</p></blockquote>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-3.png" alt=""/></figure>



<p>下面需要设置网站的目录<br><br>网站目录不存在的话会创建目录。也可以输入已经存在的目录或要设置的目录（<strong>注意如要输入必须是全路径即以/开头的完整路径！！！</strong>）。不输入直接回车的话，采用默认目录：/home/wwwroot/域名</p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-4.png" alt=""/></figure>



<p>伪静态可以使URL更加简洁也利于SEO，如程序支持并且需要设置伪静态的话，如启用输入 y ，不启用输入 n 回车(注意LNMPA或LAMP模式没有该选择项！)。<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-5.png" alt=""/></figure>



<p>默认已经有了discuz、discuzx、discuzx2(Discuz X二级目录)、wordpress、wp2(WordPress二级目录)、typecho、typecho2(Typecho二级目录)、sablog、emlog、dabr、phpwind、、dedecms、drupal、ecshop、shopex等常用的Nginx伪静态配置文件，可以直接输入名称进行使用，如果是二级目录则需要对应配置文件里的二级目录的名称。<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-6.png" alt=""/></figure>



<p>这一步是设置日志，如启用日志输入 y ，不启用输入 n 回车。<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-7.png" alt=""/></figure>



<p>如果启用需要再输入要设置的日志的名称，默认日志目录为：/home/wwwlogs/ 默认文件名为：域名.log 回车确认后，会询问是否添加数据库和数据库用户。<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-8.png" alt=""/></figure>



<p>如果需要添加数据库输入 y ，不添加数据库输入 n 回车。<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-9.png" alt=""/></figure>



<p>如果要添加，需要先验证MySQL的root密码(注：输入密码将不显示)<br>提示Enter database name: 后输入要创建的数据库名称，要创建的数据库用户名会和数据库同名，回车确认。</p>



<p>提示Please enter password for mysql user 数据库名: 后输入要设置的密码，回车确认。</p>



<p><strong>如果安装了FTP服务器</strong>会询问是否添加FTP账号<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-10.png" alt=""/></figure>



<p>如果需要添加输入 y ，不添加输入 n 回车。<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-11.png" alt=""/></figure>



<p>提示Enter ftp account name: 后输入要创建的FTP账号名称，回车确认。<br>提示Enter password for ftp account FTP账号: 后输入要设置的密码，回车确认。</p>



<p>接下来是1.4新增的添加SSL功能<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-12.png" alt=""/></figure>



<p>如果需要添加输入 y ，不添加输入 n 回车。<br>选择了添加SSL会提示<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-13.png" alt=""/></figure>



<p>有两个选项，1 选项为使用自己准备好的SSL证书和key。<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-14.png" alt=""/></figure>



<p>&gt; &gt; 提示Please enter full path to SSL Certificate file 后输入要SSL证书的完整路径和文件名，回车确认。<br>&gt; &gt; 提示Please enter full path to SSL Certificate Key file: 后输入输入要key文件的完整路径和文件名，回车确认。<br>&gt; &gt; LAMP下会提示Please enter full path to SSL Chain file: 一般Apache2.2需要用到这个添加上证书链，2.4前面证书是补全证书链的话不用。</p>



<p>2 选项为使用免费SSL证书提供商Letsencrypt的证书，自动生成SSL证书等信息。<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-add-15.png" alt=""/></figure>



<p>需要输入一个邮箱回车确认。</p>



<p>提示 Press any key to start create virtul host&#8230; 后，回车确认便会开始创建虚拟主机。</p>



<p>添加成功会提示添加的域名、目录、伪静态、日志、数据库、FTP等相关信息，如下图：<br></p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/1.4/lnmp1.4-vhost-info.png" alt=""/></figure>



<p>参考链接: <a href="/goto/qa97" rel="nofollow">https://lnmp.org/faq/lnmp-vhost-add-howto.html</a></p>



<h3 class="wp-block-heading">第三步：伪静态管理</h3>



<p><strong>将原服务器/usr/local/nginx/conf/下配置文件同步到新服务器，并同步虚拟主机配置文件：/usr/local/nginx/conf/vhost/域名.conf</strong></p>



<p>LNMPA或LAMP可以直接使用网站根目录下放.htaccess 来设置伪静态规则(具体规则可以去程序官网网站找google百度)，但是在LNMP下，需要使用Nginx伪静态规则。<br>伪静态可以随时添加或删除，如果添加完虚拟主机后忘记或没有添加伪静态，可以通过修改配置文件来添加伪静态。<br>虚拟主机配置文件在：/usr/local/nginx/conf/vhost/域名.conf</p>



<p>伪静态规则文件需要放在/usr/local/nginx/conf/ 下面。<br>编辑虚拟主机配置文件，可以使用<a href="/goto/9e25" target="_blank" rel="nofollow noreferrer noopener">vi</a>、<a href="/goto/wlq3" target="_blank" rel="nofollow noreferrer noopener">nano</a>或<a href="/goto/cl24" target="_blank" rel="nofollow noreferrer noopener">winscp</a>，后2个工具对新手来说简单些。</p>



<p>例如前面我们添加的虚拟主机，打开后前半部分配置会显示如下：</p>



<figure class="wp-block-image"><img decoding="async" src="https://lnmp.org/images/lnmp-rewrite-modify.png" alt=""/></figure>



<p>在root /home/wwwroot/www.vpser.net;这一行下面添加：<br>include wordpress.conf;<br>上面的wordpress.conf为伪静态文件，如需要其他伪静态文件自己创建个并上传到/usr/local/nginx/conf/ 下面并include 伪静态.conf; 加完保存，执行：<strong>/etc/init.d/nginx restart</strong>&nbsp;重启生效，如果报错可能是添加有误或伪静态规则有误。</p>



<p>1.4及之前版本伪静态文件都在 /usr/local/nginx/conf/ 目录下<br>1.5及之后版本伪静态文件都在 /usr/local/nginx/conf/rewrite 目录下<br>伪静态文件名称后面带2的是二级目录的伪静态，可以根据自己需求修改里面二级目录的名称或复制为其他名字后include到虚拟主机配置文件中。</p>



<p>参考链接: <a href="/goto/qa97" rel="nofollow">https://lnmp.org/faq/lnmp-vhost-add-howto.html</a></p>



<h3 class="wp-block-heading">第四步：安装wordpress</h3>



<p>下载WordPress</p>



<pre class="wp-block-code"><code>cd /home/wwwroot/文件根目录
yum -y install wget unzip net-tools
wget http://wordpress.org/latest.zip
</code></pre>



<p>解压文件，并且将其复制到/home/wwwroot/文件根目录 下</p>



<pre class="wp-block-code"><code>unzip -q latest.zip
cp -rf wordpress/* /home/wwwroot/文件根目录</code></pre>



<p>参考链接：<a href="/goto/dgm4" rel="nofollow">https://segmentfault.com/a/1190000016119293?utm_source=tag-newest</a></p>



<h3 class="wp-block-heading">第五步：备份与恢复数据库和博客网站文件</h3>



<p>可以采用phpMyadmin备份数据库或者mysqldump来备份</p>



<pre class="wp-block-code"><code>mysqldump -u用户名 -p密码 数据库名 > /备份目录/数据库名.sql 
mysql -u用户名 -p密码 数据库名 &lt; 导入数据库名.sql
参考链接: https://segmentfault.com/a/1190000019305858</code></pre>



<p>可以采用zip压缩打包的形式备份原wordpress网站目录文件或者在已知新服务器的情况下用scp命令直接迁移文件</p>



<pre class="wp-block-code"><code>scp -r   /home/wwwroot/文件根目录/  新服务器登录账号@新服务器域名:/home/wwwroot
参考链接: https://www.cnblogs.com/gudongcheng/p/8064808.html</code></pre>



<p>参考链接：<a href="/goto/qrt3" rel="nofollow">https://www.22vd.com/3979.html</a></p>



<h3 class="wp-block-heading">第六步：修改网站配置和数据库（关键）</h3>



<p>1.修改 wp-config 文件，最好不要用记事本来修改，用 notepad++或者 UltraEdit 等编辑器，把里面的数据库信息改为您新空间的数据库信息，如下：</p>



<pre class="wp-block-code"><code>/** WordPress 数据库的名称 */
define('DB_NAME', '你的新空间数据库名称');
/** MySQL 数据库用户名 */
define('DB_USER', '你的数据库用户名');
/** MySQL 数据库密码 */
define('DB_PASSWORD', '你的数据库登录密码');
/** MySQL 主机 */
define('DB_HOST', '你的数据库地址');</code></pre>



<p>2.原来的文章里有链接或者图片是用以前域名的地址，所以还要修改那些地址。可以在 phpadmin 直接修改数据库或者 velvet-blues-update-urls 这个插件（推荐）。比如在 phpadmin 里，执行执行以下语句：</p>



<pre class="wp-block-code"><code>UPDATE wp_options SET option_value = REPLACE(option_value,'旧地址','新地址');
UPDATE wp_posts SET post_content = replace(post_content,'旧地址','新地址');
UPDATE wp_posts SET post_excerpt= replace(post_excerpt,'旧地址','新地址');
UPDATE wp_posts SET guid= replace(guid, '旧地址','新地址');</code></pre>



<p>参考链接：<a href="/goto/qrt3" rel="nofollow">https://www.22vd.com/3979.html</a></p>



<h3 class="wp-block-heading">第七步：访问网站域名，检测网站运行情况</h3>



<p>同步wordpess插件，wordpress主题，主题设置，<strong>主题菜单结构</strong>，<strong>勾选自动添加页面及显示位置。</strong></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="337" src="/wp-content/uploads/2020/02/image-1024x337.png" alt="" class="wp-image-8740" srcset="/wp-content/uploads/2020/02/image-1024x337.png 1024w, /wp-content/uploads/2020/02/image-300x99.png 300w, /wp-content/uploads/2020/02/image-768x253.png 768w, /wp-content/uploads/2020/02/image-1536x505.png 1536w, /wp-content/uploads/2020/02/image-2048x674.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>参考链接：<a href="/goto/qrt3" rel="nofollow">https://www.22vd.com/3979.html</a></p>



<h3 class="wp-block-heading">异常情况：Wordpress 文章特色图无法显示</h3>



<p>在使用wordpress建设个人网站时，新手可能会遇到有的主题无法显示文章的特色图，如下：</p>



<figure class="wp-block-image size-large"><img decoding="async" src="https://img-blog.csdn.net/20170915192127606?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWludGFpd3U=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""/></figure>



<p>如果使用的是官方的主题，一般都不会出现无法显示的的情况！那么为什么我们（新手）常常会遇到这样的问题呢？这是因为wordpress官方的主题和你当前使用的主题，对网站图片的管理方式不一样，wordpress官方使用的是“一次生成”的方式，而我们使用国内的主题常常会引入一个叫“timthumb.php”的小程序来管理我们网站中的图片调用等（两者的具体差异，可自行深入查询）。</p>



<p>主要原因是一些文件的权限问题所引起的，解决方案如下：</p>



<p>1、检查你是否设置了文章的特色图</p>



<p>2、检查当前系统环境是否开启了 “GD库”支持功能</p>



<p>3、查看主题目录下的 “&nbsp;cache ”&nbsp;文件夹(及子目录的两个文件)的权限是否为 777</p>



<p>4、检查主题目录下的 “&nbsp;timthumb.php&nbsp;”&nbsp;文件权限是否为755或777<br> </p>



<p>具体操作如下：</p>



<p>a )&nbsp;检查你是否设置了文章的特色图</p>



<p>进入“编辑文章”页面，查看右下角的“特色图”设置..</p>



<figure class="wp-block-image"><img decoding="async" src="https://img-blog.csdn.net/20170915192209712?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWludGFpd3U=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""/></figure>



<p>b ) 检查是否开启 “&nbsp;GD库”&nbsp;功能</p>



<p>方法一：</p>



<p>终端模式下输入： &nbsp;php -i | grep -i &#8211;color gd</p>



<p>运行回车，如果返回的信息中有：</p>



<p>GD Support =&gt; enabled</p>



<p>表示 GD库 支持功能已开启。</p>



<p>方法二：</p>



<p>在网站根目录下创建一个 “&nbsp;.php “&nbsp;的文件(文件名随意起)，并打开输入以下内容：</p>



<p>保存！然后使用网页访问的方式去访问这个文件，如：xxx.com/xxx.php.</p>



<p>如果有返回以下界面，表示成功访问到该文件，否则请检查是否哪里有误：</p>



<figure class="wp-block-image size-large"><img decoding="async" src="https://img-blog.csdn.net/20170915192241817?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWludGFpd3U=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""/></figure>



<p>往下查看文件（可使用查询），当浏览到 GD项中浏览其状态信息，如果同样显示 “&nbsp;GD Support &nbsp;enable”，表明该功能已开启。</p>



<p>c ) 查看主题目录下的 “&nbsp;cache ”&nbsp;文件夹的权限是否为 777</p>



<p>在终端下输入: &nbsp;ls -lh cache &nbsp;&nbsp;可获得权限信息。</p>



<p>如果不符合权限要求，可输入：</p>



<p>chmod 777 cache &nbsp;&nbsp;//获取所有权限</p>



<p>同时进入其子目录将 inddx.html 和 timthumb_cacheLastCleanTime.touch 文件权限改为 777</p>



<p>d )&nbsp;检查主题目录下的&nbsp;“&nbsp;timthumb.php&nbsp;”&nbsp;文件权限是否为755或777</p>



<p>e )&nbsp;有些教程还说需要修改”&nbsp;timthumb.php&nbsp;”文件内部的：</p>



<p>define (‘ALLOW_ALL_EXTERNAL_SITES’,false)　语句，将其改为</p>



<p>define (‘ALLOW_ALL_EXTERNAL_SITES’,TRUE)</p>



<p>但尝试后，发现有没有修改都没什么影响，可能是小编环境的问题吧！</p>



<p>这里只是给大家最后一个参考的调试方案！<br> 参考链接：<a href="/goto/ggib" rel="nofollow">https://blog.csdn.net/qintaiwu/article/details/77994917</a></p>



<p><strong>至此教程结束！</strong><br> ————————————————</p>
]]></content:encoded>
					
					<wfw:commentRss>/%e8%b5%84%e6%96%99/8739.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>node.js面试题大全－侧重后端应用与对Node核心的理解</title>
		<link>/uncategorized/8689.html</link>
					<comments>/uncategorized/8689.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Mon, 26 Aug 2019 12:05:37 +0000</pubDate>
				<category><![CDATA[Node]]></category>
		<category><![CDATA[后台框架]]></category>
		<category><![CDATA[未分类]]></category>
		<category><![CDATA[node]]></category>
		<category><![CDATA[node.js]]></category>
		<guid isPermaLink="false">/?p=8689</guid>

					<description><![CDATA[Node是搞后端的，不应该被被归为前端，更不应该用前端的观点去理解，去面试node开发人员。所以这份面试题大全 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><strong>Node是搞后端的，不应该被被归为前端，更不应该用前端的观点去理解，去面试node开发人员。所以这份面试题大全，更侧重后端应用与对Node核心的理解。</strong></p>
<h3 id="为什么用nodejs它有哪些缺点">1、为什么用Nodejs,它有哪些缺点？</h3>
<ul>
<li>事件驱动，通过闭包很容易实现客户端的生命活期。</li>
<li>不用担心多线程，锁，并行计算的问题</li>
<li>V8引擎速度非常快</li>
<li>对于游戏来说，写一遍游戏逻辑代码，前端后端通用</li>
</ul>
<h4 id="当然nodejs也有一些缺点">当然Nodejs也有一些缺点：</h4>
<ul>
<li>nodejs更新很快，可能会出现版本兼容</li>
<li>nodejs还不算成熟，还没有大制作</li>
<li>nodejs不像其他的服务器，对于不同的链接，不支持进程和线程操作</li>
</ul>
<h3 id="什么是错误优先的回调函数">2、什么是错误优先的回调函数？</h3>
<ul>
<li>错误优先(Error-first)的回调函数（Error-First Callback）用于同时返回错误和数据。第一个参数返回错误，并且验证它是否出错；其他参数返回数据。
<pre><code class="hljs javascript">  fs.readFile(filePath, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, data</span>)

  </span>{

      <span class="hljs-keyword">if</span> (err)

      {

          <span class="hljs-comment">// 处理错误</span>

          <span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(err);

      }

      <span class="hljs-built_in">console</span>.log(data);

  });</code></pre>
</li>
</ul>
<h3 id="如何避免回调地狱">3、如何避免回调地狱？</h3>
<h4 id="以下方式避免回调地狱">以下方式避免回调地狱</h4>
<ul>
<li>模块化：将回调函数转换为独立的函数</li>
<li>使用流程控制库，例如[aync]</li>
<li>使用Promise</li>
<li>使用aync/await</li>
</ul>
<h3 id="什么是promise">4、什么是Promise?</h3>
<ul>
<li>Promise可以帮助我们更好地处理异步操作。下面的实例中，100ms后会打印result字符串。catch用于错误处理。多个Promise可以链接起来。
<pre><code class="hljs coffeescript">  <span class="hljs-keyword">new</span> Promise(<span class="hljs-function"><span class="hljs-params">(resolve, reject)</span> =&gt;</span>

      {

          setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span>

          {

              resolve(<span class="hljs-string">'result'</span>);

          }, <span class="hljs-number">100</span>)

      })

      .<span class="hljs-keyword">then</span>(<span class="hljs-built_in">console</span>.log)

      .<span class="hljs-keyword">catch</span>(<span class="hljs-built_in">console</span>.error);</code></pre>
</li>
</ul>
<h3 id="用什么工具保证一致的代码风格为什么要这样">5、用什么工具保证一致的代码风格？为什么要这样？</h3>
<ul>
<li>团队协作时，保证一致的代码风格是非常重要的，这样团队成员才可以更快地修改代码，而不需要每次去适应新的风格。这些工具可以帮助我们：</li>
<li>[ESLint] (<a class="uri" href="/goto/scp8" rel="nofollow">http://eslint.org/</a>)</li>
<li>[Standard] (<a class="uri" href="/goto/temy" rel="nofollow">https://standardjs.com/</a>)</li>
<li>JSLint</li>
<li>JSHint</li>
<li>ESLint</li>
<li>JSCS推荐</li>
</ul>
<h3 id="什么是stub举例说明">6、什么是stub？举例说明</h3>
<ul>
<li>stub用于模块的行为。测试时，stub可以为函数调用返回模拟的结果。比如说，我们写文件时，实际上并不需要真正去写。
<pre><code class="hljs javascript">      <span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
      <span class="hljs-keyword">var</span> writeFileStub = sinon.stub(fs, <span class="hljs-string">'writeFile'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">path, data, cb</span>)

      </span>{

          <span class="hljs-keyword">return</span> cb(<span class="hljs-literal">null</span>);

      });

      expect(writeFileStub).to.be.called;

      writeFileStub.restore();</code></pre>
</li>
</ul>
<h3 id="什么是测试金字塔举例说明">7、什么是测试金字塔？举例说明</h3>
<ul>
<li>测试金字塔反应了需要写的单元测试，集成测试以及端到端测试的比例：<br />
<img decoding="async" src="https://images2018.cnblogs.com/blog/1201653/201711/1201653-20171127104813253-720616924.png" /></li>
<li>测试HTTP接口时应该是这样的：</li>
<li>很多单元测试，分别测试各个模块(依赖需要stub)</li>
<li>较少的集成测试，测试各个模块之间的交互(依赖不能stub)</li>
<li>少量端到端测试，去调用真正地接口(依赖不能stub)</li>
</ul>
<h3 id="如何用node监听80端口">8、如何用Node监听80端口</h3>
<ul>
<li>这题有陷阱！在类Unix系统中你不应该去监听80端口，因为这需要超级用户权限。因此不推荐让你的应用直接监听这个端口。</li>
<li>目前，如果你一定要让你的应用80端口的话，你可以有通过在Node应用的前方再添加一层反向代理（例如nginx）来实现，如下图。否则，建议你直接监听大于1024的端口<br />
<img decoding="async" src="https://images2018.cnblogs.com/blog/1201653/201711/1201653-20171127113957737-1743742030.png" /></li>
<li>方向代理指的是以代理服务器来接收Internet上的连接请求，然后将请求转发给内部网络上的服务器， 并且将服务器返回的结果发送给客户端。</li>
</ul>
<h3 id="什么是事件循环">9、什么是事件循环</h3>
<ul>
<li>Node采用的是单线程的处理机制(所有的I/O请求都采用非阻塞的工作方式)，至少从Node.js开发者的角度是这样的。而在底层，Node.js借助libuv来作为抽象封装层，从而屏蔽不同操作系统的差异，Node可以借助livuv来实现线程。下图表示Node和libuv的关系<br />
<img decoding="async" src="https://images2018.cnblogs.com/blog/1201653/201711/1201653-20171127114014956-1412280481.png" /></li>
<li>Libuv库负责Node API的执行。它将不同的任务分配给不同的线程，形成一个事件循环，以异步的方式将任务的执行结果返回给V8引擎。可以简单用下面这张图来表示<br />
<img decoding="async" src="https://images2018.cnblogs.com/blog/1201653/201711/1201653-20171127114035472-900672231.png" /></li>
<li>每一个I/O都需要一个回调函数————一旦执行完便堆到事件循环上用于执行</li>
</ul>
<h3 id="运算错误与程序员错误的区别">10、运算错误与程序员错误的区别</h3>
<ul>
<li>运算错误并不是bug，这是和系统相关的问题，例如请求超时或者硬件故障。而程序员错误就是所谓的bug</li>
</ul>
<h3 id="使用npm有哪些好处">11、使用NPM有哪些好处？</h3>
<ul>
<li>通过NPM，你可以安装和管理项目的依赖，并且能够指明依赖项的具体版本号。对于Node应用开发而言，你可以通过<code>package.json</code>文件来管理项目信息，配置脚本，以及指明依赖的具体版本</li>
</ul>
<h3 id="什么是stub举个使用场景">12、什么是stub？举个使用场景</h3>
<ul>
<li>stub是用于模拟一个组件或模块的函数或程序。在测试用例中，简单的说，你可以用stub去模拟一个方法，从而避免调用真实的方法，使用stub你还可以返回虚构的结果。你可以配合断言使用stub。</li>
<li>举个例子，在一个读取文件的场景中，当你不想读取一个真正的文件时：
<pre><code class="hljs javascript">  <span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>); <span class="hljs-keyword">var</span> readFileStub = sinon.stub(fs, <span class="hljs-string">'readFile'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">path, cb</span>) </span>{ <span class="hljs-keyword">return</span> cb(<span class="hljs-literal">null</span>, <span class="hljs-string">'filecontent'</span>); }); expect(readFileStub).to.be.called; readFileStub.restore(); </code></pre>
</li>
</ul>
<p><code>在单元测试中：Stub是完全模拟一个外部依赖，而Mock常用来判断测试通过还是失败</code></p>
<h1>node开发技能图解</h1>
<p><img decoding="async" src="https://images2015.cnblogs.com/blog/730090/201509/730090-20150919214515695-745120854.jpg" alt="" /></p>
<h1><a id="user-content-起源" class="anchor" href="/goto/i8j3" rel="nofollow"></a>起源</h1>
<ul>
<li>node正风生火起，很多介绍却停留在入门阶段，无法投入生产</li>
<li>node相关的高质量面试题更是少之又少，很难全面考查应聘者的node能力</li>
<li>许多文章在讲第三方类库，可是这些库质量差距较大，一旦遇到问题怎么办</li>
<li>必需的，全面了解node核心才能成为一名合格的node开发人员</li>
</ul>
<h1><a id="user-content-目标与原则" class="anchor" href="/goto/ww2r" rel="nofollow"></a>目标与原则</h1>
<ul>
<li>前后端兼顾，更侧重后端</li>
<li>理论实战兼顾，侧重考察对实战中应用较多的理论的理解</li>
<li>参考答案简单明了，一针见血，不为追求严谨而浪费口舌，绕弯子</li>
<li>尽量用代码讲清理论的应用与区别，以接地气</li>
<li>终极目标是让大家对node有一个快速完整的认识</li>
</ul>
<h1><a id="user-content-内容大纲" class="anchor" href="/goto/hogw" rel="nofollow"></a>内容大纲</h1>
<ul>
<li>javascript高级话题(面向对象，作用域，闭包，设计模式等)</li>
<li>node核心内置类库(事件，流，文件，网络等)</li>
<li>node高级话题(异步，部署，性能调优，异常调试等)</li>
<li>常用知名第三方类库(Async, Express等)</li>
<li>其它相关后端常用技术(MongoDB, Redis, Apache, Nginx等)</li>
<li>常用前端技术(Html5, CSS3, JQuery等)</li>
</ul>
<h2><a id="user-content-javascript高级话题面向对象作用域闭包设计模式等" class="anchor" href="/goto/gaiy" rel="nofollow"></a><a name="user-content-jsAdvanced"></a>javascript高级话题(面向对象，作用域，闭包，设计模式等)</h2>
<ul>
<li><strong>1. 常用js类定义的方法有哪些？</strong></li>
</ul>
<p>参考答案：主要有构造函数原型和对象创建两种方法。原型法是通用老方法，对象创建是ES5推荐使用的方法.目前来看，原型法更普遍.</p>
<p>代码演示<br />
1) 构造函数方法定义类</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">function <span class="pl-en">Person(){
        <span class="pl-v">this.<span class="pl-c1">name = <span class="pl-s"><span class="pl-pds">'michaelqin';
    }
    Person.prototype.sayName = function(){
        alert(this.name);
    }

    var person = new Person();
    person.sayName();</span></span></span></span></span></span></pre>
</div>
<p>2) 对象创建方法定义类</p>
<pre><code class="hljs javascript">    <span class="hljs-keyword">var</span> Person = {
        <span class="hljs-attr">name</span>: <span class="hljs-string">'michaelqin'</span>,
        <span class="hljs-attr">sayName</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>()</span>{ alert(<span class="hljs-keyword">this</span>.name); }
    };

    <span class="hljs-keyword">var</span> person = <span class="hljs-built_in">Object</span>.create(Person);
    person.sayName();
</code></pre>
<ul>
<li><strong>2. js类继承的方法有哪些</strong></li>
</ul>
<p>参考答案：原型链法，属性复制法和构造器应用法. 另外，由于每个对象可以是一个类，这些方法也可以用于对象类的继承．</p>
<p>代码演示<br />
1) 原型链法</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">function <span class="pl-en">Animal() {
        <span class="pl-v">this.<span class="pl-c1">name = <span class="pl-s"><span class="pl-pds">'animal';
    }
    Animal.prototype.sayName = {
        alert(this.name);
    };

    function Person() {}
    Person.prototype = Animal.prototype; <span class="pl-c">// 人继承自动物
    Person.prototype.constructor = 'Person'; // 更新构造函数为人</span></span></span></span></span></span></span></pre>
</div>
<p>2) 属性自制法</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">function <span class="pl-en">Animal() {
        <span class="pl-v">this.<span class="pl-c1">name = <span class="pl-s"><span class="pl-pds">'animal';
    }
    Animal.prototype.sayName = {
        alert(this.name);
    };

    function Person() {}

    for(prop in Animal.prototype) {
        Person.prototype[prop] = Animal.prototype[prop];
    } <span class="pl-c">// 复制动物的所有属性到人量边
    Person.prototype.constructor = 'Person'; // 更新构造函数为人</span></span></span></span></span></span></span></pre>
</div>
<p>3) 构造器应用法</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">function <span class="pl-en">Animal() {
        <span class="pl-v">this.<span class="pl-c1">name = <span class="pl-s"><span class="pl-pds">'animal';
    }
    Animal.prototype.sayName = {
        alert(this.name);
    };

    function Person() {
        Animal.call(this); <span class="pl-c">// apply, call, bind方法都可以．细微区别，后面会提到．
    }</span></span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>3. js类多重继承的实现方法是怎么样的?</strong></li>
</ul>
<p>参考答案：就是类继承里边的属性复制法来实现．因为当所有父类的prototype属性被复制后，子类自然拥有类似行为和属性．</p>
<ul>
<li><strong>4. js里的作用域是什么样子的？</strong></li>
</ul>
<p>参考答案：大多数语言里边都是块作作用域，以{}进行限定，js里边不是．js里边叫函数作用域，就是一个变量在全函数里有效．比如有个变量p1在函数最后一行定义，第一行也有效，但是值是undefined.</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">var globalVar = <span class="pl-s"><span class="pl-pds">'global var';

    function <span class="pl-en">test() {
        <span class="pl-c1">alert(globalVar); <span class="pl-c">// undefined, 因为globalVar在本函数内被重定义了，导致全局失效，这里使用函数内的变量值，可是此时还没定义
        var globalVar = 'overrided var'; //　globalVar在本函数内被重定义
        alert(globalVar);　// overrided var
    }
    alert(globalVar); // global var，使用全局变量</span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>5. js里边的this指的是什么?</strong></li>
</ul>
<p>参考答案: this指的是对象本身，而不是构造函数．</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">function <span class="pl-en">Person() {
    }
    Person.<span class="pl-c1">prototype.sayName() { alert(<span class="pl-v">this.name); }

    var person1 = new Person();
    person1.name = <span class="pl-s"><span class="pl-pds">'michaelqin';
    person1.sayName(); <span class="pl-c">// michaelqin</span></span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>6. apply, call和bind有什么区别?</strong></li>
</ul>
<p>参考答案：三者都可以把一个函数应用到其他对象上，注意不是自身对象．apply,call是直接执行函数调用，bind是绑定，执行需要再次调用．apply和call的区别是apply接受数组作为参数，而call是接受逗号分隔的无限多个参数列表，</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">function <span class="pl-en">Person() {
    }
    Person.<span class="pl-c1">prototype.sayName() { alert(<span class="pl-v">this.name); }

    var obj = {name: <span class="pl-s"><span class="pl-pds">'michaelqin'}; <span class="pl-c">// 注意这是一个普通对象，它不是Person的实例
    1) apply
    Person.prototype.sayName.apply(obj, [param1, param2, param3]);

    2) call
    Person.prototype.sayName.call(obj, param1, param2, param3);

    3) bind
    var sn = Person.prototype.sayName.bind(obj);    
    sn([param1, param2, param3]); // bind需要先绑定，再执行 
    sn(param1, param2, param3); // bind需要先绑定，再执行</span></span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>7. caller, callee和arguments分别是什么?</strong></li>
</ul>
<p>参考答案: caller,callee之间的关系就像是employer和employee之间的关系，就是调用与被调用的关系，二者返回的都是函数对象引用．arguments是函数的所有参数列表，它是一个类数组的变量．</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">function <span class="pl-en">parent(<span class="pl-smi">param1, param2, param3) {
        child(param1, param2, param3);
    }

    function child() {
        console<span class="pl-c1">.log(arguments); <span class="pl-c">// { '0': 'mqin1', '1': 'mqin2', '2': 'mqin3' }
        console.log(arguments.callee); // [Function: child]
        console.log(child.caller); // [Function: parent]
    }

    parent(<span class="pl-s"><span class="pl-pds">'mqin1', 'mqin2', 'mqin3');</span></span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>8. 什么是闭包，闭包有哪些用处?</strong></li>
</ul>
<p>参考答案: 闭包这个术语它其实什么都不是．非要讲它是什么的话，两个字函数，更多字嵌套函数的父子自我引用关系．所有函数都是闭包．通俗的说，闭包就是作用域范围，因为js是函数作用域，所以函数就是闭包．全局函数的作用域范围就是全局，所以无须讨论．更多的应用其实是在内嵌函数，这就会涉及到内嵌作用域，或者叫作用域链．说到内嵌，其实就是父子引用关系(父函数包含子函数，子函数因为函数作用域又引用父函数，这不是死结吗？所以叫闭包），这就会带来另外一个问题，什么时候引用结束？如果不结束，就会一直占用内存，引起内存泄漏．好吧，不用的时候就引用设为空，死结就解开了．</p>
<ul>
<li><strong>9. defineProperty, hasOwnProperty, isEnumerable都是做什么用的？</strong></li>
</ul>
<p>参考答案：Object.defineProperty(obj, prop, descriptor)用来给对象定义属性,有value,writable,configurable,enumerable,set/get等.hasOwnProerty用于检查某一属性是不是存在于对象本身，继承来的父亲的属性不算．isEnumerable用来检测某一属性是否可遍历，也就是能不能用for..in循环来取到.</p>
<ul>
<li><strong>10. js常用设计模式的实现思路，单例，工厂，代理，装饰，观察者模式等</strong></li>
</ul>
<p>参考答案：</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-c1">1) 单例：　任意对象都是单例，无须特别处理
    <span class="pl-k">var obj = {name: <span class="pl-s"><span class="pl-pds">'michaelqin', age: 30};

    2) 工厂: 就是同样形式参数返回不同的实例
    function <span class="pl-en">Person() { <span class="pl-v">this.name = 'Person1'; }
    function Animal() { this.name = 'Animal1'; }

    function Factory() {}
    Factory.prototype.getInstance = function(<span class="pl-smi">className) {
        return eval('new ' + className + '()');
    }

    var factory = new Factory();
    var obj1 = factory.getInstance('Person');
    var obj2 = factory.getInstance('Animal');
    console.log(obj1.name); <span class="pl-c">// Person1
    console.log(obj2.name); // Animal1

    3) 代理: 就是新建个类调用老类的接口,包一下
    function Person() { }
    Person.prototype.sayName = function() { console.log('michaelqin'); }
    Person.prototype.sayAge = function() { console.log(30); }

    function PersonProxy() { 
        this.person = new Person();
        var that = this;
        this.callMethod = function(functionName) {
            console.log('before proxy:', functionName);
            that.person[functionName](); // 代理
            console.log('after proxy:', functionName);
        }
    }

    var pp = new PersonProxy();
    pp.callMethod('sayName'); // 代理调用Person的方法sayName()
    pp.callMethod('sayAge'); // 代理调用Person的方法sayAge() 

    4) 观察者: 就是事件模式，比如按钮的onclick这样的应用.
    function Publisher() {
        this.listeners = [];
    }
    Publisher.prototype = {
        'addListener': function(listener) {
            this.listeners.push(listener);
        },

        'removeListener': function(listener) {
            delete this.listeners[listener];
        },

        'notify': function(obj) {
            for(var i = 0; i &lt; this.listeners.length; i++) {
                var listener = this.listeners[i];
                if (typeof listener !== 'undefined') {
                    listener.process(obj);
                }
            }
        }
    }; // 发布者

    function Subscriber() {

    }
    Subscriber.prototype = {
        'process': function(obj) {
            console.log(obj);
        }
    };　// 订阅者


    var publisher = new Publisher();
    publisher.addListener(new Subscriber());
    publisher.addListener(new Subscriber());
    publisher.notify({name: 'michaelqin', ageo: 30}); // 发布一个对象到所有订阅者
    publisher.notify('2 subscribers will both perform process'); // 发布一个字符串到所有订阅者</span></span></span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>11. 列举数组相关的常用方法</strong></li>
</ul>
<p>参考答案: push/pop, shift/unshift, split/join, slice/splice/concat, sort/reverse, map/reduce, forEach, filter</p>
<ul>
<li><strong>12. 列举字符串相关的常用方法</strong></li>
</ul>
<p>参考答案: indexOf/lastIndexOf/charAt, split/match/test, slice/substring/substr, toLowerCase/toUpperCase</p>
<h2><a id="user-content-node核心内置类库事件流文件网络等" class="anchor" href="/goto/143g" rel="nofollow"></a><a name="user-content-nodeCore"></a>node核心内置类库(事件，流，文件，网络等)</h2>
<h3><a id="user-content-node概览" class="anchor" href="/goto/guxb" rel="nofollow"></a>node概览</h3>
<ul>
<li><strong>1. 为什么要用node?</strong></li>
</ul>
<p>参考答案: 总结起来node有以下几个特点:简单强大，轻量可扩展．简单体现在node使用的是javascript,json来进行编码，人人都会；强大体现在非阻塞IO,可以适应分块传输数据，较慢的网络环境，尤其擅长高并发访问；轻量体现在node本身既是代码，又是服务器，前后端使用统一语言;可扩展体现在可以轻松应对多实例，多服务器架构，同时有海量的第三方应用组件．</p>
<ul>
<li><strong>2. node的构架是什么样子的?</strong></li>
</ul>
<p>参考答案: 主要分为三层，应用app &gt;&gt; V8及node内置架构 &gt;&gt; 操作系统. V8是node运行的环境，可以理解为node虚拟机．node内置架构又可分为三层: 核心模块(javascript实现) &gt;&gt; c++绑定 &gt;&gt; libuv + CAes + http.</p>
<p><a href="/goto/x4ix" target="_blank" rel="nofollow noopener"><img decoding="async" src="https://camo.githubusercontent.com/233315761d49d4c75fe7969e36bda22ecf5bbc0f/687474703a2f2f6a6f616f7073696c76612e6769746875622e696f2f74616c6b732f456e642d746f2d456e642d4a6176615363726970742d776974682d7468652d4d45414e2d537461636b2f696d672f6e6f64656a732d617263682d7070742e706e67" alt="" data-canonical-src="http://joaopsilva.github.io/talks/End-to-End-JavaScript-with-the-MEAN-Stack/img/nodejs-arch-ppt.png" /></a></p>
<ul>
<li><strong>3. node有哪些核心模块?</strong></li>
</ul>
<p>参考答案: EventEmitter, Stream, FS, Net和全局对象</p>
<h3><a id="user-content-node全局对象" class="anchor" href="/goto/x7hg" rel="nofollow"></a>node全局对象</h3>
<ul>
<li><strong>1. node有哪些全局对象?</strong></li>
</ul>
<p>参考答案: process, console, Buffer和exports</p>
<ul>
<li><strong>2. process有哪些常用方法?</strong></li>
</ul>
<p>参考答案: process.stdin, process.stdout, process.stderr, process.on, process.env, process.argv, process.arch, process.platform, process.exit</p>
<ul>
<li><strong>3. console有哪些常用方法?</strong></li>
</ul>
<p>参考答案: console.log/console.info, console.error/console.warning, console.time/console.timeEnd, console.trace, console.table</p>
<ul>
<li><strong>4. node有哪些定时功能?</strong></li>
</ul>
<p>参考答案: setTimeout/clearTimeout, setInterval/clearInterval, setImmediate/clearImmediate, process.nextTick</p>
<ul>
<li><strong>5. node中的事件循环是什么样子的?</strong></li>
</ul>
<p>参考答案: event loop其实就是一个事件队列，先加入先执行，执行完一次队列，再次循环遍历看有没有新事件加入队列．执行中的叫IO events, setImmediate是在当前队列立即执行,setTimout/setInterval是把执行定时到下一个队列，process.nextTick是在当前执行完，下次遍历前执行．所以总体顺序是: IO events &gt;&gt; setImmediate &gt;&gt; setTimeout/setInterval &gt;&gt; process.nextTick</p>
<ul>
<li><strong>6. node中的Buffer如何应用?</strong></li>
</ul>
<p>参考答案: Buffer是用来处理二进制数据的，比如图片，mp3,数据库文件等.Buffer支持各种编码解码，二进制字符串互转．</p>
<h3><a id="user-content-eventemitter" class="anchor" href="/goto/9iwd" rel="nofollow"></a>EventEmitter</h3>
<ul>
<li><strong>1. 什么是EventEmitter?</strong></li>
</ul>
<p>参考答案: EventEmitter是node中一个实现观察者模式的类，主要功能是监听和发射消息，用于处理多模块交互问题.</p>
<ul>
<li><strong>2. 如何实现一个EventEmitter?</strong></li>
</ul>
<p>参考答案: 主要分三步：定义一个子类，调用构造函数，继承EventEmitter</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">var util = <span class="pl-c1">require(<span class="pl-s"><span class="pl-pds">'util');
    var EventEmitter = require('events').EventEmitter;

    function <span class="pl-en">MyEmitter() {
        EventEmitter.call(<span class="pl-v">this);
    } <span class="pl-c">// 构造函数

    util.inherits(MyEmitter, EventEmitter); // 继承

    var em = new MyEmitter();
    em.on('hello', function(<span class="pl-smi">data) {
        console.log('收到事件hello的数据:', data);
    }); // 接收事件，并打印到控制台
    em.emit('hello', 'EventEmitter传递消息真方便!');</span></span></span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>3. EventEmitter有哪些典型应用?</strong></li>
</ul>
<p>参考答案: 1) 模块间传递消息 2) 回调函数内外传递消息 3) 处理流数据，因为流是在EventEmitter基础上实现的. 4) 观察者模式发射触发机制相关应用</p>
<ul>
<li><strong>4. 怎么捕获EventEmitter的错误事件?</strong></li>
</ul>
<p>参考答案: 监听error事件即可．如果有多个EventEmitter,也可以用domain来统一处理错误事件.</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">var domain = <span class="pl-c1">require(<span class="pl-s"><span class="pl-pds">'domain');
    var myDomain = domain.create();
    myDomain.on('error', function(<span class="pl-smi">err){
        <span class="pl-en">console.log('domain接收到的错误事件:', err);
    }); <span class="pl-c">// 接收事件并打印
    myDomain.run(function(){
        var emitter1 = new MyEmitter();
        emitter1.emit('error', '错误事件来自emitter1');
        emitter2 = new MyEmitter();
        emitter2.emit('error', '错误事件来自emitter2');
    });</span></span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>5. EventEmitter中的newListenser事件有什么用处?</strong></li>
</ul>
<p>参考答案: newListener可以用来做事件机制的反射，特殊应用，事件管理等．当任何on事件添加到EventEmitter时，就会触发newListener事件，基于这种模式，我们可以做很多自定义处理.</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">var emitter3 = new <span class="pl-en">MyEmitter();
emitter3.on(<span class="pl-s"><span class="pl-pds">'newListener', function(<span class="pl-smi">name, listener) {
    console<span class="pl-c1">.log("新事件的名字:", name);
    console.log("新事件的代码:", listener);
    setTimeout(function(){ console.log("我是自定义延时处理机制"); }, 1000);
});
emitter3.on('hello', function(){
    console.log('hello　node');
});</span></span></span></span></span></span></pre>
</div>
<h3><a id="user-content-stream" class="anchor" href="/goto/irdg" rel="nofollow"></a>Stream</h3>
<ul>
<li><strong>1. 什么是Stream?</strong></li>
</ul>
<p>参考答案: stream是基于事件EventEmitter的数据管理模式．由各种不同的抽象接口组成，主要包括可写，可读，可读写，可转换等几种类型．</p>
<ul>
<li><strong>2. Stream有什么好处?</strong></li>
</ul>
<p>参考答案: 非阻塞式数据处理提升效率，片断处理节省内存，管道处理方便可扩展等.</p>
<ul>
<li><strong>3. Stream有哪些典型应用?</strong></li>
</ul>
<p>参考答案: 文件，网络，数据转换，音频视频等.</p>
<ul>
<li><strong>4. 怎么捕获Stream的错误事件?</strong></li>
</ul>
<p>参考答案: 监听error事件，方法同EventEmitter.</p>
<ul>
<li><strong>5. 有哪些常用Stream,分别什么时候使用?</strong></li>
</ul>
<p>参考答案: Readable为可被读流，在作为输入数据源时使用；Writable为可被写流,在作为输出源时使用；Duplex为可读写流,它作为输出源接受被写入，同时又作为输入源被后面的流读出．Transform机制和Duplex一样，都是双向流，区别时Transfrom只需要实现一个函数_transfrom(chunk, encoding, callback);而Duplex需要分别实现_read(size)函数和_write(chunk, encoding, callback)函数.</p>
<ul>
<li><strong>6. 实现一个Writable Stream?</strong></li>
</ul>
<p>参考答案: 三步走:1)构造函数call Writable 2)　继承Writable 3) 实现_write(chunk, encoding, callback)函数</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre><span class="pl-k">var Writable = <span class="pl-c1">require(<span class="pl-s"><span class="pl-pds">'stream').Writable;
var util = require('util');

function <span class="pl-en">MyWritable(<span class="pl-smi">options) {
    Writable.call(<span class="pl-v">this, options);
} <span class="pl-c">// 构造函数
util.inherits(MyWritable, Writable); // 继承自Writable
MyWritable.prototype._write = function(chunk, encoding, callback) {
    console.log("被写入的数据是:", chunk.toString()); // 此处可对写入的数据进行处理
    callback();
};

process.stdin.pipe(new MyWritable()); // stdin作为输入源，MyWritable作为输出源   </span></span></span></span></span></span></span></span></pre>
</div>
<h3><a id="user-content-文件系统" class="anchor" href="/goto/pu7z" rel="nofollow"></a>文件系统</h3>
<ul>
<li><strong>1. 内置的fs模块架构是什么样子的?</strong></li>
</ul>
<p>参考答案: fs模块主要由下面几部分组成: 1) POSIX文件Wrapper,对应于操作系统的原生文件操作 2) 文件流 fs.createReadStream和fs.createWriteStream 3) 同步文件读写,fs.readFileSync和fs.writeFileSync 4) 异步文件读写, fs.readFile和fs.writeFile</p>
<ul>
<li><strong>2. 读写一个文件有多少种方法?</strong></li>
</ul>
<p>参考答案: 总体来说有四种: 1) POSIX式低层读写 2) 流式读写 3) 同步文件读写 4) 异步文件读写</p>
<ul>
<li><strong>3. 怎么读取json配置文件?</strong></li>
</ul>
<p>参考答案: 主要有两种方式，第一种是利用node内置的require(&#8216;data.json&#8217;)机制，直接得到js对象; 第二种是读入文件入内容，然后用JSON.parse(content)转换成js对象．二者的区别是require机制情况下，如果多个模块都加载了同一个json文件，那么其中一个改变了js对象，其它跟着改变，这是由node模块的缓存机制造成的，只有一个js模块对象; 第二种方式则可以随意改变加载后的js变量，而且各模块互不影响，因为他们都是独立的，是多个js对象.</p>
<ul>
<li><strong>4. fs.watch和fs.watchFile有什么区别，怎么应用?</strong></li>
</ul>
<p>参考答案: 二者主要用来监听文件变动．fs.watch利用操作系统原生机制来监听，可能不适用网络文件系统; fs.watchFile则是定期检查文件状态变更，适用于网络文件系统，但是相比fs.watch有些慢，因为不是实时机制．</p>
<h3><a id="user-content-网络" class="anchor" href="/goto/ybcr" rel="nofollow"></a>网络</h3>
<ul>
<li><strong>1. node的网络模块架构是什么样子的?</strong></li>
</ul>
<p>参考答案: node全面支持各种网络服务器和客户端，包括tcp, http/https, tcp, udp, dns, tls/ssl等.</p>
<ul>
<li><strong>2. node是怎样支持https,tls的?</strong></li>
</ul>
<p>参考答案: 主要实现以下几个步骤即可: 1) openssl生成公钥私钥 2) 服务器或客户端使用https替代http 3) 服务器或客户端加载公钥私钥证书</p>
<ul>
<li><strong>3. 实现一个简单的http服务器?</strong></li>
</ul>
<p>参考答案: 经典又很没毛意义的一个题目．思路是加载http模块，创建服务器，监听端口.</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">var http = <span class="pl-c1">require(<span class="pl-s"><span class="pl-pds">'http'); <span class="pl-c">// 加载http模块

    http.createServer(function(<span class="pl-smi">req, res) {
        res.writeHead(200, {'Content-Type': 'text/html'}); // 200代表状态成功, 文档类型是给浏览器识别用的
        res.write('&lt;meta charset="UTF-8"&gt; &lt;h1&gt;我是标题啊！&lt;/h1&gt; &lt;font color="red"&gt;这么原生，初级的服务器，下辈子能用着吗?!&lt;/font&gt;'); // 返回给客户端的html数据
        res.end(); // 结束输出流
    }).listen(3000); // 绑定3ooo, 查看效果请访问 http://localhost:3000/ </span></span></span></span></span></span></pre>
</div>
<h3><a id="user-content-child-process" class="anchor" href="/goto/obuo" rel="nofollow"></a>child-process</h3>
<ul>
<li><strong>1. 为什么需要child-process?</strong></li>
</ul>
<p>参考答案: node是异步非阻塞的，这对高并发非常有效．可是我们还有其它一些常用需求，比如和操作系统shell命令交互，调用可执行文件，创建子进程进行阻塞式访问或高CPU计算等，child-process就是为满足这些需求而生的．child-process顾名思义，就是把node阻塞的工作交给子进程去做．</p>
<ul>
<li><strong>2. exec,execFile,spawn和fork都是做什么用的?</strong></li>
</ul>
<p>参考答案: exec可以用操作系统原生的方式执行各种命令，如管道 cat ab.txt | grep hello; execFile是执行一个文件; spawn是流式和操作系统进行交互; fork是两个node程序(javascript)之间时行交互.</p>
<ul>
<li><strong>3. 实现一个简单的命令行交互程序?</strong></li>
</ul>
<p>参考答案: 那就用spawn吧.</p>
<p>代码演示</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">var cp = <span class="pl-c1">require(<span class="pl-s"><span class="pl-pds">'child_process');

    var child = cp.spawn('echo', ['你好', "钩子"]); <span class="pl-c">// 执行命令
    child.stdout.pipe(process.stdout); // child.stdout是输入流，process.stdout是输出流
    // 这句的意思是将子进程的输出作为当前程序的输入流，然后重定向到当前程序的标准输出，即控制台</span></span></span></span></span></pre>
</div>
<ul>
<li>4. 两个node程序之间怎样交互?</li>
</ul>
<p>参考答案: 用fork嘛，上面讲过了．原理是子程序用process.on, process.send，父程序里用child.on,child.send进行交互.<br />
代码演示</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-c1">1) fork<span class="pl-k">-parent.js
    var cp = require(<span class="pl-s"><span class="pl-pds">'child_process');
    var child = cp.fork('./fork-child.js');
    child.on('message', function(<span class="pl-smi">msg){
        <span class="pl-en">console.log('老爸从儿子接受到数据:', msg);
    });
    child.send('我是你爸爸，送关怀来了!');

    2) fork-child.js
    process.on('message', function(msg){
        console.log("儿子从老爸接收到的数据:", msg);
        process.send("我不要关怀，我要银民币！");
    });</span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>5. 怎样让一个js文件变得像linux命令一样可执行?</strong></li>
</ul>
<p>参考答案: 1) 在myCommand.js文件头部加入 #!/usr/bin/env node 2) chmod命令把js文件改为可执行即可 3) 进入文件目录，命令行输入myComand就是相当于node myComand.js了</p>
<ul>
<li><strong>6. child-process和process的stdin,stdout,stderror是一样的吗?</strong></li>
</ul>
<p>参考答案: 概念都是一样的，输入，输出，错误，都是流．区别是在父程序眼里，子程序的stdout是输入流，stdin是输出流．</p>
<h2><a id="user-content-node高级话题异步部署性能调优异常调试等" class="anchor" href="/goto/4f8b" rel="nofollow"></a><a name="user-content-nodeAdvanced"></a>node高级话题(异步，部署，性能调优，异常调试等)</h2>
<ul>
<li><strong>1. node中的异步和同步怎么理解</strong></li>
</ul>
<p>参考答案: node是单线程的，异步是通过一次次的循环事件队列来实现的．同步则是说阻塞式的IO,这在高并发环境会是一个很大的性能问题，所以同步一般只在基础框架的启动时使用，用来加载配置文件，初始化程序什么的．</p>
<ul>
<li><strong>2. 有哪些方法可以进行异步流程的控制?</strong></li>
</ul>
<p>参考答案: 1) 多层嵌套回调 2)　为每一个回调写单独的函数，函数里边再回调 3) 用第三方框架比方async, q, promise等</p>
<ul>
<li><strong>3. 怎样绑定node程序到80端口?</strong></li>
</ul>
<p>参考答案: 多种方式 1) sudo 2) apache/nginx代理 3) 用操作系统的firewall iptables进行端口重定向</p>
<ul>
<li><strong>4. 有哪些方法可以让node程序遇到错误后自动重启?</strong></li>
</ul>
<p>参考答案: 1) runit 2) forever 3) nohup npm start &amp;</p>
<ul>
<li><strong>5. 怎样充分利用多个CPU?</strong></li>
</ul>
<p>参考答案: 一个CPU运行一个node实例</p>
<ul>
<li><strong>6. 怎样调节node执行单元的内存大小?</strong></li>
</ul>
<p>参考答案: 用&#8211;max-old-space-size 和 &#8211;max-new-space-size 来设置 v8 使用内存的上限</p>
<ul>
<li><strong>7. 程序总是崩溃，怎样找出问题在哪里?</strong></li>
</ul>
<p>参考答案: 1) node &#8211;prof 查看哪些函数调用次数多 2) memwatch和heapdump获得内存快照进行对比，查找内存溢出</p>
<ul>
<li><strong>8. 有哪些常用方法可以防止程序崩溃?</strong></li>
</ul>
<p>参考答案: 1) try-catch-finally 2) EventEmitter/Stream error事件处理 3) domain统一控制 4) jshint静态检查 5) jasmine/mocha进行单元测试</p>
<ul>
<li><strong>9. 怎样调试node程序?</strong></li>
</ul>
<p>参考答案: node &#8211;debug app.js 和node-inspector</p>
<h2><a id="user-content-常用知名第三方类库async-express等" class="anchor" href="/goto/f3xe" rel="nofollow"></a><a name="user-content-node3rd"></a>常用知名第三方类库(Async, Express等)</h2>
<ul>
<li><strong>1. async都有哪些常用方法，分别是怎么用?</strong></li>
</ul>
<p>参考答案: async是一个js类库，它的目的是解决js中异常流程难以控制的问题．async不仅适用在node.js里，浏览器中也可以使用． 1) async.parallel并行执行完多个函数后，调用结束函数</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">async.parallel([
        function(){ ... },
        function(){ ... }
    ], callback);</span></pre>
</div>
<p>2) async.series串行执行完多个函数后，调用结束函数</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">async.series([
        function(){ ... },
        function(){ ... }
    ]);</span></pre>
</div>
<p>3) async.waterfall依次执行多个函数，后一个函数以前面函数的结果作为输入参数</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">async.waterfall([
        function(<span class="pl-smi">callback) {
            callback(<span class="pl-c1">null, <span class="pl-s"><span class="pl-pds">'one', 'two');
        },
        function(arg1, arg2, callback) {
          <span class="pl-c">// arg1 now equals 'one' and arg2 now equals 'two' 
            callback(null, 'three');
        },
        function(arg1, callback) {
            // arg1 now equals 'three' 
            callback(null, 'done');
        }
    ], function (err, result) {
        // result now equals 'done' 
    });</span></span></span></span></span></span></pre>
</div>
<p>4) async.map异步执行多个数组，返回结果数组</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">async.map([<span class="pl-s"><span class="pl-pds">'file1','file2','file3'], fs.stat, function(<span class="pl-smi">err, results){
        <span class="pl-c">// results is now an array of stats for each file 
    });</span></span></span></span></span></pre>
</div>
<p>5) async.filter异步过滤多个数组，返回结果数组</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">async.filter([<span class="pl-s"><span class="pl-pds">'file1','file2','file3'], fs.exists, function(<span class="pl-smi">results){
        <span class="pl-c">// results now equals an array of the existing files 
    });</span></span></span></span></span></pre>
</div>
<ul>
<li><strong>2. express项目的目录大致是什么样子的</strong></li>
</ul>
<p>参考答案: app.js, package.json, bin/www, public, routes, views.</p>
<ul>
<li><strong>3. express常用函数</strong></li>
</ul>
<p>参考答案: express.Router路由组件,app.get路由定向，app.configure配置，app.set设定参数,app.use使用中间件</p>
<ul>
<li><strong>4. express中如何获取路由的参数</strong></li>
</ul>
<p>参考答案: /users/:name使用req.params.name来获取; req.body.username则是获得表单传入参数username; express路由支持常用通配符 ?, +, *, and ()</p>
<ul>
<li><strong>5. express response有哪些常用方法</strong></li>
</ul>
<p>参考答案: res.download() 弹出文件下载<br />
res.end() 结束response<br />
res.json() 返回json<br />
res.jsonp() 返回jsonp<br />
res.redirect() 重定向请求<br />
res.render() 渲染模板<br />
res.send() 返回多种形式数据<br />
res.sendFile 返回文件<br />
res.sendStatus() 返回状态</p>
<h2><a id="user-content-其它相关后端常用技术mongodb-redis-apache-nginx等" class="anchor" href="/goto/wzxv" rel="nofollow"></a><a name="user-content-otherBackend"></a>其它相关后端常用技术(MongoDB, Redis, Apache, Nginx等)</h2>
<ul>
<li><strong>1. mongodb有哪些常用优化措施</strong></li>
</ul>
<p>参考答案: 类似传统数据库，索引和分区．</p>
<ul>
<li><strong>2. redis支持哪些功能</strong></li>
</ul>
<p>参考答案: set/get, hset/hget, publish/subscribe, expire</p>
<ul>
<li><strong>3. redis最简单的应用</strong></li>
</ul>
<p>参考答案:</p>
<div class="highlight highlight-source-js">
<pre>    <span class="pl-k">var redis = <span class="pl-c1">require(<span class="pl-s"><span class="pl-pds">"redis"),
        client = redis.createClient();

    client.set("foo_rand000000000000", "some fantastic value");
    client.get("foo_rand000000000000", function (<span class="pl-smi">err, reply) {
        <span class="pl-en">console.log(reply.toString());
    });
    client.end();</span></span></span></span></span></span></pre>
</div>
<ul>
<li><strong>4. apache,nginx有什么区别?</strong></li>
</ul>
<p>参考答案: 二者都是代理服务器，功能类似．apache应用简单，相当广泛．nginx在分布式，静态转发方面比较有优势．</p>
<h2><a id="user-content-常用前端技术html5-css3-jquery等" class="anchor" href="/goto/syd6" rel="nofollow"></a><a name="user-content-otherFrontEnd"></a>常用前端技术(Html5, CSS3, JQuery等)</h2>
<ul>
<li><strong>1. Html5有哪些比较实用新功能</strong></li>
</ul>
<p>参考答案: File API支持本地文件操作; Canvans/SVG支持绘图; 拖拽功能支持; 本地存储支持; 表单多属性验证支持; 原生音频视频支持等</p>
<ul>
<li><strong>2. CSS3/JQuery有哪些学常见选择器</strong></li>
</ul>
<p>参考答案: id, 元素，属性, 值，父子兄弟, 序列等</p>
<ul>
<li><strong>3. JQuery有哪些经典应用</strong></li>
</ul>
<p>参考答案: 文档选择，文档操作，动画, ajax, json, js扩展等.</p>
<h1><a id="user-content-nodejs-设计模式" class="anchor" href="/goto/o8pw" rel="nofollow" aria-hidden="true"></a>node.js 设计模式</h1>
<ul>
<li>HeadFirstDesignPatternInJavascript</li>
<li>HeadFirstDesignPattern是一本非常经典的设计模式入门书籍。可是Javascript由于语言本身的限制，比较难以应用。随着新浏览器和Node.js开始普遍支持ES5, ES6,尤其是对类的支持。设计模式已经变得触手可及，对于大型Node.js项目更是非常必要。 HeadFirstDesignPatternInJavascript正是js版本的设计模式实现。</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>/uncategorized/8689.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>中国平安 1768游戏开发部 201905 EAP 活动</title>
		<link>/%e8%b5%84%e6%96%99/8737.html</link>
					<comments>/%e8%b5%84%e6%96%99/8737.html#respond</comments>
		
		<dc:creator><![CDATA[Mr.Lee]]></dc:creator>
		<pubDate>Thu, 30 May 2019 12:44:18 +0000</pubDate>
				<category><![CDATA[资料]]></category>
		<guid isPermaLink="false">/?p=8737</guid>

					<description><![CDATA[中国平安 1768游戏开发部 201905 EAP 活动#]]></description>
										<content:encoded><![CDATA[<h1><a href="/goto/5xtt" rel="nofollow">中国平安 1768游戏开发部 201905 EAP 活动#</a></h1>
<p><a href="/goto/c1k7" rel="nofollow"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-8738" src="/wp-content/uploads/2019/09/IMG_9921.jpg" alt="" width="6075" height="4047" srcset="/wp-content/uploads/2019/09/IMG_9921.jpg 6075w, /wp-content/uploads/2019/09/IMG_9921-300x200.jpg 300w, /wp-content/uploads/2019/09/IMG_9921-768x512.jpg 768w, /wp-content/uploads/2019/09/IMG_9921-1024x682.jpg 1024w" sizes="(max-width: 6075px) 100vw, 6075px" /></a></p>
]]></content:encoded>
					
					<wfw:commentRss>/%e8%b5%84%e6%96%99/8737.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
