2014年12月25日 星期四

yii redirect轉址說明


跳到絕對路徑:
$this->redirect('http://code-joker.blogspot.tw/');

跳到本身Controller的某個action:
$this->redirect(array('index');

在module(模組)裡要跳到預設的Controller裡(protected/controllers/):
$this->redirect(array('/user/index');

在module(模組)裡要跳到本身模組的其他Controller:
$this->redirect(array('other/index');

在module(模組)裡要跳到其他模組的其他Controller:
$this->redirect(array('/ortherModule/otherController/index');

PS:常用到的URL請取得方式參考下面連結


參考:
YII路由跳转forward\redirect
Yii的常用URL和渲染方法

2014年10月31日 星期五

yii 產生pdf 大破解 (史上最清楚的TCPDF教學)

前言 

要在yii使用tcpdf根本不用去找別人寫的套件, 只要載入官方的檔案就可以了! 
ps: 我會將tcpdf檔案放在extensions純粹是讓整個架構合理, 日後管理起來比較好找而已.

前置作業

1. 下載TCPDF (按我)

2. 解壓縮後將examples資料夾刪掉 (不需要), 這時候全部的檔案會在一個tcpdf的資料夾裡

3. 將tcpdf資料夾傳到yii 的第三方套件資料夾 (protected/extensions)

4. 到yii 的設定檔 (protected/config/main.php), 將tcpdf路徑加進去

'import' => array(
'application.models.*',
'application.components.*',
'ext.tcpdf.*',
),

5. 進到tcpdf的設定檔 (extensions/tcpdf/config/tcpdf_config.php) *重要
-如果你產生的pdf裡面要有logo的話, 先取消掉 K_PATH_IMAGES的註解, 然後設定你的logo路徑:

define ('K_PATH_IMAGES', '你的logo路徑');

如果我們的路徑是在專案下的img資料夾, 那路徑就是 var/www/ProjectName/img/member/
但是, 更活一點的寫法可以這樣:

$imgPath = dirname(Yii::app()->BasePath) . '/img/member/';
define ('K_PATH_IMAGES', $imgPath);

-設定可以顯示中文字
將PDF_FONT_NAME_MAIN的helvetica改成msungstdlight

開發

Contrller

1. 在你的controller裡設定空白的layout, 設定的方式參考下面兩篇
所謂空白layout就是裡面只有這行:
<?php echo $content; ?>

ps: 要用空白layout的原因是, 在tcpdf產生出pdf前, 如果有任何輸出的話就會出錯!

2
public function actionPrint()
{
$this->layout = '//layouts/nothing';
$data = array(
'name' => '中二不解釋',
'age' => '18',
'tel' => '0910855555',
'note' => '沒事就打lol',
);
$html = Yii::app()->controller->renderPartial('print_templet', array('data'=>$data), true, true);
$this->render('print',array(
'html'=>$html,
));
}

View

1. print_templet.php

<table>
<tr>
<td>
姓名
</td>
<td>
<?php echo data['name']; ?>
</td>
</tr>
<tr>
<td>
年紀
</td>
<td>
<?php echo data['age']; ?>
</td>
</tr>
<tr>
<td>
電話
</td>
<td>
<?php echo data['tel']; ?>
</td>
</tr>
<tr>
<td>
備註
</td>
<td>
<?php echo data['note']; ?>
</td>
</tr>
</table>

2. print.php

$pdf = new tcpdf('P', 'mm', 'A4', true, 'UTF-8', false);

$pdf->SetCreator('Joker love you');
$pdf->SetAuthor('joker');
$pdf->SetTitle('Welcome to joker.tw!');
$pdf->SetSubject('TCPDF Tutorial');
$pdf->SetKeywords('TCPDF, PDF, PHP');

$pdf->setHeaderData('logo.png', 30, 'joker.tw', '反攻大陸就靠promo!', array(0,64,255), array(0,64,128));
$pdf->setFooterData(array(0,64,0), array(0,64,128));

$pdf->setHeaderFont(Array('msungstdlight', '', '10'));
$pdf->setFooterFont(Array('helvetica', '', '8'));

$pdf->SetDefaultMonospacedFont('courier');

$pdf->SetMargins(15, 27, 15);
$pdf->SetHeaderMargin(5);
$pdf->SetFooterMargin(10);

$pdf->SetAutoPageBreak(TRUE, 25);
$pdf->setImageScale(1.25);
$pdf->setFontSubsetting(true);
$pdf->SetFont('msungstdlight', '', 14, '', true);

$pdf->AddPage();

$pdf->writeHTML($html, true, false, true, true, '');

$style = array(
    'border' => 2,
    'vpadding' => 'auto',
    'hpadding' => 'auto',
    'fgcolor' => array(0,0,0),
    'bgcolor' => false, //array(255,255,255)
    'module_width' => 1, // width of a single module in points
    'module_height' => 1 // height of a single module in points
);

$pdf->write2DBarcode('www.google.com.tw', 'QRCODE,H', 20, 210, 40, 40, $style, 'N');
$pdf->Text(20, 200, '掃我者得永生');

$pdf->Output('penisIsGood.pdf', 'I');


技術說明

1. renderPartial這個很屌, 它跟render的差異在於:

-renderPartial本質上就是include一個php文件。它和render的不同點在於後者在include完一個php文件後還會把顯示的內容安插到一個layout中。

以上說明引用自 renderPartial 的用法

-renderPartial的參數可以看官方說明
-參數的說明可以看 Yii的中渲染和的RenderPartial的區別

2014年10月16日 星期四

yii 如何在一個controller使用不同的layout?

關於yii的layout結構我們可以先參考這篇 yii 設定你的layout


如果我們的controller裡有兩個action, 我要如何各別設定layout?

class IntroductionController extends Controller {  
  
    public $layout = '//layouts/common';  //設一個這個controller預設的layout
  
    public function actionShowMe() {  
        $this->render('showme');  //使用上面預設的layout!
    }  
  
    public function actionSeeYou(){  
$this->layout = '//layouts/custom_layout';  //這樣就可以使用別的layout了!
$this->render('seeyou');  
    } 

}

參考資料:

2014年10月11日 星期六

yii 設定你的layout

我們先了解一下yii的layout運作流程

1. 我們建的Controller都會在一開始繼承一個叫Controller的Class

class IndexController extends Controller
{
....
}

2. 這個Controller的Class在哪裡呢? 原來就在components (組件)裡, 路徑如下:
components/Controller.php

裡面結構很簡單
class Controller extends CController
{
public $layout='//layouts/column1'; //這是yii預設的layout
public $menu=array();
public $breadcrumbs=array();
}

3. //layouts/column1在哪裡呢? 在views/layouts/column1.php

結構如下:
<?php $this->beginContent('//layouts/main'); ?>
<div id="content">
<?php echo $content; ?>
</div><!-- content -->
<?php $this->endContent(); ?>

4. 同理//layouts/main的路徑就在views/layouts/main.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="language" content="en" />
<!-- blueprint CSS framework -->
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/screen.css" media="screen, projection" />
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/print.css" media="print" />
<!--[if lt IE 8]>
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/ie.css" media="screen, projection" />
<![endif]-->
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/main.css" />
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/form.css" />
<title><?php echo CHtml::encode($this->pageTitle); ?></title>
</head>
<body>
<div class="container" id="page">
<div id="header">
<div id="logo"><?php echo CHtml::encode(Yii::app()->name); ?></div>
</div><!-- header -->
<div id="mainmenu">
<?php $this->widget('zii.widgets.CMenu',array(
'items'=>array(
array('label'=>'Home', 'url'=>array('/site/index')),
array('label'=>'About', 'url'=>array('/site/page', 'view'=>'about')),
array('label'=>'Contact', 'url'=>array('/site/contact')),
array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),
array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!Yii::app()->user->isGuest)
),
)); ?>
</div><!-- mainmenu -->
<?php if(isset($this->breadcrumbs)):?>
<?php $this->widget('zii.widgets.CBreadcrumbs', array(
'links'=>$this->breadcrumbs,
)); ?><!-- breadcrumbs -->
<?php endif?>
<?php echo $content; ?>
<div class="clear"></div>
<div id="footer">
Copyright &copy; <?php echo date('Y'); ?> by My Company.<br/>
All Rights Reserved.<br/>
<?php echo Yii::powered(); ?>
</div><!-- footer -->
</div><!-- page -->
</body>
</html>

好, 重點來了! $content就是你render指定的view內容
所以有感覺了嗎?
也就是除了$content以外的hmtl在畫面上就是固定的!!
這樣我們就可以任意調整我們的布局了! (ex: 左側選單固定、上方選單固定...etc)




那我們該如何使用自己寫的layout呢? 很簡單!

1. 把你的layout丟到layouts資料夾裡

2. 進到你的controller (不管是在controllers還是modules都可以), 加入下面的code
public $layout='//layouts/你的layout檔名';
ps: 檔名就好, 不用加副檔名

3. 結束!

那如果是module的話呢?
1. 把你的layout丟到你module的view裡 (ex: modules/user/view/layouts/)

2. 進到你module的controller, 加入這句
public $layout='//modules/user/view/layouts/你的layout檔名';

3. 大功告成!

2014年10月10日 星期五

yii 如何改變登入路徑

1. 打開你的config/main.php

2. 在components的user新增loginUrl
'components'=>array(
'request'=>array(
.....
),
),

'session' => array(
.....
),
),

'user'=>array(
'loginUrl'=>array('admin/index/login'),
'allowAutoLogin'=>true,
),
)

