【jQuery】HTMLの属性を操作するattr()

attr()ができること

HTMLの属性の、取得、追加、変更、削除
HTMLは、タグに対して、id="",class="",href="",value="",name=""など、をつけて、役割を与えたり他のタグと差別化する。
同じ

同士でも、育った環境によって別々の性格(性質)になるイメージ。

今回のattrは、そのタグの性質を外から色々操作できる。


書き方

1.「$(’’)」で該当のタグやid(class)で対象のHTMLにアクセス
2. 続けて「attr('')」を記述

//アクセス+属性を指定
$(’hoge’).attr('fuga');

取得

.attr('')に属性を入れればOK。属性値が戻り値。
例えば、classで複数のHTMLにアクセスした場合の戻り値はHTML上で一番初めにが該当するタグの属性値を戻す。
注意したいのは、複数にアクセスしても、配列ではかえって来ないということ。

  <!-- 取得 -->
  <a id="id-btn-A" class="class-btn" href="/test.html">続きを見る</a>
  <a id="id-btn-B" class="class-btn" href="../hoge.html">More</a>
  <a id="id-btn-C" class="class-btn" href="../program.php">詳しく見る</a>
<script>
//idでアクセスして取得した場合
  const ID = $('#id-btn-A').attr('id');
  console.log(ID);
// 結果:id-btn-A

 
 //CLASSで複数のHTMLにアクセスして取得した場合
  const CLASS = $('.class-btn').attr('id');
  console.log(CLASS);
// 結果:id-btn-A

</script>

変更

.attr('')に属性を入れ、第二引数に変更したい属性値を入れる。
属性値が戻りは、変更した属性があるタグを丸ごとは配列で返す

  <!-- 変更 -->
  <a id="id-btn-A" class="class-btn" href="/test.html">続きを見る</a>
  <a id="id-btn-B" class="class-btn" href="../hoge.html">More</a>
  <a id="id-btn-C" class="class-btn" href="../program.php">詳しく見る</a>
<script>
//idでアクセスして取得した場合
  const ID = $('#id-btn-A').attr('id', 'id-btn-AAA');
  console.log(ID[0]);
// 結果:<a id="id-btn-AAA" class="class-btn" href="/test.html">続きを見る</a>

 
 //CLASSで複数のHTMLにアクセスして取得した場合
  const CLASS = $('.class-btn').attr('id', 'id-btn-AAA');
  console.log(CLASS[2]);
// 結果:<a id="id-btn-B" class="class-btn" href="../hoge.html">More</a>
</script>

追加

.attr('')に属性を入れ、第二引数に追加したい属性値を入れる。
また、オブジェクトと記述すると複数の属性を同時に設定することができる。
属性値が戻りは、変更した属性があるタグを丸ごとは配列で返す

  <!-- 追加 -->
  <a id="id-btn-A" class="class-btn" href="/test.html">続きを見る</a>
  <a id="id-btn-B">More</a>
<script>
//idでアクセスして取得した場合
  const ID = $('#id-btn-A').attr('value', 'バリューA');
  console.log(ID[0]);
// 結果:<a id="id-btn-A" class="class-btn" href="/test.html" value="バリューA">続きを見る</a>

 
 //複数個の属性を追加したい場合
 const ID2 = $('#id-btn-B').attr({
      class:'class-btn',
      href:'/test.html',
      name:'testName',
      });
       
  console.log(ID2[0]);
// 結果:<a id="id-btn-B" class:'class-btn' href:'/test.html' name:'testName'>More</a>

</script>

削除

属性を削除するには、attr()をremoveAttr()にするだけ。




参考記事
https://www.sejuku.net/blog/23264www.sejuku.net

【js】グローバルスコープとローカルスコープ

スコープとは

プログラミングでのスコープとは、ある変数や関数が特定の名前で参照される範囲のこと。
ある範囲の外に置いた変数等は、通常、その名前だけでは参照できない。このときこれらの変数はスコープ外である、「見えない」といわれる。

スコープの種類

・グローバルスコープ → ページ全体でどこからでも参照できる。
・ローカルスコープ → ページ内の部分的な範囲のみ参照できる。

グローバルスコープ

特徴:
ページ全体のどこからでも参照できる(scriptタグで2か所に分けてもグローバル変数は共通する)
関数内でも使用、再代入できる

