カテゴリーアーカイブ 言語

著者:杉浦

PHPDocの内容を継承する@inheritdoc

Inheritance — phpDocumentor
 @inheritdocは継承元(implements元やextends元やtrait元)のPHPDocの説明を継承するタグです。@inheritdocを使うと次の様に継承元のPHPDocの説明文を受け継げます。
 
 元の振る舞いと継承後の振る舞いに大した違いが無い場合、同じ説明を記述することは面倒です。@inheritdocを使うことで何度も同じ記述を行わず済み、楽が出来ます。
 @inheritdocは継承元の説明をインラインに埋め込むコメントとして扱えます。冒頭の説明文の部分に関しては次の様にけっこう自由がききます。

  • この記事いいね! (0)
asaba 著者:asaba

【cordova-react】初期値がundefinedで警告受けた話

componentDidMount()内で値を受け取る処理の途中でWarning: `value` prop on `input` should not be null.という警告を

もらいました。これは、value内の値はnullで受け取ってはいけません、必ず空の状態で設定してください。

という意味になります。

componentDidmount()は、マウントされる際に一回だけ実行されます。筆者は前ページに戻った時に値を受け取る処理を作ったのですが

本来ならば空の状態でrenderされるにも関わらずその時に前ページから判別不能な値nullを既に受け取った状態で

コンポーネントを生成したので警告を受けたのだと思われます。

  componentDidMount() {
    // 前ページから受け取った値をsetStateしている
    const getName = window.localStorage.getItem('nameKey');
    
    this.setState({name: getName});

}

下のコンストラクタでnameを初期化していましたが、さきほどの関数内で先行してnullの値をsetStateしてしまっているので

これでは怒られる訳ですね・・・

 


constructor(props) {
    super(props);
    // 画面初期表示時の状態(state)を読み込む為のキャンセル可能なプロミス(Promise)を初期化する
this.state = {
      name: '',
    }
}

どうしてもコードを変えずに回避したい場合はinputタグ内でvalue = {this.state.name || ”}と書けば解決できます。

 

 名前<input type = "text" value = {this.state.name || ''} onChange = {this.handleNameCodeChange}></input>

参考にさせていただいたサイト→https://github.com/mozilla-services/react-jsonschema-form/issues/336

  • この記事いいね! (0)
村上 著者:村上

【React】onClickが呼び出されたときに任意の値の引数を渡す

React の書き方に未だに慣れていないところがあるので、まとめ。
今回は、onClick で呼び出した関数に、任意の引数を渡す方法です。

参考にさせていただいた記事はこちらから。

【React】イベントハンドラで引数を使いたい【備忘録】 – Qiita
https://qiita.com/tsuuuuu_san/items/73747c8b6e6e28f6bd23

 

上記の記事内でも書かれていますが、Reactの場合、下記のように書いても動きません。

sample(num) {
    // 行いたい処理
}

render() {
    return (
        <div>
            <button onClick={this.sample(100)}>ボタン</button>
        </div>
    );
}

記事によると、引数は渡せたものの、画面描画のたびに押していないはずのボタンの関数が実行されたとのことです。

で、解決策としては、下記のような書き方があるとのこと。
一つ目がこちら。

<button onClick={ () => this.sample(100) }>ボタン</button>

しかし、上記の方法だと、描画のたびに関数を作成することになるため、あまり良くない書き方だそうです。

二つ目がこちら。

<button onClick={ this.sample.bind(this, 100) }>ボタン</button>

何故動くのかは分かりませんが、とにかく動きました、とのこと。
引数が一つであればすっきりとしているので、個人的には好きな書き方ですね。
ですが、やはり何故動くかわからないものを使うのは少々怖いので、使用は見合わせかな。

三つ目がこちら。

sample(e) {
    console.log(e.currentTarget.getAttribute('data-num'));  // 100
}

render() {
    return (
        <div>
            <button onClick={this.sample} data-num="100">ボタン</button>
        </div>
    );
}

