Symfoware

Symfowareについての考察blog

Riot ボタンクリック 表示非表示 ループ(イベントハンドラー,show,hide,if,each)

Riotの最小構成で動くプログラムを調べました。
Riot 最小構成のサンプルプログラム

今回はボタンのクリックイベントを取得するプログラムを試してみます。


イベントハンドラ



こちらを参考にしています。
Riotカスタムタグ

テキストに文字を入力。
ボタンを押したらdivタグに同じ文字列を表示します。

・index.html


  1. <!doctype html>
  2. <html lang="ja">
  3.     
  4. <html>
  5. <head>
  6.     <meta charset="UTF-8">
  7.     <title>Riot click</title>
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9. </head>
  10. <body>
  11.     <!-- ここにタグの内容を反映 -->
  12.     <my-tag></my-tag>
  13. </body>
  14. <!-- ここからRiotプログラム -->
  15. <!-- カスタムタグ -->
  16. <script type="riot/tag">
  17. <my-tag>
  18. <h3>ボタンクリックで値変更</h3>
  19. <div>{ description }</div>
  20. <div><input type="text" ref="input_text"></div>
  21. <div><input type="button" value="変更" onclick={ changeText }></div>
  22. changeText(event) {
  23.      this.description = this.refs.input_text.value
  24. }
  25. </my-tag>
  26. </script>
  27. <!-- マウント -->
  28. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.2/riot%2Bcompiler.min.js"></script>
  29. <script>
  30. riot.mount('my-tag')
  31. </script>
  32.     
  33. </html>




htmlタグに対し、ref属性で名前をつけておくと、そのオブジェクトに
this.refs.[名前]
でアクセスできるようになります。
これは便利。

カスタムタグ中、scriptタグは省略できるので、htmlタグの直後にjavascriptの
関数を記載することができます。

初期状態

737_01.png


適当な文字列を入力して「変更」をクリックすると、divタグのある位置に
入力したのと同じ文字列が表示されました。

737_02.png





表示、非表示の条件分岐



特定タグの表示・非表示を切り替える方法を調べてみます。

http://riotjs.com/ja/guide/
こちらの「条件属性」を参考にしました。

ボタンクリックで表示・非表示を切り替えます。
show/hideを使用する方法とifを使用する方法の2パターンあります。


  1. <!doctype html>
  2. <html lang="ja">
  3.     
  4. <html>
  5. <head>
  6.     <meta charset="UTF-8">
  7.     <title>Riot click</title>
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9. </head>
  10. <body>
  11.     <!-- ここにタグの内容を反映 -->
  12.     <my-tag></my-tag>
  13. </body>
  14. <!-- ここからRiotプログラム -->
  15. <!-- カスタムタグ -->
  16. <script type="riot/tag">
  17. <my-tag>
  18. <h3>ボタンクリックで表示変更</h3>
  19. <div show={ is_display }>show</div>
  20. <div hide={ is_display }>hide</div>
  21. <hr>
  22. <div if={ is_display }>ifでshow</div>
  23. <div if={ !is_display }>ifでhide</div>
  24. <div><input type="button" value="変更" onclick={ changeText }></div>
  25. this.is_display = true
  26. changeText(event) {
  27.      this.is_display = !this.is_display
  28. }
  29. </my-tag>
  30. </script>
  31. <!-- マウント -->
  32. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.2/riot%2Bcompiler.min.js"></script>
  33. <script>
  34. riot.mount('my-tag')
  35. </script>
  36.     
  37. </html>




初期表示

737_03.png

ボタンクリック

737_04.png


show/hideとifで何が違うかというと、display:noneで非表示にするか、
タグごと削除されるかの差のようです。

737_05.png




ループ



