黄色のCookieのコンソールエラー

Chromeデベロッパーツールの「Console」で出てくる黄色のエラー(警告)に対処したのでメモします。

Cookieのエラー

A cookie associated with a cross-site resource at <URL> was set without the `SameSite` attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.

<URL>にはyahooのURL(http://yahoo.co.jp/)やGoogleのURL(https://www.google.com/、http://.google.com/、http://.google.co.jp/)など、https/http違いのURLが入っていました。

このエラー、いろいろなサイトで見られます。しかも多いと何十個とまとめて出ています。
目を瞑りたいではありますが、調べてみるといろいろ出てきました。

まさに翻訳されている記事。詳しい!ありがとうございます。

Chrome で SameSite=None に関する Cookieについての警告が表示される | ラボラジアン

【ポイントだけ翻訳】
http://example.com/ に存在するクロスサイトなリソースに関連付けられたクッキーは、SameSite 属性がついていません。今後の Chrome のリリースでは、クロスサイトなリクエストに付属させるクッキーは、SameSite=None と Secure 属性がついている場合のみ送信します。

http://example.com/ は前述の<URL>にあたります。

「yahooやGoogleのURLに存在するクロスサイトなリソース」というのは、どういうことなのでしょうか?

...結局答えが見つけられず。
おそらく知らず知らずのうちにyahooやGoogleへリクエストを送っていて、その際のCookieにSameSite=NoneとSecure属性が付いていないですよ、という警告なんだろうと思います。

Cookieについて図にまとめる

忘れそうなので調べたことを図にしてみました。

f:id:yokoyoko_115:20200712001704j:plain f:id:yokoyoko_115:20200712001721j:plain

※間違っている部分を発見したら修正します!

SameSite とは

SameSite 属性の目的は、
今開いているページのドメインから、別のドメインにリクエストを送る際に、クッキーをセットするかどうか
を制御することです。

HTTP クッキーをより安全にする SameSite 属性について (Same-site Cookies) | ラボラジアン

上の図では、あるページ内に別サイトの広告の表示をリクエストしている例ですが、サイトAからサイトBへページ遷移する際も、現在のドメインとは別のドメインへリクエストを送ることになります。

Secure属性とは

SSLというURLがHTTPSという暗号化された通信下でのみ読み取れるCookieの指定となります。

いまさら聞けないSameSite CookieとGoogle Chrome 80 | ecbeing

また、Cookieを発行するときに "secure" と指定されたクッキーのことをセキュアクッキーといいます。

ドメインでもCookieを送れるようにしますが、せめてSSL通信にしてください、というのが今回の警告です。

エラーの対処方法

そしてサイト運営側としてはどう対処すればいいのかというと、

自サイトに埋め込んだウィジェットや広告などから外部のドメインに送られるクッキーに関しては、こちらでコントロールできるものではないので何もすることはない。

最初に外部のサーバーからセットされたCookie(これがサードパーティCookie?)に対してはクライアントからは何もできない、SameSite=Noneの指定はできません、ということでしょうか。

ひとまずエラーに対しては一件落着です(具体的な対処は何もやっていない)。

余談

Cookieについて調べていたらあれこれ気になったのでメモします。

SameSite=NoneとSecure属性の警告は、CSRF対策のため?

クロスサイトリクエストフォージェリCSRF
ユーザーのCookieを利用して、あたかもユーザーが行ったかのような個人情報の設定などの処理をさせてしまう攻撃です。
攻撃者は罠を仕込んだ画像をユーザーに読み込ませたり、POSTでデータを送信させて攻撃します。 「forgery:偽造」という意味です。
リクエストの偽造ですね。

SameSite=NoneとSecureと規定すれば、HTTP通信の怪しい画像などの読み込み時のCookieの送信は防げる、ということでしょうか。

POST送信におけるCSRF対策について

Chrome 80が密かに呼び寄せる地獄 ~ SameSite属性のデフォルト変更を調べてみた - Qiita

SameSiteの設定値によって対策効果が変わってきます。
急に難しく感じました。

また、世間はプライバシーの侵害にもあたるサードパーティCookieを廃止しようという流れらしいです。

GoogleのChromeがサードパーティCookieを廃止。Webサイトへの影響は? | Webmedia

Cookieの確認方法

PCのChromeでは、アドレスバーにchrome://settings/siteData?search=Cookie と入れてアクセスすると「すべての Cookie とサイトデータ」という、ブラウザに保存されているCookieがサイトごとに確認できます。

結構な数があります。「ad」と付いているものは広告っぽいです。
そして結構どこにでも「_ga」と、AnalyticsのCookieがセットされています。

さらに!Chromeデベロッパーツールの Application > Storage > Cookies では、のページでセットされたCookieの一覧が送信先別で見れます(よく見たらアイコンがチョコチップのクッキーみたいですね)。
Secure指定があるかどうかも確認できます。

Google AnalyticsはファーストパーティCookieを利用している

どういうこと??と思いましたが、ga.js やgif画像をうまいことやり取りしているようです。

コラム - GoogleAnalyticsのCookieは、なぜサードパーティCookieではなく、ファーストパーティCookieなのか? | Nexal

AnalyticsはGoogleのサービスなので、どうなっても使えなくなることはなさそうですね。

最後に

Cookieをセットする方法まで調べたかったですが、来たる時が来るまでとっておきます。

本当はもう一つの黄色いエラーについても書こうと思っていました。
クッキーがここまで膨らむとは!

JavaScriptのコールバック関数について

JavaScript第一号の記事です。
JavaScriptを飛ばしてJSONの記事はあります。

こんな動きを実装しました!と堂々と記事にする以前の段階なので、そうなれるようにがんばります。

下積み記事第一弾はコールバック関数です。
やりたいことがあっても、うまくいかないときは大体コールバック関数に阻まれていることが多いです。
お勉強できる教材がないか探しました。

エンジニアYouTuberがすごい

YouTubeでプログラミングの学習ができます。
動画なので感覚的にはドットインストールみたいです。
加えて、教えてくださる方が映っています。

私が見たのは
しまぶーのIT大学
【基礎から学ぶ JavaScript 入門 #1】フロントエンド開発でJavaScriptが必要な理由を解説!【ヤフー出身エンジニアが教える初心者向けプログラミング講座】
です。

とてもわかりやすかったです!これが無料!

動画内でも「コールバック関数は初心者がつまづきやすいところ」と言われており、コメント欄を見ると、同じくコールバック関数と戦う方たちの声がたくさん。 励みになります。

このしまぶーさんという方以外にもたくさんの方がプログラミング関係の動画を上げてくださっているのですね。
結局、有用な記事を探し出して読むのと同じなので、自分に合ったYouTuberを探してみるのもいいなと思いました。

『たった3分でプログラミングを学習できる!?』知らないと損をする教育系Youtuber3選!【在宅ワークの方必見】 | キカガク公式ブログ

関数いろいろ

まずはいろいろある関数を挙げます。

関数宣言と関数式

どちらも関数の宣言をする文法です。

関数宣言

function hello() {
  console.log('こんにちは');
}

関数式

let hello = function() {
  console.log('こんにちは');
};

名前のない関数、匿名関数を変数helloに入れています。 function() {} 部分は関数リテラルという「値」で変数に代入しているため、後ろに ; を付けます。
(文末の ;javascriptで自動挿入されるそうなのでなくても大丈夫ですが、「入れるもの」だということは抑えておきたいです)

これら書き方が2つあって混乱します。「文字列の扱い ""'' 」のようにどちらを使えばいいのか...!

関数式と関数宣言の違いについて:
関数式

基本は関数の呼び出しの前後どちらに書いてもOKな関数宣言を使って、スコープを意識するときは関数式の方がいいのかなと思いました。

アロー関数

さらに関数リテラルをアロー関数を使ってシンプルに書くこともできます。

let hello = () => { 
  console.log('こんにちは');
};

// 処理が一文のときは {} を省略できる
let hello = () => console.log('こんにちは');

// 引数が一つのときは()を省略できる
let hello = name => console.log('こんにちは' + name);

アロー関数の基本

アロー関数と普通の書き方では何が違うかというと、this の解釈だそうです。

【JavaScript】アロー関数式を学ぶついでにthisも復習する話 - Qiita

アロー関数、目がまだ慣れません...!

即時関数

関数を定義すると同時に実行される関数です。

(function () {
    //処理
}());

JavaScriptで即時関数を使う理由 - Qiita

即時関数を使う理由は、スコープの汚染を防ぐため。
もっと積極的に使っていかなくてはならない関数であることは分かりました。
おいおい復習したいです。

高階関数

引数が関数(=コールバック関数)の関数。高階関数の中で関数を実行します。

function 高階関数名(コールバック関数) {
  // 処理
  コールバック関数();
}

☆「高階関数名」はなくても、匿名関数でもOKです。

匿名関数、無名関数

名前がなくても関数として動かすことができる関数。
function(){} という、今までさんざん出てきたやつです。

コールバック関数

ここでようやくコールバック関数についてです。
「引数として渡されている関数」のことをいいます。

コールバック関数を使った文法

引数になっている関数なんだ、ということを落ち着いて考えればコードも読めそうです。

言葉にすると、コールバック関数の書き方は

  • あらかじめ宣言した名前のある関数を入れるのか
  • 匿名関数をそのまま入れるのか

です。

コールバック関数をあらかじめ宣言しておく場合

// 高階関数
function kokai(fn)  {
  // 処理
  fn();  // コールバック関数の処理←よく「fn」と書かれる。
}

// コールバック関数になる関数の定義
function callback1(param) {
  // 処理
}
function callback2(param) {
  // 処理
}

// 高階関数(kokai())の実行
kokai(callback1);

コールバック関数に引数を渡す場合

高階関数の引数にコールバック関数の引数を定義します。
引数の順番は決まっていなさそうです。

function kokai(fn, param)  {
  // 処理
  fn(param);  // コールバック関数の処理
}

kokai(callback2, コールバック関数の引数);

コールバック関数が匿名関数の場合

関数式の変数部分を入れるのと、代入部分である匿名関数を入れるのは同じ、と考えれば納得です。

// 高階関数
function kokai(fn)  {
  // 処理
  fn(); 
}

// コールバック関数になる関数の宣言(関数式)
let callback3 = function(param) {
  // 処理
}

// 高階関数(kokai())の実行
kokai(callback3);  // コールバック関数が変数

kokai(function(param) {    // コールバック関数が匿名関数
  // 処理
});

これはよく見掛けます。
1回限りしか使わないコールバック関数なら、わざわざ関数宣言しなくてもまるごと引数に入れてしまおうということです。

コールバック関数に引数を渡す

高階関数の処理内容を、引数であるコールバック関数の引数として渡す場合です。

 // 高階関数の宣言
function kokai(fn) {
  const input = 'hoge';
   fn(input);    // コールバック関数に引数を渡す、という定義
}

// 高階関数の実行
kokai(function(input) {
  // inputを使った処理
});

アロー関数の高階関数

ぎりぎり分かりそうなコードです。

// 通常
const calc = function(x, y, fn) {
  return fn(x, y);
};
 
console.log(calc(2, 4, function(a, b) {
 return  a + b;
}));  // 6
console.log(calc(2, 4, function(a, b) {
  return a * b;
}));  // 8


// アロー関数
calc = (x, y, cb) => {
  return cb(x, y)
}

console.log(calc(2, 4, (a, b) => a + b))  // 6
console.log(calc(2, 4, (a, b) => a * b))  // 8

アロー関数では、(a, b) => a + b 部分がコールバック関数です。匿名関数です。
そしてアロー関数では return が省略できます。
とても短く書けます。

アロー関数については今深入りすると大混乱なので、このへんにします。

まだまだ奥が深い

関数の種類も、他に純粋関数再帰関数、あと分からない単語ではクロージャカリー化などがありました。

まずはコールバック関数を意識しながらコードを見て目を慣らします!

それにしても具体的でないコードはこうも分かりにくいのか、と思いました。 (動画のコードまんま書くのはは良くないと思い...。)
オリジナルないい例が思いついたら直したいです。

おしまい。

CGIにふれる

WordPressインストール時にまたしてもつまづいたのでメモです。
こちらにもつまづいた事例を書きました)