我的路徑是admin/index/login是因為我登入頁的相關路徑如下:
controller -> modules/admin/controllers/indexController.php
view -> modules/admin/views/index/login.php

至於登入的controller怎麼寫? 很簡單
1. 打開controllers/SiteController.php
2. 把actionLogin跟actionLogout複製起來, 貼到你的登入controller就好了!
ps: 當然, yii預設的管理帳密是寫死在php裡的, 記得改成跟資料庫比對就可以了!

2014年10月6日 星期一

yii 建立module大解密

兩種方式可以建立module

1. Gii























可以看到yii會幫我們建立以下的資料:

1. cart資料夾
-CartModule.php

2. cart/controllers資料夾
-DefaultController.php

3. cart/views資料夾

4. cart/views/default資料夾
-index,php


2. yiic shell (參考這篇)






































跟用Gii建立module的差別在, shell會多新增下面幾個資料夾:
1. components
2. messages
3. models
4. views/layouts

整體來看用shell建立的是比較完整, 不過如果你的module不會用到components跟messages的話, 其實用Gii就夠了!

不用擔心models, 因為一樣可以透過Gii來替你的module建立model, 還有CRUD
(可以參考這篇)

3. Set Module

1. 進到config/main.php

2. 將你的模組 (module) 加進去, 假設你的模組叫user:
'modules' => array(
'user',
// uncomment the following to enable the Gii tool
'gii' => array(
'class' => 'system.gii.GiiModule',
'password' => 'you password',
// If removed, Gii defaults to localhost only. Edit carefully to taste.
'ipFilters' => array('127.0.0.1','::1'),
),

yiic shell Error: index.php does not exist or is not an entry script file大解密!

今天我要使用yii 的shell指令時 (參考這篇)

在第一行 
yiic shell就出錯了!

























它說它找不到index.php~

所以就給它我們用webapp建立專案時, 內建的index.php路徑就可以了!












說明一下:
我的專案名稱是www, 跟framework在同一層目錄下
development
| -framework
| -www

yiic.bat     在framework裡
index,php 在www裡

所以下的指令就會是上面這樣

yiic shell ../www./index.php

假掰一點的表示法就是

>yiic shell webapp path/index.php

2014年8月1日 星期五

yii framework - 如何避免跨站請求偽造攻擊(CSRF)?

要開啟CSRF功能, 必須先到config/main.php裡新增以下code:

'request' => array(
            'enableCsrfValidation' => true,
        ),
 
避免遭受到CSRF攻擊有兩個注意的地方:
1. GET只能用在查資料, 不能用在其他資料庫的操作.
2. POST必須要能產生一個隨機值並且讓server端能辨識, 進而回傳資料到client端.
 
所以在yii裡面使用表單傳送(POST)的時候, 一定要使用CHtml::form, 或是Widget的CActiveForm.
千萬不要自己寫HTML, 要不然會出現以下的error:

Error 400

The CSRF token could not be verified.
因為用yii內建的來寫form, 它會生成一個隱藏的input, 裡面會有一個隨機的值, 以防止CSRF攻擊!
 
另外, 你會發現我們使用gii建立的後台, 刪除功能居然不能用了!!! 怎麼會這樣呢?
其實就像上面說的,  GET只能用在查資料, 不能用在其他資料庫的操作.
所以我們必須要做些設定, 以刪除功能為例, 原本的code如下:
array('label' => 'Delete', 'url' => '#', 'linkOptions' => array( 
 'submit' => array( 
  'delete', 'id' => $model->id), 
  'confirm' => '你確定要刪除' . $model->name . '?' 
 ),
),

請改為

array('label' => 'Delete', 'url' => '#', 'linkOptions' => array( 
 'submit' => array( 
  'delete', 'id' => $model->id), 
  'confirm' => '你確定要刪除' . $model->name . '?' 
  'csrf' => true,
 ),
),

這樣問題就解決嘍^^

2014年7月17日 星期四

yii framework - 如何上傳照片 (多張)? 使用CMultiFileUpload+getInstances

跟 yii framework - 如何上傳照片 (單張)? 使用CUploadedFile 一樣
要實現多張照片上傳功能, 一樣要在model、conrtoller、view三管齊下才能完成,
我會逐一說明 (以M->V->C的順序).

本次實作的目標:
一次將多張照片上傳至指定資料夾, 並將照片的檔名存到資料庫 (用,分隔每個檔名), 以便之後取用.



Model
在你的models裡的rules()新增以下code:
array('dbFieldsOfTheImage', 'file', 'types'=>'jpeg, jpg, png', 'allowEmpty'=>true),

1. 請將這邊的dbFieldsOfTheImage改為你照片上傳的資料表欄位名稱
2. types指的是, 指定的上傳檔案類型 (如果你要讓人上傳的是excel, 那就打上xls, xlsx...etc)

PS:還有許多參數可做設定, 例如檔案大小限制、錯誤訊息, 可參考 (CFileValidator)


重要:
網路上很多範例都會少了allowEmpty這個參數, 就像這篇 Multiple files uploader with CMultiFileUpload.

結果就會非常慘, 就是會發生檔案上傳了, 但是填寫表格的資料一直存不進資料庫. 然後會出現錯誤:XXX cannot be blank, 然後你就會匪夷所思, 明明檔案都上傳了, 檔名也都抓到了, 為什麼就是存不進去.

原來因為我們在model裡設定它是file, 所以它上傳的是檔案, 而不是一個字串 (檔名), 所以我們必須要設allowEmpty這個參數, 告訴model我們允許它是空的, 這樣在save的時候才不會被model的規則給擋住!!!

這部分我卡了好幾天, 真的很重要阿~ 各位.


View
一樣是改_form.php這個檔案 (框架預設), 修改以下的code:
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'bnb-form',
'enableClientValidation'=>true,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)); ?>

