20201104のPHPに関する記事は24件です。

mac OSにPHP(MAMP)を設定する

以下のリンクをクリック

https://www.mamp.info/en/downloads/

赤枠で囲っている部分をクリック

スクリーンショット 2020-11-04 23.24.43.png

手順に沿ってインストールを実行します。

Applications/MAMP/conf/my.cnfにmysqlの設定をする。

スクリーンショット 2020-11-04 23.28.58.png

MAMPを開いてStart Serverを押す

スクリーンショット 2020-11-04 23.34.52.png

もしMySQLが 5.6以上になっていて、そのままではこの先進めない場合は、以下のように設定する

my.cnf
[mysqld]
sql_mode=NO_ENGINE_SUBSTITUTION
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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();
のようにしてHogemethod()を呼び出すことができます。

use App\Facades\Hoge;
と名前空間を記述しなくてもいいのは楽ですね。

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

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アプリケーションの概要

アプリケーション名:「ひとことすいせん」
学生・教授どうしで、図書館の本の感想を言い合う掲示板です。

主な機能

ユーザ関連

  • 記事の投稿(アカウント登録なし、メールで認証)
  • 投稿した内容の編集
  • 閲覧(一部)

図1.png

管理者側

  • 投稿内容の一覧(全て)
  • 初期投稿時の公開状態の設定権(公開・非公開・承認待ち)
  • 投稿された内容の公開状態の設定権(公開・非公開)
  • 閲覧ページの設定権(公開・非公開)

各機能の詳細&デモ

記事を投稿する機能

 記事が投稿されるまでの流れは、以下の図のようになっています。かいつまんで言うと、以下の3つのステップを踏んでいます。

  1. ユーザーが投稿画面で(自分の)メールアドレスを入力
  2. メールにtoken付のURLが送られる
  3. そのURLを踏んで投稿開始

図2.png

  • デモ

さっきの図の番号に対応する様子をスクショしました。
①ユーザーが投稿画面でメールアドレスを入力
図3.png
②token付のURLが送られる(赤い塗りつぶしは、管理者用メールアドレスです)
図4.png
③URLをクリックすると、投稿画面に行きます。そしてなんやかんや入力すると。。。
図5.png
④プレビューが表示されて、
図1.PNG
⑤入力内容が投稿されます。と同時に”コメントID”なるものを発行します。
図2.PNG
⑥そして、URLが無効かされます。
図3.PNG

記事を閲覧する機能

 上記した感じで、ユーザーがテキストベースの内容を入力します。ということは、HTMLの入力フォームからサーバーへ入力情報が送信された、ってことですね。(POSTで送ってます)
しかし、その内容には個人情報が含まれます。例えば、学籍番号とか、氏名、所属するクラスとかですね。それらは公開したくないわけです。なので、↓図のようにapacheで公開されてない領域にすべての情報を保存します。今回は、テキストファイル形式すべての情報を保管するようにしました。

図4.PNG
 そうする事によって、入力された情報が守られるわけです。原理的には、apacheというサーバーソフトが仲介人となって、渡してよいファイル・非公開なファイルを判別しているわけです。
図5.PNG
ちなみに、アクセス不可能な領域にアクセス(URLで指定)すると、こんな感じでエラーページが返ってきて、内容が確認できないようになっています。
図6.PNG

 という事なんですが、「それじゃ投稿した内容が見れないじゃないか!」ってツッコむと思うんですが、そこら辺の処理はPHPに任せています。図(↓)で表すとこんな感じですね、投稿内容が閲覧されるまでの手順としては、

1、ユーザーから閲覧ページ(PHP)が要求される。
2、PHPにより、サーバー内の”公開してもよい情報”のみを取り出す。
3、公開してもよい情報を、HTMLにしてユーザーに返す。

てな感じです。

図7.PNG

  • デモ

 そんなわけで、実際に閲覧ページに行くと、こんな感じで投稿内容が確認できます。サーバー上には個人情報がありますが、閲覧ページからのアクセスでは、それらの情報を取得することができないようになってます。

図8.PNG

記事を編集する機能

 ちらっと”コメントID”って言ってましたけど、これは、投稿内容につき1つ発行されるtokenの事です。これを知っているのは投稿した本人(と管理者)のみなので、これを使ってコメントの編集を行うようにします。
図9.PNG
 仕組みとしては↓のようになっていて、正しいコメントIDが入力されたら、対応するコメントの修正作業ができるって感じです。

