ラベル PHP の投稿を表示しています。 すべての投稿を表示
ラベル PHP の投稿を表示しています。 すべての投稿を表示

2018年4月20日金曜日

動画をパラパラアニメに変換するサービスを5日で作りました

どうも、俺です。

 やれライブ配信だ、やれ動画広告だ、と騒がれがちな昨今ですが、
 動画ファイル(.mp4 .mov)をパラパラアニメに変換するサービスを作りました。







パラパラ動画です。


変換したい動画ファイルを選択し、
フレームレート(fps)と再生速度、出力フォーマット(gif または webp)を選んでアップロードすれば、
見事なパラパラアニメが完成します。

aPNGにも変換できるようにしてるんですが、
如何せん変換後のファイルサイズがバカでかいので、取りやめました。
仕事の合間に作ったので結構日数かかりました。

素のPHP + TwitterBootstrap3 + SQLiteです。
ページデザインはこれ以上オシャレにできませんToT

「ブログにパラパラ画像を載せたい!」というような場面で是非活用してもらえればうれしいです。



以上でぇぇぇす。

2017年3月13日月曜日

php: error while loading shared libraries: libpq.so.5: cannot open shared object fileが出る

どうも俺です。

構築したばかりのサーバーで
$ php -v
と打ってphpのバージョンを確認しようとしたら、

php: error while loading shared libraries: libpq.so.5: cannot open shared object file: No such file or directory
というエラーが出ちゃいました。

エラー内容のとおり、
何かしらの共有ライブラリ(今回はlibpq.so.5)が読み込めないというエラーです。

ちなみにrootになって同じコマンドを打つと

# php -v
PHP 5.6.24 (cli) (built: Mar  2 2017 15:32:45) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
と問題なく実行されます。
つまり、今回のエラーは何かしらのPermissionが関係してるだろうと予想つきました。

こういう場合は共有ライブラリの依存関係を確認してみます。

$ ldd /usr/local/bin/php
        linux-vdso.so.1 =>  (0x00007ffda23d7000)
        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f2982411000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f29821fa000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f2981fe0000)
        libpq.so.5 => not found
        librt.so.1 => /lib64/librt.so.1 (0x00007f2981dd7000)
        libcurl.so.4 => /lib64/libcurl.so.4 (0x00007f2981b6e000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f298186c000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f2981667000)
        libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f298144e000)
        libxml2.so.2 => /lib64/libxml2.so.2 (0x00007f29810e4000)

注目すべきは、libpq.so.5 => not found となっているところです。


今度はrootになって確認してみます。

# ldd /usr/local/bin/php
        linux-vdso.so.1 =>  (0x00007ffce4d60000)
        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f0d05ff1000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f0d05dda000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f0d05bc0000)
        libpq.so.5 => /usr/local/pgsql/lib/libpq.so.5 (0x00007f0d05997000)
        librt.so.1 => /lib64/librt.so.1 (0x00007f0d0578e000)
        libcurl.so.4 => /lib64/libcurl.so.4 (0x00007f0d05525000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f0d05223000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f0d0501e000)
        libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f0d04e05000)

今度は libpq.so.5 => /usr/local/pgsql/lib/libpq.so.5 と表示されました。

ということで/usr/local/pgsqlディレクトリを確認してみます。


$ ls -l /usr/local
drwxr-xr-x   7 root     root       62  3月  2 15:44 bin
drwxr-xr-x.  2 root     root       22  7月 29  2016 etc
drwxr-xr-x.  2 root     root        6  8月 12  2015 games
drwxr-xr-x.  3 root     root       16  7月 29  2016 include
drwxr-xr-x.  3 root     root       30 12月  6 15:26 lib
drwxr-xr-x.  2 root     root        6  8月 12  2015 lib64
drwxr-xr-x.  2 root     root        6  8月 12  2015 libexec
drwx------   6 postgres postgres   52  3月  2 14:41 pgsql
drwxr-xr-x   3 root     root       16  3月  2 15:33 sbin
予想通りpgsqlユーザーのみ読み書きできる状態になってしまっていました。

適切に権限を追加して完了。




以上でぇぇぇぇす。

2017年1月27日金曜日

LumenのEloquentでupdate()を呼ぶとMassAssignmentExceptionが出てまう

どうも、俺です。