配列をループして表示する方法。
eachでループしたいオブジェクトを指定します。


  1. <!doctype html>
  2. <html lang="ja">
  3.     
  4. <html>
  5. <head>
  6.     <meta charset="UTF-8">
  7.     <title>Riot click</title>
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9. </head>
  10. <body>
  11.     <!-- ここにタグの内容を反映 -->
  12.     <my-tag></my-tag>
  13. </body>
  14. <!-- ここからRiotプログラム -->
  15. <!-- カスタムタグ -->
  16. <script type="riot/tag">
  17. <my-tag>
  18. <h3>ボタンクリックで項目追加</h3>
  19. <ul>
  20.      <li each={ items }>{ text }</li>
  21. </ul>
  22. <div><input type="button" value="追加" onclick={ add }></div>
  23. this.items = []
  24. add(event) {
  25.      this.items.push({text : 'テキスト追加'})
  26. }
  27. </my-tag>
  28. </script>
  29. <!-- マウント -->
  30. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.2/riot%2Bcompiler.min.js"></script>
  31. <script>
  32. riot.mount('my-tag')
  33. </script>
  34.     
  35. </html>



初期表示

737_06.png


ボタンを押すと項目が増えていきます。

737_07.png


複数のタグで構成される要素をループで表示したいときはvirtualタグを使用します。


  1. <!doctype html>
  2. <html lang="ja">
  3.     
  4. <html>
  5. <head>
  6.     <meta charset="UTF-8">
  7.     <title>Riot click</title>
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9. </head>
  10. <body>
  11.     <!-- ここにタグの内容を反映 -->
  12.     <my-tag></my-tag>
  13. </body>
  14. <!-- ここからRiotプログラム -->
  15. <!-- カスタムタグ -->
  16. <script type="riot/tag">
  17. <my-tag>
  18. <h3>ボタンクリックで項目追加</h3>
  19. <virtual each={ item in items }>
  20.      <div>項目:<span>{ item.text }</span></div>
  21. </virtual>
  22. <div><input type="button" value="追加" onclick={ add }></div>
  23. this.items = []
  24. add(event) {
  25.      this.items.push({text : 'テキスト追加'})
  26. }
  27. </my-tag>
  28. </script>
  29. <!-- マウント -->
  30. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.2/riot%2Bcompiler.min.js"></script>
  31. <script>
  32. riot.mount('my-tag')
  33. </script>
  34.     
  35. </html>



関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/03/26(日) 18:32:35|
  2. 備忘録
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Riot 最小構成のサンプルプログラム

Riot - Simple and elegant component-based UI library
http://riotjs.com/ja/

jQueryでDOM操作つらいなと思う時があるので、使い方を調べていこうと思います。


最小構成のサンプル



内容の理解はおいておいて、とりあえずサンプルを最小構成で動かしてみます。

こちらを参考に、本体のjsはCDNを参照することにしました。
Riotを手に入れよう!

riot+compiler.min.jsをリンクします。


準備するファイルは2つ。

・index.html


  1. <!doctype html>
  2. <html lang="ja">
  3.     
  4. <html>
  5. <head>
  6.     <meta charset="UTF-8">
  7.     <title>Riot todo</title>
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9.     <style>
  10. .completed {
  11. text-decoration: line-through;
  12. color: #ccc;
  13. }
  14.     </style>
  15. </head>
  16. <body>
  17.     <todo></todo>
  18.     <script src="todo.tag" type="riot/tag"></script>
  19.     <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.2/riot%2Bcompiler.min.js"></script>
  20.     <script>
  21.     riot.mount('todo', {
  22.      title: 'I want to behave!',
  23.      items: [
  24.         { title: 'Avoid excessive caffeine', done: true },
  25.         { title: 'Hidden item', hidden: true },
  26.         { title: 'Be less provocative' },
  27.         { title: 'Be nice to people' }
  28.      ]
  29.     })
  30.     </script>
  31. </body>
  32. </html>





