20190211のPHPに関する記事は19件です。

Laravelを始めるときのメモ

内容

  • Ubuntu上で、Laravelのプロジェクトを生成して、PhpStormで開くまでのメモです

前提

  • Ubuntu 18.04
    • PHP 7.2
    • Laravel Installer 1.3.3
    • PhpStorm 2018.3

PHP+Laravelの環境構築

参考にしたページ
https://readouble.com/laravel/5.5/ja/installation.html

sudo apt install php-zip # ←未インストールの場合
sudo apt install composer
composer global require "laravel/installer"

laravelコマンドにパスを通す(~/.config/composer/vendor/bin)

プロジェクトの作成

laravel new {YOUR_PROJECT_NAME}
cd {YOUR_PROJECT_NAME}
composer require barryvdh/laravel-ide-helper

エラーが出て、laravel-ide-helperが入れられなかったので、以下で解消。
sudo apt install php-mbstring

初期環境の動作確認

  • PhpStormでは、"Run Anything"からphp artisan serveを実行
  • PhpStromのRunウィンドウに表示されるURLをクリックするとブラウザで確認できる。

最初に変更するところ

  • routes/web.php
    • パスが "/"直下に設置される

もしくは

  • routes/api.php
    • パスが "/api"下に設置される
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

紙ベースで実施されていた運用をシステム化してみた

はじめに

 2年前から私たちのチームは「フットサルのリーグ戦」にが参加させて頂いています。
 このリーグ戦は15年続いているそうです!
 
 リーグ戦の概要
 ・毎月1回開催(年間12回)
 ・各回、4チームの総当り戦を2セット行う
 ・年間のチームの勝点で順位を決める
 ・年間の得点王を決める
 
 
◆2019年1月に行われた試合で使用した対戦表
image.png

この紙に各試合の審判が得点、得点者を入力。
その後、主催者が毎回チームの勝点と得点者の得点を集計されています。
 (よく見ると勝点でおかしい箇所があるような気がします)

システム化しようとした背景

・紙ベースの運用されていて、主催者がデータ集計をするのが大変だと思ったから
・チーム年間順位・得点王、試合結果をいつでも参照できるようにしたいと思ったから
・集計を正しくしたいと思ったから

上記内容を対応するために
「得点入力画面で得点をDBに格納して、試合終了後、結果を集計する」ことで
主催者の負荷を下げ、参加者はいつでも結果をみることができると思い、簡易システムを作成しました。

image.png

もう一つ理由があり
12月末から1月末まで骨折していたので、フットサルできなくて暇だったのがあります。。

実現方法

実現するにあたり、以下の3つを検討
 1.どんな情報が見たいか、得点入力画面の検討
 2.1.でやりたい事のデータの持たせ方の検討(DB設計)
 3.環境の検討(サーバ、アプリの検討)

1.どんな情報が見たいか、得点入力画面の検討

まずは、Excelでイメージを書いてみる

一番欲しい情報は現在のチーム順位表と得点王
image.png

各節の試合結果と得点者
image.png

得点入力画面
得点入力は、入力させずに「+」、「-」ボタンで得点がUP、DOWNするようにする。
※入力チェック処理しなくていいし、また、ボタンだけの操作なので、システム化して得点入力が面倒くさくなったと感じさせないためです。
image.png

2.1.でやりたい事のデータの持たせ方の検討(DB設計)

大きく分けて、「マスタ」と「データ入力用」と「データ参照用」とのテーブルを作成。
※年間順位、年間得点王は、各回の試合結果入力後に集計させ、参照させる。
image.png
image.png
image.png

各試合終了後、得点集計処理を実施して、データ参照用テーブルを更新。
image.png

※実際のテーブル名、フィールド名は英語にしてます

3.環境の検討(サーバ、アプリの検討)

無料でサーバを使いたいので、無料枠 の GCE(Google Compute Engine) を使用
  https://cloud.google.com/free/?hl=ja
     
また、リーグ戦の参加者は、PC、スマホ(大部分はスマホ)で結果をみると思うので、
PC、スマホと勝手に見せ方を調整してくれるWordPressを選択。
データ格納DBは無料のmariaDB、phpはWordPressを動かす上で必要となります。

3-1 GCE(Google Compute Engine)の構築

以下の記事を参考にさせて頂きました。ありがとうございました。

 GCP上でWordPressを無料で構築したい
 GCP(Google Cloud Platform)での無料GCE(Google Compute Engine)インスタンス作成
 GCE の無料枠のサーバを立るときに、初見でハマりそうなところ
 無料のドメインを取得する
 Google Cloud DNSでIPアドレスとドメイン名を紐付ける

GCE(Google Compute Engine)の無料枠だとメモリが少ないので WordPressの画面を開くと、mariaDBがメモリが確保できないためエラーとなってしまい、WordPressの画面がみれない状態になってしまいました。

追加の設定としてSWAPを設定しました。
設定後、mariaDBのエラーは発生してません。

$ sudo dd if=/dev/zero of=/swapfile bs=1M count=1024
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile

インスタンスを再起動した時にswapが自動マウントされるようにfstabに設定をします。
※ /etc/fstab 以下の設定を追加

/swapfile none swap sw 0 0

3-2 WordPressでの開発(はまったところのメモ)

ちょっと躓いたところをメモとして残します。
結局自分でHTMLを書いたので、なにもレイアウトの設定がない「固定ページ」で全て書いています

その1. WordPressで自作のphpコードを実行する場合、WordPress固有の設定が必要

 これGCEにWordPress環境構築してから気がつきました。。

 WordPressで自分で書いたPHPを実行する場合、
 ショートコードというものを使用する必要があります。
  ショートコード API

 ◆ショートコード記載場所
  WordPressインストールディレクトリの
  「/wp-content/themes/テーマ名」直下のfunctions.phpがショートコードを記載するファイルとなります。

 ◆ショートコードを書いてみる
  functions.php を編集
  サンプルでは、phpのファンクション「sampletest」を定義して
  そのファンクション「sampletest」をショートコード「f_sampletest」と紐付けています
  ※sudo vi functions.php で更新です

functions.php
/* ショートコードサンプル */
function sampletest() {
    return "Hello";
}
add_shortcode('f_sampletest', 'sampletest');

  注意点はこのfunctions.phpはWordPressのページ表示/管理画面の表示でコールされます。
  functions.phpで構文エラー(;がない等)の場合、WordPressがみれなくなりますので
  編集する前にバックアップを取得しておくことをお勧めします。

◆WordPressからショートコードを呼び出す
image.png

画面が表示される際にショートコード(f_sampletest)が実行され、ショートコードで設定した文字が表示される
image.png

◆ショートコードに引数を渡す場合

functions.php
/* ショートコード引数あり */
function sampletest_argv($attr) {
    $msg = $attr[0];
    return $msg;
}
add_shortcode('f_sampletest_argv', 'sampletest_argv');

[ショートコード 引数] を設定⇒[更新]クリック⇒[固定ページを表示]クリック
image.png
画面が表示される際にショートコード(f_sampletest_argv)が実行され、ショートコード実行時に設定した引数の文字が表示される
image.png

◆実際のアプリで使用したショートコード抜粋

functions.php
function view_top($attr) {

    global $wpdb;

    //引数(年度)を取得
    $yyyy = $attr[0];

    $listresult  = "</tbody></table>";

    $listresult .= "<br><strong>◆得点ランキング(上位3まで)</strong><br>";

    //得点王取得SQL
    $strsql  ="select ";
    $strsql .="    r.rank,t.teamname,p.playername ,r.score";
    $strsql .="    from ";
    $strsql .="       topscore r, ";
    $strsql .="       team t, ";
    $strsql .="       player p ";
    $strsql .="    where ";
    $strsql .="        r.yyyy = %d  ";
    $strsql .="    and r.teamno = t.teamno ";
    $strsql .="    and r.playerid = p.playerid ";
    $strsql .="    and rank < 4 ";
    $strsql .="    order by r.rank,p.playername ";

    $sql = $wpdb->prepare($strsql, $yyyy);
    $rows = $wpdb->get_results($sql);

    //table ヘッダ情報
    $listresult .= "<table class=\"wp-table-yoko\"><thead><tr><th>順位</th><th>氏名</th><th>チーム名</th><th>得点</th></tr></thead><tbody>";

    //テーブルレコード設定
    foreach($rows as $row){
        $listresult .= "<tr><td>". $row->rank . "</td><td>" . $row->playername . "</td><td style =\"text-align: left;\">" . $row->teamname . "</td><td>" . $row->score . "</td></tr>";
    }

    $listresult .= "</tbody></table>";

    //画面表示
    return $listresult;

}
add_shortcode('f_viewtop', 'view_top');

ショートコード(f_viewtop)を設定⇒[固定ページを表示]クリック
image.png

ショートコード(f_viewtop)に引数を設定(2019)して実行した結果。
image.png

その2. 自作のJavaScriptを使用する場合、WordPress固有の設定が必要

 これもWordPressの設定が必要です。

 得点入力画面で「+」、「-」ボタンのみで得点入力するようにしました。
 そのため、「+」、「-」ボタンが押されたタイミングで、JavaScriptで得点表示を
 変更する必要がありました。

 (赤枠の「+」、「-」ボタンをクリックすると対応する得点が加算、減算されます)
image.png

手順1 JavaScriptを作成して格納
「/wp-content/themes/テーマ名/js」に 作成したJavaScript(score.js)を格納します

score.js
function incValue(idname){
  // value値を取得する
  var obj = document.getElementById(idname);

  //valueに値をセットする
  obj.value = parseInt(obj.value)  + parseInt(1);

}
function decValue(idname){
  // value値を取得する
  var obj = document.getElementById(idname);

  score = parseInt(obj.value)

  if (score > 0){
  //valueに値をセットする
      obj.value = parseInt(obj.value)  - parseInt(1);
  }

}

手順2 functions.php にjavascriptに関する記載を書く

functions.php
function score_scripts() {
  wp_enqueue_script( 'score-script', get_template_directory_uri().'/js/score.js' , array(), date('U'));
}
add_action( 'wp_enqueue_scripts', 'score_scripts' );

この設定で自前のJavaScriptが動くようになります


その3.データ登録方法(POST送信)

 データ登録方法は、「データ入力画面」からPOST送信して、
 送信された側の「データ登録終了画面」に設定したショートコードでデータ登録させる方法にしました。
 ※実際のアプリで使用したデータ登録をサンプルとして残します。

 手順1 POST送信する固定ページの設定
  POST送信する固定ページにformタグを設定して、POST送信するように記載。
  formタグの中でショートコードをコールするようにします。
  (ショートコードの中で、submitボタンを作成してます)
image.png
image.png

 手順2 POST受信する固定ページの設定
  ショートコード(f_postdata)のみ記載
image.png

f_postdataのショートコード(抜粋)

functions.php
function postdata() {

    global $wpdb;

    //POSTされたデータを受け取る
    $yyyy = $_POST['yyyy'];
    $mm = $_POST['mm'];
    $seq = $_POST['seq'];
    $team1 = $_POST['team1'];
    $team2 = $_POST['team2'];
    $score1 = $_POST['score1'];
    $score2 = $_POST['score2'];

<処理省略>    
    //得点を登録
    $strsql  = "update matchresults ";
    $strsql .= " set score1 = %d ,";
    $strsql .= "     score2 = %d  ";
    $strsql .=" where ";
    $strsql .="        yyyy= %d ";
    $strsql .="    and mm= %d ";
    $strsql .="    and seq= %d ";

    $sql = $wpdb->prepare($strsql,$score1,$score2, $yyyy,$mm,$seq);
    $rows = $wpdb->get_results($sql);

<処理省略 この後登録したデータを表示する処理>

}
add_shortcode('f_postdata', 'postdata');

POST送信⇒POST受信した固定ページでショートコード(f_postdata)を実行した結果
image.png

その4.ランク付け集計方法

mariaDBでOracleのRANK・DENSE_RANKを取得するSQL文使用できない
 https://docs.oracle.com/cd/E16338_01/server.112/b56299/functions052.htm

簡単に言うと、RANKはある列の値に順位をつけてくれるものになります。
DENSE_RANKは、順位をつけるのですが、同一値の場合に順位を飛ばさずに順位をつけます。
image.png
※本リーグ戦の運用では、得点王はDENSE_RANKで順位をつけています。

mariaDBでDENSE_RANKするSQLを記載
ダミーテーブルとサンプルデータとRank取得するSQL

--得点データ格納するテーブル
create table test_scoring(
    yyyy int  NOT NULL,
    mm int  NOT NULL,
    seq int NOT NULL,
    playerid  int NOT NULL,
    score int,
  PRIMARY KEY(yyyy,mm,seq,playerid)
);

--ダミーデータを入れる
insert into test_scoring values(2019,1,1,17,1);
insert into test_scoring values(2019,1,1,18,1);
insert into test_scoring values(2019,1,1,19,1);
insert into test_scoring values(2019,1,2,9,1);
insert into test_scoring values(2019,1,3,13,1);
insert into test_scoring values(2019,1,3,11,1);
insert into test_scoring values(2019,1,4,3,1);
insert into test_scoring values(2019,1,4,20,2);
insert into test_scoring values(2019,1,4,18,1);
insert into test_scoring values(2019,1,5,17,1);
insert into test_scoring values(2019,1,5,12,1);
insert into test_scoring values(2019,1,6,14,1);
insert into test_scoring values(2019,1,6,15,1);
insert into test_scoring values(2019,1,6,5,2);
insert into test_scoring values(2019,1,7,12,1);
insert into test_scoring values(2019,1,7,4,1);
insert into test_scoring values(2019,1,7,8,1);
insert into test_scoring values(2019,1,8,16,1);
insert into test_scoring values(2019,1,8,20,1);
insert into test_scoring values(2019,1,8,21,1);
insert into test_scoring values(2019,1,10,18,1);
insert into test_scoring values(2019,1,11,15,1);
insert into test_scoring values(2019,1,12,3,1);
insert into test_scoring values(2019,1,12,8,1);
insert into test_scoring values(2019,1,12,18,1);
insert into test_scoring values(2019,1,12,22,1);

