20201023のPHPに関する記事は17件です。

【PHP】FizzBuzzをカンマ&スペース区切りで出力できますか?

本記事の内容

FizzBuzzのちょっとしたアレンジ

要件

・1〜40までの数字を出力
・ただし3の倍数なら、その数字は"Fizz"と出力
・ただし5の倍数なら、その数字は"Buzz"と出力
・ただし3の倍数かつ5の倍数なら、その数字は"FizzBuzz"と出力
・ただし、各数字の間に、カンマ と 半角スペースを設けること

期待値

1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16, 17, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26, Fizz, 28, 29, FizzBuzz, 31, 32, Fizz, 34, Buzz, Fizz, 37, 38, Fizz, Buzz

ポイント

最後の数字(この場合はBuzzという文字)の後ろに、カンマと半角スペースを入れないようにするには?

答えの一例(ちょっとだけでも考えたうえで、ご覧ください)

$data = 40;

for($i = 1; $i <= $data; $i++){
    if($i % 15 == 0){
        echo "FizzBuzz";
    }elseif($i % 3 == 0){
        echo "Fizz";
    }elseif($i % 5 == 0){
        echo "Buzz";
    }else{
        echo $i;
    }

    if($i < $data){
        echo ", ";
    }

}

ひとこと

・数字だけでなく、カンマと半角スペースも、for文で出力する要素とみなして、
かつ繰り返し回数が最終回でない限り出力する、ということでした。
頭の体操でもになれば幸いです。

この記事を書いた人

現役エンジニアです。よければツイッターフォローお願いいたします。
自分含め、エンジニアで頑張っている人を褒めて、励ますようなツイートを心がけています。
https://twitter.com/ohara5555

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

Laravel:リダイレクトの記載

【概要】

1.どのように記載するか

2.開発環境

1.どのように記載するか

redirect()->route( ルート名 , 配列 )
redirect()->action( アクション名 , 配列 )
redirect()->view( ビュー名 , 配列 )
redirect()->download( ファイルパス名 )
redirect()->file( ファイルパス名 )

・ルート名は、Laravelでよく使う"web.phpに記載してあるルート情報になります。
・アクション名は、"XXXXController@index","XXXXController@show"などになります。
・ビュー名は、直接"XXXX.index"などが入ります。
・ファイルパス名は、イメージファイル名やファイルパスをテキストで記載します。


2.開発環境

PHP 7.4.10
Laravel 8.9

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

Laravel8.9.0 + Vue.jsでaxiosを使ったときにthenとcatchの両方を通るときの対処法

@babel/runtimeをインストールする

npm install --save @babel/runtime
npm install --save-dev @babel/plugin-transform-runtime
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Moodle 3.9 マニュアル - 追加の名前フィールド

原文

追加の名前フィールド

名字と苗字の他に、以下の追加の名前フィールドを使用することができます。

名字 - 表音文字
苗字 - 音韻
ミドルネーム
別名

内容

1 管理設定
1.1 フルネーム形式
1.2 代替フルネームフォーマット
2 ユーザープロファイル設定

1 管理設定

1.1 フルネーム形式

フルネームが表示されているユーザーの一覧

管理者は、管理 > サイト管理 > ユーザー > 権限 > ユーザーポリシーの「フルネームフォーマット」(fullnamedisplay)の設定で、サイト全体での名前の表示方法を設定することができます。デフォルトの設定は言語で、サイトで使用されている言語パックの情報に従って名前が表示されます。代わりに、以下のプレースホルダを使用することもできます。

ファーストネーム
ラストネーム
ファーストネーム電話
ラストネームフォネティック
中名
替名

例えば、ファーストネームがJohn、苗字がDoe、ミドルネームがJames、ファーストネームがJon、苗字がDoughのユーザーは、彼の名前が次のように表示されます。

・John James Doe は、「フルネームのフォーマット」がファーストネーム、ミドルネーム、ラストネームに設定されている場合に使用します。
・フルネーム形式」がlastname firstname(lastnamephonetic firstnamephonetic)に設定されている場合のドゥー・ジョン(Dough Jon)。

フルネーム表示のケイパビリティ:翻訳準備中を持つユーザー(デフォルトではマネージャー、教師、または非編集教師の役割を持つユーザー)は、"フルネーム形式 "の設定にかかわらず、常にファーストネームとラストネームを表示することができます。

以前のバージョンからアップグレードしたサイトの場合の注意事項。フルネーム形式」設定は以前はサイトポリシーにありました。

300px-participants-after.png

1.2 代替フルネームフォーマット

代替フルネームフォーマット設定は、フルネーム表示のケイパビリティ:翻訳準備中を使用してユーザーに表示される名前の方法を定義するために使用することができます。例えば、lastname firstname(lastnamephonetic firstnamephonetic)に設定して、音声名も表示されるようにすることができます。

2 ユーザープロファイル設定

ユーザーは、管理 > マイプロファイル設定 > プロファイルの編集でプロファイルを編集することで、追加の名前を入力することができます。

フルネーム形式」で管理者が指定した姓名、名字、および追加の名前は、「一般」セクションに記載されています。フルネーム形式」で指定されていない追加名は、「追加名」の項目に記載されています。

300px-name_fields_in_general_section.png
「フルネームフォーマット」で指定された名前のフィールド

300px-additional_name_fields.png
追加の名前フィールド

カテゴリ | アカウント | サイト管理

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

ラッコはCakePHPでWHERE条件付きのUPDATEをする方法がわからない