・todo.tag


  1. <todo>
  2. <h3>{ opts.title }</h3>
  3. <ul>
  4.     <li each={ items.filter(whatShow) }>
  5.      <label class={ completed: done }>
  6.         <input type="checkbox" checked={ done } onclick={ parent.toggle }> { title }
  7.      </label>
  8.     </li>
  9. </ul>
  10. <form onsubmit={ add }>
  11.     <input ref="input" onkeyup={ edit }>
  12.     <button disabled={ !text }>Add #{ items.filter(whatShow).length + 1 }</button>
  13.     <button type="button" disabled={ items.filter(onlyDone).length == 0 } onclick={ removeAllDone }>
  14.     X{ items.filter(onlyDone).length } </button>
  15. </form>
  16. <!-- this script tag is optional -->
  17. <script>
  18.     this.items = opts.items
  19.     edit(e) {
  20.      this.text = e.target.value
  21.     }
  22.     add(e) {
  23.      if (this.text) {
  24.         this.items.push({ title: this.text })
  25.         this.text = this.refs.input.value = ''
  26.      }
  27.      e.preventDefault()
  28.     }
  29.     removeAllDone(e) {
  30.      this.items = this.items.filter(function(item) {
  31.         return !item.done
  32.      })
  33.     }
  34.     // an two example how to filter items on the list
  35.     whatShow(item) {
  36.      return !item.hidden
  37.     }
  38.     onlyDone(item) {
  39.      return item.done
  40.     }
  41.     toggle(e) {
  42.      var item = e.item
  43.      item.done = !item.done
  44.      return true
  45.     }
  46. </script>
  47. </todo>




これだけ。
ファイルを配置したディレクトリに移動し、pythonの簡易サーバーを起動しました。


$ python -m SimpleHTTPServer




ブラウザでhttp://localhost:8000を見てみると、こんな画面が表示されます。

736_01.png


簡単なTODOリストです。
コメントの追加や削除が行えます。





カスタムタグとmount



サンプルが動かせたので、ちょっとずつ使い方を調べていきます。

さらに最小構成のサンプルに変更してみました。
値を設定して表示するだけです。

・index.html


  1. <!doctype html>
  2. <html lang="ja">
  3.     
  4. <html>
  5. <head>
  6.     <meta charset="UTF-8">
  7.     <title>Riot sample</title>
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9. </head>
  10. <body>
  11.     <my-tag></my-tag>
  12.     
  13.     <script src="my.tag" type="riot/tag"></script>
  14.     <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.2/riot%2Bcompiler.min.js"></script>
  15.     <script>
  16.     riot.mount('my-tag', {
  17.      title: 'はじめてのRiot',
  18.      description: 'タグの使い方を勉強中'
  19.     })
  20.     </script>
  21. </body>
  22. </html>




・my.tag


  1. <my-tag>
  2. <h3>{ opts.title }</h3>
  3. <div>{ opts.description }</div>
  4. </my-tag>





値を設定して表示するだけならscriptタグは不要でした。
デフォルトの変数optsに値がせっていされるので、そのまま表示してやります。

htmlに宣言するタグの名前と、tagスクリプト中のタグ名は一致させる必要がありました。

736_02.png



htmlファイル1つにまとめてしまいたい場合は、scriptタグ内に
直接カスタムタグを記載すれば良いようです。


・index.html


  1. <!doctype html>
  2. <html lang="ja">
  3.     
  4. <html>
  5. <head>
  6.     <meta charset="UTF-8">
  7.     <title>Riot sample</title>
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9. </head>
  10. <body>
  11.     <my-tag></my-tag>
  12.     
  13.     <!-- タグの内容を直接記載 -->
  14.     <script type="riot/tag">
  15. <my-tag>
  16. <h3>{ opts.title }</h3>
  17. <div>{ opts.description }</div>
  18. </my-tag>
  19.     </script>
  20.     
  21.     <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.2/riot%2Bcompiler.min.js"></script>
  22.     <script>
  23.     riot.mount('my-tag', {
  24.      title: 'はじめてのRiot',
  25.      description: 'タグの使い方を勉強中'
  26.     })
  27.     </script>
  28. </body>
  29. </html>



scriptタグはhtmlタグ内に存在していればよく、bodyの外に追いやることもできるようです。
ただし、カスタムタグはmountの宣言より前に記載する必要があります。