--DENSE_RANKでランク付けするSQL
select
    CASE WHEN @before_sumscore = d.sumscore THEN @rank
    ELSE @rank:=@rank+1
    END AS rank,
    playerid,
    @before_sumscore := d.sumscore as sumscore 
from 
   (
    select 
        playerid  ,
        sum(score) as sumscore  
    from 
        test_scoring  
    where 
        yyyy=2019 
    group by 
        playerid
   ) d,
   (select @rank:=0, @before_sumscore:=0) s
order by 
   sumscore desc ;

取得結果
同一得点の場合、Rankは同じ順位に取得されています。
また、順位が飛ばされていません。
image.png

作成した画面と遷移図

成績の参照(参加者がみる画面)
image.png

管理者(得点入力、メンバー登録、集計処理)
image.png

成績の参照は見たい情報が見れるようにしました。
得点入力画面は簡単なボタンクリックのみでできる画面にしました。

2月リーグ戦で主催者への説明

タブレットを持っていき、主催者の前で得点入力、集計処理(得点・得点王)を行い説明をしました。
image.png

主催者とお話して以下の予定で進めることになりました。

今後の予定
3月は紙ベース運用とシステムの平行運用
4月からはシステムでの運用

残りのタスク

・各試合スケジュールの登録画面の作成。
・使用者からの評価を聞き改善

こちらは時間を見つけて対応する予定

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

bladeの変数確認

bladeで変数の存在確認

controllerからviewに変数を遅れているかの判定(blade)
php:exam.php
isset($data);

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

DatePeriodクラスを使ってカレンダーに必要な値を取得

DatePeriodクラスを使って日付のレンジを指定

DatePeriodクラスを使うことによって、日付のデータをまとめて取得することができる。 

calendar.php
$period = new DatePeriod(
   new DateTime('first day of this month'),
   new DateInterval('P1D'),
   new DateTime('first day of next month')
);
//今月の月初から月末までの日付データを取得することができる

第1引数ではDateTimeクラスを使っていつの日付からデータを取得するか指定、第2引数ではDateIntervalクラスを使って何日間隔で日付データを取るかを指定、そして第3引数では同じくDateTimeクラスを使って、いつまでの日付を取得するかを指定しています。 

第3引数がnext monthになっている理由は、’last day of this month’にしてしまうと、月末日を取得できない為です。 なので月内の日付を全て取得したい場合は、上記のように書きます。 

DateTimeオブジェクト操作する 

繰り替えし処理を使い日付データを取り出していきます。

calendar.php
foreach($period as $day){
   echo $day->format('d');
}
//0102030405060708091011121314151617....

formatはDateTimeクラスに用意されているメソッドになっており、決められた書式でデータを返してくれる。 

公式サイトにまとまっているので、以下を参考に引数を設定してあげればいい。

formatに関する公式サイト

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

PHPで入力フォームのデータをSELECT文のINSERTを使って、MySQLに書き込む

以下の2つソースコードを作ります。
①入力フォーム
②入力フォームで入力されたデータをPOSTで受け取って、DBに接続して書き込む

↓入力フォーム画面
キャプチャ.PNG

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta name="description" content="このページの説明">
  <title>このページのタイトル</title>
  <link rel="stylesheet" href="/main.css">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
</head>
<body>
<div id="post_page">
  <form method="post" action="process_post.php">
    <div>name <input type="text" name="name" size="30"></div>
    <div>category <input type="text" name="category" size="30"></div>
    <div>description <textarea name="description" cols="30" rows="10"></textarea></div>
    <div><input type="submit" name="submit" value="投稿" class="button"></div>
  </form>
</div>
</body>
</html>

↓登録・登録結果表示画面

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta name="description" content="このページの説明文">
  <title>このページのタイトル</title>
  <link rel="stylesheet" href="/main.css">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
</head>
<body>

<?php
  try {
    //DB名、ユーザー名、パスワード
    $dsn = 'mysql:dbname=データベース名;host=サーバー名';
    $user = 'ユーザー名';
    $password = 'パスワード';

    $PDO = new PDO($dsn, $user, $password); //MySQLのデータベースに接続
    $PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //PDOのエラーレポートを表示

    //input_post.phpの値を取得
    $name = $_POST['name'];
    $category = $_POST['category'];
    $description = $_POST['description'];


    $sql = "INSERT INTO contents (name, category, description) VALUES (:name, :category, :description)"; // INSERT文を変数に格納。:nameや:categoryはプレースホルダという、値を入れるための単なる空箱
    $stmt = $dbh->prepare($sql); //挿入する値は空のまま、SQL実行の準備をする
    $params = array(':name' => $name, ':category' => $category, ':description' => $description); // 挿入する値を配列に格納する
    $stmt->execute($params); //挿入する値が入った変数をexecuteにセットしてSQLを実行

    echo "<p>name: ".$name."</p>";
    echo "<p>category: ".$category."</p>";
    echo "<p>description: ".$description."</p>";
    echo '<p>で登録しました。</p>'; // 登録完了のメッセージ
  } catch (PDOException $e) {
  exit('データベースに接続できませんでした。' . $e->getMessage());
  }

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

PHPでエラーメッセージを表示する

PHPは、初期設定の状態では、エラーメッセージが表示されないことを初めて知りました。

エラーメッセージを表示するには、レンタルサーバーのWebサイトの設定画面で、php.iniの設定方法を変更する必要があります。

ロリポップの例:
https://lolipop.jp/manual/user/php-setting/

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

formタグのactionとheader関数によるリダイレクトの優先度

actionとheader関数

結論からいうとaction属性が優先される

action属性

formの中の属性。
指定したURLに送信できる。
<form action="http://www.example.com/">

header関数

