cakephp3 ads.txt 追加

色々と記事見たけどうまくいかなかったので、ここにメモ。 ルート直下に置け言われたけどフレームワークはやり方違うねんという事。

まずconfig/routes.phpのRouter::scope内に以下を追加

 $routes->connect('/ads.txt', ['controller' => 'Ads', 'action' => 'ads'] );

んで、それに一致するcontroller, templateを作成

templateのファイルにははgoogle.com, pub~hogehoge~をコピって controllerはこんな感じ(AdsControllerになると思う)

public function ads()                                      
    {                                    
        $this->viewBuilder()->layout('');
        $this->response = $this->response->withDisabledCache()->withType('text/plain');
    }                                                                                  

ヘッダーフッターあるとダメそうなので、layout('')に デフォがtext/htmlをwithTypeで指定している。

多分日本語の記事ってないよね~て、っかするほどの事でもないんだと思う 精進あるのみ!

数十個ある選択肢から複数登録でき、個別に数値を変更できる。選択肢を変更しても新しいデータは新規登録、重複したデータはそのまま、前回は選択で今回未選択のデータは削除にする場合の考え方。

題名がとてもわかりずらいのですが、 例えば月間で目標を10個指定できる機能があり、個別に日々の達成度や目標期間を設定出来る機能があるとします。

その後、一部目標を変更するときに新しい目標は追加し、今回も変わらない目標は達成度も期間もそのまま、前回は設定してあって今回は選ばれなかった目標は削除したいとします。

その実装に詰まってしまって先輩から聞いて出来た考え方としては、

1,tmp_flgのようなカラムを目標のテーブルに追加

2.追加変更をするときに全部のカラムにフラグを立てる。

3.重複すればフラグを折り、リクエストデータも削除。

4.一旦フラグが折れなかったレコードを削除(今回選択されなかった為。)

5.残ったリクエストデータから新規目標を検索追加。

以上の段階で実装することができました。

先輩もこれが完璧なやり方とは思っていなく、今後ももっと良いロジックの組み方があるのか模索していきます。

chart.jsのあれこれ プロパティ編

実務で使ってるchart.jsのメモとして残してます。

一応、こちらの続きです。