・index.html


  1. <!doctype html>
  2. <html lang="ja">
  3.     
  4. <html>
  5. <head>
  6.     <meta charset="UTF-8">
  7.     <title>Riot sample</title>
  8.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  9. </head>
  10. <body>
  11.     <my-tag></my-tag>
  12. </body>
  13. <!-- タグの内容を直接記載 -->
  14. <!-- riot.mountよりも前に記載 -->
  15. <script type="riot/tag">
  16. <my-tag>
  17. <h3>{ opts.title }</h3>
  18. <div>{ opts.description }</div>
  19. </my-tag>
  20. </script>
  21.     
  22. <script src="https://cdnjs.cloudflare.com/ajax/libs/riot/3.3.2/riot%2Bcompiler.min.js"></script>
  23. <script>
  24. riot.mount('my-tag', {
  25. title: 'はじめてのRiot',
  26. description: 'タグの使い方を勉強中'
  27. })
  28. </script>
  29.     
  30. </html>



簡単なサンプルの場合、1ファイルにまとまっていたほうがわかりやすそうなので、
この記載方法で使い方を調べていこうと思います。
関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/03/26(日) 17:31:39|
  2. 備忘録
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

C# exeファイルに後から設定値を埋め込む手法の検討

プログラムで使用する何かしらの設定値を保存したい場合、
レジストリやiniファイルを使用することになると思います。

これだと、exeファイルだけコピーして別の端末で起動した時、設定値が失われてしまう。
なんとかコンパイル済のexeファイルに対して、後付で値を埋め込めないか試してみます。


最初のサンプルプログラム



文字列を出力する簡単なプログラムを作成します。

・test.cs


  1. using System;
  2. using System.IO;
  3. public class Test {
  4.         
  5.     [STAThread]
  6.     public static void Main(string[] args) {
  7.         Console.WriteLine("test");
  8.     }
  9. }




こんなバッチファイルを作成してコンパイルしました。

・build.bat


@echo off
set csc="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe"
set opt=/nologo

%csc% %opt% /out:test.exe test.cs




出力されたtest.exeをメモ帳で開いてみると、xmlな文字列が確認できます。
735_01.png


この領域を使用して、定数値を保存できるのでは?






manifestの使用



コンパイルオプションに何も指定せずにビルドすると、
デフォルトのmanifestファイルが埋め込まれるようです。