header関数はHTTPヘッダを指定できる、リダイレクトに使用できる。
header('Location: http://www.example.com/);

お問い合わせフォーム

確認画面から初期画面にもどると完了画面へ移動する分岐の際リダイレクトが必要になる

失敗例

action属性が優先されるためphpの記述でsendとbackで場合分けしているがcomplete.phpに飛ぶ

comfirm.php
<?php
session_start();
    if(isset($_POST["send"])) {
        header("Location:complete.php");
    }
    elseif (isset($_POST["back"])){
        header("Location:input.php");
    }
    else{

    }
?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>お問い合わせ</title>
</head>
<body>
<form  action="complete.php" method="post">
    名前<br />
    <?php echo $_SESSION["name"];?><br />
    電話番号<br />
    <?php echo $_SESSION["telNumber"];?><br />
    メールアドレス<br />
    <?php echo $_SESSION["mail"];?><br />
    <input type="submit" name="send" value="確認">
    <input type="submit" name="back" value="戻る">
</form>
</body>
</html>

成功例

action属性をcomfirm.phpに変更
type属性がsubmitのinputタグが押された際phpの記述が通る。

comfirm.php
<?php
session_start();
    if(isset($_POST["send"])) {
        header("Location:complete.php");
    }
    elseif (isset($_POST["back"])){
        header("Location:input.php");
    }
    else{

    }
?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>お問い合わせ</title>
</head>
<body>
<form  action="comfirm.php" method="post">
    名前<br />
    <?php echo $_SESSION["name"];?><br />
    電話番号<br />
    <?php echo $_SESSION["telNumber"];?><br />
    メールアドレス<br />
    <?php echo $_SESSION["mail"];?><br />
    <input type="submit" name="send" value="確認">
    <input type="submit" name="back" value="戻る">
</form>
</body>
</html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelとStripeを使って決済機能を持つショッピングサイトを作った

約1年前にWeb開発の業務を担当させて頂きそこからマイペースにLaravelの勉強をしてきました。
勉強してきたことを1つの成果物としてまとめたいなと思い決済機能を持つ簡単なショッピングサイトを作りました。

人によっては1ヶ月以内で出来る様な出来で恐縮ですがベーシック認証をかけた状態でherokuにデプロイをしました。
SSLの設定や画像ファイルの格納先の権限やらでまだ完璧にデプロイ出きた訳では無いですが、社内でのみ公開が出来る様にしたいと考えております。

ここでは主に画面のキャプチャを用いて画面構成やどの様に作り込みをしたかをまとめていきます。
githubにソースコードを上げているのでソースコードの詳細はそちらをご覧頂ければと存じます。
自習やポートフォリオサイトを作ってみたいという方の助けになれれば幸いです。

*決済はStripeを利用したクレジットカード決済となっています。(テストモードです。)
*以前書いた記事と重複している箇所は説明を割愛します。

動作環境について

OS:macOS High Sierra
version: 10.13.6

Docker(Engine):18.09.1

対象ブラウザ

GoogleChrome:72以上

開発環境

centOS:7.5
Laravel:5.6
PHP:7.2
MySQL:5.7
PostgreSQL:10.6
APache2.4

外部サービス

Mailgun
Stripe

参考資料

【簡単・オシャレ】PHPでstripeの決済を導入する手順【決済システム導入】
【初級編】LaravelでStripeを使って単発決済を実装する

TOPページ

現在DBに登録されている商品が表示されています。
キーワード入力による商品の検索も可能です。

FireShot Capture 6 - ECshop - http___shop1.localhost_.png

TOPページでは決済が出来ないようになっています。
管理者は管理者ログインのリンクを、お客様はお客様ログインのリンクを押下して貰うことでログインページに遷移します。
お客様の新規登録の場合は新規登録のリンクを押下することでログインページに遷移します。

ログイン・ユーザー画面

管理者と顧客それぞれのログイン関連の処理については以前書いた記事にまとめています。

adminテーブルを使って認証する方法
customerテーブルを使って認証する方法

パスワード再設定に使うメールはMailgunを使いますが、送信先が限定されているので本番環境ではsmtpを立てた方が良さそうです。

管理者画面

TOPページと同様に登録されている商品の一覧が表示されています。
TOPページと異なる点は各商品ごとに編集、画像アップロード、削除の処理を行えるボタンを置いていることです。

FireShot Capture 9 - ECshop - http___shop1.localhost_admin_home.png

ファイルアップロードについても別の記事でまとめています。

右上のプルダウンを押すとメニュー画面が出てきます。
ここから管理者のホーム画面への遷移、管理者登録、商品登録、ログアウトを行います。

スクリーンショット 2019-02-11 16.27.48.png

新商品登録

商品登録画面では商品名、価格、説明文を入力できます。

FireShot Capture 10 - ECshop - http___shop1.localhost_admin_goods_regist.png

上記3項目はバリデーションファイルにて入力条件を定めることで誤ったデータがDBに挿入されることを防いでいます。

public function rules()
{
    return [
        'goods_name'  => 'required|string|max:50',                      // 必須|文字列|最大50文字
        'price'       => 'required|integer|min:1|digits_between:1,6',   // 必須|最小値:1|数値かつ1桁~6桁
        'goods_text'  => 'nullable|string|max:120',                     // null可|文字長120文字以内
    ];
}

入力誤りがあればメッセージが表示されます。

FireShot Capture 11 - ECshop - http___shop1.localhost_admin_goods_regist.png

最終的な入力内容に誤りが無いか確認する為に確認画面を設けています。

FireShot Capture 12 - ECshop - http___shop1.localhost_admin_goods_confirm.png

「登録する」ボタンを押下すると商品の登録が完了します。

FireShot Capture 13 - ECshop - http___shop1.localhost_admin_home.png

商品情報編集

各商品の「編集」ボタンを押下します。
画面構成自体は新規登録時と違いはありません。
商品ごとにDBに登録されている値が予め入力欄に表示されます。

FireShot Capture 15 - ECshop - http___shop1.localhost_admin_goods_edit_115.png

編集し終えたら確認をし、最後にデータの更新をかけます。

FireShot Capture 24 - ECshop - http___shop1.localhost_admin_home.png

商品削除

「削除」ボタンを押すと確認のアラートが表示されます。「OK」を押すと即座に商品の削除が実行されます。

FireShot Capture 18 - ECshop - http___shop1.localhost_admin_home.png

顧客画面

TOPページと同様に登録されている商品の一覧が表示されています。
TOPページと異なる点は商品のカートへの格納と削除を行うボタン、最終的な購入手続きを行うボタンがあることです。

FireShot Capture 19 - ECshop - http___shop1.localhost_customer_home.png

右上のプルダウンを押すとメニュー画面が出てきます。
ここから顧客のHome画面への遷移、ログアウトを行います。

スクリーンショット 2019-02-11 16.58.09.png

カートに入れる

カートに何も商品を入れないまま購入手続きをしようとしても出来ない様になっています。

FireShot Capture 21 - ECshop - http___shop1.localhost_customer_home.png

「カートに入れる」ボタンを押下することで該当の商品をカートに入れることが出来ます。
1回のボタン押下によりカートに入れることが出来る数量は1つとなっています。

FireShot Capture 22 - ECshop - http___shop1.localhost_customer_home.png

カートから外す

「カートから外す」ボタンを押下することで該当の商品をカートから外すことが出来ます。
1回のボタン押下によりカートから外すことが出来る数量は1つとなっています。

FireShot Capture 23 - ECshop - http___shop1.localhost_customer_home.png

購入内手続き

ホーム画面から「購入内手続きへ」ボタンを押すと購入内容の確認画面に遷移します。

確認画面ではカートに入れた商品のデータと購入数、合計決済金額が表示されています。
確認という観点からこの画面内では一切の商品や購入数の変更が出来ない様になっています。

FireShot Capture 26 - ECshop - http___shop1.localhost_customer_cart_payment_confirm.png

「購入する」ボタンを押下するとstripeの決済画面が表示されます。(テストモードです。)
メールアドレス、カード番号、利用期限、セキュリティコードを入力して「*を支払う」と書いてあるボタンを押下することでクレジットカード決済が完了します。

FireShot Capture 27 - ECshop - http___shop1.localhost_customer_cart_payment_confirm.png

決済処理後はホーム画面に遷移し、決済完了のモーダルが表示されます。

FireShot Capture 28 - ECshop - http___shop1.localhost_customer_home.png

決済の実装で躓いた箇所がモーダルを表示する為のボタンの実装でした。

stripeのリファレンス等では下記の様な形式で記述すると書いてあります。
scriptタグ内でボタンを表示させていることを理解出来ていなかったのでどうやって任意の位置にボタンを配置すれば良いのだろうと悩んでいました。

<form action="{{ route('') }}" method="POST">
    <script
            src="https://checkout.stripe.com/checkout.js" class="stripe-button"
            data-key="{{ env('STRIPE_PUBLIC_KEY') }}"
            data-amount=1000
            data-name="EC Shop"
            data-label="決済をする"
            data-description="Online shopping by Stripe"
            data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
            data-locale="auto"
            data-currency="JPY">
    </script>
</form>

scriptタグの直前に下記のaタグを記述することでキャプチャ通りの配置でボタンを実装することが出来ました。

<a class="btn btn-primary" href="/customer/home">戻る</a>

また、Laravelでデフォルトで用意されている。app.jsがstripeの動作を妨げているらしく、モーダル画面が開くことが出来ませんでした。
この画面だけjsの利用を限定させるなどの工夫が必要でした。

まとめ

以上が、今回私が作成したショッピングサイトの構成となります。

特に時間のかかった作業は認証、ファイルアップロード、決済機能の実装に関してです。

Laravelではデフォルトでusersテーブルを使った管理者機能を利用出来る様になっていますが、別のテーブルを利用して管理者と顧客両方のログイン機能を実装するのに綿密な調査が必要でした。
ファイルアップロード機能は業務含めて初めての試みだったのでバリデーションを考慮して実装するのに時間がかかりました。
決済機能の実装も初めての試みであり今回はAPIを利用させて頂きましたが、深いところを理解出来ていないのが正直な話です。

もっと検討すべき仕様などがございますが時間的な都合で出来なかったことが多々あります。
また、本番公開の段階で発生した修正などもあり、実際に作っている中で自分の力不足を痛感することが多々ございました。

今回の反省点を踏まえてもっと品質の良いプロダクトを作れる様に精進したいと思います。

ご覧頂きありがとうございました。

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

Web開発を初めて1年の成果として決済機能を持つショッピングサイトを作った話

約1年前にWeb開発の業務を担当させて頂きそこからマイペースにLaravelの勉強をしてきました。
勉強してきたことを1つの成果物としてまとめたいなと思い決済機能を持つ簡単なショッピングサイトを作りました。

人によっては1ヶ月以内で出来る様な出来で恐縮ですがベーシック認証をかけた状態でherokuにデプロイをしました。
SSLの設定や画像ファイルの格納先の権限やらでまだ完璧にデプロイ出きた訳では無いですが、社内でのみ公開が出来る様にしたいと考えております。

ここでは主に画面のキャプチャを用いて画面構成やどの様に作り込みをしたかをまとめていきます。
githubにソースコードを上げているのでソースコードの詳細はそちらをご覧頂ければと存じます。
自習やポートフォリオサイトを作ってみたいという方の助けになれれば幸いです。

*決済はStripeを利用したクレジットカード決済となっています。(テストモードです。)
*以前書いた記事と重複している箇所は説明を割愛します。

動作環境について

OS:macOS High Sierra
version: 10.13.6

Docker(Engine):18.09.1

対象ブラウザ

GoogleChrome:72以上

開発環境

centOS:7.5
Laravel:5.6
PHP:7.2
MySQL:5.7
PostgreSQL:10.6
APache2.4

外部サービス

Mailgun
Stripe

参考資料

【簡単・オシャレ】PHPでstripeの決済を導入する手順【決済システム導入】
【初級編】LaravelでStripeを使って単発決済を実装する

TOPページ

現在DBに登録されている商品が表示されています。
キーワード入力による商品の検索も可能です。

FireShot Capture 6 - ECshop - http___shop1.localhost_.png

TOPページでは決済が出来ないようになっています。
管理者は管理者ログインのリンクを、お客様はお客様ログインのリンクを押下して貰うことでログインページに遷移します。
お客様の新規登録の場合は新規登録のリンクを押下することでログインページに遷移します。

ログイン・ユーザー画面

管理者と顧客それぞれのログイン関連の処理については以前書いた記事にまとめています。

adminテーブルを使って認証する方法
customerテーブルを使って認証する方法

パスワード再設定に使うメールはMailgunを使いますが、送信先が限定されているので本番環境ではsmtpを立てた方が良さそうです。

管理者画面

TOPページと同様に登録されている商品の一覧が表示されています。
TOPページと異なる点は各商品ごとに編集、画像アップロード、削除の処理を行えるボタンを置いていることです。

FireShot Capture 9 - ECshop - http___shop1.localhost_admin_home.png

ファイルアップロードについても別の記事でまとめています。

右上のプルダウンを押すとメニュー画面が出てきます。
ここから管理者のホーム画面への遷移、管理者登録、商品登録、ログアウトを行います。

スクリーンショット 2019-02-11 16.27.48.png

新商品登録

商品登録画面では商品名、価格、説明文を入力できます。

FireShot Capture 10 - ECshop - http___shop1.localhost_admin_goods_regist.png

上記3項目はバリデーションファイルにて入力条件を定めることで誤ったデータがDBに挿入されることを防いでいます。

public function rules()
{
    return [
        'goods_name'  => 'required|string|max:50',                      // 必須|文字列|最大50文字
        'price'       => 'required|integer|min:1|digits_between:1,6',   // 必須|最小値:1|数値かつ1桁~6桁
        'goods_text'  => 'nullable|string|max:120',                     // null可|文字長120文字以内
    ];
}

入力誤りがあればメッセージが表示されます。

FireShot Capture 11 - ECshop - http___shop1.localhost_admin_goods_regist.png

最終的な入力内容に誤りが無いか確認する為に確認画面を設けています。

FireShot Capture 12 - ECshop - http___shop1.localhost_admin_goods_confirm.png

「登録する」ボタンを押下すると商品の登録が完了します。

FireShot Capture 13 - ECshop - http___shop1.localhost_admin_home.png

商品情報編集

各商品の「編集」ボタンを押下します。
画面構成自体は新規登録時と違いはありません。
商品ごとにDBに登録されている値が予め入力欄に表示されます。

FireShot Capture 15 - ECshop - http___shop1.localhost_admin_goods_edit_115.png

編集し終えたら確認をし、最後にデータの更新をかけます。

FireShot Capture 24 - ECshop - http___shop1.localhost_admin_home.png

商品削除

「削除」ボタンを押すと確認のアラートが表示されます。「OK」を押すと即座に商品の削除が実行されます。

FireShot Capture 18 - ECshop - http___shop1.localhost_admin_home.png

顧客画面

TOPページと同様に登録されている商品の一覧が表示されています。
TOPページと異なる点は商品のカートへの格納と削除を行うボタン、最終的な購入手続きを行うボタンがあることです。

FireShot Capture 19 - ECshop - http___shop1.localhost_customer_home.png

右上のプルダウンを押すとメニュー画面が出てきます。
ここから顧客のHome画面への遷移、ログアウトを行います。

スクリーンショット 2019-02-11 16.58.09.png

カートに入れる

カートに何も商品を入れないまま購入手続きをしようとしても出来ない様になっています。

FireShot Capture 21 - ECshop - http___shop1.localhost_customer_home.png

「カートに入れる」ボタンを押下することで該当の商品をカートに入れることが出来ます。
1回のボタン押下によりカートに入れることが出来る数量は1つとなっています。

FireShot Capture 22 - ECshop - http___shop1.localhost_customer_home.png

カートから外す

「カートから外す」ボタンを押下することで該当の商品をカートから外すことが出来ます。
1回のボタン押下によりカートから外すことが出来る数量は1つとなっています。

FireShot Capture 23 - ECshop - http___shop1.localhost_customer_home.png

購入内手続き

ホーム画面から「購入内手続きへ」ボタンを押すと購入内容の確認画面に遷移します。

確認画面ではカートに入れた商品のデータと購入数、合計決済金額が表示されています。
確認という観点からこの画面内では一切の商品や購入数の変更が出来ない様になっています。

FireShot Capture 26 - ECshop - http___shop1.localhost_customer_cart_payment_confirm.png

「購入する」ボタンを押下するとstripeの決済画面が表示されます。(テストモードです。)
メールアドレス、カード番号、利用期限、セキュリティコードを入力して「*を支払う」と書いてあるボタンを押下することでクレジットカード決済が完了します。

FireShot Capture 27 - ECshop - http___shop1.localhost_customer_cart_payment_confirm.png

決済処理後はホーム画面に遷移し、決済完了のモーダルが表示されます。

FireShot Capture 28 - ECshop - http___shop1.localhost_customer_home.png

決済の実装で躓いた箇所がモーダルを表示する為のボタンの実装でした。

stripeのリファレンス等では下記の様な形式で記述すると書いてあります。
scriptタグ内でボタンを表示させていることを理解出来ていなかったのでどうやって任意の位置にボタンを配置すれば良いのだろうと悩んでいました。

<form action="{{ route('') }}" method="POST">
    <script
            src="https://checkout.stripe.com/checkout.js" class="stripe-button"
            data-key="{{ env('STRIPE_PUBLIC_KEY') }}"
            data-amount=1000
            data-name="EC Shop"
            data-label="決済をする"
            data-description="Online shopping by Stripe"
            data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
            data-locale="auto"
            data-currency="JPY">
    </script>
</form>

scriptタグの直前に下記のaタグを記述することでキャプチャ通りの配置でボタンを実装することが出来ました。

<a class="btn btn-primary" href="/customer/home">戻る</a>

また、Laravelでデフォルトで用意されている。app.jsがstripeの動作を妨げているらしく、モーダル画面が開くことが出来ませんでした。
この画面だけjsの利用を限定させるなどの工夫が必要でした。

まとめ

以上が、今回私が作成したショッピングサイトの構成となります。

特に時間のかかった作業は認証、ファイルアップロード、決済機能の実装に関してです。

Laravelではデフォルトでusersテーブルを使った管理者機能を利用出来る様になっていますが、別のテーブルを利用して管理者と顧客両方のログイン機能を実装するのに綿密な調査が必要でした。
ファイルアップロード機能は業務含めて初めての試みだったのでバリデーションを考慮して実装するのに時間がかかりました。
決済機能の実装も初めての試みであり今回はAPIを利用させて頂きましたが、深いところを理解出来ていないのが正直な話です。

もっと検討すべき仕様などがございますが時間的な都合で出来なかったことが多々あります。
また、本番公開の段階で発生した修正などもあり、実際に作っている中で自分の力不足を痛感することが多々ございました。

今回の反省点を踏まえてもっと品質の良いプロダクトを作れる様に精進したいと思います。

ご覧頂きありがとうございました。

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

各言語で定義できる関数のパラメータの最大個数

ちょっと気になって、関数で定義できるパラメータの最大個数について実験してみました。

255を閾値として、それ以上のパラメータを持つ関数を定義・実行できるのか、各言語のREPLを使って調べました。 (JavaScript はブラウザのコンソールです。)
C, C++, C# はある方からいただいたコメントを元にしています。
JavaScript は256以上できたので "(unlimited)" としています。
NodeJS, PHP, Ruby は @Nabetani 様 より情報いただきました。

Language Version the maximum number note
C 127 SOLOLEARN
C++ 256 SOLOLEARN
C# 16383 オーバフローするまで成功すると思われる。 Stackoverflow
Python 3.6.5 255 256個以上のパラメータを持つ関数は定義不可。
PHP 7.2.9 262145 オーバフローするまで成功すると思われる。 @Nabetani
Ruby 2.5.1 130767 オーバフローするまで成功すると思われる。 @Nabetani
Kotlin 1.3.0 255 256個以上のパラメータを持つ関数は定義可能だが実行時に java.lang.NullPointerException が発生します。
Java 11.0.2 255 256個以上のパラメータを持つ関数は定義不可。
JavaScript Chrome 72.0.3626.96 (unlimited) オーバフローするまで成功すると思われる。
NodeJS 11.9.0 65535 ルール上は65535。 現実にはオーバフローするまで。 @Nabetani

特に Kotlin は 1.3 で 255個のパラメータを持つ関数を定義できるようになりました。 Java も、 ルールとして 255までしかパラメータ持てないことになっています。 たぶん Scala も?

Python

シンタックスエラーが関数定義の時に255までしか受け付けませんとメッセージを返します。

>>> def f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127, a128, a129, a130, a131, a132, a133, a134, a135, a136, a137, a138, a139, a140, a141, a142, a143, a144, a145, a146, a147, a148, a149, a150, a151, a152, a153, a154, a155, a156, a157, a158, a159, a160, a161, a162, a163, a164, a165, a166, a167, a168, a169, a170, a171, a172, a173, a174, a175, a176, a177, a178, a179, a180, a181, a182, a183, a184, a185, a186, a187, a188, a189, a190, a191, a192, a193, a194, a195, a196, a197, a198, a199, a200, a201, a202, a203, a204, a205, a206, a207, a208, a209, a210, a211, a212, a213, a214, a215, a216, a217, a218, a219, a220, a221, a222, a223, a224, a225, a226, a227, a228, a229, a230, a231, a232, a233, a234, a235, a236, a237, a238, a239, a240, a241, a242, a243, a244, a245, a246, a247, a248, a249, a250, a251, a252, a253, a254, a255, a256, a257):
...     print(1)
... 
  File "<stdin>", line 1
