2012年10月25日 星期四

Symfony2 console commands

# Generate Bundle.
php app/console generate:bundle --namespace="My/Bundle" --format=yml
Doctrine

# Create database.
php app/console doctrine:database:create
# Generate Entity.
php app/console doctrine:generate:entity --entity="MyBundle:MyEntity"
# Generate Entities getters and setters.
php app/console doctrine:generate:entities MyBundle
# Update schema.
php app/console doctrine:schema:update --force
# Generate CRUD.
php app/console doctrine:generate:crud --entity="MyBundle:MyEntity"
Asset
# Install assets into web folder with symlink.
php app/console assets:install web --symlink

2012年10月24日 星期三

Doctrine以Composite及Foreign Keys作主鍵(Primary Key)

Doctrine2 可以用composite keys作為primary key(例如用戶的姓加名字作為主鍵), 而Doctrine2.1更支援關聯的foreign key.

方法很簡單:
  1. Entity內不能有@GeneratedValue, 除非設定為"ASSIGNED".
  2. 在需要作為primary key的property加上@Id這個annotation.
  3. 需要__construct() 方法在建立物件時傳入作為primary key的property, 因為primary key不是自動生成, 沒有primary key呼叫EntityManager#persist()會有問題.
<?php
use Doctrine\Common\Collections\ArrayCollection;

/** @Entity */
class Order
{
    /** @Id @Column(type="integer") @GeneratedValue */
    private $id;

    /** @ManyToOne(targetEntity="Customer") */
    private $customer;
    /** @OneToMany(targetEntity="OrderItem", mappedBy="order") */
    private $items;

    /** @Column(type="boolean") */
    private $payed = false;
    /** @Column(type="boolean") */
    private $shipped = false;
    /** @Column(type="datetime") */
    private $created;

    public function __construct(Customer $customer)
    {
        $this->customer = $customer;
        $this->items = new ArrayCollection();
        $this->created = new \DateTime("now");
    }
}

/** @Entity */
class Product
{
    /** @Id @Column(type="integer") @GeneratedValue */
    private $id;

    /** @Column(type="string") */
    private $name;

    /** @Column(type="decimal") */
    private $currentPrice;

    public function getCurrentPrice()
    {
        return $this->currentPrice;
    }
}

/** @Entity */
class OrderItem
{
    /** @Id @ManyToOne(targetEntity="Order") */
    private $order;

    /** @Id @ManyToOne(targetEntity="Product") */
    private $product;

    /** @Column(type="integer") */
    private $amount = 1;

    /** @Column(type="decimal") */
    private $offeredPrice;

    public function __construct(Order $order, Product $product, $amount = 1)
    {
        $this->order = $order;
        $this->product = $product;
        $this->offeredPrice = $product->getCurrentPrice();
    }
}
參考資料: http://docs.doctrine-project.org/projects/doctrine-orm/en/2.1/tutorials/composite-primary-keys.html

2008年6月18日 星期三

MySQL的一些操作技巧

如果要backup MySQL database, 可以用mysqldump save成text file, 可以保存整個database或個別table, 要restore時可以在mysql 裡用source filename即可.

MySQL statement裡可以用變數來增加變化, 如想在select的result裡最左邊加一個column來表示行數, 而這個行數本身沒有記錄在table裡, 是select statement執行的時間動態產生.方法是:

1. set @v1=0;
(這裡是宣告一個叫@v1的變數, 值為0)
2. select @v1:=@v1+1, name from table;
(這裡是把最左邊的column定為@v1, 而@v1每次都會+1, 所以可以代表行數, 也可以混合其他function, 如 concat('no. ',@v1:=@v1+1) 這樣行數會變成"no. 1", "no. 2", ...)
p.s. 要注意是用":="而不是平常statement用的"="

2008年5月14日 星期三

Drupal

安裝好Drupal, cleanURL無法啟動, drupal.org中提到需要在/etc/httpd/conf/http.conf中uncomment LoadModule rewrite_module modules/mod_rewrite.so 這行才可以.
但照做了也一樣無法啟動, 後來看下去才知道要加

<Directory "/var/www/html/drupal-6.2">
AllowOverride All
</Directory>

加了以後就能啟動

2008年4月7日 星期一

find 指令 time 選項及 xargs 一起使用

今天看了一下catchall的mailbox, 有9萬多封郵件, 我的postfix是以directory方式儲存郵件,每個郵件都是一個檔案, 開次一打開這個資料夾都很慢, 所以想按日期分類, 減少單一資料夾的檔案數.

我的catchall是以IMAP連接dovecot的式, 需要先create 一些按日期的資料夾, 以2008-01, 2008-02, ...的分類成式, 由於每個用也有兩萬封, 還是太多, 所以再在每個月裡create 01-10, 11-20, 11-31資料夾, 按日分類, 兩這些資料夾的實際path是在catchall Maildir/.INBOX.2008-01.01-10, Maildir/.INBOX.2008-01.11-20, ...把郵件按日期move到這些folder裡的new或cur即可(dovecot會在IMAP登入時把郵件從new移到cur).