/win32manifest (C# Compiler Options)

こちらを参考に、自分で作成したマニフェストファイルを指定してコンパイルしてみます。

・test.manifest


  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  3. <assemblyIdentity version="1.0.0.0" name="Test.app"/>
  4. <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
  5.     <security>
  6.      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
  7.         <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
  8.      </requestedPrivileges>
  9.     </security>
  10. </trustInfo>
  11. </assembly>





ビルド用のバッチファイルはこうなりました。

・build.bat


@echo off
set csc="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe"
set opt=/nologo /win32manifest:test.manifest

%csc% %opt% /out:test.exe test.cs




出力されたexeを確認すると、指定したmanifestが埋め込まれたようです。

735_02.png





manifestにタグの追加



manifestに値を保存しておくためのタグを追加してみます。
今回はdescriptionというタグを追加しました。

・test.manifest


  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  3. <assemblyIdentity version="1.0.0.0" name="Test.app"/>
  4. <description>                             </description>
  5. <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
  6.     <security>
  7.      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
  8.         <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
  9.      </requestedPrivileges>
  10.     </security>
  11. </trustInfo>
  12. </assembly>




ポイントは、タグの内容に半角スペースをある程度含めておくことです。
ビルド後、exeのバイト数が変わると実行できなくなってしまうため、ある程度余白を設けておきます。

735_03.png


この領域に値を埋め込み、プログラムから読みだして使えば良さそうです。





値の埋め込みと読み取り



exeファイルを読み込み、descriptionタグの間に文字列を埋め込むプログラム。

・setting.cs


  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. public class Test {
  5.         
  6.     [STAThread]
  7.     public static void Main(string[] args) {
  8.         
  9.         string param = args[0];
  10.         
  11.         // 元となるexeファイルの読み込み
  12.         byte[] binary = File.ReadAllBytes("test.exe");
  13.         
  14.         // descriptionタグの位置をバイナリデータから検索
  15.         int first = IndexOf("<description>", binary);
  16.         
  17.         if (first == -1) {
  18.             Console.WriteLine("descriptionタグが見つかりません。");
  19.             return;
  20.         }
  21.         
  22.         // <description>の文字数分インデックスをずらす
  23.         int binaryIndex = first + 13;
  24.         
  25.         // パラメーターの埋め込み
  26.         byte[] paramBytes = Encoding.ASCII.GetBytes(param);
  27.         for (int i = 0; i < paramBytes.Length; i++, binaryIndex++) {
  28.             binary[binaryIndex] = paramBytes[i];
  29.         }
  30.         
  31.         // パラメーターを埋め込んだexeファイル出力
  32.         File.WriteAllBytes("test_param.exe", binary);
  33.         
  34.     }
  35.     
  36.     private static int IndexOf(string target, byte[] binary) {
  37.         byte[] targetBytes = Encoding.ASCII.GetBytes(target);
  38.         
  39.         for (int i = 0; i < binary.Length - targetBytes.Length; i++) {
  40.             
  41.             bool allMatch = true;
  42.             for (int j = 0; j < targetBytes.Length; j++) {
  43.                 if (binary[i + j] != targetBytes[j]) {
  44.                     allMatch = false;
  45.                     break;
  46.                 }
  47.             }
  48.             
  49.             if (allMatch) {
  50.                 return i;
  51.             }
  52.             
  53.         }
  54.         
  55.         return -1;
  56.     }
  57. }




引数をdescriptionタグにtest.exeに埋め込み、test_param.exeとして出力します。


適当な値を埋め込んでみます。


> setting.exe test_value




出力されたtest_param.exeを見てみると、ちゃんと値が埋め込まれました。

735_04.png


test.exeを修正。埋め込まれた値を読み込めるようにします。


・test.cs


  1. using System;
  2. using System.IO;
  3. using System.Text.RegularExpressions;
  4. using System.Reflection;
  5. public class Test {
  6.         
  7.     [STAThread]
  8.     public static void Main(string[] args) {
  9.         
  10.         // 自分自身をファイルとして読み込み
  11.         var assembly = Assembly.GetExecutingAssembly();
  12.         string s;
  13.         using(StreamReader sr = new StreamReader(assembly.Location)) {
  14.             s = sr.ReadToEnd();
  15.         }
  16.         
  17.         // descriptionタグの内容を取得
  18.         Regex r = new Regex(@"<description>(.*?)</description>");
  19.         MatchCollection mc = r.Matches(s);
  20.         
  21.         string param = "";
  22.         foreach (Match m in mc) {
  23.             param = m.Groups[1].Value.Trim();
  24.         }
  25.         
  26.         if (string.IsNullOrEmpty(param)) {
  27.             Console.WriteLine("not found");
  28.             return;
  29.         }
  30.         
  31.         // 取得した値を出力
  32.         Console.WriteLine(param);
  33.         
  34.     }
  35. }





狙い通りの実行結果です。

735_05.png

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/03/25(土) 17:55:36|
  2. 備忘録
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

PythonからMariaDB(MySQL)に接続する(mysql-connector-python)

PythonからMariaDB 10に接続してみます。
以前はMySQLdbを使用していたのですが、今回はmysql-connector-pythonを試してみます。

https://pypi.python.org/pypi/mysql-connector-python
https://dev.mysql.com/doc/connector-python/en/


Pythonを動かす端末はUbuntu 16.04。
MariaDBが動いているサーバーはFreeBSD 11.0 + MariaDB 10.1です。

ここで使用した環境です。
http://symfoware.blog68.fc2.com/blog-entry-1966.html



pipによるインストール



pipをインストールしていない場合はインストール。
続いて、mysql-connector-pythonをインストールします。


$ sudo apt install python-pip
$ sudo pip install mysql-connector




mysql.connectorをimport出来るか試してみます。


$ python
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import mysql.connector
>>>







接続サンプル



MariaDB側には「test」データベースに「sample」テーブルを作成済です。


  1. create table sample(
  2.     id int,
  3.     val varchar(100)
  4. );




接続情報は以下の通り。


server ip:192.168.1.101
id:admin
password:P@ssw0rd





データベースに接続し、登録や検索を行うサンプルはこんな感じになります。


  1. # -*- coding:utf-8 -*-
  2. import mysql.connector
  3. # データベース接続
  4. con = mysql.connector.connect(
  5.     host='192.168.1.101',
  6.     db='test',
  7.     user='admin',
  8.     passwd='P@ssw0rd'
  9. )
  10. # 辞書型カーソル取得
  11. cur = con.cursor(dictionary=True)
  12. # データの削除
  13. cur.execute('delete from sample')
  14. # 登録(すっぴん)
  15. cur.execute("insert into sample (id, val) values (1, 'テスト1')")
  16. # 登録(プレースフォルダ)
  17. cur.execute("insert into sample (id, val) values (%s, %s)", [2, 'テスト2'])
  18. # 登録(一括)
  19. insert_values = [
  20.     [3, 'テスト3'],
  21.     [4, 'テスト4'],
  22.     [5, 'テスト5']
  23. ]
  24. cur.executemany("insert into sample (id, val) values (%s, %s)", insert_values)
  25. # コミットして変更を確定
  26. con.commit()
  27. # 検索
  28. cur.execute("select * from sample")
  29. # 表示
  30. for row in cur:
  31.     print("id:%d, val:%s" % (row['id'], row['val']))
  32. # 切断
  33. cur.close()
  34. con.close()




カーソル取得時、dictionary=Trueとすることで、フィールド名をキーとした辞書型でデータが取り出せます。
これを指定していないと配列でのデータ取得となるため、
row[0], row[1]のような指定でデータを参照することになります。

自動的にトランザクションが開始されているため、明示的にcommitしないと
変更が確定しません。


実行結果


$ python sample.py
id:1, val:テスト1
id:2, val:テスト2
id:3, val:テスト3
id:4, val:テスト4
id:5, val:テスト5







データ取得方法あれこれ



selectを実行した後のカーソルはそのままイテレートできます。


  1. # -*- coding:utf-8 -*-
  2. import mysql.connector
  3. # データベース接続
  4. con = mysql.connector.connect(
  5.     host='192.168.1.101',
  6.     db='test',
  7.     user='admin',
  8.     passwd='P@ssw0rd'
  9. )
  10. # 辞書型カーソル取得
  11. cur = con.cursor(dictionary=True)
  12. # 検索
  13. cur.execute("select * from sample")
  14. # 表示
  15. for row in cur:
  16.     print("id:%d, val:%s" % (row['id'], row['val']))





fetchoneで先頭のレコードを取り出せます。


  1. # -*- coding:utf-8 -*-
  2. import mysql.connector
  3. # データベース接続
  4. con = mysql.connector.connect(
  5.     host='192.168.1.101',
  6.     db='test',
  7.     user='admin',
  8.     passwd='P@ssw0rd'
  9. )
  10. # 辞書型カーソル取得
  11. cur = con.cursor(dictionary=True)
  12. # 検索
  13. cur.execute("select * from sample")
  14. # 最初の行を取得
  15. row = cur.fetchone()
  16. # 表示
  17. print("id:%d, val:%s" % (row['id'], row['val']))




$ python sample.py
id:1, val:テスト1




fetchoneすると読み込む行が1つ進みます。
次の行がない状態でfetchoneすると「None」になります。

fetchoneしながらすべての行を読み取るプログラムは
こんな感じになります。


  1. # -*- coding:utf-8 -*-
  2. import mysql.connector
  3. # データベース接続
  4. con = mysql.connector.connect(
  5.     host='192.168.1.101',
  6.     db='test',
  7.     user='admin',
  8.     passwd='P@ssw0rd'
  9. )
  10. # 辞書型カーソル取得
  11. cur = con.cursor(dictionary=True)
  12. # 検索
  13. cur.execute("select * from sample")
  14. # 最初の行を取得
  15. row = cur.fetchone()
  16. # データが取得できている間はループ
  17. while row:
  18.     # 表示
  19.     print("id:%d, val:%s" % (row['id'], row['val']))
  20.     # 次の行を読み取り
  21.     row = cur.fetchone()




$ python sample.py
id:1, val:テスト1
id:2, val:テスト2
id:3, val:テスト3
id:4, val:テスト4
id:5, val:テスト5




fetchallですべての行を変数に代入できます。


  1. # -*- coding:utf-8 -*-
  2. import mysql.connector
  3. # データベース接続
  4. con = mysql.connector.connect(
  5.     host='192.168.1.101',
  6.     db='test',
  7.     user='admin',
  8.     passwd='P@ssw0rd'
  9. )
  10. # 辞書型カーソル取得
  11. cur = con.cursor(dictionary=True)
  12. # 検索
  13. cur.execute("select * from sample")
  14. # すべての行を取得
  15. rows = cur.fetchall()
  16. for row in rows:
  17.     # 表示
  18.     print("id:%d, val:%s" % (row['id'], row['val']))




$ python sample.py
id:1, val:テスト1
id:2, val:テスト2
id:3, val:テスト3
id:4, val:テスト4
id:5, val:テスト5




関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/03/23(木) 22:48:03|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

FreeBSD 11.0 + CodeIgniter 3でMariaDBに接続

FreeBSD 11.0にPHP7とMariaDB 10.1をインストールしました。

FreeBSD 11 nginx + php7-fpmの動作環境構築(pkg使用)
FreeBSD 11.0にMariaDB 10.1をインストールし外部接続を許可する(pkg使用)


php7からMariaDBへの接続を試してみます。
フレームワークとして、CodeIgniterを使用しました。



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



phpからはmysqliを使用して接続しようと思います。
pkgコマンドで、php70-mysqliをインストール。


# pkg install php70-mysqli




これだけで大丈夫だろうと思っていたら、接続時にこんなエラーが発生しました。


An uncaught Exception was encountered

Type:        Error
Message:     Call to undefined function ctype_digit()
Filename:    /var/dev/php/ci3/system/database/DB_driver.php
Line Number: 1404




http://php.net/manual/ja/function.ctype-digit.php

ctypeライブラリが追加で必要な模様。


# pkg install php70-ctype




これでエラーはなくなります。




CodeIgniter



登録、検索のテスト用に「test」データベースを作成。
sampleテーブルを作成しておきます。


  1. create table sample(
  2. id int,
  3. val varchar(100)
  4. );




ローカルのtestデータベースに
id:admin
pass:P@ssw0rd
で接続します。

データベース接続の設定ファイル
application/config/database.php
はこうなりました。


  1. <?php
  2. defined('BASEPATH') OR exit('No direct script access allowed');
  3. $active_group = 'default';
  4. $query_builder = TRUE;
  5. $db['default'] = array(
  6.     'dsn'    => '',
  7.     'hostname' => 'localhost',
  8.     'username' => 'admin',
  9.     'password' => 'P@ssw0rd',
  10.     'database' => 'test',
  11.     'dbdriver' => 'mysqli',
  12.     'dbprefix' => '',
  13.     'pconnect' => FALSE,
  14.     'db_debug' => (ENVIRONMENT !== 'production'),
  15.     'cache_on' => FALSE,
  16.     'cachedir' => '',
  17.     'char_set' => 'utf8',
  18.     'dbcollat' => 'utf8_general_ci',
  19.     'swap_pre' => '',
  20.     'encrypt' => FALSE,
  21.     'compress' => FALSE,
  22.     'stricton' => FALSE,
  23.     'failover' => array(),
  24.     'save_queries' => TRUE
  25. );





サンプルのコントローラー。


  1. <?php
  2. class Sample extends CI_Controller {
  3.     public function index() {
  4.         $this->load->database();
  5.         
  6.         $this->db->empty_table('sample');
  7.         
  8.         $this->db->insert('sample', ['id' => 1, 'val' => 'テスト1']);
  9.         $this->db->insert('sample', ['id' => 2, 'val' => 'テスト2']);
  10.         
  11.         $rows = $this->db->get('sample')->result_array();
  12.         foreach($rows as $row) {
  13.             echo 'id:' . $row['id'] . ',val:' . $row['val'] . PHP_EOL;
  14.         }
  15.         
  16.     }
  17. }




実行してみると...


# php index.php sample
id:1,val:テスト1
id:2,val:テスト2




ちゃんとデータの登録・取得が行えているようです。

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2017/03/20(月) 19:03:00|
  2. PHP
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
次のページ