SyntaxError: more than 255 arguments

PHP

256以上のパラメータでも定義・実行できます。

php > function f($a0, $a1, $a2, $a3, $a4, $a5, $a6, $a7, $a8, $a9, $a10, $a11, $a12, $a13, $a14, $a15, $a16, $a17, $a18, $a19, $a20, $a21, $a22, $a23, $a24, $a25, $a26, $a27, $a28, $a29, $a30, $a31, $a32, $a33, $a34, $a35, $a36, $a37, $a38, $a39, $a40, $a41, $a42, $a43, $a44, $a45, $a46, $a47, $a48, $a49, $a50, $a51, $a52, $a53, $a54, $a55, $a56, $a57, $a58, $a59, $a60, $a61, $a62, $a63, $a64, $a65, $a66, $a67, $a68, $a69, $a70, $a71, $a72, $a73, $a74, $a75, $a76, $a77, $a78, $a79, $a80, $a81, $a82, $a83, $a84, $a85, $a86, $a87, $a88, $a89, $a90, $a91, $a92, $a93, $a94, $a95, $a96, $a97, $a98, $a99, $a100, $a101, $a102, $a103, $a104, $a105, $a106, $a107, $a108, $a109, $a110, $a111, $a112, $a113, $a114, $a115, $a116, $a117, $a118, $a119, $a120, $a121, $a122, $a123, $a124, $a125, $a126, $a127, $a128, $a129, $a130, $a131, $a132, $a133, $a134, $a135, $a136, $a137, $a138, $a139, $a140, $a141, $a142, $a143, $a144, $a145, $a146, $a147, $a148, $a149, $a150, $a151, $a152, $a153, $a154, $a155, $a156, $a157, $a158, $a159, $a160, $a161, $a162, $a163, $a164, $a165, $a166, $a167, $a168, $a169, $a170, $a171, $a172, $a173, $a174, $a175, $a176, $a177, $a178, $a179, $a180, $a181, $a182, $a183, $a184, $a185, $a186, $a187, $a188, $a189, $a190, $a191, $a192, $a193, $a194, $a195, $a196, $a197, $a198, $a199, $a200, $a201, $a202, $a203, $a204, $a205, $a206, $a207, $a208, $a209, $a210, $a211, $a212, $a213, $a214, $a215, $a216, $a217, $a218, $a219, $a220, $a221, $a222, $a223, $a224, $a225, $a226, $a227, $a228, $a229, $a230, $a231, $a232, $a233, $a234, $a235, $a236, $a237, $a238, $a239, $a240, $a241, $a242, $a243, $a244, $a245, $a246, $a247, $a248, $a249, $a250, $a251, $a252, $a253, $a254, $a255, $a256,  $a257) { echo 1; }
php >
php > function f($a0 = 1, $a1 = 1, $a2 = 1, $a3 = 1, $a4 = 1, $a5 = 1, $a6 = 1, $a7 = 1, $a8 = 1, $a9 = 1, $a10 = 1, $a11 = 1, $a12 = 1, $a13 = 1, $a14 = 1, $a15 = 1, $a16 = 1, $a17 = 1, $a18 = 1, $a19 = 1, $a20 = 1, $a21 = 1, $a22 = 1, $a23 = 1, $a24 = 1, $a25 = 1, $a26 = 1, $a27 = 1, $a28 = 1, $a29 = 1, $a30 = 1, $a31 = 1, $a32 = 1, $a33 = 1, $a34 = 1, $a35 = 1, $a36 = 1, $a37 = 1, $a38 = 1, $a39 = 1, $a40 = 1, $a41 = 1, $a42 = 1, $a43 = 1, $a44 = 1, $a45 = 1, $a46 = 1, $a47 = 1, $a48 = 1, $a49 = 1, $a50 = 1, $a51 = 1, $a52 = 1, $a53 = 1, $a54 = 1, $a55 = 1, $a56 = 1, $a57 = 1, $a58 = 1, $a59 = 1, $a60 = 1, $a61 = 1, $a62 = 1, $a63 = 1, $a64 = 1, $a65 = 1, $a66 = 1, $a67 = 1, $a68 = 1, $a69 = 1, $a70 = 1, $a71 = 1, $a72 = 1, $a73 = 1, $a74 = 1, $a75 = 1, $a76 = 1, $a77 = 1, $a78 = 1, $a79 = 1, $a80 = 1, $a81 = 1, $a82 = 1, $a83 = 1, $a84 = 1, $a85 = 1, $a86 = 1, $a87 = 1, $a88 = 1, $a89 = 1, $a90 = 1, $a91 = 1, $a92 = 1, $a93 = 1, $a94 = 1, $a95 = 1, $a96 = 1, $a97 = 1, $a98 = 1, $a99 = 1, $a100 = 1, $a101 = 1, $a102 = 1, $a103 = 1, $a104 = 1, $a105 = 1, $a106 = 1, $a107 = 1, $a108 = 1, $a109 = 1, $a110 = 1, $a111 = 1, $a112 = 1, $a113 = 1, $a114 = 1, $a115 = 1, $a116 = 1, $a117 = 1, $a118 = 1, $a119 = 1, $a120 = 1, $a121 = 1, $a122 = 1, $a123 = 1, $a124 = 1, $a125 = 1, $a126 = 1, $a127 = 1, $a128 = 1, $a129 = 1, $a130 = 1, $a131 = 1, $a132 = 1, $a133 = 1, $a134 = 1, $a135 = 1, $a136 = 1, $a137 = 1, $a138 = 1, $a139 = 1, $a140 = 1, $a141 = 1, $a142 = 1, $a143 = 1, $a144 = 1, $a145 = 1, $a146 = 1, $a147 = 1, $a148 = 1, $a149 = 1, $a150 = 1, $a151 = 1, $a152 = 1, $a153 = 1, $a154 = 1, $a155 = 1, $a156 = 1, $a157 = 1, $a158 = 1, $a159 = 1, $a160 = 1, $a161 = 1, $a162 = 1, $a163 = 1, $a164 = 1, $a165 = 1, $a166 = 1, $a167 = 1, $a168 = 1, $a169 = 1, $a170 = 1, $a171 = 1, $a172 = 1, $a173 = 1, $a174 = 1, $a175 = 1, $a176 = 1, $a177 = 1, $a178 = 1, $a179 = 1, $a180 = 1, $a181 = 1, $a182 = 1, $a183 = 1, $a184 = 1, $a185 = 1, $a186 = 1, $a187 = 1, $a188 = 1, $a189 = 1, $a190 = 1, $a191 = 1, $a192 = 1, $a193 = 1, $a194 = 1, $a195 = 1, $a196 = 1, $a197 = 1, $a198 = 1, $a199 = 1, $a200 = 1, $a201 = 1, $a202 = 1, $a203 = 1, $a204 = 1, $a205 = 1, $a206 = 1, $a207 = 1, $a208 = 1, $a209 = 1, $a210 = 1, $a211 = 1, $a212 = 1, $a213 = 1, $a214 = 1, $a215 = 1, $a216 = 1, $a217 = 1, $a218 = 1, $a219 = 1, $a220 = 1, $a221 = 1, $a222 = 1, $a223 = 1, $a224 = 1, $a225 = 1, $a226 = 1, $a227 = 1, $a228 = 1, $a229 = 1, $a230 = 1, $a231 = 1, $a232 = 1, $a233 = 1, $a234 = 1, $a235 = 1, $a236 = 1, $a237 = 1, $a238 = 1, $a239 = 1, $a240 = 1, $a241 = 1, $a242 = 1, $a243 = 1, $a244 = 1, $a245 = 1, $a246 = 1, $a247 = 1, $a248 = 1, $a249 = 1, $a250 = 1, $a251 = 1, $a252 = 1, $a253 = 1, $a254 = 1, $a255 = 1,  $a256 = 1) { echo 1; }
php > f()
php > ;
1

Ruby

256以上のパラメータでも実行できます。

2.5.1 :004 > def f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70,
a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127, a128, a129, a130, a131, a132, a133, a134, a135, a136, a137, a138, a139, a140, a141, a142, a143, a144, a145, a146, a147, a148, a149, a150, a151, a152, a153, a154, a155, a156, a157, a158, a159, a160, a161, a162, a163, a164, a165, a166, a167, a168, a169, a170, a171, a172, a173, a174, a175, a176, a177, a178, a179, a180, a181, a182, a183, a184, a185, a186, a187, a188, a189, a190, a191, a192, a193, a194, a195, a196, a197, a198, a199, a200, a201, a202, a203, a204, a205, a206, a207, a208, a209, a210, a211, a212, a213, a214, a215, a216, a217, a218, a219, a220, a221, a222, a223, a224, a225, a226, a227, a228, a229, a230, a231, a232, a233, a234, a235, a236, a237, a238, a239, a240, a241, a242, a243, a244, a245, a246, a247, a248, a249, a250, a251, a252, a253, a254, a255, a256, a257)
2.5.1 :005?>    puts 1
2.5.1 :006?>   end
 => :f
2.5.1 :001 > def f(a0 = 1, a1 = 1, a2 = 1, a3 = 1, a4 = 1, a5 = 1, a6 = 1, a7 = 1, a8 = 1, a9 = 1, a10 = 1, a11 = 1, a12 = 1, a13 = 1, a14 = 1, a15 = 1, a16 = 1, a17 = 1, a18 = 1, a19 = 1, a20 = 1, a21 = 1, a22 = 1, a23 = 1, a24 = 1, a25 = 1, a26 = 1, a27 = 1, a28 = 1, a29 = 1, a30 = 1, a31 = 1, a32 = 1, a33 = 1, a34 = 1, a35 = 1, a36 = 1, a37 = 1, a38 = 1, a39 = 1, a40 = 1, a41 = 1, a42 = 1, a43 = 1, a44 = 1, a45 = 1, a46 = 1, a47 = 1, a48 = 1, a49 = 1, a50 = 1, a51 = 1, a52 = 1, a53 = 1, a54 = 1, a55 = 1, a56 = 1, a57 = 1, a58 = 1, a59 = 1, a60 = 1, a61 = 1, a62 = 1, a63 = 1, a64 = 1, a65 = 1, a66 = 1, a67 = 1, a68 = 1, a69 = 1, a70 = 1, a71 = 1, a72 = 1, a73 = 1, a74 = 1, a75 = 1, a76 = 1, a77 = 1, a78 = 1, a79 = 1, a80 = 1, a81 = 1, a82 = 1, a83 = 1, a84 = 1, a85 = 1, a86 = 1, a87 = 1, a88 = 1, a89 = 1, a90 = 1, a91 = 1, a92 = 1, a93 = 1, a94 = 1, a95 = 1, a96 = 1, a97 = 1, a98 = 1, a99 = 1, a100 = 1, a101 = 1, a102 = 1, a103 = 1, a104 = 1, a105 = 1, a106 = 1, a107 = 1, a108 = 1, a109 = 1, a110 = 1, a111 = 1, a112 = 1, a113 = 1, a114 = 1, a115 = 1, a116 = 1, a117 = 1, a118 = 1, a119 = 1, a120 = 1, a121 = 1, a122 = 1, a123 = 1, a124 = 1, a125 = 1, a126 = 1, a127 = 1, a128 = 1, a129 = 1, a130 = 1, a131 = 1, a132 = 1, a133 = 1, a134 = 1, a135 = 1, a136 = 1, a137 = 1, a138 = 1, a139 = 1, a140 = 1, a141 = 1, a142 = 1, a143 = 1, a144 = 1, a145 = 1, a146 = 1, a147 = 1, a148 = 1, a149 = 1, a150 = 1, a151 = 1, a152 = 1, a153 = 1, a154 = 1, a155 = 1, a156 = 1, a157 = 1, a158 = 1, a159 = 1, a160 = 1, a161 = 1, a162 = 1, a163 = 1, a164 = 1, a165 = 1, a166 = 1, a167 = 1, a168 = 1, a169 = 1, a170 = 1, a171 = 1, a172 = 1, a173 = 1, a174 = 1, a175 = 1, a176 = 1, a177 = 1, a178 = 1, a179 = 1, a180 = 1, a181 = 1, a182 = 1, a183 = 1, a184 = 1, a185 = 1, a186 = 1, a187 = 1, a188 = 1, a189 = 1, a190 = 1, a191 = 1, a192 = 1, a193 = 1, a194 = 1, a195 = 1, a196 = 1, a197 = 1, a198 = 1, a199 = 1, a200 = 1, a201 = 1, a202 = 1, a203 = 1, a204 = 1, a205 = 1, a206 = 1, a207 = 1, a208 = 1, a209 = 1, a210 = 1, a211 = 1, a212 = 1, a213 = 1, a214 = 1, a215 = 1, a216 = 1, a217 = 1, a218 = 1, a219 = 1, a220 = 1, a221 = 1, a222 = 1, a223 = 1, a224 = 1, a225 = 1, a226 = 1, a227 = 1, a228 = 1, a229 = 1, a230 = 1, a231 = 1, a232 = 1, a233 = 1, a234 = 1, a235 = 1, a236 = 1, a237 = 1, a238 = 1, a239 = 1, a240 = 1, a241 = 1, a242 = 1, a243 = 1, a244 = 1, a245 = 1, a246 = 1, a247 = 1, a248 = 1, a249 = 1, a250 = 1, a251 = 1, a252 = 1, a253 = 1, a254 = 1, a255 = 1,  a256 = 1)
2.5.1 :002?>    puts 1
2.5.1 :003?>   end
 => :f 
