- 投稿日:2020-11-04T23:45:45+09:00
mac OSにPHP(MAMP)を設定する
以下のリンクをクリック
https://www.mamp.info/en/downloads/
赤枠で囲っている部分をクリック
手順に沿ってインストールを実行します。
Applications/MAMP/conf/my.cnfにmysqlの設定をする。
MAMPを開いてStart Serverを押す
もしMySQLが 5.6以上になっていて、そのままではこの先進めない場合は、以下のように設定する
my.cnf[mysqld] sql_mode=NO_ENGINE_SUBSTITUTION
- 投稿日:2020-11-04T23:19:12+09:00
Lumenでファサードのエイリアスを登録する
はじめに
Laravelをベースとした軽量フレームワークであるLumen。
軽くて速いため、小さなサービスなどで利用されることもありますが、
Laravelと同等の機能を使うには独自の設定が必要となります。今回はLumenでファサード機能を実装する際の、
エイリアスの設定方法を記します。※Lumenでのファサード実装の流れはまた後日記事を書こうと思います。
エイリアスの登録
Facadeクラスは
app/Facades/Hoge.php
に作成されているとします。
bootstrap/app.php
に、以下のコードを追記します。bootstrap/app.php$app->withFacades(true, [ App\Facades\Hoge::class => 'Hoge', ]);これにより、どこからでも
\Hoge::method();
のようにしてHoge
のmethod()
を呼び出すことができます。
use App\Facades\Hoge;
と名前空間を記述しなくてもいいのは楽ですね。
- 投稿日:2020-11-04T22:38:30+09:00
PHPで敷居の高い掲示板を作ってみた ~概要編~
はじめに
どうもお久しぶりです。9月はげろが出るほど忙しく、10月はそこそこに忙しくて、記事が投稿できなかったです。今回はバイトで作っている成果物(?)っぽい物について、どんなもの?とか、どうやって作った?とかについて書いていきます。
動機としては、自分の中の整理と、再来年以降の引継ぎの為に書きます。また、学生の書いている事(プロじゃない)なので、完ぺきなアプリケーションではないですし、セキュリティ的にも完全ではありません。なので、ガチガチのプロ向けの記事じゃないです。PHPとHTMLが何となく分かっていて、「何かつくりたいなぁ~」と思っている人向けです。
また、今回は概要編なので、ざっくりアプリの全体像を書いていこうと思います。
※もし参考にする場合は自己責任でお願いします。この記事の目的
- PHPを用いた新たな(?)掲示板の提案(事前調査とかはしてないです。もしかしたら既にあるかも)
- 自分の学習・作成過程の記録。
「敷居の高い掲示板」で目指した事
今回の「敷居の高い掲示板」では、何を目指して作ったのかというと、
- 学生の本の感想を集めたい
- 2ch的な気軽さ
- 投稿・閲覧は精査して行いたい
- アカウント作るとか面倒
といった要望を満たすことを目指していました。つまり、本の感想を気軽に投稿できるサイトでありつつ、投稿や閲覧にはある程度の精査を行いたい。という事です。アナログな例えで言うと、
「本の感想を、図書館カウンターで集めて、その中で良い物を掲示する」
ですね。これをサイトでやろうって訳です。
必要知識
「とにかく早く作ろう」と、ゼロからの学習をしながら作ったので、必要最低限の知識です。以下の項目は理解できないと、実際に作れるまでにならないと思います。
- Apache + sendmail (過去に書いた記事を参考)
- Apacheの設定ファイルがいじれる
- PHP(関数が書ける程度)
- HTTP(GET・POST・COOKIE・SESSION)※
- HTML(特にフォームの作り方)
※以下の記事を勉強させていただきました。
・[PHP] リクエストパラメータ・セッションに関するまとめ
・【PHP超入門】HTTP(GET・POST)について開発環境
開発に用いた言語やツールは以下の通りです。開発環境はWindows8.1で、Xamppでサーバーを立ち上げていました。
- git&github
- PHP7ぐらい
- HTML
Webアプリケーションの概要
アプリケーション名:「ひとことすいせん」
学生・教授どうしで、図書館の本の感想を言い合う掲示板です。主な機能
ユーザ関連
- 記事の投稿(アカウント登録なし、メールで認証)
- 投稿した内容の編集
- 閲覧(一部)
管理者側
- 投稿内容の一覧(全て)
- 初期投稿時の公開状態の設定権(公開・非公開・承認待ち)
- 投稿された内容の公開状態の設定権(公開・非公開)
- 閲覧ページの設定権(公開・非公開)
各機能の詳細&デモ
記事を投稿する機能
記事が投稿されるまでの流れは、以下の図のようになっています。かいつまんで言うと、以下の3つのステップを踏んでいます。
- ユーザーが投稿画面で(自分の)メールアドレスを入力
- メールにtoken付のURLが送られる
- そのURLを踏んで投稿開始
- デモ
さっきの図の番号に対応する様子をスクショしました。
①ユーザーが投稿画面でメールアドレスを入力
②token付のURLが送られる(赤い塗りつぶしは、管理者用メールアドレスです)
③URLをクリックすると、投稿画面に行きます。そしてなんやかんや入力すると。。。
④プレビューが表示されて、
⑤入力内容が投稿されます。と同時に”コメントID”なるものを発行します。
⑥そして、URLが無効かされます。
記事を閲覧する機能
上記した感じで、ユーザーがテキストベースの内容を入力します。ということは、HTMLの入力フォームからサーバーへ入力情報が送信された、ってことですね。(POSTで送ってます)
しかし、その内容には個人情報が含まれます。例えば、学籍番号とか、氏名、所属するクラスとかですね。それらは公開したくないわけです。なので、↓図のようにapacheで公開されてない領域にすべての情報を保存します。今回は、テキストファイル形式すべての情報を保管するようにしました。
そうする事によって、入力された情報が守られるわけです。原理的には、apacheというサーバーソフトが仲介人となって、渡してよいファイル・非公開なファイルを判別しているわけです。
ちなみに、アクセス不可能な領域にアクセス(URLで指定)すると、こんな感じでエラーページが返ってきて、内容が確認できないようになっています。
という事なんですが、「それじゃ投稿した内容が見れないじゃないか!」ってツッコむと思うんですが、そこら辺の処理はPHPに任せています。図(↓)で表すとこんな感じですね、投稿内容が閲覧されるまでの手順としては、
1、ユーザーから閲覧ページ(PHP)が要求される。
2、PHPにより、サーバー内の”公開してもよい情報”のみを取り出す。
3、公開してもよい情報を、HTMLにしてユーザーに返す。てな感じです。
- デモ
そんなわけで、実際に閲覧ページに行くと、こんな感じで投稿内容が確認できます。サーバー上には個人情報がありますが、閲覧ページからのアクセスでは、それらの情報を取得することができないようになってます。
記事を編集する機能
ちらっと”コメントID”って言ってましたけど、これは、投稿内容につき1つ発行されるtokenの事です。これを知っているのは投稿した本人(と管理者)のみなので、これを使ってコメントの編集を行うようにします。
仕組みとしては↓のようになっていて、正しいコメントIDが入力されたら、対応するコメントの修正作業ができるって感じです。
- デモ
①正しいコメントIDを入力すると、
②対応するコメントが表れて、
③なんやかんや編集して、
③それをプレビューして、
④投稿内容を確認すると、編集がされているのがわかりますね。
記事を管理する機能
実装した機能の最後として、管理画面があります。説明に入る前に、コメントの状態について断っておきます。コメントの状態は「公開状態」・「非公開状態」・「承認待ち状態」の3つあるとします。公開状態ではコメントが閲覧可能で、非公開・承認待ち状態ではコメントの内容が見れないようになっています。
そして、管理画面では以下の事が可能となっています。
1、コメント投稿時(初期値)の状態を設定できる。
2、投稿済みのコメントの状態を変更できる。
3、各画面自体の公開・非公開が変更できる(メンテナンス等のため)。1と2の機能によって、コメントの内容が勝手に公開されない設定が可能になるのです。これで、このサイトの秩序が管理できるはず!という狙いです。例えば、初期状態を「承認待ち」にしておいて、管理者が投稿内容を確認して、問題なければ「公開状態」に変更する、みたいな事が可能になっています。
また、3については、サイトのメンテナンス時とかに、不用意にアクセスされないための設定ができます。いつでも変更できて、もし閲覧ページが非公開にされると、↓のようになります。
管理者ログイン方法
最後に、管理者の管理画面のログイン方法ですね。これに関しては、下のように2段階認証?的なことをしています。流れとしては、
1、管理ログイン画面にてusernameとpasswordを入力。
2、正解だったら、”管理者用メールアドレス”に管理ログイン画面(2回目)を表示。
3、管理ログイン画面(2回目)にて、再度usernameとpasswordを入力。となっています。ログインできる条件としては、”管理者用メールアドレスを持っている”ことと、”username&passwordを知っている”事になります。これによって、比較的安全にログインしよう!とのことです。また、管理ログイン画面(2回目)というのは、Token付きのURLの事で、1の時にTokenを発行して、メールに送られたURLのTokenと同じだったら2回目のログイン画面を表示する仕組みになっています。
おわりに
以上が、私の作った”敷居の高い掲示板”です。今回は概要なので、ざっくりとした設計の方針みたいなものをつらつらを書いてみました。今後は、これらの機能を具体的にどう実装するか?みたいな事を書いていけたらなと思います。
皆さんのPHPの創作意欲の足しになってくれたらうれしいです。それでは!
- 投稿日:2020-11-04T22:12:12+09:00
privateの想像と違う(?)動作のお話
初書:2020/11/4
php:7.4.10前書き
オブジェクトを使う際にほぼ間違いなく使うprivate。
今回は(個人的に)意外な性質を見つけたのでメモ。コード
先にコードを提示
class tes{ private int $a = 1232; private function fc():int{ return $this->a; } public function func(tes $val) : int { return $val->fc() + 158; } } $a = new tes(); $b = new tes(); var_dump($b->func($a));数字・関数名変数名は適当。
いや今気がついたけどこのコードだとfcの定義している意味が完全に無いじゃん。
まぁ支障はないので一旦放置。簡単にコードの説明をしておくと、private変数
$a
を用意しておき、fc
関数で取得可能。
またfunc
関数では、tesクラスのインスタンスを引数とし、fc
関数と158を足した値を戻す。
そして2つのインスタンスを生成し、片方のインスタンスを引数にもう片方のfunc
を呼ぶというもの。さて、上記コードを実行してみるとどうなるか。
php > var_dump($b->func($a)); int(1390)普通に実行できる。
何が言いたいのか
つまり、privateな関数や変数1であっても、同じクラス内から呼び出す分には別のインスタンスであっても呼び出すことが可能である。(初知り)
javascriptでも試してみる。
class tes{ #a = 1232; #fc(){ return this.#a; } func(val){ return val.#fc() + 158; } } a = new tes(); b = new tes(); console.log(b.func(a));(ちなみに
#
から始まるのをフラグメント演算子というらしいのだが、いつから実装されてるのか不明。2)さて、結果はどうなったのか。ちなみにページを用意するのが面倒だったので、コンソールに投げて実行した。
safari
ver 14.0
SyntaxError: Invalid character: '#'そもそもフラグメント演算子に対応していない
chrome
ver 86.0
1390phpと同様の結果に。
Firefox
ver 82.0
Uncaught SyntaxError: private fields are not currently supported認識はするものの対応自体はしていない模様
結果
phpと同じと認識してもいいと思われる
C#でも試す。
C#というよりunity。
using UnityEngine; public class test2 : MonoBehaviour{ void Start(){ var a = new tes(); var b = new tes(); print(b.func(a)); } } class tes{ private int a = 1232; private int fc(){ return a; } public int func(tes val){ return val.fc() + 158; } }普通に1390と出た。
結論
もしかして単純に無知を晒した投稿なのでは?(今更。でも書いてしまった)
「privateは1カプセル毎に個別で持つもの、外部からは一切アクセスできない」という認識があったので少し意外な処理だった。
- 投稿日:2020-11-04T21:06:19+09:00
Moodle 3.9 マニュアル - カテゴリ:コンピテンシー
カテゴリ:コンピテンシー
Moodleのコンピテンシー機能に関するページのリストです。
カテゴリー「コンピテンシー」のページ全44ページのうち、このカテゴリには以下のページがあります。
こ
C
Capabilities/block/lp:addinstance
Capabilities/block/lp:myaddinstance
Capabilities/moodle/competency:competencygrade
Capabilities/moodle/competency:competencymanage
Capabilities/moodle/competency:competencyview
Capabilities/moodle/competency:coursecompetencyconfigure
Capabilities/moodle/competency:coursecompetencygradable
Capabilities/moodle/competency:coursecompetencymanage
Capabilities/moodle/competency:coursecompetencyview
Capabilities/moodle/competency:evidencedelete
Capabilities/moodle/competency:plancomment
Capabilities/moodle/competency:plancommentown
Capabilities/moodle/competency:planmanage
Capabilities/moodle/competency:planmanagedraft
Capabilities/moodle/competency:planmanageown
Capabilities/moodle/competency:planmanageowndraft
Capabilities/moodle/competency:planrequestreview
Capabilities/moodle/competency:planrequestreviewown
Capabilities/moodle/competency:planreview
Capabilities/moodle/competency:planview
Capabilities/moodle/competency:planviewdraft
Capabilities/moodle/competency:planviewown
Capabilities/moodle/competency:planviewowndraft
Capabilities/moodle/competency:templatemanage
Capabilities/moodle/competency:templateview
Capabilities/moodle/competency:usercompetencycomment
Capabilities/moodle/competency:usercompetencycommentown
Capabilities/moodle/competency:usercompetencyrequestreview
Capabilities/moodle/competency:usercompetencyrequestreviewown
Capabilities/moodle/competency:usercompetencyreview
Capabilities/moodle/competency:usercompetencyview
Capabilities/moodle/competency:userevidencemanage
Capabilities/moodle/competency:userevidencemanageown
Capabilities/moodle/competency:userevidenceview
Capabilities/tool/lpmigrate:frameworksmigrate
Competencies (日本語訳:コンピテンシー)
Competencies FAQ
Competency breakdown report
Competency frameworks
Competency reviewerL
Learning plan supervisor
Learning plan viewer
Learning plans
Learning plans block
- 投稿日:2020-11-04T20:44:41+09:00
Moodle 3.9 マニュアル - ロールとパーミッション
ロールとパーミッション
ロールは、特定のコンテキストで特定のユーザーに割り当てることができるシステム全体のために定義された権限のコレクションです。ロールとコンテキストの組み合わせは、特定のユーザーがどのページで何かをする能力を定義します。最も一般的な例は、コースのコンテキストにおける学生と教師のロールです。
・ロールの管理:(翻訳準備中)
・ロールの割り当て:(翻訳準備中)
・ユーザーポリシー:(翻訳準備中)
・ロールの使用:(翻訳準備中)
・標準的なロール:(翻訳準備中)
・カスタムロールの作成:(翻訳準備中)
・ロールのエクスポートとインポート:(翻訳準備中)
・パーミッション:(翻訳準備中)
・パーミッションを上書きする:(翻訳準備中)関連項目
- 投稿日:2020-11-04T20:27:35+09:00
無料天気予報OpenWeatherMap APIの使い方
OpenWeatherMap とは
OpenWeatherMapは、現在の天気や天気予報などの無料APIを提供するオンラインサービスです。
APIキーを取得する
アカウント登録
OpenWeatherMapにアクセスしてサインアップします。APIキーを取得
ログイン後のメニューに表示されているAPI Keysを選択すると、APIキーが表示されています。
OpenWeatherMapのAPIを叩く
https://api.openweathermap.org/data/2.5/onecall?lat={LAT}&lon={LON}&units=metric&lang=ja&appid={YOUR API KEY}レスポンス内容の例)
json.js{ "lat": 000000, "lon": 000000, "timezone": "Asia/Tokyo", "timezone_offset": 000000, "current": { ...(略)... }, "hourly": [ { ...(略)... }, ...(略)... { ...(略)... } ], "daily": [ { ...(略)... }, ...(略)... { ...(略)... } ] }主に使う値
- 時刻: dt
- 温度: temp
- 体感温度: feels_like
- 気圧: pressure
- 湿度: humidity
- UV指数: uvi
- 風速: wind_speed
- 気象情報: weather.main
- 気象情報の詳細: weather.description
- 気象情報のアイコンID: weather.icon
- 降水量: rain.1h
- 積雪量: snow.1h
画像アイコン
10n
の部分を変更するだけ
https://openweathermap.org/weather-conditions<img src="https://openweathermap.org/img/wn/10n@2x.png">PHPで取得
$weather_config = array( 'appid' => '○○○○○○○○○○○○○○○', 'lat' => '63.027139', 'lon' => '-150.941425', ); $weather_json = file_get_contents('http://api.openweathermap.org/data/2.5/weather?lat=' . $weather_config['lat'] . '&lon=' . $weather_config['lon'] . '&units=metric&lang=ja&APPID=' . $weather_config['appid']); $weather_array = json_decode($weather_json, true);weather.mainは英語しかないので日本語訳はこちらを使ってください。
$weatherTranslate = array( 'Clear' => '晴れ', 'Clouds' => 'くもり', 'Rain' => '雨', 'Drizzle' => '霧雨', 'Thunderstorm' => '雷雨', 'Snow' => '雪' );パラメーターオプション
オフィシャルリファレンス
https://openweathermap.org/current単位
測定単位。standard、metricおよびimperialユニットが利用可能です。unitsパラメータを使用しない場合、standardデフォルトで単位が適用されます。
「units=metric」で摂氏温度(℃)の取得ができます。
これがないと絶対温度(K)になるので、取得した数値から「-273.15」する必要があります。
standard
metric
imperial
units=○○○○モード
レスポンス形式。可能な値はxmlとhtml。modeパラメータ形式を使用しない場合、デフォルトではJSONです。
json
xml
html
mode=○○○○多言語
このパラメーターを使用して、ご使用の言語で出力を取得できます。
af
アフリカーンス語al
アルバニア語ar
アラビア語az
アゼルバイジャンbg
ブルガリア語ca
カタロニア語cz
チェコ語da
デンマーク語de
ドイツ人el
ギリシャ語en
英語eu
バスクfa
ペルシア語(ペルシア語)fi
フィンランド語fr
フランス語gl
ガリシア語he
ヘブライ語hi
ヒンディー語hr
クロアチア語hu
ハンガリー語id
インドネシア語it
イタリアのja
日本人kr
韓国語la
ラトビア語lt
リトアニア語mk
マケドニアのno
ノルウェー語nl
オランダのpl
研磨pt
ポルトガル語pt_br
ポルトガル語ブラジルro
ルーマニア語ru
ロシアsv, se
スウェーデンのsk
スロバキアsl
スロベニア語sp, es
スペイン語sr
セルビア語th
タイ語tr
トルコ語ua, uk
ウクライナ語vi
ベトナム語zh_cn
中国語(簡体字zh_tw
中国の伝統的なzu
ズールーJavaScriptコードのコールバック関数
JavaScriptコードを使用するには、
callback
functionNameをJSONPコールバックに転送できます。https://api.openweathermap.org/data/2.5/weather?q=London,uk&callback=test&appid={API key}参考サイト
https://qiita.com/nownabe/items/aeac1ce0977be963a740
https://hsmt-web.com/blog/openweathermap-api/
https://dev.classmethod.jp/articles/use-open-weather-map/
https://yuukiyg.hatenablog.jp/entry/2019/11/17/182410
- 投稿日:2020-11-04T20:10:54+09:00
Laravel:Auth認証の設定
【概要】
1.手順
3.開発環境
1.手順
備忘録も兼ねてアウトプットしておきます。
❶Node.jsをダウンロード
❷laravel/ui
をインストール
❸Auth関連ファイルの生成
❹作成されたusersをマイグレーション
❺Controllerにコーディング2.どのようにコーディングするか
❶Node.jsをダウンロード
ここからNode.jsをインストールします。❷
laravel/ui
をインストール
ターミナルで下記を記述してインストールします。$ composer require laravel/ui❸Auth関連ファイルの生成
同じくターミナルで下記を記述して実行します。$ php artisan ui vue --auth $ npm install && npm run devすると
user.php
とusers
テーブルが作成されます。❹作成されたusersをマイグレーション
下記の通りマイグレーションを実行します。$ php artisan migrateするとDBにuserテーブルが作成されます。
❺Controllerにコーディング
use Illuminate\Support\Facades\Auth;
$user = Auth::user();
を記述して完了です。app/Http/Controllers/xxxxController.phpuse Illuminate\Support\Facades\Auth; public function index(Request $requsest) { $user = Auth::user(); return view('xxx.index'); //(i) }(i)は、
$param = []
を記述している際はreturn view('xxx.index', $param);
と記述してデータを渡してください。以上のことをすると、
localhost:8000/register
,localhost:8000/login
で新規登録機能・ログイン機能を実装できます。3.開発環境
PHP 7.4.10
Laravel 8.9
Apache 2.4.41
Mysql 5.6.47
Sequl Pro 1.1.2
- 投稿日:2020-11-04T17:37:21+09:00
Moodle 3.9 マニュアル - マネージャーのロール
マネージャーのロール
目次
1 マネージャーロールの能力
2 サイトレベルでのマネージャーのロールの割り当て
3 カテゴリーレベルでのマネージャーのロールの割り当て
4 関連項目1 マネージャーロールの能力
デフォルトの管理者ロールは、ロールに割り当てられたユーザーがコースにアクセスしてコースを変更するだけでなく、コース、ユーザー、グレード設定などに関連する管理レベルのタスクを実行することを可能にします。
管理者の役割とは異なり、マネージャーの役割は、あなたが編集することができますが、その機能は、その広いデフォルトの権限のために、管理者に似ています(しかし、はるかに安全に使用することができます) '本当の役割'です。通常の役割として、コース作成者や教師のように、マネージャーの役割は、デフォルトではほとんど非常に多くの機能を持っていますが、あなたが選択した場合は、その役割を編集することができます。
(Moodleコードでパーミッションチェックが機能する方法は、has_capabilityと呼ばれる関数があります。管理者にとって、ロールがどのように設定されているかにかかわらず、has_capabilityは常にtrueを返します。したがって、管理者がどのようなパーミッションを持っているかを編集する方法はありません。)
最小特権の原則に基づくベストプラクティスを採用することは、管理者は通常、管理者アカウントを使用せず、マネージャーアカウントを使用すべきであることを示唆しています。
したがって、管理者の役割は、サイト管理者が管理者の役割を割り当てられた他の人に非常に強力な役割を与えることを可能にしますが、完全な管理者の役割を与える必要はありません。
2 サイトレベルでのマネージャのロールの割り当て
サイト管理] > [ユーザー] > [権限] > [システムロールの割り当て] に進み、[マネージャーロール] を選択し、選択したユーザーの上に移動することで、サイト全体でマネージャーロールを与えることができます(例えば、新しいユーザーを追加できるようにするため)。
そうすると、そのロールのユーザーは、サイト管理の一部の項目にしかアクセスできなくなります。セキュリティ、サーバー、プラグイン、外観、または高度な機能などの領域にはアクセスできません。サイト管理者は、ユーザー、コース、グレードのシステム設定やツールのほとんどのツールにアクセスすることができます。
特に、サイト全体の管理者ロールは、サイト管理でこれらのツールを見ることができます。
コンピテンシー フレームワークの移行 インポートコンピテンシーフレームワーク 輸出コンピテンシーフレームワーク コンピテンシーフレームワーク 学習計画書のテンプレート バッジ バッジの設定 バッジの管理 新しいバッジを追加 言語 言語のカスタマイズ 外観 デフォルトのダッシュボードページ デフォルトのプロフィールページ タグの管理 ユーザーツアー フロントページ フロントページの設定 利用者 アカウント ユーザーの一覧を見る バルクユーザーアクション 新しいユーザーの追加 コホート ユーザーのアップロード ユーザーの写真をアップロードする アクセス許可 役割の定義 システムの役割を割り当てる システムのパーミッションを確認する 能力の概要 コホートにユーザーロールを割り当てる コースのご案内 コースとカテゴリの管理 カテゴリの追加 復元コース バックアップ 一般的なバックアップのデフォルト 一般的なインポートのデフォルト バックアップの自動設定 グレード 一般的な設定 グレードカテゴリの設定 グレード項目の設定 スケール 成果(サイトで有効になっている場合 レターズ レポート設定 グレイダーレポート 学年履歴 概要レポート ユーザーレポート プラグイン 質問の種類 質問プレビューのデフォルト 報告書 コメント バックアップ ログ ライブログ パフォーマンスの概要 セキュリティの概要 統計(サイトで有効になっている場合 イベント監視ルール注意事項。
・これらのいくつかは、さらに役割の特定の機能を編集することによって制限することができます、例えば、ユーザーを作成し、ファイルからユーザーをアップロードするには、手動で登録、コホートの管理、言語のカスタマイズなど、など。
・マネージャーは、他のコースと同じようにフロントページへのアクセス権を持っています(技術的にはコースです)。
・マネージャーはほとんどのシステムレベルのレポートにアクセスできますが、設定レポートにはアクセスできません。
・マネージャーはサイト全体のマネージャーとして他のユーザーを割り当てることができます。
・また、マネージャはマネージャ自身のロールを編集する機能を持っています - これを無効にするには、ロールの作成と管理機能を禁止することができます。3 カテゴリーレベルでのマネージャーのロールの割り当て
管理者の役割は、サイト全体ではなく、コンテキストのカテゴリに割り当てることもできます。
1つのカテゴリ内のすべてのコースにアクセスして管理できるようにしたいが、サイト管理ツールにはアクセスできないようにしたい場合に使用します。
次のように割り当てます。サイト管理 > コース > コースの追加/編集 > (カテゴリを選択) > このカテゴリの編集 > 管理ブロック。ロールの割り当て > 管理者 > (ユーザーを選択) 追加
注意事項。
・カテゴリレベルの管理者は、割り当てられたカテゴリのためだけに存在します:複数のカテゴリを管理するためには、各カテゴリで個別にその役割を割り当てる必要があります。
・カテゴリレベルの管理者は、新しいサブカテゴリの作成やコースの移動など、割り当てられたカテゴリの下にあるサブカテゴリも管理します。
・割り当てられたカテゴリでコースを作成することができます。
・カテゴリレベルのマネージャは、サイトレベルのマネージャほど多くの機能を持ちません。なぜなら、特定の機能はシステムコンテキスト、すなわちシステムロールを介してのみ適用できるからです。
・他のユーザーとしてログインするケイパビリティについては、管理するカテゴリ内のコースについては、カテゴリレベルの管理者は、他のコース参加者としてログインし、そのコース内でのみ閲覧することができます。いくつかのコマンドで管理ブロックにあることに注意してください。管理者は、カテゴリの編集とカテゴリの追加リンクを持つために、編集をオンにしなければなりません。以下のスクリーンショットは、編集をオンにしたカテゴリレベルのマネージャーの管理ブロックのビューで、このカテゴリの編集とサブカテゴリの追加のコマンドが表示されています。
category-level-manager-settings.png4 関連項目
- 投稿日:2020-11-04T16:24:36+09:00
unicode正規表現サンプル
- 投稿日:2020-11-04T16:03:39+09:00
[検証] コードをもとにコードを書くコードを書きたい ~ interfaceから実装を作る
今日は皆さん。
エンジニアとしてこんなこと言っていいのかわかりませんが、コード書くの面倒なんですよ。
コード書けばバグは出るし、ファイルとクラス名のミスマッチではじめはまともに動かんし、単純に書く量だけが多いと、大したロジックを書いているわけでもないのにやたらと時間がかかったりと、とにかくストレスのもとになるのですよ。
コードを書かないための技の一つは、CakePHPのように規約を駆使しして書く必要のないコードを書かなくするというのがありまして、個人的には好きなんですが、一般的ではないオレオレルールにしちゃうと、あとがたいへんなんですよね、これ。
ほかの手段としては、コードは書くけど、あまり人間に書かせないという、要するに自動生成にしちゃおうという技です。今回はどうやってコードを生成しようかなっていうのを検証しようと思います。
目標 ~ interfaceから実装を作る
とりあえず、今回の目標は、interfaceから実装を作る、にします。
実装の中身を作るのは流石にあれですが、少なくともひな型くらいは作ってもらって、ファイルを生成するストレスからの解放を狙おうと思います。
interfaceは自分で作らなければなりませんが、こいつはまあ、設計図みたいなもんなので。とりあえず、以下のようなinterfaceがあったとして、
src/Contract.php<?php namespace Niisan\App; interface Contract { const CONTRACT_NAME = 'contract'; /** * ベクトルを足す * * @param Vector $a * @param Vector $b * @return Vector */ public function plus(Vector $a, Vector $b): Vector; /** * 適当な関数 * * @param Vector $a * @param integer|null $num * @param string|null $word * @return void */ public function tekito(Vector $a, ?int $num, ?string $word = 'default'); }こいつをもとに次のクラスを自動生成できればいいかなって思います。
src/Imple/Something.php<?php namespace Niisan\App\Imple; use Niisan\App\Contract; use Niisan\App\Vector; class Something implements Contract { public function plus(Vector $a, Vector $b): Vector { } public function tekito(Vector $a, ?int $num, ?string $word = 'default') { } }これができれば、ひな型作成は簡単ですね。
最近のエディタは異様なほど賢いので、implements Contract
とかやった瞬間に、足りない実装のひな型自動で作ってくれるとかありそうですが...。コードをもとにコードを作るクラス
とりあえず、適当なクラスを作りましょう。
src/Generator/ImplementGenerator.php<?php namespace Niisan\App\Generator; use Reflection; use ReflectionClass; use ReflectionMethod; use RuntimeException; class ImplementGenerator { }ここに対して、
- interfaceを解析する
- interfaceの各メソッドを解析して、必要なメソッドを作る
- 指定したクラス名で、interfaceの実装を作る
ってのをやっていきます。
interfaceを解析する
例によってReflectionClassを使って、interfaceの中身を丸裸にしていきます。
まず元になるinterfaceを指定します。
private ReflectionClass $interface; public function from(string $class_name): self { $reflection = new ReflectionClass($class_name); if ($reflection->isInterface() === false) { throw new RuntimeException('interfaceではない'); } $this->interface = $reflection; return $this; }interfaceからコードを作りたいので、interfaceではないクラスははじきます。
このinterfaceからは次のような情報をとることができます。
$interface_name = $this->interface->getName();// interfaceの名前空間込みの名前を取得できる $method_list = $this->interface->getMethods();// interfaceに存在するメソッドのリフレクションを取得できる次はメソッドの中を解析しましょう。
各メソッドを解析し、メソッドのひな型を作成できるようにする
適当なメソッドを作って、必要なメソッドのリストを取得します。
private function analyzeMethods(): array { $methods = []; foreach ($this->interface->getMethods() as $method) { $methods[] = $this->analyzeMethod($method); } return $methods; }各メソッドは、実際には
ReflectionMethod
になっているので、次のようなメソッドを作って、関数を作るのに必要な情報を抜き取りましょう。private function analyzeMethod(ReflectionMethod $method) { $method_name = $method->getName();// メソッド名の取得 $modifier = Reflection::getModifierNames($method->getModifiers());// メソッドの修飾子 ( public, abstract, staticなど ) を取得 $modifier = array_filter($modifier, fn($name) => $name !== 'abstract');// abstractは実装する際には不要 $return_type = ($method->hasReturnType()) ? $this->removeNamespace($method->getReturnType()->__toString()) : null;// 返り値の型 }これで、メソッドの外側の情報はゲットできていますが、大事なのは引数の情報なので、それを取得していきます。
foreach ($method->getParameters() as $param) { // }メソッドの引数は
ReflectionMethod::getParameters()
で取得できます。各要素はReflectionParameter
になっています。
各引数は主に以下の考慮要素があります。
- 型
- nullabeかどうか
- デフォルトの値
これらを考慮して、ループの中には以下のようなコードが書けます。
$arg = [ 'type' => null, 'optional' => $param->isOptional(),// これは初期値があるかどうかを判別している 'name' => $param->getName(), ]; // 引数の型が指定されている場合は型を用意しておく if ($param->hasType()) { $type = $param->getType(); $arg['type'] = $type->__toString();// nullableをあらわす ? はこの時点でついてくる } // デフォルトの値が設定されている場合 if ($arg['optional']) { $default = $param->getDefaultValue(); $arg['default'] = is_string($default) ? "'$default'": $default; }ここで引数の型は実はかなり厄介です。
ユーザ定義の型を指定している場合、echo $type->__toString();
とした場合、?Niisan/App/Vector
みたいに、オプショナルマーク付きのフルパスのクラス名が取得されます。
これを実装コードに書かれるのは嫌なので、引数の型を作っている部分をぐりっと変えます。if ($param->hasType()) { $type = $param->getType(); $optional = (strpos($type->__toString(), '?') === 0 and $type->isBuiltin() === false) ? '?': ''; $arg['type'] = $optional . $this->removeNamespace($type->__toString());// 名前空間とって、オプショナル if ($type->isBuiltin() === false) { $this->uses[] = ltrim($type->__toString(), '?');// ユーザ定義のクラスはuseに追加する } }名前空間をとる関数は名前空間だけを取得する関数とセットで作っておきます。
src/Generator/ImplementGenerator.phpprivate $defaultNameSpace = 'Niisan\\App'; private function getNameSpace(string $filename) { $segment = explode('/', $filename); if (count($segment) === 1) { return $this->defaultNameSpace; } $name = $this->defaultNameSpace; foreach ($segment as $key => $val) { if ($key === count($segment) - 1) { break; } $name .= '\\' . $val; } return $name; } private function removeNamespace(string $class): string { $segment = explode('\\', $class); return $segment[count($segment) - 1]; }## 組み立てる
必要なメソッドが大体そろってきたので、組み立てをします。src/Generator/ImplementGenerator.phppublic function output(string $filename) { $interface_name = $this->interface->getName(); $this->uses[] = $interface_name; $methods = $this->analyzeMethods(); $text = $this->buildText($filename, $methods); file_put_contents('src/' . $filename . '.php', $text); }これがファイルを生成するためのアクションメソッドになります。
$gen = new ImplementGenerator; $gen->from(Contract::class)->output('Imple/Something');こんな風に使えればいいかなって思います。
あとは未実装のメソッドである
buildText
を実装します。private function buildText(string $filename, array $methods) { $text = "<?php\n"; $text .= 'namespace ' . $this->getNameSpace($filename) . ";\n\n"; // use の部分書き連ねる $this->uses = array_unique($this->uses); foreach ($this->uses as $use) { $text .= 'use ' . $use . ";\n"; } // クラス名とインターフェースを書く $text .= "\n" . 'class ' . $this->getClassName($filename) . ' implements ' . $this->removeNamespace($this->interface->getName()); $text .= "\n{"; $indent = str_repeat(' ', self::INDENT); // メソッドのひな型を作る foreach ($methods as $method) { $text .= "\n" . $indent . $method['modifier'] . ' function ' . $method['name'] . '('; $args = []; // 引数を入れる foreach ($method['args'] as $arg) { $args[] .= (($arg['type']) ? $arg['type'] . ' ' : '') . ('$' . $arg['name']) . (($arg['optional']) ? ' = ' . $arg['default'] : ''); } $text .= implode(', ', $args) . ')'; // メソッドの型 $text .= ($method['return_type']) ? ': ' . $method['return_type'] : ''; $text .= "\n" . $indent . "{\n\n" . $indent . "}\n"; } $text .= '}'; return $text; }頭の痛くなる泥臭い文字列結合ですね。
最終コードはgistに置いておきます。https://gist.github.com/niisan-tokyo/7ca552da7ea3d73bd553513b048807e1
動かす
最後に動かして確認してみます。
generator.phprequire 'vendor/autoload.php'; use Niisan\App\Contract; use Niisan\App\Generator\ImplementGenerator; $gen = new ImplementGenerator; $gen->from(Contract::class)->output('Imple/Something');これを実行して作られるファイルがこんなやつです。
src/Imple/Something.php<?php namespace Niisan\App\Imple; use Niisan\App\Contract; use Niisan\App\Vector; class Something implements Contract { public function plus(Vector $a, Vector $b, ?Vector $c): Vector { } public function tekito(Vector $a, ?int $num, ?string $word = 'default') { } }とりあえず第一目標は達成できたかなって感じですね。
まとめ
というわけで、最近物量の多さに動きを変える必要があると考え、コードジェネレータを作るための準備をしています。
今回はinterfaceをもとにクラスのひな型を作る、あまり面白みのないやつですが、ここからより実践的なものに発展させていければと思います。こんなところですかね。
- 投稿日:2020-11-04T14:38:10+09:00
[Laravel]DBより抽出したデータをクエリビルダでとれなかったときの話
エラー文
Property [id] does not exist on this collection instance.
このコレクションインスタンスにはidプロパティはありませんとのこと。
該当ソース
$data = DB::table('users')->where('id',1)->get();これをview側で$data->idとしたときに上記エラーが起こった。
->get()の返り値はCollectionクラス。
Collectionの中身はModelの各データで構成されている。data->idで取るデータはModelの中のプロパティ変数を取るものなので、データが1件しかなくとも、各Modelの集合体の配列であるCollectionからは$data->idという取り方ではエラーが出た。解決方法
$data = DB::table('students')->where('id',1)->first();->first()の返り値はmodelオブジェクト
まとめ
view側で$data->idというように単純に一件だけデータを取りたいときは、->first()や->find()などで、Modelのオブジェクトを返すようにする必要がある。
参考文献
【Laravel】Property [id] does not exist on this collection instance.
- 投稿日:2020-11-04T13:14:58+09:00
Moodle 3.9 マニュアル - サイト管理者
サイト管理者
サイト管理者は何でもできる権限を持っています。
ユーザーは、「サイト管理」>「ユーザー」>「権限」>「サイト管理者」で、他のサイト管理者からサイト管理者のロールを割り当てられることがありますが、その役割自体を編集(または削除!)することはできません。プライマリ管理者(サイト作成時に作成された)は、サイト管理者ロールから削除することはできません。
あなたのサイトにはたくさんの管理者を置かないことをお勧めします。管理者は1人か2人だけにして、他の全員にマネージャー:(翻訳準備中)のようなロールを与え、必要な権限だけを与えるのが良い方法です。
Managesiteadministrators.pngMNetを使用している場合は、「管理者のロールの割り当て」を参照してください。
- 投稿日:2020-11-04T11:34:02+09:00
【3ヶ月】未経験転職したエンジニアが自社開発企業で行なったこと【そこから見えるやっておくべきこと】
自己紹介
yukiと申します。DMMWEBCAMPにお世話になって、今はWEBエンジニアをしつつ、自分で仲間を集めてサービス開発したり、プログラミングの家庭教師したり毎日エンジニアライフをエンジョイしています。
本日は未経験エンジニアとして、自社開発企業に就職して3ヶ月の間に何をしたか紹介します。
勤務先にもSNSで身分を明らかにすることは承諾を得ているので、その部分もお伝えします。会社の紹介
私は現在、株式会社ダイアログという物流×ITの会社に勤務しております。
2020年9月現在、エンジニアの募集はしていませんが、他にも様々な職種を募集しているので、Wantedlyのページをご覧ください。いつか自分のQiitaきっかけで応募してくださる方がいたら、嬉しいなと思います。さて、ではそんなダイアログで行なったことをまとめます。
1ヶ月目
プログラミングの部分
- 環境構築
- 自社サービスの使用方法、ファイルの場所などの研修
- 【Laravel】CSVファイルの書き出しの際の簡単なロジックの追加
- 【HTML/CSS/JS】でプロダクトのモックを作成
それ以外の部分
- エンジニアの先輩方、部署を跨いだメンターとの1on1面談
- 興味があったので、お客様とのMTGに参加
1ヶ月目は環境構築を終えたのち、大変ありがたいことにサービスの操作方法や関連するファイルの場所などの研修がありました。プログラミングに関してはある程度研修が終わったのち、Laravelを用いてCSVファイルの出力の際に、
こういう値がきたらこうする
といった簡単な処理の追加をOJT形式で行わせていただきました。また、個人の案件としてはこれまで学習した知識を生かし、HTML/CSS/JSでモック(DBの複雑な処理などはないが、見た目としてはできているプロダクト)の作成をしました。それ以外の部分では、メンター制度が手厚く、エンジニアの先輩方に質問しやすい1on1面談があっただけではなく、他部署の先輩が一人ずっとメンターとしてついてくださるので会社の精度などの質問ができました。また、お仕事の部分では開発だけではなく、早いうちからお客様の意見を直接お聞きしたかったので、ミーティングに参加希望を出したところ承認していただきました。
2ヶ月目
プログラミングの部分
- 【Laravel】APIを作成、Service層の切り分け
- 【AngularJS】APIに連携させるフロントエンドの処理を作成
- 【SQL】20行くらいのSQLを教えていただき、理解しながらLalavelの処理の中に組み込む
それ以外の部分
- Qiitaのプロジェクト提案&開始
2ヶ月目に入ると少しだけ難易度が上がり、フロントエンドとバックエンドを分けた開発に携わることになりました。LaravelでAPIを作成し、フロント側のAngularJSと連携させるような実装です。他にも、スクールでは学習しなかった【Service層】という概念を知り、ロジックを切り分けることの大切さを確認しました。また、自社サービスとなると複雑なDBがつきもので、これまで見たことのない(自分にとっては)長いSQLを扱うようになりました。ただSQLがわかるだけではなく、Railsにもアクティブレコードなんかがありますが、LaravelでのORMも同時に学ぶ必要があったので少し大変でした。
プログラミング以外の部分では、社内でこれまでにQiitaを運用したいができていなかったという課題をお聞きできたので、投稿経験もあったため、メリットデメリットをまとめ、スケジュールをひき、自分主体で投稿サイクルを作成するQiitaプロジェクトを提案し、無事まかせていただきました。(まさにこの記事もその一環なので、ぜひLGTMお願いしますっ)
3ヶ月目
プログラミングの部分
- 【Laravel】モデル以外の場所に、より細かいバリデーション(削除の際の制御など)追加
- 【AngularJS】カスタムディレクティブのメリット理解と作成
- ER図の離れたデータの取得の仕方を学習 ### それ以外の部分
- 社内の懇親会企画
3ヶ月目は、これまでの実装の他に削除制御について機能を実装しました。スクールで学習するレベルだと、モデルに簡単なバリデーションを書くだけでしたが、もっと細かい処理を書く必要があったのでいい経験になりました。フロントエンドの方では、カスタムディレクティブという概念を学び、コードをより短く書くなどリファクタリングと所謂コンポーネントの役割をしっかり決める必要性を学びました。大きいER図を見ながらデータを取りに行くことがあるのですが、その際テーブル同士の関係は非常に重要で、3ヶ月経過した今でも無駄なくそこにアクセスできるように頑張っています。企業にもよりますが、弊社にはER図のまとめがあったので印刷して暇な時に眺めています。
全く話が変わりますが、大学生の頃にボードゲームでたくさん遊んでいた経験があったので、メンターの方と協力して社内の懇親会を企画しました。オンラインが多い現状ですが、いろいろ考えながら引き続きやっていきたいと思います。
やっておいてよかったこと
- 質問の仕方をしっかり身につける まだまだわかりにくい質問をしてしまっていると思いますが、スクールで学習する際にここだけはしっかりと意識していました。
大体以下のような形で質問しています。
#【何がやりたくて】 #【今どうやってて】 #【どこでエラーが起きて】 #【自分ではこうだと思ったのだけど】 #【うまくいかないのでアドバイスをください】+【あれば参考にした記事】相手が答えやすい質問をすることはとても大切だと思うので、この辺は早いうちから意識した方がいいと思います。
- フロントとバックを分けた開発を経験していた
ポートフォリオを作る段階で、RailsでAPIを作って、フロントエンドのフレームワークNuxt.jsを使ってバックフロントを分けた開発をしていたので、その辺の合流は思っていたよりスムーズにできていたのかなと思います。これは、他の記事でもまとめておりますので、よければご覧ください。後でリンク貼ります。反省
以下、反省点です。精進します。
- もっとSQLやDBの学習をしておけばよかった
- 使うフレームワークや言語がわかったら、どんなに期間が短くても深く学んでおけばよかった
- 投稿日:2020-11-04T10:49:25+09:00
Moodle 3.9 マニュアル - 機能
機能
Moodleは無料のオンライン学習管理システムで、教育者がいつでも、どこでも、学習を拡張するダイナミックなコースで満たされた独自のプライベートウェブサイトを作成することを可能にします。
あなたが教師、学生、管理者であるかどうかにかかわらず、Moodleはあなたのニーズを満たすことができます。Moodleの非常にカスタマイズ可能なコアは、多くの標準機能を備えています。以下のMoodleのコア機能のハイライトをご覧ください。また、LMS、Moodleアプリ、オフライン機能を比較した学生向けMoodle機能 (pdf) をダウンロードしてください。
一般的な機能
モダンで使いやすいインターフェイス
レスポンシブでアクセスしやすいように設計されたMoodleのインターフェースは、デスクトップとモバイルデバイスの両方で簡単に操作できます。
デモを見るパーソナライズされたダッシュボード
現在のコース、過去のコース、将来のコースをタスクと一緒に表示します。
ダッシュボード連携ツールと活動
フォーラム、Wiki、用語集、データベース活動などで一緒に学びましょう。
活動内容オールインワンカレンダー
Moodleのカレンダーツールは、学業や会社のカレンダー、コースの締め切り、グループミーティング、その他の個人的なイベントを管理するのに役立ちます。
カレンダー:(翻訳準備中)便利なファイル管理
MS OneDrive、Dropbox、Google Driveなどのクラウドストレージサービスからファイルをドラッグ&ドロップします。
ファイルの操作:(翻訳準備中)シンプルで直感的なテキストエディタ
すべてのウェブブラウザやデバイスで動作するエディタでテキストをフォーマットし、メディアや画像を簡単に追加できます。
テキストエディタ:(翻訳準備中)お知らせ
この機能を有効にすると、ユーザーは新しい課題や締め切り、フォーラムの投稿などの自動アラートを受信したり、プライベートメッセージを送信したりすることができます。
メッセージング:(翻訳準備中)進捗状況の追跡
教育者や学習者は、個々の活動やリソース、コースレベルでの進捗状況や修了状況を追跡するためのさまざまなオプションを使用して追跡することができます。
進捗状況の追跡:(翻訳準備中)管理機能
カスタマイズ可能なサイトデザインとレイアウト
あなたのロゴ、カラースキーム、その他多くの要素でMoodleテーマを簡単にカスタマイズすることができます - または、あなた自身のテーマをデザインするだけです。
テーマ:(翻訳準備中)セキュアな認証と大量登録
あなたのMoodleサイトおよびコースにユーザを追加および登録するための50以上の認証および登録オプション。
認証/登録多言語対応
ユーザーがコースの内容を表示したり、自分の言語で学習したり、多言語のユーザーや組織のために設定したりすることができます。
言語:(翻訳準備中)コースの一括作成と簡単なバックアップ
一括でコースを追加し、簡単に大規模なコースをバックアップして復元することができます。
一括コースアップロード:(翻訳準備中)ユーザーの役割と権限の管理
ユーザーのアクセスを指定して管理するロールを定義することで、セキュリティ上の問題に対処します。
ロールとパーミッション:(翻訳準備中)オープンスタンダードをサポート
IMS-LTI、SCORMコースなどをMoodleに簡単にインポートおよびエクスポートできます。
標準:(翻訳準備中)高い相互運用性
外部アプリケーションやコンテンツを自由に統合したり、独自のプラグインを作成してカスタム統合を行うことができます。
SCORM / 外部ツールシンプルなプラグイン管理
単一の管理者インターフェース内でプラグインをインストールしたり、無効にしたりすることができます。
プラグインのインストール定期的なセキュリティアップデート
Moodleは定期的に最新のセキュリティパッチで更新されており、お客様のMoodleサイトの安全性を確保しています。
セキュリティ:(翻訳準備中)詳細なレポートとログ
コースとサイトレベルでの活動と参加に関するレポートを表示し、生成します。
サイト全体のレポート:(翻訳準備中)すべてのサイト管理・開発機能を見る→サイト管理・開発機能を見る
コース開発・運営の特徴
ダイレクトラーニングパス
様々な要件を満たすためにコースをデザインし、管理します。インストラクターによる授業、自分のペースで進められる授業、ブレンデッド授業、完全オンライン授業などがあります。
教育学連携を促す
内蔵されたコラボレーションパブリッシング機能は、エンゲージメントを促進し、コンテンツ主導のコラボレーションを促進します。
活動外部リソースを埋め込む
他サイトの教材を教えたり、課題を盛り込んだり、Moodleの成績表に接続したりすることができます。
外部ツールマルチメディア統合
Moodleのビルトインメディアサポートにより、あなたのコースにビデオやオーディオファイルを簡単に検索して挿入することができます。
メディアとの連携:(翻訳準備中)グループの管理
コースを共有し、活動を差別化し、チームワークを促進するためのグループ学習者。
グループ:(翻訳準備中)マーキングワークフロー
便利なように課題に異なるマーカーを割り当て、評定の修正を管理し、個々の学習者にマークが公開されるタイミングをコントロールすることができます。
課題モジュール:(翻訳準備中)インラインマーキング
ブラウザ内で直接ファイルに注釈を付けることで、簡単にレビューし、インラインフィードバックを提供することができます。
課題モジュール:(翻訳準備中)ピアと自己評価
ワークショップやアンケートなどのアクティビティが組み込まれており、学習者は自分や他のコースメンバーの作品をグループで見たり、評価したりすることができます。
ワークショップ:(翻訳準備中)統合されたバッジ
Mozilla Open Badgesと完全に互換性があり、カスタマイズされたバッジで学習者のモチベーションを高め、参加と成果に報います。
バッジアウトカムとルーブリック
高度なグレーディング方法から選択して、あなたのカップルに合わせてグレーディングブックを作成します。
評定:(翻訳準備中)コンピテンシーに基づくマーキング
コースや活動にまたがる個人学習計画でコンピテンシーを設定します。
コンピテンシー:(翻訳準備中)セキュリティとプライバシー
自分と自分のクラスだけがアクセスできるプライベートスペースで教えて共有することができます。
コース
- 投稿日:2020-11-04T10:42:54+09:00
【PHP】【初心者】値渡しと参照渡し
値渡しってなんぞ
関数を呼ぶとき、引数って使いますよね。
このとき、呼び出した先に渡された値は、呼び出し元の変数をコピーして使っています。
つまり、呼び出し先の関数でこの引数を変更しても、呼び出し元にはまったく影響がないということです。public function start() { $number = 10; // 上記の変数を使って関数を呼びます $this->oneUp($number); echo '3:' , $number, ' 関数の後、呼び出し元の値', PHP_EOL; } private function oneUp(int $number) { echo '1:', $number, ' これが関数に渡された値', PHP_EOL; $number += 1; echo '2:', $number, ' 引数に1を足した値', PHP_EOL; }実行結果
1:10 これが関数に渡された値 2:11 引数に1を足した値 3:10 関数の後、呼び出し元の値「3:」の値が変化していないことから、コピーであることがわかります。
これを値渡しと言います。値渡しで進める通常の処理
せっかく関数で増やしたんだから呼び出し元でも使いたいよ、というとき、
人は呼び出し元で「別の変数」として受け取ります。public function start() { $number = 10; // 左辺で別変数を指定する $oneUpNumber = $this->oneUp($number); echo '3:' , $oneUpNumber, ' 関数の後、呼び出し元で受け取った値', PHP_EOL; } private function oneUp(int $number) { echo '1:', $number, ' これが関数に渡された値', PHP_EOL; $number += 1; echo '2:', $number, ' 引数に1を足した値', PHP_EOL; // 呼び出し先でもreturnで値を返す return $number; }実行結果
1:10 これが関数に渡された値 2:11 引数に1を足した値 3:11 関数の後、呼び出し元で受け取った値こんな感じで、通常は処理を進めます。
参照渡し
ところが、こういった手順を踏まなくても、
呼び出し先で、呼び出し元の値を書き換えてしまう渡し方があります。
それが参照渡しです。public function start() { $number = 10; // 上記の変数を使って関数を呼びます $this->oneUp($number); echo '3:' , $number, ' 関数の後、呼び出し元の値', PHP_EOL; } // 受け取った引数の頭に&をつける private function oneUp(int &$number) { echo '1:', $number, ' これが関数に渡された値', PHP_EOL; $number += 1; echo '2:', $number, ' 引数に1を足した値', PHP_EOL; }実行結果
1:10 これが関数に渡された値 2:11 引数に1を足した値 3:11 関数の後、呼び出し元の値関数で受け取った引数の頭に「&」をつけたことで「3:」の値が変化しました。
呼び出し先の関数でも呼び出し元の変数(メモリアドレス)を「参照」しているからです。ここが大事な注意点
ところが、ソースの中でこういった参照渡しが存在すると、
「あれ、変数の値が途中でいつの間にか変わってる???」
という混乱の元になります。
同じ名前の変数が処理の前後で値が変わっていてしまうと、
そのことに大変気付きにくいので、大災害の火種になりかねません。関数で値を変えて、それを使いたいのであれば別の変数として受け取りましょう。
ちなみにPHPではオブジェクトはデフォルトで参照渡しです。これも注意しましょう。
- 投稿日:2020-11-04T10:26:28+09:00
Laravel ローカルに画像をアップロードするアプリを作成する
目次
- Macのローカルで作成した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 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする Laravel バージョン 6.X commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 前提条件
- MacのローカルでLaravelのアプリが作成できる状態になっていること。
- コマンド
$ composer
が実行できる状態になっていること。前提情報
- 本記事はMacのローカルで作成されたLaravelアプリから
アプリ名ディレクトリ/storage/app/public/images
にファイルをアップロードする機能を作る。- この記事ではアップロードを最終目標としアップロードしたファイルを表示する機能は別の記事で紹介する。
- Laravelアプリを作成する部分から説明する。
- 作成するLaravelアプリは「laravel6_image」とし使用するデータベース名を「laravel6_image」とする。
- 本記事の作業完了したソースは下記にアップしてある。
概要
- データベースの作成
- Laravelアプリ作成
- .envファイルの修正とシンボリックリンクの作成
- ルーティング情報の記載
- マイグレーションファイルの記載とマイグレート
- モデルファイルの修正
- コントローラファイルの作成と記載
- ビューファイルの作成と記載
- 確認
詳細
- 下記の説明で実行するコマンドはすべてMacのローカルのターミナルで実行するものとする。
データベースの作成
下記コマンドを実行してMySQLにログインする。(MySQLのパスワードがわからなくなってしまった方はこちら→Mac ローカル環境の MySQL 8.x のrootパスワードを忘れた時のリセット方法)
$ mysql -u root -p下記SQLを実行してデータベース「Laravel6_image」を作成する。
create database laravel6_image;下記SQLを実行して結果に「laravel6_image」があることを確認してMySQLからログアウトする。
show databases;Laravelアプリ作成(下記のアプリ作成実行直後のソースはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/01_create_app)
Laravelアプリのファイルを作成したいディレクトリで下記コマンドを実行する。
$ composer create-project "laravel/laravel=6.*" laravel6_image $ cd laravel6_image.envファイルの修正とシンボリックリンクの作成
下記コマンドを実行してLaravelの設定ファイルを開く。
$ vi .env下記のように内容を記載修正する。
APP_NAME=laravel6_image DB_DATABASE=laravel6_image DB_USERNAME=root DB_PASSWORD=皆さんのMySQLのrootユーザのパスワード FILESYSTEM_DRIVER=public記載修正した筆者の.envの内容を下記に記載する。(MySQLのrootパスワードは伏せる)
APP_NAME=laravel6_image APP_ENV=local APP_KEY=base64:UCrvlsgbU4qjd5H8rRSm67u1yur1lG/dmgUYOwM49YQ= APP_DEBUG=true APP_URL=http://localhost LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel6_image DB_USERNAME=root DB_PASSWORD=************* FILESYSTEM_DRIVER=public BROADCAST_DRIVER=log CACHE_DRIVER=file QUEUE_CONNECTION=sync SESSION_DRIVER=file SESSION_LIFETIME=120 REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_DRIVER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=null MAIL_FROM_NAME="${APP_NAME}" AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"下記コマンドを実行してデフォルトマイグレーションファイルのマイグレートを実行する。
$ php artisan migrate;下記コマンドを実行してシンボリックリンクの作成を行う。
$ php artisan storage:link下記コマンドを実行してローカルサーバを起動する。
$ php artisan serve下記にアクセスして下記画像の画面が表示されることを確認する。
ルーティング情報の記載(本作業完了後のソースコードはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/02_route)
下記コマンドを実行してルーティングファイルを開く。
$ vi routes/web.php下記の内容を追記する。
laravel6_image/routes/web.php// 画像アップロードページ用 Route::get('/input', 'ImageController@input')->name('input'); // 画像アップロード処理用 Route::post('/upload', 'ImageController@upload')->name('upload');記載後のルーティングファイルの全内容を下記に記載する。
laravel6_image/routes/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('/input', 'ImageController@input')->name('input'); // 画像アップロード処理用 Route::post('/upload', 'ImageController@upload')->name('upload'); // 上記までを追記マイグレーションファイルの記載とマイグレート(本作業完了後のソースコードはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/03_migrate)
下記コマンドを実行してモデルファイルとマイグレーションファイルを一緒に作成する。
$ php artisan make:model Models/Image -m下記コマンドを実行してマイグレーションファイルを開く。(YYYY_MM_DD_XXXXXXはマイグレーションファイルの作成日時)
$ vi database/migrations/YYYY_MM_DD_XXXXXX_create_images_table.phpupメソッドのcreateの中に下記を記載する。
database/migrations/YYYY_MM_DD_XXXXXX_create_images_table.php$table->string('file_path')->default('default'); $table->string('file_name')->default('default'); $table->softDeletes();記載後のマイグレーションファイルの全内容を下記に記載する。
database/migrations/YYYY_MM_DD_XXXXXX_create_images_table.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateImagesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('images', function (Blueprint $table) { $table->bigIncrements('id'); // 下記を追記 $table->string('file_path')->default('default'); $table->string('file_name')->default('default'); $table->softDeletes(); // 上記までを追記 $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('images'); } }下記コマンドを実行してマイグレートする。
$ php artisan migrate(本作業の意図はこちら→Laravel テーブル内のデータ削除を論理削除にする)(本作業完了後のソースコードはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/04_model)
下記コマンドを実行してモデルファイルを開く。
$ vi app/Models/Image.php下記の内容を追記する。
laravel6_image/app/Model/Image.phpuse Illuminate\Database\Eloquent\SoftDeletes; // Imageクラス内に下記を追記 use SoftDeletes;記載後のモデルファイルの全内容を下記に記載する。
laravel6_image/app/Models/Image.php<?php namespace App\Model; use Illuminate\Database\Eloquent\Model; // 下記を追記 use Illuminate\Database\Eloquent\SoftDeletes; class Image extends Model { //下記を追記 use SoftDeletes; }コントローラファイルの作成と記載(本作業完了後のソースコードはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/05_controller)
下記コマンドを実行してコントローラファイルを作成する。
$ php artisan make:controller ImageController下記コマンドを実行して作成したコントローラファイルを開く。
$ vi app/Http/Controllers/ImageController.php下記のようにコントローラファイルの内容を追記・修正する。追記修正後のコントローラファイルの全体の内容を下記に記載する。(Storageファサードを使用するときにdiskを処理中で指定しているドキュメントが多くあるが.envファイルで
FILESYSTEM_DRIVER=public
を一括指定しているので本方法だと処理中にdiskメソッドで指定することはない。)laravel6_image/app/Http/Controllers/ImageController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; // 下記を追記する use App\Models\Image; use Illuminate\Support\Facades\Storage; // 上記までを追記する class ImageController extends Controller { // 下記を追記する public function input() { return view('images/input'); } public function upload(Request $request) { $this->validate($request, [ 'file' => [ // 空でないこと 'required', // アップロードされたファイルであること 'file', // 画像ファイルであること 'image', // MIMEタイプを指定 'mimes:jpeg,png', ] ]); if ($request->file('file')->isValid([])) { $file_name = $request->file('file')->getClientOriginalName(); // オリジナルファイルのファイル名の取得 $file_path = Storage::putFile('/images', $request->file('file'), 'public'); // ファイルのアップロードとアップロードパスの取得 $image_info = new Image(); $image_info->file_path = $file_path; $image_info->file_name = $file_name; $image_info->save(); return redirect('/'); }else{ return redirect(route('input')); } } // 上記までを追記する }ビューファイルの作成と記載(本作業完了後のソースコードはこちら→)
下記コマンドを実行してビューファイルを格納するディレクトリを作成する。
$ mkdir -p resources/views/images下記コマンドを実行してビューファイルを作成して開く。
$ vi resources/views/images/input.blade.php下記の内容をビューファイルに記載する。
laravel6_image/resources/views/images/input.blade.php<h1>画像ファイルのアップロード</h1> <form action="{{route('upload')}}" method="POST" enctype="multipart/form-data"> @csrf @error('file') {{$message}} <br> @enderror <label for="photo">画像ファイル:</label> <input type="file" class="form-control" name="file"> <br> <input type="submit"> </form>確認
下記コマンドを実行してローカルサーバを起動する。
$ php artisan serve下記にアクセスする。
下記のページが表示されたことを確認する。
「ファイルを選択」をクリック後任意の画像ファイルを選択し「送信」をクリックする。
エラーが出ずhttp://127.0.0.1:8000にリダレクトされることを確認する。
参考文献
- 投稿日:2020-11-04T07:01:09+09:00
PHP書き方
このページについて
PHPの構文で独特だと感じたものについて備忘録を残す
遭遇しだい追記PHP構文の始め方
<?php ここに記述 ?>変数の画面出力方法
print "{$変数名}を出力"; print ''.$変数名.'を出力';値の受け取り方
$変数名 = $_POST['nameに設定した値']; $変数名 = $_GET['nameに設定した値'];エスケープ処理
$変数名 = htmlspecialchars($変数名,ENT_QUOTES,'UTF-8');form各要素ののnameの受け取り
if(isset($_POST['名前'])==true){ //その要素がある場合 }画面遷移
header('Location:遷移先'); exit();DBへの接続
$dsn = 'mysql:dbname=DB名;host=ホスト名;charset=utf8'; $user = 'ユーザ名'; $password = 'パスワード'; $dbh = new PDO($dsn, $user, $password); //PDOExceptionをエラー時に投げるための設定 $dbh -> setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); $sql = 'SQL文 代入したいものは?で指定'; $stmt = $dbh -> prepare($sql); $data[] = '代入したいデータ1'; $data[] = '代入したいデータ2'; $stmt -> execute($data); //DBからの切断 $dbh=null;
- 投稿日:2020-11-04T05:21:17+09:00
Moodle 3.9 マニュアル - カテゴリ:Moodle について
カテゴリ:Moodle について
Moodleについての紹介ページのインデックスです。
カテゴリー「Moodleについて」のページ全23ページ中、このカテゴリには以下のページがあります。
A
About Moodle
About Moodle FAQ
Accessibility
AwardsB
Background
C
Curriculum theory
D
Decision FAQ
F
Features
H
History
L
LTI and Moodle
M
Moodle development
Moodle key terms
Moodle myths
Moodle site - basic structureN
New features
New for administrators
New for students
New for teachersP
Pedagogy
PhilosophyS
Standards
U
Usage
User quick guide
- 投稿日:2020-11-04T04:52:02+09:00
Moodle 3.9 マニュアル - バッジ
バッジ
バッジは達成を祝い、進歩を示す良い方法です。バッジは選択された様々な基準に基づいて授与され、ユーザのプロフィールに表示されるか、Badgrのバックパックにプッシュすることができます。
バッジには2つのカテゴリがあります。
・サイトバッジ - サイト全体で利用可能で、サイト全体の活動に関連しているユーザが利用できます。
・コースバッジ - コースに登録されているユーザが利用でき、コース内で行われる活動に関連しています。
badgesintro.png
- 投稿日:2020-11-04T04:43:21+09:00
Moodle 3.9 マニュアル - カテゴリ:バッジ
カテゴリ:バッジ
Moodle 2.5以降のバッジに関するドキュメントページのインデックスです。
バッジ」カテゴリのページ全21ページのうち、このカテゴリには以下のページがあります。
は
B
Badges (日本語訳:バッジ)
Badges FAQ
Badges settingsC
Capabilities/block/badges:addinstance
Capabilities/block/badges:myaddinstance
Capabilities/moodle/badges:awardbadge
Capabilities/moodle/badges:configurecriteria
Capabilities/moodle/badges:configuredetails
Capabilities/moodle/badges:configuremessages
Capabilities/moodle/badges:createbadge
Capabilities/moodle/badges:deletebadge
Capabilities/moodle/badges:earnbadge
Capabilities/moodle/badges:manageglobalsettings
Capabilities/moodle/badges:manageownbadges
Capabilities/moodle/badges:revokebadge
Capabilities/moodle/badges:viewawarded
Capabilities/moodle/badges:viewbadges
Capabilities/moodle/badges:viewotherbadgesL
Latest badges block
M
Managing badges
U
Using badges
- 投稿日:2020-11-04T00:38:06+09:00
素のPHPでTwitterの文字数カウントを再現
経緯
一括ツイートサービスの制作に際して「全角:1/半角と改行:0.5/URL:11.5」という、公式の文字数カウントに近いPHPコードを模索したので共有させて頂きます。
コード
- 全角を1文字/半角を0.5文字とカウント
count.phpfunction twiCount( $text ){ $wholeLen = strlen(mb_convert_encoding($text, "SJIS", "ASCII,JIS,UTF-8,EUC-JP,SJIS")) / 2; return $wholeLen; }
- 改行を0.5文字とカウント
count.phpfunction twiCount( $text ){ $minus_lf = 0; $tempWholeLen = strlen(mb_convert_encoding($text, "SJIS", "ASCII,JIS,UTF-8,EUC-JP,SJIS")) / 2; //改行の数を検出 preg_match_all("\n|\r\n|\r", $text, $matches, PREG_PATTERN_ORDER); $lfCount = count($matches[0]); $minus_lf += ($lfCount/2);//改行1つを0.5文字として扱う $modifiedWholeLen = $tempWholeLen - $minus_lf;//減算 return $modifiedWholeLen; }
- リンクを11.5文字とカウント
count.phpfunction twiCount( $text ){ $minus_lf = 0; $tempWholeLen = strlen(mb_convert_encoding($text, "SJIS", "ASCII,JIS,UTF-8,EUC-JP,SJIS")) / 2; preg_match_all("\n|\r\n|\r", $text, $matches, PREG_PATTERN_ORDER); $lfCount = count($matches[0]); $minus_lf += ($lfCount/2); //リンクの数を検出 $regex = "/https?:\/\/[\w!\?\/\+\-_~=;\.,\*&@#\$%\(\)'\[\]]+/"; preg_match_all($regex, $text, $matches2, PREG_PATTERN_ORDER); $urls = $matches2[0];//値だけの配列 if( !empty($urls) ){ foreach($urls as $key => $url){//検出したURLを11.5文字としてカウント $urlLen = strlen( mb_convert_encoding($url, "SJIS", "ASCII,JIS,UTF-8,EUC-JP,SJIS" ) ) / 2; $minus_url += $urlLen - 11.5;//余分にカウントしていた分をマイナス } } //まとめて引く $modifiedWholeLen = $tempWholeLen - ($minus_lf + $minus_url); return $modifiedWholeLen; }参考記事
実際のURL検出には以下の記事の$regexを使わせて頂きました。
サンプル
$regex = '`\bhttps?+:(?://(?:(?:[-.0-9_a-z~]|%[0-9a-f][0-9a-f]' . '|[!$&-,:;=])*+@)?+(?:\[(?:(?:[0-9a-f]{1,4}:){6}(?:' . '[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:\d|[1-9]\d|1\d{2}|2' . '[0-4]\d|25[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25' . '[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(?' . ':\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]))|::(?:[0-9a-f' . ']{1,4}:){5}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:\d|[1' . '-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(?:\d|[1-9]\d|1\d{' . '2}|2[0-4]\d|25[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\\' . 'd|25[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])' . ')|(?:[0-9a-f]{1,4})?+::(?:[0-9a-f]{1,4}:){4}(?:[0-' . '9a-f]{1,4}:[0-9a-f]{1,4}|(?:\d|[1-9]\d|1\d{2}|2[0-' . '4]\d|25[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-' . '5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(?:\d' . '|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]))|(?:(?:[0-9a-f]{' . '1,4}:)?+[0-9a-f]{1,4})?+::(?:[0-9a-f]{1,4}:){3}(?:' . '[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:\d|[1-9]\d|1\d{2}|2' . '[0-4]\d|25[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25' . '[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(?' . ':\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]))|(?:(?:[0-9a-' . 'f]{1,4}:){0,2}[0-9a-f]{1,4})?+::(?:[0-9a-f]{1,4}:)' . '{2}(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:\d|[1-9]\d|1\\' . 'd{2}|2[0-4]\d|25[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4' . ']\d|25[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5' . '])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]))|(?:(?:' . '[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?+::[0-9a-f]{1,4' . '}:(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:\d|[1-9]\d|1\d' . '{2}|2[0-4]\d|25[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]' . '\d|25[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]' . ')\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]))|(?:(?:[' . '0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?+::(?:[0-9a-f]{1' . ',4}:[0-9a-f]{1,4}|(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25' . '[0-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(?' . ':\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(?:\d|[1-9]\\' . 'd|1\d{2}|2[0-4]\d|25[0-5]))|(?:(?:[0-9a-f]{1,4}:){' . '0,5}[0-9a-f]{1,4})?+::[0-9a-f]{1,4}|(?:(?:[0-9a-f]' . '{1,4}:){0,6}[0-9a-f]{1,4})?+::|v[0-9a-f]++\.[!$&-.' . '0-;=_a-z~]++)\]|(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0' . '-5])\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(?:\\' . 'd|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.(?:\d|[1-9]\d|' . '1\d{2}|2[0-4]\d|25[0-5])|(?:[-.0-9_a-z~]|%[0-9a-f]' . '[0-9a-f]|[!$&-,;=])*+)(?::\d*+)?+(?:/(?:[-.0-9_a-z' . '~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])*+)*+|/(?:(?:[-.0' . '-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])++(?:/(?:[-' . '.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])*+)*+)?+|' . '(?:[-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])++(?' . ':/(?:[-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&-,:;=@])*+' . ')*+)?+(?:\?+(?:[-.0-9_a-z~]|%[0-9a-f][0-9a-f]|[!$&' . '-,/:;=?+@])*+)?+(?:#(?:[-.0-9_a-z~]|%[0-9a-f][0-9a' . '-f]|[!$&-,/:;=?+@])*+)?+`i' ;公式との齟齬
・プロトコル省略URLの非検出(例:hoge.jp)
・日本語URLの非検出(例:https://ほげ.jp)
・存在しないドメインのリンクを検出(例:https://hoge.jphoge )
・一部の全角文字を公式は0.5文字と判定(例:「―」)
140字以上の長文を自動で分割して、一括ツイートするサイト作りました♡٩( ᐛ )و https://t.co/ut11CbiJg1
— それそ (@soresoja) October 30, 2020
- 投稿日:2020-11-04T00:04:47+09:00
【初心者向け】Laravelのmigrateでテーブル作成する方法
こんにちは!! ふうがと言います!プログラミング勉強中の犬です。
今回は、Laravelでartisanを使ってテーブル作成を行います。ご覧頂く前に
著者の備忘録ともなっておりますので言葉足らずな部分もございます。
ご容赦いただければと思います。公式サイト(ご参考までに)
?公式
https://readouble.com/laravel/テーブル作成の順序
①マイグレーション ファイルを作成
②マイグレーション ファイルを編集
③実行
となります。①マイグレーション ファイルを作成
下記のコマンドを叩いて、migration用のファイルを作成しましょう。
(この際のファイル名はなんでもOKです。今回はcreate_usersで作成します!)php artisan make:migration {ファイル名}下記のような結果が出れば成功です。
Created Migration: 2020_11_03_140428_create_users //日付はその日の日付になる②マイグレーション ファイルを編集
先ほどのコマンドで下記のファイルが作成されているはずです。/database/migrations/2020_11_03_140428_create_users.phpclass Create_users extends Migration { /** * Run the migrations. * * @return void */ public function up() { // } /** * Reverse the migrations. * * @return void */ public function down() { // } }こちらにテーブル情報を記載していきます。
function upにはテーブル作成情報を、
function downにはrollbackした時の情報を記載します。
今回はid,名前,年齢,作成日のカラムを登録してみましょう。
※コメントは見辛いので削除しています書き方は、こんな感じ!
$table->データ型('テーブル名');/database/migrations/2020_11_03_140428_users.phpclass Create_users extends Migration { public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->integer('age'); $table->timestamps(); //created_at,updated_atの作成 }); } public function down() { $table->dropIfExists('users'); //テーブル削除 } }③実行
下記のコマンドを叩いてください。
※コマンドをたたく場所は、databaseの上のプロジェクト直下です。php artisan migrate下記のように出れば、作成成功です!
Migrating: 2020_11_03_140428_users Migrated: 2020_11_03_140428_users以上
テーブルが作成されているか、確認してみてください。
- 投稿日:2020-11-04T00:04:01+09:00
※学習用メモ デザインパターン:Adapter編[PHP]
Adapterパターンとはどういうものか
Adapterとは「適合する」という意味で、Wrapperパターンと呼ばれることもある。
「すでに提供されているもの」を「利用できるもの」にするためのデザインパターンAdapterパターンを構成する内容の役割
・Target:必要なメソッドを持っているインターフェース。メソッドの実装方法は定めず抽象メソッドを定義している。
・Adapter:変換するための機能を持つクラス
・Adaptee:利用したいメソッドを持っているクラスどういう時に使用可能なのか
・関連性のないクラス通しを既存のクラスを変えずに関連付けする場合
・既存のクラスをある新しいインターフェイスを通じて再利用したい場合
・既存のクラス・インターフェイスをアプリケーション固有なものに(使いやすく)したい場合
などの際に有効なパターンである[参考サイト]
https://ja.wikipedia.org/wiki/Adapter_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3
https://qiita.com/shoheiyokoyama/items/bd1c692db480b640c976
https://www.programming-fun.net/article/article_77.htmlAdapterパターンを用いるメリット
・既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。
・既存のクラスをもう一度動作テストする必要がなくなる
・Adapterパターンによってバグが発生しても、既存のクラスには変更を加えていないためバグがないことが保証されるサンプルコード
仕様
消費税を計算する。ゲームとかでアイテムやガチャを販売する際の値段に税率を反映させたい。
詳細は以下。
・原価管理のクラス(adaptee):Cost
・消費税計算後(adapter):CostIncludingComsumptionTax
・消費税計算後のクラスのインターフェース(target):CostIncludingComsumptionTaxInterface今回は同様な仕様で、継承を利用したもの、委譲を利用したものを記載する。
継承を利用したパターン
CostIncludingComsumptionTaxInterfaceinterface CostIncludingComsumptionTaxInterface { public function getItemCostIncludingComsumptionTax(); public function getGachaCostIncludingComsumptionTax(); }Cost.class.phpclass Cost { private $itemCost = 100; private $gachaCost = 500; // アイテムの費用取得 public function getItemCost() { return $this->itemCost; } // ガチャの費用取得 public function getGachaCost() { return $this->gachaCost; } }CostIncludingComsumptionTax.class.phpclass CostIncludingComsumptionTax extends Cost implements CostIncludingComsumptionTaxInterface { private $taxRate = 10; // 税率(%) // 消費税を適用したアイテムの費用を返します。 public function getItemCostIncludingComsumptionTax() { return $this->getItemCost() * (1 + ($this->taxRate / 100)); } // 消費税を適用したガチャの費用を返します public function getGachaCostIncludingComsumptionTax() { return $this->getGachaCost() * (1 + ($this->taxRate / 100)); } }呼び出し
$cost = new CostIncludingComsumptionTax(); echo $cost->getItemCostIncludingComsumptionTax() . PHP_EOL; echo $cost->getGachaCostIncludingComsumptionTax() . PHP_EOL; /* 110 550 */委譲を利用したパターン
adaptee、targetについては継承を利用したパターンと同様
CostIncludingComsumptionTax.class.phpclass CostIncludingComsumptionTax implements CostIncludingComsumptionTaxInterface { private $taxRate = 10; // 税率(%) private $costData = null; public function __construct() { if (! $this->costData instanceof Cost) { $this->costData = new Cost(); } } // 消費税を適用したアイテムの費用を返します。 public function getItemCostIncludingComsumptionTax() { return $this->costData->getItemCost() * (1 + ($this->taxRate / 100)); } // 消費税を適用したガチャの費用を返します public function getGachaCostIncludingComsumptionTax() { return $this->costData->getGachaCost() * (1 + ($this->taxRate / 100)); } }``` 呼び出し ```php $cost = new CostIncludingComsumptionTax(); echo $cost->getItemCostIncludingComsumptionTax() . PHP_EOL; echo $cost->getGachaCostIncludingComsumptionTax() . PHP_EOL; /* 110 550 */まとめ
・関連性のないクラスの必要な処理を一つのクラスに既存クラスに修正を加えることなくまとめることができる部分が大きなメリットであると感じた。
・継承より委譲で使用したほうがもろもろ融通が効きそうな気がした(直感的にではあるが)