図10.PNG

  • デモ

①正しいコメントIDを入力すると、
図11.PNG
②対応するコメントが表れて、
図12.PNG
③なんやかんや編集して、
図13.PNG
③それをプレビューして、
図14.PNG
④投稿内容を確認すると、編集がされているのがわかりますね。
図15.PNG

記事を管理する機能

 実装した機能の最後として、管理画面があります。説明に入る前に、コメントの状態について断っておきます。コメントの状態は「公開状態」・「非公開状態」・「承認待ち状態」の3つあるとします。公開状態ではコメントが閲覧可能で、非公開・承認待ち状態ではコメントの内容が見れないようになっています。

図17.PNG

そして、管理画面では以下の事が可能となっています。

1、コメント投稿時(初期値)の状態を設定できる。
2、投稿済みのコメントの状態を変更できる。
3、各画面自体の公開・非公開が変更できる(メンテナンス等のため)。

1と2の機能によって、コメントの内容が勝手に公開されない設定が可能になるのです。これで、このサイトの秩序が管理できるはず!という狙いです。例えば、初期状態を「承認待ち」にしておいて、管理者が投稿内容を確認して、問題なければ「公開状態」に変更する、みたいな事が可能になっています。

図16.PNG

また、3については、サイトのメンテナンス時とかに、不用意にアクセスされないための設定ができます。いつでも変更できて、もし閲覧ページが非公開にされると、↓のようになります。

図21.PNG

管理者ログイン方法

 最後に、管理者の管理画面のログイン方法ですね。これに関しては、下のように2段階認証?的なことをしています。流れとしては、

1、管理ログイン画面にてusernameとpasswordを入力。
2、正解だったら、”管理者用メールアドレス”に管理ログイン画面(2回目)を表示。
3、管理ログイン画面(2回目)にて、再度usernameとpasswordを入力。

となっています。ログインできる条件としては、”管理者用メールアドレスを持っている”ことと、”username&passwordを知っている”事になります。これによって、比較的安全にログインしよう!とのことです。また、管理ログイン画面(2回目)というのは、Token付きのURLの事で、1の時にTokenを発行して、メールに送られたURLのTokenと同じだったら2回目のログイン画面を表示する仕組みになっています。

図22.PNG

おわりに

 以上が、私の作った”敷居の高い掲示板”です。今回は概要なので、ざっくりとした設計の方針みたいなものをつらつらを書いてみました。今後は、これらの機能を具体的にどう実装するか?みたいな事を書いていけたらなと思います。
 皆さんのPHPの創作意欲の足しになってくれたらうれしいです。それでは!

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

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

1390

phpと同様の結果に。

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カプセル毎に個別で持つもの、外部からは一切アクセスできない」という認識があったので少し意外な処理だった。


  1. 上記コードでは出てこないが、$val->fc()$val->aに変えても実行できる 

  2. ここのサイトにて、node.jsのv12からという記述は確認。 

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

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 reviewer

L

Learning plan supervisor
Learning plan viewer
Learning plans
Learning plans block

メインページ

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

Moodle 3.9 マニュアル - ロールとパーミッション

原文

ロールとパーミッション

ロールは、特定のコンテキストで特定のユーザーに割り当てることができるシステム全体のために定義された権限のコレクションです。ロールとコンテキストの組み合わせは、特定のユーザーがどのページで何かをする能力を定義します。最も一般的な例は、コースのコンテキストにおける学生と教師のロールです。

ロールの管理:(翻訳準備中)
ロールの割り当て:(翻訳準備中)
ユーザーポリシー:(翻訳準備中)
ロールの使用:(翻訳準備中)
標準的なロール:(翻訳準備中)
カスタムロールの作成:(翻訳準備中)
ロールのエクスポートとインポート:(翻訳準備中)
パーミッション:(翻訳準備中)
パーミッションを上書きする:(翻訳準備中)

関連項目

ロールFAQ:(翻訳準備中)
2.0の新しいパーミッション評価:(翻訳準備中)

カテゴリ | サイト管理 | ロール

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

無料天気予報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

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

Laravel:Auth認証の設定

【概要】

1.手順

2.どのようにコーディングするか

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.phpusersテーブルが作成されます。

❹作成されたusersをマイグレーション
下記の通りマイグレーションを実行します。

$ php artisan migrate