最近は軽量PHPフレームワークのLumenを使っています。
(※バージョンはたぶん5.2。確認の仕方が分からない...)

最近もっぱらPHP界隈を賑わしているLaravelから派生したフレームワークで、
機能が少ない分、軽量で処理速度も速いそうです。

LaravelもLumenもデータベースモデルはEloquentという機能を使って開発することができ、僕もそれを使っています。

で、データを更新するために
$userObject->update(["name"=>"山田さん", "age"=>30]);
のように実装すると、

 MassAssignmentException
が発生し小一時間ハマりました。

この場合は、その該当のモデルクラスに

// 変更可能なカラム名
protected $fillable = ["name", "age", "その他カラム名"];

// または変更不可能なカラム名
protected $guarded = ["id", "create_at"];

のどちらか(または両方)を記述すればOKです。

ただ、上記の変数を指定しなくてもupdate()メソッドが使える場合もあり、
その理由は未だ不明です...。



ちなみに、insert()またはsave()メソッドでは上記の例外の発生は未確認です。




以上でぇぇぇぇす!

2016年11月18日金曜日

Laravel(またはLumen)のクエリビルダーのWHERE条件で、()カッコ付きのSQLを作る

どうも、俺です。

忘れぬうちにメモ。

例えば、
SELECT * FROM user WHERE status=1 AND (type=1 OR type=2);
のようなクエリを作りたい場合。


$query = $userModel->where('status', 1)->where(function($query) use()
{
  $query->where('type', 1)->orWhere('type', 2);
});
になります。

ちなみに、
SELECT * FROM user WHERE status=1 AND (type=1 AND type=2);
の場合は
$query = $userModel->where('status', 1)->where(function($query) use()
{
  $query->where('type', 1)->where('type', 2);
});
になります。

ちょっと読みづらいっす...。


以上でぇぇぇす。

2013年6月21日金曜日

c++で親クラスのコンストラクタを呼び出す

どうも、俺@家です。

C++でとある基底(親)クラスから派生した子クラスのコンストラクタ内で
親クラスのコンストラクタを呼び出したい場合は、

// 親クラス
class Parent
{
public:
  // 親クラスのコンストラクタ
  Parent()
  {
  };
};


// 子クラス
class Child: public Parent
{
public:
  // 子クラスのコンストラクタ
  Child(): Parent()
  {
  };
};
と書きます。
簡単ですね。

ちなみに子クラスから親クラスの何らかのメソッドを呼び出したい場合は、
// 親クラス
class Parent
{
public:
  // methodParent()の定義
  void methodParent()
  {
  };
};

// 子クラス
class Child: public Parent
{
public:
  void Child::methodChild()
  {
    // 親クラスのmethodParent()を呼びたい
    Parent::methodParent();
  };
};
のように、親クラス名::メソッド名と書きます。
※楽して上のように書きましたが、
 関数の重複定義でコンパイルエラーになる場合があるので、
 宣言する.hファイルと関数の内容を書く.cppファイルとは別けて書きましょう。


ちなみにphpだと
// 親クラス
public class Parent
{
  public function __construct()
  {
  }
}

// 子クラス
public class Child extends Parent
{
  public function __construct()
  {
    parent::__construct();
  }
}
のように、parent::メソッド()のように書きます。


ちなみにObjective-Cはコンストラクタがなくてイニシャライザになりますが、同様に
// 親クラスの.mファイル
@implementation Parent
- (id)init
{
  if ((self = [super init])) {
  }
  return self;
}
@end


// 子クラス .hファイル
@interface Child: Parent
- (id)init;
@end

// 子クラス .mファイル
@implementation Child
- (id)init
{
  if ((self = [super init])) {
  }
  return self;
}
@end
のようにsuperを使って書きます。
そもそもParentクラスも少なくともNSObjectを継承するのでsuperが出てきちゃいますね。


以上でぇぇぇぇえす。

2012年9月13日木曜日

Facebook sdk(php)でログアウト実装

どうも、俺@残業中です。
またブログさぼっておりました。仕事していないわけではありません^^;
最近はもっぱらObjective-Cの世界にどっぷりです。


さて、今日はfacebookで提供されているphp版のAPIでログアウトする方法についてメモ。

サンプルはこちら。
$facebook = new Facebook(array('appId'=>'xxxxxx', 'secret'=>'zzzzzzzz'));

