2016年7月20日 星期三

WYSIWYG HTML editor: CKEditor 4.5.10 + CKFinder 2.6.2 整合圖片上傳



CKEditor 4.5.10


CKFinder 2.6.2

以上兩個套件都可以從官網下載
官網連結如下

CKEditor

CKFinder

都下載好之後解壓縮
放在 / 目錄下
分別取名 ckeditor 跟 ckfinder
另外取名一個 uploads 目錄
讓 ckfinder 可以上傳檔案到該目錄
權限設定 777 (全開)

打開 ckeditor/config.js
在 CKEDITOR.editorConfig 加入以下內容



config.filebrowserBrowseUrl = 'ckfinder/ckfinder.html';
config.filebrowserImageBrowseUrl = 'ckfinder/ckfinder.html?Type=Images';
config.filebrowserFlashBrowseUrl = 'ckfinder/ckfinder.html?Type=Flash';
config.filebrowserUploadUrl = 'ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files'; //可上傳一般檔案
config.filebrowserImageUploadUrl = 'ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images';//可上傳圖檔
config.filebrowserFlashUploadUrl = 'ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Flash';//可上傳Flash檔案


打開 ckfinder/config.php
找到 function CheckAuthentication()
將 return false; 改成 return true;
找到 $baseUrl 設定上傳目錄
$baseUrl = '/uploads/';

編輯 test.php

<script src="ckeditor/ckeditor.js"></script>

<textarea class="ckeditor" cols="40" id="editor1" name="content" rows="10"></textarea>


啟動 apache
打開 localhost/test.php
就可以正常使用 ckeditor + ckfinder 了!





PHP7: NULL 合併運算式 (Null coalescing operator)

Null 合併運算式 Null coalescing operator

三元運算式(Ternary operator)結合 isset() 的判斷

原本的寫法
$option = (isset($_GET['option'])) ? $_GET['option'] : 'option';

可改成
$option = $_GET['option'] ?? 'option';

也可以加入 $_POST
分別判斷 $_GET['option']  $_POST['option'] 是否存在
$option = $_GET['option'] ?? $_POST['option'] ?? 'option';

很實用的一個功能


2016年4月28日 星期四

Singleton Design Pattern PHP 實作


突然發現自己關於 PHP 的部分寫得很少
補一篇 Singleton Pattern
最簡單也最實用

網路上有篇舉例得很好
說我們建立了一個類別 P
裡面可能呼叫(或載入)了其他的類別(如 C, D, E)
在某些情況下
我們並不希望類別 P 被重複呼叫多次時
類別 C D E 被重複建立
所以才會有這個 Singleton 的策略模式

實作如下
Controller
<?php
Class Test_Controller
{
public $load = null;
public $db = null;
public function __construct()
{
$this->init();
}

private function init()
{
# 載入共用的 loader
$this->load = load::instance();
# 取得 db 連線
$this->db = $this->load->database();
}

public function __destruct()
{
if(@$this->db) $this->db->close();
}
}


Loader
<?php
final class load
{
static $load = null;
static $db = null;
static $api = null;
public static function instance()
{
if(self::$load == null)
{
self::$load = new load();
}
return self::$load;
}
public static function database($host_name = 'test_cloud', $db_name = '')
{
if(self::$db == null)
{
self::$db = new db();
}
return self::$db->$host_name($db_name);
}
}


之後就可以測試看看
當你呼叫(或繼承) Test_Controller 多次之後
load 跟 db 應該都只會有一個實體

以前對於 Singleton 的認知
只是減少了一些不必要的呼叫
對於小公司而言
感受不大

直到目前轉到電商工作之後
才發覺
在大量被訪問的狀況之下
主機的記憶體與DB的連線數
是需要被嚴格控管的
不然硬體在怎麼擴充都不夠

尤其 database transaction 的問題
如果沒有用 Singleton 的話
commit 會亂七八糟的

所以認識 Singleton Pattern 真的是很重要的一件事情
提供給大家參考

2016年4月26日 星期二

RabbitMQ Cluster + HaProxy

RabbitMQ Cluster + HaProxy

套件版本
RabbitMQ 3.6.1
Erlang 18.3
Java JDK 8u91
HaProxy 1.5.14