2.5.1 :004 > f()
1
 => nil 

Kotlin

定義はできているように見えます。しかし実行時にエラーが出ました。

>>> fun f(a0: Int, a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int, a24: Int, a25: Int, a26: Int, a27: Int, a28: Int, a29: Int, a30: Int, a31: Int, a32: Int, a33: Int, a34: Int, a35: Int, a36: Int, a37: Int, a38: Int, a39: Int, a40: Int, a41: Int, a42: Int, a43: Int, a44: Int, a45: Int, a46: Int, a47: Int, a48: Int, a49: Int, a50: Int, a51: Int, a52: Int, a53: Int, a54: Int, a55: Int, a56: Int, a57: Int, a58: Int, a59: Int, a60: Int, a61: Int, a62: Int, a63: Int, a64: Int, a65: Int, a66: Int, a67: Int, a68: Int, a69: Int, a70: Int, a71: Int, a72: Int, a73: Int, a74: Int, a75: Int, a76: Int, a77: Int, a78: Int, a79: Int, a80: Int, a81: Int, a82: Int, a83: Int, a84: Int, a85: Int, a86: Int, a87: Int, a88: Int, a89: Int, a90: Int, a91: Int, a92: Int, a93: Int, a94: Int, a95: Int, a96: Int, a97: Int, a98: Int, a99: Int, a100: Int, a101: Int, a102: Int, a103: Int, a104: Int, a105: Int, a106: Int, a107: Int, a108: Int, a109: Int, a110: Int, a111: Int, a112: Int, a113: Int, a114: Int, a115: Int, a116: Int, a117: Int, a118: Int, a119: Int, a120: Int, a121: Int, a122: Int, a123: Int, a124: Int, a125: Int, a126: Int, a127: Int, a128: Int, a129: Int, a130: Int, a131: Int, a132: Int, a133: Int, a134: Int, a135: Int, a136: Int, a137: Int, a138: Int, a139: Int, a140: Int, a141: Int, a142: Int, a143: Int, a144: Int, a145: Int, a146: Int, a147: Int, a148: Int, a149: Int, a150: Int, a151: Int, a152: Int, a153: Int, a154: Int, a155: Int, a156: Int, a157: Int, a158: Int, a159: Int, a160: Int, a161: Int, a162: Int, a163: Int, a164: Int, a165: Int, a166: Int, a167: Int, a168: Int, a169: Int, a170: Int, a171: Int, a172: Int, a173: Int, a174: Int, a175: Int, a176: Int, a177: Int, a178: Int, a179: Int, a180: Int, a181: Int, a182: Int, a183: Int, a184: Int, a185: Int, a186: Int, a187: Int, a188: Int, a189: Int, a190: Int, a191: Int, a192: Int, a193: Int, a194: Int, a195: Int, a196: Int, a197: Int, a198: Int, a199: Int, a200: Int, a201: Int, a202: Int, a203: Int, a204: Int, a205: Int, a206: Int, a207: Int, a208: Int, a209: Int, a210: Int, a211: Int, a212: Int, a213: Int, a214: Int, a215: Int, a216: Int, a217: Int, a218: Int, a219: Int, a220: Int, a221: Int, a222: Int, a223: Int, a224: Int, a225: Int, a226: Int, a227: Int, a228: Int, a229: Int, a230: Int, a231: Int, a232: Int, a233: Int, a234: Int, a235: Int, a236: Int, a237: Int, a238: Int, a239: Int, a240: Int, a241: Int, a242: Int, a243: Int, a244: Int, a245: Int, a246: Int, a247: Int, a248: Int, a249: Int, a250: Int, a251: Int, a252: Int, a253: Int, a254: Int, a255: Int, a256: Int, a257: Int) { println(1) }
>>> fun f(a0: Int = 1, a1: Int = 1, a2: Int = 1, a3: Int = 1, a4: Int = 1, a5: Int = 1, a6: Int = 1, a7: Int = 1, a8: Int = 1, a9: Int = 1, a10: Int = 1, a11: Int = 1, a12: Int = 1, a13: Int = 1, a14: Int = 1, a15: Int = 1, a16: Int = 1, a17: Int = 1, a18: Int = 1, a19: Int = 1, a20: Int = 1, a21: Int = 1, a22: Int = 1, a23: Int = 1, a24: Int = 1, a25: Int = 1, a26: Int = 1, a27: Int = 1, a28: Int = 1, a29: Int = 1, a30: Int = 1, a31: Int = 1, a32: Int = 1, a33: Int = 1, a34: Int = 1, a35: Int = 1, a36: Int = 1, a37: Int = 1, a38: Int = 1, a39: Int = 1, a40: Int = 1, a41: Int = 1, a42: Int = 1, a43: Int = 1, a44: Int = 1, a45: Int = 1, a46: Int = 1, a47: Int = 1, a48: Int = 1, a49: Int = 1, a50: Int = 1, a51: Int = 1, a52: Int = 1, a53: Int = 1, a54: Int = 1, a55: Int = 1, a56: Int = 1, a57: Int = 1, a58: Int = 1, a59: Int = 1, a60: Int = 1, a61: Int = 1, a62: Int = 1, a63: Int = 1, a64: Int = 1, a65: Int = 1, a66: Int = 1, a67: Int = 1, a68: Int = 1, a69: Int = 1, a70: Int = 1, a71: Int = 1, a72: Int = 1, a73: Int = 1, a74: Int = 1, a75: Int = 1, a76: Int = 1, a77: Int = 1, a78: Int = 1, a79: Int = 1, a80: Int = 1, a81: Int = 1, a82: Int = 1, a83: Int = 1, a84: Int = 1, a85: Int = 1, a86: Int = 1, a87: Int = 1, a88: Int = 1, a89: Int = 1, a90: Int = 1, a91: Int = 1, a92: Int = 1, a93: Int = 1, a94: Int = 1, a95: Int = 1, a96: Int = 1, a97: Int = 1, a98: Int = 1, a99: Int = 1, a100: Int = 1, a101: Int = 1, a102: Int = 1, a103: Int = 1, a104: Int = 1, a105: Int = 1, a106: Int = 1, a107: Int = 1, a108: Int = 1, a109: Int = 1, a110: Int = 1, a111: Int = 1, a112: Int = 1, a113: Int = 1, a114: Int = 1, a115: Int = 1, a116: Int = 1, a117: Int = 1, a118: Int = 1, a119: Int = 1, a120: Int = 1, a121: Int = 1, a122: Int = 1, a123: Int = 1, a124: Int = 1, a125: Int = 1, a126: Int = 1, a127: Int = 1, a128: Int = 1, a129: Int = 1, a130: Int = 1, a131: Int = 1, a132: Int = 1, a133: Int = 1, a134: Int = 1, a135: Int = 1, a136: Int = 1, a137: Int = 1, a138: Int = 1, a139: Int = 1, a140: Int = 1, a141: Int = 1, a142: Int = 1, a143: Int = 1, a144: Int = 1, a145: Int = 1, a146: Int = 1, a147: Int = 1, a148: Int = 1, a149: Int = 1, a150: Int = 1, a151: Int = 1, a152: Int = 1, a153: Int = 1, a154: Int = 1, a155: Int = 1, a156: Int = 1, a157: Int = 1, a158: Int = 1, a159: Int = 1, a160: Int = 1, a161: Int = 1, a162: Int = 1, a163: Int = 1, a164: Int = 1, a165: Int = 1, a166: Int = 1, a167: Int = 1, a168: Int = 1, a169: Int = 1, a170: Int = 1, a171: Int = 1, a172: Int = 1, a173: Int = 1, a174: Int = 1, a175: Int = 1, a176: Int = 1, a177: Int = 1, a178: Int = 1, a179: Int = 1, a180: Int = 1, a181: Int = 1, a182: Int = 1, a183: Int = 1, a184: Int = 1, a185: Int = 1, a186: Int = 1, a187: Int = 1, a188: Int = 1, a189: Int = 1, a190: Int = 1, a191: Int = 1, a192: Int = 1, a193: Int = 1, a194: Int = 1, a195: Int = 1, a196: Int = 1, a197: Int = 1, a198: Int = 1, a199: Int = 1, a200: Int = 1, a201: Int = 1, a202: Int = 1, a203: Int = 1, a204: Int = 1, a205: Int = 1, a206: Int = 1, a207: Int = 1, a208: Int = 1, a209: Int = 1, a210: Int = 1, a211: Int = 1, a212: Int = 1, a213: Int = 1, a214: Int = 1, a215: Int = 1, a216: Int = 1, a217: Int = 1, a218: Int = 1, a219: Int = 1, a220: Int = 1, a221: Int = 1, a222: Int = 1, a223: Int = 1, a224: Int = 1, a225: Int = 1, a226: Int = 1, a227: Int = 1, a228: Int = 1, a229: Int = 1, a230: Int = 1, a231: Int = 1, a232: Int = 1, a233: Int = 1, a234: Int = 1, a235: Int = 1, a236: Int = 1, a237: Int = 1, a238: Int = 1, a239: Int = 1, a240: Int = 1, a241: Int = 1, a242: Int = 1, a243: Int = 1, a244: Int = 1, a245: Int = 1, a246: Int = 1, a247: Int = 1, a248: Int = 1, a249: Int = 1, a250: Int = 1, a251: Int = 1, a252: Int = 1, a253: Int = 1, a254: Int = 1, a255: Int = 1) { println(1) }
>>> f()
java.lang.NullPointerException
        at Line_1.f$default(Line_1.kts:1)
>>> f(1)
java.lang.NullPointerException
        at Line_1.f$default(Line_1.kts:1)
>>> fun f(a0: Int = 1, a1: Int = 1, a2: Int = 1, a3: Int = 1, a4: Int = 1, a5: Int = 1, a6: Int = 1, a7: Int = 1, a8: Int = 1, a9: Int = 1, a10: Int = 1, a11: Int = 1, a12: Int = 1, a13: Int = 1, a14: Int = 1, a15: Int = 1, a16: Int = 1, a17: Int = 1, a18: Int = 1, a19: Int = 1, a20: Int = 1, a21: Int = 1, a22: Int = 1, a23: Int = 1, a24: Int = 1, a25: Int = 1, a26: Int = 1, a27: Int = 1, a28: Int = 1, a29: Int = 1, a30: Int = 1, a31: Int = 1, a32: Int = 1, a33: Int = 1, a34: Int = 1, a35: Int = 1, a36: Int = 1, a37: Int = 1, a38: Int = 1, a39: Int = 1, a40: Int = 1, a41: Int = 1, a42: Int = 1, a43: Int = 1, a44: Int = 1, a45: Int = 1, a46: Int = 1, a47: Int = 1, a48: Int = 1, a49: Int = 1, a50: Int = 1, a51: Int = 1, a52: Int = 1, a53: Int = 1, a54: Int = 1, a55: Int = 1, a56: Int = 1, a57: Int = 1, a58: Int = 1, a59: Int = 1, a60: Int = 1, a61: Int = 1, a62: Int = 1, a63: Int = 1, a64: Int = 1, a65: Int = 1, a66: Int = 1, a67: Int = 1, a68: Int = 1, a69: Int = 1, a70: Int = 1, a71: Int = 1, a72: Int = 1, a73: Int = 1, a74: Int = 1, a75: Int = 1, a76: Int = 1, a77: Int = 1, a78: Int = 1, a79: Int = 1, a80: Int = 1, a81: Int = 1, a82: Int = 1, a83: Int = 1, a84: Int = 1, a85: Int = 1, a86: Int = 1, a87: Int = 1, a88: Int = 1, a89: Int = 1, a90: Int = 1, a91: Int = 1, a92: Int = 1, a93: Int = 1, a94: Int = 1, a95: Int = 1, a96: Int = 1, a97: Int = 1, a98: Int = 1, a99: Int = 1, a100: Int = 1, a101: Int = 1, a102: Int = 1, a103: Int = 1, a104: Int = 1, a105: Int = 1, a106: Int = 1, a107: Int = 1, a108: Int = 1, a109: Int = 1, a110: Int = 1, a111: Int = 1, a112: Int = 1, a113: Int = 1, a114: Int = 1, a115: Int = 1, a116: Int = 1, a117: Int = 1, a118: Int = 1, a119: Int = 1, a120: Int = 1, a121: Int = 1, a122: Int = 1, a123: Int = 1, a124: Int = 1, a125: Int = 1, a126: Int = 1, a127: Int = 1, a128: Int = 1, a129: Int = 1, a130: Int = 1, a131: Int = 1, a132: Int = 1, a133: Int = 1, a134: Int = 1, a135: Int = 1, a136: Int = 1, a137: Int = 1, a138: Int = 1, a139: Int = 1, a140: Int = 1, a141: Int = 1, a142: Int = 1, a143: Int = 1, a144: Int = 1, a145: Int = 1, a146: Int = 1, a147: Int = 1, a148: Int = 1, a149: Int = 1, a150: Int = 1, a151: Int = 1, a152: Int = 1, a153: Int = 1, a154: Int = 1, a155: Int = 1, a156: Int = 1, a157: Int = 1, a158: Int = 1, a159: Int = 1, a160: Int = 1, a161: Int = 1, a162: Int = 1, a163: Int = 1, a164: Int = 1, a165: Int = 1, a166: Int = 1, a167: Int = 1, a168: Int = 1, a169: Int = 1, a170: Int = 1, a171: Int = 1, a172: Int = 1, a173: Int = 1, a174: Int = 1, a175: Int = 1, a176: Int = 1, a177: Int = 1, a178: Int = 1, a179: Int = 1, a180: Int = 1, a181: Int = 1, a182: Int = 1, a183: Int = 1, a184: Int = 1, a185: Int = 1, a186: Int = 1, a187: Int = 1, a188: Int = 1, a189: Int = 1, a190: Int = 1, a191: Int = 1, a192: Int = 1, a193: Int = 1, a194: Int = 1, a195: Int = 1, a196: Int = 1, a197: Int = 1, a198: Int = 1, a199: Int = 1, a200: Int = 1, a201: Int = 1, a202: Int = 1, a203: Int = 1, a204: Int = 1, a205: Int = 1, a206: Int = 1, a207: Int = 1, a208: Int = 1, a209: Int = 1, a210: Int = 1, a211: Int = 1, a212: Int = 1, a213: Int = 1, a214: Int = 1, a215: Int = 1, a216: Int = 1, a217: Int = 1, a218: Int = 1, a219: Int = 1, a220: Int = 1, a221: Int = 1, a222: Int = 1, a223: Int = 1, a224: Int = 1, a225: Int = 1, a226: Int = 1, a227: Int = 1, a228: Int = 1, a229: Int = 1, a230: Int = 1, a231: Int = 1, a232: Int = 1, a233: Int = 1, a234: Int = 1, a235: Int = 1, a236: Int = 1, a237: Int = 1, a238: Int = 1, a239: Int = 1, a240: Int = 1, a241: Int = 1, a242: Int = 1, a243: Int = 1, a244: Int = 1, a245: Int = 1, a246: Int = 1, a247: Int = 1, a248: Int = 1, a249: Int = 1,  a250: Int = 1,  a251: Int = 1,  a252: Int = 1,  a253: Int = 1,  a254: Int = 1) { println(1) }
>>> f()
1
>>> 