こちらでは、HTML5 から導入された、カスタムデータ属性を使用しています。
これは無理矢理感がなくて一番きれいかな、と思いますね。
ということで、今後は3番目のカスタムデータ属性を利用しようと思います。

 

以上、Reactで関数に引数を渡す方法でした。
と言うか、いい加減にReactの書き方に慣れたい…。頑張ります。

  • この記事いいね! (0)
著者:杉浦

PHPの引数順と最初の開発者のインタビュー

 PHPStormには次の画像の様な機能、呼び出し先の関数の引数名を表示するという機能が備わっています。

 ことPHPにおいてこの機能は非常に役立ってくれています。というのもPHPに備わっている関数の引数はその順番と役割が関数によって変わることがしばしばあるためです。例えば、array_filter,array_map,array_walkという関数があります。これらはコールバックを配列に適用する関数です。これらをPHPStorm上で呼び出すと次の様な画面が見えます。

 各引数の名前で察する通り、array_mapのみcallbackを第一引数で指定する必要があります。これはいささか極端な例ですが、同じように似た役割、挙動の関数において引数の順番と役割が異なるということが起こることがあります。このため生のPHPを記述するためにはたびたびリファレンスなりPHPDocなりの何かを参照する必要があります。
 この関数の引数の順番のようなPHPの整合性についてPHPの生みの親であるラスマス・ラードフ氏は次のように述べています。
PHPの生みの親,ラスマス・ラードフ氏インタビュー:レポート|gihyo.jp … 技術評論社

私たちがPHPの整合性のなさを直さないと言ってよく非難する人がいますが,PHPはそもそもそれが問題になるようなものではないのです。PHPは結局,ライブラリやその他基盤となっているテクノロジーへのショートカットにすぎません。それなのに,どうして誰もがPHPレベルでの整合性を求めるのか,私には分かりません。整合性をとるのはフレームワークの役割です。フレームワークは問題を解決するための全体的なアプローチを定める場所ですから。PHPはその下のレベルにあって,ただ低レベルにあるライブラリとか関数とかへのアクセスを提供するだけの存在です。

 この発言の前にはPHPよりも下位層の関数と1対1で対応した何らかの関数をPHPは持っている、PHPは垂直的に整合性を持っている、という趣旨の発言があります。PHPは中間言語に近いもので更に上級言語のフレームワークを使えと言っているわけです。最近自分はLaravelばかり触っていますが、実際生のPHPに比べて格段に書きやすくシンプルにまとまっています。

  • この記事いいね! (0)
村上 著者:村上

【HTML】様々な形式のコンテンツを埋め込めるobject要素

実際に使うかは分かりませんが、便利そうなので自分のための備忘録としてまとめ。
外部リソースをページに埋め込めるobject要素についてです。

参考にさせていただいたサイトはこちらから。

HTML5/埋め込み/外部リソースを埋め込む – TAG index
https://www.tagindex.com/html5/embed/object.html

 

こちらの要素は下記のように使います。

<object data="[埋め込みたいデータのURL]" type="[データのMIMEタイプ]"></object>

必須項目はこれだけ。
なお、data属性とtype属性は、どちらか1つは必ず指定しなければいけないとのことです。

また、下記のように複数の param を指定することもできます。

<object data="example.swf" type="application/x-shockwave-flash" width="300" height="150">
    <param name="movie" value="example.swf">
    <param name="quality" value="high">
    <param name="bgcolor" value="#ffffff">
</object>

こちらの object要素の属性には typemustmatch というものがあり、こちらを指定した場合、data 属性で指定したコンテンツと type 属性で指定したMIMEタイプが一致する必要があります。
コンテンツを厳密に指定したい場合は、こちらを使うと良さそうですね。

 

なお、参考にさせていただいたサイトでは、他の要素との比較についての記載もありました。
画像やHTMLを埋め込む場合は、それぞれ img要素ifreme要素 を使った方が良いとのこと。
対して、動画・音声を埋め込む場合は、video要素audio要素 は利用できるファイル形式が限られていますが、object要素は、それよりも多くのファイル形式を埋め込むことが可能らしいです。
video要素 は以前紹介しましたが、再生するファイル形式によっては object要素を検討してもいいかもしれませんね。

 