<?php
$this->widget('CMultiFileUpload', array(
'model' => $model,
'attribute' => 'bnbImg',
'accept' => 'jpeg|jpg|png',
'duplicate' => '你選過這個照片了喔!',
'denied' => '請選擇jpeg、jpg、png格式的影像!',
 'htmlOptions' => array('multiple' => 'multiple'),
'max' => 5,
));
?>

上傳檔案最重要的就是htmlOptions這個參數裡面的設定一定要是'enctype' => 'multipart/form-data'.

至於'enableClientValidation'=>true, 這個非常好用! 它會依你的model的規則設定來生成對應的JavaScript來做Client端的驗證, 超屌. 不過跟上傳檔案沒關係.

1. 
attribute會生成HTML input的id跟name. 例如: 我資料表叫Test, 欄位是fuck, 這時候我設定'attribute' => 'fuck', 就會產生以下code:

<input id="Test_fuck" type="file" value="" name="Test[fuck][]" />

2. 
accept - 允許的檔案格式
duplicate - 當選到重複的照片時跳出的警告視窗
denied - 當夾帶不是我們規定的檔案格式時, 跳出的警告視窗
'htmlOptions' => array('multiple' => 'multiple') - 可讓你一次選多張
max - 最多可上傳的檔案數量

別懷疑, 做了這些設定, yii就幫你把它生成JavaScript, 讓你爽的死去活來的!!