するとDBにuserテーブルが作成されます。

❺Controllerにコーディング
use Illuminate\Support\Facades\Auth;
$user = Auth::user();
を記述して完了です。

app/Http/Controllers/xxxxController.php
use 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

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

Moodle 3.9 マニュアル - マネージャーのロール

原文

マネージャーのロール

目次

1 マネージャーロールの能力
2 サイトレベルでのマネージャーのロールの割り当て
3 カテゴリーレベルでのマネージャーのロールの割り当て
4 関連項目

1 マネージャーロールの能力

デフォルトの管理者ロールは、ロールに割り当てられたユーザーがコースにアクセスしてコースを変更するだけでなく、コース、ユーザー、グレード設定などに関連する管理レベルのタスクを実行することを可能にします。

管理者の役割とは異なり、マネージャーの役割は、あなたが編集することができますが、その機能は、その広いデフォルトの権限のために、管理者に似ています(しかし、はるかに安全に使用することができます) '本当の役割'です。通常の役割として、コース作成者や教師のように、マネージャーの役割は、デフォルトではほとんど非常に多くの機能を持っていますが、あなたが選択した場合は、その役割を編集することができます。

(Moodleコードでパーミッションチェックが機能する方法は、has_capabilityと呼ばれる関数があります。管理者にとって、ロールがどのように設定されているかにかかわらず、has_capabilityは常にtrueを返します。したがって、管理者がどのようなパーミッションを持っているかを編集する方法はありません。)

最小特権の原則に基づくベストプラクティスを採用することは、管理者は通常、管理者アカウントを使用せず、マネージャーアカウントを使用すべきであることを示唆しています。

したがって、管理者の役割は、サイト管理者が管理者の役割を割り当てられた他の人に非常に強力な役割を与えることを可能にしますが、完全な管理者の役割を与える必要はありません。

2 サイトレベルでのマネージャのロールの割り当て

サイト管理] > [ユーザー] > [権限] > [システムロールの割り当て] に進み、[マネージャーロール] を選択し、選択したユーザーの上に移動することで、サイト全体でマネージャーロールを与えることができます(例えば、新しいユーザーを追加できるようにするため)。

そうすると、そのロールのユーザーは、サイト管理の一部の項目にしかアクセスできなくなります。セキュリティ、サーバー、プラグイン、外観、または高度な機能などの領域にはアクセスできません。サイト管理者は、ユーザー、コース、グレードのシステム設定やツールのほとんどのツールにアクセスすることができます。

