2021-01-28 / JSN / 0 Comments / 1,491 次瀏覽
我這邊在主機有多個使用者,每個人都要切換到使用者 ubuntu 下達 docker 相關指令。以下示範由我的帳號是 cary 切換到內建使用者 ubuntu
sudo su ubuntu
// 位在群組 docker 如果直接下 docker-compose 會出現權限不夠
docker-compose ps
// 查看自己目前的 group 有在哪些群組裡,如果沒有 docker
id $USER
//uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(lxd),114(netdev)
// 那就下這行把自己的群組加入 docker
sudo usermod -aG docker $USER
// 再次確認群組已經加入了 docker
id $USER
// uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(lxd),114(netdev),116(docker)
// 接著離開再登入 ubuntu
exit
sudo su ubuntu
// 這樣就可以不需要 sudo 了
docker-compose ps
2020-09-15 / JSN / 0 Comments / 98 次瀏覽
最近在接 wordpress 的文章,要顯示在 RSS,但遇到文字之間出現 “\x08” 造成 RSS 格式錯誤,可使用這種方式過濾掉 ASCII
/**
* 移除 ascii 由 wordpress 產生的問題,造成 RSS 無法讀取 {@see https://xilou.info/p/121}
*
* @param $text
* @return string|string[]|null
*/
public function removeAscii($text)
{
return preg_replace('/[\x00-\x08\x0b-\x0c\x0e-\x1f]/','', $text);
}
2020-05-27 / JSN / 0 Comments / 13,613 次瀏覽
Node.js 有兩種方法,一種透過 nvm 一種透過 n:
第一種 nvm
連同 NPM 一起更新到該版本預設
// 指定版本號
nvm install {version}
// 若要最後一版 lastest
nvm install node
// 看所有安裝的列表
nvm ls
// 替換到某個版本
nvm use {version}
第二種 n
npm cache clean -f
npm install -g n
// 若要更新到最後一個版本
n latest
// 若要更新到穩定版本
n stable
// 檢查一下
node -v
NPM 更新
npm install -g npm
參考網友文章
2020-05-12 / JSN / 0 Comments / 542 次瀏覽
以下介紹兩種方法都可以達到目的
方法一、在類別的方法使用 NULL
Interface MemberInterface
{
public function getName();
}
class Member implements MemberInterface
{
public function ()
{
return "Cary";
}
}
如果希望在 getName() 的時候修改回傳 “A001 – Cary”,那麼可以在方法帶入的參數使用預設值 null 來符合介面定義,修改如下
class Member implements MemberInterface
{
public function getName($id = null)
{
return "{$id} - Cary";
}
}
$member = new Member();
echo $member->getName("A001");
方法二、透過 Setter
保持介面定義的方法樣式,但為了填入參數,我們必須要製作另外一個方法來寫入類別屬性,例如修改為
class Member implements MemberInterface
{
public function setId($id)
{
$this->id = $id;
}
public function getName()
{
$id = $this->id;
return "{$id} - Cary";
}
}
$member = new Member();
$member->setId("A001");
echo $member->getName();
比較兩者
方法一,適合用在 只定義方法名稱 但不定義寫入的參數要長甚麼樣子。因為都直接定義在類別的方法中,因此比較一目了然。
$memberA = new MemberA();
$memberA->getName("A001"); // 接手人 A 可能這樣寫,結果一個禮拜後離職
$memberB = new MemberB();
$memberB->getName("B001"); // 外包商接手人 B,參考 A 很直覺得會使用這種方法
方法二,因為 setId() 方法並沒有定義在 Interface,是依照各個類別自行應用。在不同類別,要使用 getName() 的時候,需要使用的寫法可能會不一樣。
$memberA = new MemberA();
$memberA->setId("A001"); // 接手人 A 可能這樣寫,結果一個禮拜後離職
echo $memberA->getName();
$memberB = new MemberB();
$memberB->setUserId("B001") // 外包商接手人 B 可能這樣寫,沒有依照 A 的命名樣式
echo $memberA->getName();
$memberC = new MemberC();
$memberC->id($id); // 接手人 C 可能剛學 PHP 一個月,接手處理這個問題
echo $memberC->getName();
// 接手人 D 整頓程式碼,就會 WTF ...
不過,最怕的當然還是方法一、方法二的混用的狀況啦,因此定義 Interface 要實作 setter 與 getter,就很需要一些經驗了。
2020-05-02 / JSN / 0 Comments / 627 次瀏覽
這裡介紹兩種用法的比較:
我們開發常常會有一種情況,把一筆陣列資料輸入到某隻 method(),但因為是陣列,在強型別 type hinting 的時候,不知道怎麼做限制。例如加入購物車 Cart,可能會放入多筆商品,常見的寫法是:
<?php
$products = [
// 這裡省略產品類別範例
// Product("商品名稱", "數量", "單價", "單位")
new Product("手機", 2, 100, "支"),
new Product("衣服", 3, 50, "件")
];
$cart = new Cart($products);
我們常見設計的購物車類別:
<?php
class Cart
{
/**
* 購物車的商品項目
* @var array
*/
private array $items;
/**
* 建構子把輸入的參數賦予到類別屬性
* @param array $products
*/
public function __construct(array $products)
{
$this->items = $products;
}
}
這會有一個小問題,我們在建構子 __construct(array $products) 使用強型別規範輸入 array 卻無法明定陣列中的每項型態,這對接手或日後維護的人來說,無法一目瞭然陣列裡面的項目長什麼樣子。
如果我們可以針對陣列中的每個值做類型提示,那麼無論閱讀上或是搭配 IDE 如 phpStorm 都能做出優美的提示。 因此能透過 “…” 參數語法來表示,以下修改上述範例:
// 方法一,一次丟入陣列
$products = [
new Product("手機", 2, 100, "支"),
new Product("衣服", 3, 50, "件")
];
// 注意帶入的時候要加上 "..."
$cart = new Cart(...$products);
// 方法二,在參數追加
$cart = new Cart(
new Product("手機", 2, 100, "支"),
new Product("衣服", 3, 50, "件")
);
那麼購物車類別如何修改?其實很簡單
<?php
class Cart
{
private array $items;
/**
* 我們透過 ... 語法,代表參數可以輸入多筆類別是 Product 的物件
* @param Product[] $products
*/
public function __construct(Product ...$products)
{
$this->items = $products;
}
}
上面建構子改良後有兩種用法,方法一是我覺得實務上最常用的方式
$products = [
new Product("手機", 2, 100, "支"),
new Product("衣服", 3, 50, "件")
];
$cart = new Cart(...$products);
因為使用者放入的商品數量並不固定,因此方法一實務上最常見。IDE 也能非常清楚的提示:
而方法二適合用在我們寫 Code 的應用上
$cart = new Cart(
new Product("手機", 2, 100, "支"),
new Product("衣服", 3, 50, "件")
);
例如 Laravel 的 dd() 就是個好懂的範例
dd($name);
dd($name, $age);
實務上使用 Interface
中型實務上,展開運算子的強型別我們會使用 Interface 而不是 class 。例如這項發票中心系統 InvoiceCenter 的建構子簡化如下:
注意函式參數第三個,我們在 type hint 做展開運算子使用的是介面 ProductInterface 而不是 類別 Product。因此我們實例化類別的時候會是這樣:
沒錯就是依賴反轉,我們把這項發票中心系統 InvoiceCenter,所依賴的第三方廠商 API 從外部注入,也就是說廠商A
EzPay 實作 InvoicePlatformInterface User 實作 UserInterface Product 實作 ProductInterface
我們要換成廠商B,也許叫做 xxPay,那麼他們的發票系統我們也只需要實作這三項 Interface。而第三個參數 new Product() 就是我們本篇提到的應用。IDE 會告訴你這個陣列的每個類別,務必實作 ProductInterface
假設我們帶入任何一項類別,沒有實作介面 ProductInterface 那麼會輕鬆報錯給你看,這對維護人員太有效了
本篇概念參考來源 https://stackoverflow.com/questions/34273367/type-hinting-in-php-7-array-of-objects