20200727のPHPに関する記事は11件です。

yps並走備忘録 Task2 MySQL(5.7)~nginx(v1.18)~PHP(7.3)~Laravelインストール

yps Task 2 アプリを動かす準備

今回の流れ
1. MySQLインストール
2. Nginxインストール
3. PHPインストール
4. Laravelインストール
5. VS CodeでSSH接続してサーバーにあるファイルを編集

-----用意するもの-----
VS Code
折れない心(笑)

MySQL5.7のインストール&設定

アプリでデータベース管理を司るMySQLをインストール、設定していきます。

まずはインストール

sudo yum localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm
sudo yum install -y mysql-community-server -y

動作確認

mysqld --version
(正常に完了していればMySQLの情報が表示される)

sudo systemctl enable mysqld(MySQLを自動で起動する設定)
sudo systemctl start mysqld (MySQLを起動)
sudo systemctl status mysqld (MySQLの状態を確認、起動できていれば「active(Running)」という緑の文字が出てくるはず)
sudo systemctl stop mysqld (一旦MySQLを停止)

MySQLへログイン・パスワード変更・文字コードを設定

sudo cat /var/log/mysqld.log | grep -i root (仮で設定されたパスワードを表示、root@localhost: xxxxxxと表示されるはず)
sudo systemctl start mysqld
mysql -u root -pと打つとPassword:という表示になる、ここで上記の仮パスワードを入力するのですが、Linuxの仕様で入力しても何も表示されないので注意!
ミスタイプがないように打って、Enterを押すと、正しい場合はMySQLに入れ、表示がmysql>となるはず。

パスワード変更

SET PASSWORD = PASSWORD('パスワードをここに入力')
-------------注意事項-------------
- 8文字以上、英字の大文字・小文字・数字・記号を全て混ぜないといけない
- #はエラーに基になるので使用しない

変更できたらexitと打つとサーバーのターミナルへ戻れる

日本語を扱えるように文字コードを変更

sudo vi /etc/my.cnf

最終行にcharacter-set-server=utf8mb4を追記

sudo systemctl restart mysqld(MySQLを再起動して設定を反映)
mysql -u root -p(MySQLにログイン)
Password:設定したパスワード

mysql> show variables like "chara%";(文字コードの設定が反映されているか確認)

MySQLのインストールここまで


Nginxのインストール&設定

補足:nginxとは? 参考url:

インストール

1. インストール用のyumレポジトリ作成
sudo vi /etc/yum.repos.d/nginx.repo
開いたファイルに以下を記述
[nginx]
name=nginx repo
baseurl=https://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

2. 以下のコマンドを打ってインストール
sudo yum install nginx -y

完了したらバージョンを確認
nginx -v

nginxを自動で起動できるように設定
sudo systemctl enable nginx

3. AWSマネジメントコンソールからインバウンドルールにhttp、httpsポートを追加
http = 80
https = 443

nginxを再起動して設定を反映
sudo systemctl nginx

ブラウザにEC2インスタンスのIPを入れてWelcome to Nginxが表示されればインストール完了

4. nginxのrootディレクトリ変更
sudo mkdir /var/www wwwディレクトリを作成
sudo mkdir /var/www/html wwwディレクトリの中にhtmlディレクトリを作成
sudo chown -R centos:nginx /var/www /var/www以下の権限をcentosからnginxに移譲

5. nginxの設定変更
sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.org 元々の設定をorgファイルでバックアップ保存
sudo vi /etc/nginx/conf.d/default.conf 設定ファイルを編集

--------編集する場所----------
rootのパスを変更
#root /usr/share/nginx/html;  ⇒ root /var/www/html;

Nginx構文チェック
sudo nginx -t 何も表示されなければOK!

Nginxを再起動
sudo systemctl restart nginx

ブラウザで再度EC2のIPアドレスを開いて(or更新して)403エラーになっていればOK

nginxのインストール&設定ここまで


PHP 7.3のインストール&設定

お次はいよいよPHPを動かせるように必要なものをインストールしていきます

1. yum レポジトリのインストール&アップデート

EC2にインストールするためのプログラムが古いのでアップデートします。
sudo yum install epel-release -y
sudo yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm -y
sudo yum update -y

2. PHPのインストール

sudo yum -y install --enablerepo=epel,remi,remi-php73 php php-devel php-mbstring php-pdo php-gd php-xml php-mcrypt php-fpm php-mysql php-mysqlnd zip unzip

バージョンの確認
php -vで以下が表示されればOK

PHP 7.3.20 (cli) (built: Jul 7 2020 07:53:49) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.20, Copyright (c) 1998-2018 Zend Technologies

3. PHPとNginxを連携させます

php-fpmの設定

sudo cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.org 恒例、元のファイルバックアップ
sudo vi /etc/php-fpm.d/www.conf 設定ファイル編集

変更する場所
user = nginx
group = nginx
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

php-fpmの設定ここまで


Nginxの設定

sudo vi /etc/nginx/conf.d/default.conf

まずは10行目くらいにあるindexのところに追記します
index index.php(←追記) index.html index.htm;
そのすぐ下に下記も追記
try_files $uri $uri/ /index.php?$query_string;