yan-nade.hatenablog.com 今回どんなデータを表すかというと、日次 週次 月次 で健康ポイントの変動をライングラフで表せるようにしています。 多次元配列としています。

    //横サイズ    
    var xAxisLabelMinWidth = 200;
    var width = myData[0].length*xAxisLabelMinWidth;
    document.getElementById('myLineChart').style.width = width + "px";

    var selectedIndex = 0;
    
    var ctx = document.getElementById("myLineChart");
    var myLineChart = new Chart(ctx, {
        type: 'line',
        data:
        {
            labels: myData[selectedIndex][0].labels,
            datasets: [{
                //凡例
                label: myData[selectedIndex][0].label,
                //数値
     data: myData[selectedIndex][0].data,
                borderColor: myData[selectedIndex][0].borderColor,
                backgroundColor: myData[selectedIndex][0].backgroundColor,
                pointBackgroundColor: myData[selectedIndex][0].pointBackgroundColor,
                //グラフの曲線を調整
                lineTension: myData[selectedIndex][0].lineTension,
                borderWidth: 1,
            },
            {
                label: myData[selectedIndex][1].label,
                data: myData[selectedIndex][1].data,
                borderColor: myData[selectedIndex][1].borderColor,
                backgroundColor: myData[selectedIndex][1].backgroundColor,
                pointBackgroundColor: myData[selectedIndex][1].pointBackgroundColor,
                lineTension: myData[selectedIndex][1].lineTension,
                borderWidth: 1,
            },
            {
                label: myData[selectedIndex][2].label,
                data: myData[selectedIndex][2].data,
                borderColor: myData[selectedIndex][2].borderColor,
                backgroundColor: myData[selectedIndex][2].backgroundColor,
                pointBackgroundColor: myData[selectedIndex][2].pointBackgroundColor,
                lineTension: myData[selectedIndex][2].lineTension,
                borderWidth: 1,
            },
            {
                label: myData[selectedIndex][3].label,
                data: myData[selectedIndex][3].data,
                borderColor: myData[selectedIndex][3].borderColor,
                backgroundColor: myData[selectedIndex][3].backgroundColor,
                pointBackgroundColor: myData[selectedIndex][3].pointBackgroundColor,
                lineTension: myData[selectedIndex][3].lineTension,
                borderWidth: 1,
            }],
        },
        options:
        {
            responsive: false,
            tooltips:
            {
                enabled: false,
                position: 'nearest',
                intersect: false,
                custom: customTooltips,
            },
            title:
            {
                display: false,
            },
                legend:
                {
                    position: 'bottom',
                    labels:
                    {
                        generateLabels: function(chart)
                        {
                            //ここで凡例の左詰めの操作してます
                            chart.legend.afterFit = function ()
                            {
                                var width = this.width;
                                this.lineWidths = this.lineWidths.map(() => this.width - 10);
                                this.options.labels.padding = 10;
                                this.options.labels.boxWidth = 55;
                            };
                            //mapで返してます。
                            return chart.data.datasets.map(function(dataset, i)
                            {
                                return{
                                    text: dataset.label,
                                    fillStyle: dataset.backgroundColor,
                                    hidden: dataset.hidden,
                                    lineCap: dataset.borderCapStyle,
                                    lineDash: dataset.borderDash,
                                    lineDashOffset: dataset.borderDashOffset,
                                    lineJoin: dataset.borderJoinStyle,
                                    lineWidth: dataset.borderWidth,
                                    strokeStyle: dataset.borderColor,
                                    lineWidth: dataset.borderWidth,
                                    strokeStyle: dataset.borderColor,
                                    pointStyle: dataset.pointStyle,
          //ここの記述が大事、ある記事でindexだけとかあるけどdatasetIndexにしないと他がうまく動いてくれなかったりする。
                                    datasetIndex: i
                                };
                            });
                        }
                    }
                },
                scales:
                {
                    yAxes:
                    [{
                        ticks:
                        {
                            suggestedMax: 100,
                            suggestedMin: 0,
                            stepSize: 10,
                            callback: function(value, index, values)
                            {
                                return value;
                            }
                        }
                    }]
                },
        }
    });
    //ここでグラフの切り替えです。公式にもありますがupdateで再描画します。
    document.getElementById("button-day")
        .addEventListener('click',
            function()
            {
                selectedIndex = 0;
                myLineChart.data.labels = myData[selectedIndex][0].labels;
                myLineChart.data.datasets[0].data = myData[selectedIndex][0].data;
                myLineChart.data.datasets[1].data = myData[selectedIndex][1].data;
                myLineChart.data.datasets[2].data = myData[selectedIndex][2].data;
                myLineChart.data.datasets[3].data = myData[selectedIndex][3].data;
                myLineChart.update();
            }
    );
    document.getElementById("button-month")
        .addEventListener('click',
            function()
            {
                selectedIndex =1;
                myLineChart.data.labels = myData[selectedIndex][0].labels;
                myLineChart.data.datasets[0].data = myData[selectedIndex][0].data;
                myLineChart.data.datasets[1].data = myData[selectedIndex][1].data;
                myLineChart.data.datasets[2].data = myData[selectedIndex][2].data;
                myLineChart.data.datasets[3].data = myData[selectedIndex][3].data;
                myLineChart.update();
            }
    );
    document.getElementById("button-year")
        .addEventListener('click',
            function()
            {
                selectedIndex = 2;
                myLineChart.data.labels = myData[selectedIndex][0].labels;
                myLineChart.data.datasets[0].data = myData[selectedIndex][0].data;
                myLineChart.data.datasets[1].data = myData[selectedIndex][1].data;
                myLineChart.data.datasets[2].data = myData[selectedIndex][2].data;
                myLineChart.data.datasets[3].data = myData[selectedIndex][3].data;
                myLineChart.update();
            }
    );
};

実際のデータはここに書けませんが、 これで グラフ表示 tooltipsから編集や削除へ遷移 切替と色々出来るようになりました。 深いところは日本語の記事がないので、そこはやっぱりもう外国語記事をあさるしかないですね。 値がどうなっているかは chart.data.datasetsのプロパティをデバックしてって見ていました。 けど今後はhighchartで実装していくようになると思うのでしばらくはchart.jsは触らなさそう

chart.jsのあれこれ tooltips編

この前に色々弄っていてある程度のカスタマイズが出来るようになりましたので、そのメモを残します。