書き方:
〇:JavaScriptのトップの位置に記述(例:global = 'hoge';)※宣言はどちらでもOKだが、宣言した方がわかりやすいかも
△:関数内で宣言なしに定義された変数(関数)(例:global = 'hoge';)

<script>
//グローバル変数を定義
let gloval1 = 1000;
let gloval2 = 5000; //priceで再代入されて、別の関数のsumで再代入された値で処理される



window.onload = function () {
  function price(){
  console.log('商品Aの値段は'+ gloval1 + 'です。');
  
  //関数内でグローバル変数を再代入
  gloval2 = 7000; 
  console.log('商品Bの値段は値上げして、'+ gloval2 + 'になりました。'); //7000
  }



  function sum(){
    //別の関数で再代入されたグローバル変数を、他の関数でも使用
    let total = parseInt(gloval1) + parseInt(gloval2) ;
    console.log('商品Aと商品Bの合計金額は、' + total + 'です。');  //1000+7000 = 8000
  }

price();
sum();

}
</script>


【解説】
グローバル変数は、ローカル変数内で使用、再代入できる。
そして、関数内ではそれが優先される「 gloval2 = 7000;」の記述の後は7000円で処理が進む。

ただし、誤解しやすいのはこの処理の後、グローバル変数の値をどうするかである。


①関数処理によって、動的にグローバル変数値を変えたい:再代入
グローバル変数は、関数処理の結果に影響されたくない:再宣言

今回は、合計(sum関数)で再代入されたグローバル変数の値で処理する必要があったので”①再代入”を選択した。
②の時はグローバル変数と全く同じ変数名を使用しても問題ないが、紛らわしいので、関数内で宣言する変数名はふつうに別の名称が良い。
※再代入の際、変数名をタイポすると意図しないグローバル変数になるので注意

ローカルスコープ

特徴:
変数や関数が、ある特定のスコープの範囲でしか参照されない。

メリット:
・コードの他の箇所に影響を与えない(予期せぬバグも起こりにくいので、メンテナンス性もgood)
・異なるスコープ範囲であれば名称がかぶっても干渉しない(便利)


書き方:
関数内で宣言する。
★letやconstなどで宣言しないと、グローバル変数扱いになるので注意!(バグの原因)

var,let,constのスコープ範囲や使い分けはこちら

参考記事
https://www.sejuku.net/blog/23264www.sejuku.net

【js】ver,let,constの違いとスコープ範囲

結論

原則 var は使わない
変数宣言は基本的に const で
変数への再代入が必要な場合に限り let を使う

基本的に変数は const で宣言し、再代入が必要な変数のみ let を使う。
さらにどうしても var が必要なケースのみ var で宣言する、というのがベストプラクティス。
上書されたくない変数をわざわざ var や let で宣言する必要はないでしょう。また、const で宣言された変数は再代入されることが無いので、変数の内容を追跡する必要が無いということはデバッグ時の負担を軽減してくれるというメリットもある。

ver

再宣言:OK
再代入:OK
スコープ:関数スコープ

<script>
    //==関数1==
    var test = function(){
      var greet = 'こんにちは';
      console.log(greet); // 'こんにちは'
      
      //再宣言
      var greet = 'Hello';
      console.log(greet); // 'Hello'
      
      //再代入
      greet = 'アニョハセヨ';
      console.log(greet); // 'アニョハセヨ'
      
      //関数内のif文など
      if(true){
        console.log(greet); // 'アニョハセヨ'
        greet = 'ニーハオ';
  var name = '鈴木さん';
      }
      
      console.log(greet); // 'ニーハオ'
      console.log(name); // '鈴木さん'
    }


    //==関数2==
    var test2 = function(){
      console.log(greet); // not defined
    }

test();
test2();
</script>

【解説】
varの再宣言や再代入ができてます。
関数スコープなので、関数内を1つの行動範囲としているので、その関数内であればif文で囲って使用したり、再宣言、再代入しもOK。
(varは、関数内であれば細かいブロックは仕切りとして認識しない)

ただし、関数スコープなので、関数から外には出れない。
よって、別の関数2では、エラーになる。


let

再宣言:NG
再代入:OK
スコープ:ブロックスコープ