さらにlocation / 以下に下記を追記します
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

終わるとこんな感じ
image.png

上記連携が終わったら…

配下のディレクトリもnginxへ所有者変更(使えるようにする)
sudo chown -R centos:nginx /var/www/ /var/www/

php-fpmの自動起動
sudo systemctl enable php-fpm

nginx再起動
sudo systemctl restart nginx

php-fpm起動
sudo systemctl start php-fpm

ここまでできればあとちょっと!

テスト表示用のindex.phpファイルを作成
vi /var/www/html/index.php

ファイルに以下を記述
<?php echo phpinfo();?>

:wqで保存したらnginxとphp-fpmを再起動
sudo systemctl restart nginx
sudo systemctl restart php-fpm

ブラウザを更新してPHPのバージョン情報が見られれば完了です


Laravelのインストール&設定

一時フォルダに移動

cd/tmp

Laravelのインストールに必要なComposerをインストール

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"

Composerがどこでも使えるようにします

sudo mv composer.phar /usr/local/bin/composer
sudo chmod +x /usr/local/bin/composer

Laravelを構築します

cd /var/www/html
composer create-project --prefer-dist laravel/laravel yps ※ypsの部分はもちろん任意の名前でOK

※phpをインストールした時にzip unzipがちゃんとインストールされていないとここで躓く可能性があります

無事Laravelの構築が終わったら設定をしましょう

cd yps Laravelのフォルダへ移動
php artisan key:generate composerでlaravelアプリ用の暗号化キーの生成
cp -p .env.example .env
.envファイルの下記の部分を変更します
APP_URL= EC2のIPアドレス
DB_PASSWORD= MySQLのパスワード

node.jsとnpm(パッケージ管理システム)をインストール

多分後日フロント周りをいじるとき用…かな?
sudo yum install npm node -y
composer install
npm install

下記のコマンドを打てば設定は一段落

sudo chorn-R centos:nginx /var/www/
sudo chmod -R 777 storage/ bootstrap/cache/

laravelのWelcome画面表示

vi /etc/nginx/conf.d/default.conf

/var/www/html;
となっているところを
/var/www/html/yps/public;
に変更して…

nginxとphp-fpmを再起動
sudo systemctl restart nginx
sudo systemctl restart php-fpm

最後にEC2インスタンスのIPアドレスをブラウザに入力すればLaravelのWelcome画面が見られるはずです。

さらにここからVS Codeで編集できるようにします

  1. VS Codeを起動して、拡張機能のRemote-SSHをインストール
  2. 左の「リモートエクスプローラーアイコンをクリック」
  3. SSH TARGETSと書いてあるところにカーソルを合わせると出てくる歯車アイコンをクリック
  4. 画面中央上部にSelect SSH configuration file to updateと出るのでC:\users\ユーザー名.ssh\configをクリック
  • Host: 表示名、後ほどコマンドプロンプトからSSH接続をするのにも利用できる
  • Port: AWSで作成したPort番号
  • User: centos
  • HostName: EC2のIPアドレス
  • IdentifyFile: .ssh/xxxx.pem(秘密鍵ファイル)
  1. 入力後に右下の緑色の「リモートウインドウを開く」をクリック
  2. Remote-SSH Connect to Host...をクリック
  3. 上記で作成した表示名をクリック
  4. 画面中央上部にLinux, Windowsとか選択肢が3つくらい出てくるのでLinuxを選択
  5. しばらくするとVS Code Serverが立ち上がる
  6. 完了すると右下にHost名が出る
  7. エクスプローラを開いてresources ⇒ views ⇒ welcome.blade.phpを開く
  8. 84行目にあるウェルカムメッセージを変更して保存
  9. ブラウザをリロードするとウェルカムメッセージが更新されている(ハズ)

以上でTask2完了です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPにおけるページネーションの方法

初投稿です。
PHPのページネーションに関して、以前実装したものの知識が抜けていたので、アウトプットがてら復習したいと思います。何かのお役に立てれば幸いです。

要件
・各ページで5つずつ表示する
・ページの前後には「前へ」「次へ」を表示。複数ページある場合はリンクになり、それぞれのボタンを押すと前後のページへジャンプする
・ページ番号は5つまで表示。基本的に現在表示されているページの前後2つを表示させる
・ページ数が表示されてる部分にあわせて「○件中○〜○件目の商品」と記載する

なお、今回はLaravelなどのフレームワークは使わずに、生のPHPで実装します。

イメージとしてはこんな感じです。

スクリーンショット 2020-07-27 22.36.07.png

DB関連