Java

256個以上のパラメータがあると、定義することもできません。

jshell> void f(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23, int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31, int a32, int a33, int a34, int a35, int a36, int a37, int a38, int a39, int a40, int a41, int a42, int a43, int a44, int a45, int a46, int a47, int a48, int a49, int a50, int a51, int a52, int a53, int a54, int a55, int a56, int a57, int a58, int a59, int a60, int a61, int a62, int a63, int a64, int a65, int a66, int a67, int a68, int a69, int a70, int a71, int a72, int a73, int a74, int a75, int a76, int a77, int a78, int a79, int a80, int a81, int a82, int a83, int a84, int a85, int a86, int a87, int a88, int a89, int a90, int a91, int a92, int a93, int a94, int a95, int a96, int a97, int a98, int a99, int a100, int a101, int a102, int a103, int a104, int a105, int a106, int a107, int a108, int a109, int a110, int a111, int a112, int a113, int a114, int a115, int a116, int a117, int a118, int a119, int a120, int a121, int a122, int a123, int a124, int a125, int a126, int a127, int a128, int a129, int a130, int a131, int a132, int a133, int a134, int a135, int a136, int a137, int a138, int a139, int a140, int a141, int a142, int a143, int a144, int a145, int a146, int a147, int a148, int a149, int a150, int a151, int a152, int a153, int a154, int a155, int a156, int a157, int a158, int a159, int a160, int a161, int a162, int a163, int a164, int a165, int a166, int a167, int a168, int a169, int a170, int a171, int a172, int a173, int a174, int a175, int a176, int a177, int a178, int a179, int a180, int a181, int a182, int a183, int a184, int a185, int a186, int a187, int a188, int a189, int a190, int a191, int a192, int a193, int a194, int a195, int a196, int a197, int a198, int a199, int a200, int a201, int a202, int a203, int a204, int a205, int a206, int a207, int a208, int a209, int a210, int a211, int a212, int a213, int a214, int a215, int a216, int a217, int a218, int a219, int a220, int a221, int a222, int a223, int a224, int a225, int a226, int a227, int a228, int a229, int a230, int a231, int a232, int a233, int a234, int a235, int a236, int a237, int a238, int a239, int a240, int a241, int a242, int a243, int a244, int a245, int a246, int a247, int a248, int a249, int a250, int a251, int a252, int a253, int a254,  int a255) { System.out.println(1); }
|  Error:
|  too many parameters
|  void f(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23, int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31, int a32, int a33, int a34, int a35, int a36, int a37, int a38, int a39, int a40, int a41, int a42, int a43, int a44, int a45, int a46, int a47, int a48, int a49, int a50, int a51, int a52, int a53, int a54, int a55, int a56, int a57, int a58, int a59, int a60, int a61, int a62, int a63, int a64, int a65, int a66, int a67, int a68, int a69, int a70, int a71, int a72, int a73, int a74, int a75, int a76, int a77, int a78, int a79, int a80, int a81, int a82, int a83, int a84, int a85, int a86, int a87, int a88, int a89, int a90, int a91, int a92, int a93, int a94, int a95, int a96, int a97, int a98, int a99, int a100, int a101, int a102, int a103, int a104, int a105, int a106, int a107, int a108, int a109, int a110, int a111, int a112, int a113, int a114, int a115, int a116, int a117, int a118, int a119, int a120, int a121, int a122, int a123, int a124, int a125, int a126, int a127, int a128, int a129, int a130, int a131, int a132, int a133, int a134, int a135, int a136, int a137, int a138, int a139, int a140, int a141, int a142, int a143, int a144, int a145, int a146, int a147, int a148, int a149, int a150, int a151, int a152, int a153, int a154, int a155, int a156, int a157, int a158, int a159, int a160, int a161, int a162, int a163, int a164, int a165, int a166, int a167, int a168, int a169, int a170, int a171, int a172, int a173, int a174, int a175, int a176, int a177, int a178, int a179, int a180, int a181, int a182, int a183, int a184, int a185, int a186, int a187, int a188, int a189, int a190, int a191, int a192, int a193, int a194, int a195, int a196, int a197, int a198, int a199, int a200, int a201, int a202, int a203, int a204, int a205, int a206, int a207, int a208, int a209, int a210, int a211, int a212, int a213, int a214, int a215, int a216, int a217, int a218, int a219, int a220, int a221, int a222, int a223, int a224, int a225, int a226, int a227, int a228, int a229, int a230, int a231, int a232, int a233, int a234, int a235, int a236, int a237, int a238, int a239, int a240, int a241, int a242, int a243, int a244, int a245, int a246, int a247, int a248, int a249, int a250, int a251, int a252, int a253, int a254,  int a255) { System.out.println(1); }
|  ^----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------^
|  modified method f(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int), however, it cannot be referenced until this error is corrected: 
|      too many parameters
|      void f(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23, int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31, int a32, int a33, int a34, int a35, int a36, int a37, int a38, int a39, int a40, int a41, int a42, int a43, int a44, int a45, int a46, int a47, int a48, int a49, int a50, int a51, int a52, int a53, int a54, int a55, int a56, int a57, int a58, int a59, int a60, int a61, int a62, int a63, int a64, int a65, int a66, int a67, int a68, int a69, int a70, int a71, int a72, int a73, int a74, int a75, int a76, int a77, int a78, int a79, int a80, int a81, int a82, int a83, int a84, int a85, int a86, int a87, int a88, int a89, int a90, int a91, int a92, int a93, int a94, int a95, int a96, int a97, int a98, int a99, int a100, int a101, int a102, int a103, int a104, int a105, int a106, int a107, int a108, int a109, int a110, int a111, int a112, int a113, int a114, int a115, int a116, int a117, int a118, int a119, int a120, int a121, int a122, int a123, int a124, int a125, int a126, int a127, int a128, int a129, int a130, int a131, int a132, int a133, int a134, int a135, int a136, int a137, int a138, int a139, int a140, int a141, int a142, int a143, int a144, int a145, int a146, int a147, int a148, int a149, int a150, int a151, int a152, int a153, int a154, int a155, int a156, int a157, int a158, int a159, int a160, int a161, int a162, int a163, int a164, int a165, int a166, int a167, int a168, int a169, int a170, int a171, int a172, int a173, int a174, int a175, int a176, int a177, int a178, int a179, int a180, int a181, int a182, int a183, int a184, int a185, int a186, int a187, int a188, int a189, int a190, int a191, int a192, int a193, int a194, int a195, int a196, int a197, int a198, int a199, int a200, int a201, int a202, int a203, int a204, int a205, int a206, int a207, int a208, int a209, int a210, int a211, int a212, int a213, int a214, int a215, int a216, int a217, int a218, int a219, int a220, int a221, int a222, int a223, int a224, int a225, int a226, int a227, int a228, int a229, int a230, int a231, int a232, int a233, int a234, int a235, int a236, int a237, int a238, int a239, int a240, int a241, int a242, int a243, int a244, int a245, int a246, int a247, int a248, int a249, int a250, int a251, int a252, int a253, int a254,  int a255) { System.out.println(1); }
|      ^----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------^

jshell> void f(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20, int a21, int a22, int a23, int a24, int a25, int a26, int a27, int a28, int a29, int a30, int a31, int a32, int a33, int a34, int a35, int a36, int a37, int a38, int a39, int a40, int a41, int a42, int a43, int a44, int a45, int a46, int a47, int a48, int a49, int a50, int a51, int a52, int a53, int a54, int a55, int a56, int a57, int a58, int a59, int a60, int a61, int a62, int a63, int a64, int a65, int a66, int a67, int a68, int a69, int a70, int a71, int a72, int a73, int a74, int a75, int a76, int a77, int a78, int a79, int a80, int a81, int a82, int a83, int a84, int a85, int a86, int a87, int a88, int a89, int a90, int a91, int a92, int a93, int a94, int a95, int a96, int a97, int a98, int a99, int a100, int a101, int a102, int a103, int a104, int a105, int a106, int a107, int a108, int a109, int a110, int a111, int a112, int a113, int a114, int a115, int a116, int a117, int a118, int a119, int a120, int a121, int a122, int a123, int a124, int a125, int a126, int a127, int a128, int a129, int a130, int a131, int a132, int a133, int a134, int a135, int a136, int a137, int a138, int a139, int a140, int a141, int a142, int a143, int a144, int a145, int a146, int a147, int a148, int a149, int a150, int a151, int a152, int a153, int a154, int a155, int a156, int a157, int a158, int a159, int a160, int a161, int a162, int a163, int a164, int a165, int a166, int a167, int a168, int a169, int a170, int a171, int a172, int a173, int a174, int a175, int a176, int a177, int a178, int a179, int a180, int a181, int a182, int a183, int a184, int a185, int a186, int a187, int a188, int a189, int a190, int a191, int a192, int a193, int a194, int a195, int a196, int a197, int a198, int a199, int a200, int a201, int a202, int a203, int a204, int a205, int a206, int a207, int a208, int a209, int a210, int a211, int a212, int a213, int a214, int a215, int a216, int a217, int a218, int a219, int a220, int a221, int a222, int a223, int a224, int a225, int a226, int a227, int a228, int a229, int a230, int a231, int a232, int a233, int a234, int a235, int a236, int a237, int a238, int a239, int a240, int a241, int a242, int a243, int a244, int a245, int a246, int a247, int a248, int a249, int a250, int a251, int a252, int a253,  int a254) { System.out.println(1); }
|  created method f(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int)

jshell> f(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1);
1

jshell> 

JavaScript

パラメータが256個以上でも関数定義できます・