// ログアウトする
$url = $facebook->getLogoutUrl();
$facebook->destroySession();
header('location:'. $url);


以上でぇぇえぇす。

2011年9月13日火曜日

fsockopenでhttps://へ接続したいとき

どうも、久しぶりです。俺@残業中です。

今日はphpのfsockeopen()の使い方注意をメモメモ。
httpsな外部サイトへfsockopen()したいときは

fsockopen('www.example.com', 443, $errono, $errstr, $timeout);
では接続できません。
サーバ側から

<!DOCTYPE HTML PUBLIC “-//IETF//DTD HTML 2.0//EN”>

<html><head><title>400 Bad Request</title></head><body><h1>Bad Request</h1><p>Your browser sent a request that this server could not understand.<br />
Reason: You’re speaking plain HTTP to an SSL-enabled server port.<br />
Instead use the HTTPS scheme to access this URL, please.<br />
とかで帰ってきます。
fsockopen()でhttps://なサイトへ接続するときは

fsockopen('ssl://www.example.com', 443, $errno, $errstr, $timeout);
としましょう。

あ、ちなみにphpはopensslが利用可能な環境でインストールされている必要がありますよ。

 ./configure --with-openssl


以上でぇぇえっぇす。

2011年7月27日水曜日

javascriptでurlエンコードしたものをphpでデコードする

どうも、俺@仕事中です。
相変わらずNodeやってます。

Node側でユーザの入力データを受け取り、それをphpへ渡すような事をする場合は
javascriptで入力データをURLエンコードしてphpでデコードを行う必要が出てきます。

javascriptには
escape(str);
encodeURI(str);
encodeURIComponent(str);
の3つエンコード関数があり
phpには
urldecode($str);
rawurldecode($str);
の2つデコード関数があります。

どうやらそれぞれエンコード/デコードのアルゴリズムが違うらしく
全くデータの受け渡しが出来なかったので、どれとどれの組み合わせだったらうまく動作するのか確認しようかな
と思ってたところ、やってくれてる方がいらっしゃいました。

JavaScriptとPHPのURLエンコード【JavaScript,PHP】:Programming Magic

このサイトを参考にして、javascriptでは
encodeURIComponent(str)
してからphpへ送り、
phpでは
rawurldecode($str);
すれば正しく受け渡しができました。感謝!!
逆の場合でも同じですね。


以上でぇぇえっぇぇす。

2011年3月8日火曜日

phpインストール時にlibxml2を除外する

どうも、俺@おもいっきり残業中です。

php(ver.5.3.5)をインストールしてて、libxml2関連のエラーが出る場合。
※makeしたときにエラーが出ました。

configure: error: libxml2 version 2.6.10 or greater required.
僕の場合はこんな感じでしたが、いかんせんサーバが古いため試行錯誤した結果、libxml2を再インストール(またはアップデート)することを諦めた人へ。。。

簡単な話が、configureオプションでlibxml2を外してやればいいのです。

# vim /usr/local/src/php-5.3.5/conf.sh
----------------------------------------------
#!/bin/sh
./configure --with-apxs2=/usr/local/apache2/bin/apxs --enable-mbstring --enable-zend-multibyte --with-pgsql=/usr/local/pgsql --with-pdo-pgsql=/usr/local/pgsql --enable-sockets --disable-libxml --disable-dom --disable-simplexml --disable-xml --disable-xmlreader --disable-xmlwriter --without-pear
普段のオプションに加えて
--disable-libxml --disable-dom --disable-simplexml --disable-xml --disable-xmlreader --disable-xmlwriter --without-pear
これらを追加してやればmakeできます!!

ただし、phpのlibxml(xml)関連、DOM関連、PEARがインストールされませんのであしからず!


以上でぇぇぇえぇす。

2011年2月25日金曜日

PHPとpostgresqlでテーブル一覧を取得

どうも、オレ@始業しましたです。

忘れないうちにメモメモ。
DBがpostgreSQLでphpからテーブル一覧を取得するためのクエリについて。
postgreSQLのバージョンは7.4.12ですが、おそらく他のバージョンでも大丈夫かな?(未確認)
PHPのバージョンは5以上です。
<?php
$pdo = new PDO('pgsql:host=localhost;port=5432;dbname=dbname;user=username;password=password');
$sql = 'select pg_statio_user_tables.relname
from pg_catalog.pg_class,pg_catalog.pg_statio_user_tables
where relkind='r'
and pg_catalog.pg_statio_user_tables.relid=pg_catalog.pg_class.relfilenode';
$stmt = $pdo->query($sql);
var_dump($stmt->fetchAll());
連想配列(fetchAll()した結果)でテーブル一覧が取得できます。
ただし、作った覚えのないテーブルも含まれているので要注意。