<script>
    //==関数1==
    let test = function(){
      let love = '月が綺麗ですね';
      console.log(love); //'月が綺麗ですね'

      //再宣言
      let love = 'I love you';
      console.log(love); //'月が綺麗ですね' ※再宣言しても値は変わらない

      //再代入
      love = 'サランヘヨ';
      console.log(love); //'サランヘヨ' ※再代入はできる

      if(ture){
        console.log(love); //'サランヘヨ'
        love = '我爱你';
        let name = '田中さん';
      }

      console.log(love); //'我爱你'
      console.log(name); // not defined
    }
     
     //==関数2==
     let test2 = function(){
     console.log(love); // not defined
    }

test();
test2();

</script>

【解説】
同じ変数名で再宣言をするとエラーになる。
ブロックスコープなので、ブロック(if文やfor文など)内が行動範囲になる。
loveが宣言されたブロックから見ると、if文も自分のブロック内のため、使えるし、再代入もできる。
逆に、if文を見てわかるように、関数内であれば仕切りを気にしないvarとは異なり、letは仕切りをブロック単位にするため、fi文内で新しく宣言されたnameは、if文内でしか行動することができない。

当然、別のブロックの関数2では、エラーになる。

const

再宣言:NG
再代入:NG
スコープ:ブロックスコープ

<script>
    //==関数1==
    const test = function(){
      const good = '元気ですか?';
      console.log(good); //'元気ですか?'

      //再宣言や再代入
      let love = 'how are you?';
      love = 'how are you?';
      console.log(good); //'元気ですか?' ※再宣言しても再代入しても値は変わらない

      if(ture){
        console.log(good); //'元気ですか?'
        const name = '渡辺さん';
      }

      console.log(name); // not defined
    }
     
     //==関数2==
     let test2 = function(){
     console.log(good); // not defined
    }

test();
test2();

</script>

【解説】
再宣言も再代入もNG。
スコープ範囲は、let参照。

constの値は絶対に不変??

たしかにconstの値を直接再代入して変更することはできません。ただし、オブジェクトを操作することはできます。

<script>
//オブジェクトだ代入されている
const PLAYER = {name: "渡辺", age:"24", sex:"female"};

// NG (constに直接再代入しているのでエラーになる)
const PLAYER = {name: "中村", age:"30", sex:"male"};

// OK (オブジェクトを操作しているので間接的にconstの値を変更できる)
PLAYER.name = "中村";
PLAYER.age = 30;
PLAYER.sex = "male";

// PLAYER定数のオブジェクト➡ {name: "中村", age:"30", sex:"male"}; に変わる!!
</script>

javascript特有POINT!!
javascriptにおける連想配列とオブジェクトの違い

変数の巻き上げ

以下は、1つ目のXは、0ではなく、undefinedが表示されます。
JavaScriptは関数が宣言された時、その関数内でvarで宣言されてるすべての変数を、勝手に関数の一番上でundefinedで初期化します。

<script>
 var x = 'ハンバーガー';
    let test = function (){
        console.log(x); // undefined

        var x = '餃子';
        console.log(x); // '餃子'
    }
test();
</script>

↓ 起きてる現象:★部分が実装されている

<script>
 var x = 'ハンバーガー';
    let test = function (){
    var x; //    ★ ・・・ var x=undefined; この処理が入る
        console.log(x); // undefined

        var x = '餃子';
        console.log(x); // '餃子'
    }
test();
</script>

【解説】
・letとconstを使う。
・関数内で宣言する変数はなるべく、関数内の先頭に記述する。

参考URL
https://qiita.com/wannabe/items/b2a0d63fc786eab13c48qiita.com

【js】変数

宣言について

値を定義する場合

宣言のみパターン
var 変数名;

宣言+初期値を代入を同時するパターン
var 変数名 = 値;
宣言時に代入される値を初期値と呼ぶ。


複数、同時に宣言するパターン
var 変数名1 = 値1,変数名2,変数名3 = 値3;

複数同時に宣言する場合は、カンマで区切る。
初期値を入れても入れなくてもOK。
改行してもOK。
一番最後はセミコロン。

データ型

データ型ごとに代入する値の書き方を変える

<script>
var str = 'こんにちは';
var int = 21;
</script>

初期値を空にしたい場合

