[CSS] object-fitで画像のアスペクト比を変更せずに表示する

異なる画像サイズを一定サイズのカードで表示したい。元画像をそのまま指定したheight, widthで表示した場合、縦長、横長の画像は圧縮されてしまう。どうしたら良いか。

昔、先輩に教わったのだが、システムでは表示する際にデータを装飾することはあっても、基本的に元データそのものを加工・変更してはいけない。

ということで、表示を揃えるためにアップロードした画像をサーバーサイド側で切り抜くのは気が引けていた。
少し調べたら、CSSのobject-fitでアスペクト比を維持したまま処理できるらしい。

contain: アスペクト比を維持したままボックスに収まるよう拡大縮小
cover: アスペクト比を維持したまま、コンテンツボックスを埋めるよう拡大縮小

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style>
		.contain img {
			width: 200px;
  			height: 150px;
  			object-fit: contain;
		}
		.cover img {
			width: 200px;
  			height: 150px;
  			object-fit: cover;
		}
		.fill img {
			width: 200px;
  			height: 150px;
  			object-fit: fill;
		}
	</style>
</head>
<body>
	<div class="contain">
		<img src="img/bridge1.jpg"><br>
		<img src="img/bridge2.jpg">
	</div>
	<br>
	<div class="cover">
		<img src="img/bridge1.jpg"><br>
		<img src="img/bridge2.jpg">
	</div>
	<br>
	<div class="fill">
		<img src="img/bridge1.jpg"><br>
		<img src="img/bridge2.jpg">
	</div>
	<script>
	</script>
</body>
</html>

coverだと、画像が切れる恐れがあるから、containが一番しっくり来るな。

[Laravel8.16.0] Google Analyticsの値をバッチ処理で挿入する

// 1.モデルを作成
$ php artisan make:model Analytic -m

// 2.migration file

    public function up()
    {
        Schema::create('analytics', function (Blueprint $table) {
            $table->id();
            $table->integer('sessions')->nullable();
            $table->integer('pageviews')->nullable();
            $table->timestamps();
        });
    }

$ php artisan migrate
mysql> describe analytics;

// 3.PDO部分を先に作ります

$date = new DateTime();
$date = $date->format('Y-m-d H:i:s');
$sessions = 100;
$pageviews = 200;

$username="*";
$password="*";
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8';