ちなみに、MySQLだと簡単で
<?php
$sql = 'show tables';
$stmt = $pdo->query($sql);
var_dump($stmt->fetchAll());
です。

以上でぇぇぇす。

2010年9月15日水曜日

zend frameworkでルーターの設定をiniファイルで行う

どうも、俺@仕事中です。

今日はZendFrameworkでルーティングの設定(Zend_Controller_Router_Route)を直接コードに書かずにiniファイルで行う設定方法の備忘録です。

1)通常のルーティング
$ vim configs/router.ini
-------------------------------
routes.default.type = "Zend_Controller_Router_Route"
routes.default.route = ":controller/:action/*"
routes.default.defaults.module = "module_name" ; モジュール名
routes.default.defaults.controller = "index" ; デフォルトコントローラ名
routes.default.defaults.action = "index" ; デフォルトアクション名

$ vim public/index.php
-------------------------------
$router = Zend_Controller_Front::getInstance()->getRouter();
$config = new Zend_Config_Ini(APPLICATION_PATH . "/configs.router.ini");
$router->addConfig($config, "routes");
これであれば
http://koexuka.blogspot.com/foo/bar/
というURLでアクセスのあった場合、「module_name」モジュールの「foo」コントローラの「bar」アクションが呼ばれます。


2)ホスト名によるルーティング
$ vim configs/router.ini
--------------------------------
; デフォルト
routes.default.type = "Zend_Controller_Router_Route"
routes.default.route = ":controller/:action/*"
routes.default.defaults.module = "module_name"
routes.default.defaults.controller = "index"
routes.default.defaults.action = "index"

; 携帯用
routes.mobile.type = "Zend_Controller_Router_Route_Hostname"
routes.mobile.route = "m.koexuka.blogspot.com"; ホスト名はm
routes.mobile.defaults.module = "mobile"; mobileモジュールへ
routes.mobile.defaults.controller = "index"
routes.mobile.defaults.action = "index"
routes.mobile.chains.path.type = "Zend_Controller_Router_Route"
routes.mobile.chains.path.route = ":controller/:action/*"
routes.mobile.chains.path.defaults.controller = "index"
routes.mobile.chains.path.defaults.action = "index"

$ vim public/index.php
-------------------------------
$router = Zend_Controller_Front::getInstance()->getRouter();
$config = new Zend_Config_Ini(APPLICATION_PATH . "/configs.router.ini");
$router->addConfig($config, "routes");
これで
http://m.koexuka.blogspot.com/foo/bar
というURLでアクセスのあった場合、「mobile」モジュールの「foo」コントローラの「bar」アクションが呼ばれます。


設定ファイルを利用した方がよりスマートだと思います。

以上でぇぇえぇす。

2010年9月10日金曜日

ZendFrameworkでモジュール別Bootstrapを用意すると全て実行されてしまう

どうも、俺@始業です。
忘れないうちにメモメモ。

Zend Frameworkはモジュール別Bootstrap.phpを用意して利用すると、どのモジュールですべてのBootstrapクラスにある_initXX()メソッドが実行されてしまいます。

モジュールの設定
$ vim application.ini
--------------------------------
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.modules[] =

fooモジュールとbarモジュールがあった場合は
$ vim modules/foo/Bootstrap.php
--------------------------------
class Foo_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initFoo() {
// 何らかの前処理
}
}

$ vim modules/bar/Bootstrap.php
---------------------------------
class Bar_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initBar() {
// 何らかの処理
}
}
↑↑どこのモジュールからでも両方のメソッドが実行されてしまう。
なんかモジュール毎にBootstrap置く意味がないですね。というかこれだったら
application/Bootstra.php内にすべて処理を済ませてしまえば良いのです。

なのでモジュールごとにBootstrapを実行させる方法をめも。
※ココを参考にしました。Phly, boy, phly
要は各Bootstrap内で、プラグインを登録しそこで処理を実行させちゃいなよ、YOU。ということです。
$ vim modules/foo/Bootstrap.php
--------------------------------
class Foo_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initFoo() {
$this->bootstrap("FrontController");
$front = $this->getResource("FrontController");
$front->registerPlugin(new My_Plugin_Foo()); // ここでプラグイン登録
}
}