WordPressをサーバーに入れて、インストールしようとアクセスすると、phpのエラーが出ました。
require がうまくできない、といったエラーでした。

よくよく見るとマジック定数である__DIR__ が使えないようでした。
( echo __DIR__ としてもそのまま「__DIR__」と出てきてしまう)

参考:マジック定数について
PHPの__FILE__とか__DIR__とかのマジック定数まとめ | PisukeCode - Web開発まとめ

__DIR__ はPHP5.3 から使えるのですね。 使おうとしているサーバーは5.2だったのです...!

ということで、解決策は「サーバーでPHPCGIモードにする」でした。

モジュールモードとCGIモード

使っているのはさくらサーバーです。
ざっくり調べたところ、サーバーの仕様には モジュールモードCGIモード があることが分かりました。
他のサーバー会社でも同じ感じらしいです。

モジュールモードでは、PHPApacheのモジュールとして使うため高速になる。
CGIモードでは、Apacheからではなく、CGIファイルを通してPHPへのパスを通している。

といった違いです。

よく「モジュールモードは高速」と見掛けるので時代に逆行している感じはあります。
しかし共用サーバーなので、メンテナンス上個別にPHPのバージョンを上げる必要があり、CGIモードにする変更することになりました。

さくらサーバーでモジュールモードからCGIモードへ変更する

