【cakephp】paginateでのorderが効かなかった時の対応

また、たまにしか触らないcakephpではまった。しかもバージョン1
paginateでなぜかorderだけ効かなかった

こんな感じの基本的?なもので他では動いていたのに。。。

$this->paginate = array(
  "fields" => array(
    "Table.field1",
    "Table.field2",
    ),
  "order" => array(
    "Table.field1 asc",
    "Table.field2 desc",
  ),
  "limit" => 30,
);
$this->paginate("Table", array(
  "and" => array(
    "Table.deleted" => 0
  ),
));

原因はurlパラメータにsortという名前の含まれていたのが原因だったぽい。
http://example.com/sort:1/・・・動かない
http://example.com/sort2:1/・・・動いた

こんなことありえるのか。。。このアプリケーションの問題なのかcakephpの仕組みの問題なのか追求する気力はないのでとりあえず完了としよう。。。以上です

【ionic】ionic buildでgulpを実行する

今回やりたかったのは、ionic buildでもgulpが動くようにしたかった。

https://codepen.io/leob6/post/quick-tip-using-gulp-to-customize-the-serve-run-and-build-process-for-your-ionic-framework-apps
こちらにやり方書いてあった。

gulpfile.jsの例

gulp.task("js.concat-controllers", function() {
  return gulp.src("www/js/controllers/**/*.js")
    .pipe(concat("controllers.js"))
    .pipe(gulp.dest("www/build/js"));
});

今回はwww/js/controllers以下のファイルをwww/build/js/controller.jsに結合して出力するようにしてみた。

で、さらに以下を追加

gulp.task('build:before', ['js.concat-controllers']);

で、以下を実行するとちゃんとcontroller.jsが生成されることが確認できました。

$ ionic build

以上です。

git mergeやり直し手順メモ

マージし直すときの手順メモ。

いちおう今回はマージ先のブランチを残したい場合。で、この例だとgit reset でやり直せるけど今回やりたかったのはpushしたマージをやり直したかったのでこの形になった。

最初のマージ

$ git branch
* dev1
dev2

$ git merge dev2
Auto-merging test
CONFLICT (content): Merge conflict in test
Automatic merge failed; fix conflicts and then commit the result.

〜コンフリクトを修正〜

$ git commit -m "マージするよ"

失敗に気づく・・・

マージやりなおす

$ git log --graph

*   commit xxxx3
|\  Merge: xxxx1 xxxx2
| | 
| |     マージ
| | 
| * commit xxxx2
| | 
| |     dev2で追加
| | 
* | commit xxxx1
|/
|       dev1で追加
| 
*  

# マージ前の状態で別ブランチを作る
$ git checkout xxxx1

$ git branch
* (HEAD detached at xxxx1)
  dev1
  dev2

$ git checkout -b work

# マージしなおす
$ git merge dev2
Auto-merging test
CONFLICT (content): Merge conflict in test
Automatic merge failed; fix conflicts and then commit the result.

〜コンフリクトを修正〜

# workブランチをdev1ブランチに置き換える
$ git merge -s ours dev1
$ git checkout dev1
$ git merge work

こんなやり方でいいのかわからないので、もっとよいやり方教えてください。以上です

無料で使えるSEOツールまとめメモ

最近、SEOツールを調べる機会があったのでメモしておく。っていっても使いこなせないのだが。。また調べることがありそうなのでそのときのためにメモしておく。

SEOチェキ

http://seocheki.net/
・発リンク数(外部リンク、内部リンク)
・Alexa traffic rank
ドメイン取得年月
1日200回までの使用制限がある。

Moz

https://moz.com/researchtools/ose/

ドメインオーソリティ(DOMAIN AUTHORITY)
・ページオーソリティ(PAGE AUTHORITY)
・ルートドメインへのリンク数(Root Domains)
トータルリンク数(Total Links)

無料アカウントつくれば何回でも使えそう

SEO TOOLS

http://www.seotools.jp/seoanalyze/

Googleページランク
・キーワード率(総単語数、頻出単語のキーワード率)
ドメイン取得年月

Majestic

https://ja.majestic.com/

・外部被リンク
参照元ドメイン
参照元IP

Similar Web

https://www.similarweb.com/

・訪問者数(Total Visits)
・滞在時間(Avg Visit Duration)
・平均ページビュー(Page Per Visit)
直帰率(Bounce Rate)

Pagespeed Insights

https://developers.google.com/speed/pagespeed/insights/?hl=ja

ページを解析して、修正が必要なところを指摘してくれる。PCとモバイルとそれぞれ対象。APIもある。

その他Google

site://example.com
link://example.com
Googleにインデックスされてるかの確認と被リンクされているかを確認できる。

他にもいろいろありそうだけどとりあえずこんな感じ。以上です。

【ionic】タブの中に入れ子でタブをいれる方法メモ - ion-tabs

はじめに

今回やりたかったのはこんな画面。
イマイチできるのか不安だったけど無事できた。

f:id:yoppy0066:20170427004140g:plain:w250

ionicは海外の情報が多くて「ionic tabs inside tabs」とか「ionic tab nested」ってみんな検索してるみたい。

イメージはこんなかんじ
f:id:yoppy0066:20170427004202p:plain

アプリ特有?かわからないけど、タブごとにナビゲーションをつくってタブごとに遷移していくようなイメージ。

実装

app.js

