MAMPのmySQLをコマンドラインから使うときにソケットファイルが無い場合。
ソケット(mysql.sock)がApplication/MAMP以下にあるのでリンク貼るある。
ln -s /Applications/MAMP/tmp/mysql/mysql.sock /tmp/mysql.sock
ソケット(mysql.sock)がApplication/MAMP以下にあるのでリンク貼るある。
ln -s /Applications/MAMP/tmp/mysql/mysql.sock /tmp/mysql.sock
エラーの取得
$product = $this->Products->newEntity([
'id' => null,
'name'=>'商品名',
'supplier_id'=>null,
'price'=>null
]);
$product->getErrors(); //全てのエラー
$product->getError('supplier_id');//フィールド指定
エラーの設定
$orderDetail->setError('name',[
'hogehoge'=>'テストのエラーです。'
]);
//設定したエラー内容は以下になります。
[
'name' => [
'hogehoge' => 'テストのエラーです。'
]
]
結果をいうととてもシンプル使いやすくて○。
$ composer require robotusers/cakephp-excel
bootstrap.php最後に追記
$ bin/cake plugin load Robotusers/Excel -b
どこか使うところでuse
use RobotusersExcelRegistry;
あとは読み込んでentityとして取得できました。
$table = $registry->get('/your/excel/path/filename.xlsx');
$rows = $table->find()->all();
foreach ($rows as $key => $row) {
debug($row);
}
exit;
あと便利そうなオプション、
開始行を指定、開始列指定、列名(=フィールド名)を変換するマップとか。
“
$table = $registry->get($xls,null, []);
“`
cakephp3でプラグインいろいろ選んでいたけど一番余分なものいらなくシンプルに使えそうなUpload Plugin 3.0を使ってみました。
Upload Plugin 3.0
https://github.com/FriendsOfCake/cakephp-upload
(ブログ記事シンプルで判りやすい)
まずプロジェクトのルートでコンポーザーのコマンドでインストール
composer require josegonzalez/cakephp-upload
cakeコマンドでbootstrap.phpに追記
bin/cake plugin load Josegonzalez/Upload
テーブルに photo,dir フィールドを追加(varchar(255)

モデルクラスにプラグイン利用の記述を追記
public function initialize(array $config)
{
$this->addBehavior('Josegonzalez/Upload.Upload', [
'photo' => [
'path' => 'static{DS}{model}{DS}{field}{DS}'
'nameCallback' => function ($data, $settings) {
return uniqid().'-'.strtolower($data['name']);
}
],
]);
<?= $this->Form->create($product, ['type' => 'file']) ?>
<?= $this->Form->control('photo', ['type' => 'file']); ?>
webroot/file ディレクトリを作成(要書き込みパーミッション)
いざアップロード
無事アップロードできました。

最初ビヘイビアの記述に以下のようにフィールド名のみを書いていると
$this->addBehavior('Josegonzalez/Upload.Upload', [
'photo'
]);
タイプがダメよとエラーが。
Invalid data type, must be an array or ArrayAccess instance.
アップロードのファイルタイプと一瞬おもったけど。これはプラグインがオプションを拾うところで、Array を期待するがStringなのでエラーになっていた。
以下のように空のArrayにしたらOKだった。
$this->addBehavior('Josegonzalez/Upload.Upload', [
'photo' => []
]);
オプションのpathを記述した場合に{primaryKey}がAdd(新規)で使えなく断念した
$this->addBehavior('Josegonzalez/Upload.Upload', [
'photo' => [
'path' => 'static{DS}{model}{DS}{field}{DS}{primaryKey}'
]
]);
これでちゃんと写真が取得できるようになった。
object(AppModelEntityProduct) {
'id' => (int) 1,
'supplier_id' => '1',
'status_id' => (int) 11,
'name' => 'テストセット',
'description' => 'テスト',
'unit_price' => (int) 1304,
'photo' => '008.jpg',
'dir' => 'static/Products/photo/1',
'note' => '',
'created' => object(CakeI18nFrozenTime) {
商品(りんご、ばなな、メロン)テーブルがあって、単品の商品とかセット商品とかをうまく組み合わせたい。
例えば。。
フルーツ盛り合わせ(りんごx1、ばななx2、メロンx1) とか
りんご盛り(りんごx20) とか
などなどとにかく複雑なものがあとから来ても大丈夫な設計を考えて、以下のような感じにしてみた。

productsテーブルをproductsテーブル自身と多対多で繋いで中間のテーブルはproducts_componentsとするで、数量は中間テーブルに ‘num’ として持っていたら何にでもなりそうな気がする。
Modelは ProductsTable.phpを中心に以下のアソシエーションを貼る。
[Products]
belongsToMany : [Components]
hasMany : [ProductsComponents]
以下のように2つのアソシエーションを指定。
$this->hasMany('ProductsComponents', [
'className'=>'ProductsComponents',
'foreignKey'=>'product_id'
]);
$this->belongsToMany('Components', [
'joinTable' => 'products_components',
'className'=>'Components',
'foreignKey'=>'product_id',
'targetForeignKey' => 'component_id'
]);
(細かい個別の条件によるとおもうのですが、途中はまって’targetForeignKey’ が無いとうまく動かないケースがあって入れてますが実際はいらないかも><..)
これは’Components’って名前をつけているけど実態は ’Products’テーブルで、
Productsが、ProductsをbelongsToManyとするとおかしくなったので別名に。
実態はこんな感じ。
class ComponentsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('products');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->belongsToMany('Products', [
'joinTable' => 'products_components',
'className'=> 'Products',
'foreignKey'=>'component_id',
'targetForeignKey' => 'product_id'
]);
}
}
これは普通に定義のみ(あとでバリデーションとかetc入れる予定)
<?php
class ProductsComponentsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('products_components');
$this->setPrimaryKey('id');
}
}
基本belongsToMany(多対多)のばあいは、FormHelperでチェックボックスがだせるのですが、numを入力させたりがあるのでフォームは直に書いて行きます。
まずは belongsToManyのComponents用のフォーム
これはCakePHPが書き出すものを真似る感じで。最初のvalueが空のはチェックが無かった場合に値がUndefindにならない用。
<input type="hidden" name="components[_ids]" value="">
<input type="hidden" name="components[_ids][]" value="1"> アイテム1
<input type="hidden" name="components[_ids][]" value="2"> アイテム2
<input type="hidden" name="components[_ids][]" value="3"> アイテム3
で、もう一つそれぞれに対してnum用のフィールドが必要で、以下のように、‘productsComponents’ で指します。(と言うのは、上の多対多はProductsテーブルのsaveでまとめて保存できたが、中間テーブルに保存するnumがsaveの中では、一回で保存できなかったため、分けています。(afterSaveとかでどうにかとも考えたのですが、Controllerに書いて見通しが良いほうが簡単そうだったので。)
<input type="text" name="productsComponents[{component_id}][num]" value="1">個
component_id の部分は、セットに含まれるproductsのid (=componentsテーブルのid)
で、2つのフォームを合わせて以下のようにフォームを生成。
<input type="hidden" name="components[_ids]" value="">
<input type="hidden" name="components[_ids][]" value="1"> りんご x
<input type="text" name="productsComponents[1][num]" value="1">個
基本的には belongsToMany : Componentsのところは何も考えず、Productsをsave()すれば勝手に保存される。(削除してのも消してくれる)
で、中間テーブルのnumの保存方法は一旦Productsを保存してそのあと中間テーブルのnumを保存する手順にしています。
$product = $this->Products->patchEntity($product, $this->request->getData(),['associated' => ['Suppliers','Statuses','Components']]);
$connection = ConnectionManager::get('default');
$connection->begin();
if ($this->Products->save($product)) {
if(!empty($product->productsComponents)){
foreach($product->productsComponents as $component_id => $item){
$query = $this->Products->ProductsComponents->query();
$query->update()
->set(['num' => (int)$item['num']])
->where(['product_id' => $id,'component_id'=>$component_id])
->execute();
}
}
$this->Flash->success(__('The product has been saved.'));
$connection->commit();
return $this->redirect(['action' => 'index']);
}else{
//error
}
Cakephpで作っていて、いろいろController/ActionでCSSやJavascriptをうまく使えないかと思って、定数 > JS/HTMLのClass名へ落とし込んでみました。(なにかもっとスマートにできそうな気もします。)
まずAppController.phpで。Routerをuse
use CakeRoutingRouter;
config以下とか、どこかでやったほうが良いとか有りますが、
action,controller名なども加えてまとめたくこの場所。
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
define('FULL_BASE_URL',Router::fullBaseUrl());
define('CONTROLLER_NAME',strtolower($this->name));
define('ACTION_NAME',strtolower($this->request->action));
で、HTML側
JavaScriptの定数用してと、bodyクラスにconntroller-action名を割当
<script>
var FULL_BASE_URL = '<?= h(FULL_BASE_URL) ?>';
var CONTROLLER_NAME = '<?= h(CONTROLLER_NAME) ?>';
var ACTION_NAME = '<?= h(ACTION_NAME) ?>';
</script>
</head>
<body class="<?= h(CONTROLLER_NAME.'-'.ACTION_NAME) ?>">
full_base_urlは jsでも取れるとか気になりますが、見通しがよくなるようにまとめてみました。
利用するコントローラーでまずConnectionManagerをuse;
use CakeDatasourceConnectionManager;
Cakephp2と基本的には同じく、begin()で初めて、処理が終わってcommit() 、例外時は rollback()。
$connection = ConnectionManager::get('default');
$connection->begin();
if ($this->Products->save($product)){
$connection->commit(); //OK時
}else{
$connection->rollback(); //エラー時
}
commit()を行わずに終了した場合は、保存されなかった。
(2017.10.03現在の ver3.5.0にて確認)
バーコードには1次元バーコード(お菓子とかパン缶詰とかについている俗に言うバーコードハゲ的な者)
2次元バーコードとは、QRコード等、横方向だけでなく縦にも情報を持つもの総称
今回は、業務上1次元バーコードについて調べた。
| JAN(EAN、UPC) | CODE39 | CODE128 | NW–7 | ITF | |
|---|---|---|---|---|---|
| 文字 | 数字0–9 | 数字と、アルファベット/記号は一部 | 数字/アルファベット/記号(フルASC) | 数字と、アルファベット/記号は一部 | 数字0–9 |
| 桁数 | 13 or 8 | 可変 | 可変 | 可変 | 14 or 16 |
| 標準タイプ13桁 | 標準タイプ13桁 | 短縮タイプ8桁 | |
|---|---|---|---|
| 詳細 | 2001年1月以後の登録 | 2000年12月以前の登録 | 小さい物用 |
| 説明 | GS1事業者コード(9桁) | 商品アイテムコード(3桁) | チェックデジット(1桁) |
|---|---|---|---|
| コード例 | 458240192 | 927 | 3 |
| 設定者 | 流通システム開発センターが付与 | 事業者にて設定 | 計算式で算出 |
githubでスターの一番多かった上のもので大丈夫かな。ライセンスあGNU
| 名称 | url | ライセンス、料金など |
|---|---|---|
| PHP Barcode Generator | https://github.com/picqer/php-barcode-generator | GNU Lesser General Public License v3.0 |
| php-barcode | https://github.com/rlt3/php-barcode/ | MIT License |
| Barcode.php | http://www.pao.ac/barcode.php/ | 21,600 |
| Image_Barcode2 | https://pear.php.net/package/Image_Barcode2/download | PHP License |
| PHP-Barcode | https://ashberg.de/php-barcode/download/ | GNU General Public License |
git ほげほげ、gitほげほげ、何度も打ち込んで大変なのでDashにスニペットとして登録してタイプ数をへらしてみました。

よく使うものを登録しておけばタイプ数が約半分くらいになります。
git status の10文字が、 gits; 5文字。
git commit -m ‘’ の16文字が、gitc; の5文字。
git commit -am ‘’ の17文字が、 gitam; の6文字。
git commit –amendとかも。18文字タイプが、 ‘gitamd;’ 7文字。
とかなり楽になり、細かいコミットが面倒でなく1つの事 = 1コミットでも面倒でなくなりそうです。

以前のCakePHP2では、Modelのクラスのプロパティー $orderに指定すればよかったですが、なくなっているので以下のようにbeforeFindメソッドをTableクラスに追加で可能。
class StatusesTable extends Table
{
*
*
*
public function beforeFind(Event $event ,Query $query, $options, $primary) {
if(!isset($query->order)){
$query->order(['Statuses.type'=>'ASC']);
}
return $query;
}
*
*
*
すこしはまったのが、以前までの感覚で ‘Status.type’ ってやると、エラーとなった。
Table = 複数系との思考に切り替えないとだ。(Statuses.typeでOK)
Powered by WordPress & Theme by Anders Norén