以下教えていただいた方法です。

1. .htaccessを作る

Action myphp-script /php.cgi
AddHandler myphp-script .php

と書きます。
次に作る php.cgi を見に行くよう指示する記述です。(おまじない状態...)
ルートディレクトリに置きます。

2. php.cgi を作る

#!/bin/sh
#exec /usr/local/bin/php-cgi
#exec /usr/local/php/5.6/bin/php-cgi
#exec /usr/local/php/7.2/bin/php-cgi
exec /usr/local/php/7.3/bin/php-cgi

# が付いている行はコメントアウトされているので、動いているのは最後の行のみです。
この記述でPHP7.3へパスを通しているようです(おまじない...)。
こちらもルートディレクトリに置きます。

これでPHP7.3が使えるようになったので、__DIR__ も使えるようになりました。

注意点

php.cgi のアクセス権に注意です。実行ファイルなのでパーミッション755で動きます。

さいごに

少しCGIについてかじってみようかと思いましたが、まだ早かったみたいです。
Perlという言語で書かれているけど拡張子は.cgiなのですかね...。

今回は触れる程度にしておきます。

PHPで忘れがちなこと(その2)

その1の続きです。
※忘れそうになりますが、これはProgateをやってメモしたい部分をまとめた記事です。

return array() という書き方

はじめ何に違和感を覚えたかというと、それが関数の中ではなく、return array()配列のみ書かれたファイルだったということです。

A.php

<?php
return array('apple', 'remon', 'banana', 'grape');

この書き方はconfigなど、設定ファイルで見られます。
設定値をまとめて管理したい場合、↑こう書いてincludeします。

B.php

<?php
$array = include 'A.php';  // $arrayの中に配列が入っている

これは、 A.php で変数に配列を入れて B.phpinclude するのと同じですが、外部ファイルに変数がある、というのがちょっと気持ち悪いので return がいいのかなぁと思いました。

インクルードファイルで変数に配列を入れる場合
A.php

<?php
$fruits = array('apple', 'remon', 'banana', 'grape');

B.php

<?php
include 'A.php';  // B.php内で$fruitsが使える

分かってきましたが気になったので以下検証してみました。

失敗例 〜変数に配列を入れたインクルードファイルをさらに変数に入れた場合〜
A.php

<?php
$fruits = array('apple', 'remon', 'banana', 'grape');

B.php

<?php
$array = include 'A.php';  // $arrayには数値の1が入っている

1とは??

値の返し方: include に失敗したときには FALSE を返し、警告を発生させます。 成功した場合の返り値は、インクルードしたファイル側で変更していない限りは 1 です。 インクルードしたファイルの中で return を実行すれば、 そのファイルの処理をそこで止めて呼び出し元に処理を戻せます。 読み込まれたファイルから値を返すことも可能です。

