January 6, 2016
Regular expression
■正規表現
最長一致
一番長いものにマッチするので意図しないものが置換されがち
ABC (c) & DEF (c)でABC (c)にマッチさせたいとき、
ABC.*)の代わりにABC[^)]*がベターとかそういうこと
.* 繰り返し
.+ 1文字以上
[a-zA-ZO-9][a-zA-ZO-9] 英数2文字 → A1等
[a-zA-ZO-9]+\.jpg JPGファイル
\$100 \でエスケープ → $100
\\100 エスケープをエスケープ → \100
^ 行頭 ^# → #から始まる
[^] 否定 [^a-z] → aからz以外
$ 行末 jpg$ → jpgで終わる行
. 任意の1文字 ... → 3文字
* 直前文字の0回以上の繰り返し a* → aとか とかaaaaとか
シェル)0文字以上の任意の文字 *.pdf → pdfファイル
? 直前文字の1文字か0文字 all? → allかal
シェル)任意の1文字 ??? → 3文字
+ 直前文字1回以上の繰り返し a+ → aとかaaaaとか
- 範囲(文字コード上の) [0-2] → 0か1か2
[] いずれか1文字 [012] → 0か1か2
| いずれかの文字 slee|ap → sleeかap(前後文字をまとめて判断)
() まとまり sle(e|a)p → sleepかsleap
\< 単語の先頭境界 \<no → nothingやnobody等
\> 単語の末尾境界 \<no\> → noのみ
{min, max} 繰り返し回数の範囲 e{2,5} → eeやeeeeeやbeepやdeep等
シェル)リスト展開 e{2,5} → e2とe5
\b 空文字
\d 数字1文字 [0-9]
\D 数字1文字以外 [^0-9]
\s 空白文字(改ページ、改行、タブを含む)[ \f\n\r\t]
\S \s以外
\w アルファベット数字 [a-zA-ZO-9]
\W アルファベット数字以外 [^a-zA-ZO-9]
■-の範囲は文字コード上
なのでEBCDICコード(IBMEBCDICカナ)の[A-Z]は$}を含む、[A-IJ-RS-Z]が正しい
なのでposixのブラケットが安全[[:alnum:]]
■サンプルは検索すると早いが
https://murashun.jp/blog/20190215-01.html#chapter-3
■デバッガー
https://www.debuggex.com/
■Winのワイルドカード
? 1文
* 1文字以上
■オラクルSQL
% NULLを除く0文字以上の任意の文字列にマッチ
_ 任意の1文字にマッチ
■本(正規表現の達人)を見よ
シェルのメタキャラクタを使う(リストを見やすく)
シェルのメタキャラクタを使う(ファイル名を補完)
コマンドの検索パターンとして使う(条件検索)
メールアドレスを抽出する
メールアドレスを抽出する(もっと厳密に)
メールアドレスを抽出する(Perlで)
コメン卜行・空行を削除する
マッチした文字列を抽出する(Perlで)
コメント行・空行を削除する(厳密に)
コメント行・空行を削除する(Perlで)
コメン卜行・空行を削除する(Cのソースコードから)
改行コードを変燥する(Win⇔UNIX⇔Mac)
電話番号をチェックする(簡易版)
時刻を条件にロクファイルをチェックする
HTMLファイルから見出しを抽出する
HTMLファイルから見出しを抽出する(さらに加工)
HTMLファイルの記述を修正する
郵便番号のチェック(Webフォームで)
英小文字からなる文字列にマッチする正規表現は?
西暦の年月日を「年/月/日」の形式で表す正規表現は?
‘daemon'と‘demon'の両方にマッチする正規表現は?
タブで区切られた2つの項目を入れ替え、カンマ区切りにするには?
メールボックスファイルからメールアドレスを抽出するには?
メールアドレスのユーザ名を厳密にチェックするには?
メールアドレスのドメイン名を厳密にチェックするには?
Perlで変数に格納されている文字列と正規表現がマッチするかとごうかテストするには?
JavaScriptで、変数に格納されている文字列と正規表現がマッチするかどうかテストするには?
シェルスクリプトからコメント行空行を削除するには?
正規表現にマッチした文字列から必要な部分だけ抽出するには?
余分なスペスを取り除くには
Cのソースコードからコメント行空行を削除するには?
複数行にまたがったコメントを取り除くには?
正規表現を使って改行コードを変換するには?
電話番号をチェックするには?
時刻をチェックするには?
郵便番号をチェックするには?
HTMLの見出しタグに困まれたデータを取り出すには?
HTMLファイルの記述をまとめて修正するには?
sedで前方参照を使うには?
大文字小文字の区別を無視するには?
sedでパタンの区切り文字「/」を変更するには?
Perlでパタンの区切り文字「/」を変更するには?
ファイル名がある範囲の文字で、終わっているファイルを表示するには?
長いファイル名を入力する手聞を省くには?
「.」「..」を含み、「.」からはじまるファイル名のファイルを表示するには?
「.」「..」は含まずに、「.」からはじまるファイル名のファイルを表示するには
多量の画面出力に対して、ページ単位でスクロールを止めるには?
画面出力をファイルに保存するには?
編集前と編集後のデータを比較するには?
元のファイルからどれくらいデータが抽出されたか調べるには?
データをソー卜するには?
重複するデータをlつにまとめるには?
findコマンドの検索条件にメタキャラクタを使うには?
入力行の指定した文字位置から指定したフィルドを切り出すには?
egrepコマンドで、検索条件にマッチした行円以外"を表示するには?
viで複数ファイルを編集するには?
viの検索パタンに正規表現を使うには?
trコマンドで空行を削除するには?
viで、改行コードを変換するには?
trコマンドで改行コードを変換するには?
■改行コード
\n(LF):Unix系OS全般、Mac OS X
\r\n(CR+LF):Windows系OS
\r(CR):古いMac OS(9以前)
Posted by funa : 01:27 AM
| Web
| Comment (0)
| Trackback (0)
January 5, 2016
Javascript
varを省略した場合は関数内での宣言であってもグローバル変数(window.と同じ)
関数外のvarはグローバル変数
関数内のvarのみローカル変数(だが、関数の中に関数を作るとスコープチェーンによって、内側のローカル変数から順に探していくので、関数の外からは見えないが関数の内からはアクセスされる恐れはある)
関数を変数の様に書ける(無名関数)、スコープチェーンやレンダリングが関係している(後述)
//関数式による定義、JSは全てobjでありobjを受け取ってその中のメソッドを使う、New不要のケース
create_row = function(){
var tbody = document.getElementById("input_tbody");
var new_row = tbody.insertRow(num_row+1);
var cell1 = new_row.insertCell(0);
var copy = function(cell,tb,arg){
cell.innerHTML = tb.rows[num_row].cells[arg].innerHTML;
}
return {tbody: tbody, cell1: cell1, copy: copy};
};
copy_cell = function(obj_create_row){
obj_create_row.copy(obj_create_row.cell1, obj_create_row.tbody, 0);
};
//ここからフロー
num_row = 1;
setTimeout(function(){
console.log('setTimeOut');
obj_cr = create_row();
copy_cell(obj_cr);
num_row++;
}, 2000);
//ここからHTML
<table border=1>
<thead><tr><th>Items</th><th>Expenditure</th></tr></thead>
<tbody id="input_tbody"><tr><th>Pen</th><td>3,000</td></tr>
<tr><th>Eraser</th><td>1,000</td></tr></tbody>
</table>
ココから改めて追記する形でJavascriptの学び直し
///基礎文法
http://gifnksm.hatenablog.jp/entry/20100131/1264934942
一番下にリンク集がある、コメントも仕様が分かり参考になる
https://language-and-engineering.hatenablog.jp/entry/20100111/p1
///オブジェクト
https://www.wakuwakubank.com/posts/464-javascript-array-object-pattern/
オブジェクトは連想配列ようである、なおJSには配列[]/オブジェクト{}/JSON[{"":""},{"":""}]を使う
var obj = {a: 1, b: 2};
for - in は連想配列に使う(for in は配列にはダメ)
for - of は列挙可能なオブジェクト(配列等)に使う
for (var i in obj) {
alert(obj[i]);
}
for each (var v in obj) {
alert(v);
}
オブジェクトにはメソッドも付与しカプセル化可
var man = {
time: 0,
gettime: function() { this.time = new Date(); },
hello: function() { alert(this.time + 'hello!'); },
};
man.gettime();
man.hello();
///インスタンス化
ファンクションでクラスを宣言(←古い。Classが実装される前の話)
https://so-zou.jp/web-app/tech/programming/javascript/grammar/function/class/
function Image() {
this.width = 0;
this.height = 0;
this.src = '';
}
実はそれにはプロトタイプもあるので足せる(蛇足になるのでリンク等を参照)
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
Image.prototype.type = 'image object';
Image.prototype.width = null;
Image.prototype.height = null;
Image.prototype.src = null;
Image.prototype.resizeTo = function(aNewWidth, aNewHeight) {
this.width = aNewWidth;
this.height = aNewHeight;
};
まとめて下記の書き方もできる
Image.prototype = {
type : 'image object',
width : null,
height : null,
src : null,
resizeTo : function(aNewWidth, aNewHeight) { alert(aNewWidth + aNewHeight); }
};
newでコンストラクタでのインスタンス化する
var img = new Image();
img.resizeTo(30, 40);
///無名関数、匿名関数、クロージャ、関数式
https://www.sejuku.net/blog/25026
クロージャとは関数とその関数が定義された状態をセットにした特殊なオブジェクト
var メソッド名的変数 = function(引数) { /*処理*/ } あるいは他メソッド(function(引数) { /*処理*/ });等で直使用
メリットとして
極力グローバルの変数や関数を使わなくて済む
余計な関数名や変数名を考えなくても済む
無名関数は式が実行されるときにFunctionオブジェクトが生成される
無名関数は定義より前では呼び出せない(定義した所で呼び出すので混同がなく安全と考えられる)
Javascriptは同名をオーバーライドする
旧来の関数宣言は定義より前に実行が書かれていても呼べる
どの関数が使われるか注意が必要(便利だが大規模では危険と考える場合も)
手続き型ではこうだが、
<html>
<head>
<script type="text/javascript">
function button1Click(){
alert(1);
}
function windowOnload(){
var button1 = document.getElementById("button1");
button1.onclick = button1Click;
}
</script>
</head>
<body onload="windowOnload()">
<form name="foo">
<input type="button" id="button1" value="1">
</form>
</body>
↓無名関数ではこう
<script type="text/javascript">
window.onload = function(){
document.getElementById("button1").onclick = function(){
alert(1);
};
};
</script>
//下記は無名関数を変数に入れているので実行自体はされない
実行結果を入れている分けではない、なお実際は変数名が関数名だが
var hello = function(){alert("Hello");};
//これなら実行される、ほかにも即時関数の書き方がある
setTimeout(function(){ alert("Aloha"); },1000);
///即時関数
functionから始まる関数定義そのものを()でくくって(arg)を付けて即実行できる
普通()だが関数式と評価されればいいので、!でも同じ、+-でもOK
(function(){ /*処理*/ })();
<script>
var sum = (function(a,b){
var result = a + b;
return result;
})(1,2);
alert(sum);
!function(a,b){
let result = a + b;
alert(result);
}(3,4);
+function(a,b){
let result = a + b;
alert(result);
}(5,6);
</script>
///上記重複だがclassが導入されたES6より前の書き方(Classがないver)
https://www.yunabe.jp/docs/javascript_class_in_google.html
関数には関数式(無名関数)と関数宣言の2通り
関数宣言は旧来のfunction name(){}の方法
下記例が関数式
//関数式でのクラス、これはnewが必要だった
var Person = function(name, age) {
this.name = name;
this.age = age;
};
var alice = new Person("Alice", 7);
console.log(alice.name); // Alice
//これならnewは不要
var Person = function() {
return { name: "alice", age: 7 };
};
var alice = Person();
console.log(alice.name); // Alice
//オブジェクトでの継承、オブジェクトではnewが不要
var sayHelloShared = function() {
console.log("Hello, I'm " + this.name);
};
var alice = {
sayHello: sayHelloShared,
name: "Alice"
};
var bob = {
sayHello: sayHelloShared,
name: "Bob",
child: alice
};
alice.sayHello(); // Hello, I'm Alice
bob.sayHello(); // Hello, I'm Bob
bob.child.sayHello(); // Hello, I'm Alice
//new必要?
エラーがでなければ不要といえるのでは、、、
newするとコンストラクタで明示的初期化がされインスタンスも作られるが、、、
Javascriptは全てがオブジェクトであり、newを要不要は仕様でなく使い方の範疇のようで、それゆえ、functionでクラス化したり、メソッドを定義したり、無名関数だったりできる、、、newもエラーがでなければ不要かと
//扱い注意
thisが指す対象が、objが参照で別実態だったり、タグ要素であったりで注意が必要
console.logに出して確認するといいかも
メソッド内で使われている this が指すものは呼び出され方によって変わる
obj.hoge(); の形で呼び出された場合thisはobjになり
hoge();の形で呼び出された場合はthisは window (グローバルオブジェクト) になります
https://so-zou.jp/web-app/tech/programming/javascript/grammar/function/class/
別実態
var Person = function(a, b) {
return { name: a, age: b };
};
var alice = new Person('Alice', 7);
var takahashi = new Person('Takahashi', 6);
takahashi = alice;
console.log(takahashi.name); //Alice
///ECMAScript 6 (ES6) でクラスの構文が追加
クラス構文にはクラス宣言とクラス式という 2 つの定義方法
クラス宣言の方法
class Teki{
constructor(name, hp){
this.name = name;
this.hp = hp;
}
attack(){
console.log(`${this.name}の攻撃!`);
}
}
class Dragon extends Teki{
hello(){
console.log(`${this.name}のHPは${this.hp}です。`)
}
}
var boss = new Dragon('どらごん', 3000);
boss.attack(); // どらごんの攻撃!
boss.hello(); // どらごんのHPは3000で
こちらがクラス式
var Foo = class {
hello(){
console.log("Hi!");
}
};
var obj = new Foo();
obj.hello();
///可変変数(変数名に変数を使いたいとき)はevalで変数を含んで実行する
var new_div = eval('document.querySelector(\'#item' + settings.num_item + '\')');
eval('window.item' + settings.num_item + ' = new classItem;');
エスケープは円マーク
indow.a とwindow.を付けるとグローバルになる(関数の中からグローバル変数を作る等)
//タグ要素を取得、cssセレクタで指定
document.querySelector('#main .posts h1'); //最初の一つを取得
document.querySelectorAll('a'); //すべて取得
///実行の順番
https://kde.hateblo.jp/entry/2017/05/20/212928
https://www.javadrive.jp/javascript/ini/index2.html
ブラウザはスクリプトが記述されたHTMLファイルを順に解析しながらブラウザに表示。その途中に<script>要素が現れるとHTMLの解析を一時中断し、そのスクリプトが実行されるのを待ちます。そしてスクリプトの実行が終了すると続きからHTMLを実行していきます
Javascriptは同名をオーバーライドします
そのためwindow.onload = function(){は、複数あってもオーバーライドで一番下だけ実行する
外部ソースにwindow.onload = function(){ があってもトータルでどれか一つしか実行されない
window.onload = function(){
alert('1');
}
window.onload = function(){
alert('2');
}
テストしました
<html>
<head>
<script type="text/javascript" src="/js/js1.js"></script>
<script type="text/javascript">
alert('at header 1');
window.onload = function(){
alert('at window.onload');
}
alert('at header 2 after window.online');
</script>
<script type="text/javascript" src="/js/js2.js"></script>
</head>
<body onload="alert('at body tag onload');">
<script type="text/javascript">alert('at body');</script>
</body>
</html>
↓
下記順番に実行される
↓
1)js 1
2)header1
3)header2 after window.online
4)js2
5)body
6)window.onloadの中で最後のもの一つだけ実行(最下行が強い)
js1 window.onload(後ろのwindow.onloadあると本項目は実行されない)
window.onload(後ろのbody tag onloadがあると本項目は実行されない)
body tag onload(これがあると'at window.onload'は実行されない)
js2 window.onload(これがあると'body tag onload'は実行されない)
onloadは実行の順番を遅くする方法、他のテクとして
window.addEventListener('DOMContentLoaded', function() {
これはDOMのツリー構造が完了した時点で実行されるのでonloadより早い
bodyの閉じタグ直前にJSを入れる
//JavaScriptはシングルスレッド、非同期でも待ちが発生する場合もあり遅い、WebWorkersならマルチ可
setTimeoutは 「指定秒数後に実行」ではなく「指定秒数後に実行キューに登録」
https://language-and-engineering.hatenablog.jp/entry/20090614/p1
JavaScriptの非同期処理は並列処理でない
非同期処理では処理が実行できるようになるのを待ち実行できるようになってから実行する
タイマー系はシングルスレッド問題がある、書き方ではない、()必要、""不要、無名関数でもだめ
setInterval(set(),10) setInterval("set",10) setInterval(function(){set();},10);
setTimeout(function(){ }, 0)と書くと擬似的に並列処理ができるらしい
非同期処理の考慮はpromise/async/awaitで行うことが多いが癖が強い、こちらに移行
https://www.bangboo.com/cms/blog/page_341.html
マルチスレッドで実行するにはWebWorkersというAPIを使うと実装可
Web Workerとメインスレッドでのデータのやり取りにはpostMessageというメソッドを利用する必要がある
https://qiita.com/klme_u6/items/ea155f82cbe44d6f5d88
オブジェクト的な方が早い
手続き型の上から下への書き方は、実行スレッドが通信中に解放されないことである。
UIスレッドからこんなプログラムを実行すればユーザーインターフェイスが無反応になる。
https://satoshi.blogs.com/life/2010/01/sync_vs_async.html
//Web worker 並行処理 postMessage
https://www.html5rocks.com/ja/tutorials/workers/basics/
https://www.atmarkit.co.jp/ait/articles/1201/13/news138_2.html
別ファイルにしてキックするだけで簡単
///引数
https://wp-p.info/tpl_rep.php?cat=js-application&fl=r12
数が多くても少なくても実行される、可変長引数argumentsオブジェクトを使っているから
var f = function(x, y, z){
console.log(x);
console.log(y);
console.log(z);
console.log(arguments[0]);
if(arguments.length == 4){ console.log('4'); }
};
f(1, 2, 3); //1,2,3,1
f(1, 2, 3, 4); //1,2,3,1,4
f(1, 2); //1,2,undefined,1
■ES6での変更
https://qiita.com/soarflat/items/b251caf9cb59b72beb9b
///letは再宣言が不可能な宣言、constは再宣言と再代入が不可能な宣言
varは利用する理由がない?varは関数スコープで関数内ならどこでもOK、またグローバル化も可
letとconstはカーリーブラケット{}によるブロックスコープが有効で、For等ブラケット外からアクセスできない
letとconstは安全、varに単純置き換えはアルゴが変わるのでできない
if (true) {
var a = 1;
let b = 'aaa';
b = 'bbb'; // 再代入する
let b = 'ccc'; // 再宣言はエラー
const C = 'ddd';
C = 'eee'; // 再代入はエラー
}
console.log(a); // => 1
console.log(b); // => undefined
console.log(C); // => undefined
///アロー関数(無名関数の省略形、なおthisの扱いが違う)
アロー関数は、関数が定義されたスコープ内のthisを参照する
従来の無名関数は関数の呼び方によってthisの参照先が異なる
const fn = (a, b) => {
return a + b;
};
// 単一式の場合はブラケットやreturnを省略できる
const fn = (a, b) => a + b;
// ブラケットやreturnを省略してオブジェクトを返したい場合は`()`で囲む
const fn = (a, b) => ({ sum: a + b });
// アロー変数はargumentsがなく可変長引数を使う必要がある
const arrow = (...arguments) => { console.log(arguments); }
arrow(1, 2, 3) //=> [ 1, 2, 3 ]
///関数にデフォルト引数を指定できる
function multiply (a = 5) {
///分割代入
const [a, b, c, d] = [1, 2, {d: 3}, 3];
const object = {a: 1, b: 2, c: {d: 3}};
const {a, b, c, c: {d}} = object;
///テンプレート文字列(プレースホルダ)
``(バッククオート)で文字列を囲むと${}で文字列内に変数展開ができる
const name = 'soarflat';
const name = 'aaa';
console.log(`AAA is ${name}`);
///スプレッド構文
...で可変長の複数要素を表す、下記のように柔軟に
function func1 (a, ...r) { alert(a + r + r[0]); }
func1(1, 2, 3, 4, 5);//でa=1、r[0]=2が入る
console.log(Math.max(r)); // => NaN
console.log(Math.max(...r)); // => 5 上手くいかないケースでも使える
function func2 (a, b, c){
func2(...array_arg);//argumentsオブジェクトのようにできる
const [a, b, ...c] = ['a', 'b', 'c', 'C'];
console.log(c); // => ["c", "C"]
const array2 = [...c, 4, 5, 6];
for in/for ofで配列やオブジェクトの扱い
const array = [65, 55, 80, 100];
const obj = {name: 'aaa', country: 'Japan'}
for(const index in array) {
console.log(array[index]);
}//65 55 80 100
for(const key in obj) {
console.log(key);
}//name country
for(const value of array) {
console.log(value);
}//65 55 80 100
///try catch
syntaxエラーはtry catchする必要がある、エラーハンドリングはこれ以外に色々ある
try{
let obj = JSON.parse(input);
}catch(e){
console.log(e instanceof SyntaxError);
console.error(e.message);
console.error(e.name);
console.error(e.stack);
flg_e = 'ERROR'
}
///文字置換 正規表現replace
output = input.replace(/\,/g, ",\n"); gを付けなければ最初の一つだけ
■promise/async/await はこちらに移行
https://www.bangboo.com/cms/blog/page_341.html
■FetchはAjax変わりになる
https://qiita.com/tomoyukilabs/items/9b464c53450acc0b9574
https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch
fetchでget post
https://qiita.com/okashi/items/b5d5635b399396294af3
■ショートハンド
糖衣構文(シンタックスシュガー)とも:同じ意味の処理を元の構文よりシンプルに書ける別の書き方のこと
https://www.webprofessional.jp/shorthand-javascript-techniques/
https://qiita.com/kozzzz/items/b4cd57ead41fc6355afd
短縮記法が色々あって読みにくい↑を参考
他にもあるが、下記は参考になったので↓
「!==」(厳密不等価)は「&&」(論理AND)よりも強く結びつく
つまりnull!==e&&(e.innerHTML=t,e.style.display="block")は
(null!==e)&&(e.innerHTML=t,e.style.display="block") という意味
「&&」は 論理AND は、下記の動作をする
前から評価する
評価値「偽」が出たならば、「偽」を返して残りの部分は評価しない
カンマ演算子は、単純にカンマで区切られた式を順番に評価し、最後の式の値を返す
演算子であるのでカンマで区切られるものはすべて値・関数・式である必要
最終的にその演算子で繋がった式全体で真または偽となります
<script type="text/javascript">
let aaa={
displayResult:function(t){
let e=document.getElementById("result");
//該当DIVがあれば&&()の処理をする、IFの省略
null!==e&&(e.innerHTML=t,e.style.display="block")
}
};
window.onload = function(){
(function(t){
let e=document.getElementById("result");
if(e){
e.innerHTML=t;
e.style.display="block";
}
})('bbb');
setTimeout(aaa.displayResult('bbb'),5000);
};
</script>
<div id="result" style="display:none">aaa</div>
■ゲーム
https://qiita.com/doxas/items/9debec7e1f0c19bc8daa チュート8迄でOKか、9でボス10で処理高速化
http://www.west-mira.jp/javascript/list/4/16/ の打打打
どちらもsetTimeoutで自己関数を呼び出すループをしている
var run = true;
var fps = 1000 / 30;
window.onload = function(){
// ループ処理
(function(){
// HTMLを更新
info.innerHTML = message + ' at ' + mouse.x + ' : ' + mouse.y;
if(p.length() < chara.size){
// 衝突があったのでパラメータを変更してループを抜ける
run = false;
message = 'GAME OVER !!';
break;
}
// フラグにより再帰呼び出し
if(run){setTimeout(arguments.callee, fps);}
})();
};
function Games(){
//判定処理やら得点処理やら描画処理
clearTimeout(my_time);//setTimeoutをキャンセル
if(tokutenn<0){
game_end=1;
alert("GAME OVER...");
}
if(game_end!=1)my_time=setTimeout('Games();',hayasa);
}
■ネイティブで実現させるフロントエンド
https://blog.kannart.co.jp/coding/1199/
カルーセル addEventListenerでクリックされると要素分移動する
ハンバーガ 画面サイズでハンバーガDivの表示切替、クリックでナビDiv表示
グローバルナビ マウスオーバでナビDiv表示
フッター固定 スクロール300でposition:fixedを表示
スムーズスクロール scrollTop分をsettimeoutでループし段々移動
無限スクロール ローディング画像を非表示>最下部に行けば>ローディングを表示>要素を追加していくが
ページネーションのURL page.php?p=3から指定の要素を取り込んでいる(サーバサイド処理不要)
///解説系
https://www.nishi2002.com/14962.html フッター表示
https://beginners.atompro.net/smpdhtm_divhide1.html ナビ
https://popo-design.net/template/ シンプルRWD
http://cly7796.net/wp/javascript/implement-infinite-scrolling/ 無限スクロール
///例
カルーセル、ヒーロー、グローバルナビ
https://www.rakuten-card.co.jp/e-navi/members/index.xhtml
スクロール系(タイトルとナビとサブナビとフッターが各スクロールポイントが違う、広告追従、トップ戻るボタン)
フッターに広告、トップにスクロールで戻るボタン
https://ferret-plus.com/6385
https://www.sejuku.net/blog/52998
https://liginc.co.jp/392786 (グローバルナビも)
広告がスクロールに追従
https://dekiru.net/article/19272/
sticky-state 2.4.1 - (http://soenkekluth.com/) - https://github.com/soenkekluth/sticky-state#readme
スクロールの進み具合を表示、最後に広告?
https://blog.hubspot.jp/google-forms
無限スクロール ローディングbyスクロール
https://shopping.yahoo.co.jp/search?p=Oakley+holbrook
ハンバーガ拡大アニメ
https://rfs.jp/sb/javascript/js-lab/resize-header-scroll.html
Wijimo Grapecity 感じのいいレスポンシブ
https://demo.grapecity.com/wijmo/demos/Input/ListBox/InfiniteScroll
ドラッグ&ドロップでHTML要素を移動
https://q-az.net/elements-drag-and-drop/
https://web-designer.cman.jp/javascript_ref/mouse/move/
https://qiita.com/kaikusakari/items/ca45910a35712daca68c
ドラッグ&ドロップでファイルをアップロード
https://platycerium.sakura.ne.jp/node/812
https://www.okushin.co.jp/kodanuki_note/2018/02/%E3%83%89%E3%83%A9%E3%83%83%E3%82%B0%E3%82%A2%E3%83%B3%E3%83%89%E3%83%89%E3%83%AD%E3%83%83%E3%83%97%E3%81%A7%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC.html
↓使用されるJS
https://lab.syncer.jp/Web/API_Interface/Reference/IDL/DataTransfer/dropEffect/
https://lab.syncer.jp/Web/API_Interface/Reference/IDL/DataTransfer/effectAllowed/
https://lab.syncer.jp/Web/API_Interface/Reference/IDL/Event/preventDefault/
https://app.codegrid.net/entry/dnd-api-1
https://qiita.com/tochiji/items/4e9e64cabc0a1cd7a1ae
https://chaika.hatenablog.com/entry/2019/02/15/090000
DataTransferは、ドラッグ操作やクリップボード操作で転送されるデータ扱うインターフェイス
コンストラクタ
DataTransfer() 新しいDataTransferのオブジェクトを作成します。
メソッド
clearData() 転送中のデータを削除します。
getData() 転送中のデータの内容を取得します。
setData() 転送中のデータの内容を変更します。
setDragImage() ドラッグ操作中に表示するイメージを設定します。
プロパティ
dropEffect 転送データを取り扱う時のドロップ側の操作を返します。
種類:copy, move, link, none
effectAllowed 転送データを取り扱う時のドラッグ側の操作を返します。
種類:copy, move, link, copyLink, copyMove, linkMove, all, none, uninitialized
files 転送中のファイルの一覧をFileListで返します。
items 転送中のデータの一覧をDataTransferItemListで返します。
types 転送中のデータの種類の一覧を配列で返します。
addEventListener()でリッスンするドラッグイベント
dragstart, drag, dragenter, dragleave, dragover, drop, dragend
preventDefault() 規定の動作をキャンセルし文字入力やクリックや画面の遷移を行わない等
stopPropagation() イベント伝播を行わないようにする
classList クラス属性でDOM操作できるオブジェクト、クラスの追加/削除/切替/含むか判定等ができる
■ indexedDB
https://dev.classmethod.jp/articles/html5-indexed-database-api/
キーバリューを保存できる
このサイトのバックアップもアップロードフォルダーに一応取ってある
/// BANGBOO BLOG /// - Dexie がラッパーとして良き
IndexedDB のインターフェースは非同期でイベントベース
indexedDB.openのonsuccessで実行が必要だったり、UX上は良いかもしれんが扱いは面倒(毎回Openのonsuccessで良いが)
色んな形式で保存できるらしい、インデックス化は便利か
https://qiita.com/butakoma/items/2c1c956b63fcf956a137
https://ikkyu.hateblo.jp/entry/2019/11/23/180259
https://blog.htmlhifive.com/2018/06/06/indexed-db/
https://qiita.com/sachiko-kame/items/aebd618ef39de982ed7b
/// 他のクライアントへのデータ保存
1)localStorage/sessionStorageは同期型でgetItem/setItemを実行できる、5MBでStringのみ
扱いは簡単だが、引っこ抜き安全でない
https://techracho.bpsinc.jp/hachi8833/2019_10_09/80851
https://www.granfairs.com/blog/staff/local-storage-01
https://qiita.com/masamitsu-konya/items/c69515604570150d3ab9
2)Cookieはサーバでヘッダーで生成される、4KBまで、JSで生成し書込/読込できる、サーバ送信される?
通常ページ表示でCookieがブラウザ保存され、再度そのページにアクセスの際ブラウザからCookieがサーバーに送信
https://qiita.com/dokkoisho/items/b415f1c9852c8fd12ec8
https://www.sejuku.net/blog/28696
Secure属性 httpsの通信の時のみCookieを送信、のぞかれないように、ONに
HHTPOnly属性 JSでの参照を防ぐ、ONに
SameSite属性 上の2つをした上でサイト構成を見てLAX以上にできればする
Strict: 同一サイト/ドメインリクエスト間のリクエストでのみCookieを送信
Lax: 他サイト/ドメインの遷移で、GETであればCookieセット
None: 以前通りリクエスト先がCookieをセットしたドメインであればCookieをセット
https://laboradian.com/same-site-cookies/
https://www.future-shop.jp/magazine/info-samesite
https://www.softel.co.jp/blogs/tech/archives/4942
■知りたい実装
/// e = pow(10)=10の累乗=0の数
31536e3 は 31536 * pow(10,3) = 31536000 であり秒数換算で1年
/// 引数にアルファベット1文字 function(a,b,c,x,y,z,e,t,n,s,o){
a,b,cとかx,y,zとかの順番とか、後は大体頭文字
eはイベント、エラー、エレメント、Tはタイプ、テンポラリ、ターゲット、テキスト、Nはナンバー、Sはストリング、Oはオブジェクト、Iはインクリメント等
/// エンコード系
btoa バイナリデータの文字列から base64 エンコードされた文字列を作成、文字列変換なので入力はアスキー化かURIエンコードの事前処理が必要
atob base64 形式でエンコードされたデータの文字列をデコード
escape 文字列をASCII形式でエンコード、ブラウザによってはLatin1ではなくUnicodeになる?
unescape ASCII形式の文字列をデコード
encodeURIComponent スペースが%20になったりURL用エンコード
decodeURIComponent URL用にエンコードされた文字列をデコード
base64はa-Z0-9と幾つかの記号の64種で画像や音声等バイナリを文字化しメール送信等の用途、普通はURIエンコードだけ使う感じか
==============================
■Chrome DevTools デバッガー
JSをソースタブで開く
{} でMinifyを解除
ブレイクポイントで止めて変数の状態を調べステップ(イン)で実行
console.log()でロギング
エラー発生時の自動一時停止の有効化
https://qiita.com/d-dai/items/0b580b26bb1d1622eb46
https://ja.javascript.info/debugging-chrome
スタックトレースするにはdebuggerとかconsole.trace()
JavaScriptのデバッグにはdebugger文を使おう - Qiita
リバースエンジニアリング
エレメントタブで影響のあるエレメントのソースを抜き出す
classやidの名前から機能を類推、CSSやJSで使われているか検索する
[Ctrl] + [Shift] + [F] を押すとページが読み込んだソース全体から検索可
https://www.doe.co.jp/hp-tips/browser/chrome-devtools-techniques/
Posted by funa : 07:27 AM
| Web
| Comment (0)
| Trackback (0)
January 4, 2016
Laravel
https://coinbaby8.com/laravel-php-dekirukoto.html
https://laravel10.wordpress.com/
https://paiza.jp/works/laravel/primer
ルーティング: URLと対応 .phpで終わせず処理をひとつのファイルやクラスにまとめる
Blade: テンプレートエンジン
ミドルウェア: URL前後に処理を付加
エラーハンドラ: 例外やエラーが発生した際の処理
DI : サービスコンテナというのを用いクラスインスタンスの依存度を極力下げて、実行時に外部から与えてもらえるように
バリデーション: 入力値のチェックを設定のみで自動的に
データベース連携
認証の自動化
■PHPフレームワーク Laravel入門 サンプルファイルのダウンロード
https://www.shuwasystem.co.jp/support/7980html/5258.html
■XAMPP 7.4.1 インスコ(X-platform/Apache/MySQL/PHP/Perl)
https://www.apachefriends.org/jp/index.html
Win用Exeでインスコ C:\xampp\htdocs ← http://localhost/
xamppコンパネのショートカットをデスクトップに作成
Composer PHPのパッケージ管理システム
https://getcomposer.org/download/
Win用Exeで通常(devでなく)でインスコ
PHPはC:\xampp\php\php.exe、ユーザパスはC:\xampp\php
Laravel インスコ(プロジェクト作成)
コマンドを打つと自動でインスコ
cd C:\xampp\htdocs
composer create-project laravel/laravel prj_laravel --prefer-dist
5分位掛かる
Xampp(appach, mysql)起動し、Laravelプロジェクト起動はコマンドを打つ
cd C:\xampp\htdocs\prj_laravel
php artisan serve
次のURLへアクセスする http://localhost:8000/
8000のルートはここ C:\xampp\htdocs\prj_laravel\public
http://localhost では:80
php artisan serve --port=8000 がデフォ、Xamppは80
netstat -an でリスナーを見れる(XAMPPコンパネでもOK)
C:\xampp\apache\conf\httpd.conf でDocumentRootを変更できる
Alias / "C:\xampp\htdocs\prj_laravel\public"でエイリアス?
自由に使えるか?
1)C:\xampp\htdocs\prj_laravel\public\direct_test1.php を置くとhttp://localhost:8000/direct_test1.php でPHPが動くページにアクセスできる
2)ビューで自由にPHPを動かせるか?→例えばtest.blade.phpに<?php --- ?>でコードを書けば動く
http://localhost:8000/_test でアクセスすれば下記ルートとビューが使われtest.blade.phpだけで動く
routes/web.php
C:\xampp\htdocs\prj_laravel\app\Http\Controllers 無し
config/app.php ファサード無し サービスプロバイダ無し
C:\xampp\htdocs\prj_laravel\app\Http\Middleware フィルタ無し
C:\xampp\htdocs\prj_laravel\app\Http/Kernel.php ミドルウェア無し
C:\xampp\htdocs\prj_laravel\resources\views\test.blade.php
http://localhost:8000/fun/
php artisan make:controller FunController --resource
MySQLにDB:test ID:test/testtestを設定しテーブルを作成
CREATE TABLE `fun_inquiry` (
`no` bigint(20) NOT NULL auto_increment,
`title` varchar(255) NOT NULL default '',
`inquiry` text,
`title_ex` varchar(255) NOT NULL default '',
`inquiry_ex` text,
`date_latest` datetime NOT NULL default '1000-01-01 00:00:00',
`date_2ndlast` datetime NOT NULL default '1000-01-01 00:00:00',
`date_first` datetime NOT NULL default '1000-01-01 00:00:00',
`ip` varchar(255) NOT NULL default '',
`flag_who` tinyint(4) NOT NULL default '0',
`flag_active` tinyint(4) NOT NULL default '0',
PRIMARY KEY (`no`)
) ENGINE=InnoDB
DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci;
/*
flag_who 1:customer,2:admin
flag_active 1:有効,2:削除
*/
ダミーデータ挿入
INSERT INTO `fun_inquiry`(`title`, `inquiry`, `date_lastest`, `date_first`, `ip`, `flag_who`, `flag_active`) VALUES ('あああ', 'いいい', now(), now(), '192.168.56.1', '2', '1')
.env とconfig/database.phpに DB情報を記入
変更後は php artisan config:cache
C:\xampp\htdocs\prj_laravel\routes\web.php にコントローラ渡し記述
index crate store show($id) edit($id) update(Request $request, $id) destroy($id)
C:\xampp\htdocs\prj_laravel\app\Http\Controllers\FunController.php にView渡し記述
C:\xampp\htdocs\prj_laravel\resources\views\index.blade.php など
index crate store show edit update destroyのViewファイルを作成し リンク設定
href=/でルートからリンクを指定
パスはルート/が安定する、相対だと理由不明で階層が崩れる事があった、Form methodを入れる
情報を表示させたい
コントローラに
$param = ['items' => $items,
'msg' => 'データを追加しました',
'request' => $request,
'response' => $response];
return view('index', $param);
ビューに
<?php dump($items);
dump($msg);
dump($request);
dump($response); ?>
バリデーションするのに同カラム保持のpostsテーブルが必要であったので作成(多分ダミー)
テーブル作成方法: php artisan make:model posts をCMDしSQL流し込み
CREATE TABLE `posts` (
`no` bigint(20) NOT NULL auto_increment,
`title` varchar(255) NOT NULL default '',
`inquiry` text,
`title_ex` varchar(255) NOT NULL default '',
`inquiry_ex` text,
`date_latest` datetime NOT NULL default '1000-01-01 00:00:00',
`date_2ndlast` datetime NOT NULL default '1000-01-01 00:00:00',
`date_first` datetime NOT NULL default '1000-01-01 00:00:00',
`ip` varchar(255) NOT NULL default '',
`flag_who` tinyint(4) NOT NULL default '0',
`flag_active` tinyint(4) NOT NULL default '0',
PRIMARY KEY (`no`)
) ENGINE=InnoDB
DEFAULT CHARACTER SET utf8
COLLATE utf8_unicode_ci;
エラー後は元のページに戻るが元の値とエラーを出すには
<input name="title" value="{{old('title')}}">
@if($errors->has('title'))
@foreach($errors->get('title') as $message)
<br><red>{{ $message }}</red>
@endforeach
@endif
//バリデーション例
https://qiita.com/fagai/items/9904409d3703ef6f79a2
https://blog.capilano-fw.com/?p=341#digitsdigits_between
$validate_rule = [
'title' => 'required|unique:posts|max:255',
'inquiry' => 'required',
'title_ex' => 'required|unique:posts|max:255',
'inquiry_ex' => 'required',
'date_latest' => 'required|date_format:Y-m-d H:i:s',
'date_2ndlast' => 'date_format:Y-m-d H:i:s',
'date_first' => 'required|date_format:Y-m-d H:i:s',
'ip' => 'required|ip',
'flag_who' => 'required|integer|between:1,2',
'flag_active' => 'required|integer|between:1,2'];
$this->validate($request, $validate_rule);
自分で命名したデータベースをLaravelに参照させたいときは、テーブル名をモデルファイル内で指定しなければいけない
php artisan make:model DbTblFunInquiry をCMDし
app/DbTblFunInquiry.php を編集
namespace App;
use Illuminate\Database\Eloquent\Model;
class DbTblFunInquiry extends Model{
protected $table = 'fun_inquiry';
}
コントローラでDB追加
$now = date('Y-m-d H:i:s');
$input = ['title' => $request->title,
'inquiry' => $request->inquiry,
'date_latest' => $now,
'date_first' => $now,
'ip' => $request->ip(),
'flag_who' => '1',
'flag_active' => '1'];
$insert = DB::insert('insert into fun_inquiry(title, inquiry, date_latest, date_first, ip, flag_who, flag_active) values (:title, :inquiry, :date_latest, :date_first, :ip, :flag_who, :flag_active)', $input);
DB操作で同じパラメータを使おうとしてもSQLで数が合わないとだめで$input作り直した
→エラーはrequest/responseインスタンスをダンプしキッチリと見ると原因がわかる
$update = DB::update('update fun_inquiry set
title = :title,
inquiry = :inquiry,
title_ex = :title_ex,
inquiry_ex = :inquiry_ex,
date_latest = :date_latest,
date_2ndlast = :date_2ndlast,
ip = :ip,
flag_who = :flag_who,
flag_active = :flag_active
where no = :no', $input);
$input = ['no' => $request->no];
$items = DB::select('select * from fun_inquiry where no = :no', $input);
■ララベルの基本
gitの管理対象から外す
.gitignore ファイルに追加
環境毎に変更したい情報
.env ファイルにステージング環境、本番環境の情報をまとめる
設定情報は下記以下、DB接続/メール/サービスプロバイダ登録/ファサード登録等
config/
バリデーションメッセージの日本語化
resources/lang/ja/validation.php
===============
├── app
│ └── Article.php
│ └── Http
│ └── Controllers
├── resources
│ └── views
└── routes
//基本構成
routes/web.php
C:\xampp\htdocs\prj_laravel\app\Http\Controllers ある程度処理をする?モデル化?
config/app.php ファサード サービスプロバイダ
C:\xampp\htdocs\prj_laravel\app\Http\Middleware フィルタ
C:\xampp\htdocs\prj_laravel\app\Http/Kernel.php ミドルウェア
C:\xampp\htdocs\prj_laravel\resources\views\test.blade.php
CRUDはリソースコントローラで一気作成ができる
php artisan make:controller PostsController --resource
モデルを作成cmd EloquentでDB接続 app/Article.php
php artisan make:model Article
ファサード
対象となるクラスの作成 class Payment {
サービスプロバイダの作成 php artisan make:provider PaymentServiceProvider
サービスコンテナに paymentキーでPaymentクラスをバインド
config/app.php に PaymentServiceProviderと エリアスを追加
認証用ビューとルートを作成(認証機能はプロジェクト作成時点で既成)
php artisan make:auth
//php artisanコマンド(独自作成も可)
何ができるかリスト確認cmd
php artisan list
使い方確認cmd
php artisan help コマンド名
cmdでララベル機能が使える
php artisan tinker
古いパッケージをチェック
composer update --dry-run
古いパッケージをチェック(グローバルの場合)
composer global update --dry-run
.env変更後は
php artisan config:cache
コントローラを作成cmd
php artisan make:controller WelcomeController
モデルを作成cmd
php artisan make:model Article
Form Request を生成
php artisan make:request ArticleRequest
CRUDはリソースコントローラで一気作成ができる
php artisan make:controller PostsController --resource
認証用ビューとルートを作成(認証機能はプロジェクト作成時点で既成)
php artisan make:auth
ルーティングのリストを表示
php artisan route:list
//jsファイルやcssファイルはpublicフォルダ配下に入れる、HTMLやIMGも
public
|__ css
|__ js
|__ img
|__ html
asset('ファイルパス')はpublicディレクトリのパスを返す関数、SSLならsecure_assset()
<script src="{{ asset(mix('js/app.js')) }}" defer></script>
<link href="{{ asset(mix('css/app.css')) }}" rel="stylesheet">
<img alt="ロゴ" src="{{ asset('/img/logo.png') }}">
url()で完全なURL、SSLならsecure_url( )
.hoge::before { background: url("../img/hoge.svg") no-repeat center center; }
レスポンスでHTMLファイルを返したい時
Route::get('fun/html', function() {
return File::get(public_path() . '/html/test_direct.html');
});
//ルーティング routes/web.php
必須パラメータ(値がないとエラー)
Route::get('login/{id]/{pass}', function($id, $pass){
任意パラメータ
Route::get('login/{id?]/{pass?}', function($id='noname', $pass='unknown'){
login/taro/aaa でアクセスするときRouteにlogin/taro/{pass?}とlogin/{id?]/{pass?}があればどうなる?
通常 http://url/コントローラ/アクション と設計され Route::get('パス', 'コントローラ@アクション' (アクションはコントローラ内のメソッド)
Route::get('/', 'WelcomeController@index');
Route::get('contact', 'WelcomeController@contact');
正規表現を配列にして、複数指定
Route::get('foo/{id}/{name?}', function($id, $name = 'init') {
return "パラメータ $id, $name";
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
下のようにnamed rootで名付けも
Route::get('articles', 'ArticlesController@index')->name('articles.index');
Route::get('articles/{id}', 'ArticlesController@show');
Route::post('articles', 'ArticlesController@store')->name('articles.store');
//コントローラ app/Http/Controllers/WelcomeController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class WelcomeController extends Controller{
public function index(){
return view('welcome');
}
public function contact(){
return view('contact');
}
}
class ArticlesController extends Controller {
public function create() {
return view('articles.create');
}
public function store(ArticleRequest $request) {
//コントローラはメソッドの引数にタイプヒントでクラスを記述するとインスタンスを自動生成して渡してくれます
//$inputs = \Request::all(); //フォームの入力値を取得
//dd($inputs); //デバッグ: $inputs の内容確認
Article::create($request->validated());//マスアサインメントで記事をDBに作成
return redirect()->route('articles.index')->with('message', '作成!'); //記事一覧へリダイレクト
}
}
//ビュー resouces/views/welcome.blade.php
resources/view/contact.blade.php
view('aaa')の場合、ビューはaaa.blade.phpが読まれる、なければaaa.php
blade では PHP で評価した結果を表示する場合、ダブルカーリー {{ }}
{{!! XXXX !!} はPHP評価をエスケープ処理を行わず表示(htmlタグがでる)、{{ XXXX }} のエスケープ(htmlタグがでない)
@csrfでCSRFトークン(hidden)を挿入
{{-- コメント文 --}}
ビューテンプレ
親ビューですべきこと
大まかレイアウトを記述し、各子ビュー固有のパーツをどこの@yieldで反映させたいかを指定
<html><body>
@yield('body')
</html>
子ビューですべきこと
@extendsで親ビュー継承、@sectionで自分固有のパーツを定義
@extends('common.layout')//resources/views/common/layout.blade.php dotはフォルダの事
@section('body')
<p>表示したい内容<p>
@endsection
@extends('layout')
<h1>About Me: {{ $first_name }} {{ $last_name }}</h1>
{{-- エラーの表示を追加 --}}
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
{!! Form::open() !!}
<div class="form-group">
{!! Form::label('title', 'Title:') !!}
{!! Form::text('title', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('body', 'Body:') !!}
{!! Form::textarea('body', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('published_at', 'Publish On:') !!}
{!! Form::input('date', 'published_at', $published_at, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::submit($submitButton, ['class' => 'btn btn-primary form-control']) !!}
</div>
大元のレイアウトビュー resouces/views/layout.blade.php
<!DOCTYPE HTML>
<html lang="ja">
<body>
@if (session('message'))
<div class="alert alert-success">{{ session('message') }}</div>
@endif
@yield('content')
</body>
</html>
変数を渡す場合
ビューファサードは第二引数へ配列でパラメータを渡す
Route::view('sample/view', 'sampleview', ['number' => 123456789]);
コントローラでは配列で渡す
public function create(Request $request, Response $response){
$items = DB::select('select * from fun_inquiry');
$param = ['items' => $items,
'msg' => 'データを追加するにはログインが必要です',
'request' => $request,
'response' => $response];
return view('index', $param);
他にはcompact関数又はwithメソッドで送信
public function test() {
$test_1 = "テスト1";
$test_2 = "テスト2";
return view('test.normal',compact('test_1','test_2'));
}
public function test() {
$test_1 = "テスト1";
$test_2 = "テスト2";
return view('test.normal')->with([
"test_1" => "テスト1",
"test_2" => "テスト2",
]);
}
フォーム
<input type="text" name="textbox" value="">
<input type="radio" name="radio-btn" value="選択1">
<input type="radio" name="radio-btn" value="選択2">
テキストボックスは{{$post_data['textbox']}}
ラジオボタンは{{$post_data['radio-btn']}}
処理系ディレクティブ
@isset($msg) {{$msg}} @else 今何してる? @endisset
@for($i=1;$i<10;$i++;) {{$i}} @endfor
@while($msg=='') 今何してる? @endwhile
@break @continueも
@foreach($db_data as $recode)
{{$recode->id}}
{{$recode->name}}
{{$recode->old}}
@endforeach
{{$db_data[0]->name}} 0番目
$count = $db_data->count(); カウント
$avg = $db_data->avg('old'); 平均
//モデル app/Article.php
DBとモデルオブジェクトを対応付ける機能を Eloquent という
Eloquent の機能を継承しビジネスロジックを加えたクラスがモデル
ORM(Object-relational mapping)でDBアクセスをする
$items = DbTblFunInquiry::all(); //モデルを作成しているのでコレでDBアクセス可
$items = DbTblFunInquiry::where(no, '>=', 3)->get();
Eloquentのリレーションには、1対n、1対1やn対n等が
$this->hasMany('App\Article');
$this->belongsTo('App\User');
//バリデーション
エラーが出て前のページに戻る
public function update(Request $request, Response $response){
$validate_rule = [
'title' => 'required|unique:posts|max:255',
'inquiry' => 'required'];
$this->validate($request, $validate_rule);
作り方、まずコントローラでは
$upfileRequest = new upfileRequest();
$rules = $upfileRequest->rules();
$errorMsg = $upfileRequest->messages();
$result = $this->validate($request, $rules, $errorMsg);
cmdでリクエストクラスを生成
$ php artisan make:request upfileRequest
下記のように
class upfileRequest extends Request{
public function rules(){
return [
'title' => 'required',
'address' => 'required',
'url' => 'url',
'img' => 'file|image|mimes:jpeg,jpg,png,gif|max:' . config('const.validate_limits.upload_image_size'),
'img_update_flag' => 'sometimes|accepted',
];
}
public function messages(){
return [
'title.required' => 'タイトルは必須です',
'address.required' => '住所は必須です',
'url.url' => 'このURLは不正です(http://またはhttps://から記述してください)',
'img.mimes' => '選択できる画像はJPEG・GIF・PNG形式のみです',
'img.max' => '1MB以下のファイルを選択してください',
'img_update_flag.accepted' => '1MB以下のファイルを選択してください',
];
}
}
//ミドルウェアでフィルタリングを実行
記事の作成や編集、削除はログインしていないと実行出来ないように制限する等
app/Http/Middleware/ にミドルウェアがある(vendor/laravel/framework 以下にも多数ある様)
├── CheckForMaintenanceMode.php
├── EncryptCookies.php
├── RedirectIfAuthenticated.php
├── TrimStrings.php
├── TrustProxies.php
└── VerifyCsrfToken.php
app/Html/Kernel.php の中でミドルウェアをシステムに登録
1)グローバルミドルウェア(全ての HTTP リクエストに適用)
2)ルートミドルウェア(Routeで使用)
3)グループ(Web等)で登録可
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
ミドルウェアの使用
routes/web.phpで定義したルートには全てwebミドルウェアが適用される
ルートミドルウェアを使う場合(Routeに配列で登録)
Route::get('admin/profile', function () {
//処理
})->middleware('auth', '2つ目', ...);
// ホーム(ログインしていないと見れないよう)
Route::group(['middleware' => 'auth'], function() {
Route::get('/home', function () {
return view('home');
});
});
コントローラで使う場合
ログインをしていなくてもindexとshowの表示が可能
class ArticlesController extends Controller{
public function __construct(){
$this->middleware('auth')
->except(['index', 'show']);
}
ビューでの使用
@auth
ログインしています
@endauth
Middleware の新規作成(基本的なものは元々ある)
php artisan make:middleware MyMiddleware
登録確認メールの確認が済んでいるかミドルウェアで
https://laravel10.wordpress.com/2015/05/05/laravel5
//ファサード
サービスコンテナで利用可能なクラスへのstaticインターフェースを提供
サービスコンテナからオブジェクトへのアクセスを提供するクラス
Hoge::ぶらぶら とシンプルにコードが書けるようになる
Route::get('/', 'WelcomeController@index'); はファサードがあり実際は下記
$this->app->make('router')->get('/', 'WelcomeController@index');
<?php namespace Illuminate\Support\Facades;
class Route extends Facade {
protected static function getFacadeAccessor() {
return 'router';
}
}
実際に作成↓
対象となるクラスの作成 class Payment {
サービスプロバイダの作成 php artisan make:provider PaymentServiceProvider
サービスコンテナに paymentキーでPaymentクラスをバインド
class PaymentServiceProvider extends ServiceProvider {
public function boot(){ }
public function register() {
$this->app->bind(
);
}
}
config/app.php に PaymentServiceProviderを追加
ファサードクラスを作成
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Payment extends Facade {
protected static function getFacadeAccessor() {
return 'payment';
}
}
config/app.php に Paymentファサードのエリアスを追加
'aliases' => [
'Payment' => App\Facades\Payment::class,
],
app/Http/route.php 内で Paymentファサードを使用
Route::get('pay/{money}', function($money){
return \Payment::pay($money);
})->where('money', '[0-9]+');
この場合はここへアクセス http://localhost:8000/pay/10000
'payemnt', 'App\Services\Payment'
//セッションはキーと値 https://qiita.com/reflet/items/5638ab18fd7cededed17
$requet->session()->put(key, value); 値を保存
$v = $request->session()->get(key); 値を取得
$request->session()->flush(); セッション破棄 session()->forget('key');個別
$request->session()->all(); 全取得
//クッキー
\Cookie::queue('testcookie', "aaa", 60); 書き込み60分
$test = \Cookie::get('testcookie');取得
setcookie('testcookie');削除
//httpヘッダー
以下を入れて見れる
Controllerで
use Illuminate/http/Request;
use Illuminate/http/Response;
public function create(Request $request, Response $response){
$param = ['msg' => 'データを追加します',
'request' => $request,
'response' => $response];
return view('create', $param);
Viewで
<?php
dump($msg);
dump($request);
dump($response);
?>
下記メソッドも
$request->url() クエリ変数がつかないURL
$request->fullUrl() クエリ変数つきフルURL
$request->path() ドメインがないパス部分
$response->status()
$response->content()
$response->setContent(値)
//認証
https://reffect.co.jp/laravel/laravel-authentication-understand
https://qiita.com/apricotcomic/items/d7407d4b12f41e2ff5ed
http://recipes.laravel.jp/recipe/64
https://takahashi-it.com/php/laravel54-auth-customize/
https://saba.omnioo.com/note/6246/laravel6-0-makeauthが無くなった/
基本ページと認証仕組みをcmdで入れ込む
(users/pw_resetsテーブル等はmigrationで作成しておく必要)
php artisan make:auth はv6から使えない様
vue省略型、React性能高
composer require laravel/ui
php artisan ui vue --auth
Nodeを入れて下記が必要のようだが(管理者権限が要るCMD)
cd C:\Program Files\nodejs
npm init --yes
npm install
npm run dev
下記ページができる
http://localhost:8000/login
http://localhost:8000/register
http://localhost:8000/password/reset
ルーティング関連(コントローラ)
C:\xampp\htdocs\prj_laravel\app\Http\Controllers\HomeController.php
C:\xampp\htdocs\prj_laravel\app\Http\Controllers\Auth
ルーティングAuth::routes();から下記へ
C:\xampp\htdocs\prj_laravel\vendor\laravel\framework\src\Illuminate\Support\Facades\Auth.php
C:\xampp\htdocs\prj_laravel\vendor\laravel\framework\src\Illuminate\Routing\Router.php
C:\xampp\htdocs\prj_laravel\vendor\laravel\framework\src\Illuminate\Foundation\Auth
migration するとデータは消えるのか? php artisan migrate ではDropされない、migrate:flushだと消える
Auth自動生成ページ系の遷移設定
protected $redirectTo = RouteServiceProvider::HOME;
HOMEは定数(C:\xampp\htdocs\prj_laravel\app\Providers\RouteServiceProvider.php で
public const HOME = '/fun';に設定
コントローラ類に下記を追加することで制御が可能だがコントローラを分ける必要がありそう
public function __construct(){ $this->middleware('auth'); }
public function __construct(){ $this->middleware('guest'); }
public function __construct(){ $this->middleware('guest')->except('logout'); }
ビューでログイン判定可
<?php
$user = \Auth::user();
if ($user) {
echo 'ログイン中: ' . $user->name;
?>
| <a href={{ route('logout') }} onclick="event.preventDefault();document.getElementById('logout-form').submit();">ログアウト</a>
<form id='logout-form' action={{ route('logout')}} method="POST" style="display: none;">
@csrf
</form>
<?php
}else{
?>
<a href="/login">Login</a> |
<a href="/register">Register</a>
<?php
}
?>
ビューにこんな感じでも
@if(Auth::check())
{{ Auth::id() }}
@endif
@auth
<p>ログインユーザーに表示する。</p>
@guest
<p>ログインしていないユーザーに表示する。</p>
@endguest
編集機能ページ等はコントローラでログイン判定しMSG表示とページ変遷(ログインするとCreateとUpdate可)
public function edit(Request $request, Response $response)
{
$user = \Auth::user();
if ($user) {
$input = ['no' => $request->no];
$items = DB::select('select * from fun_inquiry where no = :no', $input);
$param = ['items' => $items,
'msg' => '#' . $request->no . 'を編集できます',
'request' => $request,
'response' => $response];
return view('edit', $param);
}else{
$input = ['no' => $request->no];
$items = DB::select('select * from fun_inquiry where no = :no', $input);
$param = ['items' => $items,
'msg' => '#' . $request->no . 'を編集するにはログインが必要です',
'request' => $request,
'response' => $response];
return view('show', $param);
}
}
コントローラでユーザ判定
use Illuminate\Support\Facades\Auth;
class モデル名Controller extends Controller
{
public function ブレード名(){
$auths = Auth::user(); // ログイン中のユーザー情報
$user_no = Auth::id(); // ユーザーIDのみ
if (Auth::check()) {
if($a==1){ Auth::logout(); }
ログアウト時の変遷
logoutメソッドの本体は、AuthenticatesUsers にあるのでHOMEへ変更
C:\xampp\htdocs\prj_laravel\vendor\laravel\framework\src\Illuminate\Foundation\Auth
//return $this->loggedOut($request) ?: redirect('/');
use App\Providers\RouteServiceProvider;
return $this->loggedOut($request) ?: redirect(RouteServiceProvider::HOME . '?fr=logout');
https://takahashi-it.com/php/laravel-login-authenticated-override/
/vendor/laravel/framework/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php の
中に、ログイン処理のリダイレクト直前で実行される authenticated() メソッドが書かれているが空で
LoginController.php でオーバーライドする形で実装
use Illuminate\Foundation\Auth\AuthenticatesUsers;
protected function authenticated()
{
Session::put('session_start_time', date('H:i'));
}
Session にログイン時間を入れる
use Session;//これは場合によって不要なようである
Session::put('session_start_time', date('H:i'));
$session_start_time = Session::get('session_start_time');
@if (Session::has('session_start_time'))
{{ Session::get('session_start_time') }}
@endif
Authと連動しログアウトするとSessionがなくなる
//サービスプロバイダー ServiceProvider
処理や表示したいビューを登録しておける(初期処理用、カウンターのようにインクリできない)
クラスを作りboot()に付与して、例えばいつでもその処理とメッセージをビューに呼び出す
MVCでビューにビジネスロジックを書く必要がある矛盾を解消するもの?
クラス作成 C:\xampp\htdocs\prj_laravel\app\Http\Gadget\Lucky.php
namespace App\Http\Gadget;
class Lucky
{
public $count = 0;
public $rate = 0;
public function addupCounter(){
$this->count++;
}
public function getCounter(){
$this->count++;
return $this->count;
}
public function getLucky(){
$this->rate = rand(1, 100);
return $this->rate;
}
}
サービスプロバイダの作成 php artisan make:provider GadgetServiceProvider
app/Providers/AppServiceProvider.php に追記でもいい
config/app.php に GadgetServiceProviderを追加
GadgetServiceProviderのbootに追記
public function boot(){
\View::composer(
'index', function($view){
$LuckyInstance = new \App\Http\Gadget\Lucky;
$view->with('lucky', $LuckyInstance->getLucky());
});
index.bladeのビューに追記 {{ $lucky }}
//ユニットテスト(Laravel PHPunit)
リファレンス https://readouble.com/laravel/5.7/ja/http-tests.html#assert-see
https://qiita.com/rev84/items/12fbd16d210d6a86eff9
処理を全部書かないと駄目か https://qiita.com/shindex512/items/4f28f8e06ef2d10e8d2b
PHPUnitが入っていてTestsフォルダに
TestCaseクラスにあるメソッドはtestで始まる名前のメソッドと判断し実行する、testABC()とか
DB_DATABASEが使用されるのでDBに用意する、設定等
database/factoriesにダミーデータ作成ファクトリーがある、必要な形式のデータが作られるよう調整する
$factory->define(App\User::class, function (Faker\Generator $faker) {
static $password;
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => $password ?: $password = bcrypt('secret'),
'remember_token' => str_random(10),
];
});
$factory->define(App\Person::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'mail' => $faker->safeEmail,
'age' => random_int(1,99),
];
});
テストクラス作成 php artisan make:test LuckyTest
use Tests\TestCase;
use App\Http\Gadget\Lucky;
class LuckyTest extends TestCase{
public function testLucky(){
$response = $this->get('/fun');
$response->assertStatus(200);
$lucky = new Lucky;
$lucky_num = $lucky->getCounter();
$response->assertGreaterThanOrEqual(1, $lucky_num);
$response->assertLessThanOrEqual(100, $lucky_num);
}
}
use DatabaseMigration; を入れておくとテスト前後で自動でロールバックするらしい
テスト実行cmd vendor\bin\phpunit
//ページネーション
コントローラ側: $items = DB::table('fun_inquiry')->Paginate(7);
ビュー側: {{ $items->links() }} 合計{{ $items->total() }}
CSS側:
ul.pagination { text-align: center; margin: 0; padding: 0; }
.pagination li { display: inline; margin: 0 2px; padding: 0; display: inline-block; background:#eeeeee; width: 25px; height: 25px; text-align: center; position: relative; }
.pagination li a:hover, .pagination li a.active{ color: #000; background: #ccf; }
下記ではオブジェクトではなく配列を返しておりエラー
$items = DB::select('select * from fun_inquiry')->simplePaginate(7);
下記のようにクエリビルダかエロクエントならばOKのよう
$users = DB::table('users')->paginate(15); //query builder example
$users = User::where('votes', '>', 100)->paginate(15); //eloquent example
$users = DB::table('users as u')->select(['u.email','u.name','u.created_at'])->whereRaw("u.id in (select max(ui.id) from users ui where ui.status = 0)")->orderBy("ui.id","desc")->paginate(3)
吐き出されるソース resources/views/pagination/default.blade.phpで修正可能
<nav>
<ul class="pagination">
<li class="page-item disabled" aria-disabled="true" aria-label="pagination.previous">
<span class="page-link" aria-hidden="true">‹</span>
</li>
<li class="page-item active" aria-current="page"><span class="page-link">1</span></li>
<li class="page-item"><a class="page-link" href="http://localhost:8000/fun?page=2">2</a></li>
<li class="page-item">
<a class="page-link" href="http://localhost:8000/fun?page=2" rel="next" aria-label="pagination.next">›</a>
</li>
</ul>
</nav>
===============
■その他の機能
オートローダー
require "vendor/autoload.php";
autoload設定はcomposer.json を修正
ロガー
Monolog\Logger
エラーログ
storage/logs/*.log
メール送信
Mail::raw()
Laravel 5.3 からは artisan make:mail でMailable の派生クラス
php artisan make:mail Hello
app/Mail/Hello.php が作成される、Viewで本文
Mail::to('reciver@example.com')->send(new Hello($name));
データベース管理(migrationファイルを作成→migration実行)
php artisan make:migration create_users_table --create=users
php artisan migrate
database/migrations/2014_10_12_000000_create_users_table.php ができる
php artisan migrate:rollback でロールバック
Bootstrap
靴紐のソースを npm でダウンロードしLaravel Mixで public に配置
デバッガー
composer require barryvdh/laravel-debugbar でインスコ
config/app.php のサービス・プロバイダーとファサードに以下の設定を追加
Barryvdh\Debugbar\ServiceProvider::class,
'Debugbar' => Barryvdh\Debugbar\Facade::class,
デバッグ
dd($articles->first()); // dump and die ダンプして停止
Log::debug("incoming: GET hello");
Log::info("incoming: GET hello");
Log::warning("incoming: GET hello");
debug,info,notice,warning,error,critical,alertの7つ、storage/logs/に出力
全件
$articles = Article::all();
作成日の降順に記事をソート
$articles = Article::orderBy('published_at', 'desc')->orderBy('created_at', 'desc')->get();
$articles = Article::latest('published_at')->latest('created_at')->get();
現在より以前
$articles = Article::latest('published_at')->latest('created_at')->where('published_at', '<=', Carbon::now())->get();
フラッシュメッセージ
composer require laracasts/flash
Named rootはURLでなくルーティングに別名をつける
return redirect()->route('articles.index')
CRUDはリソースコントローラで一気作成ができる
php artisan make:controller PostsController --resource
// routes/web.php
Route::resource('posts', 'PostsController')->only(['index', 'show']);
Route::resource('posts', 'PostsController')->expect(['create', 'store', 'update', 'destroy']);
IDEでファサードの補完を行う
composer require barryvdh/laravel-ide-helper
php artisan ide-helper:generate
ページネーションで1ページに表示するデータ数を指定
$articles = Article::latest('published_at')->paginate(15);
render() でページネーションリンクをビューに生成 {!! $articles->render() !!}
ダミーデータ生成
seeder/factory/fakerで
サービスコンテナ
インスタンス化を管理する
サービスコンテナへクラスをバインドすると(キー名とクラスの紐付け)、クラス間の依存性を管理しやすい
インターフェイスでバインドとタイプヒントで依存性注入
$this->app->bind('SenderInterface', 'MailSender');
singleton()でバインドすると何度コンテナが呼び出されても同じインスタンスが返されメモリ効率が良い
$this->app->singleton('sender_single', 'MailSender');
Route::get('send/{message?}', function(Messenger $messenger, $message = '合格') {
return $messenger->send($message);
});
シングルトン(Singleton)パターンは
あるクラスのインスタンスを一つだけにする
同じクラスを使って新しいオブジェクトを再度作成すると最初に作ったオブジェクトの参照になる
function Singleton () {
// すでにSingleton.instance が存在する場合にはSingleton.instance を返す
if(typeof Singleton.instance === 'object') {
return Singleton.instance;
}
サービスプロバイダー
config/app.php にリストアップされ起動時に読込
Composerを使ってパッケージをインストールしたもの
vendor/laravel/framework/src/illuminate/Auth\AuthServiceProvider等を見ると
register()に登録を実装、boot()でそのサービス固有の初期処理を自由に実装
作成は php artisan make:provider MessengerProvider
エリクサー
Elixirはnode.jsのgulpをラッピングした自動化ツール
SassをCSSに変換、複数のファイルを1ファイルに結合、ミニファイ(余計な空白や改行を削る)、ファイルの変更を監視してタスクを実行、リロード用にCSSやJavaScriptのファイル名にバージョンを付与
ファイルアップロード
https://reffect.co.jp/laravel/how_to_upload_file_in_laravel
https://team-lab.github.io/skillup/step2/07-upload.html
https://laraweb.net/tutorial/2707/
https://qiita.com/mashirou_yuguchi/items/14d3614173c114c30f02
php.iniで定義: upload_max_filesize post_max_size等
windowsはパーミッションの設定は不要、XamppのTMPはここ C:\xampp\tmp\
$request->file('upfile')->getRealPath();//C:\xampp\tmp\php103B.tmp
dump($request->file('upfile'));
vendor\symfony\http-foundation\Request.phpにまつわるもの
$request->file('file')->store($path);
$request->file('file')->storePublicly($path);
$request->file('file')->storePubliclyAs($path);
$request->file('file')->storeAs($path,$filename);
$pathにtestならstorage/app/testに保存される
vendor\laravel\framework\src\Illuminate\Http\Request.phpにまつわるもの
$request->file('file')->move($destinationPath);
echo $request->file('upfile')->getPathname() . '<br>'; //C:\xampp\tmp\php76B8.tmp
echo $request->file('upfile')->getClientOriginalName() . '<br>'; //kanoe.jpg
echo $request->file('upfile')->getClientMimeType() . '<br>'; //image/jpeg
echo $request->file('upfile')->guessClientExtension() . '<br>'; //jpeg
echo $request->file('upfile')->getClientSize() . '<br>'; //20367
echo $request->file('upfile')->getError() . '<br>'; //0
echo $request->file('upfile')->isValid() . '<br>'; //1
echo $request->file('upfile')->getMaxFilesize() . '<br>'; //41943040
echo $request->file('upfile')->getErrorMessage() . '<br>'; //The file "kanoe.jpg" was not uploaded due to an unknown error.
こういうのもあるが、、、
echo $request->file('upfile')->getRealPath() . '<br>'; //C:\xampp\tmp\php9EA6.tmp
echo $request->hasFile('upfile') . '<br>'; //1
echo $request->file('upfile')->path() . '<br>'; //C:\xampp\tmp\php9EA6.tmp
echo $request->file('upfile')->extension() . '<br>'; //jpeg
ビューでは
<form action="{{ url('upload') }}" method="POST" enctype="multipart/form-data">
{{ csrf_field() }}
<input type="file" name="upfile">
<input type="submit">
</form>
@if ($errors->any())
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
@isset ($filename)
<div>
<img src="{{ asset('storage/' . $filename) }}">
</div>
@endisset
コントローラでは
public function upload(Request $request){
$this->validate($request, [
'file' => [
'required',
'file',
'image',
'mimes:jpeg,png',
]//1行だと上手くいかんかった
]);
if ($request->file('file')->isValid([])) {
$path = $request->file('file')->store('public');//適当な名前でstorage/app/publicに保存
return view('home')->with('filename', basename($path));
} else {
return redirect()
->back()
->withInput()
->withErrors();
}
}
名前をつけたいのであれば
$new_filename = 'up_' . $request->file('file')->getClientOriginalName();
$request->file('file')->storeAs('public', $new_filename);
storage/app/publicに保存されるからアクセスするにはpublic/storageからシンボリックリンクを張る
cmdのphp artisan storage:link
ストレージ
https://reffect.co.jp/laravel/laravel-storage-manipulation-master
config/filesystems.php に設定があり
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
storage/app/publicがpublic diskになっておりファイルが保存されるが
アクセスするにはpublic/storageからシンボリックリンクを張る必要がある
ララベルでは/publicに通常アクセスさせるから
php artisan storage:link
URLメソッド
https://blog.capilano-fw.com/?p=2537
echo url('/'); //url()の引数に空白もしくは/を指定するとトップページを取得
定数 const
https://qiita.com/clustfe/items/4fa169c6d5114a9b6f4e
https://hiroto-k.hatenablog.com/entry/2018/03/28/213000
config/*.phpにenv()の値を入れてconfig()から参照
config/const.phpを作り下記を入れCache更新で読まれる
<?php
return [
'validate_limits' => [
'MAX_UPLOAD_SIZE' => 4032,
],
];
呼び出しconfig('const.validate_limits.MAX_UPLOAD_SIZE')
■依存性の注入という概念を核とするフレームワーク
依存性の注入,Dependency Injection(DI),Inversion of Control(制御の反転)とも言われ(IoC)
DI コンテナでクラスの生成を1箇所に集約、保守性、柔軟性、テスト性が上がる
composerでカレントディレクトリにPimpleをインストール
composer require pimple/pimple:~3.0
Illiminate\Foundation\Application クラスが DI コンテナにあたります
<?php
require "vendor/autoload.php";
interface SenderInterface {
public function send($message);
}
class MailSender implements SenderInterface {
public function send($message) {
return "メールで送りました。";
}
}
class GMailSender implements SenderInterface {
public function send($message) {
return "GMailで送りました。";
}
}
class Messenger {
protected $sender;
public function __construct(SenderInterface $sender) {
$this->sender = $sender;
}
public function send($message) {
return $this->sender->send($message);
}
}
//Config(DIコンテナにバインドすると言う)
$container = new Pimple\Container();
$container['mail'] = function($container) {
// return new MailSender();
return new GMailSender();
};
// メールで送る
$messenger = new Messenger($container['mail']);
echo $messenger->send("合格通知") . "\n";
?>
■ジョブキュー(Job Busというのもあるらしい)
時間の掛かる処理を非同期で実行、下記の6種類くらい
sync: デフォルト設定で、実際には同期処理として動きます
database: データベースをジョブキューとして使います
beanstalkd: beanstalkd オープンソースのジョブキューです
sqs: Amazon Simple Queue Service 有料サービスです
データベースの場合
.env、config/queue.phpを編集
ジョブテーブルが必要
php artisan queue:table
php artisan queue:failed-table
php artisan migrate
ジョブの作成
php artisan make:job SendReminderEmail --queued
app/Jobs/SendReminderEmail.php にできるので処理
コンストラクタでこのコマンドに必要なデータを受け取る
handle() メソッドでこのコマンドがやることを実装
routes.phpでQueue::push()やコントローラを作成しdispatch()を使う
データベースの jobs テーブルを確認
select * from jobs;
キューの中のジョブを実行するには、キューリスナーを動かす必要がある
php artisan queue:listen
キューの最初のジョブだけ実行したい場合(リスナーならずっと動くから)
php artisan queue:work
■タスクスケジューラ(Cronの代わり)
app/Console/Commands/Kernel.phpに記載
$schedule->command('auth:clear-reminders')->daily();
$schedule->call('YourClass@someMethod')->hourly();
$schedule->exec('cp oldThing newThing')->weekly()->mondays()->at('13:00');
毎分のcronエントリー1つだけ必要
* * * * * php /path/to/artisan schedule:run 1>> /dev/null 2>&1
■イベントとリスナー
app/Providers/EventServiceProvider.phpに登録
class EventServiceProvider extends ServiceProvider {
protected $listen = [
'App\Events\UserWasRegistered' => [ //イベント
'App\Listeners\SendWelcomeMail', //リスナー
],
];
}
イベントとリスナーの生成
php artisan event:generate
event:generateは、a
Posted by funa : 12:00 AM
| Web
| Comment (0)
| Trackback (0)
January 3, 2016
Git
■Git
https://backlog.com/ja/git-tutorial/intro/01/
コマンドを使わずに理解するGit - Qiita
Gitを使いこなしたい!〜仕組みとコマンド24選〜 - Qiita
[初心者向け]GitとGitHubの使い方を徹底解説 - Qiita
Gitのローカルリポジトリには下記がある
リモートブランチ (リポジトリのorigin ブランチのmaster)
=== ↕ ===
ローカルリポジトリ(上記の4つが含まれる)
┣リモート追跡ブランチ (リモートのコピーをローカルに置いている、git fetch、ブランチのorigin/master)
┣ローカルブランチ (git merge/pull、ブランチのmaster)
┣インデックス(コミットデータ git commit)
┗ワーキングツリー (実データ)
ブランチの概要 #初心者 - Qiita
最もポピュラーなリモートリポジトリ名の 「origin」 にあるmaster
ローカルリポにあるリモート追跡ブランチでは「origin/master」
ローカルブランチでは「master」
origin master はリモートのoriginリポのmasterブランチを○○するという意味
origin/master はローカルリポにあるリモート追跡ブランチを○○するという意味
Gitクライアント、Sourcetree/TortoiseGit etc
ローカルリポジトリとリモートリポジトリを作りソース管理、通常別途で運用サーバにデプロイ
ローカルのリモート追跡ブランチ(リモートリポジトリのコピーをfetch)は
originという名がつきorigin/ブランチ名、リモート/ローカルのデフォブランチは両方通常はmaster
チェックアウトするとローカルの作業ソースの内容がその版に切り替わる
ワークツリー(作業)とインデックス(中間)を持ちローカル作業をindexにaddしcommit
バグ修正や機能追加などの異なる意味を持つ変更は、できるだけ分けてコミット
コメント 1行目 : 変更内容の要約 2行目 : 空行 3行目以降 : 変更した理由
cloneで、リモートリポジトリの内容を丸々ローカルリポジトリとしてDL
Pullで、リモートリポジトリから最新の変更履歴をローカルリポジトリにDL
Staged changes(index)に入れる → コメントを付記しCommitする
PushしリモートリポジトリにUPする(fast-forwardマージ)
///ブランチ運用モデル https://backlog.com/ja/git-tutorial/stepup/05/
master(デフォ)
hotfix
release
develop
feature
masterとdvelopの2つがメインブランチで大きな流れ
releaseブランチでリリースの調整、ブランチ名にrelease-をprefix
緊急修正の場合hotfixブランチで調整、hotfix-をprefix
featureブランチで機能追加しdevに纏める
※もしUAT/QAサーバがあるならmaster/developに加えてもう一本QAブランチがあってもいい
使用(ワークツリー)のブランチを切り替えるにはチェックアウト
HEADとは現在使用しているブランチの先頭を表す(更新の先頭のイメージ)
stashでコミットしていない変更を退避させ、今すぐやりたい作業をしてから、退避させていた変更を取戻して作業を再開することができる(変更があればcommitするまでブランチを切り替えができない)
mergeは複数のブランチを統合し両方の変更を取り込んだマージコミットが作成されます。masterブランチの先頭はそのコミットに移動。non fast-forwardを行うとブランチがそのまま残る
rebaseはmasterブランチの前に別ブランチの内容を付与する。先頭はmasterブランチのままなので、mergeもする。トピックブランチに統合ブランチの最新のコードを取り込む場合はrebaseを使う。iオプションでコミット書換、入替、削除、統合の制御可 git pull --rebase
git pull と git pull –rebase の違いって?図を交えて説明します! – KRAY Inc.
git pull --rebaseをpushする前にやろうという話。 - Qiita
自分の作業中に元のブランチに変更がかかった場合、その変更を取り込んでPushする必要がある>マージかリベース (リベースの方がツリーがきれい)
master ブランチ用のfeat/20240727a の場合
git pull --rebase origin master
リモートリポジトリ (origin) から指定されたブランチ (master) の最新の変更をもとにリベース
git pull-rebase
カレントの作業ブランチがビハインドなのでPushできないためリベース
git push
stgプランチ用のfeat/20240727a-stg の場合(stgブランチから切った作業ブランチ、masterから切った作業ブランチをマージしている)
git pull-rebase origin staging は不要で上記のリベース分をマージする
git merge feat/20240727a
git push
ちなみに下記はデフォルトのまま git pull-rebase等のオプションで操作するのが良さそう
git config pull.rebase false #merge (the default strategy)
git config pull rebase true #rebase
git config pull.ff only #fast-forward only
Gitのマージ(pull)方式には、fast-forward & non-fast-forwardの2種類
ffの早送りは自分の作業ブランチでの走行中に他の修正がなく先頭になる
デフォルトだと merge なのか fast-forward なのか実行時に判明する
pullを実行してから次のpushをするまでの間に、ほかの人がpushをしてリモートリポジトリを更新してしまっていた場合、マージを行なって他の履歴での変更を取り込むまで自分のpushは拒否されます(競合)マージは自動統合を行うが同じ箇所の場合はエラー。解決をして自分でコミットする必要がある
fetchは単にリモートリポジトリの内容を確認したいだけの時。ローカルに統合したい時はFETCH_HEADをマージするか、改めてpullを実行します
軽量タグと注釈付きタグの2種類。軽量タグはローカルで一時的に使用。タグで過去に戻せる
amend:直前のコミットを修正
revert:指定したコミットを打ち消すコミット
reset:コミットを捨てる
変更したインデックスの状態を元に戻す(mixed)
最近のコミットを完全に無かったことにする(hard)
コミットだけを無かったことにする(soft)
cherry-pick:指定のコミットを現在のブランチに取り込む
mergeのsquashオプション:該当ブランチの全コミットを一つのコミットに纏めて統合
(競合は修正してaddし直したいが、、、)
fetchでエラーがあれば git reset --hard HEAD で作業を取り消し
pullでエラーがあれば git merge --abort と git reset --hard HEAD でマージと作業取り消し
githubでマージエラーがあれば git checkout kuso-sagyo > git pull origin master > 競合解消作業 > git commit > git push origin HEAD
プルリクエスト https://backlog.com/ja/git-tutorial/pull-request/03/
機能追加や改修など作業内容をレビュー・マージ担当者やその他関係者に通知する
プッシュされたコミットは自動的にプルリクエスト上に反映
プルリクエストは一覧され未完了のプルリクエストを確認しレビュー・マージ担当者は漏れなく処理可
ソースコードの変更箇所をわかりやすく表示、コメントのやり取り可
1[開発者] 作業対象のソースを clone または pull
2[開発者] 作業用のブランチを作成
3[開発者] 機能追加、改修といった開発作業
4[開発者] 作業が完了したら push
5[開発者] プルリクエストを作成
6[レビュー・マージ担当者] 通知されたプルリクエストから変更を確認しレビュー
7[レビュー・マージ担当者] レビュー結果を判断し必要ならば開発者にフィードバック
8[レビュー・マージ担当者] レビューの結果、問題がない場合はマージ
9[レビュー・マージ担当者] レビューの結果、対応自体が不要となるなど、プルリクエスト自体が必要ない場合はクローズ
====================
Gitクライアント Sourcetree
https://eng-entrance.com/sourcetree-usehttps://tracpath.com/bootcamp/learning_git_sourcetree.html新しいverのSourcetreeではインストールができなかった ver 2.6.10.0ならOK
https://www.sourcetreeapp.com/download-archives
IEは上手く動かず Chromeを使う こちらでもインスコはできなかったが
SSH鍵をputtyで https://webkaru.net/linux/putty-ssh-login-public-key/
データフォルダに.gitフォルダがあるので別のGITクライアントでもデータフォルダをDDするだけ
文字化けはKB4074906では直らなかった、UTF8⇔Shift-jisでも直らん?
Virtualbox等のLinux環境でインストールが良いかも?
sudo apt-get install git だったかと
gitのバージョンを上げる
プロキシを引き継ぎながら最新GITを取れるように ppaをリポジトリに追加
sudo -E add-apt-repository ppa:git-core/ppa
sudo apt update
sudo apt upgrade
git --version
====================
git init --bare --shared 空のリモートリポジトリ(ワークツリーのない開発メンバー全員で使う共有のリポジトリ)を作成
git remote add origin https://github.com/YY/XX.git リモートリポジトリに名前設定:git remote add [追加リモートリポジトリ名] [追加する場所リポジトリ]
git remote -v リモートリポジトリの確認
git init 各人使用したいローカルディレクトリに移動しリポジトリ(dir)の.gitを作成
git status 状態確認
git clone https://github.com/YYYYYY/XXXXX.git リモートリポジトリのクローンをローカルに作成
※作成した場所にcdし実行、リポジトリのフォルダもできるのでローカルの/home/おまはん/repoで実行でよい
git clone ssh://user@hostname/path/to/repos GitHub用(鍵登録しssh)
git branch 移動できるブランチとカレントを表示
git branch -a ブランチの一覧を見る(リモート側?)
git checkout master ローカルの使用ブランチを切替
git pull origin master リモートの該当ブランチをローカルの使用中のブランチに(git pull=fetch+merge)
git fetch origin master リモートのデータをリモート追跡ブランチに取り込む(変更点を確認
git merge origin/master リモート追跡ブランチにある変更点を取り込む
【Git基礎】git push origin masterのmasterはローカル/リモートどっちのこと? #Git - Qiita
git fetch origin master はリモート側のマスターブランチを差す
git push origin master はローカル側のマスターブランチを差す
ソース:行き先 が本来だが行き先が省略されている
git checkout -b hotfix ブランチhotfixへ移動(-bをつける事でカレントから新規にブランチを作成し移動)
git branch hotfix ブランチhotfixを作成(カレントから?
git checkout hotfix ローカルの使用ブランチを切り替え
※hotfixで修正する場合
git checkout a.txt 特定ファイルの変更を取り消す
git checkout . add前の未追跡編集ファイルの取り消し、作業を取消し別ブランチ切替ができるように
git clean -df . add前の未追跡新規ファイルの取り消し
git reset HEAD . addを取り消し
gitでいろいろ取り消したい #Git - Qiita
git add a.txt 削除したファイルをaddでリポジトリから削除
git rm a.txt リポジトリから削除しディレクトリからも削除
git rm --cached a.txt リポジトリから削除するがディレクトリには残す
rm a.txt ディレクトリから削除、リポジトリには残す
git add -n . アドの対象を表示
git add . カレントdir以下の全てをIndex追加(危ない)
git add *.py ワイルドカード
git add a.txt ファイル追加
git add dirA ディレクトリ追加
git add -A 変更のあったすべてgit add --all
git reset . addを取消す
git diff --cached ステージング(index追加)の内容確認
git commit ローカルレポにindexをコミット、エディターが開く、iインサートモードで編集、ESC:wqで保存
git commit -a -m "comment" -aは変更点がある登録された全ファイル
git log コマンドでコミットの履歴
git show コミットした内容自体を確認
git reset --soft HEAD^ コミットの取り消し
git cherry-pick _commit_id_ 他ブランチでコミットした内容をカレントブランチに適応
※コミットが済んでいないファイルが残っている状態で git checkout の別ブランチ作成や git merge でmasterにマージしない事
git reset --hard HEAD^ 直前のコミットを取消(hardはcommit logが残らず、indexやworktreeもオプで戻せる、綺麗だが競合?)
git reset --hard HEAD~2 数字で複数コミット取消
git stash 退避/git stash list 退避リスト
git revert コミットNo. 直前のコミットを取消す再コミットでチーム開発向き(戻したcommit logが残る)
→commit文を書かされるので保存してgit push
誤ってmasterで修正をしてpushしてしてしまったときにはこれ
git logでコミットIDをしらべ、git revert <commitID>、git pushでmasterにpushしてしまう
git branch -vv 上流ブランチの名前を確認
git config --get remote.origin.url リモートのリポジトリURLの確認
git pull --rebase origin master push前にリモートのmasterの更新を取り込んでおけばコミットが綺麗になる
git push リモートに同ブランチがあれば通るがなければ下の--set-upstreamでリモートに作る
git push --set-upstream origin hotfix push時にリモートに該当ブランチを作成
git push リポジトリ名 ローカルブランチ名:リモートブランチ名 が本来
リモートリポジトリのアクセス先がoriginという名前で省略設定されている
git push origin 20250101aaa:20250101aaa -> git push
これ以外の場合は通常github等のリポジトリ側でPR先を変えるといいと思われるが、、
git pushの取り消しはgithub上でブランチを削除すればよいのではと
リモートでPull Requestを作成
レビュアーはPull Reqeustを確認し問題なければリモートにマージする
hotfix等はPull Requestをmasterにするが同時にその1度のpushをdevelopにもPull Requestする/マージも
プルリクエストでコンフリクトしたときの対処方法(備忘録) - Laravel学習帳 (laraweb.net)
サーバーにデプロイ
git checkout master マスターブランチに移動
git pull マスターからデータを取る
デプロイ作業(サーバにアップロード/terraform apply)
戻し(リバートバック)用にPRを事前準備をしたい
空のaddやcommitはできない
githubのコミットグラフで不要なコミット上でRevertボタンを押すとPRが作成される
戻す可能性がある場合はmasterにマージせず作業ブランチでApply(下記リモートからデータ取得参照)
ダメならmasterでApplyし直す、あるいはRevertボタンを押す
リモートからデータを取ってくる
git branch -r リモート追跡ブランチの一覧(pullしとけば出る)
git fetch origin darekanounko リモートにあるブランチを取得
git checkout darekanounko これで切り替えができる
なければ同名で作ってpull? git checkout -b darekanounko > git pull これはダメ
git initの取消し
rm -rf .git でgit initした場所の.gitファイルを削除
gitの作り直し(最悪これで回復)
rm -rf .git でgit initした場所の.gitファイルを削除し、改めて git clone
git branch -d hotfix/unco072 hotfixブランチを削除 -dはマージ済みのもの、-Dで何でも削除
git push origin :hotfix/unco072 hotfixブランチをリモートから削除
git branch --merged マージしたブランチ一覧
git branch --merged | egrep -v "\*|master|develop" マージしたブランチmaster/dev以外
git branch --merged | egrep -v "\*|master|develop" | xargs git branch -D それらを削除
git remote prune origin リモートで消されたブランチをローカル反映 prune余分な枝を落とす
git branch --format "%(refname:short) %(upstream:track)" ブランチ名とトラック状態を取得
git branch --format "%(refname:short) %(upstream:track)" | grep "\[gone\]" 削除された[gone]のみ取得
git branch --format "%(refname:short) %(upstream:track)" | grep "\[gone\]" | awk '{print $1}' | xargs -IXXX git branch -D XXX それらはリモートで削除されており削除
git stash clear スタッシュを消す
git gc ガーベージコレクション
よく使う お掃除系 git 便利コマンド集 (foresta.me)
コンフリクト
コンフリクトはgithubのPRのマージボタンがあるあたりで見れる
masterから修正ブランチを切り出しているのでstgブランチにマージしようとするとコンフリクトする
(masterには未だマージされていないが、stgには既にマージされているPR)
例えば
<<<< feat/kuso
kuso2 = dead
====
kuso = smells
>>>> stg
github上のresolve conflictで更新を掛けるとfeat/kusoPRに反映され、DEV/STGだけでなく本番へも変更が掛かってしまうため、DEV/STGから切りなおしfeatを合体させコンフリクト解消する
git checkout master
git pull
git switch stg
git pull
git switch -c feat/kuso-stg
git merge feat/kuso
コンフリクトを手修正
git add/commit/push (addがなくても強引にpushすればよい?)
githubでstgへ向けてPRを作成
元のstgへのfeat/kusoPRは却下する
git pull で下記エラー
error: cannot lock ref 'refs/tags/v1.3.38': unable to resolve reference 'refs/tags/v1.3.38': reference broken
→cat .git/refs/tags/v1.3.38 .git内のことで対象を見る、GUIフォルダでも大体空
→rm .git/refs/tags/v1.3.38
→RMすると大概git pullができるようになっている
reference brokenでgit pullできなくなったときの対策 - Qiita
他の対応方法として
→rm -rf おまはんのリポジトリのフォルダ フォルダごと消す
→git clone https://やり直しなはれ クローンやり直す
→git checkout master > git pull > git checkout 飛んだbranch (事前にgit pushで保存しとく)
not something we can merge のエラー
ブランチ名のスペル入力間違い、あるいはローカルにないブランチでmaster pull>該当ブランチにcheckoutしpull等が必要
.gitignoreという設定ファイルにデフォルトで対象外とするファイルを設定
.git/config を見るとどのURLにpushするか分かる
リポジトリが不要になったときは.git dirを削除する。管理ファイル(ワークツリーにないファイル)が削除されワークツリーのファイルはそのまま影響がない
ローカルリポジトリで複数のブランチがある場合、必要なブランチをチェックアウト後ワークツリーのファイルを別途保存してから削除することを勧める
リポジトリを作成し直したい場合は.git dirを削除してから改めてgit initを実行
https://www.atmarkit.co.jp/ait/articles/2003/12/news010.html init
https://www.atmarkit.co.jp/ait/articles/2003/05/news006.html clone
https://www.atmarkit.co.jp/ait/articles/2003/06/news019.html pull
https://www.atmarkit.co.jp/ait/articles/2003/13/news031.html add
https://www.atmarkit.co.jp/ait/articles/2003/19/news018.html commit
git: git stashの使い方 - Qiita
https://www.atmarkit.co.jp/ait/articles/2005/21/news023.html push
https://www.atmarkit.co.jp/ait/articles/2005/22/news028.html push衝突
https://www.atmarkit.co.jp/ait/articles/2004/24/news028.html checkout
https://www.atmarkit.co.jp/ait/articles/2004/30/news017.html checkout2
https://www.atmarkit.co.jp/ait/articles/2006/11/news025.html revert
https://www.atmarkit.co.jp/ait/articles/2007/01/news015.html revert2
https://www.atmarkit.co.jp/ait/articles/2007/10/news010.html revert3
https://www.atmarkit.co.jp/ait/articles/2007/27/news013.html reset
Git revertとresetについて - Qiita
https://www.atmarkit.co.jp/ait/articles/2004/09/news018.html log
https://www.atmarkit.co.jp/ait/articles/2004/16/news025.html log2
https://www.atmarkit.co.jp/ait/articles/2004/17/news021.html show
https://www.atmarkit.co.jp/ait/articles/2004/23/news034.html show2
https://www.atmarkit.co.jp/ait/articles/2005/01/news024.html tag
https://www.atmarkit.co.jp/ait/articles/2005/07/news009.html tag2
https://www.atmarkit.co.jp/ait/articles/2005/08/news017.html remote
https://www.atmarkit.co.jp/ait/articles/2005/14/news025.html remote2
https://www.atmarkit.co.jp/ait/articles/2006/04/news022.html rm
https://www.atmarkit.co.jp/ait/articles/2006/05/news021.html rm2
https://www.atmarkit.co.jp/ait/articles/2006/12/news017.html mv
■ツール
git :: bash プロンプトにブランチ名と作業ツリーの状態を表示する [Tipsというかメモ] (root-n.com)
home/.bashrcに追記、1行目が切れがちで注意
Posted by funa : 12:00 AM
| Web
| Comment (0)
| Trackback (0)
January 2, 2016
Agile
■アジャイル
http://codezine.jp/article/detail/546510年ちょっとやってきた僕のアジャイル開発の現在地スコープを柔軟化するため、スプリントで区切り、スプリント後は動作するようにする、しかしスケジュール/リソースは固定
ボトムアップとして(ストーリー、タスクなどの)バックログ。WBSはトップダウンだった
スクラムやXP等を使う
- 要求機能はストーリーとして表現される(エピックはストーリーを一定のジャンルでグループ化し可視化)
- プロダクトバックログを作成し、直近のリリース(スプリント数個分)ごとにリリースバックログを作成する
- スプリントごとにスプリントバックログとして作業を詳細化(時間単位)する
- スプリントの完了時には、テストされ、デモが可能な状態でなければならない
スプリントを導入しても、設計、実装、単体テスト、結合テストとタスクを分割していたのでは、ミニウォーターフォール
逆に管理工数がかかったり品質が下がるかも。継続的統合やテスト駆動開発などが要る
1.計画を簡易的に行なう(スプリント単位で等)
2.その代わり定期的に見直す
3.簡易な計画/管理ツールを利用する
4.チームとしてスケジュールを組む
粗い要求までもリストアップするプロダクトバックログ(エクセルレベルで可)
次のリリースのためのリリースバックログ(エクセルレベルで可)
直近のスプリントのためのスプリントバックログ(タスク管理システムにすると意識しなくても良いかも)
初日にプランニングミーティングを行い、直近(2週間等)のタスクを計画
そして、毎日デイリースクラムを実施し、最終日にレトロスペクションミーティングで締めて
スプリントの1サイクルとなる
ミーティングでは、タスク管理システムないしは、
ホワイトボードに張られたタスクやバックログリスト(場合によってはガントチャート)などの
タスクを一覧できるツールを用いる
///プランニングミーティング
プロダクトバックログから優先順位に従って選択したストーリーをタスクにブレークダウン
ミーティング前
1.タスクを決定する
ミーティング時
2.前スプリントのタスク完了を確認する
3.メンバーの予定作業時間を確認する
4.スプリントのゴールを共有する
5.タスクを説明し工数を見積もる
ミーティング後
6.タスクを割り当てる
///デイリースクラム
昨日何をしたか?
今日何をするか?
進捗を妨げている問題は何か?
///レトロスペクションミーティング
何をしたかについて、1人数分から十数分説明する
何ができないか、どのような課題が残っているかに言及する
↓↓↓↓↓↓アジャイルから明確にスクラム
■スクラム
https://qiita.com/gold-kou/items/90ba982a14ca79d843c9
///対話の価値(左が要らないとは言っていない)
プロセスやツール < 個人と対話
包括的なドキュメント < 動くソフトウェア
契約交渉 < 顧客との対話
計画に従う < 変化への対応
透明性:スクラムチームの現状や問題点を見える化すること
検査:見える化により問題点を見つけること
適応:スクラムチームに問題があった場合に、改善策を考えて対処すること
個人はスクラムチームのゴールの達成を確約しなければならない
メンバーは正しいことをする勇気を持ち困難な問題に取り組まなければいけない
全員がスプリントの作業とスクラムチームのゴールに集中しなければいけない
スクラムチームとステークホルダーは仕事や課題とその遂行の様子を公開する
メンバーはお互いを能力のある独立した個人として尊敬しなければいけない
///プロダクトオーナー(PO)
- プロダクトバックログアイテム(PBI)の管理
- リリース計画策定
- 市場調査
- ステークホルダとの対話
- 開発チームとの対話
- 予算管理
- スプリントレビューで"DONEの定義"にしたがって受け入れ判断をする
注意点:POを複数人で実施することも可能だが、その場合は代表者を1人決めておく必要がある。
///スクラムマスター(SM)
- 妨害リストの管理
- 妨害の除去
- POのサポート
- 開発チームのサポート
注意点:チームが自己組織化するために、SMはメンバーに直接的な指示(タスク割り当てなど)や管理(進捗管理など)をしてはいけない。スクラムにはPMは存在しない。
///開発チーム
- 開発、インクリメント(成果物)を完成
- プロダクトバックログの追加
- 妨害リストの追加
注意点:開発チームは自己組織化されており、外部から仕事の進め方やタスクを指示されるようなことがあってはならない。1つの開発チームは3-9人で構成されなければならない。それより少ないと機能横断的でなくなる可能性が高くなるためNG。多すぎると調整が大変になってしまうためNG。多すぎる場合は別のスクラムチームをもう1つ作るべき。開発チーム内で年齢や役職、会社の違いがあったとしても全員フラットな関係でなければならない。開発チームに専門能力の高いメンバーがいて、その分野ではその人に頼りがちだけど、そこで問題が起きたとしてもそれはそのメンバーだけの責任でなく開発メンバー全員の責任であることに注意する。
///ユーザーストーリー形式
「〜として、〜したい。それは、〜だからだ。」を書きます。これは、INVEST(Independent, Negotiable, Valuable, Estimable, Small, Testableの頭文字をとったもの)を満たす必要があります。プロダクトバックログのDoneの定義も定義
///スプリントバックログ
開発チームにより作成される。スプリント期間中での修正、追加、削除も可能である。スプリントバックログの管理を行えるのは開発チームだけである。規模や工数はバラバラで問題ないが、1つのスプリントバックログアイテムの見積もりは1日以下の大きさに分割すること。スプリントバックログアイテムは"未着手"、"着手中"、"完了"などのいずれかのステータスがラベル付けされており、そのステータスが可視化されている必要がある。JIRAでも付箋とホワイトボードによるアナログ方式でもどちらでも問題ない。自己組織化されているので、誰かに割り当てられるものではなく自ら挙手する。設計、コーディング、テストコードの作成だけでなく、結合テストなどの実施、CI環境改良、ノウハウを残すなどもスプリントバックログとして分割するべきである。
///妨害リスト
スクラムチーム内外で、妨害になっていることを優先度順にリスト化したものである。どのロールの人でも追加できるが、妨害リストの管理の責任者はSMである。いつでも追加可能だが、特にデイリースクラムやスプリントレトロスペクティブで課題(妨害)の共有が行われやすい。
///スプリント
1ヶ月以内の固定した開発期間を何度も繰り返す。1週間、2週間、1ヶ月のいずれかが一般的。スプリント期間内に完了しなかったプロダクトバックログアイテムがあったとしても、スプリントを延長してはいけない。スプリントの中止はよっぽどのことが無い限り、行われるべきでないが、もしものときは実行権限を持つのはPOだけである。
///スプリント0
自己紹介、スクラム理論の勉強会(認識合わせ必須)、当面のプロダクトバックログの作成と共有、必要技術スキルの勉強会、開発環境構築などを行うスプリント開始前の準備期間のこと。必要期間はチームにより異なる。
///リリーススプリント
インクリメントの統合テストや通常スプリントで残ったタスクを実施してリリースを行うための特別なスプリント。 原則、このスプリントは存在しません。スプリント毎にリリース可能なものを作成するので、リリーススプリントが無いことが理想だが、そうでない場合に用意される。リリーススプリントはPOがリリース準備が整ったと判断するまで続く。
///イベント
開発チームでイベント以外のミーティングができるだけ行われないようにする。全てのイベントはタイムボックス化されている(何分とか、何時間までとかが決まっている)。もし、タイムボックスを超えてしまった場合、議論をそこで打ち切る必要はないが、タイムボックスを越してしまったという事実は妨害リストに追加したり、スプリントレトロスペクティブで話し合う必要がある。
///スプリントプランニング
第一部は全てのロールが参加する。ただし、第二部はPOは連絡がつく状態であれば参加しなくてもよい。第一部では、ベロシティをもとに今回のスプリントで対応できそうな範囲でプロダクトバックログを開発チームが選択する。(POが選択してはいけない)
プロダクトバックログはリファインメントによってすでに見積もりがされている状態のはずだが、リファインメント後に新規追加されたプロダクトバックログアイテム(つまり見積もりがまだされていないもの)が含まれている場合は、この場でリファインメントを実施する。第二部では、開発チームは選択したプロダクトバックログアイテムをスプリントバックログに分割する。これにより、POとSMにどのようにプロダクトバックログアイテムを消化できるかを伝えられる状態になる。分割したスプリントバックログに時間数を見積もり、その総計が1スプリントでのチームが開発できる時間をオーバーした場合は優先度の低いプロダクトバックログから外していく。逆に余裕がある場合なプロダクトバックログを追加する。POの予想より多すぎたり少なすぎたりする場合は、開発チームとPOは話し合う。開発チームは選択したプロダクトバックログアイテムを完了することに全力を注がなければならないが、完了することを約束するわけでない。なぜならば、見積もり時にはわからなかった技術的に困難な事象が発生することはよくあるからである。無謀な長期の残業は行わない。
///デイリースクラム
- いつ?⇒毎日同じ時間(一般的には朝)
- どこで?⇒どこでもいいがいつも同じ場所
- 誰が?⇒開発メンバー。SMは必要に応じて参加する。POは見学(発言は基本的にNG)してもよい。
- 目的は?⇒開発チームの検査
- どれくらい?⇒最大15分
昨日やったこと、今日やること、あれば課題(妨害)の共有。課題は共有に留めること。管理職の見学は避けたい。なぜならば、共有でなく管理職への報告になりがちで自己組織化が損なわれやすいのと、課題共有がしにくい雰囲気になりやすいからである。もし管理職にエスカレーションするべき課題があるならば、デイリースクラム後に報告すること。
///プロダクトバックログリファインメント
- いつ?⇒スプリント期間中であればいつでも良い。
- 誰が?⇒全てのロール
- 目的は?⇒プロダクトバックログの透明性の獲得
- どれくらい?⇒最大1日(8h)
POはプロダクトバックログの説明(前回からの変更分、追加分、削除分、詳細決定部分、順序変更部分など)を行う。リファインメントの対象は、次のスプリントあるいはさらにその次のスプリントで開発対象となりそうなくらいの範囲となる。優先度低いプロダクトバックログの説明までは行う必要はない。本当に実施するかも不透明だし変更も発生しやすいため。開発チームはプロダクトバックログへの意見(追加アイディアや順序変更や質問など)、新しいプロダクトバックログアイテムの見積もり、必要であれば再見積もりを行う。
///プランニングポーカー
プロダクトバックログの見積もりには"プランニングポーカー"と呼ばれる手法が一般的に使われる。プ開発チーム全員がフィボナッチ数列(0, 0.5, 1, 2, 3, 5, 8, 13,...∞)の値が書かれたカードを持ち、プロダクトバックログアイテムごとに「いっせーのせ!」でカード(見積もり)を提示する。この見積もりは単位のない"相対見積もり"である。見積もりの値が似たような値で均等に分散したとき(例えば5が3人で8が3人の場合)は、悲観的に考えて大きい値(ここでは8)をストーリポイントとして計算したほうがよい。
///スプリントレビュー
- いつ?⇒スプリントの終わり
- 誰が?⇒全てのロールとPOが招待した重要な関係者(ステークホルダーなど)
- 目的は?⇒インクリメントの検査とプロダクトバックログの適応
- どれくらい?⇒最大2時間(スプリント2週間の場合)
開発チームはインクリメントのデモを実施して、質問に答える。また、完了できなかったプロダクトバックログがあれば説明する。開発チームはデモをやることと受け入れに通ることばかり考えがちだが、大切なのはスプリントレビューを通して、よりよいプロダクトを得るための手がかりを見つけることである。デモはそのための手段であって目的ではないことに注意しよう。また、デモの説明スライドは作るべきでない。そこに労力が割かれがちだからだ。POはDONEの定義に従い、インクリメントが受け入れ可能かを判断する。
///スプリントレトロスペクティブ
- いつ?⇒スプリントレビュー後かつ次のスプリントが開始される前
- 誰が?⇒SMと開発チーム。POは参加してもよいが必須でない。
- 目的は?⇒スクラムチームの検査と適応
- どれくらい?⇒最大1.5時間(1スプリント2週間の場合)
スプリントで人・プロセス・ツールの観点から問題がなかったか、もっと成果を出すためにできることがないかを議論し、次回のスプリント以降の改善策を考える。手法として、KPT(Keep, Problem, Tryを出し合うこと)がよく使われる。
///ベロシティ
ベロシティとは、そのスプリントで開発したプロダクトバックログのストーリーポイントの合計である。スクラムチームはベロシティを高めて安定させることを目指す。そもそもストーリーポイントがいい加減な値。フィボナッチ数列の値しかだせないし、開発者は技術的な不安点があるからとりあえず大きな値をしばしば出しがちである。さらに、スプリントの日数は祝日、メンバの休暇などでスプリント毎に異なるものである。
スクラムではテスト専門チームの存在を許していない。スプリントの中で徹底的にバグを発見して潰すべきなのである。
■スクラムガイド Ken Schwaber & Jeff Sutherland
2020-Scrum-Guide-Japanese.pdf (scrumguides.org)
■マネジメント向け アジャイルの利点
https://www.ryuzee.com/contents/blog/13147
■カンバン
ToDo、進捗、ワークフロー整理、振り返り、で活用できれば
カンバンの基本のキ - Qiita
※なおトヨタのカンバン方式は意味自体はJust in timeの意、中で使われていた伝達法もTodoリストと違う、生産と運搬のタグみたいなもの
■JIRA
コンポーネントはプロジェクトを分割(トップダウン)
エピックはストーリーを一定のジャンルでグループ化(ボトムアップ)
タスクはスプリントの期間で終わり作業が内容が分かるタイトルに
ラベルがあれば時間集計できるので作業ラベル
Posted by funa : 12:00 AM
| Web
| Comment (0)
| Trackback (0)
January 1, 2016
PHP Developer
■スクラム
https://www.bangboo.com/cms/blog/page_321.html
https://www.ryuzee.com/contents/blog/7137
プロダクトオーナー(バックログ並び)
スクラムマスター(外部からチームを守る)
デイリースクラム(毎朝)
プロダクトバックログをスプリントバックログに
ベロシティ(工数)
レビューをしてリリース可能な状態に(実際のリリースはビジネス判断)
スプリントレビュー(デモ)
スプリントレトロスペクティブ(チーム改善)
■PHP開発
http://www.objective-php.net/
オブジェクト指向(クラス、メソッド、プロパティ)、MVCについて
まずプログラムが動くようにしてから必要ならクラス化やMVCにすればよい、大体は不要だが
fatコントローラならページ化した方がいいのだが
MVCのモデルMをロジックとデータの2段構成→ファイル増え逆に一元管理ができないしょ
利点:オブジェクト指向は他言語への応用力鍛錬、MVCはVの役割分担、参入障壁
Cを無くしVがハンドルする、Page-Objectモデルが、レスポンスも早く、込み入った処理/デザインも出来てよいけど
靴紐やら枠嵌よりHTMLやら言語やらはネイティブがいい
SPA(Single Page Application)はJSがサーバに欲しいデータを要求する、MVCがダメだからPOモデル
■オブジェクト指向のルール
カブセル化:隠蔽するべくできるだけpublicメンバを使わない
継承:親クラスのプロパティやメソッドが引き継がれる(private以外の)、ルールが多くありOOにできる
ポリモーフィズム(多態性):オーバライドやオーバロードでメソッドを状況で使分ける
//// アクセス修飾子
public オブジェクト外からアクセス可
private オブジェクト外からアクセス不可、継承されない
protected オブジェクト外からアクセス不可、継承される
//// コンストラクタ
__construct()はインスタンスの生成時に一度だけ自動的に実行される
アクセス修飾子は基本的にはpublic
//// オーバーライド
継承クラスで親クラスのメソッドを上書きし乗っ取る
//// 静的メンバ
static修飾子をつける
インスタンスを生成しなくてもアクセス可能(publicにしておくと)
「クラス名::メソッド名()」で呼び出す
staticメソッドはインスタンスから呼び出せない(クラス自体に属する)
クラスのメソッドでなく関数のような役割
//// クラス定数
const 定数名 = 値
アクセス修飾子は付けられません(クラス定数はpublic扱い)
定数名には「$」は付けません、define関数と同じ
設定値の格納用として普通使う、クラスで纏め分類しておくとdefine関数より管理がし易い
静的フィールドとの違いは値の変更が出来るか出来ないかだけ
//// 抽象クラス
abstractをつける
直接インスタンスを生成できず必ず継承して使用するクラス
継承先のクラスで必ずオーバーライドする必要がある
抽象メソッドとは処理内容を持たずに名前だけ定義されたメソッド
共通で行う処理を抽象クラスとして定義し各画面の処理は抽象メソッドとしておく使い方
//// インターフェイス
インターフェイスとは抽象メソッドのみ定義可能なクラス
抽象メソッドだがabstractはいらない
アクセス修飾子にはpublicしか指定できない
直接インスタンスの生成はできない
実装にはインターフェイスで定義されているメソッドは全て実装する必要があり、アクセス修飾子はpublicで引数の数も名前も完全一致が必要
インターフェイスの実装でポリモーフィズムであることを保障できる
インターフェイスは多重実装可
class FoodProduct implements IProduct, IFood
//// タイプヒンティング
引数で受取るクラスやインターフェイスを制限できる
public function addProduct(Meet $product) ←Meetクラスを指定
public function addProduct(IProduct $product) ←Iproductインターフェイスを指定
//// 名前空間
異なる名前空間同士では同じ名前のクラスが定義できるようになる(長名になりがちなので)
名前空間未指定はグローバル空間、\をつけるとグローバル throw new \Excetpion('hogehoge');
クラス定義ファイルの頭にnamespaceキーワードで名前空間を定義 namespace Food;
使用は2つの方法
1)namespaceを含めたフルパスでクラス名を指定し使用 $item = new \Food\Product();
2)前空間の利用宣言をあらかじめする use Food\Product; $item = new Product();
同名だと衝突するので別名や階層化やオートローダ http://www.objective-php.net/basic/namespace
namespace はディレクトリではなく別名であり、
接頭文でもなく、関数名が被らないように名付時と使用時の両方で宣言してるだけ
関数名被らなければ使用時に気にしすぎる必要はない、下記でOK
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;(App\Http\Controllers\App\Http\Requestsというわけではない)
//// 例外
PHPは勝手に例外を投げないので自分で書くのであまり意味がない(新しい関数やクラスは例外を投げてくれるが)
try {
if($a!==1){ throw new Exception('Bad'); }
echo "End";
} catch (Exception $e) {
Logger::write($e->getMessage());
echo "ERror";
}
-> ERror
//// サンプル
<?php
//カプセル化、アクセス修飾子、コンストラクタ、セッター/ゲッターのメソッド、継承
class Product{
protected $name; // 商品名
protected $price; // 価格
public function __construct($name){
$this->name = $name;
}
public function getPrice(){
return $this->price;
}
public function setPrice($price){
$this->price = $price;
}
}
class FoodProduct extends Product{
private $expire;
public function setExpire($expire){
$this->expire = $expire;
}
public function getExpire(){
return $this->expire;
}
}
$food = new FoodProduct('肉');
$food->setPrice(100);
$food->setExpire(30);
echo '価格を' . $food->getPrice() . '円に設定しました。';
echo '賞味期限を' . $food->getExpire() . '日に設定しました。';
?>
<?php
//静的メンバ(静的メソッド)
class PriceFormater{
private static $fee = 10;
public static function formatJapanese($price){
$price = number_format($price + self::$fee);
$price = $price . '円';
return $price;
}
}
$price = PriceFormatter::formatJapanese(3000);
?>
<?php
//クラス定数
class Tax{
const IMPORT_TAX_RATE = 0.08;
}
class Product{
const TAX_RATE = 0.05;
private $price = 100;
public function getSalePrice(){
$tax = $this->price * self::TAX_RATE;
$tax2 = $this->price * Tax::IMPORT_TAX_RATE;
$price = $this->price + $tax + $tax2;
return $price;
}
}
var_dump(Product::TAX_RATE);
$prd = new Product();
$price = $prd->getSalePrice();
?>
<?php
//抽象クラス(文字追加の処理所要時間測定)
abstract class TimeMeasurer{
abstract protected function process();
public function exec(){
$startTime = $this->getMicrotime();
$this->process();
$endTime = $this->getMicrotime();
$procSecs = $endTime - $startTime;
echo sprintf('処理所要時間は%s秒でした。', $procSecs);
}
private function getMicrotime(){
$splitedMt = explode(' ', microtime());
return $splitedMt[0] + $splitedMt[1];
}
}
class TestClass extends TimeMeasurer{
protected function process() {
for ($i = 0; $i < 1000000; $i++) {
$str .= 1;
}
}
}
$test1 = new TestClass();
$test1->exec();
?>
//インターフェイス、タイプヒンティング、(ポリモーフィズム)
---- Car.php
interface Car{
public function start();
}
GasolineCar.php
class GasolineCar implements Car{
public function start(){
echo sprintf('%s エンジンOK', $this->gasolineIgnition());
}
//関数の戻り値の型をstringで指定
private function gasolineIgnition(): string
{
return 'brrr';
}
}
---- DieselCar.php
class DieselCar implements Car{
public function start(){
echo sprintf('%s エンジンOK', $this->DieselIgnition());
}
private function DieselIgnition(): string
{
return 'vvvv';
}
}
---- driver.php
class driver{
public function on(Car $car){
$car->start();
}
}
index.php
$driver = new driver();
$driver->on(new GasolineCar());
$driver->on(new DieselCar());
//// OO設計
index.php
Dispacherを呼ぶ
↓
abstract class Dispatcher
URL引数を取得
class siteDispatcher extends Dispatcher
URL引数から適切なコントローラを呼ぶ
↓
↓abstract class RequestVariables
↓ $_POST、$_GETを取得
↓class Post extends RequestVariables
↓ Post変数
↓class QueryString extends RequestVariables
↓ Get変数
↓class Request
↓ Post変数とGet変数を纏める
↓
↓class ModelBase
↓ モデルの共通機能(DB接続等)をstaticメソッド、継承してもいい
↓
class CartController extends ControllerBase
カート用コントローラ(ヘッダーやコンテント)
abstract class ControllerBase
カート以外でも使用する共通機能(Post/Get取得やビュー呼出)
↓
class CartHeader
ユーザ情報等のカートのヘッダー情報のモデル
class CartContent
リスト取得や追加や削除の操作のモデル
====
//// オブジェクト指向のメモ
コントローラのメソッド内では変数にスコープをつけなくて良い
メソッド外にはpublic/private/protectedを付ける
インスタンス生成 $a = new Class名; コンストラクタに渡す場合は new Class名(引数);
メソッド使用 $a->メソッド();
-> (クラスのフィールド名、メソッド名) アロー演算子 メンバ変数やメンバ関数を使う
:: (クラスのメソッド名) スコープ演算子 インスタンスを生成していないクラスのメンバ関数を使う事が出来る
class Pet{
var $dog = "wan";
var $cat = "nyan";
function func(){
echo "Welcome";
}
}
echo Pet::cat;
$obj = new Pet();
echo $obj->func();
phpにおける :: と ->に違いについて
アロー(->)演算子を使う場合 インスタンスプロパティとインスタントメソッドにアクセスする echo $a->name
スコープ定義(::)演算子を使う場合 静的プロパティと静的メソッドにアクセスする
https://qiita.com/mpyw/items/41230bec5c02142ae691
| インスタンスプロパティ | インスタンスメソッド | 静的プロパティ | 静的メソッド |
外部から | $v->name | $v->name() | クラス名::$name | クラス名::name() |
インスタンスメソッド内から | $this->name | $this->name() | self::$name | self::name() |
静的メソッド内から | 無 | 無 | self::$name | self::name() |
クラス名に変数が使えるので注意 $con = new AAA(); は下と同じ
$className = 'AAA';
$con = new $className();
$_SERVER['REQUEST_URI']等はグローバル変数なのでどこへでも書ける(クラスやメソッド内等)
====
可変変数
$test = "aaa";
$var = "test";
echo $$var; //"aaa"が出力
echo ${"test"}; //これも"aaa"が出力
echo ${$var}; //これでも"aaa"が出力
${"name_$test"}
$this->{$test}
$foo->{$start . $end}
$foo->{$arr[1]}
三項演算子
条件式 ? 真の式 : 偽の式
$lang = 'En';
$msg = $lang == 'Jp' ? 'こんにちは' : 'Hello';
print $msg;//Hello
エルビス演算子
条件式(真の式) ?: 偽の式;
条件式がTUREと同等だった場合その値または「1」が返され、FALSEだった場合に偽の式が返されます
$a = 4;
$b = 9;
$num = $a < $b ?: 'aはbより大きい値';
echo $num;//1
NULL合体演算子
条件式または$変数 ?? 式;
条件式または$変数の値が「NULL」のとき式が返り、FALSEのときは条件式または$変数の値が返えされます
条件が存在しなくてもnoticeエラーが出ない
$list = ['a' => 1, 'b' => 2, 'c' => 3];
echo $list['b'] ?? '99'; // 2
echo $list['z'] ?? '99'; // 99
https://www.tomcky.net/entry/2018/02/17/093654
https://qiita.com/ritsuka/items/b4f78ac4121ce5e01173
連想配列はforeach
$preflist = array('Tokyo' => '東京', 'Osaka' => '大阪');
foreach ($preflist as $key => $value){
echo $key . ':' . $value;
}
$fruits = array("Orange","Apple","Berry");
for($i = 0 ; $i < count($fruits); $i++){
echo $fruits[$i];
}
配列を指定した値で埋める
array_fill (インデックス, 要素数, "値");
$ar = array_fill (4, 3, "PHP");
Array ( [4] => PHP [5] => PHP [6] => PHP )
配列の中で最も大きい数値を返します
max( array(100, 200, 300) )
min( 100, 200, 300 )
変数の整数としての値を取得する integer
intval('122.34343The') = 122
平方根/べき乗を取得するには、sqrt()、pow()関数
pow(8, 2) = 64
sqrt( 16 ) = 4
NULLか変数ありか空か
(is_null($val01) ? 'TRUE' : 'FALSE')
(isset($val01) ? 'TRUE' : 'FALSE')
(empty($val01) ? 'TRUE' : 'FALSE')
値の出現回数の総ざらい
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
[1] => 2, [hello] => 2, [world] => 1
asort($A)値で昇順にキー保持しソート、連想配列向き arsot($A, SORT_STRING)降順にソート,文字のモード
sort() / rsort() ソート後にキーが添字配列が付け直される
文字列を配列に変換する
str_split('hel')
[0] => H
[1] => e
[2] => l
配列に追加
$hoge['key2'] = 'value2';
$hoge[] = 'AAA';
array_push($hoge,'CCC','DDD');
array から要素を削除、ループ中のcount()現象に注意
unset($arr[1]);
$arr = array_values($arr);//添字が0から振られ直す
breakはデフォルトでは一番内側のwhile文を抜けて次の処理へ移る
ネストの場合は抜けたい階層の数を指定 break 2;
現在のループ処理を抜けて、次のループ continue;
配列のキー・添字を確認
$ar = array("PHP" => 4, "CGI" => 5);
if(array_key_exists("PHP", $ar)){
配列の値の有無をチェック
$ar = array("PHP", "CGI", "PERL");
if(in_array("PHP", $ar)){
シリアライズ
ソフトウェア内部で扱っているデータを丸ごと、ファイルで保存したりネットワークで送受信することができるようにバイトストリームに変換する、これにより配列やオブジェクト等ををデータベースやテキストとして保存したりすることができる、シリアライズ後の文字列は「型:値」の形式に変換されている(string:byte数)
$data=array('key1' => 'value1','key2' => 'value2');
$serial=serialize($data);
var_dump($serial);//string(54) “a:2:{s:4:”key1″;s:6:”value1″;s:4:”key2″;s:6:”value2″;}”
//戻す $data=unserialize($serial);
■ファイルアップロード(のエラー判定)がダメはphp.ini
memory_limit (メモリ使用量の上限)128MB
post_max_size (POSTの最大サイズ ※1回の全upファイルの合計サイズ)8MB->16M
upload_max_filesize (1ファイルあたりの最大アップロードサイズ)2MB->8MB
memory_limit >= post_max_size >= upload_max_filesize > MAX_FILE_SIZE で設定する必要がある
max_execution_time スクリプトの実行時間 30
file_uploads ファイルアップロードが許可されているか On
max_file_uploads 一度にアップロードできるファイル数 20
apacheに「LimitRequestBody」がありデフォ2GB いくらPHP側でそれ以上を設定をした所でHTTPリクエストで駄目(FTPが必要?)
<?php phpinfo(); ?>で確認
php.iniを変更する(通常これ)
htaccessで設定する
httpd.confで設定する
1)<input type="hidden" name="MAX_FILE_SIZE" value="8000000">のタグを埋めハンドリング
超えると$_FILES['userfile']['error']で0以外の確か2が返る
2)アプリ側でも閾値を持ち$_FILES['userfile']['size']でエラーハンドリング、小さめに設定
しかしファイルが大きすぎるとPHPではファイルサイズが0になり不明になるが
$_SERVER['CONTENT_LENGTH']でPostサイズは取れる→(2)で
3)upload_max_filesizeを超えると$_SERVER['CONTENT_LENGTH']でエラーハンドリング
これなら(1)のアプリ制限を持たす必要もないが動的に制限を掛けたい場合に
4)post_max_sizeを超えるとアプリが落ちるので大き目に設定
※下記の考え方は参考になるがコードは間違っている
upload_max_filesize post_max_sizeエラーの対策 CakePHP - watuu's diary (hatenablog.com)
php — PHPの `post_max_size`を超えるファイルを適切に処理する方法は? (it-swarm-ja.tech)
■Javascript
関数宣言>無名関数>ES6 クラス で書き方の変遷
コツ、使用、注意事項をまとめてある
https://www.bangboo.com/cms/blog/page_325.html
■CSSレイアウト
https://www.bangboo.com/cms/blog/page_327.html
Grid 格子状のレイアウト(テーブルレイアウトな感じで)
flexbox 1行の横並び、縦並び
float テキストの回りこみ
https://speakerdeck.com/tonkotsuboy_com/2019nian-madenijian-zhi-siteokitai-cssjavascriptfalseshou-fa
https://qiita.com/kura07/items/e633b35e33e43240d363
https://idotdesign.net/blog/web/htmlcss/css-grid-layout/
http://www.htmq.com/css3/
■CSS
Lightboxなしモーダル https://unicolabo.jp/topics/668.html#overlay
https://www.bangboo.com/reserve/index.php
Formのフォーカスやツールチップ https://www.go-next.co.jp/blog/web/html_css/23603/
Table Trオンマウス https://gray-code.com/html_css/change-style-when-cursor-is-on-table-line-or-cell/
■HTMLタグ
https://qiita.com/kudo_kk/items/b2b1341b2b2543b6fa58
alt属性は画像の代替テキスト
title属性はふきだしチップを表示
/// HTML5
https://www.bangboo.com/cms/blog/page_273.html
■Laravel ララベル
https://coinbaby8.com/laravel-php-dekirukoto.html
https://laravel10.wordpress.com/
ルーティング: URLと対応 .phpで終わせず処理をひとつのファイルやクラスにまとめる
Blade: テンプレートエンジン
ミドルウェア: URL前後に処理を付加
エラーハンドラ: 例外やエラーが発生した際の処理
DI : サービスコンテナというのを用いクラスインスタンスの依存度を極力下げて、実行時に外部から与えてもらえるように
バリデーション: 入力値のチェックを設定のみで自動的に
データベース連携
認証の自動化
インスコ~機能~使い方
https://www.bangboo.com/cms/blog/page_324.html
■IDE/Editor
VS code, Atom, PhpStorm, etc.
HTMLエディタ: Dreamweaver, Brackets etc.
https://hota1024.com/2018/02/19/php%E3%81%AE%E3%81%8A%E3%81%99%E3%81%99%E3%82%81%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF5%E9%81%B8/
Visual studio codeにPHP intelephense、PHP Debugを入れる?
DW8の拡張子設定:
C:\Program Files (x86)\Macromedia\Dreamweaver 8\Configuration\DocumentTypes\MMDocumentTypes.xml
https://helpx.adobe.com/jp/dreamweaver/kb/change-add-recognized-file-extensions.html
■Git
https://www.bangboo.com/cms/blog/page_322.html
■XSS対策、CSRF対策、脆弱性チェック
https://www.bangboo.com/cms/blog/page_267.html
PHPサイバーテロの技法
■SQL
https://www.bangboo.com/cms/blog/page_151.htmlhttps://www.bangboo.com/cms/blog/page_154.html■Memcached
KVSでメモリにキャッシュを持たせる
1)Memcached にget
2)キャッシュがない or Memcachedサーバが落ちている場合、DBから取得
3)2の結果をMemcached にset
http://dbinfo.sakura.ne.jp/?contents_id=219■画像アクセスのPW保護
ディレクトリのBasic認証PW保護 ログイン時にhtpasswdを時間制限で書き換える https://teratail.com/questions/121911
<img src="https://user:password@example.com/secret.jpg"> 画像URLのPW埋込がFirefoxしかできなくなってた(2019年8月時点)
ApacheでCookieによるアクセス制御をかける http://webos-goodies.jp/archives/50573319.html
BlobでPHPでセッション認証を判定後に出力(ヘッダーで画像として)
ファイル名を変名してサーバに置く、アクセス時に変名をしてDL(画像じゃないが)
■要件定義、上流工程、PMBOK
https://www.bangboo.com/cms/blog/page_171.html======================
■今昔
■MySQL
type=でなく ENGINE=InnoDB で
0000-00-00はだめ datetime NOT NULL default '1000-01-01 00:00:00',
■画像にアクセス制御を加えアクセスできなくする
1)htaccessのBasic認証 https://www.kens-web.com/2011/06/1235
2)PHPでセッションを使いDBでBlob http://web-design-fox.hatenablog.com/entry/2015/06/23/000412
上記2つがメインか?Basic認証のPWの管理方法で工夫はできそう(アクセス禁止フォルダやログインPW共用等で)
Posted by funa : 10:47 PM
| Web
| Comment (0)
| Trackback (0)
August 30, 2015
Photo Boo
Photo Boo超重要サイト。写真部の部活。現時点では1年足らずだが大体同じプロセスでこの釣果。ライザップと3股中。α7R、G7X、Kiss X4、DP2 Merrill、ixy 30s
Posted by funa : 01:17 AM
| Web
| Comment (0)
| Trackback (0)
January 9, 2014
Camoufla
Posted by funa : 12:08 AM
| Web
| Comment (0)
| Trackback (0)
September 2, 2013
A Bao A Qu
1)ネットの炎上は直接の被害者でなく第三者が被害者の代弁者として引き起こす
2)嘘をねつ造し、そのねつ造した嘘について誹謗中傷をする
ポジティブなことでも同じ方法。今は右翼のターン、右翼ばっかり、あと扱き下ろし。
Posted by funa : 12:02 AM
| Web
| Comment (0)
| Trackback (0)
October 6, 2011
Online softwares
http://e0166.blog89.fc2.com/blog-entry-937.html
Pixlr Photo Editor|オンラインフォトエディタ
Phoenix|フェニックス-Photoshopに近いレイヤー型フォトエディタ
Raven|レイヴン-ベクター形式でイラストが作成できるサービス
Roc|ロック-ミュージックツクール
Myna|ハッカチョウ-オーディオ編集ツール
JayCut|オンラインビデオ編集ツール
Color Scheme Designer 3|配色ジェネレータ
ThinkFree Online|MS Officeのオンライン版
オンラインで使えるツール、WEBサービス。無料で使えるのが多いし段々ローカルのソフトウェアを買う必要が無くなってくるな。
Posted by funa : 01:21 AM
| Web
| Comment (0)
| Trackback (0)