以上、object要素についての簡単なまとめでした。

  • この記事いいね! (0)
asaba 著者:asaba

【cordova-react】値を動的に次ページに渡す方法

axiosなどの非同期通信を絡めた開発をしているとどうしても単純な画面遷移のことを忘れそうになってしまいます。

ただ単純に遷移だけするならば this.props.history.push({pathname: ‘/next’)}でいけますが、値をもって遷移だと始めたばかりの方は

?となってしまいがちですよね。基礎中の基礎なのでネットにもたくさん情報がありますが、コードには個人差があるのでどうしても

どれを参考にしたらいいか分からない、長くて知らない文法も書かれているから今の自分には理解し難いなど頭を抱えてしまうことも

多いと思います。自分も辛酸を嘗めてきた身ですので、ここでは可能な限り簡潔に書きまとめて同じ悩みを抱えてる方の助けに

なればいいなと思っています。分かりにくかったらごめんなさい。

 

とりあえず値をもって遷移させるコードがこちらです。↓


main.js

this.props.history.push({pathname: '/next', state: { name: this.state.name }});

 

現在の値であるstateを引数にして飛ばしています。これだけで次のページで値nameを扱うことができます。

 

めっちゃ簡単ですね。明解ですね。じゃあ次のページではどうやって受け取るの?ってなった時はこちら↓


next.js
constructor(props) {
    super(props);
    this.state = {
      name: this.props.location.state.name,
    }
}

this.props.location.state.nameとは、タグに格納されたname(値を)意味しています。つまり、前ページでタグで受け取った

値nameをthis.stateのnameキーに値として登録しています。

コンストラクタ内でconsole.log(prop)すると、locationタグの中にしっかりとnameの値が入っており

これで取ってきているのが確認できます。

これでnext.js内のrender(){}内で

{this.state.name}

と定義すればnameの値を表示させることができます。

ざっくりでしたがどうでしょうか。これがすらすら書けるようになれば初級者も卒業できて次のタスクも見えてくると思います。

  • この記事いいね! (0)
著者:杉浦

Chromeブラウザ上でJSONを楽にわかりやすく見るJSON Viewer

 JSON Viewer – Chrome ウェブストア
tulios/json-viewer: It is a Chrome extension for printing JSON and JSONP.
 JSON ViewerはGoogle Chromeの拡張の一つでChrome上でJSONを整形して色付けして見せてくれます。これを利用することで簡単にJSONで送られてきたデータを視認できます。
 特に威力を発揮するのは次の様な圧縮されたJSONです。何が何だか分からないですし、単に黒一色で整形しただけではまだ読みにくいです。

 上のJSONをJSON Viewerを通してみた結果が次です。ずいぶん縦長ですが読みやすくなりました。

 階層構造のデータを読むときにあるとないとで全然違う、任意のデータの塊を広げる畳むの機能も備えています。この機能は図の赤丸部から動作します。

 これで長大なデータの中腹や末尾付近にある目的の項目も楽に探せます。開発者ツールでいちいち開いたり、どこかのサービスやエディタにコピペ、整形とするよりずいぶん楽になります。

  • この記事いいね! (0)
takahashi 著者:takahashi

Laravel環境をインポートしたときに”artisan package:discover handling the post-autoload-dump event returned with error code 1″エラーが出た時に確認したいこと

いろいろあって、開発中のLaravel環境をgit経由で再インポートしたのですが、再度npm installしてからcomposer installしたところ、こんなエラーが発生しました。

Script @php artisan package:discover handling the post-autoload-dump event returned with error code 1

エラーで調べるとこんな記事が。

[Laravel] プロダクション環境にはLaravel Duskをインストールしない – 端くれプログラマの備忘録

