Laravel セッションドライバ(session driver)

セッションはstorage/framework/sessionsに保存される。

セッションは暗号化され、クッキーに保存される。
セッションはdatabaseに保存される。

開発環境ではfileセッションだが、本番環境ではDBやredisに入れるとあるぞ。

まず、routingから設定します。
routes/web.php

Route::get('/put-data', function(){
	session()->put(['email'=> 'example@gmail.com']);
	return session()->get('email');
});
Route::get('/list-data', function(){
	return session()->all();
});

サーバーを立てます。
[vagrant@localhost zeus]$ php artisan serve –host=192.168.35.10
Laravel development server started:

続いて、/put-dataにアクセスします。

次に、/list-dataにアクセスします。
セッションに保存されているデータがjson形式で表示されます。
{“_token”:”Lc4QKtUxDWzNI2IelKkLcylMfBSB2jgfjbWU8mwD”,”email”:”example@gmail.com”,”_previous”:{“url”:”http:\/\/192.168.35.10:8000\/put-data”},”_flash”:{“old”:[],”new”:[]}}


token, email, _previous, _flashがキーになっていそうですね。

Laravel 5.7のHTTPセッションの設定を見てみる(config.session.php)

セッションとは、ユーザがWebサイトを表示して離脱するまでの一連の流れ
訪問のvisitと同じ

Laravel5.7ではリクエスト間に渡りユーザに関する情報を保存するセッションが提供されている。
Laravel5.7 HTTPセッション

セッションの設定はconfig/session.phpにある。

session.phpの中身を見てみましょう。

return [

    /*
    |--------------------------------------------------------------------------
    | Default Session Driver
    |--------------------------------------------------------------------------
    |
    | This option controls the default session "driver" that will be used on
    | requests. By default, we will use the lightweight native driver but
    | you may specify any of the other wonderful drivers provided here.
    |
    | Supported: "file", "cookie", "database", "apc",
    |            "memcached", "redis", "array"
    |
    */

    'driver' => env('SESSION_DRIVER', 'file'),

    /*
    |--------------------------------------------------------------------------
    | Session Lifetime
    |--------------------------------------------------------------------------
    |
    | Here you may specify the number of minutes that you wish the session
    | to be allowed to remain idle before it expires. If you want them
    | to immediately expire on the browser closing, set that option.
    |
    */

    'lifetime' => env('SESSION_LIFETIME', 120),

    'expire_on_close' => false,

    /*
    |--------------------------------------------------------------------------
    | Session Encryption
    |--------------------------------------------------------------------------
    |
    | This option allows you to easily specify that all of your session data
    | should be encrypted before it is stored. All encryption will be run
    | automatically by Laravel and you can use the Session like normal.
    |
    */

    'encrypt' => false,

    /*
    |--------------------------------------------------------------------------
    | Session File Location
    |--------------------------------------------------------------------------
    |
    | When using the native session driver, we need a location where session
    | files may be stored. A default has been set for you but a different
    | location may be specified. This is only needed for file sessions.
    |
    */

    'files' => storage_path('framework/sessions'),

    /*
    |--------------------------------------------------------------------------
    | Session Database Connection
    |--------------------------------------------------------------------------
    |
    | When using the "database" or "redis" session drivers, you may specify a
    | connection that should be used to manage these sessions. This should
    | correspond to a connection in your database configuration options.
    |
    */

    'connection' => env('SESSION_CONNECTION', null),

    /*
    |--------------------------------------------------------------------------
    | Session Database Table
    |--------------------------------------------------------------------------
    |
    | When using the "database" session driver, you may specify the table we
    | should use to manage the sessions. Of course, a sensible default is
    | provided for you; however, you are free to change this as needed.
    |
    */

    'table' => 'sessions',

    /*
    |--------------------------------------------------------------------------
    | Session Cache Store
    |--------------------------------------------------------------------------
    |
    | When using the "apc" or "memcached" session drivers, you may specify a
    | cache store that should be used for these sessions. This value must
    | correspond with one of the application's configured cache stores.
    |
    */

    'store' => env('SESSION_STORE', null),

    /*
    |--------------------------------------------------------------------------
    | Session Sweeping Lottery
    |--------------------------------------------------------------------------
    |
    | Some session drivers must manually sweep their storage location to get
    | rid of old sessions from storage. Here are the chances that it will
    | happen on a given request. By default, the odds are 2 out of 100.
    |
    */

    'lottery' => [2, 100],

    /*
    |--------------------------------------------------------------------------
    | Session Cookie Name
    |--------------------------------------------------------------------------
    |
    | Here you may change the name of the cookie used to identify a session
    | instance by ID. The name specified here will get used every time a
    | new session cookie is created by the framework for every driver.
    |
    */

    'cookie' => env(
        'SESSION_COOKIE',
        str_slug(env('APP_NAME', 'laravel'), '_').'_session'
    ),

    /*
    |--------------------------------------------------------------------------
    | Session Cookie Path
    |--------------------------------------------------------------------------
    |
    | The session cookie path determines the path for which the cookie will
    | be regarded as available. Typically, this will be the root path of
    | your application but you are free to change this when necessary.
    |
    */

    'path' => '/',

    /*
    |--------------------------------------------------------------------------
    | Session Cookie Domain
    |--------------------------------------------------------------------------
    |
    | Here you may change the domain of the cookie used to identify a session
    | in your application. This will determine which domains the cookie is
    | available to in your application. A sensible default has been set.
    |
    */

    'domain' => env('SESSION_DOMAIN', null),

    /*
    |--------------------------------------------------------------------------
    | HTTPS Only Cookies
    |--------------------------------------------------------------------------
    |
    | By setting this option to true, session cookies will only be sent back
    | to the server if the browser has a HTTPS connection. This will keep
    | the cookie from being sent to you if it can not be done securely.
    |
    */

    'secure' => env('SESSION_SECURE_COOKIE', false),

    /*
    |--------------------------------------------------------------------------
    | HTTP Access Only
    |--------------------------------------------------------------------------
    |
    | Setting this value to true will prevent JavaScript from accessing the
    | value of the cookie and the cookie will only be accessible through
    | the HTTP protocol. You are free to modify this option if needed.
    |
    */

    'http_only' => true,

    /*
    |--------------------------------------------------------------------------
    | Same-Site Cookies
    |--------------------------------------------------------------------------
    |
    | This option determines how your cookies behave when cross-site requests
    | take place, and can be used to mitigate CSRF attacks. By default, we
    | do not enable this as other CSRF protection services are in place.
    |
    | Supported: "lax", "strict"
    |
    */

    'same_site' => null,

];