どうもオッターです。
久々に使う関数って使い方わからなくなることありますよね。

今回は条件句付きのUPDATE文ってどうやってCakePHPで実行させるのか、忘れたのでしらべたよ。

CakePHP UPDATE などと調べてみるとこちらの記事を発見。(めちゃくちゃわかりやすかったです。見習っていきたい)
https://qiita.com/PallCreaker/items/14ef5cdec236f2b97fa7

きちんとソースを確認すべくドキュメントを呼んだところ、やはりこのやり方でOKとわかりました。
https://api.cakephp.org/4.1/interface-Cake.Datasource.RepositoryInterface.html#updateAll

updateAll()の第二引数に条件句を連想配列で表したものを入れれば、万事解決。
めでたしめでたし!

僕のようにフロントもバックも担当していると、あまり使わない関数については忘れがちですが、こんなふうに検索する方法やドキュメントの読み方を身に着けておくと5分もかからず答えにたどり着けるんだなぁと思った金曜日でした。

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

Laravelでプロジェクト作成後にすべきこと

概要

Laravelでアプリ作成時に自分がプロジェクト作成後、最初に設定していることをメモとしてまとめました。

何か間違い等がございましたら、ご指摘していただけたらと思います!

新規プロジェクト作成

composerコマンドでLaravelのプロジェクトを作成します。

ターミナル
$ composer create-project --prefer-dist laravel/laravel <プロジェクト名>

念のため、Laravelが導入されたか確認。

ターミナル
$ cd ~/<プロジェクト名>
php artisan -v

Laravel Framework <バージョン>

httpsへの対応

app/Http/Middleware/TrustProxies.php の一部を下記のように変更します。

app/Http/Middleware/TrustProxies.php
protected $proxies;

// 上記の記述を下記のように変更

protected $proxies = '*';

Laravel 5.5以前は'**'だそうです。

【公式】Laravel 5.5 HTTPリクエスト
【公式】Laravel 8.x HTTPリクエスト
// ページ最下部の「信用するプロキシの設定」参照

APP_NAMEの設定

.env
APP_NAME = <アプリケーション名>
config/app.php
'name' => env('APP_NAME', '<アプリケーション名>'),

APP_KEY

ターミナル
$ php artisan key:generate

APP_KEYの解説 → [Laravel5.5] APP_KEY の行方を追う

public/storageにstorage/app/publicへのシンボリックリンク作成

ターミナル
php artisan storage:link

解説

データベースの設定

MySQLに接続し、データベースを作成(rootユーザーで作成する場合)

ターミナル
$ mysql -u root

mysql> CREATE DATABASE <データベース名>
env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=データベース名
DB_USERNAME=root
DB_PASSWORD=

.envファイルの変更が反映されない場合があるのでキャッシュクリアを。

ターミナル
$ php artisan cache:clear

$ php artisan config:cache

MySQLコマンドまとめ


root以外のユーザーを作成し、使用する場合

上記のようにMySQLに接続し、データベースを作成。

以下の手順でユーザーを作成。

CREATE USER '<登録するユーザーの名前>'@'<アクセス元になるIP>' IDENTIFIED BY '<パスワード>'

#例(ユーザー名: user 、アクセス元: localhost 、 パスワード XXXXXXXX )

CREATE USER 'user'@'localhost' IDENTIFIED BY 'XXXXXXXX'
GRANT ALL PRIVILEGES ON <プロジェクト名>.* TO 'user'@'localhost';
env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=データベース名
DB_USERNAME=root
DB_PASSWORD=

.envファイルの変更が反映されない場合があるのでキャッシュクリアを。

ターミナル
$ php artisan cache:clear

$ php artisan config:cache

タイムゾーンの変更

config/app.php
'timezone' => 'UTC',

// 変更

'timezone' => 'Asia/Tokyo',

言語の日本語化

config/app.php
'locale' => 'en',

// 変更

'locale' => 'ja',
config/app.php
'faker_locale' => 'en_US',

// 変更

'faker_locale' => 'ja_JP',

ログイン画面やエラーメッセージなどの日本語化

こちらはLaravelで日本語化の記事で解説しています。

デバッグバーの導入

Authの設定(必要な場合)

こちらはLaravelでAuthを導入の記事で解説しています。

Laravel Mixの環境構築

こちらはLaravel Mixのインストールの記事で解説しています。

参考記事

[Laravel5.5] APP_KEY の行方を追う

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

Laravelでインストールしたらやることのメモ

概要

Laravelでアプリ作成時に自分がプロジェクト作成後、最初に設定していることをメモとしてまとめました。

何か間違い等がございましたら、ご指摘していただけたらと思います!

新規プロジェクト作成

composerコマンドでLaravelのプロジェクトを作成します。

ターミナル
$ composer create-project --prefer-dist laravel/laravel <プロジェクト名>

念のため、Laravelが導入されたか確認。

ターミナル
$ cd ~/<プロジェクト名>
php artisan -v

Laravel Framework <バージョン>

httpsへの対応

app/Http/Middleware/TrustProxies.php の一部を下記のように変更します。

app/Http/Middleware/TrustProxies.php
protected $proxies;

// 上記の記述を下記のように変更

protected $proxies = '*';

Laravel 5.5以前は'**'だそうです。

【公式】Laravel 5.5 HTTPリクエスト
【公式】Laravel 8.x HTTPリクエスト
// ページ最下部の「信用するプロキシの設定」参照

APP_NAMEの設定

.env
APP_NAME = <アプリケーション名>
config/app.php
'name' => env('APP_NAME', '<アプリケーション名>'),