Laravel Duskはブラウザでの自動テストAPIを提供するプラグインで、製品版(production)モードではセキュリティ上の理由で無効化しなければいけないため、productionモードで有効化されているとエラーになります。

記事の通りにcomposer.jsonを確認すると

...
"require": {
        "php": "^7.1.3",
        "ext-json": "*",
        "fideloper/proxy": "^4.0",
        "intervention/image": "^2.4",
        "lampager/lampager-laravel": "^0.3.0",
        "laravel/framework": "5.6.*",
        "laravel/tinker": "^1.0",
        "league/flysystem-aws-s3-v3": "^1.0",
        "maatwebsite/excel": "^3.1",
        "simplesoftwareio/simple-qrcode": "^2.0"
    },
    "require-dev": {
        "beyondcode/laravel-dump-server": "^1.0",
        "filp/whoops": "^2.0",
        "friendsofphp/php-cs-fixer": "^2.13",
        "fzaninotto/faker": "^1.4",
        "laravel/dusk": "^4.0",
        "mockery/mockery": "^1.0",
        "nunomaduro/collision": "^2.0",
        "phpunit/phpunit": "^7.0",
        "squizlabs/php_codesniffer": "^3.3"
    },
...

あれ、含まれてない(汗

ちゃんとrequire-devにしか”laravel/dusk”の項目は入っていません。
もしやと思ってcomposer.lockの方を確認すると…

...
"name": "laravel/dusk",
            "version": "v4.0.2",
            "source": {
                "type": "git",
                "url": "https://github.com/laravel/dusk.git",
                "reference": "9810f8609c8b53d9a3bac7d38c56530e0d77a6bb"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/laravel/dusk/zipball/9810f8609c8b53d9a3bac7d38c56530e0d77a6bb",
                "reference": "9810f8609c8b53d9a3bac7d38c56530e0d77a6bb",
                "shasum": ""
            },
...

含まれていました。
composer installすると
composer.lock
の記述が優先されます。

今回の原因は、composer.lockにその記述が入っていることが原因か…
と思いましたが、ここでふと気づきます。

(まてよ、そもそも開発を始めるときにdevelopモードにしていたはずじゃなかったっけ…)

そもそも今回のエラーはproductionモードにしていなければ出ないはずのエラーなのですが、それにもかかわらず出てしまっているので、よく考えたらおかしな状況です。
そこで調べたところ、.envファイルが入っていないことに気づきました。

前に使っていたLaravelのプロジェクトから.envファイルを書き戻してみると、

composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: beyondcode/laravel-dump-server
Discovered Package: fideloper/proxy
Discovered Package: intervention/image
Discovered Package: lampager/lampager-laravel
Discovered Package: laravel/dusk
Discovered Package: laravel/tinker
Discovered Package: maatwebsite/excel
Discovered Package: nunomaduro/collision
Discovered Package: simplesoftwareio/simple-qrcode
Package manifest generated successfully.

となり、先ほどのDuskのエラーは出なくなりました。

.envファイル内の
APP_ENV
の設定が
APP_ENV=local
または
APP_ENV=development
になっていないと、自動でproductionモードとして動作してしまい、Duskの部分でエラーになるようです。

つまり開発の際は.envファイルに
APP_ENV=local
または
APP_ENV=development
を記述するのが必須になってきますので、最初にLaravel環境を展開したときは要注意です。

  • この記事いいね! (0)
村上 著者:村上

【HTML】Content-Security-Policyについての私的簡易まとめ【Cordova】

タイトル通り、本日の記事は私のための備忘録です。
たまに読み方が分からなくなり、どういう設定なのか解読できないことがあるので、その対策としてまとめ。

参考にさせていただいたサイトはこちら。

Cordova アプリの Content-Security-Policy 設定について – Corredor
http://neos21.hatenablog.com/entry/2017/12/27/080000

 

まず、「Content-Security-Policy」とは「クロスサイトスクリプティング (XSS) やデータインジェクション攻撃などのような、特定の種類の攻撃を検知し、影響を軽減するために追加できるセキュリティレイヤーです。」とのこと。
上記の参考サイトでは、「サーバサイドからクライアントサイドのブラウザに対して「このコンテンツはこういう範囲で扱っていいよ (それ以外の扱い方はしないでね)」というポリシーを伝えることで、クロスサイトスクリプティングなどの脆弱性攻撃を軽減するために設定する。」とありました。
こちらの説明の方が分かりやすいですね。

では早速簡易まとめ。
まず、default-srcです。
これは名前のとおり、基本的な設定を指定することができ、‘self’ は自身のホストを、* はすべてのホストへのアクセスが許容されます。
なお、Cordova の環境の場合、プラグインが動作するためには gap: プロトコルが必要とのことなので、必要に応じて gap: も追加します。

記述方法はそれ以外も同じで、style-srcimg-srcmedia-src など、それぞれ定義したい項目ごとに記述します。

ちなみに、私の環境では下記のような指定になっています。

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:; connect-src *;">

‘unsafe-inline’ はインラインのCSSやJavaScript を有効にするもので、これがないと CSS、JavaScript が有効にならないので追加します。

とりあえずは、このあたりまで分かっていれば基本的なところだけは大丈夫のはず…?
下記のサイトに記述例が記載されている箇所があるので、こちらも参考になります。

コンテンツセキュリティポリシー (CSP) – HTTP|MDN
https://developer.mozilla.org/ja/docs/Web/HTTP/CSP

 

以上、Content-Security-Policy についての簡易まとめでした。

  • この記事いいね! (0)
著者:杉浦

pythonの人間のためのHTTPライブラリRequests

 Requests: HTTP for Humans™ — Requests 2.20.1 documentation
 requests · PyPI
 Requestsは人間に優しいHTTP通信用ライブラリです。ちょっとしたリクエストをAPIに送る時などに便利です。次のコード例はbacklogの課題追加APIです。backlogの課題はまとめて追加することが多くいちいちUIで記述をするのは面倒です。APIでまとめて送ることで楽が出来ます。

import requests

BACKLOG_URL = "https://hogehoge.backlog.jp/api/v2/issues"
API_KEY = "hogehogefugafuga"
PROJECT_ID = 104607  # プロジェクトID
ISSUE_TYPE_ID = 485681  # 課題種別ID
CATEGORY_ID = 279257  # カテゴリID
PRIORITY_ID = 3  # 優先度
ASSIGNEE_ID = 251977  # ユーザID

request_data = [
    {
        'summary': '会員登録機能',
        'startDate': '2018-12-07',
        'endDate': '2018-12-08',
    }, {
        'summary': '会員削除機能',
        'startDate': '2018-12-08',
        'endDate': '2018-12-09',
    }
]
for data in request_data:
    BACKLOG_PARAMS = {
        'apiKey': API_KEY,
        'projectId': PROJECT_ID,
        'summary': data['summary'],
        'issueTypeId': ISSUE_TYPE_ID,
        'categoryId[]': CATEGORY_ID,
        'priorityId': PRIORITY_ID,
        'startDate': data['startDate'],
        'endDate': data['endDate'],
        'estimatedHours': 7,
        'assigneeId': ASSIGNEE_ID,
    }

    response = requests.post(BACKLOG_URL, params=BACKLOG_PARAMS)
    print(response)

 requetsでリクエストを送るのは簡単です。送信メソッド毎(get,post,put,patch,delete)のメソッドがrequests内に用意されており、それの引数に文字列のURLと辞書型のボディを渡すだけです。これだけの設定でファイルを実行するとリクエストが送られます。
 細かい設定、細かい結果の取得も簡単にできます。

>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
>>> r.status_code
200
>>> r.headers['content-type']
'application/json; charset=utf8'
>>> r.encoding
'utf-8'
>>> r.text
u'{"type":"User"...'
>>> r.json()
{u'private_gists': 419, u'total_private_repos': 77, ...}
  • この記事いいね! (0)