4台主機
HaProxy   172.20.10.10
MQ_Master 172.20.10.11
MQ_Slave1 172.20.10.12
MQ_Slave2 172.20.10.13

# RabbitMQ Cluster 實作
請參考 RabbitMQ 3.6.1 Cluster 安裝

# HaProxy 安裝
yum install haproxy

# HaProxy 設定
global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    stats socket /var/lib/haproxy/stats

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

frontend  RabbitmqWeb
    bind *:35672
    mode http
    default_backend             RabbitmqCluster:15672

backend RabbitmqCluster:15672
    log global
    balance     roundrobin
    cookie  SERVERID insert indirect nocache
    server  mq_master 172.20.10.11:15672 inter 10s check cookie s1
    server  mq_slave1 172.20.10.12:15672 inter 10s check cookie s2
    server  mq_slave2 172.20.10.13:15672 inter 10s check cookie s3

listen stats:8888
    bind *:8888
    mode http
stats enable
stats hide-version
stats realm Haproxy\ Statistics
stats uri /
stats auth admin:haproxy
stats refresh 10s

frontend RabbitmqServer
    log global
    bind *:45672
    mode tcp
option tcplog
option logasap
timeout client 168h
    default_backend  RabbitmqCluster:5672

backend RabbitmqCluster:5672
    mode tcp
timeout server 168h
    balance   roundrobin
    server mq_master 172.20.10.11:5672 check inter 1000 fall 3 rise 3
    server mq_slave1 172.20.10.12:5672 check inter 1000 fall 3 rise 3
    server mq_slave2 172.20.10.13:5672 check inter 1000 fall 3 rise 3

# 啟動 HaProxy
systemctl start haproxy
systemctl enable haproxy

# HaProxy 介面
172.20.10.10:8888

# RabbitMQ Web 登入介面
172.20.10.10:35672


# RabbitMQ amqp-lib 設定
define('HOST', '172.20.10.10');
define('PORT', 45672);


2016年4月21日 星期四

RabbitMQ 3.6.1 Cluster 安裝

預備三台機器做 RabbitMQ Cluster
IP 分別為 172.20.10.11~13

套件版本為
RabbitMQ 3.6.1
Erlang 18.3
Java JDK 8u91

# 修改三台 hostname
172.20.10.11$ hostnamectl set-hostname mq_master
172.20.10.12$ hostnamectl set-hostname mq_slave1
172.20.10.13$ hostnamectl set-hostname mq_slave2

# reboot 之後才會生效(以下 all 的動作包含全部的 master & slave)
all$ reboot

# 設定 hosts
all$ vi /etc/hosts

# 加上所有 nodes 的資料
172.20.10.11
172.20.10.12
172.20.10.13

# 安裝 rabbitmq, 作法請參考上一篇的 Centos7 + Rabbitmq
rabbitmq 3.6.1 安裝流程

# 啟動 rabbitmq
all$ rabbitmq-server -detached

# 備份 erlang cookie
all$ cp /root/.erlang.cookie /root/erlang.cookie.bak

# 關閉 rabbitmq(注意, 以下動作包含全部的 slave, 本文則是指 slave1 & slave2)
mq_slave1$ rabbitmqctl stop

# 將 .erlang.cookie 的資料從 mq_master 複製過來(必須是相同的 cookie, 才可加入同一個 cluster)
mq_slave1$ scp root@mq_master:/root/.erlang.cookie /root/

# 啟動 rabbitmq
mq_slave1$ rabbitmqctl start

# 啟動 rabbitmq_management
mq_slave1$ rabbitmqctl enable rabbitmq_management

# 停止 cluster node
mq_slave1$ rabbitmqctl stop_app

# 加入 mq_master 的 cluster
mq_slave1$ rabbitmqctl join_cluster rabbit@mq_master

# 啟動 cluster node
mq_slave1$ rabbitmqctl start_app

# 回到 mq_master 查看 cluster 狀態(重複處理其他的 slave)
mq_master$ rabbitmqctl cluster_status
 # 連到 rabbitmq_management 查看狀態

2016年4月19日 星期二

CENTOS 7 安裝 RabbitMQ 3.6.1