APP_KEY

ターミナル
$ php artisan key:generate

APP_KEYの解説 → [Laravel5.5] APP_KEY の行方を追う

public/storageにstorage/app/publicへのシンボリックリンク作成

ターミナル
php artisan storage:link

解説

データベースの設定

MySQLに接続し、データベースを作成(rootユーザーで作成する場合)

ターミナル
$ mysql -u root

mysql> CREATE DATABASE <データベース名>
env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=データベース名
DB_USERNAME=root
DB_PASSWORD=

.envファイルの変更が反映されない場合があるのでキャッシュクリアを。

ターミナル
$ php artisan cache:clear

$ php artisan config:cache

MySQLコマンドまとめ


root以外のユーザーを作成し、使用する場合

上記のようにMySQLに接続し、データベースを作成。

以下の手順でユーザーを作成。

CREATE USER '<登録するユーザーの名前>'@'<アクセス元になるIP>' IDENTIFIED BY '<パスワード>'

#例(ユーザー名: user 、アクセス元: localhost 、 パスワード XXXXXXXX )

CREATE USER 'user'@'localhost' IDENTIFIED BY 'XXXXXXXX'
GRANT ALL PRIVILEGES ON <プロジェクト名>.* TO 'user'@'localhost';
env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=データベース名
DB_USERNAME=root
DB_PASSWORD=

.envファイルの変更が反映されない場合があるのでキャッシュクリアを。

ターミナル
$ php artisan cache:clear

$ php artisan config:cache

タイムゾーンの変更

config/app.php
'timezone' => 'UTC',

// 変更

'timezone' => 'Asia/Tokyo',

言語の日本語化

config/app.php
'locale' => 'en',

// 変更

'locale' => 'ja',
config/app.php
'faker_locale' => 'en_US',

// 変更

'faker_locale' => 'ja_JP',

ログイン画面やエラーメッセージなどの日本語化

こちらはLaravelで日本語化の記事で解説しています。

デバッグバーの導入

Authの設定(必要な場合)

こちらはLaravelでAuthを導入の記事で解説しています。

Laravel Mixの環境構築

こちらはLaravel Mixのインストールの記事で解説しています。

参考記事

[Laravel5.5] APP_KEY の行方を追う

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

[PHP] SimpleXMLElement の使い方

環境:PHP Version 7.4.9

XML文字列の読込

$xmlString = <<<EOM
    <hoge>
        <moge></moge>
    </hoge>
EOM;
$xml = simplexml_load_string($xmlString);

simplexml_load_string() でXML文字列を読み込める。
パラメータにはXML文字列を指定する。

XMLファイルの読込

$xml = simplexml_load_file($xmlFilePath);

simplexml_load_file() でXMLファイルを読み込める。
パラメータにはXMLファイルのパスを指定する。

子ノードへのアクセス

$xmlString = <<<EOM
    <hoge>
        <moge></moge>
    </hoge>
EOM;
$xml = simplexml_load_string($xmlString);
$child = $xml->moge;

アロー演算子でアクセスできる。

プロパティへのアクセス

$xmlString = <<<EOM
    <hoge PropA="1" PropB="2">
    </hoge>
EOM;
$xml = simplexml_load_string($xmlString);
$propA = (string) $xml->attributes()->PropA;
$propB = (string) $xml->attributes()->PropB;

attributes() で属性一覧を取得したあと、アロー演算子でアクセスする。
また、そのままでは値として扱いにくいので string へのキャストも併せて行う。

ノード名の取得

$xmlString = <<<EOM
    <hoge>
    </hoge>
EOM;
$xml = simplexml_load_string($xmlString);
$name = $xml->getName();

getName() で名前を取得できる。
今回の例なら「hoge」が取得できる。

全ての子ノードを取得してループ

$xmlString = <<<EOM
    <hoge>
        <moge></moge>
        <moge></moge>
        <moge></moge>
        <sage></sage>
        <sage></sage>
    </hoge>
EOM;
$xml = simplexml_load_string($xmlString);
$children = $xml->children();
foreach ($children as $val) {
   // 何らかの処理
}

children() で全ての子ノードを取得できる。

特定の子ノードを取得してループ

$xmlString = <<<EOM
    <hoge>
        <moge></moge>
        <moge></moge>
        <moge></moge>
        <sage></sage>
        <sage></sage>
    </hoge>
EOM;
$xml = simplexml_load_string($xmlString);
foreach ($xml->moge as $val) {
   // mogeのみに何らかの処理
}

アロー演算子を用いて特定の子ノードに対してのみループを行える。

JSONへの変換

$xmlString = <<<EOM
    <hoge>
        <moge></moge>
        <moge></moge>
        <moge></moge>
        <sage></sage>
        <sage></sage>
    </hoge>
EOM;
$xml = simplexml_load_string($xmlString);
$json = json_encode($xml);
foreach ($json as $val) {
   // 何らかの処理
}

json_encode() でJSON形式への変換ができる。




以上。

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

Moodle 3.9 マニュアル - アカウントFAQ

原文

アカウントFAQ

目次
1 どのようにしたら生徒に自分のMoodleサイトにサインアップさせることができますか?
2 ユーザのアカウントを停止するにはどうすればよいですか?
3 ユーザのアカウントの削除と一時停止の違いは何ですか?
4 アカウントが作成されたとき、Moodleは新しいユーザに通知メールを自動的に送信することができますか
5 他のユーザとしてログインするにはどうすればよいですか?
6 ユーザが自分のプロフィールの要素を編集できないようにするにはどうすればいいですか?
7 ユーザの検索ボックスは表示されるユーザ数が100に制限されています。これを変更することはできますか?
8 ユーザーデータを含むcsvファイルをアップロードするとエラーが発生します。