次にプラグインを作成します。
$ vim My/Plugin/Foo.php
--------------------------------
class My_Plugin_Foo extends Zend_Controller_Plugin_Abstract {
/**
* @Override
*/

public function dispatchLoopStartup(Zend_Controller_Requset_Abstract $req) {
if ($req->getModuleName() != "foo") { // ちょっとアナログな感じ、、
return;
}

// ここに処理
}
}
これでOKです。
barモジュールも同様にすれば良いです。
また処理ごとにMy_Plugin_Foo_XXとか My_Plugin_Foo_YYとかクラスを分けた方が分かりやすいと思います。


ただ、注意するのはモジュール内のBootstrapでプラグインを登録する方法だと、
実際に処理が実行されるタイミングがルータが動作した後だったりするので、完全な意味での「前処理」が出来ない場合もあるので注意しましょう。


では、次回はもう1つの方法をメモしときまぁぁす。

2010年9月8日水曜日

zend frameworkでZend_Filterを設定かつZend_Layoutを使うと文字化け

どうも、俺@仕事中です。

タイトルの通り、zend framework(v1.10.8)でZend_Filterを使ってviewにフィルタをかけて(実際は絵文字変換)、さらにZend_Layoutを利用すると文字化けが発生してしまいました。

Zend_Filterはこんな感じ(省略してます)
<?php
class My_View_Filter implements Zend_Filter_Interface {
public function filter($output) {
return mb_convert_encoding($output, "SJIS-win", "UTF-8");
}
}

で、コントローラのinit()メソッドで
public function init() {
$this->view->setFilterPath("My/View", "My_View_")->addFilter("Filter");
}
としてフィルタをセットしています。
レイアウトはapplication.iniの設定で
resources.layout.layout = "layout"
resources.layout.layoutPath = APPLICATION_PATH "/views/layouts"
としてレイアウトを有効にしています。

これだと、どうやらそれぞれのviewスクリプトに対しフィルタがかかり、さらに全てのviewスクリプトを含んだlayout.phtmlでさらにフィルタがかかるという2重フィルタ処理で文字化けが起こっているようです。

※このブログでも言及されていました。骨折り損のくたびれ儲け::ZendFrameworkで携帯 文字化け対応

上記のブログと同じ現象なのでこれで解決かな?と思ったのですが、なぜかうまくいきません。
1)独自のZend_Layout_Controller_Plugin_Layoutを拡張したクラスを作成
<?php
class My_Layout_Controller_Plugin_Layout extends Zend_Layout_Controller_Plugin_layout {
plubic function postDispatch(Zend_Controller_Request_Abstract $request) {
parent::postDispatch($request);
$filter = new My_View_Filter();
$this->getResponse()->setBody($filter->filter($this->getResponse()->getBody()));
}
}

2)application.iniに追記
resources.layout.pluginClass = "My_Layout_Controller_Plugin_Layout"


やり方が間違っているのか、、でも上のpostDispatch()メソッドで親クラスのを一度呼び出してるから文字化けするんじゃ??とも思うのですが、、
正しい方法があれば教えてください><

で、解決方法ですが、↑で作ったクラスなどはそのままにしておいてZend_View_Abstractクラスのrender()メソッドをちょこっと変更すればできます。
public function render($name) {
-- 中略 --
// return $this->_filter(ob_get_clean());
return ob_get_clean();
}


Zend_View_Abstractクラスを拡張しても良いかもしれませんね。

以上でぇぇす。

-- 2010.09.08 追記 --
Zend_Viewクラスを拡張したバージョンを作りました。
まず拡張クラスを作ります。
<?php
class My_View extends Zend_View {
private $_file = null;
// 一応
private $_useViewStream = false;
private $_useViewStreamWrapper = false;

public function render($name) {
$this->_file = $this->_script($name);
unset($name);

ob_start();
$this->_run($this->_file);
return ob_get_clean(); // ここは親クラスと違う
}
}

次はこの拡張Viewクラスを使うようindex.phpか、またはBootstrapに(※この例ではBootstrapを利用)
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initView() {
$view = new My_View(array()); // コンストラクタの引数はViewに渡すオプション配列、またはZend_Config
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper("ViewRenderer");
$viewRenderer->setView($view);
}
}