最近要重新架構系統
所以抓了新版的 RabbitMQ 來試試看
跟之前的安裝方式有點不同
不需要在編譯了
步驟簡單很多

安裝套件如下
erlang 18.3
rabbitMQ 3.6.1
php-amqplib 2.6.2

================= 安裝 erlang ==================
# 安裝 ncurses-devel / 核心依賴文件
yum install -y wget unixODBC-devel fop gcc-c++ ncurses-devel openssl-devel autoconf

# 透過 wget 下載 Java JDK(到 www.oracle.com 取得最新的 Java JDK)
wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u91-b14/jdk-8u91-linux-x64.rpm"

# 安裝 Java JDK
rpm -ivh jdk-8u91-linux-x64.rpm

# 安裝 erlang / RabbitMQ伺服器是用Erlang語言編寫的 (連至 http://www.erlang.org/download.html 查看最新文件)
wget http://erlang.org/download/otp_src_18.3.tar.gz

# 解壓縮
tar zxvf otp_src_18.3.tar.gz
cd otp_src_18.3

# 組態(可看有那些沒裝好)
./configure

# 建立檔案與安裝(超久)
make && make install

# 測試 erlang 是否安裝成功, "." 為 erlang 的結束符號
erl
9+3.

# halt(). 結束執行
halt().

# 安裝 rabbitMQ
wget https://www.rabbitmq.com/releases/rabbitmq-server/v3.6.1/rabbitmq-server-generic-unix-3.6.1.tar.xz
xz -d rabbitmq-server-generic-unix-3.6.1.tar.xz
tar -xvf rabbitmq-server-generic-unix-3.6.1.tar

# 搬移到 /usr/local/bin 底下管理
mv rabbitmq_server-3.6.1 /usr/local/bin

