- 投稿日:2020-09-29T19:18:11+09:00
PHP printf クラス インスタンス
printf
printfとは「あるフォーマットに従った文字列を返す」関数です。
[構文]
sprintf(文字列のフォーマット, 入力したい文字1, 入力したい文字2, ・・・)
[例]
"%s 君は %s を %d 個食べました。"
「%s」には文字列を、「%d」には数値を代入することができます。ですので、
髙橋 君は パン を 100 個食べました。
という文章にしたい場合は、
sprintf("%s 君は %s を %d 個食べました。", "髙橋", "パン", 7)と書くことで、「髙橋 君は パン を 100個食べました。」という文字列が返ります。
他にも沢山の指定子がありますので、活用していきたいと思います。
クラス
class Post{}
でクラスを生成できます。
※クラス名の最初は大文字にします。プロパティ
public $変数
変数を宣言します。メソッド
こちらもpublic をつけて関数を定義します。
this
this->変数 は変数にアクセスするために使っています。
インスタンス
$posts[0] = new Post();
でインスタンスを作成しています。$posts[0]->text = 'hello';
$posts[0]->likes = 0;
でクラス内のプロパティに代入しています。
- 投稿日:2020-09-29T17:56:12+09:00
PHP(+MySQL)のランダム関数を使ってガチャを作る話
はじめに
ソーシャルアプリのガチャを作ったときの話。
無作為にデータを取り出すプログラムを書いたとき「なんだか偏るなぁ」と感じたので、
自分の中でどのやり方が課金者に平等で無作為(そして簡単に)にデータを取り出せるか調べてみたことを書きます。使用している言語
PHP7.0.0、データベースはMySQL
そもそもMySQLでランダムにレコードを取得してはいけない?
SELECT * FROM 'gacha' ORDER BY RAND() LIMIT 1;
超簡単に取得できる方法ではありますが、SQLアンチパターンであるので却下しました。PHPで取得したデータからランダムに取得
rand()
、mt_rand()
どちらも擬似乱数を整数で返してくれるもの。
mt_randの方が数倍高速だということですので使うならmt_randかなぁと思いましたが
暗号学的に安全ではないようなのです。PHP7以降では暗号学的に安全と言われている
random_int()
が存在します。PHP7以降で暗号化に使う場合であればこちら推奨されています。
引数を省略することはできませんが、基本的な使い方自体はmt_rand()
と変わらないので置き換えも簡単にできるかと思います。ではランダム関数使うならrandom_intを使いましょうという話なのか?
安全面を考えると
random_int()
でいいと思います。
ただ、速度はmt_randの方が早そうなので、単純に乱数が欲しいだけならmt_randで十分だと思います。stackoverflowに速度を検証された方がいたようです。
PHP Rand()vs. random_int()結論
課金が絡むようなできる限り不具合なく安全で公平なシャッフルを望むのであれば多少速度が遅かろうが
random_int()
を使った方がいいと判断しましたので、PHP7以降であればrandom_int()
、それ以下であればmt_rand()
を使用するとします。本題
ただ、プログラムで完璧な無作為を行うことは不可能なので関数を利用しつつ
仕組みでカバーすることにします。つくるガチャについて(ここからは興味のある人だけお読みください)
ここで、どんなガチャがあるのか覚えている限り書きます(備忘録)
ランダム型
データベースから1件ランダムで排出するものを決定する一番作りやすいガチャです。
以前私が作っていたものもこの形で、データのレコード数を調整することで確率を収束させていました。
問題点は当たらない時はいくらお金をつぎ込んでも当たらない、という点です。コンプリート型
例えば10種類のアイテムを全てガチャで引けたら今回の目玉のアイテムをもらえるといったものです。
欲しくもないアイテムをひたすら狙い続ける上にランダム型ベースなので確率も上がらない最も闇が深いガチャです。
現在は規制が入り、使えませんボックス型
コンプリート型が規制されたことによってよく使われるようになったガチャです。
イメージは実物のガチャポンのように袋の中から一つずつ引いていき、いずれ空になるので欲しいものが確実に手に入るガチャです。基本的に空になるともう課金されないため、売り上げの上限が決まってしまうという問題があったので
目玉のアイテムを複数集めるメリットを用意した上で、目玉のアイテムをユーザーが手に入れた段階でボックスをリセットできる機能をつけた派生系のものが生まれてきました。
いずれ100%欲しいものが欲しいだけ手に入る分コンプリート型よりは良心的になりました。ステップアップ型
ガチャを引くとステップが上がるとともにオマケなどがもらえて、ステップが上がるほどにオマケやお得なアイテムが豪華になっていくガチャです。
また、頭打ちにならないように10ステップまで進むと1ステップに戻るものもあります。その場合は10ステップ目に目玉アイテムがある場合が多いです。
ボックス型よりも比較的早く目的のアイテムが確実に手に入るのでわかりやすいです。テーブル型
ランダム性を完全に取り除いて最初からガチャで出る順番をデータに全て登録しておく、というものです。
これはかなり古いやりかたでデータをいい感じに登録する作業が面倒なのでやっているゲームはもうないかもしれません。今回は単純に確率の話なので「ランダム型」でいきます。
以下のようなデータを用意します。
実際作ったものとは少々異なりますがイメージはこんな感じです。gacha_item テーブル
id gacha_id rarity item_name min_ratio max_ratio 1 1 5 アイテムSSR 0 10 2 1 4 アイテムSR 11 100 3 1 4 アイテムSR 101 500 4 1 4 アイテムSR 501 1000 5 2 4 アイテムSR 0 200 6 2 3 アイテムR 201 500 7 2 3 アイテムR 501 1000 8 3 2 アイテムUC 0 250 9 3 2 アイテムUC 251 500 10 3 2 アイテムUC 501 750 11 3 2 アイテムUC 751 1000 フロー
やりたいこと。
- ユーザーがガチャを回す
- ガチャIDをランダムで取得
- ガチャIDの中からランダムで1件取得
- データベースから絞り込んだアイテムを取得
- ユーザーがアイテムをGET
$a = random_int(1, 3); // ガチャ&演出決定 $b = random_int(0, 1000); // ratio決定 $Item = getGachaItem($a,$b); // データベースから排出アイテム取得// sqlはこんな感じ
SELECT * FROM 'gacha_item' WHERE 'gacha_id' = $a AND 'min_ratio' <= $b AND 'max_ratio' >= $b LIMIT 1;
一発でテーブルから1件取得するのではなく、ガチャIDを先にランダムで選ぶことで無作為性を上げています。
これで、簡単な仕組みのガチャができました。
あと必要なのはゲームバランス等を加味した排出率の計算をします。
データの設定ができたら後は10万回ほど回してみて排出率を出します。データがでたらどれくらいのユーザーが目玉のアイテムを手に入れて欲しいかを考えます。
アクティブユーザー数や平均のガチャ回数を見たり、そのアイテムがゲームプレイに与える影響の大きさ(ゲームバランス)を鑑みて排出率を決定すればOKです。余談:ガチャ演出について
gacha_idはガチャを入れ物で分けて無作為性を上げていますが「ガチャ演出の切り替え」に使う場合もあります。
レアリティによって演出を変えてもいいんですが、上位レアリティを増やすときでも演出を増やしやすいというメリットがあります。
例:
gacha_idが1の場合はrarityが高いものが入っているあたりガチャ。演出も派手。
gacha_idが2の場合は少しrarityが低いものが入っています。演出は少し派手。
gacha_idが3の場合はrarityが低いものが入っています。演出はノーマル。
- 投稿日:2020-09-29T16:36:21+09:00
パスワードリセット時の有効期限つきワンタイムURL
今回解説していくのはパスワードリセット時の有効期限付きワンタイムURLの作り方です
流れは
- パスワードリセットのページでメールアドレスを入力
- メールアドレスが登録されていても登録されていなくても同じ文言を出力
- メールアドレスが登録されていた場合は有効期限付きワンタイムURLが記載されたメールを送信する
- パスワードを更新した場合は
5秒後
にログイン画面にリダイレクトsendMail.php<?php if (isset($_POST['submit']) && isset($_POST['email'])) { $email = $_POST['email']; if (filter_var($email, FILTER_VALIDATE_EMAIL)) { try { $dbh = new PDO('mysql:host=localhost; dbname=dbname;', 'username', 'password'); } catch (PDOException $e) { exit('接続失敗:' . $e->getMesssage()); } $exists_email_sql = 'SELECT mail FROM members WHERE mail = :mail'; $exists_email_stmt = $dbh->prepare($exists_email_sql); $exists_email_stmt->execute([':mail' => $email]); $exists_email = $exists_email_stmt->fetch(); $msg = $email . "宛にパスワード再発行URLを送信しました。\n30分間のみ有効です"; if ($exists_email) { $url = 'https://example.com/reset.php?key='; $secret_key = md5(uniqid(mt_rand(), true)); $url .= $secret_key; mb_language('Japanese'); mb_internal_encoding('UTF-8'); $title = 'パスワード再発行'; $content = "パスワード再発行URLは以下の通りです。30分間のみ有効です\n " . $url; $headers = 'From: example@from.com'; //なぜか送れなかったので'-f'以降(エラー用送信先)を付け加えました。$headerまでで基本はいけると思います。 mb_send_mail($email, $title, $content, $headers, '-f' . 'example@forError.com'); $reset_date = date('Y-m-d H:i:s'); $update_sql = 'UPDATE members SET reset_date = :reset_date, secret_key = :secret_key WHERE mail = :mail'; $update_stmt = $dbh->prepare($update_sql); $params = [ ':reset_date' => $reset_date, ':secret_key' => $secret_key, ':mail' => $email, ]; $update_stmt->execute($params); } } else { $msg = 'メールアドレスを入力してください'; } } ?> <!DOCTYPE html> <html lang='ja'> <head> <meta charset='UTF-8'> <title>パスワードリセット</title> </head> <body> <?php if (isset($_POST['submit']) && isset($email)) : echo $msg; else : ?> <form method='post'> <div>登録したメールアドレスを入力してください</div> <input type='email' name='email' placeholder='example@gmail.com' required> <input type='submit' name='submit' value='送信'> </form> <?php endif; ?> </body> </html>まずはメールアドレスが入力されていて、送信ボタンが押されていたら
入力フォームを出さないようにします
メールアドレスのバリデーションはfilter_var()
関数を使うのが無難
正規表現には諸説あるので。
メールアドレスの形式が正しければ、次にメールアドレスがDBに登録されているか調べる
boolean
の返り値を返す変数名には以下を参考にしてくださいis+形容詞 has+過去分詞 can+動詞の原型 exists+名詞 has+名詞 should+動詞の原型今回は
has_email
かexists_email
でいいと思う
あとはregistered_email
とかかなセキュリティ上メールが登録されていようがなかろうが同じ文言を返すようにするため
先に文言を代入しておくメールアドレスが登録されていた場合のポイントは2つ
まずワンタイムURL
にすること
それから時間制限を設ける
ことここで乱数をurlに追加しているのはメール受信者のみアクセス可能にするためです。
次のページでは有効な乱数がurlについていない場合はパスワードを入力した次の画面でエラー文言が出るようにしています。
また、乱数の頭や、urlに時刻を含めるのも容易に改竄ができてしまうためNGですここでは後に乱数が有効か調べるために、乱数をDBに保存しています。
また、後に時間制限の確認を行うために、メール送信時の時刻もDBに保存しています。メールの送信方法は以下の二つが必要です
- 文字エンコードの指定
- 言語の指定
マルチバイトの文字を扱う場合は
mb_send_mail(送信先、タイトル、本文、省略可能追加ヘッダ、省略可能追加コマンドパラメータ)
を使いましょうmb_send_mail(string $to, string $subject, string $message[, mixed $additional_headers = NULL[, string $additional_parameter = NULL]] ): bool今回使用した
-f
以降はエラー用のメール送信先なので、送信先のメールアドレスと同じものを指定すれば良いと思いますreset.php<?php $msg = '不正なアクセスです'; $redirect_login_flg = false; if (isset($_POST['change']) && isset($_POST['pass']) && isset($_GET['key'])) { $pass = $_POST['pass']; $key = $_GET['key']; if (!empty($pass)) { try { $dbh = new PDO('mysql:host=localhost; dbname=dbname;', 'username', 'password'); } catch (PDOException $e) { exit('接続失敗:' . $e->getMesssage()); } $is_valid_sql = 'UPDATE members SET pass = :pass, secret_key = NULL WHERE :reset_date <= date_add(reset_time, INTERVAL 30 MINUTE) AND secret_key = :secret_key'; $is_vallid_stmt = $dbh->prepare($is_valid_sql); $params = [ ':reset_date' => date('Y-m-d H:i:s'), ':pass' => $pass, ':secret_key' => $key, ]; $is_valid_stmt->execute($params); $is_valid = $is_valid_stmt->rowCount(); if ($is_valid) { $redirect_login_flg = true; $msg = "パスワードの更新が完了しました。\nこのページは5秒後にログインページへリダイレクトします"; } } else { $msg = "パスワードを入力してください\n<a href=\"board_reset.php?key=" . $key . ">戻る</a>\n"; } } ?> <!DOCTYPE html> <html lang='ja'> <head> <meta charset='UTF-8'> <?php if ($redirect_login_flg) : ?> <meta http-equiv="refresh" content=" 5; url=./home.php"> <?php endif; ?> <title>パスワード再発行</title> </head> <body> <?php if (isset($_POST['change']) && isset($_POST['pass'])) : echo $msg; else : ?> <form method='post'> <div>新しいパスワードを入力してください</div> <input type='password' name='pass' placeholder='password' required> <input type='submit' name='change' value='変更'> </form> <?php endif; ?> <a href='board.php'>ホームに戻る</a> </body> </html>ここでも同様にformの出しわけを行っています
パスワードが正しく入力された場合は、シークレットキーを基に、該当するレコードを探して、secret_key
をNULL
に変更し
password
をユーザーが入力したものに変更します。
secret_key
をNULL
にすることで、次回以降URLが使えなくなるのでワンタイムURLにすることができます
なおreset_date
は変更しなくても良いでしょう。
変更しなければ、パスワードを更新した日にちがわかりますね。
$redirect_login_flg
を設定することでパスワードを正常に変更できたあとは5秒後にリダイレクトされるようになっています。
これは<meta http-equiv="refresh" content=" 秒数; url=相対パスか絶対パス">で実装することができます。
他の方法もあるので調べてみてください補足
html
側のinput
でrequired
などの入力を制限していてもバックエンド側での制御は必要です。
html
側の制限は入力をアシストするためのものと考えてください
実際にChrome DevTools
を使って、制限を消してフォームを送信することができるので
- 投稿日:2020-09-29T15:20:37+09:00
Laravelルーティング
Laravelにおけるルーティングを説明していきます。
ルーティングとは
ブラウザから任意のURLアクセスがあった場合、どのController処理を動かすのかを定義するところになります。記述する場所は
routes/web.php
になります。またHTTPメソッド(GET,POST,PUT等)も定義できます。下記のイラストの①の部分にあたります。
ルーティングの書き方
記載する場所は
routes/web.php
になります。
例) ブログ一覧を表示したいroutes/web.phpRoute::get('blogs','BlogContoller@showlist');左から順に説明します。
1. Laravel既存機能のRouteファサードを使う(Route)
2. HTTPメソッドの指定(get)
3. 任意のURLを指定(blogs)
4. 作ったControllerを指定(BlogContoller)
5. Controllerのメソッドを指定(showlist)名前付きルート
作成したRouteに名前をつける事ができます。これにより特定のルートへのURLを生成したり、リダイレクトしたりする場合に便利です。ルート定義に
name
メソッドをチェーンする事で名前がつけられます。routes/web.phpRoute::get('/','BlogContoller@showlist')->name('blogs');生成+リダイレクト
ルートに一度名前を付ければ、その名前をグローバルな
route
関数で使用すればURLを生成したり、リダイレクトしたりできます。//URLの生成 $url = route('blogs'); //リダイレクトの生成 return redirect()->route('profile');URLを一括で変更できる
viewで
{{ url('/users/1/profile')}}上記のように書いてしまうと、URLを変更する際にviewの中から同じ箇所を探さないといけなくなってしまいますが、
{{ route('user.profile',['id' => 1])}}としていれば、
routes/web.php
のみを変更すればよくなります。resource
resourceはリソースコントローラーと呼ばれ、一般的なCRUD(投稿、一覧、更新、削除、詳細)操作を予めLaravel側で用意してくれるものです。web.phpでHTTP動詞を
Route::resource
とする事で以下のメソッドを定義した扱いとなります。また、name()
も勝手に付与してくれます。
1. index(一覧)
2. show(詳細)
3. create(作成画面)
4. store(作成処理)
5. edit(編集画面)
6. update(編集処理)
7. destroy(削除処理)これにより、かなりのコード短縮化が図れます。
一つずつ
web.phpRoute::get('admin/post', 'Admin/PostController@index')->name('admin.post.index'); Route::get('admin/post/show/{id}', 'Admin/PostController@show')->name('admin.post.show'); Route::get('admin/post/create', 'Admin/PostController@create')->name('admin.post.create'); Route::post('admin/post/store', 'Admin/PostController@store')->name('admin.post.store'); Route::get('admin/post/edit/{id}', 'Admin/PostController@edit')->name('admin.post.edit'); Route::post('admin/post/update/{id}', 'Admin/PostController@update')->name('admin.post.update'); Route::post('admin/post/destroy/{id}', 'Admin/PostController@destroy')->name('admin.post.destroy');
resource版
Route::resourcre('post','PostController');また、以下のartisanコマンドで対応するコントローラとメソッドを自動生成してくれます。
$ php artisan make:controller PhotoController --resourcePhotoController//コマンド入力で自動的に作成される namespace App\Http\Controllers; class PhotoController extends Controller { public function index() { // } public function create() { // } public function store(Request $request) { // } public function show($id) { // } public function edit($id) { // } public function update(Request $request, $id) { // } public function destroy($id) { // } }onlyオプション/exeptオプション
これにより、resource使った時のルーティングを制限する事ができるので、余計なルーティングを生成しないで済みます。
routes/web.php//edit,updateのルーティングを削除 //only Route::resource('hoge', 'HogeController', ['only' => ['index','create','show','store','destroy']]); //except Route::resource('hoge', 'HogeController',[except => ['edit','update']]);resource懸念点
実務で
resource
を使ってしまうと、使わないルートまで定義されてしまうので、「個別で書いた方がいい」、「only,exceptオプションを使う」という意見があるらしいです。使う用途によって使い分けた方が良さそうです。終わりに
参考サイト
https://qiita.com/sympe/items/9297f41d5f7a9d91aa11
https://qiita.com/namizatork/items/78487c2504b7ad4faf27
- 投稿日:2020-09-29T13:44:41+09:00
Ubuntu 16.04を実行しているAlibaba Cloud Elastic Compute Service上でownCloudを設定
この記事では、Ubuntu 16を使用してAlibaba Cloud Elastic Compute Service (ECS)インスタンスにownCloudをインストールする際に役立つ、いくつかの情報を入手できます。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
Ubuntu 16.04を実行しているAlibaba Cloud Elastic Compute Service (ECS)上で独自のCloudサーバーを設定することができます。クラウドソフトウェアはPHPとJavaScriptで書かれており、機能するためにはApacheのようなWebサーバーと一緒にMariaDB/MySQLデータベースが必要です。
このステップバイステップガイドに従って、Apacheウェブサーバー、MySQLサーバーをインストールし、ownCloud MySQLデータベースとユーザーを作成することができます。
PHPスクリプト言語のインストール
PHPは最も広く使われているサーバーサイドスクリプト言語の一つです。このオープンソースの汎用プログラミング言語は、動的でインタラクティブなWebアプリケーションを実行するのに強力です。
このガイドを書いている時点では、ownCloudがサポートしているPHPの最高バージョンはPHP 7.1でした。
インストールするには、以下のコマンドを実行します。
$ sudo apt-get install software-properties-commonYボタンを押し、Enterキーを押してインストールを確認します。
$ sudo add-apt-repository ppa:ondrej/phpリポジトリを追加するように促されたら、Enter キーを押します。
その後、以下のコマンドでリポジトリ情報を更新します。
$ sudo apt-get updateこれで、先に行ってPHP 7.1をインストールすることができます。
$ sudo apt-get install php7.1Yを押し、Enterキーを押してインストールを確認します。
ownCloudがPHP 7.1で動作するためには、以下のコマンドを実行して、必要なPHPモジュールがすべてインストールされていることを確認する必要があります。
$ sudo apt-get install php7.1.1-cli php7.1.1-common php7.1-mbstring php7.1-gd php7.1-intl php7.1-xml php7.1-mysql php7.1-zip php7.1-curl php7.1-xmlrpcY を押し、Enter を押してインストールを確認してください。
これでPHPをロードするようにApacheを再起動することができます。
$ sudo systemctl restart apache2ownCloudソフトウェアをダウンロード
これで、Webサーバ、データベースサーバ、PHPスクリプト言語のセットアップが完了しました。これで、ownCloudソフトウェアを実行するためのサーバー環境が整いました。
最新のownCloudソフトウェアは以下のリンクからzip形式でダウンロードできます。
https://download.owncloud.org/community/owncloud-10.0.3.zipまず、Ubuntuサーバーの/tmpフォルダにCDを入れます。
$ cd /tmpそして、Linuxのwgetユーティリティを使用して、リンク先からファイルをダウンロードします。
$ wget https://download.owncloud.org/community/owncloud-10.0.3.zipzipファイルは
/tmp
ディレクトリに保存されているはずなので、それを解凍して、unzipコマンドを使用して、あなたのウェブサーバ/var/www/html
のルートにコピーする必要があります。まず、unzipツールをインストールします。
$ sudo apt-get install unzipそして、ファイルを解凍して、サイトのルートに内容を送信します。
$ sudo unzip owncloud-10.0.3.zip -d /var/www/html/unzipユーティリティが処理を最終化するために数秒待ちます。
その後、ownCloudのディレクトリとファイルのパーミッションを設定して、インストールを完了させることができます。詳細は、Alibaba Cloud ECS Ubuntu 16.04にownCloudをインストールする方法を参照してください。
関連ブログ記事
Ubuntu 16.04でZabbixを設定する方法
Zabbixはオープンソースのエンタープライズクラスのネットワーク監視ツールで、サーバ、ネットワークデバイス、その他のネットワークコンポーネントのパフォーマンスと可用性を監視するために使用できます。ZabbixはMySQL、PostgreSQL、Oracleを使用してデータを保存します。また、Zabbixはデータや設定を監視・追跡するためのユーザーフレンドリーなWebインタフェースを提供しています。ZabbixはZabbixエージェントを使用してデータを収集し、Zabbixサーバに送信します。
Ubuntu 16.04でModEvasiveを使ってApache Webサーバーをセキュアにする方法
w3techsが発表した2018年7月の調査によると、Apacheの市場シェアは約45.9%となっています。そのため、Apacheウェブサーバはほとんどのハッカーに狙われています。ソフトウェアはアウトオブボックスで安全ですが、いくつかの追加モジュールを使用して固めることができます。
Alibaba Cloud上でホストされているApacheウェブサーバーを安全にする最も一般的な方法の1つは、ModEvasiveをインストールすることです。これは高度にインテリジェントなApacheモジュールで、分散型サービス拒否攻撃やブルートフォース攻撃に対して回避的なアクションを提供します。
関連市場製品
パートナー企業が構築したPHPインフラを搭載した製品は、アリババクラウドのサーバー上ですぐに立ち上げることができるものがあります。
Websoft9(WAMPServer)が提供するPHPインフラ
Websoft9 WAMPServerスタックは、Alibaba Cloud上でPHPアプリケーションを実行するための事前に設定された、実行可能なイメージです。WampServerはWindowsのWeb開発環境で、Apache2、PHP、MySQLデータベースを使用したWebアプリケーションを作成することができます。
Ubuntu 14.04 64ビットでのLAMP
IGSは、ウェブサービスソリューションのための最も人気のあるソフトウェアと事前に統合されたイメージのリストを提供しています。Apache/Nginx、MySQL、PHP、phpMyAdminなどの実行可能なバージョンが含まれています。
Apache/Nginx、MySQL、PHP、phpMyAdminなどのすぐに実行可能なバージョンが含まれています。IGSイメージは、Webアプリケーションの開発とデプロイメントを大幅に簡素化します。
関連ドキュメント
参考になるかもしれないドキュメントがあります。
「脆弱性のお知らせ」CVE-2018-5711: PHP GD ライブラリに DoS 脆弱性が存在します。
2018年1月22日、セキュリティ研究者がPHP環境にDoSの脆弱性を発見しました。PoCは、特別に細工されたGIF画像を使用してPHPのプロセスの停止やクラッシュを引き起こし、ウェブサイトの機能やサービスに影響を与える可能性があります。PoCは公開されています。PHPで開発されたWebサイトでは、画像のアップロードにGDライブラリを使用しているため、この脆弱性については常に最新の情報を入手しておくことをお勧めします。
PHP環境のセキュリティを強化
PHPのアプリケーションの増加に伴い、セキュリティはより顕著な関心事となってきています。PTP環境で提供されるセーフモードは、重要な組み込みセキュリティ機能であり、 system()関数のようないくつかのPHP関数を制御することができます。一方、セーフモードは多くのファイル操作機能のパーミッションも管理し、/etc/passwdファイルのような特定のキーワードファイルの編集を許可しません。ただし、php.iniの設定ファイルでは、セーフモードはデフォルトでは有効になっていません。本書では、PHPのセキュリティ機能を利用してWebサイトのセキュリティを高める方法を解説します。
関連製品
エラスティックコンピュートサービス
クラウドホスティングのあらゆるニーズに対応するために、弾力的で安全な仮想クラウドサーバーを提供するオンラインコンピューティングサービスです。
マネージドセキュリティサービス
完全に管理されたセキュリティサービスで脆弱性を特定し、オンラインビジネスシステムのセキュリティ管理を改善します。
関連コース
アリババクラウドマネージドセキュリティサービスの紹介
このコースを通じて、アリババクラウドマネージドセキュリティサービスがお客様にとって何ができるのか、サービス全体の構造とメリットをよりよく理解することができます。
ウェブアプリケーションの攻撃と防御のディープダイブ
ウェブアプリケーションは、クラウド上でサービスを提供するための最も一般的な方法であり、最も脆弱なセキュリティターゲットです。本講座を通じて、OWASPがリストアップしたネットワークアプリケーションのセキュリティリスクトップ10を理解することができます。この10のセキュリティリスクを1つずつ解説し、XSS、SQLインジェクション、Webshell、3つの最も一般的な攻撃手法を選択してさらに深く議論し、最後にアリババクラウドのWAF製品を紹介して、オンラインアプリケーションのセキュリティ問題を一挙に解決することができるようにします。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-09-29T13:42:17+09:00
Laravel Passportでgrant_typeを制限する
https://qiita.com/h1na/items/25a08122418df782d2b9
ここにほとんど書いてあるLaravel公式に追加しろって書いてある
Passport::routes();
←これpublic function boot() { $this->registerPolicies(); Passport::routes(); }たどってPassport.phpをみてみると、 デフォルトのコールバックが
$router->all();
public static function routes($callback = null, array $options = []) { $callback = $callback ?: function ($router) { $router->all(); }; }all()って何?って思ったら
\Laravel\Passport\RouteRegister
に書いてあったpublic function all() { $this->forAuthorization(); $this->forAccessTokens(); $this->forTransientTokens(); $this->forClients(); $this->forPersonalAccessTokens(); }じゃあ例えば、
forAuthorization
とforAccessTokens
だけ使いたい!ってなったときPassport::routes(function (RouteRegistrar $router) { $router->forAuthorization(); $router->forAccessTokens(); });こうすればいい
- 投稿日:2020-09-29T13:08:37+09:00
Laravelモデル
今回はmvcモデルのM(モデル)の作成をしていきます。
Model
モデルとはビジネスロジックを書く場所になります。また、データを処理したり、データをDBに保存するところです。逆に、DBから情報を取り出して、Controllerに送ったりしてくれます。
そして、Laravelでモデルを扱うにはEloquent ORM を使っていきます。Eloquent ORM
Laravelで提供されているデータ操作のための機能で、「モデル」と「DB」を対応付けてくれます。ORMとは「Object Relational Mapping」の略称で、プログラミング技法のことです。これにより、DBから取得してきた情報をオブジェクトとして扱う事ができます。
Eloquentモデルの作り方
$ php artisan make:model モデル名* モデル名はテーブルの単数形にする必要がある
このコマンドを打つとファイルが生成されるので、その中にmodelの定義などを書いていきます。また、他のテーブルとの紐付けもこのファイルで操作できます。コマンドを打ち、ファイルが作成されたら、ファイルに記述を加えていきます。<?php namespace App\Models\Modols; // use Illuminate\Database\Eloquent\Factories\HasFactory;//テストで使うらしいです。 use Illuminate\Database\Eloquent\Model; class Blog extends Model//上のモデルを継承してBlogというクラスを作っている { // use HasFactory;//テストで使うらしいです。 //テーブル名 protected $table = 'blogs';//使いたいテーブル名を指定 //可変項目 protected $fillable = [ 'title', 'content' ]; }$fillableとguarded
上記で可変項目として、'title','content'と書いてあると思いますが、ここについて説明していきます。
isertやcreateメソッドでテーブルのカラムに値を挿入する際、予期せぬ代入が起こる事を防ぐために、モデルへ、$fillable or $guardedを設定する必要があります。予期せぬ代入とは
複数代入による予期せぬ代入とは、製作者が意図していない代入のことです。ユーザーから変えて欲しくない値(id,passwordなどの管理者権限を管理するカラム)を自由に変えられてしまっては困ります。そこで入力によって変動する値を安全に管理するために、$fillable or $guardedで値を管理します。
$fillable
$fillableとはホワイトリストと言い、
複数代入時に代入を許可する属性を配列で設定
します。解釈があってるか分かりませんが、変更可能な値を保存する時に使います。protected $fillable = ['name','age','update_at'];$guraded
$guardedは$fillableとは逆にブラックリストと言い、
複数代入時に代入を許可しない属性と配列で設定
します。変更して欲しくない値を保存する際に使います。両者の属性は併せて使うことはできません。protected $guarded = ['id'];他の生成メソッド
他にも属性の複数代入可能なメソッドが2つあります。
firstOrCreate
とfirstOrNew
です。firstOrCreate
指定されたカラム/値ペアでデータベースレコードを見つけようとします。モデルがデータベースで見つからない場合には指定された属性でレコードが挿入されます。
$flight = App\Flight::firstOrCreate(['name'] => 'Flight 10');//属性のフライトを取得するか、存在しなければ作成firstOrNew
指定されたデータベースのレコードを見つけようとします。モデルが見つからない場合は、新しいモデルインスタンスが返されます。こちらが返すモデルはデータベースに保存されません。保存するには
save
メソッドが必要になります。$flight = App\Flight::firstOrNew(['name'] => 'Flight 10');//属性のフライトか、存在しなければ、新しいインスタンスを取得するモデル削除
モデルを削除する際には、モデルに対して、
delete
メソッドを呼び出します。$flight = App\Flight::find(1); $flight =->delete();上記では
delete
メソッドを呼び出す前にデータベースからモデルを取得しています。しかしモデルの主キーが分かっているのならdestroy
メソッドを使えます。これによりモデルを取得せずに削除できます。App\Flight::destroy(1); App\Flight::destroy([1,2,3]);終わりに
基本的なモデルの説明でした。
参考サイト
https://snome.jp/framework/mvc-model/
https://qiita.com/kk_take/items/3e0639ed605f74c34619
https://udemy.benesse.co.jp/development/web/laravel-model.html
- 投稿日:2020-09-29T12:58:53+09:00
Elastic ComputeService上のNginxおよびHHVMを使用したUbuntu16.04へのWordPressのインストール
この記事では、Alibaba Cloud Elastic Compute Service (ECS)上のUbuntu 16.04にNginxとHHHVMを使用してWordPressをインストールする方法について、いくつかの情報を得ることができます。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
HHVMはHipHop Virtual Machineとしても知られており、Facebookが開発したオープンソースの仮想マシンで、HackやPHPで書かれたプログラムを実行するために使用することができます。HHVMは、パフォーマンスの理由からジャストインタイムのコンパイルアプローチを採用しています。HHVMはZENDの従来のPHPエンジンよりも高速で、Facebookが1日に何十億ものWebリクエストに対応するために使用しています。
前提条件
1、Ubuntu 16.04サーバをインストールしたばかりのAlibabaクラウドインスタンス。
2、インスタンスに静的IPアドレス192.168.0.103が構成されています。
3、サーバにrootパスワードを設定します。その後、こちらをクリックすると、NginxとMariaDBのインストール、MariaDBの設定、HHVMのインストールと設定の手順が表示されます。これらのパッケージのインストールと設定に成功したら、WordPressのインストールを続けます。
WordPressをインストール
まず、WordPressの最新版を公式サイトからダウンロードする必要があります。これは以下のコマンドで行うことができます。
wget https://wordpress.org/latest.zipダウンロードが完了したら、以下のコマンドでダウンロードしたファイルを解凍します。
unzip latest.zip次に、以下のコマンドで解凍したディレクトリをNginxのWebルートディレクトリにコピーします。
cp -r wordpress/* /var/www/html/次に、ディレクトリを/var/www/html/に変更し、wordpressのサンプル設定ファイルをコピーします。
cd /var/www/html/ cp wp-config-sample.php wp-config.php次に、wp-config.phpファイルを開き、先ほど作成したデータベースの認証情報を追加します。
nano wp-config.php以下の変更を行います。
/* The name of the database for WordPress / define('DB_NAME', 'wordpressdb'); /* MySQL database username / define('DB_USER', 'wordpress'); /* MySQL database password / define('DB_PASSWORD', 'password'); /* MySQL hostname / define('DB_HOST', 'localhost’);保存してファイルを閉じ、WordPressに適切なパーミッションを与えます。
chown -R www-data:www-data /var/www/html/ chmod -R 775 /var/www/html/最後に、NginxとHHVMのサービスを再起動します。
systemctl restart nginx systemctl restart hhvmそして、WordPressのWebインストールウィザードにアクセスすると、こちらに詳細が記載されています。
関連ブログ記事
Ubuntu-16.04にZabbixをインストールして設定する方法
Zabbixはオープンソースのエンタープライズクラスのネットワーク監視ツールで、サーバ、ネットワークデバイス、その他のネットワークコンポーネントのパフォーマンスと可用性を監視するために使用できます。ZabbixはMySQL、PostgreSQL、Oracleを使用してデータを保存します。また、Zabbixはデータや設定を監視・追跡するためのユーザーフレンドリーなWebインタフェースを提供しています。ZabbixはZabbixエージェントを使用してデータを収集し、Zabbixサーバに送信します。
このチュートリアルでは、Ubuntu 16.04サーバにZabbixサーバとZabbixクライアントをステップバイステップでインストールしていきます。
UbuntuにLAMPをインストールする方法
この記事では、Ubuntuにランプをインストールする方法と、LAMPを使ってUbuntuマシンにアプリケーションをインストールするためのいくつかのガイドを紹介します。
関連市場商品
パートナーが構築したPHPインフラを使って、アリババクラウドのサーバー上ですぐに立ち上げることができる製品があります。
Websoft9(HHVM)を利用したPHPの高性能なインフラストラクチャ
Websoft9 HHVMは、Alibaba Cloud上でHHVMを実行するための設定済みの実行準備の整ったイメージです。
LEMP CentOS7.2 64ビット版のWordpressは、IGSで動作
最新のCentOS上で、ブログやウェブサイトを構築するための世界で最も人気のあるウェブ公開プラットフォームと統合されています。IGSは、ウェブソリューションのための最も人気のあるソフトウェアと事前に統合されたイメージのリストを提供しています。これには、Apache/Nginx、MySQL、PHP、phpMyAdmin、およびこれらのコンポーネントを実行するために必要な他のすべてのソフトウェアの実行可能なバージョンが含まれています。IGSイメージは、ウェブアプリケーションの開発と展開を大幅に簡素化します。
関連ドキュメント
いくつかのドキュメントが参考になるかもしれません。
ACM PHP SDK
ACMは、ACMでアプリケーションの設定を管理するためのPHP SDKをPHPプログラム用に提供しています。
ACM PHP SDKは現在オープンソース化されています。手順はGithubを参照してください。
PHPのバージョンを変更
ウェブホスティングはPHPをサポートしており、デフォルトではPHP 5.3を使用しています。
デフォルトのPHPのバージョンがプログラムで必要とされるものと異なる場合は、PHPのバージョンを変更することができます。
関連製品
ApsaraDB for RDSは、データベース管理の管理タスクから解放され、コアビジネスに集中できる時間を確保できるオンデマンドのデータベースサービスです。ApsaraDB for RDSは、MySQL、SQL Server、PostgreSQL上で提供されるすぐに使えるサービスです。RDSは、プロビジョニング、パッチアップ、バックアップ、リカバリ、障害検出、修復などの日常的なデータベースタスクを処理します。
分散リレーショナルデータベースサービスは、シングルホストリレーショナルデータベースのスケーラビリティの問題を解決するために、アリババグループが独自に開発した軽量(ステートレス)、柔軟性、安定性、効率性に優れたミドルウェア製品です。
DRDSは主に大規模なオンラインデータ運用に使用され、ライフサイクル全体を通して分散データベースの運用・保守・管理を行います。DRDSはコンパートメント化された構造のため、リレーショナルデータベースのオンラインサービスの需要に合わせて効率的な運用を行うことができます。Alibaba Cloud Virtual Private Cloudでは、論理的に分離された安全な環境でクラウドアーキテクチャを柔軟に構築することができます。これは、IPアドレス範囲の選択、サブネットの作成、ルートテーブルやネットワークゲートウェイの設定など、ユーザーが仮想ネットワーク環境を制御できることを意味します。また、ユーザーは、セキュリティグループ機能を使用して、VPCインスタンスを異なるセキュリティドメインに分離することもできます。
関連コース
クラウド上のリレーショナルデータベースの運用と管理
このclouderレッスンでは、RDSの概念と機能、SQLデータベースをホストして管理するためにRDSコンソールを使用する方法を学びます。
DTSでローカルDBからRDSへのデータ移行を実装 - ライブデモ
データ伝送サービス(DTS)は、リレーショナルデータベース、NoSQL、OLAPなどのデータストレージタイプ間のデータ移行を支援します。このサービスは、異なるデータストレージタイプ間の同種移行だけでなく、異種移行もサポートしています。
このデモセッションでは、DTSを使用してAlibaba CloudのRDSインスタンスにローカルデータベースを移行する方法を紹介します。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-09-29T12:45:43+09:00
mysqlで新規ユーザーを作成する方法
1 まずはデフォルトユーザーであるrootでmysqlにログインする
mysql -u root
2 ログインできたら、mysqlのユーザ一覧でどんなユーザーがいるのか確認する
SELECT Host, User FROM mysql.user;
3 新しくユーザー作成する
grant all on データベース名.* to ユーザー名@接続元 identified by ‘パスワード’;
4 現在rootでログインしてるためexitでログアウトする
5 新規で作成したユーザーでログインする
mysql -u ユーザー名 -p
- 投稿日:2020-09-29T10:16:08+09:00
Laravel テストコードを書いてみよう
目的
- Laravelのフューチャーテストコードの書き方をまとめる
実施環境
- ハードウェア環境
項目 情報 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 Homwbrewを用いて導入 Laravel バージョン 8.6.0 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 前提条件
- 実施環境と同じ、もしくは準ずる環境が構築されていること。
前提情報
- Laravelのテストはフューチャーテストとユニットテストが存在しこの記事ではフューチャーテストの方法を紹介する。
- MacのローカルにLaravelアプリを作成し
$ php artisan serve
コマンドを用いてローカルサーバを起動して確認するものする。- 「特定の文字がビューに表示されているか」と「Httpステータスコードの200が帰ってくるか」を確認する。
概要
- アプリの作成
- ルート情報の記載
- コントローラーファイルの作成と記載
- ビューファイルの作成と記載
- テストコードの作成と記載
- テストの実行
詳細
アプリの作成
任意のディレクトリで下記コマンドを実行してLaravelアプリを作成する。
$ laravel new feature_test先のコマンドで作成された
feature_test
ディレクトリに移動する。ルート情報の記載
feature_testディレクトリで下記コマンドを実行してルーティングファイルを開く。
$ vi routes/web.php下記のルーティング情報を追記する。
feature_test/routes/web.phpRoute::get('/hello', 'App\Http\Controllers\HelloController@index');追記後のルーティングファイルの内容を下記に記載する。
feature_test/routes.web.php<?php use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::get('/', function () { return view('welcome'); }); // 下記を追記する。 Route::get('/hello', 'App\Http\Controllers\HelloController@index');コントローラーファイルの作成と記載
feature_testディレクトリで下記コマンドを実行してコントローラファイルを作成する。
$ php artisan make:controller HelloControllerfeature_testディレクトリで下記コマンドを実行して先に作成したコントローラファイルを開く。
$ vi app/Http/Controllers/HelloController.php開いたコントローラファイルに下記のアクションを追記する。
feature_test/app/Http/Controllers/HelloController.phppublic function index() { return view('hello/index'); }追記後のコントローラファイルの内容を下記に記載する。
feature_test/test/Http/Controllers/HelloController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class HelloController extends Controller { public function index() { return view('hello/index'); } }ビューファイルの作成と記載
feature_testディレクトリで下記コマンドを実行してビューファイルを格納するディレクトリを作成する。
$ mkdir resources/views/hellofeature_testディレクトリで下記コマンドを実行してビューファイルを作成する。
$ vi resources/views/hello/index.blade.php開いたファイルに下記の内容を記載する。
resources/views/hello/index.blade.php<h1>hello japan!</h1>feature_testディレクトリで下記コマンドを実行してローカルサーバを起動する。
$ php artisan serve下記にアクセスして「Hello japan!」の文字が表示されていることを確認する。
テストコードの作成と記載
feature_testディレクトリで下記コマンドを実行してテストコード用のファイルを作成する。
$ php artisan make:test HelloIndexPageTestfeature_testディレクトリで下記コマンドを実行して先に作成したテストコードファイルを開く。
$ vi tests/Feature/HelloIndexPageTest.php開いたテストコードファイルを下記の様に追記・修正をする。
feature_test/tests/Feature/HelloIndexPageTest.php<?php namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; use Tests\TestCase; class HelloIndexPageTest extends TestCase { /** * A basic feature test example. * * @return void */ public function testStatusCode() { $response = $this->get('/hello'); $response->assertStatus(200); } public function testBody() { $response = $this->get('/hello'); $response->assertSeeText('hello japan!'); } }テストの実行
feature_testディレクトリで下記コマンドを実行してテストを実行する。
$ vendor/bin/phpunit tests/Feature/HelloIndexPageTest.php下記の様に出力されればテストは完了であり、当該ページはテスト条件を満たしている。
OK (2 tests, 2 assertions)
参考文献
- 投稿日:2020-09-29T03:25:14+09:00
【PHP初心者向け】MySQLからSQL文で絞り込み、結果をサイトに表示する
0.概要
デザイナーをやっていると、静的なサイトは作れるものの、
動的なサイトを作る時にはエンジニアに頼むことが多く、
自身で完結できないことが歯痒い時があります(実体験)。そこで今回は、
データベース(今回はMySQL)に保存したデータを、
条件によって動的に出し分け(PHPで、SQLのクエリを書く)、
サイトに表示する方法を記載いたします。1.はじめに(データベースの準備)
まず最初に、データベース自体にデータを入れます。
借りてるレンタルサーバーのコントロールパネルから、
phpMyAdminにログインするか、
データベースをデータベース管理ツールと連携させましょう。オススメの無料データベース管理ツールは下記の2つです。
名前 特徴 入手先URL DBeaver クラシカルなUIだが多機能。ER図というDBの繋がりを表示してくれる機能がある。※今回はこれを実例に進めて参ります。 https://dbeaver.io/ Metabase ビジュアライズが充実している。クエリを知らなくともGUI上で色々できるのでデザイナーにも扱いやすい。 https://www.metabase.com/start/oss/jar ※導入に関しては他の方が書かれた下記の記事を参考にして下さい。
・ データベースツール DBeaver のインストール(Windows 上)
https://www.kkaneko.jp/tools/win/dbeaver.html
・MetabaseをWindowsにインストールする
https://qiita.com/n-i-e/items/b721687903055659ee2d上記いずれかのデータベースにて入れたら、
まずはDB上にテーブル・カラム(項目名)を設定するために、
UI上にてテーブルの設定、カラムの設定、レコードの追加を行って下さい。ここではDBeaverの画面を参考に進めて参ります。
・テーブルの追加
ツリーでDBをクリックし、ウインドウで開いたら[テーブル]を右クリックし、
[新しく作る 表]をクリックすると設定画面に入り、作成されます。
・カラムの追加
先程作成されたテーブルを開き、[列]にて、右クリックし、
[新しく作る カラム]をクリックすると設定画面に入り、作成されます。
・レコードの追加
最後に、今設定されたテーブル・カラムにレコードを追加するため、
SQL文のエディタを開きます。
DBeaverであれば、メニューの[SQLエディタ]から開けます。
開けたらDB上に新規レコードを追加するクエリを記述しましょう。
INSERT INTO [DB名].[テーブル名] ([カラム名1], [カラム名2]) VALUES('[カラム名1の値]', '[カラム名2の値]');※[]は削除し、中身をご自身のDBに合わせた文字に変えて下さい。
終了したらテーブルの[データ]にてちゃんと追加されているか確認しましょう。
私の場合は2つのレコードを下記のように入れ、問題ないことを確認しました。
2.PHP側でのMySQLとの連携
データベースの準備が出来たら、
PHPの読み込むファイル(例えばindex.phpなど)に、
MySQLへ接続するための、情報を記載いたします。<?php // MySQLの接続情報をセット $db = 'mysql:host=[データベースのホスト名];dbname=[データベース名]'; $user = '[ユーザー名]'; $pass = '[パスワード]'; //接続のテスト try { $pdo = new PDO($db, $user, $password); echo "接続に成功しました"; } catch (PDOException $e) { echo "接続に失敗しました"; exit(); } //次のステップの時にここにSQLを書く ?>こちらを読み込んでみて「接続に成功しました」と出れば成功です。
接続に失敗しましたと表示された場合は、接続設定を見直してみて下さい。豆知識・・・PDOはPHP Data Objectが正式名称です。
3.実際にクエリを書いて反映してみる
先程のphpファイルの、
//次のステップの時にここにSQLを書くを書き換えます。
が、SQLを書く際はprepare文とexecute文で前処理をする必要があり、
その記述も合わせて書きましょう。// SQLを書く(''の中は任意のクエリを記述) $sql = 'SELECT [表示項目] FROM [データベース名].[テーブル名] WHERE [条件]'; // prepare文で上記のSQLを定義し、execute文で定義したSQLを実行 $prepare = $pdo->prepare($sql); $prepare->execute(); // 結果を出力 foreach($prepare->fetchAll() as $result){ // echo $result['カラム名'];にて出力できる }私の場合、クエリにてshop_idがtest1のものに絞り、
2つのカラム(shop_nameとshop_id)をh2要素として表示させたため、
と表示されました。4.最後に
今回はクエリをこちら側で書きましたが、
サイト閲覧者に入力してもらうことによって、
ユーザー毎にリクエストした結果を表示することも可能です。今後、その方法も記事にして行きます。