重要:
有些人會在CActiveForm裡做AJAX, 所以會加上這個 'enableAjaxValidation'=>false,
在表格有檔案上傳的欄位時千萬不要加那個! 因為它會讓你出錯, 以下擷取官方部分內容:
基於AJAX的驗證有一些限制:首先,它不能用於文件上傳字段;其次,它不能用於可能產生服務器端狀態改變的驗證;第三,它目前還不能用於表格式輸入的驗證。

Conrtoller
public function actionCreate()
{
$model = new Bnb;

if(isset($_POST['Bnb']))
{
$model->attributes=$_POST['Bnb'];
/*
$uploadPath Set info:
Linux: /images/bnb/ , Win: \images\bnb\
*/
$uploadPath = DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'bnb' . DIRECTORY_SEPARATOR;

if($allFilesName=$this->uploadMultiFile($model, 'bnbImg', $uploadPath))
$model->bnbImg = implode(",", $allFilesName);

if($model->save())
$this->redirect(array('view', 'id'=>$model->bnbId));
}

$this->render('create',array(
'model'=>$model,
));

}

private function uploadMultiFile($model, $attr, $path)
{
if($fileInfo = CUploadedFile::getInstances($model, $attr))
{
foreach ($fileInfo as $i=>$file)
{
$formatName = $file->name;
$file->saveAs(Yii::getPathOfAlias('webroot') . DIRECTORY_SEPARATOR . $path . $formatName); //webroot: you'r project/protected
$allFilesName[$i] = $formatName;
}
return ($allFilesName);
}
 }