function f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, a120, a121, a122, a123, a124, a125, a126, a127, a128, a129, a130, a131, a132, a133, a134, a135, a136, a137, a138, a139, a140, a141, a142, a143, a144, a145, a146, a147, a148, a149, a150, a151, a152, a153, a154, a155, a156, a157, a158, a159, a160, a161, a162, a163, a164, a165, a166, a167, a168, a169, a170, a171, a172, a173, a174, a175, a176, a177, a178, a179, a180, a181, a182, a183, a184, a185, a186, a187, a188, a189, a190, a191, a192, a193, a194, a195, a196, a197, a198, a199, a200, a201, a202, a203, a204, a205, a206, a207, a208, a209, a210, a211, a212, a213, a214, a215, a216, a217, a218, a219, a220, a221, a222, a223, a224, a225, a226, a227, a228, a229, a230, a231, a232, a233, a234, a235, a236, a237, a238, a239, a240, a241, a242, a243, a244, a245, a246, a247, a248, a249, a250, a251, a252, a253, a254, a255) { console.log(1); }
f(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
1
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[PHP]MacにComposerをインストールしよう。

composer.png
PHPを扱うものとしてはComposerは必須ですよね。
インストール方法を簡単ですがまとめました。

+Composerって?

PHPのパッケージ管理ツールのことです。
CakePHPやLaravelなどのフレームワークであったり、Githubなどで公開されている便利なパッケージ(メール操作・ファイル操作など)を一元管理してくれます。
違う環境で作業を行うときなど、コマンドを叩くだけですべてのパッケージを一括でインストールできます。

+事前準備

  • パソコン:MacでもWindowsどちらでもOK。
  • PHP:バージョン5.3.2以上 ※MAMPでサクッとインストールした方が簡単。

※ PHPのインストール確認
1.Macのターミナル or Windowsのコマンドプロンプトを立上げる。
2.以下のコマンドを入力する。

$ php -v

3.こんな感じでバージョンが表示されるとOK。

PHP 7.1.12 (cli) (built: Nov 27 2017 15:53:40) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

+インストール

1.インストールしたいディレクトリに移動する。

$ cd インストールディレクトリ

2.インストール用コマンドを入力

$ curl -sS https://getcomposer.org/installer | php

これで、ディレクトリ内に 「composer.phar」 が作成されればインストール完了です。
このファイルを実行することでcomposerを利用できます。

また、パスを通すことでグローバルに実行できます。
パスを通すには以下の様にパスが通ったディレクトリ(/usr/local/bin/)に移動してください。

$ mv composer.phar /usr/local/bin/composer

※ homebrewでのインストールは以下にサクッとまとめています。
[PHP]MacにhomebrewでComposerをインストールしよう。

+確認

1.composerコマンドを入力

$ composer

2.こんな感じでバージョンが表示されるとOK。

   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.6.5 2018-05-04 11:44:59
Usage:
  command [options] [arguments]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[PHP]MacにhomebrewでComposerをインストールしよう。

composer.png
PHPを扱うものとしてはComposerは必須ですよね。
homebrewでのインストール方法を簡単ですがまとめました。

+Composerって?

PHPのパッケージ管理ツールのことです。
CakePHPやLaravelなどのフレームワークであったり、Githubなどで公開されている便利なパッケージ(メール操作・ファイル操作など)を一元管理してくれます。
違う環境で作業を行うときなど、コマンドを叩くだけですべてのパッケージを一括でインストールできます。

+事前準備

  • パソコン
  • PHP:バージョン5.3.2以上 ※MAMPでサクッとインストールした方が簡単。

※ PHPのインストール確認
1.Macのターミナル or Windowsのコマンドプロンプトを立上げる。
2.以下のコマンドを入力する。

$ php -v

3.こんな感じでバージョンが表示されるとOK。

PHP 7.1.12 (cli) (built: Nov 27 2017 15:53:40) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

+インストール

1.homebrewでComposerを検索する。

$ brew search composer

こんな感じで表示されればOKです。

==> Formulae
composer

2.インストール用コマンドを入力

$ brew install composer

以上でインストールは完了です。

+確認

1.composerコマンドを入力

$ composer

2.こんな感じでバージョンが表示されるとOK。

   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.6.5 2018-05-04 11:44:59
Usage:
  command [options] [arguments]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel5.6でファイルアップロードの実装と躓いたところまとめ

業務でも自習でも初めてファイルアップロード機能を手を動かして実装してみたので手順をまとめておこうと思います。
実装中に躓いた箇所があったのでその対応方法も記載します。

動作環境について

OS:macOS High Sierra
version: 10.13.6
Docker(Engine):18.09.1

対象ブラウザ

GoogleChrome:72以上

環境

centOS:7.5
Laravel:5.6
PHP:7.2
MySQL:5.7
PostgreSQL:10.6(MySQLから変更しました。)
APache2.4

参考資料

Laravelで画像ファイルアップロードをする簡単なサンプル
【Laravel5.6】画像ファイルアップロードについてのポイントまとめ
Laravelのバリデーションで指定できる内容をざっくりまとめ直しました。

画面構成について

全然スマートな画面じゃなくて恐縮ですが・・・。
管理画面にある各商品情報の右に「画像」ボタンを配置しています。

スクリーンショット 2019-02-11 12.04.58.png

「画像」ボタンを押下するとファイルアップロードのモーダルが表示されます。

スクリーンショット 2019-02-11 12.05.18.png

アップロードに成功するとTOPページに各商品ごとの画像が表示される様になります。
*「-------」となっている商品はまだ画像のアップロードを行っていないことを示しています。

スクリーンショット 2019-02-11 12.07.58.png

下記では、この上記画像の動作を実現する方法をまとめています。

View

モーダルのformタグ内は下記の通りになっています。
name属性が「select_id」のinputタグは「画像」ボタン押下時にjavascriptでvalueが入る様になっています。

<form method="POST" action="{{ route('admin_upload_image') }}" enctype='multipart/form-data'>
    {{ csrf_field() }}
    <input type="hidden" name="select_id" value="">

    <div class="form-group row">
        <label for="goods_image" class="col-md-3 col-form-label text-md-left">{{ __('イメージ') }}</label>

        <div class="col-md-7">
            <input type="file" name="goods_image" value="" style="border:none;" >
            <small class="input_condidion">*jpg,png形式のみ</small></br>
            <small class="input_condidion">*最小画像サイズ:縦横100px</small></br>
            <small class="input_condidion">*最大画像サイズ:縦横600px</small>

            @if ($errors->has('goods_image'))
                <span class="invalid-feedback" role="alert">
                    <strong>{{ $errors->first('goods_image') }}</strong>
                </span>
            @endif
        </div>
    </div>

    <div class="col-md-offset-3 text-center">
        <button type="button" class="btn btn-primary" data-dismiss="modal">閉じる</button>
        <input type="submit" class="btn btn-success" value="登録">
    </div>
</form>

ルーティング

web.phpに下記の通りに記載しています。

Route::group(['prefix' => 'admin'], function(){
.
.
.
    Route::post('goods/upload', 'Admin\HomeController@uploadGoodsImage')->name('admin_upload_image');
});

Controller

Controllerの処理の前にバリデーションファイルを別途用意する予定でしたが、後述の躓いた箇所の影響もあり、他の人が書いてくださった内容に習わせて頂きました。
拡張子の指定が「mimes」、画像サイズの指定が「dimensions」をキーとして詳細を指定しています。

・画像の格納先を指定するstoreAs()について
⇨第1引数:保存するディレクトリ名,第2引数:アップロードするファイル名,第3引数:disksのドライバ名(config/filesystems.phpに記載)となっています。
今回の場合はgoodsディレクトリの中に各商品IDのディレクトリを作成し、その中にアップロードした時の同様のファイル名で格納する様にパラメーターを変数で指定しています。
第3引数は特に変更がなければ「public」のままで良いと思います。
変更する場合は「config/filesystems.php」を編集する必要があります。

public function uploadGoodsImage(Request $request)
{
    // 選択した商品IDの取得
    $select_id = $request->input('select_id');
    // アップロードしたファイル名を取得
    $upload_name = $_FILES['goods_image']['name'];

    // アップロードするディレクトリ名を指定
    $up_dir = 'goods/' . $select_id;

    // アップロードしたファイルのバリデーション設定
    $this->validate($request, [
        'goods_image' => [
            'required',
            'file',
            'image',
            'mimes:jpeg,png',
            'dimensions:min_width=100,min_height=100,max_width=600,max_height=600',
        ]
    ]);

    //アップロードに成功しているか確認
    if ($request->file('goods_image')->isValid([])) {
        $filename = $request->file('goods_image')->storeAs($up_dir, $upload_name, 'public');

        // DBへファイル名登録処理
        $goods = \App\Models\Goods::findOrFail($select_id);
        // $filenameだとパスが含まれてしまう為、basename()で囲う
        $goods->image_name = basename($filename);
        // 更新(差分があればDBに登録)
        $goods->save();

        return redirect()->to('admin/home')->with('flashmessage', 'イメージ画像の登録が完了しました。');
    }
    else{
        return redirect()->to('admin/home')->with('flashmessage', 'イメージ画像の登録に失敗しました。');
    }
}

シンボリックリンクの作成

下記コマンドで public/storage から storage/app/public にシンボリックリンクを貼ること出来ます。

[root@87c2be02241a shop]# php artisan storage:link
The [public/storage] directory has been linked.

画像アップロードの確認

各商品のIDを格納先として画像が保存されていることが確認出来ます。

[root@87c2be02241a shop]# ls public/storage/goods/4
sample_goods.png
[root@87c2be02241a shop]# ls storage/app/public/goods/4
sample_goods.png

アップロードするファイルを表示させる時

各商品の画像名を取得して、nullでは無い場合はURLを指定して表示させています。

@if($goods->image_name)
    <img src="{{ asset('storage/goods/' . $goods->id . '/' . $goods->image_name) }}" width="40" height="40" alt="no_goods_image" />
@else
    <p>--------</p>
@endif

躓いたところ

アップロードするとhome画面にリダイレクトしてしまう不具合が発生。
バリデーションで何かミスかなと調べてみました。

Controller部分内でdd()を使ってファイルが取得出来ているかを確認してみると、ファイルを取得出来ていませんでしrた。

本来下記の形でファイルを取得出来るのですが、nullになるばかり。$_FILESを確認してもアップロードされたファイルが無い状態でした。

$file = $request->file('goods_image');
dd($file)

調べていく中でformタグに「enctype」属性が抜けていたのを気づいたので下記の通り追記してみたのですが、これもだめでした。

enctype="multipart/form-data"

php.iniの設定が悪いのかと思い確認してみました。
ファイルアップロード関連で関係のありそうなのは下記の設定ですが確認してみるとアップロードしているファイルのサイズ的には問題無さそうでした。

upload_max_filesize = 10M
file_uploads = On
max_file_uploads = 20
post_max_size = 8M

⇨念の為「post_max_size」と「upload_max_filesize」の上限を上げてみたのですがこれも結局だめでした。

その後調べを進めてみるとやはり「enctype="multipart/form-data"」が記載されていないのが原因とする記述が多かった為、もしかしてブラウザ上では表示されていないのかなと思いデベロッパーツールで確認してみると、原因がわかりました。

「enctype="multipart/form-data"」と表示されるべきところが下記の様に表示されていました。

enctype=""multipart/form-data""

そこでviewファイルにて「enctype='multipart/form-data'」と書き直したところ、無事ファイルアップロードが出来ました。

後日改めてダブルクォーテーションで囲ってみたらブラウザでも「enctype="multipart/form-data"」と表示されていました。
viewファイルの構成を考えながら作っていた為、viewファイルのどこかで記述がミスがあったと思われます。
viewとファイルアップロードを同時平行で作っていたのがアダとなった形です。

取り急ぎでファイルアップロードの機能を試したい時に正常に動かない場合、上記対応で動かせることがわかりました。

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

【Laravel】実行されたSQLを取得する

実行されたSQLを出力します。
SQLだけでなく、プリペアドステートメントや実行時間も出力されるので便利です。

Laravel 5.0 データベースの基本的な使用法

ログの出力

// ログを有効化
DB::enableQueryLog();

City::where('Name', '=', 'Kabul')->get();

// ログ出力
dd(DB::getQueryLog());

// ログを無効化
DB::disableQueryLog();

出力結果

array:1 [
  0 => array:3 [
    "query" => "select * from `city` where `Name` = ?"
    "bindings" => array:1 [
      0 => "Kabul"
    ]
    "time" => 6.46
  ]
]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelのDIでサービスコンテナを使って環境ごとにクラスを使いわける

開発環境の時はslackにさせたい(orさせたくない)とか、動作確認を簡単にするために艦初環境ではバリデーションをゆるくしたいなど、環境ごとに処理を分けたいことがあると思います。
直接コードの中に環境ごとの分岐を書くこともできるのですが、テスタブルではなくなるので、外からクラスを渡せるようにコンストラクターインジェクションを行い、環境に応じたクラスを使い分ける方法とテストコードについて書きます。

環境ごとに使いたいクラスを用意する

今回はシンプルにproductionの処理とそれ以外の環境での処理を分けるようにします。処理の内容は環境ごとに違う文字列を返すだけです。

production用クラス

Services/Message.php
<?php

namespace App\Services;

class Message
{
    public function makeMessage()
    {
        return 'message';
    }
}

その他用のクラス

先ほどのクラスを継承させて、開発環境などで使われるfakeのクラスを作成しました。

Services/FakeMessage.php
<?php

namespace App\Services;

class FakeMessage extends Message
{
    public function makeMessage()
    {
        return 'fake message';
    }
}

実際には通知先を変えるとか特定の処理を行わないとかもう少しこのクラス内でやることが変わるはずですがシンプルに。

呼び出し元

コンストラクタの引数にMessageクラスを渡せるようにしておきます。

Services/Notification.php
<?php

namespace App\Services;

class Notification
{
    private $messageService;

    // インスタンス生成時にMessageクラスを渡せるようにする
    public function __construct(Message $messageService)
    {
        $this->messageService = $messageService;
    }

    public function send()
    {
        // どこかに通知をしたとする
        return $this->messageService->makeMessage();
    }
}

サービスコンテナに追加をする

環境ごとにクラスを使い分けたいので、サービスコンテナに記載します。
どのクラスを使うかは、configファイルから取得をします。

元のクラスがMessgeクラスでそれを継承しているクラスがFakeMessageなので、デフォルトではMessageクラスを使用して、使うクラスが指定されている場合のみそのクラスを使うようにします。

app/Providers/AppServiceProvider.php
public function register() {
    if (!$messageClass = config('app.message')) {
        // configで指定されていないので、Messageクラスを使う
        $this->app->bind("App\\Services\\Message", "App\\Services\\Message");
    } else {
        // Messageクラスの代わりにconfigで指定されたクラスを使う
        $this->app->bind("App\\Services\\Message", "App\\Services\\$messageClass");
    }
}

こちらの部分で、configディレクトリapp.php のkeyがmessage の値を取得しています。

config('app.message')

config

.envファイルから値を取得します。

config.app.php
'message' => env('MESSAGE_CLASS', ''),

下記envファイルからその環境で使うクラス名を指定します。(localやstagingなども同様に)

env.testing
MESSAGE_CLASS=FakeMessage

ここまでで環境ごとに使い分けられるようになりました。
各環境ごとにクラスを分ける場合にはenvファイルに追加すれば環境ごとに変えられます。

テストコード

そのまま使用をするとtestingの環境として実行されるため、本番環境で動くコードのテストが行えません。
そのためコンストラクタインジェクションで本番環境で実行されるクラスを渡すようにします。

test/Unit/NotificationTest.php
<?php

namespace Tests\Unit;

use App\Services\Message;
use App\Services\Notification;
use Tests\TestCase;

class NotificationTest extends TestCase
{
    public function testNotification()
    {
        // FakeMessageではなくMessageクラスを使用する
        $notification = new Notification(new Message());
        $this->assertEquals('message', $notification->send());
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】既存テーブルのマイグレーションファイルを作成する

Laravelで既存のテーブルを使用したい場合は、マイグレーションファイルを自分で用意する必要があります。

それを自動化するパッケージがあったので、ご紹介します。

使用パッケージ

migrations-generatorというパッケージを利用します。

migrations-generator

参考記事です。

Laravelで既存のDBからmigrationsファイルを作成する「migrations-generator」

開発環境

  • PHP 7.3.2
  • Laravel 5.7.25
  • Composer 1.8.3

手順

マイグレーションファイルの生成

worldデータベースにある下記テーブルのマイグレーションファイルを生成します。

  • city
  • country
  • countrylanguage

手順はREADMEに書かれています。
その通りに実行します。

$ composer require --dev "xethron/migrations-generator"

Laravel既存のテーブルusers, password_resetsを除いて、マイグレーションファイルを生成します。

$ php artisan migrate:generate --ignore="users, password_resets"

# 省略

 Do you want to log these migrations in the migrations table? [Y/n] :
 > Y

Migration table created successfully.

 Next Batch Number is: 1. We recommend using Batch Number 0 so that it becomes the "first" migration [Default: 0] :
 > 0

# 省略

これで、以下のマイグレーションファイルが生成されました。合わせて外部キーのマイグレーションファイルも生成されています。

  • 2019_02_10_224508_create_city_table.php
  • 2019_02_10_224508_create_country_table.php
  • 2019_02_10_224508_create_countrylanguage_table.php
  • 2019_02_10_224509_add_foreign_keys_to_city_table.php
  • 2019_02_10_224509_add_foreign_keys_to_countrylanguage_table.php

Modelの設定

試しにcityテーブルを扱うCityモデルを作成します。

$ php artisan make:model City

テーブル名が「city」のため、Modelにテーブル名を明示する必要があります。
以下、公式サイトからの引用です。

他の名前を明示的に指定しない限り、クラス名を複数形の「スネークケース」にしたものが、テーブル名として使用されます。

参考記事です。

Laravelで「Base table or view not found: 1146 Table」エラーが出るときの対処法

City.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class City extends Model
{
    protected $table = 'city';
}

これでテーブルが使用できるようになりました!

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

【Laravel】allメソッドを使うとtoSqlメソッドが使えない

クエリビルダを使用すると、toSqlメソッドで実行されるSQLを取得することができます。

しかし、City::all()のようにallメソッドを使用した場合は、toSqlメソッドを使うことができません。

以下のエラーが出ます。

Method Illuminate\Database\Eloquent\Collection::toSql does not exist.

エラーメッセージの通りなのですが、原因を探ってみました。

allメソッドの場合

test.php
$sql_all = City::all();
var_dump(get_class($sql_all));
// エラー発生
var_dump($sql_all->toSql());

オブジェクトのクラス名を取得すると、Illuminate\Database\Eloquent\Collectionクラスが使用されていることがわかります。

addメソッド自身は、スーパークラスであるSupport\Collectionクラスに定義されています。

しかし、両クラスともtoSqlメソッドが定義されていません。
これが原因でした。

Illuminate\Support\Collection.php
/**
 * Get all of the items in the collection.
 *
 * @return array
 */
public function all()
{
    return $this->items;
}

さらに、getメソッドを使用した場合も同じエラーが出ます。

test.php
$sql_builder = DB::table('city')->get();
var_dump(get_class($sql_builder));
// エラー発生
var_dump($sql_builder->toSql());

上記のコードではEloquentを使用していないので、オブジェクトのクラス名はIlluminate\Support\Collectionになります。

エラーの理由は上記と同じです。

toSqlメソッドの場所

当のtoSqlメソッドが定義されているクラスは、Builderクラスになります。

Illuminate\Database\Query\Builder.php
/**
 * Get the SQL representation of the query.
 *
 * @return string
 */
public function toSql()
{
    return $this->grammar->compileSelect($this);
}

whereメソッドの場合

whereメソッドを使用する場合は、toSqlメソッドが使用できます。

オブジェクトのクラス名を確認すると、lluminate\Database\Eloquent\Builderクラスが使用されていると確認できます。

これはtoSqlメソッドが定義されているクラスと同じです。

test.php
$sql_where = City::where('Name', '=', 'Kabul');
var_dump(get_class($sql_where));
// 出力される
var_dump($sql_where->toSql());

コアファイルを読む良いきっかけになりました。

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

php-master-changes 2019-02-10

今日は PHP TestFest 2017 で追加された各種テストの取り込みと修正があった!

2019-02-10

flow-control: Added basic test for ZipArchive::unchangeIndex()

flow-control: Added basic test for ZipArchive::unchangeName()

mbniebergall: Add test for date_time_immutable invalid arguments

MarkBaker: Tests for __set_state magic method

petk: Fix failing readline() basic test

petk: Fix failing tests

guilliamxavier: Delete duplicate test file

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

PHPの無名関数って何?

無名関数は、関数名のない関数のことです。

無名関数はクロージャとも呼ばれ、 関数名を指定せずに関数を作成できるようにするものです。 コールバック パラメータとして使う際に便利ですが、用途はそれにとどまりません。
PHP: 無名関数 - Manual

PHPでは、「無名関数」「ラムダ関数」「匿名関数」が同じものを指す・・・らしい。

無名関数をコールバックで使うパターン

WhatMumeiKansu.php
<?php
namespace App;

/**
 * PHPの無名関数って何?.
 */
class WhatMumeiKansu
{
    /** @var string スネークケースの区切り文字. */
    const SNAKE_DELIMITER = '_';

    /*
     * パスカルケース文字列を大文字のスネークケース文字列へ変換する.
     * @param  array $pascals パスカルケース文字列.
     * @return array         大文字のスネークケース文字列.
     */
    public function convertStringToUpperSnakeCase(array $pascals): array
    {
        // 無名関数をコールバックで使うパターン.
        return array_map(function ($pascal) {
            $snake = preg_replace_callback('([A-Z])', function($matches) {
                return self::SNAKE_DELIMITER.$matches[0];
            }, $pascal);

            if (mb_substr($snake, 0, 1) === self::SNAKE_DELIMITER) {
                $snake = ltrim($snake, self::SNAKE_DELIMITER);
            }
            return strtoupper($snake);
        }, $pascals);
    }
}

$pascals = [
    'PonsukeTarou',
    'ponsukeTarou',
    'Ponsuketarou'
];
$what = new WhatMumeiKansu();
var_dump($what->convertStringToUpperSnakeCase($pascals));
$ php src/WhatMumeiKansu.php 
array(3) {
  [0]=>
  string(13) "PONSUKE_TAROU"
  [1]=>
  string(13) "PONSUKE_TAROU"
  [2]=>
  string(12) "PONSUKETAROU"

無名関数を変数に代入するパターン

WhatMumeiKansu.php
<?php
// 無名関数を変数に代入する.
$toPascalCase = function($snake)
{
    $lowerSnakeCase = strtolower($snake);
    $upperCamelCase = ucwords($lowerSnakeCase, '_');
    return str_replace('_', '', $upperCamelCase);
};

var_dump($toPascalCase('ponsuke_tarou'));

$snakeStrings = [
    'ponsuke_tarou',
    'PONSUKE_TAROU',
    'poNSUKE_TARou'
];

// 無名関数を代入した変数をコールバックで使う.
var_dump(array_map($toPascalCase, $snakeStrings));
$ php WhatMumeiKansu.php 
string(12) "PonsukeTarou"
array(3) {
  [0]=>
  string(12) "PonsukeTarou"
  [1]=>
  string(12) "PonsukeTarou"
  [2]=>
  string(12) "PonsukeTarou"
}

class内で無名関数をプロパティに代入するとFatal error: Constant expression contains invalid operationsになります。

WhatMumeiKansu.php
<?php
/**
 * PHPの無名関数って何?.
 */
class WhatMumeiKansu
{
    /** @var string スネークケースの区切り文字. */
    private const SNAKE_DELIMITER = '_';

    /** @var Closure $toPacalCas スネークケース文字列をパスカルケース文字列にする. */
    $toPascalCase = function($snake)
    {
        // 無名関数を変数に代入するパターン
        $lowerSnakeCase = strtolower($snake);
        $upperCamelCase = ucwords($lowerSnakeCase, self::SNAKE_DELIMITER);
        return str_replace(self::SNAKE_DELIMITER, '', $upperCamelCase);
    };
}

$what = new WhatMumeiKansu();
var_dump($what->toPascalCase('ponsuke_tarou'));
$ php WhatMumeiKansu.php 
PHP Fatal error: Constant expression contains invalid operations in /path/to/WhatMumeiKansu.php on line 11

Fatal error: Constant expression contains invalid operations in /path/to/WhatMumeiKansu.php on line 11

原因は、クラスのプロパティとメソッドは別々の名前空間にいるからです。

プロパティとメソッド
クラスのプロパティとメソッドは、それぞれ別の名前空間に存在するので、 同じ名前のプロパティとメソッドを共存させることもできます。 プロパティを参照する場合もメソッドを参照する場合も書きかたは同じです。 それがプロパティへのアクセスなのかメソッドの呼び出しなのかは、そのコンテキストによって決まります。 つまり、変数にアクセスしようとしているのか関数を呼び出そうとしているのかの違いです。
これはつまり、プロパティに 無名関数 を代入した場合に、その関数は直接呼び出せないということです。 その場合は、たとえば事前にプロパティを変数に代入しておく必要があります。
PHP: クラスの基礎 - Manual

class内で無名関数をプロパティに代入する場合はコンストラクタで代入します。

WhatMumeiKansu.php
<?php
namespace App;

/**
 * PHPの無名関数って何?.
 */
class WhatMumeiKansu
{
    /** @var string スネークケースの区切り文字. */
    private const SNAKE_DELIMITER = '_';

    /** @var Closure $toPacalCas スネークケース文字列をパスカルケース文字列にする. */
    public $toPascalCase;

    /**
     * コンストラクタ.
     */
    public function __construct()
    {
        // コンストラクタでプロパティに無名関数を代入する.
        $this->toPascalCase = function($snake)
        {
            // 無名関数を変数に代入するパターン
            $lowerSnakeCase = strtolower($snake);
            $upperCamelCase = ucwords($lowerSnakeCase, self::SNAKE_DELIMITER);
            return str_replace(self::SNAKE_DELIMITER, '', $upperCamelCase);
        };
    }

    /**
     * スネークケース文字列の配列をパスカルケース文字列の配列へ変換する.
     * @param  array  $snakes スネークケース文字列の配列.
     * @return array          パスカルケース文字列の配列.
     */
    function convertStringsToPascalCase(array $snakes): array
    {
        // 無名関数を代入した変数をコールバックで使うパターン.
        return array_map($this->toPascalCase, $snakes);
    }

    /*
     * パスカルケース文字列を大文字のスネークケース文字列へ変換する.
     * @param  array $pascals パスカルケース文字列.
     * @return array         大文字のスネークケース文字列.
     */
    public function convertStringToUpperSnakeCase(array $pascals): array
    {
        // 無名関数をコールバックで使うパターン.
        return array_map(function ($pascal) {
            $snake = preg_replace_callback('([A-Z])', function($matches) {
                return self::SNAKE_DELIMITER.$matches[0];
            }, $pascal);

            if (mb_substr($snake, 0, 1) === self::SNAKE_DELIMITER) {
                $snake = ltrim($snake, self::SNAKE_DELIMITER);
            }
            return strtoupper($snake);
        }, $pascals);
    }
}

$what = new WhatMumeiKansu();

var_dump(($what->toPascalCase)('ponsuke_tarou'));

$pascals = [
    'PonsukeTarou',
    'ponsukeTarou',
    'Ponsuketarou'
];

var_dump(
    $what->convertStringsToPascalCase(
        $what->convertStringToUpperSnakeCase($pascals)
    )
);
$ php WhatMumeiKansu.php 
string(12) "PonsukeTarou"
array(3) {
  [0]=>
  string(12) "PonsukeTarou"
  [1]=>
  string(12) "PonsukeTarou"
  [2]=>
  string(12) "Ponsuketarou"
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む