1 どのようにしたら生徒に自分のMoodleサイトにサインアップさせることができますか?

Eメールベースの自己登録を設定する方法(翻訳準備中)をご覧ください。

2 ユーザのアカウントを停止するにはどうすればよいですか?

プロファイル編集ページの「アカウントの一時停止」チェックボックスにチェックを入れてください。

3 ユーザのアカウントの削除と一時停止の違いは何ですか?

両方のオプションの詳細については、ユーザの一覧(翻訳準備中)を参照してください。

4 アカウントが作成されたとき、Moodleは新しいユーザに通知メールを自動的に送信することができますか?

はい。手動で追加されたユーザについては、新規ユーザの追加を参照してください。

ユーザ用のCSVを作成し、パスワードフィールドをOMITした場合、cronジョブが起動され、ユーザにEメールが送信されます。電子メールのテキストは、管理者が管理者設定でカスタマイズできます。ユーザーをアップロードするを参照してください。

5 他のユーザとしてログインするにはどうすればよいですか?

これはセキュリティ上の問題があるため、通常は管理者か管理者のみに許可されています。ユーザーのプロフィールをクリックして、管理のセクションを見てください。そこに「Log in as」リンクが表示されます。

終了するとログアウトされ、再度ログインしなければならないことに注意してください。これはセキュリティ上の理由から意図的に行われていますが、先ほどのページに戻ります。

6 ユーザが自分のプロフィールの要素を編集できないようにするにはどうすればいいですか?

管理 > サイト管理 > プラグイン > 認証 > 手動アカウントからユーザーフィールドをロックすることができます。

7 ユーザの検索ボックスは表示されるユーザ数が100に制限されています。これを変更することはできますか?

はい - ユーザーポリシー(翻訳準備中)を参照してください。

8 ユーザーデータを含むcsvファイルをアップロードするとエラーが発生します。

これはいくつかの原因が考えられます。

メモ帳やメモ帳++などのテキストエディタでファイルを開き、余分なカンマがないことを確認してください。
例えば'course1', 'course2'フィールドを使用する場合は、コースの名前がSHORTであることを確認してください。
コホートをアップロードする場合は、コホート名ではなくコホートの ID を使用してください。
あなたが国を追加する場合は、2文字の国コードではなく、完全な国名を使用していることを確認してください。

カテゴリー | アカウント | サイト管理 | FAQ

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

Nano-Terminal (php上でterminal)

参考

1ファイルだけで利用ができるので持ち運びやすい

インストール

git clone https://github.com/tukiyo/Nano-Terminal
cd Nano-Terminal
  • terminal.php内でユーザー名、パスワードの指定をするとログインができる。
    • なおvimなどは動かない。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

10分でLaravelにログイン認証を追加する手順

はじめに

LaravelのWebアプリに10分で認証機能を追加します。
予めLaravelプロジェクトやSQLite3が用意できていれば、10分もかからず3分でもできるかもしれません。。。
それくらい簡単!

Laravel公式ガイド

Laravel公式ガイドの認証に関する情報は以下のページにあります。
ざっくり手を動かしてみたら、一読することをオススメします。

Laravel 5.7 認証

ログイン認証機能の追加手順

Laravelプロジェクトがまだ無い状態を想定して、プロジェクト作成から進めます。

デモ用のLaravelプロジェクトを作成

Laravelプロジェクトを作成

composer create-project laravel/laravel=5.7 laravel_auth_demo

SQLiteデータベースファイル作成

touch database/database.sqlite

LaravelプロジェクトのDB接続情報を変更

viで設定ファイルを開きます。

vi .env

以下の記述を、

.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

以下のように書き換えます。

.env
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=homestead
# DB_USERNAME=homestead
# DB_PASSWORD=secret

ここまでの動作確認

以下のコマンドでテスト用サーバを起動します。

php artisan serve

Laravelと表示されることを確認してください。

Laravelプロジェクトに認証機能を追加

認証用のビューを追加

Ctrl+Cで開発サーバを停止し、以下のコマンドを実行します。

php artisan make:auth

Authentication scaffolding generated successfully.というメッセージが表示されれば成功です。
以下のファイルが新たに作成されており、web.phpも認証用に書き換えられています。

  • auth/login.blade.php
  • auth/register.blade.php
  • auth/verify.blade.php
  • auth/passwords/email.blade.php
  • auth/passwords/reset.blade.php
  • layouts/app.blade.php
  • home.blade.php

認証用のテーブルを作成

以下のコマンドを実行します。

php artisan migrate

Migration table created successfully.というメッセージが表示されれば成功です。
sqlite3でdatabase/database.sqliteを開いて、テーブルが作成されているか確認してください。

sqlite3 database/database.sqlite
SQLite version 3.28.0 2019-04-15 14:49:49
Enter ".help" for usage hints.
sqlite> .table
migrations       password_resets  users          

ここまでの動作確認

以下のコマンドでテスト用サーバを起動します。

php artisan serve

アカウント登録

http://127.0.0.1:8000/registerを開いて、アカウント登録画面が表示されることを確認してください。

image.png

アカウントを登録したら、Dashboardというページが表示されます。
右上のユーザアカウント名のセレクトボックスからLogoutを選択してログアウトしてみてください、

image.png

ログイン

