• WordPressサイトを簡単に他国語化できるプラグイン

    qTranslate プラグイン

    図1: qTranslate プラグイン

    WordPressはGNUのGettextを取り入れて多言語対応しているものの、実際に1つのサイトで多国語化を実現しようとすると、色々と困難な問題に突き当たる。とある開発案件にて多国語化の要望があったので、色々と言語系のプラグインなどを調べていたところ、見つけたのが「qTranslate」プラグインだ。

    このプラグイン、サイト全体の言語管理と各投稿毎(コンテンツ毎)の言語管理を一括で行えるという優れもののプラグインである。

    qTranslate プラグイン 2 図2: 管理パネルのメニュー

    管理パネルのメニューにてプラグインで指定した複数の言語を切り替えられるようになる(図2参照)のは序の口で、サイトのフロントエンド側からも言語を切り替えられる(切り替えのUIは別途作る必要はあるが…)。切り替え方も、ブラウザの言語設定に応じて自動化したり、訪問者の手動切り替えや、URLパラメータによる一時的な切り替えなど、色々と選べる。
    そして、極めつけが、それぞれ個別の投稿に対して別言語によるコンテンツを同時に投稿できる点が素晴らしい機能である。

    サイトの多国語化対応に際して一番大きな障壁が、サイトのメニューやフッター、ボタンといった共用コンテンツは言語ファイルにて他国語化できても投稿等のコンテンツはそれぞれ個別に管理しなければならないという点だ。例えば、日本語でアップした投稿と英語でアップした投稿はそれぞれ個別のコンテンツであり、それらを同じ一つのコンテンツとして管理するためには別の仕組みが必要だった。投稿のUI的にも同時に複数言語の記事が書けないことがネックとなって、サイトの保守性や利便性に難があったのだが、このプラグインはそれらの問題を一挙に解決してくれるのだ。

    ということで、モノは試しに、この記事を日本語と英語両方で投稿してみた。英語版を見てみる場合はこのリンクをクリックしてみて欲しい。

    qTranslate プラグイン 3

    図3: プラグイン設定画面

    「qTranslate」プラグインは2013年6月19日現在のバージョンが2.5.34であり、同梱されている日本語翻訳ファイルが古く、一部翻訳されない部分があったので、私の方で最新バージョンに合わせた翻訳を行ってみた。

    ※ 下記でダウンロードできた .mo ファイルを qTranslate プラグインの lang フォルダ内に入れてやる(上書きする)ことで最新の翻訳が反映されます。

    qTranslate プラグイン 日本語化ファイル

    動作確認:WordPress 3.5.1 / qTranslate 2.5.34

    ...
  • 裏セグメントからyumやwget等したい場合の設定

     

    裏セグメントのホスト(たとえばVPCのEIPついてないのとかDBやNASなど裏においときたいやつ) から名前解決とかメールとかyumとかwgetとか時刻同期とかメールしたい! という場合の設定についてざっくりまとめさせていただきます。

    とりあえず2パターンあります。 NATする(AWSの場合NATインスタンスを使う)パターンと、 グローバル通信できる管理サーバにソフトウェアを入れて解決するパターン。

     

    ★NATする(AWSの場合NATインスタンスを使う)パターン

    db側はInternetGatewayつけてなくてパブリックでなくローカルなルーティングな場合、 名前解決をはじめ外に出られないです。(※) NATインスタンスを作るのも勿体ないと、複数NICがついたwebをnat化しようとしたところ、 マルチインタフェースなインスタンスはNATの出口に出来ない模様でした。 (※)最近新しくとったアカウントはVPCオンリーになっていてそちらだとグローバルIPがどんどん勝手に振られるようです。。(EIPつけざるをえない仕様)

    NATインスタンス作成方法は以下URLから Amazon VPCトレーニング-NATインスタンスの作成方法 VPC詳細 -ほぼ週刊AWSマイスターシリーズ第7回- Amazon VPCでNATを使ってPublic SubnetとPrivate Subnetを分ける

    一番上のスライドのとおりでnatインスタンスを作成可能。 ざっくりいうと、 VPCサブネットをつくり、 “ami-vpc-nat"AMIでNATインスタンスを作成し、 NATインスタンスの"Change Source/DestCheck"をDisableにし、 NATインスタンスにEIPをアソシエートし、 PublicSubnetのRouterTableにNATインスタンスのIDを追加し、 必要に応じてNATインスタンスのSecurityGroupを設定する

    そのほか、一般的なルータ化設定方法と同様に、 インスタンス作成後にiptablesでnatのルール設定が必要になる模様。

    /sbin/iptables -t nat -A POSTROUTING -o eth0 -s 10.0.0.0/16 -j MASQUERADE
    service iptables save
    iptables --list -t nat
    

    上記スライドのとおりNATインスタンスをデフォルトゲートウェイにするルーティング設定も必要 forwardingの設定も必要

    ...
  • muninのデータを引き継ぐ方法

    こんにちわ。 プラットフォーム担当の宮下です。
    今回は、オープンソースのモニタリングツール「munin」でホスト名を変更した時に
    今までのデータもそのまま移行する方法を説明します。
    なお使用するmuninのバージョンは、1.4.5を使います。

    1)RRDのデータを移す。

    muninのグラフ描写を行っている「RRD tool」のデータを移行します。

    [shell] # cd /var/lib/munin/DIR # rename test01 test01-old ./test01-* [/shell]

    格納場所に移動して、ファイルを一括で変換してしまいます。

    2)HTMLファイルを移す。

    [shell] # cd /var/www/html/munin/DIR # mkdir test01-old # chown munin:munin test01-old # cp -pfR test01/* test01-old/ [/shell]

    生成されているHTMLと画像ファイルをまとめて移動します。
    移動先のディレクトリが既にある場合は、mkdirとchownは飛ばして下さい。
    またOSによってはaliasで「cp -i」が入っているかも知れません。
    その時は、バックスラッシュを使って一括移動をします。

    [shell] # \cp -pfR test01/* test01-old/ [/shell]

    これで次の収集間隔から新しいホスト名でデータが更新されていきます。
    地味な作業ですが、過去のデータを捨ててしまうのはもったいない気がします。
    そんな時はデータも一緒に移動してあげて下さい。

    ...
  • mysqlパフォーマンス改善への道(その1、現状の確認)

    パワー不足のmysqlをチューニングしてみます。

    こんばんわ。プラットフォーム担当の宮下です。

    今回は、バックアップ兼集計用に稼働しているmysqlのレプリケーションンサーバの
    パフォーマンス改善していきたいと思います。
    これまでにもいくつか対策はしてきましたが、まずは環境をおさらいします。

    ◇稼働してる環境は、AWSのEC2でlargeインスタンスを使用しています。
     サービスは、OpenPNEを使用したSNSのサービスとなります。対象のMysqlはバックアップとデータ集計が目的で稼働しています。
     (本番サービスでは使用していません)

    ◇mysqlのバージョンはちょっと古くて「5.0.77」になっています。multiで起動させていていて
     この他に開発環境用のmysqlも稼働していたりします。  ちなみに今の遅延秒数は、「1512561 秒」でまだ増加中です。

    ◇これまでに変更した点ですが、
     「innodb_buffer_pool_size」を512Mから2028Mまで増加、
     「innodb_flush_log_at_trx_commit」を2から0に変更、
     (リカバリの精度よりもスループットを優先)
     「key_buffer_size」を32Mから300Mに変更、
     「query_cache_size = 0」にして無効化しました。
     効果は、DISKのI/Oが半分くらい減りましたが、遅延解消とまではいってません。

    ◇最後にmuninで取得しているデータを確認します。

    delay0527

    遅延が日々増えています。たまに減る事もありますが要因は分かりません。

    io0527

    常にDISKのread I/Oが大量に発生しています。

    原因ははっきりしていて、DBデータに画像や動画データが格納されている為となります。
     buffer pool sizeでは収まり切らないデータサイズなので常にDISKのread/writeが発生しています。
     またMyISAMとInnodbが混在していてリソースが効率的に利用出来ていない事や、
     OpenPNEが「delete aaa filename LIKE ‘%bbb%’」というクエリを大量に発行している事
     などが解決すべき課題がたくさんあります。

    現状を整理した事で、次回からは一つずつ改善対策を実施していきたいと思います。

    ...
  • 瀕死の技術ブログを復旧した話

    こんにちわ。

    今回は主に(当ブログの)mysqlデータベース復旧のお話になります。

    担当のお方が
    「waordpressだとinnodbよりmyisamのほうが早いらしいので、
     変える前にinnodbのmy.cnfのパラメータいじくってベンチマークとろうとした」
    ことをきっかけにDBのデータがぶっ壊れました。
    mysql5.6ならmyisam使わなくても参照専用トランザクション使うよう改造できれば早いらしいよという話はおいといて。(5.5だし)
    DBデータが読めなくてwordpressの管理画面にログインできなくなってしまいました。

    -————————————————– 130528 11:59:24 [ERROR] Missing system table mysql.proxies_priv; please run mysql_upgrade to create it
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.’events_waits_current’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.’events_waits_history’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.’events_waits_history_long’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘setup_consumers’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘setup_instruments’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘setup_timers’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘performance_timers’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.’threads’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.’events_waits_summary_by_thread_by_event_name’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.’events_waits_summary_by_instance’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.’events_waits_summary_global_by_event_name’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘file_summary_by_event_name’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘file_summary_by_instance’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘mutex_instances’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘rwlock_instances’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘cond_instances’ has the wrong structure
    130528 11:59:24 [ERROR] Native table ‘performance_schema’.‘file_instances’ has the wrong structure
    130528 11:59:24 [Note] Event Scheduler: Loaded 0 events
    130528 11:59:24 [Note] /usr/libexec/mysqld: ready for connections.
    Version: ‘5.5.30-log’ socket: ‘/var/lib/mysql/mysql.sock’ port: 3306 MySQL Community Server (GPL) by Remi
    130528 11:59:50 [ERROR] Cannot find or open table xxxxxx_db/dl_options from
    the internal data dictionary of InnoDB though the .frm file for the
    table exists. Maybe you have deleted and recreated InnoDB data
    files but have forgotten to delete the corresponding .frm files
    of InnoDB tables, or you have moved .frm files to another database?
    or, the table contains indexes that this version of the engine
    doesn’t support.
    See http://dev.mysql.com/doc/refman/5.5/en/innodb-troubleshooting.html
    how you can resolve the problem.);
    -————————————————–

    ...
  • AmazonEBSでraid0を組んだ時のパフォーマンス検証

    AmazonEBSでraid0を組んだ時のパフォーマンス検証

    EBSを組むと早いはなしを検証したい

    testでマルチ、ラージなら結構こうかある説がある模様。
    既存移行の方法も検討(バイナリログ等のディレクトリ分けるところからかと。)

    公式のユーザガイド(EBSPerformance)
    EBS自体が冗長構成組まれているのでraid0でいいと思われる。

    インスタンスディスク(ローカルディスク、エフェメラルディスク)を使ってRAID0
    EBSでRAID0を組むことは、RAID10(ミラーのストライプ)と同等である

    Largeインスタンス以上であれば、1台よりも2台の方がディスクI/O性能が目に見えて上がりました

    エフェメラルディスク(stopすると消えるほうのディスク)でraid0したい場合の起動コマンド例
    [shell] ec2-run-instances ami-e965ba80 –region us-east-1 –key id_rsa –group sg-a4866fcc –placement-group test –instance-type cc2.8xlarge -b “/dev/sdb=ephemeral0” - b “/dev/sdc=ephemeral1” -b “/dev/sdd=ephemeral2” “/dev/sdf=ephemeral3” [/shell] ・ラージでEBSディスクを2つ追加して起動してログインする
    [shell] # df -h Filesystem Size Used Avail Use% Mounted on /dev/xvde1 9.9G 867M 8.5G 10% / none 3.7G 0 3.7G 0% /dev/shm # ls -l /dev/xv* brw-rw—- 1 root disk 202, 65 Mar 21 02:15 /dev/xvde1 brw-rw—- 1 root disk 202, 80 Mar 21 02:15 /dev/xvdf brw-rw—- 1 root disk 202, 96 Mar 21 02:15 /dev/xvdg find /dev -type b -print [/shell] してみたがそれらしい名前のは上記のみ。

    ...
  • IDCフロンティア セルフクラウド入門編

    IDCフロンティアのセルフクラウドでAPI環境を用意するまで

    その1サーバを起動する

    始めまして。プラットフォーム担当の宮下です。

    かねてから利用している、「IDCフロンティア クラウドセルフタイプ」の利用方法について基本的な流れを案内していきたいと思います。
    会社としてもう今回は、仮想マシンの起動までの簡単な流れを説明させて頂きます。
    パブリッククラウドは各社で独自の管理コンソールがあって慣れるまではそれぞれにくせがあります。その辺についても今後触れていければと思います。

    • 仮想マシン作成

     作成したユーザ/パスワードでログインしたら、〔ホーム〕→〔ダッシュボード〕から〔仮想マシン作成〕で作成を開始します。

    noah_cloud01

    • OSの選択

    次に起動するOSを決めていきます。リストをスクロールすると標準で用意されたテンプレートがたくさん出てきますのでお目当てのOSタイプが見つかるまで頑張って探してみて下さい。
    (特にOSの指定が無ければLATESTの中から選び、ミドルウェアが必要かどうかで決めれば良いと思います)
    今回はAPIツールを使用する環境を作りたいのでLATESTのLAMP環境OSを選びます。

    noah_cloud02

    〔[LATEST] LAMP or LVS(keepalived) or HAProxy or API Access Tool or Scalr or Elecoma or Yahoo! Cloud Storage Access Tools〕
    を〔選択〕します。

    • マシンスペックの選択

     次にサーバのスペックを決めます。

    noah_cloud03

    これはどこのクラウドでも同じだと思います。必要な用途に応じて最適なマシンスペックを選びます。
    今回は最小の〔XS〕(1CPU/メモリ0.5GB)を選択します。

    ...
  • MHAの動作確認と切替検証

    MHAの動作確認と切替検証
    前回のつづきです。以下の図のように切り替わるようテストします。

    mha_after_failover  ※本検証はマスタ1台、スレーブ2台、マネージャ1台構成。(多段構成は中間ノード障害時の復旧が猥雑になるので回避)
      スレーブにmanagerを同居させるとpurge_relay_logsとかぶると上手く切り替わらない可能性があるようです。
     ※2台しかない場合で上手く切り替わらないことがあるようです。以下参考。
      http://heartbeats.jp/hbblog/2013/05/mysql-mha-haproxy.html

    ⑥ 起動前チェック

    ・sshの動作チェック
    [shell] # masterha_check_ssh –conf=/etc/app1.cnf [/shell] OKな場合最終的に以下のように出力される
    [shell] Tue Oct 23 15:02:22 2012 - [info] All SSH connection tests passed successfully. [/shell]
    ・replicationの動作チェック
    [shell] # masterha_check_repl –conf=/etc/app1.cnf [/shell] OKな場合最終的に以下のように出力される(※mysql5.6からはMHAのバージョンによってはbinlog-checksum=NONEにしないとここで失敗するかもしれません)
    [shell] MySQL Replication Health is OK. [/shell] ※失敗するパターン
    レプリケーションのフィルタリングルールが合っていない
    LVSとMHAマネージャが相乗りの場合、チェックタイミングが重複しホスト毎DBサーバに拒否されてしまう(要flush hosts;)

    ...
  • MHA(MasterHighAvailabilityManager)の導入設定

    MHA(MasterHighAvailabilityManager)の導入設定 使用バージョン:mha4mysql-manager-0.53-0、MySQL-5.5

    mha-img1

    ①簡単な利点などの解説

    MHAとはmysqlのマスタ障害時に最新のスレーブをマスタとして他のスレーブの差分を補完しマスタの向き先を変えてくれるプロダクト。
    Heartbeat+mon+mysqlに比べるとreplicationの再構成も行ってくれるので切り替わってもDBがシングルにならないのが利点。(3台以上の構成の場合)

    作者のスライド
    公式サイト
    MHAの制約:mysql5.0以上、SBR(ステートメントベースレプリケーション)の場合LOAD DATA INFILEを使えない
    ※マネージャはadminサーバ、ノードはDBサーバ(マスタ・スレーブ共通)

    ② マネージャにてインストール    ※以下、admサーバから実施

    ・インストール
    [php]

    wget http://mysql-master-ha.googlecode.com/files/mha4mysql-node-0.53-0.noarch.rpm

    wget http://mysql-master-ha.googlecode.com/files/mha4mysql-manager-0.53-0.noarch.rpm

    yum –enablerepo=rpmforge install \

    perl-Config-Tiny \ perl-Time-HiRes \ perl-Log-Dispatch \ perl-Parallel-ForkManager \ perl-Params-Validate

    yum install perl-DBD-MySQL

    rpm -ivh mha4mysql*

    [/php] 入ってなかったら

    [shell]yum install –enablerepo=remi mysql mysql-server perl-DBD-MySQL[/shell] ※マネージャはmysql-serverいらないかも

    ③ ノードにてインストール ※以下、dbサーバから実施
    [shell]

    ...
  • DEVLABはNginx環境に移行しました

    2013年3月末週、DEVLABサイトの環境移管を人知れず行ってました。
    今週の4/2頃まではDEVLABにアクセスした人の中には、サイトが表示されなかったり、不具合が起きていた人もいたかもしれませんが、それらはすべて環境移管に伴う余波としてご理解いただけますと幸いです。まぁ、DEVLABの存在意義と運営方針の一つとして、「インターネットに関わる技術の研究開発のためには恐れずに何でもやってみよう!」というコンセプトを持っているので、今後もISAO社のDEVLABに関わるエンジニアの「好奇心の趣くままに」「衝動的に」「たとえサイトが壊れるとしても」色々とやって行くので、もしサイト来た時に変な動きをしていても ―― お、今何かやっているのかな?――と、温かく見守っていただきたいです(単なるバグの可能性もありますが、それも含みで)。

    そんなこんなで、DEVLABの環境を今までのApache環境から今流行りのNginx環境に移管した次第。
    さらに、noSQLデータベースの「MongoDB」やNode.jsもインストールして、今後は「リアルタイムWEBアプリケーション」の開発もできるように整備したのですが、これはISAO社のエンジニア向けの環境整備なので、DEVLAB側には今のところ影響はないかと。

    さて、巷では「Nginx+リバースプロクシ+WordPress」の構成でWordPressのサイトパフォーマンスが劇的に向上すると云われているので、早速本DEVLABでもその施策を実施してみました。
    結果、1ページ単位での表示レスポンス(レイテンシー)は特に変化はなかった(単ページ単位だと、逆にレスポンスはApacheの方が勝ってました…が、体感速度的には変わらなかった)のだが、Jmeterで負荷テストしてみたら、多数の同時リクエストが発生した際のNginxのレスポンスはかなり驚異的な向上が見られた次第。
    実際にDEVLABのTOPページのリクエストレスポンスを比較したら、Nginx環境ではApacheの約23倍ほどもレスポンスが向上しました。
    いやぁ、Nginxスゴイ!という感想でした。

    ま、DEVLABは常時負荷が高まるほどアクセスされないので、今のところNginx環境も宝の持ち腐れ的な感があるんですけどね…。

    ...
  • Contact Form 7 でエラー時用画面にリダイレクトする方法

    Contact Form 7では、管理画面の、各フォームごとの編集画面の「その他の設定」に、

    on_sent_ok: "window.location.href = 'リダイレクト先のURL';"
    

    と入力すれば、Contact Form 7 の処理終了後に、設定したURLにリダイレクトしてくれます。

    しかし、この設定をすると、成功しても失敗しても同じURLに遷移するため、送信が成功したか失敗したかわかりません。

    画面遷移ではなく、メッセージの表示をさせる場合では、成功時と失敗時でメッセージが切り替えられており、その処理にはJavaScriptを使っているはずです。

    そこで、Contact Form 7 のjsファイルを改変して、エラー時にエラー時用のリダイレクトURLへ遷移させることにします。

    /pm_webform/wp-content/plugins/contact-form-7/includes/js scripts.js

    67行目付近の以下の行

    } else {
    

    の下に以下の行を追加すると、失敗時用のリダイレクトURLへ遷移できます。

    window.location.href = "失敗時用リダイレクトURL";
    

    同様に、57行目付近の以下の行

    } else if (1 == data.mailSent) {
    

    の下に以下の行を追加すると、成功時用のリダイレクトURLへ遷移できます。

    window.location.href = "成功時用リダイレクトURL";
    
    ...
  • Contact Form DB でチェック処理

    Contact Form DB でテーブルへの insert を行う前に、何らかのチェック処理を入れたい場合、フックを使います。

    function my_form_chk( $cf7 ) {
    
                // 入力フォームの値取得
                foreach ($cf7->posted_data as $posted_name => $posted_value) {
                    // 元の値は変えないため別変数へ
                    $posted_name_2 = $posted_name;
                    $posted_value_2 = $posted_value;
    
                    // 値の整形
                    $posted_nameClean = stripslashes($posted_name_2);
    
                    $posted_value_2 = is_array($posted_value_2) ? implode($posted_value_2, ', ') : $posted_value_2;
                    $posted_valueClean = stripslashes($posted_value_2);
    
                    // それぞれの変数に代入
                    if( $posted_nameClean == 'a' ) {
                        $input_param_a = $posted_valueClean;
                    }
                    if( $posted_nameClean == 'b' ) {
                        $input_param_b = $posted_valueClean;
                    }
                    if( $posted_nameClean == 'c' ) {
                        $input_param_c = $posted_valueClean;
                    }
    
                }
    
                // チェック処理
                if ( $input_param_a !== $input_param_b || $input_param_a !== $input_param_c ) {
                      $cf7->skip_mail = true;
                }
    
    }
    
    add_action('wpcf7_before_send_mail', 'my_form_chk', 1);
    

    上記の例では、入力フォームで a,b,c という3つの入力項目があり、その値を受け取って、a と b、または a と c が一致指定なければ $cf7->skip_mail に true を代入しています。

    ...
  • Contact Form DB のテーブルについて

    Contact Form 7 というアンケートフォームのプラグインは、メールを送信するだけなので、DBへデータを格納するようにするプラグインが Contact Form DB です。

    両プラグインをWordPressに入れることで、手軽に入力フォームの内容をDBに格納できます。

    しかし、この Contact Form DB で作られるテーブルが曲者でした。

    WordPressの管理画面から Contact Form DB の管理画面を表示すると、入力フォームから入力されたデータの一覧を表示でき、それを見るとあたかも一つのフォームからの投稿が一つのレコードとして格納されているように見えます。 しかし、実際のテーブルには、入力フォームの input 一つ一つがそれぞれ1レコードとして登録されます。

    入力項目が3つのフォームだと、1回の投稿で3つレコードが登録されるわけで、それぞれのレコードには、それぞれの入力項目の内容のみが、投稿時間と入力フォーム名と入力項目名をキーに記録されるのです。

    ちなみにテーブル構造は下記の通り。

    mysql> DESC wp_cf7dbplugin_submits;
    +-------------+---------------+------+-----+---------+-------+
    | Field       | Type          | Null | Key | Default | Extra |
    +-------------+---------------+------+-----+---------+-------+
    | submit_time | decimal(16,4) | NO   | MUL | NULL    |       |
    | form_name   | varchar(127)  | YES  | MUL | NULL    |       |
    | field_name  | varchar(127)  | YES  | MUL | NULL    |       |
    | field_value | longtext      | YES  |     | NULL    |       |
    | field_order | int(11)       | YES  |     | NULL    |       |
    | file        | longblob      | YES  |     | NULL    |       |
    +-------------+---------------+------+-----+---------+-------+
    6 rows in set (0.03 sec)
    

    インデックス一覧は下記の通り。

    ...
  • iPhoneやiPadで撮影した画像を他のデバイスで見ると自動で回転してしまう場合の対処法

    .iphone { position: relative; height: 123.75px; width: 62.5px; border-radius: 8.75px; margin: 12.5px auto; background: -webkit-linear-gradient(-165deg, rgba(255,255,255,0.4), rgba(255,255,255,0.15) 35%, transparent 35%), -webkit-linear-gradient(top, transparent 21.25px, #222222 21.25px, #151515 102.5px, transparent 102.5px), -webkit-linear-gradient(top, #000, #0a0a0a); background-repeat: no-repeat; background-size: 100% 100%, 55px 100%, 100% 100%; background-position: 0 0, 3.75px 0, 0 0; box-shadow: 0 0 0 0.75px black, -10px -32px 0 -30.75px black, 0 0 0 1.25px #a09f9d, 12.25px -32.5px 0.75px -30.75px #777, 11.5px -32.5px 0.5px -30.75px #ddd, 15.5px -27.75px 0 -26.25px #8e8d8b, 15.5px -28px 0 -26.25px #b4b3b1, 15.5px -28.25px 0 -26.25px #666; } .iphone:after { content: ‘▢’; line-height: 11.5px; text-align: center; font-size: 7px; color: #666; position: absolute; width: 11.5px; height: 11.5px; border-radius: 50%; background: white; bottom: 4.5px; left: 25px; border: 0.5px solid #0a0a0a; background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.85), black); box-shadow: -9.75px -102.5px 0 -5.75px #000f31, -9.75px -102.5px 0 -5.5px #0a1c5a, -10px -102.5px 0 -5.25px #0d1216, -10px -102.5px 0 -4.75px #1b191a, -3px -102.5px 0 -5.5px #333, -2px -102.5px 0 -5.5px #333, -1px -102.5px 0 -5.5px #333, -0px -102.5px 0 -5.5px #333, 1px -102.5px 0 -5.5px #333, 2px -102.5px 0 -5.5px #333, 3px -102.5px 0 -5.5px #333, 4px -102.5px 0 -5.5px #333, 5px -102.5px 0 -5.5px #333, 6px -102.5px 0 -5.5px #333, -3px -102.5px 0 -4.5px #0a0a0a, -2.25px -102.5px 0 -4.5px #0a0a0a, -1.5px -102.5px 0 -4.5px #0a0a0a, -0.75px -102.5px 0 -4.5px #0a0a0a, 0px -102.5px 0 -4.5px #0a0a0a, 0.75px -102.5px 0 -4.5px #0a0a0a, 1.5px -102.5px 0 -4.5px #0a0a0a, 2.25px -102.5px 0 -4.5px #0a0a0a, 3px -102.5px 0 -4.5px #0a0a0a, 3.75px -102.5px 0 -4.5px #0a0a0a, 4.5px -102.5px 0 -4.5px #0a0a0a, 5.25px -102.5px 0 -4.5px #0a0a0a, 6px -102.5px 0 -4.5px #0a0a0a; } .iphone:before { position: absolute; content: ‘’; width: 0.5px; height: 29.25px; background: transparent; top: 10px; left: -1.75px; background-image: -webkit-linear-gradient(left, transparent 0px, transparent 0.25px, #7a7879 0.5px), -webkit-linear-gradient(top, #383838 0.25px, #b9b9b9 0.75px, #b9b9b9 2.5px, #383838 4.75px, #b9b9b9 5.75px, transparent 5.75px, transparent 13.25px, #383838 13.25px, #b9b9b9 13.5px, #dadada 14.5px, #383838 15.5px, black 15.5px, black 16.5px, #383838 16.5px, #b9b9b9 16.75px, #dadada 17px, #383838 17.5px, transparent 17.5px, transparent 25px, #383838 25px, #b9b9b9 25.25px, #dadada 26.25px, #383838 27.25px, black 27.25px, black 28.25px, #383838 28.25px, #b9b9b9 28.5px, #dadada 28.75px, #383838 29.25px); } .display { position: absolute; top: 21.75px; left: 2px; width: 56px; height: 80px; margin: 0; padding: auto; background: #fafafa; border: solid 1px #afafaf; font-size: 24px; font-weight: bold; line-height: 78px; text-align: center; vertical-align: middle; } .rotate_90deg { -moz-transform: rotateZ(90deg); -webkit-transform: rotateZ(90deg); -o-transform: rotateZ(90deg); } .rotate_180deg { -moz-transform: rotateZ(180deg); -webkit-transform: rotateZ(180deg); -o-transform: rotateZ(180deg); } .rotate_270deg { -moz-transform: rotateZ(270deg); -webkit-transform: rotateZ(270deg); -o-transform: rotateZ(270deg); } .device_deg_list { margin: 1em auto 2em; padding: 0; background: #ffffff; border: solid 1px #999999; } .device_deg_list th { padding: 2px; background: #d0d0d0; font-weight: bold; } .device_deg_list td { text-align: center; vertical-align: middle; } .device_deg_list td.odd { background: #f0f0f0; } .device_deg_list td.visual { width: 160px; text-align: center; vertical-align: middle; } .device_deg_list td.orientation { min-width: 120px; } .device_deg_list td.resampling { min-width: 200px; } .exif-value{ clear: both; display: block; font-size: 9px; color: #808080; }

    ...