try {
  $dbh = new PDO($dsn, $username, $password,array(PDO::ATTR_EMULATE_PREPARES => false,PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`"));
  $sql = "INSERT INTO analytics(
  sessions, pageviews, created_at
  ) VALUES (
    ".$sessions.", ".$pageviews.", '".$date."'
  )";

  $res = $dbh->query($sql);
} catch (PDOException $e) {
  exit('データベース接続失敗。'.$e->getMessage());
}

$dbh = null;

mysql> select * from analytics;
+—-+———-+———–+———————+————+
| id | sessions | pageviews | created_at | updated_at |
+—-+———-+———–+———————+————+
| 1 | 100 | 200 | 2020-12-05 00:37:52 | NULL |
+—-+———-+———–+———————+————+
1 row in set (0.00 sec)

// 4. GoogleAnalyticsAPIを連結
L バッチで処理する際は、required_once と p12ファイルを絶対パスで指定する必要がある。

require_once '/home/vagrant/dev/test/google-api-php-client/src/Google/autoload.php';
$service_account_email = '*.iam.gserviceaccount.com';
$key = file_get_contents('/home/vagrant/dev/test/analytics-*.p12');
$profile = '*';

$client = new Google_Client();
$analytics = new Google_Service_Analytics($client);

$cred = new Google_Auth_AssertionCredentials(
  $service_account_email,
  array(Google_Service_Analytics::ANALYTICS_READONLY),
  $key
);

$client->setAssertionCredentials($cred);
if($client->getAuth()->isAccessTokenExpired()){
  $client->getAuth()->refreshTokenWithAssertion($cred);
}

$result = $analytics->data_ga->get(
  'ga:' . $profile,
  'yesterday',
  'yesterday',
  'ga:sessions,ga:pageviews',
);
$sessions = $result -> rows[0][0];
$pageviews = $result -> rows[0][1];

mysql> select * from analytics;

$ sudo chmod 755 batch.php

// 5.Cronの設定
$ which php
/usr/bin/php

$ sudo vi /etc/crontab

*/1 * * * * /usr/bin/php /home/vagrant/dev/testApp/batch.php

mysql> select * from analytics;

$ sudo tail -f /var/log/cron でcronログ見るとエラーは出てないのに、mysqlにデータが入ってなくてなんでかと思ったが、required_once と p12ファイルを絶対パスで指定していなかったのが原因だったみたい。難儀なこっちゃ。

[Laravel8.16.0] コントローラのメソッド名とviewsファイル名の命名規則

入力->確認->登録という画面遷移の時に、確認画面のControllerの関数名とtemplateのファイル名に迷った。

関数のメソッドは下のようにキャメルケースで書く。これはいつも通り。

public function createConfirm() {
        return view('admin.client.input_confirm');
    }

で、viewsはスネークケースで書くらしい。アンダーバー無しにつなげて書くのはNGらしい。今までずっとアンダーバー削除してた。
正) input_confirm.blade.php
誤) inputconfirm.blade.php

### まとめ
テーブル名
 L スネークケース(複数): users_table
モデル名
L アッパーキャメル(単数): UserData
migration名
L スネークケース(単数): xxx_crate_users_table
seeder名
L アッパーキャメル: UsersTableSeeder
Controllers名
L アッパーキャメル: UserDataController
views名
L スネークケース: users_add.blade.php
※PHPの関数名ではスネークケースで書くこともあるとのこと

なんか、HTMLのファイル名やルーティングでスネークスケールで書くのかなり抵抗あるけど、bladeならユーザに見えないからまあいいのか。そういえば、migrationも確かにスネークスケールですね。

[Laravel8.16.0] laravel collective(v6.2.0)を使う

$ composer require laravelcollective/html

laravelは8系なのに、collectiveがv6.2.0って、全然追いついてないけど、使ってみます。
L collectiveはcsrfは自動

config/app.php

'providers' => [
   // 省略
   Collective\Html\HtmlServiceProvider::class,
]

'aliases' => [
  // 省略
  'Form' => Collective\Html\FormFacade::class,
  'Html' => Collective\Html\HtmlFacade::class,
],

まず、普通のhtmlで書きます。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
	<h1>user id:{{ $user-> role_id}}</h1>
	<div class="col-md-8">
	<form method="post" action="/admin/create">
		<div class="form-group">
			<label for="title">Title:</label>
			<input class="form-control" name="title" type="text" id="title">
		</div>

		<div class="form-group">
			<label for="body">Body:</label>
			<textarea class="form-control" name="body" type="text" id="body"></textarea>
		</div>

		<div class="form-group">
			<label for="published_at">Publish On:</label>
			<input class="form-control" name="published_at" type="text" id="published_at">
		</div>
		<div class="form-group">
			<input class="btn btn-primary form-control" type="submit" value="送信">
		</div>
	</form>
	</div>
</body>
</html>

続いて、collectiveを使います。

{!! Form::open(['url' => '/admin/create']) !!}
			<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', 'Published On:') !!}
				{!! Form::text('published_at', null, ['class' => 'form-control']) !!}
			</div>
			<div class="form-group">
			{!! Form::submit('送信',['class' => 'btn btn-primary form-control']) !!}
			</div>
		{!! Form::close() !!}

ふむ、laravel8系でもcollective v6使えますね。安心した。
これを実装していきます。

[Laravel8.16.0] カラム追加・削除のmigrationファイルの書き方

usersテーブルで、first_name、last_nameを削除して、client_nameのカラムを作りたい
※「姓」・「名」を「名前」のカラム一つに統一したい

$ php artisan -V
Laravel Framework 8.16.0

migrationファイルの作成
$ php artisan make:migration change_name_columns_to_users_table –table=users

2020_12_04_040045_change_name_columns_to_users_table.php

    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            //
            $table->string('client_name')->nullable();
            $table->dropColumn('first_name');
            $table->dropColumn('last_name');
        });
    }

$ php artisan migrate

// migration確認
mysql> describe users;
mysql> select * from users

// git push
$ git add .
$ git commit -m “name columns changed”

‘first_name’、’last_name’もnullableで作っていたが、dropColumnの時は特にnullbaleとかはつけなくて良いみたい。
なるほど。

[UI・UX] 背景色とテキストカラーのコントラスト比の確認方法

https://lab.syncer.jp/Tool/Color-Contrast-Checker/というサイトで、背景色とテキストのコントラスト比を確認できる。

例えば、背景色が、#ffffff(white)で、テキストが#9A9A9Aだと、コントラスト比が2.81で、Web Content Accessibility Guidelines (WCAG) 2.0の基準4.5に満たないとのこです。

Web Content Accessibility Guidelines
https://waic.jp/docs/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html

テキスト及び文字画像の視覚的提示に、少なくとも 4.5:1 のコントラスト比がある。

なうほど、こういうのがあるんやな。勉強になります。

alt属性とtitle属性

alt属性はよく画像につけるものとしてありますが、title属性とは何でしょうか?

– alt属性はロボットに対して明示してあげるもの
– title属性は要素の補足説明をするためのものいわゆる「ツールチップ」

ロゴで以下の様にtitle属性、alt属性を設定すると良いとのこと。

<a href="/" title="トップページへ">
          <div class="top-logo">
            <img src="img/logo.png" alt="サービス名・会社名">
          </div>
        </a>

なるほどー

[jQuery3.5.1]最新版のバージョン

公式サイトを確認すると、最新版のバージョンは3.5.1となっています。

フロントを構築する場合は、最新のjQueryを使わないと駄目とのこと。
なるほど、勉強になりますね。

[viewport] maximum-scale=1.0, user-scalable=0

viewportの指定で例えば以下の様に設定していたとする。

<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, shrink-to-fit=no' name='viewport' />

user-scalable:ズームの操作
-> ユーザーがズームできるかどうかの設定。
-> 初期値はyes。yes=1,no=0。

maximum-scale 最大倍率
-> 最小拡大比率の設定。
-> デフォルトは1.6で指定可能範囲は0より大きく、10までの値。

つまり、「maximum-scale=1.0, user-scalable=0」だと、ユーザのズームを禁止しており、仕様にもよるが、多くの場合、ユーザエクスペリエンス上、望ましくないとのこと。

なるほど、プロの領域やな。

[Laravel8.16.0] Google Analytics APIを使う

まず、analytics-*-*.p12ファイルですが、publicには置けないので、resourcesフォルダの下にstaticフォルダを作成し、そこに置きます。
※storageやpublicに置かない様にする。

続いて、google-api-php-clientをインストールします。
githubで最新を確認する。この記事を書いている時点では^2.7が最新です。
https://github.com/googleapis/google-api-php-client

$ composer require google/apiclient:”^2.7″

AdminController.php (*test)
L resource_path(‘static/analytics-*-*.p12’)で、p12を指定する

    public function index(){

        $client = new Google_Client();
        $client->setApplicationName("Client_Library_Examples");
        $client->setDeveloperKey(resource_path('static/analytics-*-*.p12'));
        dd($client->getAccessToken());

    	$user = Auth::user();
        return view('admin.index',compact('user'));
    }

nullが返ってくるとOKっぽい。

テスト環境と同じ様に書いてみます。

use Google_Client;
use Google_Service_Analytics;

$service_account_email = '*.iam.gserviceaccount.com';
      $key = file_get_contents(resource_path('static/analytics-*-*.p12'));
      $profile = '*';

      $client = new Google_Client();
      $analytics = new Google_Service_Analytics($client);

      $cred = new Google_Auth_AssertionCredentials(
        $service_account_email,
        array(Google_Service_Analytics::ANALYTICS_READONLY),
        $key
      );

      $client->setAssertionCredentials($cred);
      if($client->getAuth()->isAccessTokenExpired()){
        $client->getAuth()->refreshTokenWithAssertion($cred);
      }

Class ‘App\Http\Controllers\Google_Auth_AssertionCredentials’ not foundのエラー

issueに原因が載ってます。
https://github.com/GoogleCloudPlatform/nodejs-docs-samples/issues/158

Oh, I've just found https://github.com/google/google-api-php-client/blob/master/UPGRADING.md

So it's the docs at https://developers.google.com/analytics/devguides/reporting/core/v3/quickstart/service-php that are wrong.

GoogleDevコンソールで、「サービス アカウント キーの作成」からjsonファイルを作成して、以下に書き換えます。

use Google_Client;
use Google_Service_Analytics;

$profile = '*';

        $client = new Google_Client();
        $client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly'));

        $client->setSubject('*.iam.gserviceaccount.com');
        $client->setAuthConfig(array(
            'type' => 'service_account',
            'client_email' => '*.iam.gserviceaccount.com',
            'client_id' => '*',
            'private_key' => "-----BEGIN PRIVATE KEY-----***-----END PRIVATE KEY-----\n"
        ));

        $analytics= new Google_Service_Analytics($client);

         $result = $analytics->data_ga->get(
         'ga:' . $profile,
         'yesterday',
         '0daysAgo',
         'ga:pageviews',
         array(
           // "dimensions" => 'ga:pageTitle',
           "dimensions" => 'ga:pagePath',
           "sort" => '-ga:pageviews',
           "max-results" => '10',
         )
        );

        $data = $result->rows;
        dd($data);

これでいけました。結局p12は使わない。
う〜ん、AnalyticsAPIは使うの緊張する。