https://stackoverflow.com/questions/1763639/how-to-deal-with-page-breaks-when-printing-a-large-html-table
分类: 技术
Laravel 事件
事件类通常被保存在 app/Events 目录下,而它们的处理程序则被保存在 app/Handlers/Events 目录下。
leokim\app\Events\LeokimTestEvent.php
<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Queue\SerializesModels; use Illuminate\Broadcasting\PrivateChannel; use Illuminate\Broadcasting\PresenceChannel; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class LeokimTestEvent { use Dispatchable, InteractsWithSockets, SerializesModels; /** * Create a new event instance. * * @return void */ public function __construct() { // } /** * Get the channels the event should broadcast on. * * @return Channel|array */ public function broadcastOn() { return new PrivateChannel('channel-name'); } }
1.创建事件
php artisan make:event LeokimTestEvent
2.创建事件handle
leokim\app\Handlers\Events\LeokimTestEventHandler.php
<?php namespace App\Handlers\Events; use App\Events\LeokimTestEvent; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldBeQueued; class LeokimTestEventHandler{ public function __construct() { } public function handle(LeokimTestEvent $event) { echo '<br>事件触发测试'; } }
3.在EventServiceProvider中注册
leokim\app\Providers\EventServiceProvider.php
<?php namespace App\Providers; use Illuminate\Support\Facades\Event; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider { /** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'App\Events\Event' => [ 'App\Listeners\EventListener', ], 'App\Events\LeokimTestEvent' => [ 'App\Handlers\Events\LeokimTestEventHandler', ], ]; /** * Register any events for your application. * * @return void */ public function boot() { parent::boot(); // } }
4.在controller中触发
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Events\LeokimTestEvent; class LeokimController extends Controller { protected $leo; function __construct($leo) { $this->leo = $leo; } function index(){ echo '123'; event(new LeokimTestEvent()); } function test($id){ return $this->leo.$id; } }
Laravel Contracts 学习笔记
Laravel 的 Contracts 是一组定义了框架核心服务的接口。说白了就是一组接口。使用它就是为了降低耦合性。
即便如此,是不是也有同学会搞不清楚Contracts在lavarel体系中的到底在一个什么样的位置?下面上一张自制的图,也许有地方不对,但是初学的同学可以通过它大概的,简单的解决下心中的困惑。
通过这张图我们可以看到,当写好自定义的Contract接口及其实现类后,在ServiceProvider中绑定,此时服务容器已经登记上这个Contract了。之后就可以在要用到它的地方,经过服务容器解析直接使用了。
下面就详细写一下怎么具体的使用:
第一步,写一个Contract接口:
<?php namespace App\Contracts; interface LeokimContract { public function test($id); }
第二步,写上面Contract的实现类:
<?php use App\Contracts\LeokimContract; class LeokimService implements LeokimContract { function test($id){ return "ID is :".$id; } }
第三步,写一个自定义的ServiceProvider:
<?php namespace App\Providers; use App\Http\Controllers\LeokimController; use Illuminate\Support\ServiceProvider; class LeokimProviders extends ServiceProvider { /** * Bootstrap the application services. * * @return void */ public function boot() { // } /** * Register the application services. * * @return void */ public function register() { //简单绑定 // $this->app->bind(LeokimController::class, function (){ // return new LeokimController('LeoKim-Test!! '); // }); //给Contracts一个别名 // $this->app->bind('LeokimContract','APP\Contracts\LeokimContract'); //绑定接口到实现 $this->app->bind('App\Contracts\LeokimContract','App\Services\LeokimService'); } }
这里起别名的作用,是为了在使用的时候方便,不需要写完整的命名空间;绑定的作用是为了使用Contracts时,服务容器能够有线索找到它的实现类,从而解析出来。
第四步,在config\app.PHP中注册这个服务提供者:
在providers中加入这行代码即可:
App\Providers\HelloServiceProvider::class,
第五步,可以使用了:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Contracts\LeokimContract; class LeokimController extends Controller { protected $leo; // function __construct($leo) // { // $this->leo = $leo; // } function __construct(LeokimContract $leo) { $this->leo = $leo; } // function index(){ // echo '123'; // } function test($id){ return $this->leo->test($id); } }
-
在构造方法中,将Contract接口引入(注入)这里参数中‘LeokimContract’就是刚才起的别名。
-
因为刚才已经在服务提供者中绑定了Contract和其实现方法,所以这里能够通过LeokimContract这个Contract,解析并使用其实现类中的方法test().
使用免费的ssl证书
小程序ajax请求都需要https 没办法 我只有自己弄一下
我这里要介绍的是另外一个 acme.sh 这个是用 Shell 脚本编写的,安装更容易,Let's Encrypt 那个 certbot
工具需要安装一大堆系统库以及 python 库,Python 的 pip 在国内还会有墙的问题…
安装acme.sh
curl https://get.acme.sh | sh
然后重新载入一下
source ~/.bashrc
现在就可以执行acme.sh命令了
acme.sh --issue -d ssl.leokim.cn -w /data/wwwroot/default/ssl
这个以后就生成秘钥了
放到指定文件夹下
用阿里云创建虚拟主机的程序跑就行了
http://www.07net01.com/2017/01/1769454.html
======================================
昨天那个用不了 浏览器报不安全 然后今天我重新操作了一下
git clone https://github.com/letsencrypt/letsencrypt cd letsencrypt ./letsencrypt-auto certonly --manual -d ssl.leokim.cn //证书在下面文件夹里 cd /etc/letsencrypt/live/ssl.leokim.cn/ //然后修改httpd配置文件 填好证书路径就好了 <VirtualHost *:443> ServerAdmin admin@linuxeye.com DocumentRoot "/data/wwwroot/default/ssl" ServerName ssl.leokim.cn SSLEngine on SSLCertificateFile "/etc/letsencrypt/archive/ssl.leokim.cn/fullchain1.pem" SSLCertificateKeyFile "/etc/letsencrypt/archive/ssl.leokim.cn/privkey1.pem" ErrorLog "/data/wwwlogs/ssl.leokim.cn_error_apache.log" CustomLog "/data/wwwlogs/ssl.leokim.cn_apache.log" common <Directory "/data/wwwroot/default/ssl"> SetOutputFilter DEFLATE Options FollowSymLinks ExecCGI Require all granted AllowOverride All Order allow,deny Allow from all DirectoryIndex index.html index.php </Directory> </VirtualHost>
计算得出非连续数字分段
<?php
$array = array(10010,10011,10012,10013,10015,10016,10026,10027,10028,10029);
$range = get_num_range($array);
print_r($range);
function get_num_range($arr){
$range = array();
$i = 1;
$tmp_min = $tmp_max = '';
foreach($arr as $no){
//如果没有此range的最小值 第一个就是最小值
if(empty($tmp_min)){
$tmp_min = $no;
}
//下一个值不存在计算出最大值
$next_no = $no+1;
if(!in_array($next_no,$arr) && !empty($next_no)){
$tmp_max = $no;
$range[] = array($tmp_min, $tmp_max);
$tmp_min = '';
}
}
return $range;
}
?>
MySQL 事务,锁
ACID
-
Atomic同一个事务里,要么都提交,要么都回滚
-
Consistency即在事务开始之前和事务结束之后,数据库的完整性约束没有被破坏
-
Isolation 并发事务间的数据是彼此隔离的
-
Durabiliy 事务提交后,所有结果务必被持久化
支持事务:InnoDB,NDBCluster, TokuDB
不支持事务:MyISAM,MEMORY
-
隔离性通过锁实现
-
原子性,一致性,持久性通过数据库的redo和undo来完成
撤销日志: UNDO LOG (现在正在活跃的事务,但还没有提交,或者还没有完成check point)
重做日志:REDO LOG (已经提交的事务)
REDO 和 UNDO 在做数据库恢复的时候的作用是相反的,
RODO:在做数据库恢复的时候,如果有事务还没有真正的提交,那么需要前滚(扫描RODO LOG检查哪些事务已经提交了,但还没有持久化到数据文件【table spacs, data table spage】里的,再把这些重做一次事务【再重新提交一次】)
UNDO: 正好是相反 找到还没有提交的事务 但是再undo log里需要进行一次回滚,就是把已经提交的事务回滚掉
在做数据库恢复的时候要做这样的一个过程
autocommit = 0|1
设置事务自动 开启|关闭
显示事务 启动 | 关闭
-
以START TRANSACTION/BEGIN开始事务
-
以COMMIT/ROLLBACK TRANSACTION结束事务
隐性事务提交
主要是DDL,DCL会引发事务的隐性提交
MySQL 多列索引的生效规则
mysql中 myisam,innodb默认使用的是 Btree索引,至于btree的数据结构是怎样的都不重要,
只需要知道结果,既然是索引那这个数据结构最后是排好序;就像新华字典他的目录就是按照a,b,c..这样排好序的;
所以你在找东西的时候才快,比如你找 “中” 这个字的解释,你肯定就会定位到目录的 z 开头部分;
组合索引可以这样理解,比如(a,b,c),abc都是排好序的,在任意一段a的下面b都是排好序的,任何一段b下面c都是排好序的;
组合索引的生效原则是 从前往后依次使用生效,如果中间某个索引没有使用,那么断点前面的索引部分起作用,断点后面的索引没有起作用;
比如
where a=3 and b=45 and c=5 .... 这种三个索引顺序使用中间没有断点,全部发挥作用; where a=3 and c=5... 这种情况下b就是断点,a发挥了效果,c没有效果 where b=3 and c=4... 这种情况下a就是断点,在a后面的索引都没有发挥作用,这种写法联合索引没有发挥任何效果; where b=45 and a=3 and c=5 .... 这个跟第一个一样,全部发挥作用,abc只要用上了就行,跟写的顺序无关
(a,b,c) 三个列上加了联合索引(是联合索引 不是在每个列上单独加索引)
还需注意, (a,b,c)多列索引和 (a,c,b)是不一样的,看上面的图也看得出来关系顺序是不一样的;
分析几个实际例子来加强理解;
分析句子中使用的索引情况
select * from mytable where a=3 and b=5 and c=4; abc三个索引都在where条件里面用到了,而且都发挥了作用 select * from mytable where c=4 and b=6 and a=3; 这条语句列出来只想说明 mysql没有那么笨,where里面的条件顺序在查询之前会被mysql自动优化,效果跟上一句一样 select * from mytable where a=3 and c=7; a用到索引,b没有用,所以c是没有用到索引效果的 select * from mytable where a=3 and b>7 and c=3; a用到了,b也用到了,c没有用到,这个地方b是范围值,也算断点,只不过自身用到了索引 select * from mytable where b=3 and c=4; 因为a索引没有使用,所以这里 bc都没有用上索引效果 select * from mytable where a>4 and b=7 and c=9; a用到了 b没有使用,c没有使用 select * from mytable where a=3 order by b; a用到了索引,b在结果排序中也用到了索引的效果,前面说了,a下面任意一段的b是排好序的 select * from mytable where a=3 order by c; a用到了索引,但是这个地方c没有发挥排序效果,因为中间断点了,使用 explain 可以看到 filesort select * from mytable where b=3 order by a; b没有用到索引,排序中a也没有发挥索引效果
MySQL 索引使用笔记
用voucher表来做单表测试
-
创建voucher_id为主键
-
创建voucher_idx(voucher_id, prefix, voucher_no)
当我查主键的时候毫无疑问 肯定是走主键索引的
当我只查找主键字段的时候 Extra显示“Using index”不回表直接使用到覆盖索引
可以看到 当查询条件里有主键的时候 查询会直接用主键查询 可能是因为主键是唯一索引 直接就定位到是最简方法
下面不用主键来做条件, 直接用voucher_idx里的字段来查找
可以看到type变成了ref 不再是有主键时的const
ref:是一种索引访问(有时也叫索引查找),它返回所有匹配某个单个值的行。然而,它可能会找到多个符合条件的行,因此它是查找和扫描的混合体…
可以看到找到了45310条记录,测试的voucher总数是319814 45310/319814≈0.15 不到30%所以还是能使用索引的
但是这就不对了 prefix是‘A10’的占了76% 还是能用到索引 是不是说明“一个值超过30%就无法使用索引”的描述? 可能是新版功能加强了吧
这个确实能证实,不是从索引左侧的列搜索用不到索引,这条语句扫描了319814行
下面这个语句 其实说明了不按索引顺序 也是能用到索引的 应该是索引优化器把where里的索引列又排了下
查了一下优化器执行的代码 好像也没有对索引重排 看来还是service层做了优化让我们能使用到索引?
我又创建了一个索引voucher_idx2,我以为搜索条件是voucher_no, prefix和 prefix,voucher_no的时候会不一样,结果都用到了voucher_idx2
这可以说明当查询条件和搜索条件都在索引内时,不按索引顺序也是能用到索引的,但是扫描了全表
但是查询列或者搜索列里有不在索引列里的列的时候 是会扫描全表的
那我把所有列都拿进来 是不是都能用到索引??
可以看到,其实是走了索引,但是也是扫了全表,效率应该相当差, 需要用数据量很大的库来试一下,如果不按索引顺序来跑的效率
MySQL 高可用
MySQL 什么情况下无法使用索引
-
通过索引扫描的记录超过30%,变成全表扫描
-
联合索引中,第一个索引列使用范围查询
-
联合索引中,第一个查询条件不是最左索引列
-
模糊查询条件列最左以通配符%开始
-
内存表(HEAP)表使用HASH索引时,使用范围检索或者ORDER BY
-
两个独立索引,其中一个用于检索,一个用于排序
-
使用了不同的ORDER BY 和 GROUP BY 表达式
-
索引列检索使用函数
-
两表连接的时候如果连接字段类型不一致是无法使用索引的(其实可以使用,但是需要进行隐式转换,导致没有办法2个表都使用到索引,只有一个表能用到索引,另一个表被隐式转换了 用不到索引 )
2个独立的索引 and的情况下只能用到一个索引,or的情况下可以用到index mearge把结果联合起来