宣言だけだと、初期値が、undefinedになる。
ただし、undefinedは予約語ではないため、変数で何かしたのデータを代入される可能性もあるので、予約語であるnullを入れておいた方が安全らしい。
「''」

<script>
var a = '';
console.log(typeof a);
//結果
string
</script>

「''」を初期値にすると、string型の空文字がはいっている。
つまり、見えない値がある状態である。


「null」

<script>
var b = null;
console.log(typeof b);
//結果
object
</script>

「null」を初期値にすると、object型で"値が存在しない空の状態"ということになる。
「null」は特殊なオブジェクト型の値で、JavaScript予約語として用意されている。
「null」は変数、関数、メソッド、あるいはオブジェクトの識別子として用いることはできない予約語
「null」は有効な値が存在しなかった場合に代わりにnullが返されるといった用途で使われる。
その為、値を取得した時にnullかどうかを判定することがよく行われます。


「undefined」
nullと混同されがちだけど厳密には違う。

<script>
console.log( null == undefined );
console.log( null === undefined );
//結果
true
false

//
console.log(typeof undefined);
//結果
undefined
</script>

値が同じかを確認する「==(等価演算子)」で確認すると、同じ。
値とデータ型の一致を確認する「==(厳密等価演算子)」で確認すると、別物。
つまり、値は同じ。だけどデータ型が異なる。
そして、undefinedのデータ型はundefined型である。

<script>
console.log(typeof undefined);
//結果
undefined
</script>

配列を定義する場合

宣言だけのパターンと初期化を同時に行うケース。

<script>
var items = [];
//配列
var items = ['りんご','みかん','メロン']; 
//連想配列
 var items = {
         'ringo' : 'りんご',
         'mikan' : 'みかん',
         'meron' : 'メロン',
 };

</script>
<script>
items[1]; // みかん
 items['ringo'] // りんご

</script>

関数を定義する場合

<script>
var func = function(){
  //処理内容
  }
</script>
<script>
//関数を呼び出すとき
func();
</script>
<script>

</script>
<script>

</script>
<script>

</script>

【SQL】トランザクション、コミット、ロールバック

トランザクションとは

DBに対して複数の処理が行われるとき、それを1つのまとまった処理として扱うこと。

(よくある例)
誰かに送金するとき。
1、A口座が減る
2、B口座が増える

別の処理だがどちらかの処理だけ成功したりするのはNGですよね。
そのために1つにパッケージングしてくれる機能。

トランザクションの目的と種類

目的:データの整合性を保ちやすく、イレギュラー(システム的というよりはユーザー的に)な処理になりにくい。また、障害復旧時も役に立つ。

トランザクション処理したユーザー登録機能があるとする。
ユーザー名、名前、電話番号、アドレス のうち、アドレスだけ空だと、ロールバックし、アドレスだけ空の状態は許さないことができる。
そのために、不完全なユーザー登録を防ぐことができるというわけだ。

f:id:aruku-hito:20191201164644p:plain

ACID特性

・原子性 (ATOMICITY)
トランザクション内で実行する処理が全て完了するか、または全て行われないかのどちらかで中間的な状態がない性質です。(0か100か的なイメージ)

・一貫性 (CONSISTENCY)
整合性とも呼ばれており、DBの内容に矛盾がなく正常な状態が保たれる性質です。
例えば、商品の在庫数データは負の数を設定することが許されませんので在庫数が負の数になるような処理を許可しないようにします。

・独立性 (ISOLATION)
独立性は更新中のデータが他のトランザクションに影響を与えないようにする性質です。
ぼぼ同じタイミング、またはトランザクション処理実行中に同じ処理が来ても、ごちゃ混ぜではなく、現状の処理を終わらせた後に、次のトランザクションに移り、ちゃんと1つずつ順序だてて実行してくれる。

・持続性 (DURABILITY)
持続性はトランザクションが終了した結果を障害などによってデータが損失しないようにする性質です。
この性質の保証のために、一般的にはトランザクションのログを記録しておき、障害が起きた場合はログを使用して障害発生前の状態に復旧する。

コミットとロールバック

COMMIT :トランザクション処理を確定させる処理。
ROLLBACK:トランザクション処理を中断、または取り消す処理。

書き方