ドライバー
supported file, cookie, database, apc, memcached, redis, array
‘driver’ => env(‘SESSION_DRIVER’, ‘file’),
セッションライフタイム
‘lifetime’ => env(‘SESSION_LIFETIME’, 120),
‘expire_on_close’ => false,
暗号化
セッションを暗号化できる。
‘encrypt’ => false,
session file location
セッションを保存する場所
‘files’ => storage_path(‘framework/sessions’),
DB connection
‘connection’ => env(‘SESSION_CONNECTION’, null),
sessionを入れるDBテーブル
‘table’ => ‘sessions’,
Session Cache Store
‘store’ => env(‘SESSION_STORE’, null),
‘lottery’ => [2, 100],
session cookie name
‘cookie’ => env(
‘SESSION_COOKIE’,
str_slug(env(‘APP_NAME’, ‘laravel’), ‘_’).’_session’
),
session cookie path
‘path’ => ‘/’,
session cookie domain
‘domain’ => env(‘SESSION_DOMAIN’, null),
HTTPS Only Cookies
‘secure’ => env(‘SESSION_SECURE_COOKIE’, false),
HTTP Access Only
‘http_only’ => true,
Same-Site Cookies
‘same_site’ => null,

apacheのLogLevelディレクティブ

LogLevelディレクティブでは、エラーログに記録するエラーレベルを指定することができる。
以下のように、LogLevel warnでは、”warn”以上のエラーレベルはすべてエラーログに記録するようになり、逆にnotice以下のエラーレベルに関してはログに記載されなくなる。

#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel warn

ふーん

apacheエラーログの場所とフォーマット

まず、apacheのエラーログの場所は、アクセスログと同様に、
/var/log/httpd/配下にあります

エラーログの中身を見てみましょう。
error_log-yyyymmdd