# 加到 bin 方便操作
ln -s /usr/local/bin/rabbitmq_server-3.6.1/sbin/* /usr/bin

================== rabbitMQ 指令 ==================
# 啟動 rabbitmq-server
rabbitmq-server

# 背景執行
rabbitmq-server -detached

# 新增使用者
rabbitmqctl add_user admin 12345

# 設定管理者權限
rabbitmqctl set_user_tags admin administrator

# 給予管理者權限
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"

================== 安裝 rabbitMQ Management ==================
# 啟動 rabbit_management
rabbitmq-plugins enable rabbitmq_management
rabbitmq-plugins enable amqp_client

# 打開 rabbitmq management 的 port 15672
firewall-cmd --zone=public --add-port=15672/tcp --permanent
firewall-cmd --reload

# 開啟網頁
http://127.0.0.1:15672

================== 安裝 php-amqplib ==================
# 先安裝 php 依賴文件 composer
curl -sS https://getcomposer.org/installer | php

# 安裝 php-bcmath php-mbstring
yum install php-bcmath php-mbstring

# 建立 composer.json
vi composer.json
內容如下
{
  "require": {
      "php-amqplib/php-amqplib": "2.6.*"
  }
}

# 安裝
php composer.phar install


新版的 rabbitmq 畫面保持一貫的簡潔

2016年3月30日 星期三

CentOS7 儲存 Firewall 的設定


在 CentOS7 底下設定好 Firewall 之後
重啟 CentOS7 就會不見
後來發現 firewall-cmd 只會暫時性的存放
並不會常駐
而 firewall 也沒有儲存(save)的功能
查了一下才知道
要加上 --premanent(常駐)
這樣系統重啟之後
firewall-cmd 有加上 --permanent 的設定就會自動被載入
舉個例子...

設定開啟 port 80(重開機後此設定無效)
firewall-cmd --zone=public --add-port=80/tcp
設定常駐開啟 port 80(重開機後此設定依舊保留)
firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --reload


Oracle VM VirtualBox Bridge(橋接介面卡) 模式下 CentOS7 Static IP 設定

開啟 VM
點選[設定]->[網路]->[介面卡1]
選擇您要橋接的網卡


進入 CentOS7
編輯 /etc/sysconfig/network-scripts/ifcfg-enp0s3(依照你的網卡名稱)
調整設定如下
BOOTPROTO="static"
IPADDR="172.20.10.3"
NETMASK="255.255.255.240"
GATEWAY="172.20.10.1"
以上的值請依據您的環境自行修改
因為我是透過手機
所以GW跟NM都是參考手機的設定

再來設定  DNS
編輯 /etc/resolv.conf\
輸入以下兩組 nameserver
nameserver 168.95.1.1
nameserver 8.8.8.8


重啟 network, ping 看看 yahoo 是否正常
systemctl restart network
ping tw.yahoo.com



2016年3月27日 星期日

CentOS 7 下安裝 Mariadb + phpMyAdmin 搭配 Nginx + php-fpm




















# 安裝 Mariadb
yum install mariadb mariadb-server -y

# 開啟 Mariadb
systemctl start mariadb

# 設定為服務
systemctl enable mariadb

# mysql 安裝
mysql_secure_installation

# 安裝畫面


# 登入
mysql -u root -p



# 查看 db
show databases;

# 離開 mariadb
exit

# 安裝 phpmyadmin
yum install epel-release
yum install phpmyadmin


# 安裝 php
yum install php php-mysql php-fpm

# 設定 phpmyadmin 到 nginx 的目錄下
ln -s /usr/share/phpMyAdmin /usr/share/nginx/html

# 修改 cgi.fix_pathinfo = 0, 1表示找尋相似(相近)的檔案讀取, 關閉此功能讓系統安全一點
參考: cgi.fix_pathinfo 漏洞

vim /etc/php.ini

# 找到 cgi.fix_pathinfo, 設定為 0
cgi.fix_pathinfo=0

# 修改 php-fpm 的設定檔 www.conf
vim /etc/php-fpm.d/www.conf

# 找到 listen, 修改如下列所示(檔案尚未產生, 等重新執行 php-fpm 後就會有了)
listen = /var/run/php-fpm/php-fpm.sock

# 接下來找 listen.owner 跟 listen.group, 取消註解
listen.owner = nobody
listen.group = nobody

# 最後找 user 跟 group, 將他們的值從 apache 改成 nginx
user = nginx
group = nginx

# 重新執行 nginx
systemctl restart nginx
# 設定成服務
systemctl enable nginx
再來設定 Nginx, 讓他可以執行 php-fpm(未設定好, php 的檔案會變成下載的方式讀取)

# 修改 Nginx server block level(Nginx服務區塊, 類似 apache 的 virtual host)
vim /etc/nginx/conf.d/default.conf
# 修改內容如下
server {
    listen       80;
    server_name  localhost;

    # note that these lines are originally from the "location /" block
    root   /usr/share/nginx/html;
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

# 重啟 Nginx
systemctl restart nginx

開啟 phpmyadmin 之後發現 session 寫入有問題
因為 nginx 沒有寫入 php/session 的權限


# 修改 php/session 的權限
chown nginx:nginx /var/lib/php/session

# 重新開啟 phpmyadmin, 正常了

登入 phpMyAdmin 後出現 blowfish_secret 錯誤
# 修改 /usr/share/phpMyAdmin/libraries/config.default.php
vim /usr/share/phpMyAdmin/libraries/config.default.php

# 填入隨便一組加密碼
$cfg['blowfish_secret'] = 'oxoxox12345';

# 重新登入 phpMyAdmin 後就正常了


之前由於 php-fpm 沒設定
導致透過 nginx 開啟 php 網頁都變成下載 php 的檔案
連到 localhost/phpMyAdmin 則會出現 403 forbidden

用 google 查了 nginx phpmyadmin 403 forbidden
大部分都是檔案缺少或是權限問題
可是我實際處理之後發現我的問題似乎不在此

後來就回頭去研究 nginx + php-fpm 的設定
參考了 How To Install LEMP(Linux Nginx Mysql PHP) 之後
所有的問題就都解決了

2016年3月3日 星期四

centos 7 手動加入 nginx 的 repo 設定

# 建立 repo
vi /etc/yum.repos.d/nginx.repo

#讓yum找的到nginx
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enable=1


#執行安裝
yum install nginx

#安裝結果

# 關閉 apache(如果有開啟的話)
service httpd stop

# 啟動 nginx
service nginx start

# 初始畫面


參考連結
http://yenpai.idis.com.tw/