通常の include が成功したときの返り値は「1」なんですね。
return していると、その値を返すことができると。

インクルードファイルは、関数の使い方と似ていると思いました。

returnとincludeの引数を括弧でかこむこと

include('A.php') という書き方も気になってきたので調べました。
括弧については

include は「不要です」。
returnは「非推奨です」。

includeとreturnは関数ではなく言語構造です。
include() の書き方は、読み込んだファイルの戻り値の評価の際など、if文の中で使うとややこしくなりそうです。なるべく括弧なしで書いていきたいです。

このあたり、またつまづきそうなのでその都度ドキュメントを熟読しようと思います。

参考

phpの閉じタグ

脱線ついでにもう一丁!

ちなみに、閉じる ?> のないファイルをよく見ます。WordPressのfucntions.phpとか。

どういうことなのか調べました。

PHPの最後の終了タグ ?> は付けないでおこうねというお話 | ザ・サイベース

例として紹介するこのPHPファイルでは、PHPの終了タグ「?>」の後に改行コードが2つあります。[EOF]はEnd Of Fileの略で、ファイル内での終了箇所です。

無駄な改行コードが含まれるPHPファイルを使用すると、プログラムが誤作動する場合があります!!

ファイル全体が純粋なPHPコードの場合、phpの閉じタグを入れると改行コードが混入してしまうことがあるため、ない方がいいんですね。
?> で終わる行が「許容される改行」というのが面白いです。

phpの開始タグ

開始タグについても発見があったので追記です。
<?php<? に省略できるケースがあります。

https://www.php.net/manual/ja/language.basic-syntax.phptags.php

PHP では、短い形式の開始タグ <? も使えます (しかしこれはおすすめしません。というのも、この形式のタグは php.ini で short_open_tag を有効にするか --enable-short-tags オプションつきで PHP を configure した場合でないと使えないからです)。

php.iniはPHPの設定ファイルです。
short_open_tag = On とするそうです。
.htaccessなどでもshort_open_tagの設定はできるようです。

short_open_tag = Off になっているのに <? を使うとエラーになってしまうので、あまり推奨されない設定です。

クラスについて

ここからはクラスのお話です。

Progateでは食べ物の注文サイト制作を通してMenuクラス(子クラスにFoodクラス、Drinkクラス)、メニューに対するユーザーのレビューでUserクラス、Reviewクラスを作りました。

クラスの規模感(どこまででクラスとする、など)や継承の感覚について知ることができました。

インスタンスを作るときに、コンストラクタの引数として値を渡すことができる

オブジェクトの設計図であるクラス。インスタンスを作る際に最初に実行されるメソッド、コンストラクタには引数を渡すことができます。

// クラス
class User {
  private $userName;

  public function __construct($name) {
    $this->userName = $name;
  }
}

// インスタンスを作る
$user1 = new User('hanako');  // コンストラクタの引数に$name = 'hanako' が入る

「ゲッター」「セッター」メソッド

クラスのプロパティは、public ではなく、privateで定義してクラス外からは直接触れないようにしておきましょう、というのが出発点です。
これをカプセル化というそうです。

publicprivate、そして protectedアクセス修飾子といいます。

使える機能を制限することで他の人も使いやすくなる、安全に利用できるようになります。

そこでpublicのメソッドを使って
プロパティの値を取得する: ゲッター(頭に「get」を付ける)
プロパティの値を更新する:セッター(頭に「set」を付ける)

と定義すると分かりやすいです(絶対そうしなければいけないという決まりはないです)。

// 先程のUserクラスの中
class User {
  private $userName;
  private $userAge;

  public function __construct($name, $age) {  // コンストラクタ修正
    $this->userName = $name;
    $this->userAge = $age;
  }

  public function getName() {  // ゲッター
    return $this->userAge;
  }

  public function setName($age) {  // セッター
    $this->userAge= $age;
  }
}

// インスタンスを作る
$user2 = new User('kumiko', 20);

echo $user2->getAge();  // 20
echo $user2->UserAge; // 取得できない

WordPressでもget_the_title() でタイトルの取得です(表示は the_title())。
ちょっと覚えておくだけで、「get〜だから取得する関数だっけ?」と考える時間が減りそうです。

static

静的プロパティ静的メソッドについてです。
Progateでは「クラスプロパティ」「クラスメソッド」という名前で出てきましたが、あまり一般的ではないのかもしれません。

staticの働きはずばり

newせずに利用できるプロパティやメソッドのことです。

PHPのstaticプロパティとstaticメソッド、定数 (1/3):Web業界で働くためのPHP入門(15) - @IT

使い所は、「作られたインスタンスの数を数える」など、個々のインスタンスには関係のないもの、クラスのデータ管理のためのものです。

// 先程のUserクラスの中  
class User {
(省略)
  private static $count = 3;  // 静的プロパティの定義

  public static getCount() {  // 静的メソッドの定義。$thisではなくself
    return self::$count;
  }
(省略)
}

echo 'ユーザの数は' . User::getCount() . '人です。';  // 静的メソッドの呼び出し  
// ユーザーの数は3人です。

使い道が分かればstaticも怖くない!

最後に

ふんわりと知っているのは、あと「名前空間(namespace)」とtraitです(Progateでは出てきませんでした)。 名前空間は抑えておきたい...!
また問題に直面したらおさらいしたいと思います。

これらの知識をうまくフレームワークで落とし込みたいところです!

PHPで忘れがちなこと(その1)

ProgeteでPHPをやっています。
これまで断片的に調べながら書いていたので、体系的に学習することは、とても効率的だと実感しています。