但catchall inbox的郵件太多, 執行ls等指令很慢, 單用mv 及 rm等指令一次也不能處理太多檔案. 其中一個辦法是以find找到想移動的檔案再用xargs送到mv處理, find 能處理的檔案很多, 但好像也有限(至少9萬個處理不了, 會直接停止執行), 所以find的使用要有點技巧.

find的功能很多, 這次要以郵件檔的modification time來判斷它到達server的時間, 所以要用mtime選項(因為ctime在移動後會改為移動的時間, 所以執行第二次已經不能判斷).

find . -mtime n 當中 . 為目前路徑搜尋, n 為數字, 代表多少個24小時. mtime default是以當前時間的n*24小時計算, 如果想要以當日的24:00作基準(實際是向未來的時間方向移動,即明日的00:00的n*24小時計算),需要加上-daystart參數.

n 的數值為 0 時代表現在到24小時前之間, 加上daystart代表現在到今天00:00之間
n 的數值為 1 時代表24小時前到48小時前之間, 加上daystart代表今天00:00到昨天00:00之間(即整個昨天)
n 還可以加+或-, 分別代表1(24小時前到48小時前的時段)的兩邊, 但不包括1, 即-1代表現在(理論上是無限的未來)到24小時前的時段, +1代表48小時及之前(理論上是無限的過去)的時段. -0應該沒有任何結果, 除非有未來建做的檔案存在, 有這樣的檔案應該是電腦的時間調校錯了.
之外mtime可以組會使用, 如:
find . -mtime +1 -mtime -3 這裡指48小時前及未到72小時之間, 相當於 -mtime 2.

了解mtime的用法後回到剛才的一個問題上, find遇到超出數量時也不能運作, 所以在我那個有9萬個files的folder上使用時需要些技巧, 經我測試發覺組合的mtime是由左至右執行,例如我想找48小時前至72小時前之間的files, 需要用 -mtime +1 及 -mtime -3, 如果是:

find . -mtime +1 -mtime -3 這樣會先執行 +1 , 即所有48小時前的檔案, 以我的情況是至少有8萬多個, 一段時間後自動跳出執行, 沒有結果. 相反:

find . -mtime -3 -mtime +1 這樣會先執行 -3, 現在至72小時前之間, 有幾千, 沒有超出限量, 跟著再以 +1把現在至48小時前之間的除去, 得到我想要的結果.

以find 找到檔案後要送給xargs再執行mv:
find . -mtime -3 -time +1 | xargs -i mv {} destination.
當中 -i 代表用{}代表前面送來的結果(這裡即find的結果), {}代表find的結果, 並作為mv的source, destination代表目標路徑.
除了-i外可以用 -I, 差別是-I可以指定代表結果的字完, 如:
xargs -i mv {} /tmp
相當於:
xargs -I [] mv [] /tmp

最後成功把emails按日期分類.

2008年1月13日 星期日

NTP server 設定

安裝套件:
ntp: NTP server的主要套件啦,包括設定檔以及執行檔等等,都是這個套件提供的;

tzdata: 套件名稱為『 Time Zone data 』的縮寫,提供了各個時區對應的顯示格式。

主要檔案:
/etc/ntp.conf: ntp的主要設定檔.
/usr/sbin/ntpd: ntp的daemon, 啟動時會讀取ntp.conf的設定.
/usr/sbin/ntpdate: ntp的client, 用來連接NTP server.
/bin/date: 可以顯示或修改時間, 但不會存到BIOS.
/sbin/hwclock: root才能執行,把時間寫入BIOS.

ntp是使用類似於DNS的階層式的架構, 每一層稱為stratum, 下層stratum會向上曾同步, 最多可以有15層.在Linux架設ntp server主要設定ntp.conf

ntp.conf中可以用restrict參數來限制連線, 其用法是:
restrict [ip] mask [netmask_ip] [parameter]
parameter有:
  1. ignore 拒絶所有ntp連線,
  2. nomodify 用戶不能修改,
  3. noquery 用戶不能查詢,等於不提供網絡校時,
  4. notrap 不提供trap ( remote event logging ),
  5. notrust 拒絶沒有認証的用戶.
如沒加任何parameter代表不設任何限制,另外上層的NTP server必須在被允許的清單內才能同步.
設定上層NTP server:
server [ ip or hostname ] [ prefer ]
其中prefer代表優先使用

設定記錄BIOS與NTP server震盪的誤差:
driftfile [可以被ntpd寫入的目錄及檔案 ]

設定以certificate來控制權限:
key [ keyfile]

另外在 /etc/sysconfig/ntpd裡面的SYNC_HWCLOCK改為yes:
SYNC_HWCLOCK=yes
可以就會把ntpd同步的時間寫入BIOS中

Client可以用ntpdate [ip or hostname]來與NTP server同步時間,然後用hwclock -w寫入BIOS即可.
在/etc/crontab中加入
10 5 * * * /usr/sbin/ntpdate server_ip && /sbin/hwclock -w
可以在每天5:10時與server_ip同步時間.

port number

ntp udp 123