PHP Eloquentで既存のPDOを利用する – 既存プロジェクトにEloquent追加

既存の独自フレームワークに新しい機能を追加する機会があり、DB周りを確認したのですが、PDOをゴリゴリに使っており、サニタイズも独自だったのでせめて追加の部分はライブラリ(Eloquent)を利用して安全にしたいと思いましたが、追加分の為にフィルター系の処理をEloquentで別で作って管理するのは別の題もあるので、PDOは残しつつ、Eloquentを利用しようとおもいます。

が、 PDOと別でEloquentでコネクションを作るのはトラブルの元なので、既存処理で接続状態になっているPDOを利用します。

いつもだと

$capsule = new Capsule;
$capsule->addConnection([
	'driver' => 'mysql',
	'host' => 'db.local',
	'database' => 'test',
	'username' => 'db_test',
	'password' => 'pass0000',
	'charset' => 'utf8',
	'collation' => 'utf8_unicode_ci',
	'prefix' => '',
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();

上記の様にEloquent単体で利用する場合は、Capsuleを初期化してますが今回は既存のPDOがあるので、下記の様にしてMySqlConnectionを生成してEloquentのModelに渡します。

$existPDO = 既存のPDOオブジェクトを取得();
$mySqlCon = new MySqlConnection($existPDO);
$resolver = new ConnectionResolver([$mySqlCon]);
$resolver->setDefaultConnection(0);
Model::setConnectionResolver($resolver);

上記でSELECTは動作したのですが、Eloquent Modelでsaveが動きませんでした。EloquentのQueryLogを確認しても問題ないクエリですし、エラーも出ません。save()の戻りもtrue。。

試しにEloquentのモデル側でconnectionをdefault指定したのですが、queryエラーが出たので、どうやらsetDefaultConnection(0)では更新時には’default’として働かない?ようなので、下記に変更しました。


$mySqlCon = new MySqlConnection($existPDO);
$resolver = new ConnectionResolver();
$resolver->addConnection('default', $mySqlCon);
$resolver->setDefaultConnection('default');
Model::setConnectionResolver($resolver);

YDLIDAR X2Lを買ってみた( ROSに接続前にWindowsで動作チェック)

ROSでSLAMやりたいので、YDLIDAR X2を購入しました。

YDLIDAR X4はレビューをよく見るのですが、X2Lって(X2と違う?)機種を見つけてX4でもリーズナブルなんですが、さらにサンプリングレートと範囲がさがってるお手軽版のようなので買ってみました。

YDLIDAR X2L

  • スキャン範囲:半径8 m
  • サンプリングレート:3000 Hz
  • 8500円くらい

YDLIDAR X4

  • スキャン範囲:半径10 m
  • サンプリングレート:5000 Hz
  • 12,000 円くらい

スイッチサイエンスは在庫切れになってたので、送料込みでほとんど変わらないのでAmazonで購入しました。

まずは、初期不良は嫌なので、とりあえずparallels desktopで実行しているWindows10で簡単な動作だけチェックしました。

YDLIDAR X2Lのソフトウェア

YDLIDAR X2( L付 )のソフトウェアですが、なぜか公式サイトでX2を選んでSoftをクリックすると、404にリダイレクトされるですが、下記のマニュアルにファームのリンクはありました。

また、PointCloudViewerはX2でもX4でも一緒で起動時に機種を選択するので、YDLIDARX4のリンクからダウンロードしました。

YDLIDAR X2( L付 )のファームウェアダウンロードリンク

YDLIDAR X2のマニュアルダウンロードリンク

Twilio+ngrok Twilio番号に着信があった場合のWebhookのREQUEST (A CALL COMES IN)

Twilioを利用する必要が出たので、ドキュメントを見ながらAPIなどを確認中

いろいろ機能はあるけど、まずは基本の部分を見てみる。
LINEボットなどと同様にTwilioのconsoleから着信時にHTTPのWebhookを設定できるので、サーバーにおいてもいいけど、ngrokが楽だよとドキュメントにもあるので、利用してみる。

ngrokにアカウント登録して、実行するとngrok.ioのサブドメインへのアクセスを実行してるローカルマシンの8000にフォワードしてくれる。

ngrok by @inconshreveable                                       (Ctrl+C to quit)

Session Status                online
Account                       droid (Plan: Free)
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://704be30b.ngrok.io -> http://localhost:8000
Forwarding                    https://704be30b.ngrok.io -> http://localhost:8000

なので、上記でいう「http://704be30b.ngrok.io」を公開URLとして、
Twilioのコンソールで
http://704be30b.ngrok.io/callback.php
を「Programmable Voice」の「受電したい番号」から「A CALL COMES IN」のWebhookURLを設定

?php
// パラメータが見たいだけなので、TwilioSDKは今回不要
error_log(print_r($_REQUEST, true));

上記に加えて受信スクリプトを配置した場所で実行して、Twilioの番号に電話をかける

RC211v:app dp$ php -S localhost:8000
PHP 7.3.5 Development Server started at Fri Jan 24 12:53:18 2020
Listening on http://localhost:8000
Document root is /Users/dp/projects/twilio/app
Press Ctrl-C to quit.
[Fri Jan 24 12:54:13 2020] [::1]:62430 [200]: /callback.php
[Fri Jan 24 12:56:26 2020] Array
(
    [Called] => +125647****Twilioで取得した受電番号
    [ToState] => AL
    [CallerCountry] => JP
    [Direction] => inbound
    [CallerState] =>
    [ToZip] => 35739
    [CallSid] => CA7f52ed3ec************************
    [To] => +125647****Twilioで取得した受電番号
    [CallerZip] =>
    [ToCountry] => US
    [ApiVersion] => 2010-04-01
    [CalledZip] => 35739
    [CalledCity] => ELKMONT
    [CallStatus] => ringing
    [From] => +81801234発信者番号
    [AccountSid] => AC31a5******************************
    [CalledCountry] => US
    [CallerCity] =>
    [Caller] => +81801234発信者番号
    [FromCountry] => JP
    [ToCity] => ELKMONT
    [FromCity] =>
    [CalledState] => AL
    [FromZip] =>
    [FromState] =>
)

カンファレンスなどでFromを判定したりするには、$_REQUESTのformなどを元にすればいいということか。

–>

pyenvで3.7.xのインストールでエラー( ModuleNotFoundError: No module named ‘_ctypes’)

ROS2の環境構築でpyenvで3.7.xをインストールしようとしたらエラーが発生
最小インストール後に、mac用のWifiドライバーなどを軽く入れたくらいなので、ライブラリが足りなかった。

droid@rc211v-usb:~$ pyenv install 3.7.4
Downloading Python-3.7.4.tar.xz...
-> https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tar.xz
Installing Python-3.7.4...

BUILD FAILED (Ubuntu 18.04 using python-build 1.2.16)

Inspect or clean up the working tree at /tmp/python-build.20200109175000.3042
Results logged to /tmp/python-build.20200109175000.3042.log

Last 10 log lines:
  File "/tmp/tmpge7ufapu/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/commands/__init__.py", line 6, in 
  File "/tmp/tmpge7ufapu/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/commands/completion.py", line 6, in 
  File "/tmp/tmpge7ufapu/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/cli/base_command.py", line 20, in 
  File "/tmp/tmpge7ufapu/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/download.py", line 37, in 
  File "/tmp/tmpge7ufapu/pip-19.0.3-py2.py3-none-any.whl/pip/_internal/utils/glibc.py", line 3, in 
  File "/tmp/python-build.20200109175000.3042/Python-3.7.4/Lib/ctypes/__init__.py", line 7, in 
    from _ctypes import Union, Structure, Array
ModuleNotFoundError: No module named '_ctypes'
Makefile:1132: recipe for target 'install' failed
make: *** [install] Error 1
droid@rc211v-usb:~$ sudo apt install libffi-dev

PHPでBOMを削除 ( remove \xEF\xBB\xBF | U+FEFF | efbbbf)

LINE messaging APIでTextファイルを受信した際に、BOMがついており先頭の空白削除がうまく動作しなかったので、PHPでUTF8のBOMを削除する方法がいくつかあったのでメモ

preg_replaceで削除するパターン
今回はこっちを使って削除

return preg_replace("/^\xEF\xBB\xBF/", '', $text);

U+FEFFで指定するパターン

$str = preg_replace('/\x{FEFF}/u', '', $file);

hexで削除するパターン

function remove_utf8_bom_head($text) {
    if(substr(bin2hex($text), 0, 6) === 'efbbbf') {
        $text = substr($text, 3);
    }
    return $text;
}

PHPでBOM削除で検索すると、自分が前に公開していたJSONから削除する記事が上位に表示され恥ずかしい。

https://stackoverflow.com/questions/10290849/how-to-remove-multiple-utf-8-bom-sequences

Vue.js Bootstrap4のd-flexはv-showで表示/非表示が制御出来ない(flex!important)

既存のBootstrap4&Jqueryなサイトでちょっと凝った制御が必要になって、Jqueryでjavascriptとdom側の両方を制御するのが辛くなったので部分的にVueを導入してみま
した。

d-flexのdivをv-showで制御する予定が、常に表示されてしまう。

< div v-show="showInfo" class="d-flex justify-content-around">
 表示されちゃう。
< /div>

以前AngulerJSでも似たことがあって、CSSをみてみたらimportantが設定されてる。
v-showはelementStyleでnoneつけてるけど、importantに負けてるので常に表示になってしまった。

.d-flex {
    display: -ms-flexbox!important;
    display: flex!important;
}

今回はrefから参照したい都合でvue-ifで消したくないので、d-flexをdivで囲って回避しました。

ROS2 pkg create invalid choice: ‘ament_python’ – macにインストールROS2(Dashing)

macにROS2をインストールして、Pythonでパッケージを作ろうとしたら、エラーが発生した。

$ ros2 pkg create --build-type ament_python dp_test_pkg
ros2 pkg create: error: argument --build-type: invalid choice: 'ament_python' (choose from 'cmake', 'ament_cmake')

invalid choice: ‘ament_python’

??
タイプミスかと思ったけど、(choose from ‘cmake’, ‘ament_cmake’)ってpythonは?

調べてみたら、これかな?
「Add Pkg create for ament python #296」
https://github.com/ros2/ros2cli/pull/296
どうやらDashing patch release 4には含まれていないようで、今回macにインストールしたのがまさにDashing patch release 4でpythonがpkgコマンドに含まれていなかった。
Eloquentに更新というか新規インストールして完了

$ros2 pkg create --build-type ament_python dp_test_pkg
(ros@3.7.0) mba:src dp$ tree
.
└── dp_test_pkg
    ├── dp_test_pkg
    │   └── __init__.py
    ├── package.xml
    ├── resource
    │   └── dp_test_pkg
    ├── setup.cfg
    ├── setup.py
    └── test
        ├── test_copyright.py
        ├── test_flake8.py
        └── test_pep257.py

ROS2をUbuntu 18.04.3 LTSにインストール( CMake Error:ASIO_INCLUDE_DIR )

EC2でROS1,ROS2の環境を以前セットアップしたけど、やっぱり手元に欲しいなということでMacにROS2をインストールしましたが、動作させる環境がUbuntuなのでrEFIndでのデュアルブート、Parallelsと悩んだ末、USBにUbuntu18をインストールすれば、別のノート(MacBookPro)でも共有で使えるじゃんと思い、LiveUSBじゃなくて、USBにUbuntu18インストールして、そのUbuntuにROS2をインストール(ちゃんとUEFIの設定などしました)

MacBookで起動するUSBが意外と手間がかかったのは別で説明します。

今回はまっさらなUbuntuでROS2専用にするので、Pyenvは利用せず本当にマニュアル通りに実行
https://index.ros.org/doc/ros2/Installation/Crystal/Linux-Development-Setup/

sudo apt update && sudo apt install curl gnupg2 lsb-release
curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -
sudo sh -c 'echo "deb [arch=amd64,arm64] http://packages.ros.org/ros2/ubuntu `lsb_release -cs` main" > /etc/apt/sources.list.d/ros2-latest.list'

ライブラリのインストール

sudo apt update && sudo apt install -y \
  build-essential \
  cmake \
  git \
  python3-colcon-common-extensions \
  python3-lark-parser \
  python3-pip \
  python-rosdep \
  python3-vcstool \
  wget
# install some pip packages needed for testing
python3 -m pip install -U \
  argcomplete \
  flake8 \
  flake8-blind-except \
  flake8-builtins \
  flake8-class-newline \
  flake8-comprehensions \
  flake8-deprecated \
  flake8-docstrings \
  flake8-import-order \
  flake8-quotes \
  pytest-repeat \
  pytest-rerunfailures \
  pytest \
  pytest-cov \
  pytest-runner \
  setuptools
# install Fast-RTPS dependencies
sudo apt install --no-install-recommends -y \
  libasio-dev \
  libtinyxml2-dev

ワークスペースの作成

mkdir -p ~/ros2_crystal/src
cd ~/ros2_crystal
wget https://raw.githubusercontent.com/ros2/ros2/crystal/ros2.repos
vcs import src < ros2.repos
rosdep update
rosdep install --from-paths src --ignore-src --rosdistro crystal -y --skip-keys "console_bridge fastcdr fastrtps libopensplice67 libopensplice69 rti-connext-dds-5.3.1 urdfdom_headers"
python3 -m pip install -U lark-parser

コードをビルドしたらエラー

colcon build --symlink-install

CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
/home/dp/ros2/src/eProsima/Fast-RTPS/src/cpp/ASIO_INCLUDE_DIR
   used as include directory in directory /home/dp/ros2/src/eProsima/Fast-RTPS/src/cpp

---
Failed   <<< fastrtps	[ Exited with code 1 ]
[5.435s] WARNING:colcon.colcon_ros.task.ament_python.build:Package 'ament_pep257' doesn't explicitly install a marker in the package index (colcon-ros currently does it implicitly but that fallback will be removed in the future)
[5.436s] WARNING:colcon.colcon_ros.task.ament_python.build:Package 'ament_pep257' doesn't explicitly install the 'package.xml' file (colcon-ros currently does it implicitly but that fallback will be removed in the future)
[5.448s] WARNING:asyncio:Unknown child process pid 7474, will report returncode 255
Aborted  <<< ament_cmake_core
Aborted  <<< ament_pep257
Aborted  <<< ament_cppcheck

Summary: 4 packages finished [5.43s]
  1 package failed: fastrtps
  3 packages aborted: ament_cmake_core ament_cppcheck ament_pep257
  1 package had stderr output: fastrtps
  225 packages not processed

依存ライブラリ(libasio-dev)が足りないらしい。

sudo apt install libasio-dev

ビルドが通りました。

colcon build --symlink-install
しばらく待つ
Starting >>> tf2_msgs
[29min 39.6s] [140/233 complete] [4 ongoing] [rviz_ogre_vendor:build 74% - 25min 38.7s] [sensor_msgs:build 33% - 1min 56.1s] .

ROS2をMacbookにインストールする( macOS Catalina)けど大量のエラー : Library not loaded: /usr/local/opt/poco/lib/libPocoFoundation

いつもはUbuntuだけど、macでもROS2にもインストールできるそうなんで、手持ちのMacbookAirにインストールしてみる。

公式ドキュメント
https://index.ros.org/doc/ros2/Installation/Dashing/OSX-Install-Binary/

まずはbrewで必要な物をインストール

brew install asio tinyxml2
brew install tinyxml eigen pcre poco
brew install opencv
brew install openssl
echo "export OPENSSL_ROOT_DIR=$(brew --prefix openssl)" >> ~/.bashrc
brew install qt freetype assimp
brew install log4cxx
brew install cunit
brew install pyqt5
ln -s /usr/local/share/sip/Qt5 /usr/local/share/sip/PyQt5
brew install graphviz

次にPythonのモジュールを入れる。
virtualEnvでROS2用に環境を作る。

mba:pyenv dp$ virtualenv ros@3.7.0
mba:pyenv dp$ source ros\@3.7.0/bin/activate
(ros@3.7.0) mba:pyenv dp$ pip install pygraphviz pydot lxml catkin_pkg empy lark-parser pyparsing pyyaml setuptools argcomplete

Macの場合、SIP(System Integrity Protection)の無効化をしないと親子プロセスで変数の継承ができないらしいので、OFFにしようと思ったら

$ csrutil status
System Integrity Protection status: disabled.

SIPがdisabledになってる。
Macのログイン画面の背景変更の時かな?
OFFだったので、スルーする。

ROS2のダウンロード
https://github.com/ros2/ros2/releases

mba:pyenv dp$ mkdir -p ~/ros2_crystal
mba:pyenv dp$ cd ~/ros2_crystal
mba:pyenv dp$ wget https://github.com/ros2/ros2/releases/download/release-dashing-20191018/ros2-dashing-20191018-macos-amd64.tar.bz2
mba:pyenv dp$ tar xf ros2-dashing-20191018-macos-amd64.tar.bz2 
mba:pyenv dp$ . ~/ros2_crystal/ros2-osx/setup.bash

ROS2インストール完了したはずなので
デモを起動したら、エラー。。。

mba:pyenv dp$ ros2 run mba:pyenv dp$ demo_nodes_cpp talker

Failed to load entry point 'delete': dlopen(/Users/dp/ros2_crystal/ros2-osx/lib/python3.7/site-packages/rclpy/_rclpy.cpython-37m-darwin.so, 2): Library not loaded: /usr/local/opt/tinyxml2/lib/libtinyxml2.7.dylib
  Referenced from: /Users/dp/ros2_crystal/ros2-osx/lib/libbuiltin_interfaces__rosidl_typesupport_fastrtps_c.dylib
  Reason: image not found
The C extension '/Users/dp/ros2_crystal/ros2-osx/lib/python3.7/site-packages/rclpy/_rclpy.cpython-37m-darwin.so' failed to be imported while being present on the system. Please refer to 'https://index.ros.org/doc/ros2/Troubleshooting/#import-failing-even-with-library-present-on-the-system' for possible solutions
Failed to load entry point 'info': dlopen(/Users/dp/ros2_crystal/ros2-osx/lib/python3.7/site-packages/rosbag2_transport/_rosbag2_transport_py.cpython-37m-darwin.so, 2): Library not loaded: /usr/local/opt/poco/lib/libPocoFoundation.63.dylib
  Referenced from: /Users/dp/ros2_crystal/ros2-osx/lib/python3.7/site-packages/rosbag2_transport/_rosbag2_transport_py.cpython-37m-darwin.so
  Reason: image not found
The C extension '/Users/dp/ros2_crystal/ros2-osx/lib/python3.7/site-packages/rclpy/_rclpy.cpython-37m-darwin.so' failed to be imported while being present on the system. Please refer to 'https://index.ros.org/doc/ros2/Troubleshooting/#import-failing-even-with-library-present-on-the-system' for possible solutions
dyld: Library not loaded: /usr/local/opt/poco/lib/libPocoFoundation.63.dylib
  Referenced from: /Users/dp/ros2_crystal/ros2-osx/lib/librosidl_typesupport_c.dylib
  Reason: image not found

調べてみたらlibtinyxml2のバージョンに問題があるみたい。
Homebewでインストール済みのバージョンはtinyxml2(7.1.0)だけど7系は動かないとのこと
「ROS 2 fails to build against tinyxml2 7.0.0 #671」
https://github.com/ros2/ros2/issues/671
Homebewでインストール済みのtinyxml2をダウングレード
https://github.com/ros2/ros2/issues/625

brew unlink tinyxml2
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/da9a96f093a57eb8ac7c9470c1ec04fd1823a37a/Formula/tinyxml2.rb
brew switch tinyxml2 6.2.0

またdylibが見つからないのはlinkを作成

$ ll /usr/local/opt/poco/lib/libPocoFoundatio*
-rw-r--r--  1 dp  staff  1701096 12 19 23:12 /usr/local/opt/poco/lib/libPocoFoundation.64.dylib
lrwxr-xr-x  1 dp  staff       26  9 18 17:03 /usr/local/opt/poco/lib/libPocoFoundation.dylib -> libPocoFoundation.64.dylib
ln -s libPocoFoundation.dylib libPocoFoundation.63.dylib
$ ll /usr/local/opt/tinyxml2/lib/libtinyxm*
lrwxr-xr-x  1 yuta  staff     23  4  6  2018 /usr/local/opt/tinyxml2/lib/libtinyxml2.6.dylib -> libtinyxml2.6.2.0.dylib
lrwxr-xr-x  1 yuta  staff     19  4  6  2018 /usr/local/opt/tinyxml2/lib/libtinyxml2.dylib -> libtinyxml2.6.dylib
$ cd /usr/local/opt/tinyxml2/lib/
$ ln -s libtinyxml2.6.2.0.dylib libtinyxml2.7.dylib

console_bridgeのインストールを忘れてた。

brew install console_bridge

これで対応できたと思ったけどpipモジュールが見つからないエラーが大量。。

(ros@3.7.0) mba:lib dp$ ros2 -help
Failed to load entry point 'test': No module named 'yaml'
Failed to load entry point 'launch': No module named 'yaml'
Failed to load entry point 'send_goal': No module named 'yaml'
Failed to load entry point 'list': No module named 'yaml'
Failed to load entry point 'load': No module named 'yaml'
Failed to load entry point 'standalone': No module named 'yaml'

これはpyenv使ってインストールした関係なので、パスを設定してからsetup.shを実行してOK

export PYTHONPATH=~/pyenv/ros\@3.7.0/lib/python3.7/site-packages/
$ which python
/Users/dp/pyenv/ros@3.7.0/bin/python
$. ~/ros/dashing/setup.bash

まだ自分マックはbashを使ってる。
間違えてsetup.shを実行したらエラーがでてしばらく悩んでしまった。

export PYTHONPATH=~/pyenv/ros\@3.7.0/lib/python3.7/site-packages/
$. ~/ros/dashing/setup.sh
The build time path "/Users/osrf/jenkins-agent/workspace/packaging_osx/ws/install" doesn't exist. Either source a script for a different shell or set the environment variable "COLCON_CURRENT_PREFIX" explicitly.

AmazonLinux2でLet’s Encryptがエラー – Sorry, I don’t know how to bootstrap Certbot on your operating system!

久しぶりにAmazonLinux2に触ったら
Let’s Encryptのインストール後、certbot-auto実行でエラーが発生

[ec2-user@ip-99-99-99-99 certbot]$ sudo ./certbot-auto
Sorry, I don't know how to bootstrap Certbot on your operating system!

You will need to install OS dependencies, configure virtualenv, and run pip install manually.
Please see https://letsencrypt.readthedocs.org/en/latest/contributing.html#prerequisites
for more info.

certbot-autoを開くと、Amazon Linuxの判定があるけどこれを修正する必要があるらしい。

elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then
  Bootstrap() {
    ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon
  }
  BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION"

確かに、判定できない。。

[ec2-user@ip-99-99-99-99 certbot]$ grep -iq "Amazon Linux" /etc/issue
[ec2-user@ip-99-99-99-99 certbot]$
[ec2-user@ip-99-99-99-99 certbot]$ cat /etc/issue
\S
Kernel \r on an \m

[ec2-user@ip-99-99-99-99 certbot]$

これに書き換える。

elif grep -i "Amazon Linux" /etc/issue > /dev/null 2>&1 || grep 'cpe:.*:amazon_linux:2' /etc/os-release > /dev/null 2>&1; then
  Bootstrap() {
    ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon
  }
  BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION"

参考-> Amazon Linux 2でLet’s Encryptが使えない