投稿者「junichi_11」のアーカイブ

jQuery 二重送信防止

二重送信防止

二重送信のイメージ

一度クリックして反応が遅い場合、ユーザがせっかちな場合など、フォームの送信ボタンを連打されてしまう場合がある。

このとき、フォームの情報が2回送信されてしまうことになる。

つまり、同じデータを複数登録されてしまうことがある。

このように複数回のの送信を防止する仕組みはいくつかある。

ここではjQueryのプラグインを使って、防止するする方法を紹介する。

二重送信防止のイメージ(jQueryプラグイン)

次のような仕組みになっている。

最初にボタンをクリックされたときに、そのボタンをグレーアウトにしてクリックできなくする。

二重送信防止用のjQueryのプラグインのダウンロード、使い方は以下のサイトを参照してください。

プラグインのダウンロードおよび参考サイト:
http://www.alink.co.jp/tech/blog/2009/04/05/javascript-jqueryでフォームの2重送信を防ぐ/
http://www.evanbyrne.com/article/jquery-disable-on-submit-plugin
http://neta.ywcafe.net/001046.html

CakePHP Twitter連携 OAuthConsumerを使ってみた

完成イメージ

Twitterへの投稿を 

    $this->Twitter->tweet(“つぶやくぞ”); 

という具合に実行できるようにする。 

準備

Basic認証での投稿はできなくなるらしいので、OAuth認証によるツイートが出来るようにする。 

すでにOAuth認証による投稿ができるクラスとComponentを作っている人がいるので、それを利用する。 

参考にしたサイトではClassを使っていたので、ここではComponentを使ってみる。 

また、ここで作成するものは、ACCESS TOKENを直接WEBページから取得するので、個人的な利用の場合のみ使用可能。 

OAuthConsumerComponetをダウンロード
http://code.42dh.com/oauth/ 

参考にしたサイト: http://www.zontheworld.com/blog/archives/119 

概要

  1. Twitterのアカウントから必要な情報を取得する。
  2. DLしたOAuthConsumerComponentの設定。
  3. TwitterComponentの作成。
  4. ツイート!

Twitterの設定

アプリの登録

ツイッターにログインし 

http://twitter.com/apps 

にアクセス。参考サイトと同様にして、アプリの登録を済ませる。 

必要情報の取得 (TOKEN)

Consumer Key & Consumer Secret

登録したアプリケーションの詳細から取得。 

Access Token & Access Token Secret

http://dev.twitter.com/apps/にアクセス。 

登録したアプリの詳細をみる。 

My Access Tokenをクリック。 

CakePHP の処理

OAuthConsumerComponentの設定

DLしたものを展開して、 

controllers/componetsを自分のcontrollers/componetsに配置。 

vendors/OAuthを app/vendorsに配置。
 

// 取得したToken等をapp/config/bootstrap.phpに追記
define('TWITTER_CONSUMER_KEY', '**************');
define('TWITTER_CONSUMER_SECRET', '**************');
define('TWITTER_ACCESS_TOKEN', '**************');
define('TWITTER_ACCESS_TOKEN_SECRET', '**************');

 

// app/controllers/components/oauth_consumers/twitter_consumer.php
class TwitterConsumer extends AbstractConsumer {
    public function __construct() {
        parent::__construct(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);
    }
}

 TwitterComponentの作成

// app/components/twitter.php
<?php
class TwitterComponent extends Object { 
 // Oauth認証を使うためのコンポーネント
 public $components = array('OauthConsumer'); 

 /**
  * ツイートする
  * @param string $tweet ツイートする内容
  * @return
  */
 function tweet($tweet){
  $tw = $this->OauthConsumer->post(
    'Twitter',
    TWITTER_ACCESS_TOKEN,
    TWITTER_ACCESS_TOKEN_SECRET,
    'http://twitter.com/statuses/update.json',
    array('status' => $tweet)
   );
  return $tw;
 }
}
?>