function get_db_connect(){
  $dsn = 'mysql:dbname='. DB_NAME .';host='. DB_HOST .';charset='.DB_CHARSET;

  try {
    $dbh = new PDO($dsn, DB_USER, DB_PASS, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'));
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
  } catch (PDOException $e) {
    exit('接続できませんでした。');
  }
  return $dbh;
}


function fetch_all_query($db, $sql, $params = array()){
  try{
    $statement = $db->prepare($sql);
    $statement->execute($params);
    return $statement->fetchAll();
  }catch(PDOException $e){
    set_message('データ取得に失敗しました。');
  }
  return false;
}

①modelで必要な要素をselectで抽出する

$db = get_db_connect();

function get_items_list($db, $limit = 5, $offset = 0){
  $sql = '
    SELECT
       --selectする要素を記載
    limit ?
    offset ?';

  return fetch_all_query($db, $sql, array($limit, $offset));
}

このとき、$limit=5で表示させる件数を予め限定させておく。

また、全体の件数も知っておきたいので、countを使って実装。

function get_items_count($db) {
  $sql = '
    SELECT
        count(*)
    FROM
        テーブル名'

    $result = fetch_all_query($db, $sql);

    return $result[0]['count(*)'];
}

②view画面の実装

<?php 

foreach($items as $value) {

--ここにget_items_list関数から表示させたいアイテムを表示

} 

echo $items_count. '件中'.$page_ini. "〜" .$page_fin. "件目の商品";

// リンクをつけるかの判定
if($now > 1){ 
    print '<a href=\'../html/〜.php?page_id='.($now - 1).'\')>前へ</a>'. ' ';
} else {
    print '前へ'. ' ';
}

for($i = 1; $i <= $max_page; $i++){
    if($i >= $now - $range && $i <= $now + $range) {
        if ($i == $now) {
            print '<a class="current_page" href=\'〜.php?page_id='.$now.'\')>'. $now. '</a>'. ' ';
        } else {
            print '<a href=\'../html/〜.php?page_id='.$i. '\')>'. $i. '</a>'. ' ';
        }
    }
}
// リンクをつけるかの判定
if($now < $max_page){ 
    print '<a href=\'../html/〜.php?page_id='.($now + 1).'\')>次へ</a>'. ' ';
} else {
    print '次へ';
}
?>

まず、〜件中○〜○件目の商品の部分から。

$items_countに関しては、modelで記述したget_items_count関数を使って表示させます。

page_iniとpage_fin(つまり、表示させる商品ページの最初と最後の部分)に関しては、getで取得するページidによって、offsetの値が定義され、それにより表示されるページが変わるといった感じ。

「前へ」「次へ」に関しては、クリックするとgetしたページid+1がgetで渡される。

表示されるページの数に関しては、for文にて表示。

$rangeに関しては、ページidが1、もしくは最後のページのときは4、id=2、最後のページから1つ前のときは3、それ以外は2となるように設定しています。

//ページネーションの表示数
if((int)$now === 1 || (int)$now === (int)$max_page) {
    $range = 4;
} else if((int)$now === 2 || (int)$now === ((int)$max_page -1)) {
    $range = 3;
} else  {
    $range = 2;
}

③controllerの記載

viewで指定した変数をそれぞれ定義する。

if(get_get('page_id')) {
  $now = $_GET['page_id'];
} else {
  $now = 1;
}

$offset = ($now - 1) * 5;

$items = get_items_list($db, $limit = 5, $offset);

$items_count = get_items_count();

$max_page = ceil($items_count / 5);

$page_ini = ($offset + 1);

if(count($items) === 5) {
  $page_fin = ($offset + 5);
} else {
  $page_fin = $items_count;
}

if((int)$now === 1 || (int)$now === (int)$max_page) {
    $range = 4;
} else if((int)$now === 2 || (int)$now === ((int)$max_page -1)) {
    $range = 3;
} else  {
    $range = 2;
}

まずGETで受け取ったページidを定義する(get_getはユーザー定義関数)

//viewからのidをgetしたとき
if(get_get('page_id')) {
  $now = $_GET['page_id'];
} else {
  //設定されてない場合は1ページ目にする
  $now = 1;
}

定義したら、その変数($now)を使ってoffsetを定義する

//ここでoffsetの定義
$offset = ($now - 1) * 5;

modelで実装したselect文もここで定義しておく。

$items = get_items_list($db, $limit = 5, $offset);
$items_count = get_items_count();

ceil関数を使って、小数点になる場合は繰り上げを行う。

$max_page = ceil($items_count / 5);

前述の通り、page_iniとpage_fin(つまり、表示させる商品ページの最初と最後の部分)に関しては、offsetの値により表示されるページが変わる。

//最初
$page_ini = ($offset + 1);

//最後(1ページに表示されるアイテム数が5つの場合とそうでない場合で条件分岐)
if(count($items) === 5) {
  $page_fin = ($offset + 5);
} else {
  $page_fin = $items_count;
}

あとはLaravelでもページネーションを実装してみたいな。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

問題集への解答

C016 文字列の置き換え

置き換え前 置き換え後
A 4
E 3
G 6
I 1
O 0
S 5
Z 2
    $input_line = fgets(STDIN);
    $array=array(
        "A"=>   4,
        "E"=>   3,
        "G"=>   6,
        "I"=>   1,
        "O"=>   0,
        "S"=>   5,
        "Z"=>   2  
        );

    $newword=$input_line;
    for ($i = 0; $i < strlen($input_line); $i++) {
        foreach ($array as $key=>$value) {
            if($newword[$i]==$key){
                $newword[$i]=$value;
            }
        }
    }
    echo $newword."\n";

C019

<?php
$count=(int)fgets(STDIN);
for ($i=0; $i <$count ; $i++) {
    print res((int)fgets(STDIN));
}
function res($num)
{
    $sum=0;

    for ($i=1; $i <$num ; $i++) {
        if ($num%$i==0) {
            $sum+=$i;
        }
    }
    switch ($sum) {
      case $num:
      print "perfect\n";
      break;
      case abs($num-1):
      print "nearly\n";
      break;

      default:
      print "neither\n";
      break;
    }
}

C024

<?php

function toArray($input){
  $s=explode(' ',trim($input));
  return $s;
}

$n=(int)fgets(STDIN);
$x1=0;
$x2=0;
for ($i=0; $i <$n ; $i++) {
  $query=toArray(fgets(STDIN));
  switch ($query[0]) {
    case 'SET':
      if($query[1]==1){
        $x1=$query[2];
      }else {
        $x2=$query[2];
      }
      break;
      case 'ADD':
        $x2=$x1+$query[1];
        break;
        case 'SUB':
          $x2=$x1-$query[1];
          break;
  }
}
print $x1.' '.$x2."\n";

C034

<?php
function toArray($input){
  $input=trim($input);
  return explode(' ',$input);
}
// $input='3 + 1 = x';
// $nums=toArray(fgets(STDIN));
$input=toArray(fgets(STDIN));


$x=array_search('x', $input );
$i=1;
if($input[1]=='-')  $i=-1;



switch ($x) {
  case 0:
    $x=$input[4]-$input[1]*$i;
    break;
    case 2:
      $x=$input[4]*$i-$input[0]*$i;
      break;
      case 4:
        $x=$input[0]+$input[2]*$i;
        break;


}
print $x;

C035

<?php
function toArray($input){
  $input=trim($input);
  return explode(' ',$input);
}
// $input='3 + 1 = x';
// $nums=toArray(fgets(STDIN));
$count=0;
$n=fgets(STDIN);
for ($i=0; $i <$n ; $i++) {
  $res=[];
  $s=explode(" ",trim(fgets(STDIN)));
  $key=$s[0];
  unset($s[0]);
  $res[$key]=$s;


  $num=0;
  if(array_sum($res[$key])>=350){
    // print_r($res);

    if($key=='l')$num=2;
      $sum=$res[$key][2+$num]+$res[$key][3+$num];  
      if($sum>=160){
        $count++;
        // print "\n\n\n\n".($i+1)."\n";
      }
  }
}
print $count."\n";

C043

<?php
$n=(int)fgets(STDIN);

$array=toArray(fgets(STDIN));

$array=array_count_values($array);




  foreach ($array as $key=>$value) {
    if(max($array)==$value){
      $res[]=$key;
    }
  }

  for ($i=0; $i <count($res) ; $i++) {
    print $res[$i];
    if(count($res)-$i==1){
      print "\n";
    }else{
      print " ";
    }
  }



function toArray($input){

  $s=explode(' ',trim($input));
  return $s;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VSCodeでAWSのLightsailインスタンス上のソースコードを編集する

はじめに

WordPress用のインスタンスを簡単に作成できるAWSのサービス「Lightsail」を触っていて、サーバ上のソースコードを編集したくなりました。
Vimを使うのもいいのですが、使い慣れているVSCodeで作業したくなりました。

VSCodeに拡張機能を入れる

VSCodeでLightsailサーバにアクセスするには、SSH接続が出来るようにする必要があります。
そこで、Microsoftがリリースしている「Remote - SSH」を使用します。
Image from Gyazo

SSH接続をする

拡張機能が入ったら、ウィンドウ左側のサイドメニューに新たなアイコンが表示されるので、クリックします。
Image from Gyazo

SSH TARGETSの右側に+ボタンがあるので、クリックします。
Image from Gyazo

SSH接続のコマンドを入力します。
"ssh -i "[秘密鍵]" [ユーザ]@[ホスト]"
Image from Gyazo

ユーザはbitnami(デフォルト)、ホストはパブリックIPです。
※パブリックIPを固定にしています。方法は「Lightsail 静的IP」などで調べてください。
秘密鍵は、Lightsailインスタンス管理画面、アカウントページからダウンロードできます。
Image from Gyazo

接続完了したら、SSH TARGETSの下に接続先サーバが表示されるので、右クリックをして、現在のウィンドウで接続します。
Image from Gyazo

完了

あとは、Open Folderをクリックしてフォルダを開けば、VSCodeで編集可能です。
Image from Gyazo

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MacOS(15.x以上)環境でPHPの「Class 'ZipArchive' not found」エラーを解消する方法

実行環境

  • MacBook Pro(MacOS Catalina v10.15.5)
  • Homebrewインストール済み
  • PHP7.3インストール済み

実行コマンド一覧

brew update
brew install php@7.3
brew link --force php@7.3

linkには必ず「--force」をつけること
linkの段階でエラーが出る場合、下記のコマンドも試してみること

brew link --overwrite php@7.3 --force

参考リンク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】Linuxコマンドでファイルを監視する

はじめに

PHPのデバッグ機能が使えないときなどに便利なデバッグ方法があったのでまとめる。

1. 特定のファイルにログ等を追記する

file_put_contentsコマンドを使うと、データをファイルに書き込むことができる。

以下、PHP マニュアルより抜粋。

file_put_contents ( string \$filename , mixed \$data [, int \$flags = 0 [, resource \$context ]] ) : int
この関数は、fopen()、fwrite()、 fclose() を続けてコールしてデータをファイルに書き込むのと同じです。

  • 第一引数にファイルを指定(存在しなければ新規作成される)
  • 第二引数に書き込む文字を指定
  • 第三引数にフラグを指定
フラグ 説明
FILE_USE_INCLUDE_PATH filename をインクルードディレクトリから探します。 詳細な情報は include_path を参照ください。
FILE_APPEND filename がすでに存在する場合に、 データをファイルに上書きするするのではなく追記します。
LOCK_EX 書き込み処理中に、ファイルに対する排他ロックを確保します。 つまり、fopen() の呼び出しから fwrite() の呼び出しまでの間に flock() の呼び出しが発生するということです。 これは、モード "x" で fopen() を呼び出すことと同等ではありません。
php
// 例
file_put_contents('hoge.txt', "ほげほげ" . "\n", FILE_APPEND);

2. ファイルを監視する

ターミナル
$ tail -f ファイルパス

-f: リアルタイムで中身を表示するオプション

3. 特定の文字で検索してリアルタイムで表示したい場合

ターミナル
$ tail -f ファイルパス | grep --line-buffered "hoge"

※単純にgrep "hoge"としてしまうと、バッファリングされてリアルタイムで表示されなくなってしまうので注意。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelでオリジナルなページネーションを作る

Laravelには協力なページネーションの機能があるので、カスタマイズしなくても大体のことは出来るのですが、

  • 見た目を完全にオリジナルにしたい
  • ページ数が省略される位置のロジックを特殊なものにしたい、一番端まで行くボタンを追加したい

などの仕様に対応するためには少し工夫が必要です。以下でどうやってやるか解説していきます。

見た目を完全にオリジナルにしたい

php artisan vendor:publish --tag=laravel-pagination

を実行して、Laravelのフレームワーク側が持っているレイアウトを/resources/views/vendor/pagination/以下に持ってきて、レイアウトファイルをカスタマイズします。

カスタマイズしたページネーターを/resources/views/vendor/pagination/custom/pagenator.blade.phpとした場合は、

{{ $paginator->links('pagination::service/offer/offer-list') }}

という形で呼び出すことができます。

ページ数が省略される位置のロジックを特殊なものにしたい、一番端まで行くボタンを追加したい

ページの制御はLengthAwarePaginator::elements()にかかれており、その実装はIlluminate\Pagination\UrlWindowにかかれているので、これら2つをカスタマイズすればよいです。

UrlWindow::getSliderTooCloseToBeginning()UrlWindow::getSliderTooCloseToEnding()UrlWindow::getUrlSlider()辺りが、ページネーションの最初の方に何件ページを表示して残りを…にするか、ページネーションの最後の方に何件ページを表示して残りを…にするか、ページネーションの中間のところで何件ページを出して残りを…にするか、というのが設定できるので、そこをカスタマイズすればよいです。

おまけ

ページネーションで移動するときはページのトップではなくて、一覧の最初の部分から始まって欲しいのでid指定をしたい、ということもあるでしょう。

そういうときはfragment()を使えばよいです。

{{ $paginator->fragment('pagination-form')->links('pagination::custom/paginator') }}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】データベースを使った画像の取得と表示

画像のアップロードとデータベースへの保存

画像のアップロード

formを作る

新しくviewファイルを作りformを作る。

<form action="{{route('任意のルート名')}}" method="post" enctype="multipart/form-data">
    @csrf
    <input type="file" name="sample_image" >
    <input type="submit" value="投稿">
</form>
  • formはenctype=“multipart/form-data”とする。multipart/form-dataはファイルの送信をするときに指定する必要がある。
  • enctypeは送信データのエンコードタイプを指定しており、methodがpostのときにしか使えない。
  • 何も指定しなければapplication/x-www-form-urlencodedとなり、これは全ての文字をURLにする。
    • enctypeは基本は書かずにファイルの送信をするときだけmultipart/form-dataとすればいい。
  • input type=“file”でファイルを選択できる。

Controllerで画像を保存する

public function store(Request $request){
  $image = $request->file('sample_image')->store('public/image');
}
  • contorollerで$request->file(‘name’)->store(‘任意のディレクトリ);とすることでstorage/app直下の任意のディレクトリにユニークなファイル名で保存される。
    • 今回はname="sample_image"、保存するディレクトリはstorage/public/imageになる。

データベースにファイル名を保存する

「Controllerで画像を保存する」で作成したstoreの中身に追加する。

public function store(Request $request){
  $image = $request->file('sample_image')->store('public/image');

  #この下に追加する

  $image = str_replace('public/image/', '', $image);

  $image = new Image;
  $image->file = $image;

  $image->save();
}
  • str_replace('指定の文字列' , '置換する文字列' , '対象の文字列')で対象の文字列から指定した文字列を置換する文字列に置き換える。
    • 今回は$imageに保存されているファイル名からpublic/image/という文字列を''(空文字)に置き換えている。

※今回は画像を表示するのにヘルパ関数のassetを使うことを前提にしているのでファイル名のみをデータベースに保存した。

保存した画像の表示

ファイル名をデータベースから取得する

今回はimages_table(モデルはImage)の中のfileというカラムにファイル名が入っているとする。

public function index(){
  $image = Image::all();

  return view('image.index', compact('image'));
}

viewファイルで画像を表示する

※storage/app/public配下(画像を保存した場所)はwebからのアクセスを許可しないので、データベースからファイル名を取得しても画像は表示されない。

artisanコマンドでstorage:linkとすることでstorageのファイルがpublic直下に同期される(publicの中にstorageが追加されている)。

  • 画像が保存されている場所:storage/app/public/image
  • 画像を取得する場所:public/storage/image
php artisan storage:link

上記のartisanコマンドを通せばpublic/storage配下に画像があるのでにassetを使ってアクセスできる。

<img src="{{asset('storage/image/'.$image->file)}}">

バージョン

php:7.3.11
Laravel:7.21.0

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPのビルトインウェブサーバで起動するスクリプトをsystemdのサービスとして登録する

PHPにはビルトインウェブサーバが付属していますので、WEB用のPHPスクリプトをちょっとテストするのに便利です。ただ、ある程度継続して使い続けるためには、サービスとして登録する必要があります。そんな時にどうするかという話です。

想定環境

  1. PHPのWebアプリのテスト、ローカルポータルサイトの構築などの目的
  2. LAN内のLinuxサーバ、またはLinuxPC上に設置(グローバルに公開しない)

ローカルにかつ一時的に利用することを想定しています。恒常的なサービスにする場合は記事末を見てください。

手順

  1. .serviceファイルを用意する
  2. /etc/systemd/systemにシンボリックリンクを作成する
  3. サービスを有効化する
  4. サービスを起動する

.serviceファイルは、ウェブサーバで起動するPHPスクリプトとペアにして、同じディレクトリ内に置いておくと管理のために便利です。

.serviceファイル

.serviceファイルはリスト2のように記述します。「{ }」内には具体的な値が入ります。なお、筆者はDebianを使っていますので、サービスの実行ユーザをwww-dataにしています(お使いのOSの習慣に従って、適宜変更してください)。

リスト1
[Unit]
Description = {Description}

[Service]
ExecStart = /usr/bin/php -S {HOSTNAME}:{PORT} {SCRIPTPATH}
User = www-data
Group = www-data

[Install]
WantedBy = default.target

{HOSTNAME}

ウェブサーバをPC上で起動する場合は

localhost あるいは 127.0.0.1

にしてください。これにより、LAN内であっても他のホストからのアクセスができません。LAN内の別ホスト上で起動する場合は

プライベートアドレス あるいは そのアドレスを指すローカルホスト名

にします。

{PORT}

Webサービスであることを明示的に示すためには、ポートは

8080 〜 8089

を使うのが良いでしょう。他のサービスと重複しなければ何でも良いのですが、特権ポート(1023以下)は避けた方が無難です。

{SCRIPTPATH}

ビルトインウェブサーバにより起動されるPHPスクリプト名です。必ずフルパスで指定してください。

{DESCRIPTION}

「systemctl status」コマンド等の結果として表示されるサービスの名前です。.serviceファイルのベース名(拡張子を取り除いた部分)を使うのが無難でしょう。

サービスの登録と起動

筆者はリスト2のようなスクリプトを使っています。「register-service」と名付けてパスの通っている場所に保存しています。このスクリプトは、.serviceファイルが置かれたディレクトリをカレントにしないと実行できないようになっています。これは、あくまでも一時的なサービスであることを強調するためです。

リスト2(register-service)
01: #!/usr/bin/env bash
02: NAME=$1
03: # 第1引数でサービスの名前を定義する
04: if [ "${NAME}" == "" ]; then
05:     echo "Service name required."
06:     exit 1
07: fi
08: NAME=${NAME%.service}
09: SNAME=${NAME}.service
10: # カレントディレクトリに定義ファイルが存在するか
11: if [ ! -f "${SNAME}" ]; then
12:     echo "${SNAME} not found."
13:     exit 1
14: fi
15: SDIR=/etc/systemd/system
16: # 同じ名前のserviceが存在するか
17: if [ -e ${SDIR}/${SNAME} ]; then
18:     echo "Service ${NAME} already exists."
19:     exit 1
20: fi
21: # リンクを作成する
22: sudo ln -s ${PWD}/${SNAME} ${SDIR}/${SNAME}
23: # serviceを有効化する
24: sudo systemctl enable ${NAME}
25: # serviceを起動する
26: sudo systemctl start ${NAME}

例えば、「php8081.service」を登録する場合には、そのファイルの存在するディレクトリをカレントにして

$ register-service php8081

などと実行します。一般のサービスへできるだけ影響を与えないように、.serviceファイルの存在するディレクトリで実行します。

サービスの削除

一時的なサービスですので、いつかは削除します。その際、サービスをdisableする前に、stopしなければならないことに注意してください。サービスが起動中にdisableしてしまうと、ゾンビのようなサービスが残ってしまいます(リスト3)。

リスト3
$ sudo systemctl status php8081
● php8081.service
     Loaded: not-found (Reason: Unit php8081.service not found.)
     Active: active (running) since Mon 2020-07-27 00:35:21 JST; 2min 49s ago
...
 7月 27 00:36:36 chiimama systemd[1]: php8081.service: Current command vanished from the unit file,
    execution of the command list won't be resumed.

筆者は、サービスを間違いなく削除するために、リスト4のスクリプトを利用しています。

リスト4(unregister-service)
14: (ここまでリスト2と同じ)
15: # serviceを停止する
16: sudo systemctl stop ${NAME}
17: # serviceを無効化する
18: sudo systemctl disable ${NAME}

恒久的なサービスにする場合

PHPのビルトインウェブサーバを使用するのは、大抵の場合、一時的なテストのためでしょうが、恒久的なサービスとして登録することもないわけではありません。その場合には、次の手順に従ってください。

  1. .serviceファイルを /lib/systemd/system に移動する
  2. 所有者を root.root に変更する
  3. /etc/systemd/system ディレクトリに.serviceファイルへのシンボリックリンクを作成する
  4. systemctl enable
  5. systemctl start
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPのビルトインウェブサーバをsystemdのサービスとして登録する

PHPにはビルトインウェブサーバが付属していますので、WEB用のPHPスクリプトをちょっとテストするのに便利です。ただ、ある程度継続して使い続けるためには、サービスとして登録する必要があります。そんな時にどうするかという話です。

想定環境

  1. PHPのWebアプリのテスト、ローカルポータルサイトの構築などの目的
  2. LAN内のLinuxサーバ、またはLinuxPC上に設置(グローバルに公開しない)

ローカルにかつ一時的に利用することを想定しています。恒常的なサービスにする場合は記事末を見てください。

手順

  1. .serviceファイルを用意する
  2. /etc/systemd/systemにシンボリックリンクを作成する
  3. サービスを有効化する
  4. サービスを起動する

.serviceファイルは、ウェブサーバで起動するPHPスクリプトとペアにして、同じディレクトリ内に置いておくと管理のために便利です。

.serviceファイル

.serviceファイルはリスト2のように記述します。「{ }」内には具体的な値が入ります。なお、筆者はDebianを使っていますので、サービスの実行ユーザをwww-dataにしています(お使いのOSの習慣に従って、適宜変更してください)。

リスト1
[Unit]
Description = {Description}

[Service]
ExecStart = /usr/bin/php -S {HOSTNAME}:{PORT} {SCRIPTPATH}
User = www-data
Group = www-data

[Install]
WantedBy = default.target

{HOSTNAME}

ウェブサーバをPC上で起動する場合は

localhost あるいは 127.0.0.1

にしてください。これにより、LAN内であっても他のホストからのアクセスができません。LAN内の別ホスト上で起動する場合は

プライベートアドレス あるいは そのアドレスを指すローカルホスト名

にします。

{PORT}

Webサービスであることを明示的に示すためには、ポートは

8080 〜 8089

を使うのが良いでしょう。他のサービスと重複しなければ何でも良いのですが、特権ポート(1023以下)は避けた方が無難です。

{SCRIPTPATH}

ビルトインウェブサーバにより起動されるPHPスクリプト名です。必ずフルパスで指定してください。

{DESCRIPTION}

「systemctl status」コマンド等の結果として表示されるサービスの名前です。.serviceファイルのベース名(拡張子を取り除いた部分)を使うのが無難でしょう。

サービスの登録と起動

筆者はリスト2のようなスクリプトを使っています。「register-service」と名付けてパスの通っている場所に保存しています。このスクリプトは、.serviceファイルが置かれたディレクトリをカレントにしないと実行できないようになっています。これは、あくまでも一時的なサービスであることを強調するためです。

リスト2(register-service)
01: #!/usr/bin/env bash
02: NAME=$1
03: # 第1引数でサービスの名前を定義する
04: if [ "${NAME}" == "" ]; then
05:     echo "Service name required."
06:     exit 1
07: fi
08: NAME=${NAME%.service}
09: SNAME=${NAME}.service
10: # カレントディレクトリに定義ファイルが存在するか
11: if [ ! -f "${SNAME}" ]; then
12:     echo "${SNAME} not found."
13:     exit 1
14: fi
15: SDIR=/etc/systemd/system
16: # 同じ名前のserviceが存在するか
17: if [ -e ${SDIR}/${SNAME} ]; then
18:     echo "Service ${NAME} already exists."
19:     exit 1
20: fi
21: # リンクを作成する
22: sudo ln -s ${PWD}/${SNAME} ${SDIR}/${SNAME}
23: # serviceを有効化する
24: sudo systemctl enable ${NAME}
25: # serviceを起動する
26: sudo systemctl start ${NAME}

例えば、「php8081.service」を登録する場合には、そのファイルの存在するディレクトリをカレントにして

$ register-service php8081

などと実行します。一般のサービスへできるだけ影響を与えないように、.serviceファイルの存在するディレクトリで実行します。

サービスの削除

一時的なサービスですので、いつかは削除します。その際、サービスをdisableする前に、stopしなければならないことに注意してください。サービスが起動中にdisableしてしまうと、ゾンビのようなサービスが残ってしまいます(リスト3)。

リスト3
$ sudo systemctl status php8081
● php8081.service
     Loaded: not-found (Reason: Unit php8081.service not found.)
     Active: active (running) since Mon 2020-07-27 00:35:21 JST; 2min 49s ago
...
 7月 27 00:36:36 chiimama systemd[1]: php8081.service: Current command vanished from the unit file,
    execution of the command list won't be resumed.

筆者は、サービスを間違いなく削除するために、リスト4のスクリプトを利用しています。

リスト4(unregister-service)
14: (ここまでリスト2と同じ)
15: # serviceを停止する
16: sudo systemctl stop ${NAME}
17: # serviceを無効化する
18: sudo systemctl disable ${NAME}

恒久的なサービスにする場合

PHPのビルトインウェブサーバを使用するのは、大抵の場合、一時的なテストのためでしょうが、恒久的なサービスとして登録することもないわけではありません。その場合には、次の手順に従ってください。

  1. .serviceファイルを /lib/systemd/system に移動する
  2. 所有者を root.root に変更する
  3. /etc/systemd/system ディレクトリに.serviceファイルへのシンボリックリンクを作成する
  4. systemctl enable
  5. systemctl start
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laminasことはじめ

Laminasをとりあえずローカルで動かしてみようという記事です。
おや?Laminasをご存じない?
PHPといえばZend、そう、ZendFrameworkがLinux Fundationに移行されて後続的にOSSとして開発されているのがLaminasです。

Laminasにもいくつかパッケージがあり、

  • Component and MVC
  • Mezzio(ZendExpressiveの後続)
  • API Tools

今回はMVCのSkeletonをローカルで動かすまでをやってみます。
ありがたいことにこんな素敵なリポジトリがあり、READMEを追って作業するだけであっという間に立ち上がります。
https://github.com/laminas/laminas-mvc-skeleton

導入

ちなみにMacOS環境でローカルにPHP7.4,Composerを導入済みです。

適当なディレクトリを作成してcomposerを実行するだけですね。

$ mkdir laminas
$ composer create-project -sdev laminas/laminas-mvc-skeleton laminas

実行するとコンソールで対話式に色々聞かれます。
適当に選んでいきます。

Do you want a minimal install (no optional packages)? Y/n
N

Would you like to install the developer toolbar? y/N
Y

Would you like to install caching support? y/N
Y

Would you like to install database support (installs laminas-db)? y/N
Y

Would you like to install forms support? y/N
N

Would you like to install JSON de/serialization support? y/N
Y

Would you like to install logging support? y/N
Y

Would you like to install MVC-based console support? (We recommend migrating to zf-console, symfony/console, or Aura.CLI) y/N
Y

Would you like to install i18n support? y/N
N

Would you like to install the official MVC plugins, including PRG support, identity, and flash messages? y/N
Y

Would you like to use the PSR-7 middleware dispatcher? y/N
Y

Would you like to install sessions support? y/N
Y

Would you like to install MVC testing tools for testing support? y/N
Y

Would you like to install the laminas-di for laminas-servicemanager? y/N
Y

一通り必要なパッケージの有無を求められました。
続いて設定ファイルに関して聞かれます。

  Please select which config file you wish to inject 'Laminas\Cache' into:
  [0] Do not inject
  [1] config/modules.config.php
  [2] config/development.config.php.dist
  Make your selection (default is 1):

Remember this option for other packages of the same type? (Y/n)
N

ここでN(No)にするとパッケージ毎にどうするか聞かれるのでだいたいデフォルトでいいんじゃないですかね・・・

Y(Yes)を選んでも以下の項目は再度聞かれます。Developmentモードのときだけ必要なやつの設定ですね。

Please select which config file you wish to inject 'Laminas\DeveloperTools' into:
  [0] Do not inject
  [1] config/modules.config.php
  [2] config/development.config.php.dist
  Make your selection (default is 1):
N

これで導入は完了。
ご丁寧にVagrantとDockerのローカル環境の設定があるので今回はDockerで起動してみます。

$ docker-compose up -d --build

http://localhost:8080にアクセスすると以下のような画面が表示されます。
スクリーンショット 2020-07-27 0.48.03.png

自分たちが開発していくアプリケーションはmodules/Application/srcになります。以前ZendExpressiveのv2系をやったことがあるんですがまた違ったディレクトリ構造ですね・・・
PSR-7,DI,UnitTestがデフォルトでついてる(任意選択)のは今どきのPHPフレームワークって感じですね。
とはいえPSR-7といいつつlaminas-psr7bridgeでLaminas独自の型に変換してるので純粋なPSR-7じゃないっぽい?

公式ドキュメントも豊富なので良さそうですね。とはいえフルスタックなフレームワークなだけに機能豊富で一通りの使い方を覚えるのには骨が折れそう・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む