http://127.0.0.1:8000/loginを開いて、ログイン画面が表示されることを確認してください。

image.png

先ほど作成したユーザ情報でログインできることを確認してください。
※パスワードのリセット機能は、サーバからメールを送信する機能を実装しないと動作しません

ここまでで、Laravelにログイン認証機能を追加する対応は完了です。

ルートの保護を行う

この時点では、まだユーザの登録・ログインができるだけなので、どのビューに対してもログインによる保護がかかっていない状態(ログインしていなくてもアクセスできてしまう状態)です。
そのため、ルートの保護を設定してログインしていないと見れないページを作成してみます。

確認用のテストページを追加

ビューファイルを作成します。

touch /resources/views/test.blade.php

以下のような内容で保存しておきます。

test.blade.php
<h1>テストページ</h1>                                                                                              
<p>このページはログインしているユーザにしか見せたくない。。。</p>

テストページへのルーティングを設定

web.phpを開きます。

vi /routes/web.php

テストページへのルーティングを設定します。

web.php
<?php                                                                                                              

/*
|--------------------------------------------------------------------------
| 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('/test', function() {  // 追加
    return view('test'); // 追加
}); // 追加

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

動作確認

http://127.0.0.1:8000/testへアクセスしてみます。

image.png

まだ保護していないので、ログインしていないのにページが見えちゃいますね。。。

ルートの保護を行う

web.phpを再度開きます。

vi /routes/web.php

以下の設定を追加します。これがルートの保護に関する設定です。
たったこれだけでログインしていないとアクセスできないルーティングになります。

web.php
<?php                                                                                                              

/*
|--------------------------------------------------------------------------
| 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('/test', function() {
    return view('test');
})->middleware('auth'); // 修正

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');

改めて動作確認

http://127.0.0.1:8000/testへアクセスしてみます。

image.png

ルートの保護がされているビューをログインしていない状態で表示しようとすると、ログインページへリダイレクトされます。
続けてログインすると、もともと見ようとしていたビューを表示してくれます。

image.png

まとめ

10分でLaravelプロジェクトにログイン認証機能を追加できましたでしょうか?
慣れれば10分と言わず、3分もかからずに追加できるほど簡単ですね。

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

dockerでdocker-compose up -dができない

困りごと

macos 2020 にて、
どこかしらのディレクトリでサーバーに接続したいとき、
dockerは起動しているのに、ターミナルで、

docker-compose up -d

としても、エラーが出てしまいます↓

ERROR:
Can't find a suitable configuration file in this directory or any
parent. Are you in the right directory?
Supported filenames: docker-compose.yml, docker-compose.yaml
E41F52C2-788C-4ED3-B6C5-019E45F957C2_4_5005_c.jpeg

解決

どこかしら別のディレクトリでdocker-compose up -dを起動したままだった為でした。
そのディレクトリにて停止させます。ターミナルで、

docker-compose stop

これで一旦落着!

おわり。

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

【スギちゃん風】カスタム投稿タイプの個別投稿ページにはこうやってコメントをつけるんだぜぇ〜

背景

カスタム投稿タイプの個別投稿ページにコメント機能をつけたいと思ったのですが、
普通の投稿タイプと同様のやり方では表示されない。

そんな悩みを抱えている方のための備忘録になります。

まずコメント機能どうやってつくるの??

comments.phpを作ります

<?php if( comments_open() ){ ?>  //現在の投稿に対してコメントが許可されいるかの条件分岐
    <div id="comments">
        <?php if( have_comments() ){ ?>  //コメントがある場合ループを開始する
        <ul id="comments-list">
            <?php wp_list_comments(); ?>  //コメントをリストで表示する
        </ul>
        <?php } ?>
        <?php comment_form(); ?>   //コメントフォームを表示する
    </div>
<?php } ?>

表示したい部分に次を記述

<?php comments_template(); ?>

これで簡単なコメント機能は完成です。

カスタム投稿タイプでコメントをつける

functions.php にあるカスタム投稿タイプの関数内に以下の内容を盛り込む

function create_post_type() {
  #省略
  'supports' => array(
    'title',
    'editor',
    'excerpt',
    'thumbnail',
    'custom-field',
    'comments',  #カスタム投稿タイプでコメントを表示指定
  ),
  #省略
}
add_action( 'init', 'create_post_type', 1);

WPの管理画面を設定

設定 < ディスカッション < 新しいコメントを許可にチェック
個別記事 < 編集 < コメントのプルダウン「ーー変更なしーー」から「許可する」に変更

以上

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

Mcryptについて

Mcryptとは

・元々McryptはUnix cryptの代替コマンドで、エニグマ暗号に近いアルゴリズムを使用した暗号化ツール
・目的はパスワード・個人情報・顧客情報などの暗号化・復号化

非推奨の理由

・10年近く更新されていない拡張モジュールのため。

対処法

・Mcryptを使い続ける
・OpenSSLに移行する

OpenSSLとは

・暗号化通信プロトコル
・OpenSSL関数にもデータの暗号化・復号化を行う関数が用意されている。
 またOpenSSL関数では秘密鍵・公開鍵によるデータの暗号化・復号化をより手軽に扱うことができる。

OpenSSLに変更する場合

・事前に openssl_get_cipher_methods() を使って利用可能な暗号化方式を確認

var_dump(openssl_get_cipher_methods());

OpenSSLに変更する場合の参考になる記事

https://qiita.com/Uchikoba/items/7784e1f1eb7bae3b1593

参考

https://agency-star.co.jp/column/php--with-mcrypt/
https://tech.mktime.com/entry/451
https://qiita.com/Uchikoba/items/7784e1f1eb7bae3b1593

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

Moodle 3.9 マニュアル - カテゴリ:FAQ

原文

よくある質問 (FAQ) およびその回答は、moodle.orgのフォーラムからドキュメントに転送されます。あなたの質問が以下のFAQページで回答されているかどうかを確認してください。

あなたの質問に対する答えが見つからない場合は、Moodle.orgのGoogle検索および/またはMoodle in English高度なフォーラム検索をお試しください。

カテゴリ「FAQ」のページ

全85ページのうち、次の85ページがこのカテゴリになります。

アップグレードFAQ

インストールFAQ

コースFAQ


プラグインFAQ

A

About Moodle FAQ
Accounts FAQ
Activity completion FAQ
Administration FAQ
Assignment FAQ
Authentication FAQ

B

Backup and restore FAQ
Badges FAQ
Beginning Moodle 2.0 Administration
Beginning Moodle 2.x Administration 2 FAQ
Blocks FAQ
Blogs FAQ
Book FAQ

C

Calendar FAQ
Certificate FAQ
Chat FAQ
Choice FAQ
Cohorts FAQ
Course completion FAQ
Course FAQ (日本語訳:コースFAQ)

D

Database activity FAQ
Dataform FAQ
Decision FAQ
Development:Developer FAQ

E

Enrolment FAQ
Errors FAQ
External tool FAQ

F

Feedback FAQ
File upload size
File picker FAQ
File resource FAQ
File system repository FAQ
Filters FAQ
Folder resource FAQ
Forum FAQ
Front page FAQ

G

Game FAQ
GDPR FAQ
Glossary FAQ
Grades FAQ
Groupings FAQ
Groups FAQ

H

H5P FAQ
Hotpot module FAQ

I

Import and export FAQ
IMS content package FAQ
Installation FAQ (日本語訳:インストールFAQ)

L

Label FAQ
Language FAQ
Lesson FAQ

M

Mathematics tools FAQ
Media FAQ
Messaging FAQ
MNet FAQ
Moodle app FAQ
Moodle documentation FAQ
Moodle Learning Analytics FAQ
Moodle version
Multimedia plugins FAQ

N

Development:NEWMODULE FAQ

P

Page FAQ
Performance FAQ
Plagiarism prevention FAQ
Plugins FAQ (日本語訳:プラグインFAQ)

Q

Questions FAQ
Quiz FAQ

R

Repositories FAQ
Resources FAQ
Restrict access FAQ
Roles FAQ
RSS feeds FAQ

S

SCORM FAQ
Security FAQ
Sessions FAQ
Student FAQ
Sunsetting moodle.net
Survey FAQ

T

Text editor FAQ
Themes FAQ

U

Upgrading FAQ (日本語訳:アップグレードFAQ)
URL resource FAQ

W

Web services FAQ
Wiki FAQ
Workshop FAQ

X

Xampp Installer FAQ

メインページ

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

【PHP】php.ini Security Deep Dive

PHPerの皆さんはphp.iniをちゃんと設定していますか?
全てデフォルト値を使用しているなんてことありませんよね? (煽り

セキュリティの観点から設定した方がいいパラメータの設定値を可能な限り説明を交えつつ紹介していきたいと思います :muscle:

前提

php.ini

php.iniで設定可能な全パラメータは公式ドキュメントPHP-7.3/php.ini-productionを参照ください
では、セキュリティの観点から設定した方がいいパラメータについて説明していきます

open_basedir

説明

PHPによってアクセス可能なディレクトリを制限します
デフォルトでは全てのディレクトリにアクセス可能です
directory traversalなどの攻撃を防御するために必ず設定をしておきましょう

基本的には/var/www/htmlを指定するだけで十分なケースが多いですが、:を区切り文字として複数のディレクトリを指定可能です

DeepDive

open_basedirの実装を追ってみましょう

plantuml (1).png

以下はphp_check_open_basedir_exのコアな処理を抜粋したコードです
https://github.com/php/php-src/blob/PHP-7.3/main/fopen_wrappers.c#L300-L319

php_check_open_basedir_ex
while (ptr && *ptr) {
    end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
    if (end != NULL) {
        *end = '\0';
        end++;
    }

    if (php_check_specific_open_basedir(ptr, path) == 0) {
        efree(pathbuf);
        return 0;
    }

    ptr = end;
}
if (warn) {
    php_error_docref(NULL, E_WARNING, "open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s)", path, PG(open_basedir));
}
efree(pathbuf);
errno = EPERM; /* we deny permission to open it */
return -1;