でもがっつりカスタマイズやりたいのであれば、highchartsやamchartsでやったほうが良いですね。 非商用なら無償で使えるので、個人で試すのもありかも

ちなみに自分はまだエンジニア数ヶ月でJSもよくわかってないのにぶん投げられて四苦八苦してやりました泣
ではchart.jsに戻ります。

まずは作った全文から、だいぶ長くなります。 今回はtooltips編です

window.onload = function()
{
    var customTooltips = function(tooltipModel)
    {
        // ツールチップ要素
        var tooltipEl = document.getElementById('chartjs-tooltip');

        // 最初の表示時に要素を生成。
        if (!tooltipEl) {
            tooltipEl = document.createElement('div');
            tooltipEl.id = 'chartjs-tooltip';
            tooltipEl.innerHTML = "<table></table>"
            this._chart.canvas.parentNode.appendChild(tooltipEl);
        }

        if (tooltipModel.opacity === 0) {
            tooltipEl.style.opacity = 0;
            return;
        }

        tooltipEl.classList.remove('above', 'below', 'no-transform');
        if (tooltipModel.yAlign) {    
            tooltipEl.classList.add(tooltipModel.yAlign);        
        } 
        else{ 
             tooltipEl.classList.add('no-transform');     
        }   
        function getBody(bodyItem) { 
             return bodyItem.lines;      
        }  
       if (tooltipModel.body) { 
           var titleLines = tooltipModel.title || []; 
           var bodyLines = tooltipModel.body.map(getBody);       
           var innerHtml = '<thead>';    
           titleLines.forEach(function(title) {
               innerHtml += title;     
           });           
          innerHtml += '</thead><tbody>';      
            //削除ボタン用   ボタンを押したらその日のグラフを削除したいという要件があったため       
          var index = tooltipModel.dataPoints[0].index;       
          //削除ボタン用 タップした凡例文字が一致したら値付与     
           var vital_text = tooltipModel.body[0].lines; 
           var str = vital_text.toString();      
           if( str.match( /text1/ ) ) {
                text = 0;      
            }      
            else if( str.match( /text2/ ) )  { 
                text = 1;
            }
            else if( str.match( /text3/ ) ) {
                text = 2;
            }
            else if( str.match( /text4/ ) ) {
               text = 3;
            }

             window.tipDelete = function tipDelete(){
                var result = window.confirm('削除しても宜しいですか?');
                if ( result )
                {
                    myLineChart.data.datasets[text].data[index] =  0;
                    myLineChart.update();
                }
            }

            var dayStr = myLineChart.data.labels.toString();
            bodyLines.forEach(function(body, i) {
                var colors = tooltipModel.labelColors[i];
                var style = 'background:' + colors.backgroundColor;
                var span = '<span class="chartjs-tooltip-key" style="' + style + '"></span>';
                if( dayStr.match(/月/) || dayStr.match(/年/)) {
                    innerHtml += '<tr><td>' + span + body + '</td></tr>';
                }
                else {
                    innerHtml += '<tr><td>' + span + body + '</td></tr>'
                    + '<a href="/users/vital-transition/1/edit"><button id="tip-edit">' + '編集' +'</button</a>'
                    + '<button id="tip-delete" onClick="tipDelete()">' + '削除' + '</button>';
                }
            });
        }
        var tableRoot = tooltipEl.querySelector('table');
        tableRoot.innerHTML = innerHtml;
  //ここら辺はポイントクリック時のtooltipsの場所を指定してます。
        var positionY = this._chart.canvas.offsetTop;
        var positionX = this._chart.canvas.offsetLeft;
  
        tooltipEl.style.opacity = 1;    
        tooltipEl.style.top = positionY + (tooltipModel.caretY / 2) + 'px';
        tooltipModel._fontFamily;
        tooltipEl.style.fontSize = tooltipModel.fontSize;
        tooltipEl.style.fontStyle = tooltipModel._fontStyle;
        tooltipEl.style.padding = tooltipModel.yPadding + 'px ' + tooltipModel.xPadding + 'px';
};

基本的には公式に乗っているんですが、それでは対応できないこともやってあります。

わからない、ググってもそれっぽいのがない時はひたすらconsole.logで当たっているプロパティを探す感じですね!

ここで作ったtooltips用の関数をchart.jsでのインスタンスにあてていきます。

次はデータ編にいきます。