- 投稿日:2020-12-27T22:36:04+09:00
Synfony2 メソッド,フォーム,アノテーション チートシート
個人的なメモであります
コントローラーメソッド
メソッド名 説明 generateUrl() ルート名からURLを生成 forward( ) 指定した名前のコントローラーへ処理を引き渡しその結果を取得 redirect( ) 指定したURLヘHTTPリダイレクトするレスポンスを生成 redirectToRoute() リダイレクト先をルート名で指定してHTTPリダイレクトレスポンスを生成 addFlash( ) 種類と文字列を指定してflashメッセージを登録 isGranted( ) 指定したロールを現在の認証ユーザが保持しているかどうかをチェック denyAccessUnlessGranted( ) 指定したロールを現在の認証ユーザが保持していない場合アクセス拒否、レスポンスを例外としてスロー renderView( ) テンプレートをレンダリングしその結果を取得 render( ) テンプレートをレンダリングして、それが格納されたResponseオブジェクトを取得 stream( ) ストリーム機能を使ってテンプレートを遅延レンダリングするResponseオブジェクトを取得する createNotFoundException() Not Found のレスポンスを例外としてスロー CreateAccessDeniedException( ) アクセス拒否レスポンスを例外としてスロー createForm( ) FormTypeを指定してフォームオブジェクトを取得 createFormBuilder( ) FormBuilderオブジェクトを取得 getRequest() 現在のRequest オブジェクトを取得す getDoctrine( ) Doctrine のレジストリオブジェクトを取得 getUser( ) 現在の認証ユーザオブジェクトを取得 has( ) サービスコンテナのhas( ) メソッドを呼び出す get( ) サービスコンテナのget( ) メソッドを呼び出す getParameter( ) サービスコンテナのgetParameter( )メソッドを呼び出す IsCsrfTokenValid() CSRFトークンの有効性をチェック Twigテンプレートメソッド
メソッド名 説明 autoescape ブロックに対して個別にエスケープを設定 block 継承関係にあるテンプレートとブロックを共有する do {{...}}と同様に式の評価を行うが、出力はしない< embed 他のテンプレートファイルを埋め込む(include の機能に加えてextendsのようにブロック単位で上書き可能 extends 指定したテンプレートファイルの継承を宣言 filter ブロックに対して任意のフィルタを適用 flush 出力バッファをフラッシュする for ループ処理を実行する form マクロを読み込む(import の別記法) if 条件分岐を実行する import マクロを読み込む sandbox includeで読み込むテンプレートにサンドボックスモードを適用する set 変数に値を代入する include 指定したテンプレートファイルの内容を読み込む macro マクロ(再利用可能なテンプレート部品)を定義する spaceless HTMLタグ間の空白文字を削除(HTML内やテキスト内の空白文字ではない) use extendsを使用しているテンプレートにさらに他のテンプレーファイルからブロックを読み込む verbatim ブロック内をパースせず生テキストとして出力する 拡張タグ
メソッド名 説明 form_theme 指定したフォームに対してカスタマイズしたテーマをセットする trans 翻訳を適用して返す transchoice 選択肢に翻訳を適用して返す trans_default_domain 翻訳に利用するデフォルトのドメインを設定する stopwatch タグ内のコードの実行時間を計測してプロファイラに表示 Fromメソッド
メソッド名 説明 form フォーム全体をレンダリング form_start フォームの開始タグをレンダリング form_end フォームの終了タグをレンダリング form_label フォームの個別フィールドのラベルをレンダリング form_errors フォームのエラーをレンダリング form_widget フォームの個別フィールドのウィジェットをレンダリング form_row フォームの個別フィールド全体をレンダリング form_rest フォームでまだレンダリングされていないフィールドをすべてレンダリング form_enctype フォームのenctypeをレンダリング render Controller 関数と合わせて使い、指定したコントローラの結果をレンダリング render_esi renderと同様で、結果をESI機能で埋め込む controller コントローラを指定 asset 指定したパスに対応する、アセットのパスを返す asset_version アセットのバージョンを返す csrf_token CSRFトークンを生成して返す is_granted 認証ユーザのロールをチェック logout_path 設定されたログアウトパスを返す FormType
フォームタイプ 説明 text input type="text" textarea input type="textarea" input type="email" integer input type="integer" password input type="password" search input type="search" percent テキスト入力と%記号 choice radio, checkbox, select entity エンティティー覧の選択肢 (radio、checkbox、select) kanguage 言語オード一覧 (radio、checkbox、select) date 日付(単一テキスト、 複数テキスト、複数のselect、またはHTML5の日付ウィジェット) datetime 日時(単一テキスト、 複数テキスト、複数のselect、またはHTML5の日付ウィジェット) file ファイル(file) collection コレクションを扱う場合に利用するフィールド submit 送信ボタン(submit) DoctrineのQueryBuilderメソッド
メソッド名 説明 expr( ) クエリパーツを組み立てるExprオブジェクトを取得 getType( ) 現在のクエリの種類を取得 getEntityManager( ) 関連づけられているエンティティマネージャを取得 getState( ) クエリビルダの変更状態を取得 getDQL( ) 現在のクエリビルダの内容からDQL文を取得 getQuery( ) 現在のクエリビルダの内容からクエリオブジェクトを取得 getRootAlias( ) クエリの起点となっているエンティティのエイリアスを取得 setParameter( ) クエリのパラメータを設定する getParameter( ) 現在のクエリビルダに設定された特定のパラメータの値を取得 setMaxResults( ) 取得するレコードの件数を設定 getMaxResults( ) 取得するレコードの件数設定を取得 add( ) 種類を指定してクエリのパーツを追加 select( ) クエリで取得するエンティティを指定 distinct( ) DISTINCT(重複レコードを除外する)かどうかを設定 addSelect( ) クエリで取得するエンティティを追加 delete( ) DELETEクエリに設定 update( ) UPDATEクエリに設定 indexBy( ) コレクションのインデックスに利用するフィールドを指定して取得 join() クエリでJOINして取得するエンティティを指定 innerJoin( ) クエリでINNER JOINして取得するエンティティを指定 leftJoin( ) クエリでLEFT JOINして取得するエンティティを指定 set( ) 更新クエリで更新するフィールドと値を指定 where( ) クエリのWHERE句を指定 andWhere( ) クエリのWHERE句の条件をANDで追加 orWhere( ) クエリのWHERE句の条件をORで追加 groupBy( ) クエリの GROUP BY句の条件を指定 addGroupBy( ) クエリのGROUP BY句の条件を追加で指定 having( ) クエリのHAVING句の条件を指定 andHaving( ) クエリのHAVING句の条件をANDで追加 orderBy() クエリの結果の並び順を指定 addOrderBy( ) クエリの結果の並び順を追加で指定 getDQLpart( ) 現在のクエリビルダから指定した種類のDQLパーツを取得 resetDQLpart( ) 現在のクエリビルダから特定のDQLパーツをリセット アノテーション
アノテーション 説明 @ORM\Column クラスのプロパティをDBテーブルのカラムとマッピング @ORM\ColumnResult ネイティブSQLクエリの結果でスカラ値のマッピングを指定 @ORM\Cache キャッシュ方法を指定する @ORM\ChangeTrackingPolicy エンティティの変更追跡方法を指定する @ORM\DiscriminatorColumn Doctrine の継承を利用する場合の基底クラスで、サブクラスの識別名を保存するカラムを指定 @ORM\DiscriminatorMap Doctrine の継承を利用する場合の基底クラスで、サブクラスの識別名とエンティティクラス名との対応を指定 @ORM\Entity クラスをエンティティとして利用するよう指示 @ORM\EntityResult ネイティブSQLクエリの結果でエンティティへのマッピングを指定 @ORM\FieldResult ネイティブSQLクエリの結果でエンティティのフィールドへのマッピングを指定 @ORM\GeneratedValue エンティティのIDの生成方法を指定 @ORM\HasLifecycleCallbacks エンティティでライフサイクルコールバックを有効にする @ORM\Index エンティティの対応するテーブルで、DBのインデックス定義を指定 @ORM\ld エンティティの識別子となるプロパティを指定 @ORM\InheritanceType Doctrine の継承を利用する場合、継承の種類を指定 @ORM\JoinColumn 関連を持ったエンティティの取得時にJOINを使う @ORM\JoinColumns 複合キーの関連を持ったエンティティの取得時にJOINを使う @ORM\JoinTable 関連エンティティを使った関連先をJOINして取得する @ORM\ManyToOne 多対一の関連を指定 @ORM\ManyToMany 多対多の関連を指定 @ORM\MappedSuperclass Doctrine の継承を利用する場合、継承の親であることを指示 @ORM\NamedNativeQuery 名前付きのネイティブSQLクエリを定義 @ORM\OneToOne 一対一の関連を指定 @ORM\OneToMany 一対多の関連を指定 @ORM\OrderBy 多対多、一対多の関連先を取得するときの並び順を指定 @ORM\PostLoad ライフサイクルコールバックでエンティティを読み込んだあとに実行されるメソッドを指定 @ORM\PostPersist ライフサイクルコールバックでエンティティが初めてエンティティマネージャの管理下へ登録されたときに実行されるメソッドを指定 @ORM\PostRemove ライフサイクルコールバックでエンティティがエンティティマネージャから削除されたときに実行されるメソッドを指定 @ORM\PostUpdate ライフサイクルコールバックでエンティティの内容の更新が適用されたあとに実行されるメソッドを指定 @ORM\PrePersist ライフサイクルコールバックでエンティティが初めてエンティティマネージャの管理下へ登録される直前に実行されるメソッドを指定 @ORM\PreRemove ライフサイクルコールバックでエンティティがエンティティマネージャから削除される直前に実行されるメソッドを指定 @ORM\PreUpdate ライフサイクルコールバックで エンティティの内容の更新が適用される直前に実行されるメソッドを指定 @ORM\SequenceGenerator エンティティのIDの生成方法にSEQUENCEを指定している場合に利用するシーケンスを指定 @ORM\SqlResultSetMapping ネイティブSQLクエリの結果のマッピングを定義 @ORM\Table クラスをDBのテーブルとマッピング @ORM\UniqueConstraint エンティティの一意性制約を指定 @ORM\Version ロックに使うバージョン値を保持するプロパティを指示
- 投稿日:2020-12-27T22:23:34+09:00
Laravel のwhereHasをwhereInに置き換える
追記
下記の方が、便利なライブラリを作成してくれています。
古のphpバージョンだと対応していない(未確認)ので、以降の記事は備忘録的な意味で残します。
https://qiita.com/mpyw/items/0761a5e44836c9bebcd5難しいクエリを作りたくない
whereHasは遅い。激遅い。
left joinや、whereInすれば良いらしいと推測。
でもleft joinはコーディングがしんどいのよな……。結論:whereInで頑張れば簡単だし改善はできるよ
modelの関係性
usersはcommentsと「1対多」の関係。
whereHasを用いた場合
前提
- リレーション先のカラムでwhereしたい。
- 姓と名が別々のカラムになっており、concatでlikeしないとならない。(この条件は今回関係ない)
UsersController.phpComments::whereHas('Users', function($query) use ($user_name){ $query = $query->where(DB::raw('CONCAT(mei, sei)'), 'like', "%$user_name%"); });whereInに置き換え
UsersController.php// users単体で、クエリをたたく $users = User::where(DB::raw('CONCAT(mei, sei)'), 'like', "%$user_name%") ->select('id') ->pluck('id') ->toArray(); // その結果を、当モデルに組み込む。 Comments::whereIn('user_id',$users);計測はしていないけど、体感で明らかに早くなったのでよしとする。
生クエリや、left joinする方とどちらのコーディングが美しいかは言うな。
僕みたいなよわよわ頭脳の場合は上記の方が早く書けるし、見やすい!以上。
- 投稿日:2020-12-27T20:24:36+09:00
【初心者】PHPの論理演算子について
論理演算子とは?
論理演算子と言われてもピンとこないかもしれない。
ただ、それが何か言われると知っているし、使っていると思う。
AND
やOR
のこと。
例があると非常に分かりやすいが、これらが論理演算子ということを覚えておきたい。実際に使ってみる
//ANDを使する $n = 40; if($n >= 30 && $n <= 50) { echo($n)."は30以上かつ50以下です"; }else { echo($n)."は30以上かつ50以下ではありません"; } //出力結果 40は30以上かつ50以下です //ORを使用する $n = 40; if($n % 2 == 1 || $n >= 30) { echo($n)."は30以上もしくは奇数の数値です"; }else { echo($n)."は30より小さい偶数です"; } //出力結果 40は30以上もしくは奇数の数値です
AND
は&&
、OR
は||
と記述することが一般的?なのだろうか。$n = 20; if($n >= 30 AND $n <= 50) { echo($n)."は30以上かつ50以下です"; }else { echo($n)."は30以上かつ50以下ではありません"; } //出力結果 40は30以上かつ50以下ですこのように
AND
と記述しても大丈夫だった。and
も試してみたところ出力できた。
OR
も同様にor
でも出力はできていた。やはり根本的な理解が私には欠けているのかもしれない。
もしくはこのような知識よりも何かアプリケーションを作成できる知識を重点的に学ぶべきなのか…
- 投稿日:2020-12-27T15:54:49+09:00
EC-CUBE4 プラグインでマスターテーブルを追加する
はじめに
初めての投稿となります。
よろしくお願いします。仕事で始めてEC-CUBE4を利用したECサイトを仕事で制作しました。
その際、プラグインでマスターテーブルを新規追加することになったのですが、
テーブルの新規追加はよく見かけるのに対し、マスターテーブルの記事が少ないように感じたので作成方法を簡単に記事にまとめよう思います。新規プラグイン作成方法については多くのサイトが存在するのでそちらを参考にしください。
目標
マスターテーブル(mtb_sample)の新規追加。
管理画面>設定>システム設定>マスタデータ管理 へ登録。最終的なマスターテーブル
形は以下のしたいと考えています。
id name sort_no discriminator_type 1 テスト1 1 samplemtbconfig 2 テスト2 2 samplemtbconfig 3 テスト3 3 samplemtbconfig 4 テスト4 4 samplemtbconfig 管理画面>設定>システム設定>マスタデータ管理
以下の設定にマスターテーブル(mtb_sample)を編集出来るようにします。
EC-CUBE Version
Version 4.0.4プラグイン
プラグイン生成時の項目は以下にしています。
name:SamplePlugin code:SamplePlugin ver: 1.0.0プラグインのディレクトリ構成
SamplePlugin\ |―― Entity\ |―― Master\ |―― SampleMtbConfig.php |―― Repository\ |―― Master\ |―― SampleMtbRepository.php |―― Form\ |―― Type\ |―― Extension\ |―― SampleMasterdataType.php |―― composer.json |―― PluginManager.phpcomposer.json
プラグインの情報の記述
composer.json{ "name": "ec-cube/SamplePlugin", "version": "1.0.0", "description": "SamplePlugin", "type": "eccube-plugin", "require": { "ec-cube/plugin-installer": "~0.0.7" }, "extra": { "code": "SamplePlugin" } }Entity\Master\SampleMtbConfig.php
まずはエンティティクラスを作成します。
普通のテーブルであればここに setId()やgetid()などを記述していくのですが、必要ありません。以下の記述でマスターテーブルの名前を設定します。
@ORM\Table(name="mtb_sample")
SampleMtbConfig.php<?php namespace Plugin\SamplePlugin\Entity\Master; use Doctrine\ORM\Mapping as ORM; /** * SamplePlugin * * @ORM\Table(name="mtb_sample") * @ORM\InheritanceType("SINGLE_TABLE") * @ORM\DiscriminatorColumn(name="discriminator_type", type="string", length=255) * @ORM\HasLifecycleCallbacks() * @ORM\Entity(repositoryClass="Plugin\SamplePlugin\Repository\Master\SampleMtbRepository") * @ORM\Cache(usage="NONSTRICT_READ_WRITE") */ class SampleMtbConfig extends \Eccube\Entity\Master\AbstractMasterEntity { }Repository\Master\SampleMtbRepository.php
Repositoryはテーブルのデータを操作する際に利用されます。
SampleMtbRepository.php<?php namespace Plugin\SamplePlugin\Repository\Master; use Eccube\Repository\AbstractRepository; use Plugin\SamplePlugin\Entity\Master\SampleMtbConfig; use Symfony\Bridge\Doctrine\RegistryInterface; class SampleMtbRepository extends AbstractRepository { /** * * @param RegistryInterface $registry */ public function __construct(RegistryInterface $registry) { parent::__construct($registry, SampleMtbConfig::class); } }Form\Extension\SampleMasterdataType.php
管理画面>設定>システム設定>マスタデータ管理 へ登録や変更を行うことが出来る機能へ反映させるための記述です。
SampleMasterdataType.php<?php namespace Plugin\SamplePlugin\Form\Type\Extension; use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; use Eccube\Form\Type\Admin\MasterdataType; use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; class SampleMasterdataType extends AbstractTypeExtension { /** * * @var EntityManagerInterface */ protected $entityManager; /** * * @param EntityManagerInterface $entityManager */ public function __construct(EntityManagerInterface $entityManager) { $this->entityManager = $entityManager; } /** * * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $masterdata = []; /** @var MappingDriverChain $driverChain */ $driverChain = $this->entityManager->getConfiguration()->getMetadataDriverImpl(); /** @var MappingDriver[] $drivers */ $drivers = $driverChain->getDrivers(); foreach ($drivers as $namespace => $driver) { if ($namespace == 'Eccube\Entity' || $namespace == 'Plugin\SamplePlugin\Entity') { $classNames = $driver->getAllClassNames(); foreach ($classNames as $className) { /** @var ClassMetadata $meta */ $meta = $this->entityManager->getMetadataFactory()->getMetadataFor($className); if (strpos($meta->rootEntityName, 'Master') !== false && $meta->hasField('id') && $meta->hasField('name') && $meta->hasField('sort_no') ) { $metadataName = str_replace('\\', '-', $meta->getName()); $masterdata[$metadataName] = $meta->getTableName(); } } } } $builder ->add('masterdata', ChoiceType::class, [ 'choices' => array_flip($masterdata), 'expanded' => false, 'multiple' => false, 'constraints' => [ new Assert\NotBlank(), ], ]) ; } /** * * {@inheritdoc} */ public function getBlockPrefix() { return 'admin_system_masterdata'; } /** * * {@inheritdoc} */ public function getExtendedType() { return MasterdataType::class; } }PluginManager.php
PluginManager.phpはプラグインのインストールやアンインストール時に呼び出されますので、プラグインインストール時に、マスターデータを書き込む記述をします。
PluginManager.php<?php namespace Plugin\SamplePlugin; use Eccube\Plugin\AbstractPluginManager; use Plugin\SamplePlugin\Entity\Master\SampleMtbConfig; use Symfony\Component\DependencyInjection\ContainerInterface; class PluginManager extends AbstractPluginManager { /** * * @param array $meta * @param ContainerInterface $container */ public function install(array $meta, ContainerInterface $container) { $em = $container->get('doctrine.orm.entity_manager'); $CustomerQuestionnaire = new SampleMtbConfig(); $CustomerQuestionnaire->setId('1'); $CustomerQuestionnaire->setName('テスト1'); $CustomerQuestionnaire->setSortNo('1'); $em->persist($CustomerQuestionnaire); $em->flush(); $CustomerQuestionnaire = new SampleMtbConfig(); $CustomerQuestionnaire->setId('2'); $CustomerQuestionnaire->setName('テスト2'); $CustomerQuestionnaire->setSortNo('2'); $em->persist($CustomerQuestionnaire); $em->flush(); $CustomerQuestionnaire = new SampleMtbConfig(); $CustomerQuestionnaire->setId('3'); $CustomerQuestionnaire->setName('テスト3'); $CustomerQuestionnaire->setSortNo('3'); $em->persist($CustomerQuestionnaire); $em->flush(); $CustomerQuestionnaire = new SampleMtbConfig(); $CustomerQuestionnaire->setId('4'); $CustomerQuestionnaire->setName('テスト4'); $CustomerQuestionnaire->setSortNo('4'); $em->persist($CustomerQuestionnaire); $em->flush(); } /** * * @param array $meta * @param ContainerInterface $container */ public function enable(array $meta, ContainerInterface $container) { } /** * * @param array $meta * @param ContainerInterface $container */ public function disable(array $meta, ContainerInterface $container) { } }プラグインインストール
以上のコードを記述後、プラグインをインストールすれば(mtb_sample)が生成されます。
マスターデータ管理にも以下のように追加されて編集出来るようになりました。
参考サイト
https://xoops.ec-cube.net/modules/newbb/viewtopic.php?topic_id=22996&forum=10
最後に
拙い記事を最後まで見ていただきありがとうございました。
- 投稿日:2020-12-27T15:42:49+09:00
GCP Cloud Vision APIでドラゴンボール表紙をOCRにかけてみた
Cloud Vision API の 光学式文字認識(OCR)
Google Cloud Platform (GCP) > Cloud Vision API ではいろいろなものを検出できます。
先日
光学式文字認識(OCR)
を利用してみて、精度の高さに驚きました。そして、画像化した書籍は読めても、ではマンガはいけるのか、が気になっため、やってみました。
Cloud Vision API
https://cloud.google.com/visionには 大きく、
- AutoML Vision
- Vision API
があり、
AutoML Vision
はカスタムオブジェクトの検出などより高度なことができ、
Vision API
は顔検出、ロゴ検出など、汎用的なオブジェクトの検出が手軽に利用できます。
今回は
Vision API
の光学式文字認識(OCR)
を利用しました。解析した画像
ドラゴンボールコミックなどの表紙を解析しました。
左 = 元画像と解析結果を重ねたもの
右 = 解析結果のみを描画したものです。
ドラゴンボール 42 巻
画像
読み取り内容
JUMP COMICS DRAGON BALL 鳥山明 THANK YOU! GOOD BYE !! 巻四十二 バイバイドラゴンワールド著者名や、フキダシの
THANK YOU! GOOD BYE !!
まで拾っており、かなり正確に読み取りができてることがわかります。ところが、青丸に黄文字の「ドラゴンボール」は、読めていないですね。
ドラゴンボール 13 巻
画像
読み取り内容
JUMP COMICS DRAC BALL DRAGON UNUK CEAPSULE NO. 158 鳥山明 卷十三系倍空のロゴ
DORAGON
は、イラストで隠れている文字を解釈するのは流石に難しいようでした。人間には、
DORAGON
がわかっているからそう脳内補完が働き、読める類のものですね。
(カスタムオブジェクト検知なら行けるかもです。未検証)また、画像右、縦書き文字について、
孫悟空
が系倍空
になっていたり逆襲
が読めていなかったりしていますが、
縦書きと横書きが混在していても、ある程度解釈できている事がわかります。また、読み間違いについては、元画像の解像度を上げると改善するかも、という雰囲気を感じます。
ニンテンドークラシックミニ 週刊少年ジャンプ創刊50周年記念バージョン
コミックではありませんが、もっと複雑なものはどうだろうかと検証してみました。
画像
読み取り内容
シテン 週刊少年ジャンプ 創刊50周年記念バージョン ジャンプ特別編集 2018年8月号増刊 定価1080円(税込) 世界最クリアグ ロ ジャンプゲーム 特製ポスターつき 合黒神語。 スト 20本の イ、 ファミコン ファミコン ジャンプ ジャンプロ 英雄列伝 強のフ人。 ★ファミコン神単を語る/★。 ★英社の攻略本いろいろ★ジャン ■元週刊少年ジャンプ& Vジャンプ編集長 島嶋和彦氏インタビュー ビ kこれは流石に読み取りが難しかったようです。
思ったよりも、文字が読める
周囲とのコントラストが曖昧だったり、装飾的に過ぎたり、文字方向などが変則的なものはちょっと、という感じがしましたが、それでも十分読めてるな、と感じました。
フォントが違うものや、縦書き横書きが混在していてもOKなところは驚きです。
同様なもので、Google Drive で画像をアプリで開くと、同様に OCR にかけて文字を起こしてくれますが、
これを初めてやった 5 年前と比べると、格段に精度が上がったのではないかと感じますね。これからもっと精度が上がっていくのではないかと感じます。
純粋にこういうのって面白いですね。どうやったの ?
最後に、掲載した画像の作成手順についてさらっと記載します。
1.はじめに
Cloud Vision API > ドキュメント > ガイド > クイックスタート: クライアント ライブラリの使用
https://cloud.google.com/vision/docs/quickstart-client-librariesのクライアントライブラリを導入し
2.次に
Cloud Vision API > ドキュメント > ガイド > 画像内のテキストを検出する
https://cloud.google.com/vision/docs/ocrに掲載のあるプログラムを用意して画像解析のリクエストを行い
3.最後に
HTML の Canvas で、解析結果を描画した
という感じで組み立ててます。
- 投稿日:2020-12-27T11:43:42+09:00
WordPressでOGPの自動出力をしてみた
はじめに
最近流行りのJamstack、いいですよね。
弊社でもGatsby.jsを使ったJamstackの実績があります。(※担当エンジニアは私じゃないです)
“TINDER” CORPORATE WEB SITE & MOVIE|WORKS|PLUS-D Inc.Gatsby.jsを調べているうちに、Gatsby.jsでOGPの自動出力をしたという記事を拝見しました。
GatsbyJSでOGP画像の動的生成にチャレンジしてみた | Learn Something Newで、OGP自動出力したすぎる、と。目的がGatsby.jsからOPG自動出力に変わりまして。
じゃあ、個人でやってるブログで試したろ!と思ったのですが、私のブログ、ヘッドレスCMS化?SSR?なにそれ?みたいなWordpressを使ったフツーのブログなんですよね。(しかも1年以上放置)え、サイト作り直すのだる……PHPでどうにかできるならしよ。
というのが、今回の趣旨です。
PHPで画像作成
そもそもできるのか、というところから調べたのですが、できるらしいです。
imgタグには普通画像を指定しますが、.phpファイルを指定できるらしい。
PHPってサーバー関係!みたいなザックリした理解の仕方をしていたのでなんか画像と結びついてなかった。
そして驚きのあまりこの記事を書いているんですが、そんなの知ってるよって方はもう話すことはないです。参考:PHPで画像を動的に生成する【GD編】 | バシャログ。
ディレクトリ構成
ファイルを置く場所は極端にいえばドキュメントルートでもテーマ内でもどこでもいいのですが、こんな感じで。
/og ├─img.php ├─og_base.png └─xxx.ttf.phpファイル、画像、フォントが必要です。
画像はなくても作れますが、今回はこちらを用意しました。こちらの上にテキストを重ねるだけの簡単なOGPを作ります。
PHPを書く
img.php<?php $fontSize = 40; // 文字サイズ $fontFamily = 'xxx.ttf'; // 字体 $txtX = $fontSize; // 文字の横位置(文字の左が基準) $txtY = $fontSize * 2; // 文字の縦位置(文字のベースラインが基準) $txt = $_GET['text']; // テキスト $img = imagecreatefrompng('ogp_base.png'); // テキストを載せる画像 // $img = imagecreatefromjpg('ogp_base.jpg'); // 元画像がjpgの場合はこうなります $color = imagecolorallocate($img, 0, 0, 0); // テキストの色指定(RGB) imagettftext($img, $fontSize, 0, $txtX, $txtY, $color, $fontFamily, $txt); header('Content-Type: image/png'); imagepng($img); imagedestroy($img);上はいろいろ指定なので、下4行が重要です。
一つだけ注意が必要なのが縦位置。文字のベースラインが基準となっているため、縦位置に0を指定するとテキストが画像の外に行ってしまいます。
いい感じの改行などはできないので実際はもう少しいじる必要があります。
imagettftext($img, $fontSize, 0, $txtX, $txtY, $color, $fontFamily, $txt);
重ねるテキストに関する指定です。左から順番に下記を指定します。
- 重ねる画像
- 文字サイズ
- テキストの角度
- 横位置
- 縦位置
- 色
- フォント
- テキスト
header('Content-Type: image/png');
画像として情報を送信します。
imagepng($img);
PNG画像を表示。
imagedestroy($img);
メモリを解放。og:imageを指定
header.phpなど<meta property="og:image" content="img.php?text=<?php the_title(); ?>">PHPファイル内で取得するテキストデータに合わせてパラメータを付けます。
できた
たとえば、同じ内容をアップしている下記記事だと、こんな感じです。アッ、ブログはメモとして使っていてもっと
雑に簡略化して書いてます。よろしくお願いします。
WordPressでOGPの自動出力をする方法 | I log.
JKゴシックかわいい。まとめ
- PHPで画像生成ができる
- imgタグやmetaタグなど、画像を指定するときに.phpファイルを指定できる
- 投稿日:2020-12-27T11:21:06+09:00
Laravel すべてのviewで共通する変数の設定
はじめに
Laravelを勉強中です。備忘録として残しておきます。
手順
サービスプロバイダーの作成
app/Provider/ComposerServiceProvider.php<?php namespace App\Providers; use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Auth; class ComposerServiceProvider extends ServiceProvider { public function boot() { View::composer('*', function($view) { $view->with('user'(使いたい変数名), Auth::user()(使いたいデータ)); }); } }View::composerの第一引数「*」はすべてのviewという意味。
作成したComposerServiceProviderの登録
config/app.php'providers' => [ . . . App\Providers\ComposerServiceProvider::class, ],これですべてのviewで使用できるようになります。
参考にさせて頂いたサイト
- 投稿日:2020-12-27T09:21:27+09:00
[仕事納め]2020年にやらかしたミスをまとめる[未経験から2年目]
こんにちは。web系を中心としたプラグラマをしております。
小さなミスからそこそこ大きめのミスまで、今年1年でたくさんのミスをしてきました。
まだ新人で大きな権限を頂いていないこともあり、本番環境でやらかしてしまった皆様ほどのインパクトあるやらかしはないのですが、コーディングや開発環境構築などであれこれ反省点があるのでまとめていきたいと思います。
アンチパターンやあるあるとしてお楽しみ下さい。コーディング系
誤字
とにかく多かったです。
クラス名や関数名ならすぐエラーが発生して見つけやすいのですが、phpで変数名のスペルミスをしたりすると、そのままnullが代入されたりして見つけづらく、時間の無駄になりがちでした。$address = 'hogehoge'; print $adress; // 返却値なしくだらない誤字ですが、この手のエラーが出ない誤字で無駄にした時間も、年間を通せばかなり膨大になって来ます。
解決策としては、コードを細かく切り分けてこまめにテストを実行しました。これによって誤字箇所を発見するのが早くなった実感があります。
また、エディタはVSCodeを使用しており補完機能は元々使っていたのですが、コード量が多いとなかなか読み込まず使用を諦めて手入力することもあったので、今後補完機能をうまく活用できるように工夫していきたいです。
......そんなことより静的言語を使った方がいいのかもしれません。エスケープ
先日LaravelのselectRawメソッドを用いて生に近いSQLを書く機会がありました。WHERE句の対象となるカラムにバックスラッシュを用いたパスが入っていて、この部分をエスケープ出来ておらず検索結果が0となる失敗を犯しました。この質問と大体同じ内容です。
// 失敗例 DB::table('hoge') ->selectRaw('* WHERE `path`="PATH\\TO\\SOME\\MODEL"') ->get();一見エスケープ出来ていそうですが、phpではダブルクォート内ではバックスラッシュが
//
→/
となり、かつ、Laravelのraw関係のメソッドではエスケープされない(というかrawって書いてあるのでそりゃそうですね)ので、MySQLに送られるクエリは以下のようになります。SELECT * FROM hoge WHERE `path`='PATH\TO\SOME\MODEL'結果、MySQLでもエスケープされて無事死亡しました。
できるだけこのような生っぽいSQLは書かないのが一番ですが、この時は諸事情で仕方なかったので、以下のようにして解決しました。// 成功例 DB::table('hoge') ->selectRaw('* WHERE `path`="PATH\\\\TO\\\\SOME\\\\MODEL"') ->get();SELECT * FROM hoge WHERE `path`='PATH\\TO\\SOME\\MODEL'ともかく、何かとバックスラッシュは問題のタネになりやすいので警戒していきたいと思います。
環境系
Dockerコンテナの内か外か
Dockerを立ち上げてシェル作業する時、必要なコマンドをコンテナの内側で行うのか外側で行うのかを間違えて
command not found
になったり、最悪の場合想定外の処理が始まったりします(しました)。
基本的にどのコマンドをどこで実行するのかはプロジェクトによるので、実行前に確認するようになりました。特にcomposerの実行場所で事故ったので気をつけていきたいと思います。バージョン違い
composerで依存パッケージをインストールすることが多いのですが、マイナーバージョンは指定しておらず不具合が発生する場合があります。
また、私が今年特に詰まったのはcomposer自体のバージョン違いです。
2020年10月頃にcomposerのバージョン2.0がリリースされました。これに気づかずdocker-compose
コマンドを実行してしまった結果、DockerFile内にcomposer関係の諸々のコマンドが実行されてしまい、大量のエラーが発生しました。
この件の解決策は、こちらの方と同じ方法を使いました。
コマンドは以下のものです。curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --1 --filename=composerバージョンアップの詳細はこちらです。
人として
連絡が遅い
思い出すと胃が痛くなります.......
進捗が悪いのに、頑張って挽回しようと試行錯誤していて締め切りギリギリまで上司への進捗が遅れている旨の連絡をしませんでした。上司からは特に怒られず、淡々と「了解です。次は早めに連絡・相談して下さい」という内容のメッセージが返ってきて逆に怖かったです。
とにかく、早めの報告・連絡・相談は本当に大切です。技術的なミスより何より連絡不足が一番信用を失うと思いました。仕様通りでない
仕様変更が頻繁でも、仕様書が読みづらくても、決定した仕様が一意である以上、仕様通りでないのは絶対にダメですよね。
コミット前にもう一度、成果物のチェックを怠らない。大事だと思います。
あと、最初に仕様書を通しで読んだ時に矛盾点を見つけられるようになりたいです。実装を始めてから気づくことが多いので.......まとめ
結局、ほとんどのミスが確認不足に起因していました。
コミット前、コマンド入力前、上司への報告前......この記事を振り返ってミスを減らしていきたいと思います。
というわけで、皆様1年間お疲れ様でした。2021年も頑張っていきましょう!!
- 投稿日:2020-12-27T00:37:20+09:00
PHP 月末の日にちを取得する
目的
- PHPで月末の日にちを取得する方法をメモ的にまとめる
前提情報
- 下記サービスを用いてWeb上でコードの動作を確認した。
- 忘れそうなのでメモ的にまとめる。
詳細
ひと月前の月末の日にちを取得したい時は下記を実行する。(YYYY/MM/DDの形式で情報を取得する事ができる。)
$last_day_of_last_month = date('Y/m/d', mktime(0, 0, 0, date('m'), 0, date('Y'))); echo $last_day_of_last_month;今月の月末の日にちを取得したい時は下記を実行する。(YYYY/MM/DDの形式で情報を取得する事ができる。)
$last_day_of_this_month = date('Y/m/d', mktime(0, 0, 0, date('m') + 1, 0, date('Y'))); echo $last_day_of_this_month;来月の月末の日にちを取得したい時は下記を実行する。(YYYY/MM/DDの形式で情報を取得する事ができる。)
$last_day_of_next_month = date('Y/m/d', mktime(0, 0, 0, date('m') + 1, 0, date('Y'))); echo $last_day_of_next_month;参考文献