以上でーす。

2010年8月2日月曜日

OpenFlashChartで折れ線グラフを描く

どうも、俺@週明け仕事中です。

今日はphpの便利なFlashグラフ作成ライブラリOpen Flash Chartを使って折れ線グラフを描く方法をメモします。

.swfファイルの配置などは割愛します。
上記URLから一式ファイルを落として、open-flash-chart.swfをサーバへ置き、クライアント側からはjavascriptで
<script src="swfobject.js" type="text/javascript"></script>
swfobject.embledSWF("open-flash-chart.swf");
のように呼び出すだけです。

では、折れ線グラフ(2本の折れ線)を作るためにサーバ側では
<?php
$chart = new OFC_Chart();

// 1本目
$line = new OFC_Charts_Line();
$line->set_values(array(1,2,3));
$line->set_width(2);
$line->set_colour("#000000");
$chart->add_element($line);

// tool_tipを使う場合
$dot = new OFC_Charts_Line_Dot();
$dot->set_dot_size(3);
$dot->set_halo_size(1);
$dot->set_colour("#000000");
$dot->set_tooltip("ここはツールチップ #val##x_label#");
$line->set_default_dot_style($dot);

/Charts/OFC_Charts_Line.phpに以下のメソッド追加
function set_tooltip($tip) {
$this->tip = $tip;
}
function set_default_dot_style($style) {
$this->{"dot-style"} = $style;
}


// 2本目
$line = new OFC_Charts_Line();
$line->set_values(array(4,5,6));
$line->set_width(2);
$line->set_colour("#000000");
$chart->add_element($line);

// tool_tipを使う場合
$dot = new OFC_Charts_Line_Dot();
$dot->set_dot_size(3);
$dot->set_halo_size(1);
$dot->set_colour("#000000");
$dot->set_tooltip("ここはツールチップ #val##x_label#");
$line->set_default_dot_style($dot);


// Y軸
$y = new OFC_Elements_Axis_Y();
$y->set_range(0,100,10);// Y軸の幅
$y->set_colour("#000000")
$y->set_grid_colour("#cccccc");
$chart->set_y_axis($y);

// X軸
$x_label = new OFC_Elements_Axis_X_Label_Set();
$x_label->set_labels(array("その1", "その2"));
$x_label->set_steps(1);
$x_label->set_colour("#000000");

$x = new OFC_Elements_Axis_X();
$x->set_labels($x_label);
$x->set_colour("#000000");
$x->set_grid_colour("#cccccc");
$x->set_range(0,null,null);

$chart->set_x_axis($x);

print $chart->toPrettyString();
exit;
こんな感じです。

詳細は公式を見てね。

2010年6月9日水曜日

zend frameworkでレスポンスヘッダを扱う

どうも、俺@定時間際です。

今日は前回「ZendFrameworkでViewを無効化する」のつづきのお話になるのですが、Viewのレンダリングを無効化しレスポンスヘッダを開発者の思うように返す方法についてめもめも。

Zend_Controller_Actionの派生クラス内でレスポンスヘッダを変更する場合は
<?php
$response = $this->getResponse();
$response->setHeader("Content-Type", "image/gif"); // 例えば画像出力
// $response->setRedirect("http://google.co.jp", 302); // 例えばリダイレクト

$response->sendResponse();
これ。

やり方たくさんあるっぽいので、もっと便利な別の方法もできますね。


以上。どぇぇぇす。

2010年6月3日木曜日

ZendFrameworkでViewを無効化する

どうも、俺@仕事中 今日2度目の投稿です。
ZendFrameworkを使っていて、Viewを無効化(Viewレンダリングを無効煮する)方法についてめもめも。

やりたい事は、ZendFrameworkで受け付けたリクエストを処理して別サイトへリダイレクトするだけのコントローラーを作る!というものです。


Zend_Controller_Actionを継承したコントローラを作成し、init()メソッドで
$rediretor = $this->_helper->getHelper("Redirector"); // リダイレクトに関する処理をまとめて行う。
$redirector->setCode(302); // ステータスコードを302にセット
$redirector->setExit(true); // リダイレクトの後exit();を行う。