TwitterComponentの使い方

class HogeController extends AppController{
    public $name = 'Hoge';
    public $components = array('Twitter');

    function example(){
        $message = "hogedehogesuru";
        $this->Twitter->tweet($message);
    }
}

CakePHP MediaPlugin + Plupload 複数ファイルの同時アップロード

追記 2011-08-01
CakePHPのプラグイン化してみました
https://junichi11.com/?p=1406

複数のファイルを同時にアップロード

多くのファイルをアップロードしたい場合は、ファイルを何度も選択するのが大変。

何かいいものはないかと探していたところ、

PluploadというjQueryのプラグインを見つけた。
Pluploadでは下図のように複数のファイルを一度に選択することができる。

ダウンロード:http://www.plupload.com/

Pluploadの仕組み

Pluploadは以下のような仕組みになっている。

  1. 非同期で選択したファイルを複数に分割(chunkというもの)して送信する。
  2. 全ての送信が完了。
  3. 送信したファイル情報をPOSTで送信する。
    送信したファイルの情報はPluploadのサイトを参照。
    サーバー側には上図のような情報がファイル数分送られてくる。

 CakePHPでの処理

  1. 送信されてきたファイルを処理するメソッドを作成する。
    メソッドの中身はDLしたpluploadのファイルの中に、ファイルを処理するプログラムファイルがあるのでそれをそのまま使う。
  2. POSTされてきた情報をもとに、ファイルのUPロード処理を行う。
    (MediaPluginを使用する。)

MediaPluginのインストールは下記を参照
http://d.hatena.ne.jp/slywalker/20090730/1248916519
http://www.zontheworld.com/blog/archives/111
PHPで作る携帯サイト デベロッパーズガイド」秀和システム 滝下真玄著

ここではPHPで作る携帯サイト デベロッパーズガイドを参考にMediaPluginをインストールしています。

通常Pictureの部分はAttachementとして作成されているかもしれません。

app/controllers/photos_controller.php

class PhotosController extends AppController {
    public $name = 'Photos';
public $uses = array('Photo', 'Picture');

public $components = array('RequestHandler');
    //  …

function plupload(){
// plupload/examples/upload.phpの中身をコピペ
}

    function add(){

/*....................................................
* POST
* uploader_0_tmpname
* uploader_0_name
* uploader_0_status
* ...
....................................................*/
if(!empty($this->data)){
        $plupload = null;
$cnt = 0;
$tmpdir = ini_get('upload_tmp_dir');
foreach($_POST as $key => $value){
if($key == 'uploader_count'){
$cnt = $value;
}
$split = explode('_', $key);

if(in_array('tmpname', $split) || in_array('name', $split)){
$plupload[$split[1]][$split[2]] = $value;
}

}
foreach($plupload as $file){
@rename($tmpdir.DS.$file['tmpname'], $tmpdir.DS.$file['name']);
}

for($i = 0; $i<count($plupload); $i++){
$this->data['Picture'][$i]['title'] = '';
$this->data['Picture'][$i]['description'] = '';
$this->data['Picture'][$i]['model'] = 'Photos';
$this->data['Picture'][$i]['file'] = $tmpdir.DS.$plupload[$i]['name'];
        }

        if($this->Photos->saveAll($this->data, array('validate' => 'first'))){
$this->flash('データを追加しました', 'index',3);
foreach($plupload as $file){
@unlink($tmpdir.DS.$file['name']);
}
return;
}else{
$this->flash('失敗', 'add');
foreach($plupload as $file){
@unlink($tmpdir.DS.$file['name']);
}
        }
        }
}

    function beforeFilter(){
        if ($this->RequestHandler->isFlash()) {
            $this->Auth->allow('add');
        }
    }

}


/app/models/photos.php