DEFAULT_DIR_SEPARATORは:として定義されています

php_check_specific_open_basedirの返り値が0 ( = open_basedirで許可されている)か、strchr(ptr, DEFAULT_DIR_SEPARATOR)の返り値がNULL ( = open_basedirの設定値による探査終了) になるまでループします

if (warn)ではphp_check_open_basedirから呼び出される時に第2引数warnに1を指定しているので、open_basedirに指定されていないディレクトリを呼び出そうとするとphp_error_docrefによって警告が出力されます
警告用の引数を渡しておいて、その条件分岐前にreturnするかどうかで警告出すかどうかを決めるのはいい実装方法ですよね
内部で警告出すフラグをゴニョゴニョする必要がなく、すっきりしている印象を抱きます


php_check_specific_open_basedirはsymlinkにも対応しているので、ファイル本体がopen_basedir外であればエラーになります
以下がsymlinkの処理を行っているコードです
https://github.com/php/php-src/blob/PHP-7.3/main/fopen_wrappers.c#L167-L181

php_check_specific_open_basedir
#if defined(PHP_WIN32) || defined(HAVE_SYMLINK)
        if (nesting_level == 0) {
            ssize_t ret;
            char buf[MAXPATHLEN];

            ret = php_sys_readlink(path_tmp, buf, MAXPATHLEN - 1);
            if (ret == -1) {
                /* not a broken symlink, move along.. */
            } else {
                /* put the real path into the path buffer */
                memcpy(path_tmp, buf, ret);
                path_tmp[ret] = '\0';
            }
        }