$this->_helper->getHelper("ViewRenderer")->setNeverRender(true); // viewのレンダリングを行わない。
のようにすれば、リダイレクトの処理とViewのレンダリング無効化を初期処理にて行えます。


詳しくはZend Framework アクションヘルパーまで


以上でぇぇぇす(´・ω・`)

2010年5月19日水曜日

Zend Frameworkでモジュール単位でBootstrap.phpを使うとエラー(Warning)

どうも、俺@残業中です。
今日はZendFrameworkでモジュールディレクトリ直下にBootstrap.phpを設置するとエラーになる対処法です。

ZFのバージョンは1.10.4です。

モジュールディレクトリ下に設置したファイルは
<?php
class Module_Bootstrap extends Zend_Application_Module_Bootstrap {
}
です。
これだと
 Warning: include_once(FrontController.php) [function.include-once]: failed to open stream: No such file or directory in...
というエラーがでます。

どうやらこれ、
http://framework.zend.com/issues/browse/ZF-6658
で上がっているようなバグらしいのですが、バージョン1.9で修正されたような事が書いてあるのです。
あれ?俺は1.10使ってるけど、、、?
で見てると
http://framework.zend.com/issues/browse/ZF-7696
に、
Fixed in r22124
と書かれてます。

それを参考に
# vim Zend/Application/Bootstrap/BootstrapAbstract.php
348 if (false !== $pluginName = $this->_loadPluginResource($plugin, $spec)) {
349 if (0 === strcasecmp($resource, $pluginName)) {
350 return $this->_pluginResources[$pluginName];
351 }
352 continue; // ここ追加
の352行目を追加してあげれば良いようです。(たぶん)


以上でぇぇす。

2010年5月11日火曜日

phpで「send of xx bytes failed with errno=32 Brokenpipe in xxxx」というエラーが出る

どうも、俺@今日2度目の書込みです。
さっき出ました。
( ! ) Notice: fwrite() [function.fwrite]: send of 67 bytes failed with errno=32 Broken pipe in /usr/local/path/to/php/source/file.php on line 61
というエラー。

該当箇所のソースは
$written = fwrite($fp, $send_data);
です。

どうやら、phpでソケット通信をする際に
 1 $fp = fsockopen($host, $port);
2 if (is_resource($fp)) {
3 fwrite($fp, $send_data);
4 fclose($fp);
5 }
という事をよくやるかと思いますが、3行目の時点で接続先サーバから切断された場合、上記のようなエラーが出るようです。
この例で挙げたくらいのソースの実行速度で接続が切断されることは滅多にないと思います(というか防ぎようがない)が、一度接続したソケットポインタを使い回している場合などでは今回のエラーが発生する可能性がありますので、要注意(`・ω・´)



以上どぇぇぇぇぇぇす。

2010年4月22日木曜日

OpenFlashChart(php ver5)をちょっとカスタマイズ

どうも、俺@OpenFlashChartでグラフ作成中です。

Flashを使ったキレイなグラフ作成ライブラリOpen Flash Chartを使っています。
pythonとかperlとかjspからも呼び出せて、キレイなグラフを描画してくれるのでかなり使えるやつです。


僕はphpを使ってるので、アーカイブを展開して「/php5-ofc-library」以下のファイルを使ってグラフを作っているのですが、どうもこれが未完成っぽい。
未完成というより、「/php-ofc-library」以下にあるファイル(php4用)の方が色々充実しているみたいですね。

積み上げ棒グラフを作っているのですが、このサンプルにあるようにグラフ上部に凡例を出したいのに出せませんでした。
※php4版ではすぐ出せました。

というわけでphp5版の/OFC/Charts/Bar/OFC_Charts_Bar_Stack.phpをイジっちゃいましょう。

# vim /OFC/Charts/OFC_Charts_Bar.php
// set_keys()メソッドを作成
function set_keys ($keys) {
$this->keys = $keys;
}

# vim /OFC/Charts/Bar/OFC_Charts_Bar_Stack.php
// OFC_Charts_Bar_Stack_Keyクラスを追加
class OFC_Charts_Bar_Stack_Key {
function OFC_Charts_Bar_Stack_Key($color, $text, $font_size) {
$this->colour = $color; // `colour`なことに注意
$this->text = $text;
$this->font-size = $font_size;
}
}


呼び出し側では