1. 用 DIRECTORY_SEPARATOR 是因為路徑在Linux跟windows不一樣的, 所以為了都能正常運做, 就用了比較長的寫法. (參考 DIRECTORY_SEPARATOR的作用)
2. 將上傳的code單獨寫成uploadMultiFile是為了讓整個可讀性更高, 避免程式絮亂, 以方便維護.


Finish~ thx GOD


參考資料:CMultiFileUpload

2014年7月5日 星期六

yii framework - 如何用AJAX來做表單驗證 (client端)

yii真的太猛了!

上次 如何用AJAX來做表單驗證 用的方式是在server端做驗證, 所以用的是

'enableAjaxValidation'=>true,

不過事實上我們很多時候, 是(只)需要用到client端驗證, 那怎麼辦呢?
很簡單! 加上下面的code就可以了!

'enableClientValidation'=>true,
'clientOptions'=>array(
'validateOnSubmit'=>true,
),

這樣yii就會用jQuery來作client端的驗證了~! 並且沒全部通過還不讓使用者送出喔^^

真的超屌的!!

所以如果有些地方需要很嚴謹的檢查的話, 就可以兩個都加上去, 這樣就可以在server及client端做驗證

yii framework - 如何用AJAX來做表單驗證 (server端)

在我們使用gii來建立我們的CURD後, 我們可以在Controller最下面看到這個function