#endif

余談

ちなみにopen_basedirを設定するとrealpath cacheは使用できなくなるので注意が必要です
realpath cacheの設定をしていて、「あれ?」とならないようにしましょう
タイプは違えどopcacheは利用できます
open_basedirを設定している場合にrealpath cacheを無効にしているコードは以下になります
https://github.com/php/php-src/blob/PHP-7.3/main/main.c#L1802-L1805

/* Disable realpath cache if an open_basedir is set */
if (PG(open_basedir) && *PG(open_basedir)) {
  CWDG(realpath_cache_size_limit) = 0;
}

realpath_cache_size_limitを0に設定して無効化しています
シンプルで美しい :sparkles: (ただ言いたかっただけw

disable_functions

説明

実行禁止する関数を設定できます
一般的なアプリケーションはファイルシステム・OSユーザなどをいじることはないと思うので、これらの変更が可能な関数は禁止しておきましょう
disable_fuctionsを設定するTipsとして、最初は厳し目に設定しておいてテストなどを通じて実行が必要な関数を設定から削除していくのがいいでしょう
自身で書いたコード以外にも使用しているライブラリやフレームワークなどにも影響が出るので注意が必要です

(1行だと見にくいと思うのでリスト化していますが、php.iniに書く際は,を区切り文字として1行で書きます)

設定した方がいい関数例
- system
- exec
- shell_exec
- passthru
- phpinfo (開発時は許可してもよい)
- show_source,
- highlight_file
- popen
- fopen_with_path
- dbmopen
- dbase_open
- putenv
- move_uploaded_file
- chdir
- mkdir
- rmdir
- chmod
- rename
- filepro
- filepro_rowcount
- filepro_retrieve
- posix_* (prefixがposixである関数)

DeepDive

disable_functionsの実装を追っていきましょう

plantuml (3).png

disable_functionsはphp_module_startup、つまり起動時に読み込まれます
なので、PHPスクリプトで上書きすることはできません

PHPの関数はfunction_tableというハッシュテーブルで管理されています
disable_functionsで指定されて関数はfunction_tableから削除されるわけではなく、関数のハンドラーにdisplay_disabled_functionというエラーハンドラー(zend_error)をラップした関数をセットします
display_disabled_functionはエラーを発生させて、セキュリティの設定上関数が無効化されているメッセージを出力します
以下は関数を無効化するzend_disable_functionのコードです
https://github.com/php/php-src/blob/PHP-7.3/Zend/zend_API.c#L2847-L2859

zend_disable_function
ZEND_API int zend_disable_function(char *function_name, size_t function_name_length) /* {{{ */
{
    zend_internal_function *func;
    if ((func = zend_hash_str_find_ptr(CG(function_table), function_name, function_name_length))) {
      func->fn_flags &= ~(ZEND_ACC_VARIADIC | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_HAS_RETURN_TYPE);
        func->num_args = 0;
        func->arg_info = NULL;
        func->handler = ZEND_FN(display_disabled_function);
        return SUCCESS;
    }
    return FAILURE;
}
/* }}} */

zend_hash_str_find_ptrによってfunction_tableから無効化したい関数を探査します
そして、該当の関数が存在すれば無効化します

expose_php

説明

expose_phpをOffにすると、PHPで処理していることやバージョンをHTTP Headerに含めないようにできます
プロダクションでは必ずOffにすべきパラメータです

DeepDive

plantuml (5).png

HTTP Headerにセットする内容は以下のように定義されています
https://github.com/php/php-src/blob/PHP-7.3/main/SAPI.h#L289

SAPI.h
#define SAPI_PHP_VERSION_HEADER     "X-Powered-By: PHP/" PHP_VERSION

display_errors

説明

実行時のPHPエラーをHTMLの一部として画面に出力するかどうかを設定します
開発時には役に立ちますが、内部事情がバレてしまうのでプロダクションではOffにしましょう

DeepDive

エラーハンドラーのセットアップ

plantuml (7).png

エラーハンドラーの呼び出し

plantuml (8).png

html_errors

説明

display_errorsかlog_errorsが有効な場合に、HTMLタグをエラーメッセージ内に含めることができます
上記の2つのパラメータが無効な場合、html_errorsを有効にしていてもHTMLタグを含んだエラーメッセージは出力されません
こちらのパラメータもプロダクションではOffにしておきましょう

DeepDive

php_error_cb、php_verrorやphp_error_docref内の条件分岐のパラメータとして使用されます

HTMLタグを含めるかどうかのシンプルな条件分岐で使われている例
https://github.com/php/php-src/blob/PHP-7.3/main/main.c#L1338-L1358

php_error_cb
if (PG(html_errors)) {
    if (type == E_ERROR || type == E_PARSE) {
        zend_string *buf = php_escape_html_entities((unsigned char*)buffer, buffer_len, 0, ENT_COMPAT, get_safe_charset_hint());
        php_printf("%s<br />\n<b>%s</b>:  %s in <b>%s</b> on line <b>%" PRIu32 "</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, ZSTR_VAL(buf), error_filename, error_lineno, STR_PRINT(append_string));
        zend_string_free(buf);
    } else {
        php_printf("%s<br />\n<b>%s</b>:  %s in <b>%s</b> on line <b>%" PRIu32 "</b><br />\n%s", STR_PRINT(prepend_string), error_type_str, buffer, error_filename, error_lineno, STR_PRINT(append_string));
    }
} else {
    /* Write CLI/CGI errors to stderr if display_errors = "stderr" */
    if ((!strcmp(sapi_module.name, "cli") || !strcmp(sapi_module.name, "cgi") || !strcmp(sapi_module.name, "phpdbg")) &&
        PG(display_errors) == PHP_DISPLAY_ERRORS_STDERR
    ) {
        fprintf(stderr, "%s: %s in %s on line %" PRIu32 "\n", error_type_str, buffer, error_filename, error_lineno);
#ifdef PHP_WIN32
        fflush(stderr);
#endif
    } else {
        php_printf("%s\n%s: %s in %s on line %" PRIu32 "\n%s", STR_PRINT(prepend_string), error_type_str, buffer, error_filename, error_lineno, STR_PRINT(append_string));
    }
}

allow_url_fopen

説明

外部のリソース(URL)をファイルオブジェクトのように扱います
fopenのラッパーであるfile_get_contentsなどによってURLにアクセス可能になるので、任意のスクリプトをアプリケーションに挿入できてしまいます
悪意ある外部のスクリプトによってインジェクションされないように、allow_url_fopenは必ず無効化しましょう

DeepDive

plantuml (9).png

実際にallow_url_fopenによってURLにアクセス可能か条件分岐しているコード
https://github.com/php/php-src/blob/PHP-7.3/main/streams/streams.c#L1850-L1866

php_stream_locate_url_wrapper
if (wrapper && wrapper->is_url &&
            (options & STREAM_DISABLE_URL_PROTECTION) == 0 &&
        (!PG(allow_url_fopen) ||
            (((options & STREAM_OPEN_FOR_INCLUDE) ||
                PG(in_user_include)) && !PG(allow_url_include)))) {
    if (options & REPORT_ERRORS) {
        /* protocol[n] probably isn't '\0' */
        if (!PG(allow_url_fopen)) {
            php_error_docref(NULL, E_WARNING, "%.*s:// wrapper is disabled in the server configuration by allow_url_fopen=0", (int)n, protocol);
        } else {
            php_error_docref(NULL, E_WARNING, "%.*s:// wrapper is disabled in the server configuration by allow_url_include=0", (int)n, protocol);
        }
    }
    return NULL;
}

return wrapper;

allow_url_include

説明

includeやrequireでURL(file://、http://)をオープンするかを制御する
外部リソースの状態は不明な場合が多く不確実性があるので、allow_url_includeは無効化しましょう
信頼できる外部リソースでもURL経由ではなく、ダウンロードして内部に保存し、検証して安全性を確保された状態のものを使用しましょう

終わりに

公式ドキュメントとソースコードを追いながら、実際にパラメータを設定するとどうなるのってところまで深堀してみました
基本的なパラメータしか深掘りできていないので、sessoin周りとかもいずれはDeep Diveしていきたいですね

Reference

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

PHP:ビルトイン関数array_unique()を自作してみた

やりたいこと

ジャズライブの口コミをタグ付きで投稿できるサイトを、チームで開発しています。
タグが送信された時に、配列の中に2つ以上同じ文字列があったら、前者だけを残して他を削除し、配列内の値が全てユニークである状態を作るプログラムを作りたくルンルン楽しく試行錯誤していたら、array_unique()というPHPの便利なビルトイン関数があることを知り、便利と思いつつちょっと萎えました。なら無駄に自作してみっか!と思い作ってみました。

YouTube万屋エンジニアチャンネルのコミュニティーで大いに助けていただきました。大感謝!

やってみた

試行錯誤しましたが、下記でarray_unique()と同じ結果が得られます。

<?php

$tags = ['jazz', 'onuma', 'fusion', 'jazz', 'fusion', 'fusion', 'tokyo'];

$unique_tags = array(); //(1)unique_tagsを配列にする

foreach ($tags as $key=>$val) { //(2)後述
  $unique_tags[$val] = true;
}
$unique_tags = array_keys($unique_tags); //(3)配列のkeyを返す

print_r($unique_tags);

//出力↓
Array
(
    [0] => jazz
    [1] => onuma
    [2] => fusion
    [3] => tokyo
)

(1)は結構誰でもわかると思います。
(2)は初心者の私にはトリッキーでしたが、
  a. まずforeachで配列$tagsをキーを$key、値を$valと名前を付けて一つずつ処理すると()内で宣言。
  b. (1)で配列化した$unique_tagsのキーに$tagsの値の方を渡し、連想配列化し、その値には定数trueを代入。連想配列とは、キーを数字ではなく文字列にして管理する配列。
  c. キーの重複は不可能なので、自然とbの時点で、重複するtagsの値は弾かれる。
  d. この時点で$unique_tagsは下記のようになっています。

Array
(
    [jazz] => 1
    [onuma] => 1
    [fusion] => 1
    [tokyo] => 1
)

(3)array_keysで配列のキーを配列で返します。

最後に

ご指摘や他のやり方を知ってるという方いましたら、ぜひコメントにてよろしくお願い申し上げます、

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