angular.module('ionicApp', ['ionic'])

  .config(function($stateProvider, $urlRouterProvider) {

    $stateProvider

    // ベースとなるタブ
      .state('tabs', {
        url: "/tab",
        abstract: true,
        templateUrl: "templates/tabs.html"
      })

    // ホーム
      .state('tabs.home', {
        url: "/home",
        views: {
          'home-tab': {
            templateUrl: "templates/home.html"
          }
        }
      })

    // ニュースタブの中のタブ
      .state('tabs.news', {
        url: "/news",
        abstract: true,
        views: {
          'news-tab': {
            templateUrl: "templates/news.html"
          }
        }
      })

    // 新着ニュース一覧
      .state('tabs.news.new', {
        url: "/new",
        views: {
          'news-page': {
            templateUrl: "templates/news-new.html"
          }
        }
      })

    // お気に入りニュース一覧
      .state('tabs.news.favorite', {
        url: "/favorite",
        views: {
          'favorite-page': {
            templateUrl: "templates/news-favorite.html"
          }
        }
      })

    // 新着ニュース詳細
      .state('tabs.news.new-detail', {
        url: "/new-detail",
        views: {
          'news-page': {
            templateUrl: "templates/news-detail.html"
          }
        }
      })

    // お気に入りニュース詳細
      .state('tabs.news.favorite-detail', {
        url: "/favorite-detail",
        views: {
          'favorite-page': {
            templateUrl: "templates/news-detail.html"
          }
        }
      })
    ;

    $urlRouterProvider.otherwise("/tab/home");

  });

templates/tabs.html

<ion-tabs class="tabs-icon-top tabs-positive">
  <ion-tab title="ホーム" icon="ion-home" href="#/tab/home">
    <ion-nav-view name="home-tab"></ion-nav-view>
  </ion-tab>
  <ion-tab title="ニュース" icon="ion-document" href="#/tab/news/new">
    <ion-nav-view name="news-tab"></ion-nav-view>
  </ion-tab>
</ion-tabs>

templates/home.html

<ion-view title="ホーム">
  <ion-content class="padding">
    <p>ホーム</p>
  </ion-content>
</ion-view>

templates/news.html

<ion-view title="ニュース">
  <ion-tabs class="tabs-icon-top tabs-positive tabs-top">
    <ion-tab title="新着" href="#/tab/news/new" icon="ion-ios-clock-outline">
      <ion-nav-view name="news-page"></ion-nav-view>
    </ion-tab>
    <ion-tab title="お気に入り" href="#/tab/news/favorite" icon="ion-bookmark">
      <ion-nav-view name="favorite-page"></ion-nav-view>
    </ion-tab>
  </ion-tabs>
</ion-view>

templates/news-new.html

<ion-view title="新着ニュース一覧">
  <ion-content class="padding has-tabs-top">
    <p>新着ニュース一覧</p>
    <a href="#/tab/news/new-detail">詳細へ</a>
  </ion-content>
</ion-view>

templates/news-favorite.html

<ion-view title="お気に入りニュース一覧">
  <ion-content class="padding has-tabs-top">
    <p>お気に入りニュース一覧</p>
    <a href="#/tab/news/favorite-detail">詳細へ</a>
  </ion-content>
</ion-view>

templates/news-detail.html

<ion-view title="ニュース詳細">
  <ion-content class="padding has-tabs-top">
    <p>ニュース詳細</p>
  </ion-content>
</ion-view>

ずらずら書いたけど以上です。

参考
http://codepen.io/Glitchbone/pen/GEcae

【angularjs】$http.postでのjson送信でoptions method not allowedを解決した時のメモ

やりたかったことは、localhostのサーバーで動いてるクライアントHTMLからサーバー上のAPIにPOSTでJSONを送るということでした。
なんかうまくいかなくて色々やってみたけど、結論からいうとangular側は以下のコードでいけました。

クライアント側

$http.post("/path/to/api",{
  param1: "value1",                                                                                                                                                                                                
  param2: "value2"                                                                                                                                                                                                 
});

問題はサーバーサイドにありました。レスポンスヘッダーに以下を追記したらいけました。

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"

ちなみにfuelphpだと

Input::json(); // array("param1" => "value1", "param2" => "value2");
試したけどうまくいかなかったこと
// REQUEST METHODは解決するがFuelPHPでInput::jsonで取得できない                                                                                                                                                    
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';                                                                                                                         

// REQUEST METHODは解決するがFuelPHPでInput::jsonで取得できない                                                                                                                                                    
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;application/json;charset=utf-8';                                                                                          

// REQUEST METHODがOPTIONSとなり、「405 Method Not Allowed」                                                                                                                                                       
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json';                                                                                                                                          

残念ながら丸半日以上でつぶれました。。。以上です

【fuelphp】Redisでロック・排他制御する方法メモ

APIの実装でクライアントからの2重送信対策にRedisを使ってみた。
MySQLでやろうとも思ったのだが負荷のことを考えるとRedisの方がいいのかなという判断。

$token = クライアントから送られるトークン 

$redis = Redis::forge();
if (1 === $redis->setnx($token, 1)) {
  // ロックに成功したら有効期限に1分をセット                                                                                                                                                                 
  $redis->expireAt($token, time() + 60);
} else {
  // ロックに失敗(同じキーが登録済み)なら処理中断                                                                                                                                                                  
}

当初は$redist->get($key)で取得できたら、2重送信と判定していたのだがこれだと全く同タイミングだと正しく判定できない(排他制御できてない)。で、ググてみるとsetnxを使えとのことでした。動作確認したら期待通りの挙動となりました。以上です。