class Photo extends AppModel {
var $name = 'Photo';

//アソシエーション設定
var $hasMany = array(
'Picture' => array(
'className' => 'Picture',
'foreignKey' => 'foreign_key',
'conditions' => array('Picture.model' => 'Photo'),
'dependent' => true,
),
);
}

最初に上手くいかなかったのが、下記の部分。
送られてくる情報が通常のファイルを送信する場合と違うから、
[‘file’]の部分をどうしていいのかわからなかった。

    $this->data['Picture'][$i]['file'] = $tmpdir.DS.$plupload[$i]['name'];

mediapluginのgitのwikiをみると解決。

MediaPluginの転送方法は3つある

[‘file’]の部分は以下の指定が可能。
pluploadでアップした場合2番目の使い方をする。

HTML formタグによるHTTP POST配列を使う

array(
'name' => 'hoge.jpg',
'type' => 'image/jgeg',
'tmp_name' => '/tmp/3242ljl',
'error' => 0,
'size' => 3524
)

ファイルへの絶対パスを使う

Ex : ‘/var/www/tmp/hoge.jpg’

URLを指定する

Ex : ‘http://www.cakephp.org/imgs/hoge.png’

/app/views/photos/add.ctp


<!-- Thirdparty intialization scripts, needed for the Google Gears and BrowserPlus runtimes -->
<?php echo $javascript->link('plupload/gears_init.js');?>
<script type="text/javascript" src="<a href="http://bp.yahooapis.com/2.4.21/browserplus-min.js%22%3E%3C/script">http://bp.yahooapis.com/2.4.21/browserplus-min.js"></script</a>>

<!-- Load plupload and all it's runtimes and finally the jQuery queue widget -->
<?php echo $javascript->link('plupload/plupload.full.min.js');?>
<?php echo $javascript->link('plupload/jquery.plupload.queue.min.js');?>
<script type="text/javascript">
// Convert divs to queue widgets when the DOM is ready
$(function() {
$("#uploader").pluploadQueue({
// General settings
runtimes : 'gears,flash,silverlight,browserplus,html5',
url : '<?php echo $html->webroot('/photos/plupload')?>',
max_file_size : '3mb',
chunk_size : '1mb',
unique_names : true,

// Resize images on clientside if we can
//resize : {width : 640, height : 480, quality : 100},

// Specify what files to browse for
filters : [
{title : "Image files", extensions : "jpg,gif,png"},
{title : "Zip files", extensions : "zip"}
],

// Flash settings
flash_swf_url : '<?php echo $html->webroot('/js/plupload/');?>plupload.flash.swf',

// Silverlight settings
silverlight_xap_url : '<?php echo $html->webroot('/js/plupload/');?>plupload.silverlight.xap'
});

// Client side form validation
$('form').submit(function(e) {
var uploader = $('#uploader').pluploadQueue();

// Validate number of uploaded files
if (uploader.total.uploaded == 0) {
// Files in queue upload them first
if (uploader.files.length > 0) {
// When all files are uploaded submit form
uploader.bind('UploadProgress', function() {
if (uploader.total.uploaded == uploader.files.length)
$('form').submit();
});

uploader.start();
} else
alert('You must at least upload one file.');

e.preventDefault();
}
});
});
</script>
<h2>写真の追加</h2>
Add files をクリックしてファイルを追加してください。<br />
ファイルを選択するときに複数のファイルを選択することができます。<br />
Google Gears をインストールしていれば、ファイルをドラッグ&ドロップで追加できます。
<?php echo $form->create('Photo', array('type' => 'file', 'action' => 'add', 'class' => 'plupload')); ?>
<span id="plupload">
<div id="uploader">
<p>You browser doesn't have Flash, Silverlight, Gears, BrowserPlus or HTML5 support.</p>
</div>
<br style="clear: both" />
</span>
<?php echo $form->end('追加'); ?>

実際に作ったものと名前等を変えているので、調整しないと動かないかもしれません。

もっといい作り方があるかもしれませんが、

参考までに。。