protected function performAjaxValidation($model)
{
if(isset($_POST['ajax']) && $_POST['ajax']==='house-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
}

原來~ yii已經幫我們建立好AJAX的驗證code了!
那我們來實作吧!


STEP 1
在Contorller裡需要用到AJAX的action加上這句:
$this->performAjaxValidation($model);

結果就會像這樣:

public function actionCreate()
{
$model=new Bnb;
$this->performAjaxValidation($model);

if(isset($_POST['Bnb']))
{
$model->attributes=$_POST['House'];
if($model->save())
$this->redirect(array('view', 'id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));

}


STEP 2
view裡的_form.php打開AJAX服務

<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'house-form',
'enableAjaxValidation'=>true,
)); ?>



NOTE:
驗證的相關規則是在models裡喔! 

ex:
public function rules()
{
return array(
array('adminId, adminPw, 'required'),
array('adminMail', 'email'),
);
}

yii內建的驗證功能如下:(CValidator)

required
驗證屬性值必需有值,不能為空
fil​​ter
用過濾器轉換屬性的值
match
驗證屬性值匹配一個正則表達式
email
驗證屬性值為有一個有效的Email地址
url
驗證屬性值是一個有效的URL
unique
驗證屬性值在表中的對應列中是唯一的
compare
驗證屬性值與另一個屬性的值相等
length
驗證屬性值的長度在一個範圍內
in
驗證屬性值在一個預定義列表中
numerical
驗證屬性值是數字
captcha
驗證屬性的值等於一個顯示的CAPTCHA(驗證碼)的值
file
驗證屬性值包含上傳的文件
type
驗證屬性值是一個指定的數據類型
default
驗證屬性值為分配的默認值
exist
驗證屬性值在表中的對應列中存在
boolean
驗證屬性值是布爾值(true或false)
safe
標記屬性值為安全
unsafe
標記屬性值為不安全
date
驗證屬性值是日期


2014年7月4日 星期五

yii framework - 如何上傳照片 (單張)? 使用CUploadedFile

要實現照片上傳功能, 需在model、conrtoller、view三個地方逐一修改才能完成,
我會逐一說明 (以M->V->C的順序).

本次實作的目標:
將照片上傳至指定資料夾, 並將照片的檔名存到資料庫, 以便之後取用.


Model
在你的models裡的rules()新增以下code:

array('dbFieldsOfTheImage', 'file', 'types'=>'jpg, gif, png'),

1. 請將這邊的dbFieldsOfTheImage改為你照片上傳的資料表欄位名稱
2. types指的是, 指定的上傳檔案類型 (如果你要讓人上傳的是excel, 那就打上xls, xlsx...etc)

PS:還有許多參數可做設定, 例如檔案大小限制、錯誤訊息, 可參考 (CFileValidator)


View
看看你的controller新增、修改對應的view, 會發現表單的實體是在_form.php這個檔案 (框架預設),
進到_form.php後修改以下code:

<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'bnb-form',
'enableAjaxValidation'=>false,
'htmlOptions' => array('enctype' => 'multipart/form-data'), <-新增這行
)); ?>

然後在新增這段, 才會有上傳的按鈕出現
<div class="row">
<?php echo $form->labelEx($model,'dbFieldsOfTheImage'); ?>
<?php echo $form->fileField($model,'dbFieldsOfTheImage'); ?>
<?php echo $form->error($model,'dbFieldsOfTheImage'); ?>
</div>

注意第二個的fileField, 在yii的框架預設下是textField (文字框), 要改成fileField.


Conrtoller
public function actionCreate()
{
$model=new House;

if(isset($_POST['House']))
{
$model->attributes=$_POST['House'];
$imageUploadFile = CUploadedFile::getInstance($model,'houseImg');
$fileName = $imageUploadFile->name;
$model->bnbImg = $fileName;
if($model->save())
$file_path = Yii::app()->basePath.'/../images/house/' . $fileName;
$imageUploadFile->saveAs($file_path);
$this->redirect(array('view', 'id'=>$model->bnbId));
}

$this->render('create',array(
'model'=>$model,
));
}

1. 使用CUploadedFile::getInstance為一個模型屬性生成一個文件輸入框
2. $imageUploadFile->name可以取得檔名 (連同副檔名)
3. saveAs是將上傳的照片從上傳的暫存區移到指定的目錄 (記得要目錄+檔名喔!)


PS:
1. Yii::app()->basePath是取得網站的protected資料夾位置, 如果你的網站建置時取名www, 那就會返回 - 網站在主機的路徑/www/protected. 所以如果你的照片位置在網站根目錄下的images, 那就要用".."返回到上一層, 並進到images資料夾. ex: Yii::app()->basePath.'/../images/

其實用 Yii::getPathOfAlias('webroot')就可以直接取得網站專案名/protected的路徑 - 2014.7.6 補充

2. 測試後發現上傳的資料夾要先建立好, 要不然會出錯 (如果有需要可以自己寫一個建資料夾的程式)

2014年6月30日 星期一

yii framework - [UI] 如何變更CGridView的檢視、修改、刪除icon及超連結?

先來看段code:

<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'user-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'id',
'name',
'phone',
array(
'class'=>'CButtonColumn',
'template'=>'{lookMyDetail} {justUpdate} {deleteMe}',
'buttons'=>array
(
'lookMyDetail' => array
(
'label'=>'來看我的一切秘密吧',
'imageUrl'=>Yii::app()->request->baseUrl . '/images/icons/view.png',
'url'=>'Yii::app()->createUrl("user/detail", array("id"=>$data->id))',
),
'justUpdate' => array
(
'label'=>'就是要改怎樣?',
'imageUrl'=>Yii::app()->request->baseUrl . '/images/icons/update.png',
'url'=>'Yii::app()->createUrl("user/adminUpdate", array("id"=>$data->id))',
),
'deleteMe' => array
(
'label'=>'刪掉我的記憶',
'imageUrl'=>Yii::app()->request->baseUrl . '/images/icons/delete.png',
'url'=>'Yii::app()->createUrl("user/delete", array("id"=>$data->id))',
),
),
),
),
));
?>

紅色字就是特別要注意的地方!

1. 首先columns是你要顯示的欄位
2. CButtonColumn就是為了後面的按鈕所呼叫的class
3. template非常重要!! 這裡預設是{view} {update} {delete}, 分別代表三個按鈕的順序及超連結目標.