特にPHPでもWordPressから入った身としては、オブジェクトやクラスなどを意識することなく、世にたくさんある参考サイトを見ながらコードを貼り付けていました...そんな感じでサイトを作れてしまうWordPressは易しいというか。

次第にフレームワークを使ったサイトやフルスクラッチのサイトを垣間見ては行き詰まり、解読してちょろっと書いて...という状態です。

手元にはLaravelの本もあるのにほとんど読んでいません。
本を買ったときの情熱を思い出して、基礎から勉強します!

前置きが長くなりましたが、思い出したときに振り返られるように、私が忘れがちなことを書きました。

文字列の中に変数を入れる

$name = "太郎";  
echo "こんにちは、{$name}さん";  // こんにちは、太郎さん
echo 'こんにちは、{$name}さん';  // こんにちは、{$name}さん

ダブルクォーテーション "" で囲むと変数展開というものができます。
一方でシングルクォーテーション'' で囲むと、中を文字列として扱います。

だいたいは echo "こんにちは、".$name."さん" として書くことが多いのですが、場合によっては上記の書き方の方が見やすいので書き分けたいところです。

また変数展開同様に改行コードを使うときもダブルクォーテーションで囲みます。

echo "\r\n";  // 改行される。文字列扱いしたいのなら「"\\r\\n"」と書く(エスケープ処理)
echo '\r\n';  // \r\n として出力される。

となります。

https://yaruzou.net/html-quotation

""'' どちらを使うべき?

これらのような場合以外ではどちらでも使える、というシングルクォーテーション''とダブルクォーテーション""
コードの中で混ざっていると気持ち悪いです。

統一するならどちらだろうと調べました。

PHPのダブルクォーテーションとシングルクォーテーションの違いを理解する - Qiita

速度に違いがあるとは!基本シングルクォーテーションを使うようにします。

htmlのタグを出力するときなどもシングルクォーテーションで囲った方が便利です。

echo '<img src="image.jpg">';
echo "<img src=\"image.jpg\">";  

後者のように "" で囲った中で "" を使う場合は、文字列として認識させるためのエスケープ処理が必要です。

javascriptの場合

javascriptでも変数展開を見かけた事があったのでついでに。

var = "花子"   
console.log(`こんにちは、${name}さん`)   // こんにちは、花子さん