$mysqli = new mysqli( 'host_name', 'user_name', 'password', 'database_name');

if( $mysqli->connect_errno ) {
	echo $mysqli->connect_errno . ' : ' . $mysqli->connect_error;
}

$mysqli->set_charset('utf8');

// トランザクション開始
$mysqli->begin_transaction();

try {
	// UPDATE
	$sql = "UPDATE gc_granola SET price=400 WHERE id = 11";
	$res = $mysqli->query($sql);

} catch( Exception $e ){
	// エラーが起きたらロールバック
	$mysqli->rollback();
}

// 正常に終了したらコミット
$mysqli->commit();

$mysqli->close();

参考記事
https://qiita.com/komattio/items/838ea5df68eb076e8099qiita.com
https://yttm-work.jp/lang/mysql/mysql_0004.htmlyttm-work.jp

https://qiita.com/Sobue-Yuki/items/8016acbf11483b070804qiita.com

【DB:パターン】一覧 → 詳細

【目的】
DBからある特定のデータだけ表示したい。

【仕様】
一覧+詳細
f:id:aruku-hito:20191122214727p:plain

2つを1つに

テーブルの結合とは、重複したデータのテーブルを分割しておいて、必要に応じて、仮想的な1つの表として連結して扱う方法。
このようにテーブルを結合することを「リレーション」とか「連結」「関連付け」と呼ぶ場合もある。

一覧ページ

index.php

<?php

    $pdo = new PDO('mysql:host=localhost; dbname=mydb; charset=utf8','root','');

    $sql = 'SELECT players.id, name, level, job_name FROM players LEFT JOIN jobs ON jobs.id = players.job_id';
    $statement = $pdo->prepare($sql);
    $statement->execute();


//☆☆複数のレコード情報を1行ずつ、配列に格納☆☆
    $results = [];
    while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
        $results[] = $row;
    }

    $statement = null;
    $pdo = null;

    $message = 'hello world';
    require_once 'views/index.tpl.php';

?>

index.tpl.php

 <!DOCTYPE html>
<html lang='ja'>
    <?php include('header.inc.php'); ?>
    <body>

        <h1><?= $message ?></h1>

        <table>
    	    <?php foreach ($results as $player) { ?>
                <tr>
                    <td><?= $player['id'] ?></td>
                    <td><?= $player['name'] ?></td>
                    <td><?= $player['job_name'] ?></td>
                    <td><?= $player['level'] ?></td>
      //☆☆idをURLのパラメータで渡している☆☆
                    <td><a href="show_player.php?id=<?= $player['id'] ?>">表示</a></td>
                </tr>
             <?php } ?>
    	</table>

        <?php include('footer.inc.php'); ?>
    </body>
</html>

詳細ページ

show_player.php

<?php

    $pdo = new PDO('mysql:host=localhost; dbname=mydb; charset=utf8','root','');

//☆☆idがある場合、id変数に代入☆☆
    if(isset($_REQUEST['id'])) {
        $id = $_REQUEST['id'];
    }

//☆☆idのレコードだけ取得(WHERE)☆☆
    $sql = 'SELECT players.id, name, level, job_name
            FROM players LEFT JOIN jobs ON jobs.id = players.job_id
            WHERE players.id = :id';

//:id', と $id, を紐づけている(bindValue)☆☆
    $statement = $pdo->prepare($sql);
    $statement->bindValue(':id', $id, PDO::PARAM_INT);
    $statement->execute();

//☆☆1行のレコード情報を変数に格納☆☆
    $player = $statement->fetch(PDO::FETCH_ASSOC);

    $statement = null;
    $pdo = null;

    $message = 'This is piaza';
    require_once 'views/profile.tpl.php';
?>

showprofile.tpl.php

<!DOCTYPE html>
<html lang='ja'>
    <?php include('header.inc.php'); ?>
    <body>

        <h1>Player profile</h1>

            <ul>
                <li>ID:<?= $player['id'] ?></li>
                <li>名前:<?= $player['name'] ?></li>
                <li>職業:<?= $player['job_name'] ?></li>
                <li>レベル:<?= $player['level'] ?></li>
            </ul>
            
            <p><a href="index.php">リストに戻る</a></p>
        
        <?php include('footer.inc.php'); ?>
    </body>
</html>