特に、サイト全体の管理者ロールは、サイト管理でこれらのツールを見ることができます。

   コンピテンシー
       フレームワークの移行
       インポートコンピテンシーフレームワーク
       輸出コンピテンシーフレームワーク
       コンピテンシーフレームワーク
       学習計画書のテンプレート
   バッジ
       バッジの設定
       バッジの管理
       新しいバッジを追加
   言語
       言語のカスタマイズ 
   外観
       デフォルトのダッシュボードページ
       デフォルトのプロフィールページ
       タグの管理
       ユーザーツアー
   フロントページ
       フロントページの設定
   利用者
       アカウント
          ユーザーの一覧を見る
          バルクユーザーアクション
          新しいユーザーの追加
          コホート
          ユーザーのアップロード
          ユーザーの写真をアップロードする
       アクセス許可
          役割の定義
          システムの役割を割り当てる
          システムのパーミッションを確認する
          能力の概要
          コホートにユーザーロールを割り当てる
   コースのご案内
       コースとカテゴリの管理
       カテゴリの追加
       復元コース
       バックアップ
          一般的なバックアップのデフォルト
          一般的なインポートのデフォルト
          バックアップの自動設定
   グレード
       一般的な設定
       グレードカテゴリの設定
       グレード項目の設定
       スケール
       成果(サイトで有効になっている場合
       レターズ
       レポート設定
          グレイダーレポート
          学年履歴
          概要レポート
          ユーザーレポート
    プラグイン
       質問の種類
          質問プレビューのデフォルト
   報告書
       コメント
       バックアップ
       ログ
       ライブログ
       パフォーマンスの概要
       セキュリティの概要
       統計(サイトで有効になっている場合
       イベント監視ルール

注意事項。

・これらのいくつかは、さらに役割の特定の機能を編集することによって制限することができます、例えば、ユーザーを作成し、ファイルからユーザーをアップロードするには、手動で登録、コホートの管理、言語のカスタマイズなど、など。
・マネージャーは、他のコースと同じようにフロントページへのアクセス権を持っています(技術的にはコースです)。
・マネージャーはほとんどのシステムレベルのレポートにアクセスできますが、設定レポートにはアクセスできません。
・マネージャーはサイト全体のマネージャーとして他のユーザーを割り当てることができます。
・また、マネージャはマネージャ自身のロールを編集する機能を持っています - これを無効にするには、ロールの作成と管理機能を禁止することができます。

3 カテゴリーレベルでのマネージャーのロールの割り当て

管理者の役割は、サイト全体ではなく、コンテキストのカテゴリに割り当てることもできます。

1つのカテゴリ内のすべてのコースにアクセスして管理できるようにしたいが、サイト管理ツールにはアクセスできないようにしたい場合に使用します。

次のように割り当てます。サイト管理 > コース > コースの追加/編集 > (カテゴリを選択) > このカテゴリの編集 > 管理ブロック。ロールの割り当て > 管理者 > (ユーザーを選択) 追加

注意事項。

・カテゴリレベルの管理者は、割り当てられたカテゴリのためだけに存在します:複数のカテゴリを管理するためには、各カテゴリで個別にその役割を割り当てる必要があります。
・カテゴリレベルの管理者は、新しいサブカテゴリの作成やコースの移動など、割り当てられたカテゴリの下にあるサブカテゴリも管理します。
・割り当てられたカテゴリでコースを作成することができます。
・カテゴリレベルのマネージャは、サイトレベルのマネージャほど多くの機能を持ちません。なぜなら、特定の機能はシステムコンテキスト、すなわちシステムロールを介してのみ適用できるからです。
他のユーザーとしてログインするケイパビリティについては、管理するカテゴリ内のコースについては、カテゴリレベルの管理者は、他のコース参加者としてログインし、そのコース内でのみ閲覧することができます。

いくつかのコマンドで管理ブロックにあることに注意してください。管理者は、カテゴリの編集とカテゴリの追加リンクを持つために、編集をオンにしなければなりません。以下のスクリーンショットは、編集をオンにしたカテゴリレベルのマネージャーの管理ブロックのビューで、このカテゴリの編集とサブカテゴリの追加のコマンドが表示されています。
category-level-manager-settings.png
category-level-manager-settings.png

4 関連項目

サイト管理者

カテゴリ | ロール

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

unicode正規表現サンプル

unicode正規表現サンプル

毎回調べるのが面倒なので、自分が使いそうなunicode正規表現を記事にしておく...

概要 unicode正規表現
漢字ひらがな \u30a0-\u30ff\u3040-\u309f\u3005-\u3006\u30e0-\u9fcf
全角スペース \u3000
全角アルファベット大文字 \uFF41-\uFF5A
全角アルファベット小文字 \uFF21-\uFF3A
全角数字 \uFF10-\uFF19

参考

https://www.tamasoft.co.jp/ja/general-info/unicode.html

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

[検証] コードをもとにコードを書くコードを書きたい ~ 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.php
    private $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.php
    public 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.php
require '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をもとにクラスのひな型を作る、あまり面白みのないやつですが、ここからより実践的なものに発展させていければと思います。

こんなところですかね。

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

[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.

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

Moodle 3.9 マニュアル - サイト管理者

原文

サイト管理者

サイト管理者は何でもできる権限を持っています。

ユーザーは、「サイト管理」>「ユーザー」>「権限」>「サイト管理者」で、他のサイト管理者からサイト管理者のロールを割り当てられることがありますが、その役割自体を編集(または削除!)することはできません。プライマリ管理者(サイト作成時に作成された)は、サイト管理者ロールから削除することはできません。

あなたのサイトにはたくさんの管理者を置かないことをお勧めします。管理者は1人か2人だけにして、他の全員にマネージャー:(翻訳準備中)のようなロールを与え、必要な権限だけを与えるのが良い方法です。
Managesiteadministrators.png
Managesiteadministrators.png

MNetを使用している場合は、「管理者のロールの割り当て」を参照してください。

カテゴリ | ロール

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

【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の学習をしておけばよかった
  • 使うフレームワークや言語がわかったら、どんなに期間が短くても深く学んでおけばよかった
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Moodle 3.9 マニュアル - 機能

原文

機能

Moodleは無料のオンライン学習管理システムで、教育者がいつでも、どこでも、学習を拡張するダイナミックなコースで満たされた独自のプライベートウェブサイトを作成することを可能にします。

あなたが教師、学生、管理者であるかどうかにかかわらず、Moodleはあなたのニーズを満たすことができます。Moodleの非常にカスタマイズ可能なコアは、多くの標準機能を備えています。以下のMoodleのコア機能のハイライトをご覧ください。また、LMS、Moodleアプリ、オフライン機能を比較した学生向けMoodle機能 (pdf) をダウンロードしてください。

一般的な機能

モダンで使いやすいインターフェイス

レスポンシブでアクセスしやすいように設計されたMoodleのインターフェースは、デスクトップとモバイルデバイスの両方で簡単に操作できます。
432px-Moodle_Modern_Interface2_March_2017.png
デモを見る

パーソナライズされたダッシュボード

現在のコース、過去のコース、将来のコースをタスクと一緒に表示します。
432px-Dashboard35+.png
ダッシュボード

連携ツールと活動

フォーラム、Wiki、用語集、データベース活動などで一緒に学びましょう。
432px-FeaturesForum.png
活動内容

オールインワンカレンダー

Moodleのカレンダーツールは、学業や会社のカレンダー、コースの締め切り、グループミーティング、その他の個人的なイベントを管理するのに役立ちます。
432px-FeaturesCalendar.png
カレンダー:(翻訳準備中)

便利なファイル管理

MS OneDrive、Dropbox、Google Driveなどのクラウドストレージサービスからファイルをドラッグ&ドロップします。
432px-FileManagementNewFeatures.png
ファイルの操作:(翻訳準備中)

シンプルで直感的なテキストエディタ

すべてのウェブブラウザやデバイスで動作するエディタでテキストをフォーマットし、メディアや画像を簡単に追加できます。
432px-TextEditorFeatureNew.png
テキストエディタ:(翻訳準備中)

お知らせ

この機能を有効にすると、ユーザーは新しい課題や締め切り、フォーラムの投稿などの自動アラートを受信したり、プライベートメッセージを送信したりすることができます。
432px-NotificationsFeaturesNew.png
メッセージング:(翻訳準備中)

進捗状況の追跡

教育者や学習者は、個々の活動やリソース、コースレベルでの進捗状況や修了状況を追跡するためのさまざまなオプションを使用して追跡することができます。
432px-AcitivityReportFeaturesNew.png
進捗状況の追跡:(翻訳準備中)

機能の完全なリストを表示する→

管理機能

カスタマイズ可能なサイトデザインとレイアウト

あなたのロゴ、カラースキーム、その他多くの要素でMoodleテーマを簡単にカスタマイズすることができます - または、あなた自身のテーマをデザインするだけです。
432px-CustomTheme17.png
テーマ:(翻訳準備中)

セキュアな認証と大量登録

あなたのMoodleサイトおよびコースにユーザを追加および登録するための50以上の認証および登録オプション。
432px-EnrolmentFeaturesNew.png
認証/登録

多言語対応

ユーザーがコースの内容を表示したり、自分の言語で学習したり、多言語のユーザーや組織のために設定したりすることができます。
432px-MultiLingualFeaturesNew.png
言語:(翻訳準備中)

コースの一括作成と簡単なバックアップ

一括でコースを追加し、簡単に大規模なコースをバックアップして復元することができます。
432px-CourseUploadFeaturesNew.png
一括コースアップロード:(翻訳準備中)

ユーザーの役割と権限の管理

ユーザーのアクセスを指定して管理するロールを定義することで、セキュリティ上の問題に対処します。
432px-RolesFeaturesNew.png
ロールとパーミッション:(翻訳準備中)

オープンスタンダードをサポート

IMS-LTI、SCORMコースなどをMoodleに簡単にインポートおよびエクスポートできます。
432px-StandardsFeaturesNew.png
標準:(翻訳準備中)

高い相互運用性

外部アプリケーションやコンテンツを自由に統合したり、独自のプラグインを作成してカスタム統合を行うことができます。
432px-LTIFeaturesNew.png
SCORM / 外部ツール

シンプルなプラグイン管理

単一の管理者インターフェース内でプラグインをインストールしたり、無効にしたりすることができます。
432px-PluginsFeaturesNew.png
プラグインのインストール

定期的なセキュリティアップデート

Moodleは定期的に最新のセキュリティパッチで更新されており、お客様のMoodleサイトの安全性を確保しています。
432px-SecurityFeaturesNew.png
セキュリティ:(翻訳準備中)

詳細なレポートとログ

コースとサイトレベルでの活動と参加に関するレポートを表示し、生成します。
432px-LogsFeaturesNew.png
サイト全体のレポート:(翻訳準備中)

すべてのサイト管理・開発機能を見る→サイト管理・開発機能を見る

コース開発・運営の特徴

ダイレクトラーニングパス

様々な要件を満たすためにコースをデザインし、管理します。インストラクターによる授業、自分のペースで進められる授業、ブレンデッド授業、完全オンライン授業などがあります。
432px-LearningPathFeatures1New.png
教育学

連携を促す

内蔵されたコラボレーションパブリッシング機能は、エンゲージメントを促進し、コンテンツ主導のコラボレーションを促進します。
432px-CollaborativeFeaturesNew.png
活動

外部リソースを埋め込む

他サイトの教材を教えたり、課題を盛り込んだり、Moodleの成績表に接続したりすることができます。
432px-LTIFeaturesNew (1).png
外部ツール

マルチメディア統合

Moodleのビルトインメディアサポートにより、あなたのコースにビデオやオーディオファイルを簡単に検索して挿入することができます。
432px-InsertMediaFeaturesNew.png
メディアとの連携:(翻訳準備中)

グループの管理

コースを共有し、活動を差別化し、チームワークを促進するためのグループ学習者。
432px-GroupsFeaturesNew.png
グループ:(翻訳準備中)

マーキングワークフロー

便利なように課題に異なるマーカーを割り当て、評定の修正を管理し、個々の学習者にマークが公開されるタイミングをコントロールすることができます。
432px-MarkingWorkflowFeaturesNew.png
課題モジュール:(翻訳準備中)

インラインマーキング

ブラウザ内で直接ファイルに注釈を付けることで、簡単にレビューし、インラインフィードバックを提供することができます。
432px-GradingFeaturesNew.png
課題モジュール:(翻訳準備中)

ピアと自己評価

ワークショップやアンケートなどのアクティビティが組み込まれており、学習者は自分や他のコースメンバーの作品をグループで見たり、評価したりすることができます。
432px-PeerSelfAssessmentFeaturesNew.png
ワークショップ:(翻訳準備中)

統合されたバッジ

Mozilla Open Badgesと完全に互換性があり、カスタマイズされたバッジで学習者のモチベーションを高め、参加と成果に報います。
432px-BadgesFeaturesNew.png
バッジ

アウトカムとルーブリック

高度なグレーディング方法から選択して、あなたのカップルに合わせてグレーディングブックを作成します。
432px-RubricFeaturesNew.png
評定:(翻訳準備中)

コンピテンシーに基づくマーキング

コースや活動にまたがる個人学習計画でコンピテンシーを設定します。
432px-CompetenciesFeaturesNew.png
コンピテンシー:(翻訳準備中)

セキュリティとプライバシー

自分と自分のクラスだけがアクセスできるプライベートスペースで教えて共有することができます。
432px-SecureEnrolmentFeaturesNew.png
コース

コース作成・管理機能を全て見る→コース作成・管理機能を全て見る:(翻訳準備中)

カテゴリ | Moodle について

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

【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ではオブジェクトはデフォルトで参照渡しです。これも注意しましょう。

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

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」とする。
  • 本記事の作業完了したソースは下記にアップしてある。

概要

  1. データベースの作成
  2. Laravelアプリ作成
  3. .envファイルの修正とシンボリックリンクの作成
  4. ルーティング情報の記載
  5. マイグレーションファイルの記載とマイグレート
  6. モデルファイルの修正
  7. コントローラファイルの作成と記載
  8. ビューファイルの作成と記載
  9. 確認

詳細

  • 下記の説明で実行するコマンドはすべてMacのローカルのターミナルで実行するものとする。
  1. データベースの作成

    1. 下記コマンドを実行してMySQLにログインする。(MySQLのパスワードがわからなくなってしまった方はこちら→Mac ローカル環境の MySQL 8.x のrootパスワードを忘れた時のリセット方法

      $ mysql -u root -p
      
    2. 下記SQLを実行してデータベース「Laravel6_image」を作成する。

      create database laravel6_image;
      
    3. 下記SQLを実行して結果に「laravel6_image」があることを確認してMySQLからログアウトする。

      show databases;
      
  2. Laravelアプリ作成(下記のアプリ作成実行直後のソースはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/01_create_app

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

      $ composer create-project "laravel/laravel=6.*" laravel6_image
      $ cd laravel6_image
      
  3. .envファイルの修正とシンボリックリンクの作成

    1. 下記コマンドを実行してLaravelの設定ファイルを開く。

      $ vi .env
      
    2. 下記のように内容を記載修正する。

      APP_NAME=laravel6_image
      
      DB_DATABASE=laravel6_image
      DB_USERNAME=root
      DB_PASSWORD=皆さんのMySQLのrootユーザのパスワード
      
      FILESYSTEM_DRIVER=public
      
    3. 記載修正した筆者の.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}"
      
    4. 下記コマンドを実行してデフォルトマイグレーションファイルのマイグレートを実行する。

      $ php artisan migrate;
      
    5. 下記コマンドを実行してシンボリックリンクの作成を行う。

      $ php artisan storage:link
      
    6. 下記コマンドを実行してローカルサーバを起動する。

      $ php artisan serve
      
    7. 下記にアクセスして下記画像の画面が表示されることを確認する。

  4. ルーティング情報の記載(本作業完了後のソースコードはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/02_route

    1. 下記コマンドを実行してルーティングファイルを開く。

      $ vi routes/web.php
      
    2. 下記の内容を追記する。

      laravel6_image/routes/web.php
      // 画像アップロードページ用
      Route::get('/input', 'ImageController@input')->name('input');
      
      // 画像アップロード処理用
      Route::post('/upload', 'ImageController@upload')->name('upload');
      
    3. 記載後のルーティングファイルの全内容を下記に記載する。

      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');
      // 上記までを追記
      
  5. マイグレーションファイルの記載とマイグレート(本作業完了後のソースコードはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/03_migrate

    1. 下記コマンドを実行してモデルファイルとマイグレーションファイルを一緒に作成する。

      $ php artisan make:model Models/Image -m
      
    2. 下記コマンドを実行してマイグレーションファイルを開く。(YYYY_MM_DD_XXXXXXはマイグレーションファイルの作成日時)

      $ vi database/migrations/YYYY_MM_DD_XXXXXX_create_images_table.php
      
    3. upメソッドの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();
      
    4. 記載後のマイグレーションファイルの全内容を下記に記載する。

      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');
          }
      }
      
      
    5. 下記コマンドを実行してマイグレートする。

      $ php artisan migrate
      
  6. (本作業の意図はこちら→Laravel テーブル内のデータ削除を論理削除にする)(本作業完了後のソースコードはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/04_model

    1. 下記コマンドを実行してモデルファイルを開く。

      $ vi app/Models/Image.php
      
    2. 下記の内容を追記する。

      laravel6_image/app/Model/Image.php
      use Illuminate\Database\Eloquent\SoftDeletes;
      // Imageクラス内に下記を追記
      use SoftDeletes;
      
    3. 記載後のモデルファイルの全内容を下記に記載する。

      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;
      }
      
  7. コントローラファイルの作成と記載(本作業完了後のソースコードはこちら→https://github.com/miriwo0104/laravel6_image/tree/image_upload_local/05_controller

    1. 下記コマンドを実行してコントローラファイルを作成する。

      $ php artisan make:controller ImageController
      
    2. 下記コマンドを実行して作成したコントローラファイルを開く。

      $ vi app/Http/Controllers/ImageController.php
      
    3. 下記のようにコントローラファイルの内容を追記・修正する。追記修正後のコントローラファイルの全体の内容を下記に記載する。(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'));
              }
      
          }
          // 上記までを追記する
      }
      
  8. ビューファイルの作成と記載(本作業完了後のソースコードはこちら→

    1. 下記コマンドを実行してビューファイルを格納するディレクトリを作成する。

      $ mkdir -p resources/views/images
      
    2. 下記コマンドを実行してビューファイルを作成して開く。

      $ vi resources/views/images/input.blade.php
      
    3. 下記の内容をビューファイルに記載する。

      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>
      
  9. 確認

    1. 下記コマンドを実行してローカルサーバを起動する。

      $ php artisan serve 
      
    2. 下記にアクセスする。

    3. 下記のページが表示されたことを確認する。

      127_0_0_1_8000_input.png

    4. 「ファイルを選択」をクリック後任意の画像ファイルを選択し「送信」をクリックする。

      127_0_0_1_8000_input.png

    5. エラーが出ずhttp://127.0.0.1:8000にリダレクトされることを確認する。

      Laravel.png

参考文献

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

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;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Moodle 3.9 マニュアル - カテゴリ:Moodle について

原文

カテゴリ:Moodle について

Moodleについての紹介ページのインデックスです。
カテゴリー「Moodleについて」のページ

全23ページ中、このカテゴリには以下のページがあります。

A

About Moodle
About Moodle FAQ
Accessibility
Awards

B

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 structure

N

New features
New for administrators
New for students
New for teachers

P

Pedagogy
Philosophy

S

Standards

U

Usage
User quick guide

メインページ

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

Moodle 3.9 マニュアル - バッジ

原文

バッジ

バッジは達成を祝い、進歩を示す良い方法です。バッジは選択された様々な基準に基づいて授与され、ユーザのプロフィールに表示されるか、Badgrのバックパックにプッシュすることができます。

バッジには2つのカテゴリがあります。

・サイトバッジ - サイト全体で利用可能で、サイト全体の活動に関連しているユーザが利用できます。
・コースバッジ - コースに登録されているユーザが利用でき、コース内で行われる活動に関連しています。
badgesintro.png
badgesintro.png

バッジの管理
バッジの設定
バッジの使用
バッジFAQ

カテゴリ | バッジ

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

Moodle 3.9 マニュアル - カテゴリ:バッジ

原文

カテゴリ:バッジ

Moodle 2.5以降のバッジに関するドキュメントページのインデックスです。
バッジ」カテゴリのページ

全21ページのうち、このカテゴリには以下のページがあります。

バッジ

B

Badges (日本語訳:バッジ)
Badges FAQ
Badges settings

C

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:viewotherbadges

L

Latest badges block

M

Managing badges

U

Using badges

メインページ

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

素のPHPでTwitterの文字数カウントを再現

経緯

一括ツイートサービスの制作に際して「全角:1/半角と改行:0.5/URL:11.5」という、公式の文字数カウントに近いPHPコードを模索したので共有させて頂きます。

コード

  • 全角を1文字/半角を0.5文字とカウント
count.php
function twiCount( $text ){
  $wholeLen = strlen(mb_convert_encoding($text, "SJIS", "ASCII,JIS,UTF-8,EUC-JP,SJIS")) / 2;
  return $wholeLen;
}
  • 改行を0.5文字とカウント
count.php
function 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.php
function 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文字と判定(例:「―」)


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

【初心者向け】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.php
class 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.php
class 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

以上

テーブルが作成されているか、確認してみてください。

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

※学習用メモ デザインパターン: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.html

Adapterパターンを用いるメリット

・既存のクラスに対して修正を加えることなく、インタフェースを変更することができる。
・既存のクラスをもう一度動作テストする必要がなくなる
・Adapterパターンによってバグが発生しても、既存のクラスには変更を加えていないためバグがないことが保証される

サンプルコード

仕様

消費税を計算する。ゲームとかでアイテムやガチャを販売する際の値段に税率を反映させたい。
詳細は以下。
・原価管理のクラス(adaptee):Cost
・消費税計算後(adapter):CostIncludingComsumptionTax
・消費税計算後のクラスのインターフェース(target):CostIncludingComsumptionTaxInterface

今回は同様な仕様で、継承を利用したもの、委譲を利用したものを記載する。

継承を利用したパターン

CostIncludingComsumptionTaxInterface
interface CostIncludingComsumptionTaxInterface {
    public function getItemCostIncludingComsumptionTax();

    public function getGachaCostIncludingComsumptionTax();
}
Cost.class.php
class Cost {
    private $itemCost = 100;
    private $gachaCost = 500;

    // アイテムの費用取得
    public function getItemCost()
    {
        return $this->itemCost;
    }

    // ガチャの費用取得
    public function getGachaCost()
    {
        return $this->gachaCost;
    }
}
CostIncludingComsumptionTax.class.php
class 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.php
class 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
*/

まとめ

・関連性のないクラスの必要な処理を一つのクラスに既存クラスに修正を加えることなくまとめることができる部分が大きなメリットであると感じた。
・継承より委譲で使用したほうがもろもろ融通が効きそうな気がした(直感的にではあるが)

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