例如:

如果我只想要刪除、修改的話, 那就是 {delete} {update}, 這樣就不會有檢視 (view的圖案跟連結), 而且順序也改變了!

再進階點:

那就是如上面的例子, 透過設置buttons的array參數來添加
1. 滑鼠移過去時的文字提示 (label)
2. 圖示 (imageUrl)
3. 超連結的網址 (url)

這樣就可以符合我們的基本需求了吧^^ 來睡嘍~

yii framework - [UI] 如何修改CListView的id連結?

一般我們會在view裡看到這段code

<?php $this->widget('zii.widgets.CListView', array(
'dataProvider' => $dataProvider,
'itemView' => '_view',
)); ?>

然後我們會看到一個把db"部分"資料列出來的表格, 第一欄的id預設的超連結是xxx/view

但是我要改成detail要怎麼改呢?

本來以為要改變id的超連結要設定CListView的參數, 但是查半天都沒看到...

最後原來要修改的東西是在_view.php這個檔案裡...暈

<b><?php echo CHtml::encode($data->getAttributeLabel('bnbId')); ?>:</b>
<?php echo CHtml::link(CHtml::encode($data->bnbId), array('view', 'id'=>$data->bnbId)); ?>
<br />

view改成detail就搞定了!! 就這麼簡單...睡覺去zzzz

2014年6月24日 星期二

yii framework - [UI] 按鈕超連結設定linkButton、CJuiButton

如果要單純生成一個具有超連結功能的按鈕, 並且可以傳值, 有幾種方式:

這是常用的兩種 linkButtonCJuiButton

CHtml::linkButton('變更', array(
'submit'=>array('food/update', 'id'=>$model->id)
));

$this->widget('zii.widgets.jui.CJuiButton', array(
'buttonType'=>'link',
'name'=>'update',
'caption'=>'變更',
'url'=>array('food', 'id'=>$model->id),
));

linkButton (官方說明)
會生成一個一般的超連結, 不過他並不會大剌剌的將你的參數跟值秀出來
(ex: index.php?r=food/update&id=xxxxx)

CJuiButton (官方說明)
由於這是yii封裝了jQueryui, 所以它會生成一個很漂亮的按鈕樣式, 並且提供許多實用的功能
不過他大剌剌的將你的參數跟值秀出來


CHtml提供了一般前端會需要的一些東西, 例如:
tag、textArea、form、button、radio....等

而CJuiWidget則封裝了jQueryui, 所以jQueryui的東西都可以直接用, 真的是很方便

2014年6月20日 星期五

yii framework - 分頁功能要怎麼做? 運用CPagination+CLinkPager

分頁是一個網站的常見功能, 所以勢必要學會如何使用! 那我們開始吧!


首先是Controller的部分:
function actionIndex(){
    $criteria = new CDbCriteria();
    $count=Article::model()->count($criteria);
    $pages=new CPagination($count);

    $pages->pageSize=10;
    $pages->applyLimit($criteria);
    $models = Post::model()->findAll($criteria);

    $this->render('index', array(
    'models' => $models,
         'pages' => $pages
    ));
}