[Sun Dec 16 16:35:05 2018] [notice] Digest: generating secret for digest authentication ...
[Sun Dec 16 16:35:05 2018] [notice] Digest: done
[Sun Dec 16 16:35:06 2018] [notice] Apache/2.2.15 (Unix) DAV/2 configured -- resuming normal operations
[Mon Dec 17 22:12:31 2018] [notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Mon Dec 17 22:12:32 2018] [notice] Digest: generating secret for digest authentication ...
[Mon Dec 17 22:12:32 2018] [notice] Digest: done
[Mon Dec 17 22:12:42 2018] [notice] Apache/2.2.15 (Unix) DAV/2 configured -- resuming normal operations
[Tue Dec 18 22:53:56 2018] [warn] child process 6696 still did not exit, sending a SIGTERM
[Tue Dec 18 22:53:58 2018] [notice] caught SIGTERM, shutting down
[Thu Dec 20 00:32:58 2018] [notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Thu Dec 20 00:32:58 2018] [notice] Digest: generating secret for digest authentication ...
[Thu Dec 20 00:32:58 2018] [notice] Digest: done
[Thu Dec 20 00:33:03 2018] [notice] Apache/2.2.15 (Unix) DAV/2 configured -- resuming normal operations
[Sat Dec 22 21:33:15 2018] [notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Sat Dec 22 21:33:15 2018] [notice] Digest: generating secret for digest authentication ...
[Sat Dec 22 21:33:15 2018] [notice] Digest: done
[Sat Dec 22 21:33:31 2018] [notice] Apache/2.2.15 (Unix) DAV/2 configured -- resuming normal operations
[Sun Dec 23 09:19:04 2018] [notice] SIGHUP received.  Attempting to restart
httpd: Could not reliably determine the server's fully qualified domain name, using localhost.localdomain for ServerName

割と色々出てますが、内容は比較的複雑ではありません。
[Sun Dec 23 09:19:04 2018] :エラー検知日付
[notice] : エラー重要度
SIGHUP received. Attempting to restart
httpd: Could not reliably determine the server’s fully qualified domain name, using localhost.localdomain for ServerName : エラー内容

エラーレベルの種類
emerg: 緊急
alert: ただちに対処が必要
crit: 致命的状態
error: 通常エラー
warn: 警告
notice: 通知
info: サーバーの状態についての情報
debug: デバッグメッセージ

にゃーるほど

apacheログの場所とフォーマット

httpdにアクセスがあった場合やエラーがあった場合、ログに保存される

場所は以下にあります。
var/log/httpd/access_log

アクセスしようとしたら、permission denied! 何?

とりあえず、アクセス権を変更します。
[vagrant@localhost ~]$ sudo chmod 777 /var/log/httpd/

var/log/httpd/に入れるようになりました。
access_logとerror_logがあります。

access_log-yyyymmddから見てみましょう。

192.168.35.1 - - [25/Nov/2018:20:48:18 +0900] "GET /login HTTP/1.1" 404 282 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"
192.168.35.1 - - [25/Nov/2018:20:48:20 +0900] "GET /favicon.ico HTTP/1.1" 404 288 "http://192.168.35.10/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"
192.168.35.1 - - [25/Nov/2018:20:48:59 +0900] "GET / HTTP/1.1" 200 142 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"

ログフォーマット

%h %l %u %t \"%r/" %>s %b \"%{refferer}i"\" /"%{user-agent}i"

%h リモートホスト:192.168.35.1
%l リモートログ名、mod_identモジュールがロードされており、IdentityCheckディレクティブがOnになっている場合のみ表示。それ以外の場合は『-』と表示。:-
%u リモートユーザ:-
%t リクエストを受信した時刻:25/Nov/2018:20:48:18 +0900
%r リクエストの最初の行:GET /login HTTP/1.1
%>s %sはステータスコード。内部でリダイレクトされた場合でも元々のステータスコードを出力。%>sはリダイレクトされた場合最後のステータスコードを出力。:404
%b HTTPヘッダを除くレスポンスのバイト数:282
%{referer}i サーバが受信したリクエストヘッダのReferer:-
${user-agent}i サーバが受信したリクエストヘッダのUser-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36

/etc/httpd/conf/httpd.confの497行目に記載があります。

#
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
#
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent

なるほどー そういうこと

ブラウザの横幅が変わった時の複数画像表示

横幅320pxの画像を1枚表示
viewportはinitial-scale=1.0とする

<!DOCTYPE html>
<html lang="ja">
<head>
	 <meta charset="UTF-8">
	 <title>画像の縮小</title>
         <meta name="viewport" content="initial-scale=1.0,width=device-width">
<style>
	.center {
		text-align:center;
	}
</style>
</head>
<body>
  <div class="center">
	<img src="img/cat.jpeg">
  </div>
</body>
</html>

PC版:画像よりも広いブラウザで閲覧
当然、ブラウザの横幅におさまる

PC版:画像よりも狭いブラウザで閲覧
ブラウザに収まらない 例:287pxのブラウザでみてみる

mobile版:画像よりも狭いブラウザで閲覧
view-portを設定しているので、画面幅で表示される

画像を2枚にします

<body>
  <div class="center">
	<img src="img/cat.jpeg">
	<img src="img/frog.jpeg">
  </div>
</body>

PC版:複数画像よりも広いブラウザで閲覧