<?php
$bar_stack = new OFC_Charts_Bar_Stack();
$bar_stack->set_keys(
array (
new OFC_Charts_Bar_Stack_Key($color, $text, $font_size),
new OFC_Charts_Bar_Stack_Key($color, $text, $font_size),
new OFC_Charts_Bar_Stack_Key($color, $text, $font_size)
)
);
のようにしてやればOKです。


OpenFlashChart(php版)は、最後のtoString()メソッドやprettyString()メソッドでセットされた値を単にjson_encode()して吐き出しているだけ
なので、どんな値をセットしてもjson形式でデータを出力してくれます。
あとは、ライブラリに用意されているswfファイルが読み取ってFlashグラフを作成している、という訳です。

ちゃんちゃん。

2010年4月6日火曜日

Zend_Db_Selectの便利な使い方

どうも、俺@風呂上りです。

今日はZend Frameworkで用意されているZend_Db_Selectクラスを使った便利な方法をメモします。
ま、ZendFrameworkの公式にあるので、そちらを参考に!

Zend Frameworkのコンポーネント達はそのフレームワークを利用せずとも、組み込めるように作られているので、そういう使い方もできますよ(´・ω・`)

インスタンスの生成は、
<?php
$select = new Zend_Db_Select(Zend_Db_Adapter $db);
これでZend_Db_Selectのインスタンスが生成されます。

Where句は、
<?php
$select->where("id = ?", $id_param, Zend_Db::INT_TYPE);
// WHERE id=$id_param
で作れます。
続けて書けば、
<?php
$select->where("id = ?", $id_param, Zend_Db::INT_TYPE);
$select->where("name = ?", $name_param);
// WHERE id=$id_param AND name='$name_param'
のようになり、
<?php
$select->where("id = ?", $id_param, Zend_Db::INT_TYPE);
$select->orWhere("name = ?", $name_param);
// WHERE id=$id_param OR name='$name_param'
になります。

Order by句は、
<?php
$select->order("id");
// ORDER BY id

<?php
$select->order("id DESC");
// ORDER BY id DESC
になります。

Limit Offset句は、
<?php
$select->limit(30, 10);
// LIMIT 30 OFFSET 10 または LIMIT 30, 10
でできます。

Group by句は、
<?php
$select->group("id");
// GROUP BY id
です。

で、ここがとても感動したポイントですが、取得したカラムやテーブルの指定する方法は、
<?php
$select->from("foo_table");
// SELECT * FROM foo_table

<?php
$select->from(array("foo" => "foo_table"), "id");
// SELECT foo.id FROM foo_table AS foo
となるのです(´・ω・`)
カラムにエイリアス(別名)をつける場合は、
<?php
$select->from(array("foo" => "foo_table"), array("id_aliase" => "id"));
// SELECT foo.id AS id_aliase FROM foo_table AS foo
です。
途中でカラムを追加するには、
<?php
$select->from(array("foo" => "foo_table"), array("id_aliase" => "id"));
$select->columns("name", "name_aliase");
// SELECT foo.id AS id_aliase, foo.name AS name_aliase FROM foo_table AS foo
です。
一気に大量のカラムを書きたい場合は、
<?php
$select->from(array("foo" => "foo_table"), array("id", "name", "birthday", "address",....));
のようにします。



ということは、これらをまとめると、
<?php
$select = new Zend_Db_Select(Zend_Db_Adapter $db);
$select->from(array("foo" => "foo_table"), array("id", "name"));
$select->where("id IN (". implode(",", $id_list).")");
$select->order("id DESC");
$select->limit(30, 10);
// SELECT foo.id, foo.name FROM foo_table AS foo WHERE id IN (x,x,x,x,x) ORDER BY id DESC LIMIT 30 OFFSET 10;
のようになるわけです。

これにZend_Db_Adapterを利用して、
<?php
$result_set = $db->fetchAll($select);
とかやると、一発で配列でデータを取得できたり、
<?php
$stmt = $db->query($select);
while ($rs = $stmt->fetch()) {
// 処理
}
のように1レコードずつデータ処理を行ったりできます。

ちなみに、クエリ文字列を取得するには、
<?php
$query = $select->__toString();
でできますし、Where句だけ取りたいという場合は
<?php
$wheres = $select->getPart(Zend_Db_Select::WHERE);
// where句すべてを配列で取得できるのであとで、implode()とかやれば使える
で取れます。

いやぁ、超便利ーー(´・ω・`)