說明:
1. CDbCriteria把你要抓的資料條件都設好 ( 查詢資料大解密之"CDbCriteria到底是什麼? )
2. count得到符合條件的資料筆數
3. 把得到的資料筆數丟到CPagination
4. pageSize設定每個分頁要顯示幾筆
5. applyLimit 設定SQL的limit跟offset, 來得到當下選擇的分頁資料 ( 官方的applyLimit-detail說明 )
6. 將$pages渲染 (render)到view去

2014年6月12日 星期四

Swift-中文導覽手冊

相信很多人都在Apple的WWDC 2014看到這個新語言, 並且躍躍欲試.
但是官方的文件是英文的阿! 雖然說身為一位程式設計師要有一定的讀英文能力啦~
不過如果有中文版的勢必會加速大家在新語言的學習速度阿!
小第剛好爬到由許多大大共同完成的Swift中文版, 並公開分享 (實在偉大)


下面就是Swift的中文版導覽手冊:

https://www.gitbook.com/book/tommy60703/swift-language-traditional-chinese/details

2014年5月17日 星期六

yii framework - 如何一次寫入多筆資料?

假設現在要購買一台, 車的紀錄有顏色最高時速 (饒了我~ 我比較懶~先舉這兩個就好),
並且我們有個購物車清單陣列來紀錄所有要買的車.

一般我們新增 (insert)單筆資料時用的方法是 save(), 例如:

$car=new Car;        
$car->color=$color
$car->maxSpeed=$speed; 
if($car->save ()){ 
   echo "新增成功";  
}else{  
   echo "新增失败";  
}
但是當我們要新增多筆的時候呢? 例如:

2014年5月2日 星期五

yii framework - 如何使用某個資料夾的php function呢?

假設我們今天要在專案下新增一個資料夾 (ex: Tools)來統一管理我們寫的function
 (ex: test.php裡的function showMyName)時, 要怎麼做呢?

test.php
<?php
class Custom
{
  publice function showMyName($name)
 {
  return $name;
 }
}
?>

2014年4月28日 星期一

yii framework - 如何多個Controller共用一個filter?

我們都知道Yii可以跨Controller使用function (ex: UserController::ShowHallo), 但是很多時候我們會希望一個過濾器(filter)能讓許多的Controller共用.

因為我們不用再重複寫一樣的cord, 是吧! 正如《Clean Code》的Bob大叔說的:不要重複自己DRY (Don't Repeat Yourself)

步驟:
1. 在protected/下建立一個資料夾 (ex: filers)

2. 在protected/filers下建立一個檔案 (ex: ShowHalloFilter.php)

3. 幫你的filter寫點東西

4. 在要使用的Controller裡的filers用array ('application.filters.ShowHalloFilter + aboutMe, fuckYou')的方式來使用我們建立的filter


2014年4月21日 星期一

yii framework - 為什麼Facebook登出會轉到home.php

問題:

為什麼在登出fb的時候沒有轉到自己所指定的頁面, 而是跑到Facebook的home.php?


可能的原因:

1. 你的登出後要轉到(next)的網址錯誤, 例如:

$params = array( 'next' => 'http://www.test.com/index.html' );
$logout_url = Yii::app()->facebook->getLogoutUrl($params);

如果你是index.php, 而不是index.html的話就會發生這個現象!

2. 你沒有拿到正確的access token

其實檢查方式很簡單, 你可以把上面的$logout_url echo出來, 就可以知道到底getLogoutUrl()這個函式到底都產生了什麼鬼.

2014年3月22日 星期六

yii framework - 如何使用Facebook登入(Facebook PHP SDK)


本篇是使用Facebook API PHP SDK, 如果是要用JavaScript SDK的人可以直接搜尋"JavaScript SDK facebook"就有非常多資訊了! 或是參考這篇:facebook程式設計-JavaScript SDK


許多開發者都會經歷一個階段, 就是讓使用者可以用FB登入->註冊
到底在yii framework要如何實現呢? 在這Joker就分享一下自己的開發過程及心得:

首先我先講一下, 網路上很多都使用JavaScript SDK, 這讓我很困惑. 困惑的點是我到底該使用哪個呢? PHP or JavaScript SDK?

其實兩邊的寫法都不難, 只是一個寫在客戶端、一個是在伺服端罷了!
後來我想到有關於資訊安全上的問題, 所以試著去找一下, 有沒有相關的資料來印證我對於JavaScript安全性的顧慮, 後來我找到這篇, 大家可以看一下:網站利用 Facebook 帳號登入 (使用 OAuth)

2014年2月28日 星期五

yii framework - Warning: Cannot modify header information要怎麼解決?

你如果看到這問題表示你一定是在Cookie的地方出問題了!

簡單的說, 就是你在寫入Cookie前有東西輸出了(ex: echo xxx or print_r (xxx))

我自己本身是前面有東西echo了, 所以移除掉就好了!


裡面有人提到修改php.ini, 將output_buffering 設為 On

不過這要看你是否有權限可以進到裡面修改, 這就要看你的主機商了!


2014年2月19日 星期三

yii framework - 抓出全部資料後如何取其中一個欄位的資料?

舉個例子:

假設我們用find抓符合條件的第一筆資料的話, 如下

$criteria=new CDbCriteria;
$criteria>select='id,pw,name,about';
$criteria->compare('loginId',$id);
$detail=RoomType::model()->find($criteria);

我們要如何取其中的id呢?

答案就是:

$detail->id

沒錯! 看到這相信大家就知道要用物件導向的方式來取得了吧!


那如果是用findAll的話呢?