PC版:複数画像よりも狭いブラウザで閲覧
収まらないので、改行されて表示される

mobile版
収まらないので、改行されて表示される

ブラウザ幅に合わせて画像サイズを自動調整したい

<head>
	 <meta charset="UTF-8">
	 <title>画像の縮小</title>
	 <meta name="viewport" content="initial-scale=1.0,width=device-width">
<style>
	.center {
		text-align:center;
	}
	.center img {
		width:45%;
	}
</style>
</head>
<body>
  <div class="center">
	<img src="img/cat.jpeg">
	<img src="img/frog.jpeg">
  </div>
</body>

widthを%で指定すれば、ブラウザサイズに合わせて自動縮小される。

ただ、これ、画像が可変だと、例えば3マイになったらあかんやん。。

phpで文頭半角ドット(.)を正規表現(preg_match)

まず文章を用意します。
test.txt

.Linuxは無料です。あなたの時間に価値が無いなら。
Jamie Zawinski

1行ずつ正規表現でみていき、文頭に半角ドットがあった場合は、エラーをアラートメッセージを出します。

ini_set('mbstring.internal_encoding' , 'UTF-8');
$file = fopen("test.txt", "r");

if($file){
	while($line = fgets($file)){
		if(preg_match('/^./', $line)){
			echo "文頭に半角ドットが含まれています". "<br>";
		} else {
			echo $line . "<br>";
		}	
	}
}

fclose($file);

なに!? 半角ドットがエスケープされていない。

if($file){
	while($line = fgets($file)){
		if(preg_match('/^\./', $line)){
			echo "文頭に半角ドットが含まれています". "<br>";
		} else {
			echo $line . "<br>";
		}	
	}
}

出来たー

phpでif文で1行ずつ取得して出力する

まずテキストファイルを作成します。
test.txt

Linuxは無料です。あなたの時間に価値が無いなら。
Jamie Zawinski

phpで1行ずつ読み込む

ini_set('mbstring.internal_encoding' , 'UTF-8');
$file = fopen("test.txt", "r");

if($file){
	while($line = fgets($file)){
		echo $line . "<br>";
	}
}

fclose($file);
?>

続いて、正規表現で、「半角ドット(.)」「半角スペース( )」「ダブルクォート(“)」が含まれていた場合の処理をやりたいと思います。

バッチ処理(英語ではBatch proccessing)とは

今更感がありますが。。
バッチ処理:英語ではBatch proccessing

– 一つの流れのプログラムを順次実行すること。
– 予め定められた処理を一度に行う。

PC起動時の処理などもバッチ処理という。
というこは、クローンタブで時間を定めて処理することだけをバッチ処理とは言わない、もっと広義な意味を含めているようですな。

ざっくりというと、まとめて処理ですが、場面によって微妙に違いますね。

Mysql “ENCLOSED BY”

mysqlのENCLOSED BYって何?

mysql5.6のリファレンスマニュアルを覗いてみます。
LOAD DATE INFILE構文
optionallyでENCLOSED BY ‘char’と記載があります。

LOAD DATA INFILEは、高速にテキストファイルからテーブルに行を読み取る。
TSVやCSVからMySQLにロードする方法なのね。

サンプルのコマンドを見てみましょう。

mysql> SET character_set_server= utf8mb4;
mysql> SET NAMES utf8mb4;
mysql> use databasename
mysql>  LOAD DATA INFILE 'hoge.CSV' INTO TABLE foo
    ->  FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
    ->  ( @dummy, @dummy, @dummy, @dummy, @dummy, @dummy)
    ->  SET created_at = CURRENT_TIMESTAMP;

LOAD DATA INFILE でファイルを読み込んで、INTO TABLEで指定したデータベースに値を入れてますね。

まずデータを用意します。配当利回りトップのデータにしておきましょう。dividen.csvで保存します。

/home/vagrantにdividen.csvを保存します。
/home/vagrant/dividen.csvの状態

続いて、databaseを作ります。
mysql> create database equity;

mysql> use equity;
Database changed

mysql> create table dividen(
-> code int,
-> name varchar(30),
-> yeild float
-> );
Query OK, 0 rows affected (0.29 sec)

コードはこれでいいのかな?

LOAD DATA INFILE '/home/vagrant/dividen.csv' INTO TABLE dividen
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY ''
(code, name, yeild)

では行きましょう。

mysql> LOAD DATA INFILE '/home/vagrant/dividen.csv' INTO TABLE dividen
    -> FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY ''
    -> (code, name, yeild);
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

なにいいいいいいいいいいいいいいいいいい

だが、使い方は解った^^