囲むのはバッククォート` を使います。 そしてこれはES2015(ES6)からのテンプレート構文(Template literal)で使えます。

バッククォートでも囲える!

JavaScript (ES2015) 文字列中に変数展開できるテンプレート構文のメモ - かもメモ

そして「シングルクォートとダブルクォート(加えてバッククォート)どちらがいいの?」という問題ですが、

JavaScriptのシングルクォーテーションとダブルクォーテーション - Qiita

【JavaScript】コーディング規約の文字列リテラルのクオートはどれを採択すべきか

PHP同様、状況に応じて使い分けたほうがよさそうです。
処理速度については調べ切れませんでした。

()のくくり方

if文の if(条件A && 条件B){} という書き方。
私がよくやってしまうのが if((条件A) && (条件B)){} という書き方。
() が余計なのです。

「条件A」に == などの比較演算子が使われていると () でくくりたくなってしまいます。くくっても動きはするのですが冗長なのでやめます。

$i = 15;
if ($i % 3 == 0 && $i % 5 == 0){}  // これでOK
if (($i % 3 == 0) && ($i % 5 == 0)){}  // 条件式を()でくくらなくてよい

全ては演算子

  • 評価の優先順位
    and < = < && の順で強い、など
  • 評価順
    1 - 2 - 3(1 - 2) - 3 で左から評価されている→左結合
    $a = $b = $c$a = ($b = $c) で右から評価されている→右結合

という調整の際に()でくくったりします。

https://www.php.net/manual/ja/language.operators.precedence.php

優先して評価させたいがうまくいかないときは () でくくる、と考えておけばいいのかなと思いました。 (その前にそもそものコードの見直しもしたい!)

1行のコードであれば文末の「;」は不要

<?php echo $name ?> でいいのです。

正しくは

phpの「?>(終了タグ)」の直前は「 ; (セミコロン)」を省略することが出来ます。
これはPHPの終了タグにセミコロンが含まれていると解釈されるからです。

PHP の 区切り文字 「 ; (セミコロン)」の扱いについて | WEPICKS!

優しい設計ですね。ただ、複数の文になるときは ; は全ての文末に入れた方がいいですね。

foreachのつかい方

私がループでよく使うのがforeach文です。
for文やwhile文を書かないのは使い分けがうまくいっていない気がするのですが...。

それはさておき、キー変数も入れる foreach($array as $key => $value) という書き方もあまりしない、無駄な書き方をしているのではないかと思い、見直してみます。

foreach($array as $key => $value) は連想配列

結論は、「foreach($array as $key => $value)$key =>連想配列でも省略できるので、$key が使いたければこの書き方をすればよい」となりました。

普通の配列でもこのforeach($array as $key => $value)は使えて、

$fruits = ['apple', 'orange', 'banana'];
foreach($fruits as $key => $value) {
echo 'フルーツの' . $key . 'つ目は' . $value . 'です';
echo '<br>';
}
// フルーツの0つ目はappleです
// フルーツの1つ目はorangeです
// フルーツの2つ目はbananaです

と、$key にはインデックス番号が入ります。
なので◯番目がどう...とかしたいときには使えそうです。

そこで、いつもどのように foreach を使っているか振り返ってみると、多次元配列が多い気がしました。

$foods = [
  ['group' => 'fruit', 'name' => 'banana', 'color' => 'yellow'],
  ['group' => 'vegetables', 'name' => 'carrot', 'color' => 'orange'],
  ['group' => 'fruit', 'name' => 'apple', 'color' => 'red']
];
foreach($foods as $food) {
  echo '食べ物の種類は' . $food['group'] . 'で、名前は' . $food['name'] . 'で、色は' . $food['color'] . 'です';
  echo '<br>';
}
// 食べ物の種類はfruitで、名前はbananaで、色はyellowです
// 食べ物の種類はvegetablesで、名前はcarrotで、色はorangeです
// 食べ物の種類はfruitで、名前はappleで、色はredです

という書き方です。
そこで、別の方法を考えると、

foreach($foods as $food) {
  foreach($food as $key => $value) {
  echo $key . ':' . $value . '、';
  }
  echo '<br>';
}
// group:fruit、name:banana、color:yellow、
// group:vegetables、name:carrot、color:orange、
// group:fruit、name:apple、color:red、

foreachの中にforeachを入れました。近い感じになりました。

それにしても例の配列の中身、微妙。

おさらい↓

【PHP入門】多次元配列・連想配列の使い方と便利な関数を解説! | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト

ここまで書いて、もしかして、配列ありきのループはforeachを使うと都合いいのでは?...と思ったのですが、確信持てず。
その都度forやwhileも念頭に置きながら書いていこうと思います!

***

以上です。

結構文法ミスのエラーの場合もあるので、小さいことでも抑えておきたいです。

タイトルに「(その1)」と付けてしまったので「(その2)」も書きます。クラスについて書く予定です。

追記:その2書きました!

JSONについて

ついにこのときが来ました。
ずっとよく分からないままモヤモヤしていたjson
分かったつもりでいてもどこか腑に落ちていなかったjson

あまり肩肘張らずに整理していきます。

JSONJavaScript Object Notation)とは

【IoT用語集】JSONとは?

XMLなどと同様のテキストベースのデータフォーマットです。
(中略)データを引用する言語であるXMLマークアップ言語であるのに対して、JSONはオブジェクト言語である点が異なっています。 (中略)JavaScriptのオブジェクト表記構文の下位構造(サブセット)をつくるデータフォーマットです。

非エンジニアに贈る「具体例でさらっと学ぶJSON」 | Developers.IO

JavaScriptの中でオブジェクトを記述する書式」のことです。
(中略)「データを表現するための記法(≒文法)」です。

JSONはデータの書き方の一つなんだ、ということがわかりました。

Markdownについてまとめた際も書きましたが、jsonに関して追加してみると下記のような関係かと思いました。
※合っていないかもしれないのでお気をつけください!

コンピューター言語
┗データ記述言語・・・json (オブジェクト言語)
 ┗ マークアップ言語・・・HTML、XMLMarkdown
プログラミング言語・・・スクリプト言語コンパイル言語
┗ データベース言語・・・SQL

JavaScriptのオブジェクトについて

たびたび出てくるオブジェクト。分かっているようで分かっていないようなもののうちの一つです。

オブジェクトまわりの関係する言葉を調べました。

データ型

データ型

"値"の種類は大きく2つに分けられて、さらにプリミティブは6つに分けられます。

プリミティブ・・・1つの値
 ┗数値
 ┗文字列
 ┗boolean(true / false)
 ┗"null"
 ┗"undefined"
 ┗シンボル
オブジェクト・・・複数の値
 ┗オブジェクト・・・{} で囲む(オブジェクトリテラル)、new Object() で定義する
 ┗関数・・・function() {} で定義する
 ┗配列・・・[] で囲む(配列リテラル)、new Array() で定義する

☆プリミティブのデータ型(数値や文字列)も、オブジェクトとして扱うことができます。

プリミティブのメソッド

ここまでまとめて、オブジェクトとは広義と狭義の意味があると考えました。ここからは純粋な狭義の(?)オブジェクトの話です。

メンバー

コロン : を、name(文字列値)と値ではさんだもの。
メンバーの値によって、呼び方が異なる。

  • 関数オブジェクト →メソッド
  • 関数以外のオブジェクト →プロパティ

JavaScriptは「オブジェクト」

{} で囲まれたものの呼び方は言語によって異なります。
JavaScriptは「オブジェクト」、
Pythonは「ハッシュ」...大体はオブジェクトっぽいですが、気をつけましょう。

意味は同じです。

サブセットとは

JSONJavaScriptにおけるオブジェクト表記法のサブセットである

とあります。

サブセットとは「本来備えている要素の一部を省略・削除した簡易版、限定版、軽量版」という意味なので、
ここではJavaScriptの一部の機能(オブジェクト表記法)だけを扱った限定版がJSONということになります。

...ここまでが長い!

JSONは文字列

混乱していたのが「JSONはの中身はテキストではないの?オブジェクト?」ということです。

JSONは文字列です(「JSON-text」というそうです)

JSONデータ」や「JSON形式」など呼ばれ方に幅があるように思います。

JSONの書き方

JSONの使われ方は、

  • 外部ファイルとして
  • 他の言語ファイル内で

の2パターンあります。

例を挙げます。

js内にて変数に入れる場合

var json = {
  "name" : "ichiro",  // ←JSON形式ではnameにダブルクォーテーション必須
  "age" : 24
}

{} 部分がJSONのデータ部分です。
javascriptのオブジェクトとの違いはnameに "" が必要かどうかです。
また配列もJSONデータとして扱われるそうです。

// 配列もオブジェクトなのでOK
var object2 = [
  {
    "name" : "jiro",
    "age" : 22
  },
    {
    "name" : "saburo",
    "age" : 20
  },
]
// 関数は入れられない
var object3 = {
  "name": "shiro",
  "age": 18,
  "hobby": ["fishing", "game", "drive"],  // 値に配列も入れられる
  "parents": [
    {                     // オブジェクトも入れられる
      "name": "taro",
      "age": 50
    },
    {
      "name": "hanako",
      "age": 48
    }
  ]
}

これらはオブジェクトなので以下の方法で参照が行なえます。

JSONデータの参照

javascriptでは上の object3の、shiroの名前と親のtaroの年齢の参照は次のようになります。

 console.log(object3.name);  // shiro

 console.log(object3.parents[0]["age"]);  // 50
 console.log(object3.parents[0].age);  // これもOK。50

ちなみに、オブジェクト(ここではobject3)をconsole.logで出すと object と出て、「▼」で開くと

{name: "shiro", age: 18, hobby: Array(3), parents: Array(2)}
age: 18
hobby: (3) ["fishing", "game", "drive"]
name: "shiro"
parents: (2) [{…}, {…}]
__proto__: Object

と表示されます。

JSONファイルを使う場合

この場合は変数に代入せず、{}[]で囲ったJSONデータを .json の拡張子を付けて保存します。(phpファイルなど他の言語ファイルでもよさそう?)

data.json

 {
  "name" : "ichiro", 
  "age" : 24
}

JSONファイルを読み込む

javascriptから読む方法です。

jQueryを使う場合 ー $.getJSON()メソッド

jQuery.getJSON( url, data, callback )

url:読み込むJSONデータのあるファイル
data:読み込み成功したときのコールバック関数に渡される値(オブジェクト)
callback:読み込み成功したときのコールバック関数

jQuery: JSON形式のWeb APIにアクセスするには?($.getJSON) - Build Insider

API」、「Ajax」、「クロスドメイン」、「XMLHttpRequestオブジェクト」、「GET」、「非同期通信」...などなど、未知の領域なので深入りはまたの機会にして...。

ここで大事なのは、戻り値がオブジェクトであるということです。 テキストであるJSONデータをオブジェクト化する必要がない。便利なメソッドのようです。

jQueryを使わない場合(ネイティブ)

JavaScriptでのJSONのパーシング - JSONの読み込みと値の取得 - JavaScript プログラミング

結局「XMLHttpRequestオブジェクト」が出てきました。これは避けては通れなさそうですね...。

ここでもし渡ってきJSONデータを console.log で確認すると

{"name":" ichiro","age":24}

と出てきます。これは文字列です。

この場合はテキストで渡ってきたJSONデータをオブジェクトにする処理が必要です。
JSON.parse() を使います。

パース:文字列を解釈すること
です。

なお、eval() という、同じく「javascptの構文があればその文字列を解析して実行する」関数がありますが、JSON.parse()JSONのオブジェクト化に特化しているのでそちらを使う方がよいそうです。

リスクも正しく把握! JavaScriptのevalで文字列をコードとして使おう | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト

まとめ

JSONデータを外部ファイルに書き出す流れや、phpからJSONデータを読み込む・書き出す場合など、もう少しいろいろまとめたいではありましたが、散らかってきたのでこの辺で終わります。

最後に図にしてみました!

f:id:yokoyoko_115:20200531012530p:plain

APIへの階段をひとつずつ登っていこうと思います。

Gitの学習ツール「Git-it」

Visual Stusdio Code(以下VS Code)でGitを使えるようになりたい、Atom + SourceTree から卒業しよう!ということでVS CodeでGitについて調べたものの、分からないことだらけだったのでGit(GitHub)についてイチから学習しようと思いました。

Visual Studio Code の git 連携機能と git コマンドについて (2018/05/23) - Qiita

とても今後役立ちそうなこちらの記事に「Git-itがおすすめ(日本語で解説してくれる)」とあったのでやってみました。

本日のつまづき

ずばりなかなか「Git-it」が見つからなかったことです。
しょうもない...。

GitHub - jlord/git-it-electron: Git-it is a (Mac, Win, Linux) Desktop App for Learning Git and GitHub

最初にページを開いて真っ先に目に入る、この緑のボタン「Read the guide」を押して、GitHubのガイドを読んでリポジトリを作ってブランチを作ってコミットしてプルリクをしてマージして...ということをしましたが、一向に日本語が出て来ず。

f:id:yokoyoko_115:20200503014808p:plain

次に同じページの緑のボタン「Clone or download」を押して確認しましたが、違いました。

正解はこのページの「releases」というアンカーテキストから移動したページ

Releases · jlord/git-it-electron · GitHub

からダウンロードです。

「Git-it」からの発見

ProgateのGitレッスンと内容は同じかと思いきや、こちらの方が盛りだくさんでした。

Git-itでは、練習で作成したローカルリポジトリをGit-itに登録して、レッスンの区切りごとに「VERIFY」ボタンでできているかチェックできます。

以下GitHub、gitコマンド初心者である私が引っかかったところをメモします。

git commit の前は git add する

Git-itでは練習として

一回コミットしたファイルをもう一度変更・保存して git diff で差分を確認して、コミットしましょう

と出てくるので、その通りにすると、

On branch master
Changes not staged for commit:
    modified:   readme.txt

no changes added to commit

と、コミットできないようなことを言われました。

調べると、

“はじめのGit”――超基本的な作業フローと5つのコマンド (3/3):こっそり始めるGit/GitHub超入門(2) - @IT

「Changes not staged for commit」はファイルが変更されているのに変更がステージングエリアにない(インデックスされていない)ときに出てくるメッセージだそうです。

確かにSourceTreeでもコミット前に毎回ファイルをチェックする操作をしていました。
git addgit commit はセット!覚えます。

user.username はGit−it独自のもの

git config の設定値でuser.username というものが出てきます。Git-itの日本語版では「GitHubと同じユーザー名にしてください」と出てきます。
英語版では↓

f:id:yokoyoko_115:20200504004631p:plain
Git-itテキストがコピペできず、Google翻訳を断念し、雰囲気で解釈
どうやらuser.username はGit−itでしか使わないもののようです。

フォーク、クローン

GitHubで人様のリポジトリをコピーして自分のアカウントに置くフォーク。これはGitHub上で操作します。
さらにそのリポジトリをローカルにコピーするクローン。
コピー先に移動して

git clone <URL>

です。

フォークは初めて知りました。
プルリクのための機能、元のリポジトリを汚さずにコピーしたリポジトリを更新してプルリクする。共有されていないリポジトリに対して行うことが多いようです。

共有されているリポジトリ、同じプロジェクトを複数人で触るときなどは、フォークを使わず、そのままブランチを切って更新、プルリクをする、というパターンを取ります。

GitHub Pages

GitHubは'ph-pages'という名前のブランチにあるファイルを自動的に静的なWebサイトとしてホストしてくれる機能があります。

すごいですね。なんて太っ腹!

2020年5月現在では、ブランチ名は自由に設定できそうです。

【初心者向け】Github pagesでwebページを公開する方法 - Qiita

ページを作るときが来たらまた調べようと思います。

ブランチ

ブランチの作成: git branch ブランチ名
ブランチの確認: git branch  今どのブランチにいるか * で記されます
ブランチの切り替え(チェックアウト): git checkout ブランチ名

pushするときの注意点

push先のリポジトリ、ブランチを意識する

コマンドで push するとき

git push origin ローカルリポジトリのブランチ名:リモートリポジトリのブランチ名

となります。

ローカルとリモートでブランチ名が同じ場合は : で区切らずブランチ名1つでOKです。

Git-itではGitHubの「patchwork」というリモートリポジトリをフォーク、クローンして、ローカルリポジトリに「add-<USERNAME>」というブランチを作りました。

ファイル更新後のpushコマンドは git push origin <BRANCHNAME> なのですが、
そこで何を思ったか勘違いをしてgit push origin patchwork と、リポジトリ名を入れてしまいました。すると

error: src refspec patchwork does not match any
error: failed to push some refs to 'リモートリポジトリのURL'

というエラーが出ました。
勘違いにつぐ勘違いで、それじゃあ git push origin add-<USERNAME>:patchwork だ!とpushしたところ、「VERIFY」とチェックしてもOKとなりませんでした。

リポジトリ名とブランチ名の混同問題。気をつけます。

リモートリポジトリにローカルと同名のブランチがなければ新しく作られる

しっかりした確証はないのですが、そのようです。
前述のようにブランチ名が異なるpushをしたのですが、リモートリポジトリにこれまでなかった「patchwork」ブランチが作られていました。

新しくリモートに作られたブランチが自分には見えるのにリポジトリを共有している人には見えなかったりなど、いろいろ問題が起こるそうなので、覚悟しておきます。

コラボレーター(Collaborators)

GitHubのユーザーでかつ誰かのリポジトリにアクセスして編集することが許された権限を持つ人たちのことです。

GitHubの Settings >Manage access というメニューにありました(2020年5月現在)

フェッチ

gitがバージョンアップして「pull = fetch + merge」という解釈で良いとありました。

【入門者向け】Gitのfetchコマンドについて図を用いて解説

フェッチをすると、リモートの変更を追跡するためのブランチ「リモートトラッキングブランチ(origin/master)」がローカルに作成されます。

そしてローカルのmasterブランチを最新にするためには、masterブランチから
git marge origin/master とマージします。

これまで謎だった origin/master の正体が少しわかりました。

またGit-itには、
git fetch --dry-run で「Pullする前にリモート上で行われた変更を見てみる」 とありました。
pullではなくfetch?引っかかる表現だな...という印象なのですが、おそらく --dry-run は処理のシュミレートをするオプションなので、fetch時により詳細な内容が表示されるのではないかと想像しました。おいおい確認できれば。

最後までやらずに終了

Git-it最後のステップは、練習用のGitHubリポジトリにプルリクを送り、マージされた内容をプルする、というものでした。

こちらに自分のユーザー名のテキストファイルが追加されます。

patchwork/CONTRIBUTORS at gh-pages · jlord/patchwork · GitHub

Git-it修了生の方々がずらり。
おもいっきり日本人とわかるユーザー名にしてしまったことを少し後悔して、操作の流れを読んで終わりにしました(いくじなし)。

***

コマンドでGitを覚えると、SourceTreeなどのGUIの操作はこういうことだったのか、という気付きがありました。嫌でも黒い画面の英文を読まなくてはいけないので、ちゃんとした理解が必要で、「なんとなく」の操作が減りそうです。

...忘れてはいけないのは、私はVS CodeでGitを使う方法を模索しているということです。
黒い画面慣れしてきたので、VS Codeでもやっていけそうです。