新北市教育局程式應用研發社群工作坊:PHP 框架 CodeIgniter 3(1060913-0927)

日期:106年9月13日 – 9月27日

時間:週三下午

地點:新北市教研中心

公文與計畫:

課程主題:PHP 框架 CodeIgniter 3

講師:樹林國小黃保太老師

開發環境與工具:

學習資源】【九月13日】【九月20日九月27日

課後補充教材:

  • CodeIgniter3 Linux開發環境0001 ~ 0003
  • CodeIgniter3 上傳XML、解析、寫入資料庫01 ~ 05

講義:1060927_PHP_Framework_Codeigniter(三)

課程網站資料下載:

教學相關網站:

  • NTPC OpenID:http://openid.ntpc.edu.tw
    • 欄位規格說明
    • 範例程式下載
    • 注意事項:
      openid 的範例中,openid.php 這支library裡在 #280, #293, #309 這三行中,判斷 ssl 的 CN_match 這個設定已不再使用(deprecated)。apache2 目前似乎仍可正常使用,不過,放在 nginx 的話,會噴錯誤,將 ‘CN_match’ 自行改成 ‘peer_name’ 可正常執行。

教學內容:

application\views\auth\form.php

<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
    <ul class="nav navbar-nav">
        <?php foreach( $menu as $key => $value): ?>
            <li>
                <a href="<?=base_url()?><?=$value?>"><?=$key?></a>
            </li>
        <?php endforeach; ?>
    </ul>
</div>
...

<!-- Post Content -->
...

<ul>
    <form action="/ntpc_openid_login" method="post">
        <input
                class="btn-info btn-lg"
                type="submit"
                value="新北市OpenID登入"
        >
    </form>
</ul>

application\views\template\main.php

<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
    <ul class="nav navbar-nav">
        <?php foreach( $menu as $key => $value): ?>
        <li>
            <a href="<?=base_url()?><?=$value?>"><?=$key?></a>
        </li>
        <?php endforeach; ?>

        <?php if($this->session->is_logined ) :?>
        <li>
            <a href="user/" title="<?=$cname?>"><?=$account?></a>
        </li>
        <li>
            <a href="<?=base_url()?>auth/logout" title="登出">登出</a>
        </li>
        <?php endif; ?>

    </ul>
</div>
...

<!-- Post Content -->
<ul>
    <?php if( isset($posts) ) : ?>
    <?php foreach( $posts->result() as $row ): ?>
    <li class="lead">
        <a href="/post/post_desc/<?=$row->id?>"><?=$row->post_title?></a>
        <?php if( $is_logined and $level >=100 ): ?>
        <a class="btn-danger" href="/post/delete/<?=$row->id?>">刪</a>
        <?php endif; ?>
    </li>
    <?php endforeach; ?>
    <?php endif; ?>
</ul>

application\helpers\utility_helper.php

function get_default_data(){
    $data["title"] = '語文競賽報名系統';

    $data["menu"] = array(
        "說明"     => "welcome",
        //"報名"     => "enroll",
        "清單"     => "post/show",
        "登入"     => "auth/form"
        //"個人資訊"  => "userinfo",
        //"admin"    => "系統管理",
    );
    return $data;
}

application\controllers\Auth.php

class Auth extends CI_Controller
{
    public function index()
    {
        $data = get_default_data();
        $this->load->library('form_validation');
        $this->load->view('auth/form', $data);
    }

    public function form()
    {
        $data = get_default_data();
        $this->load->library('form_validation');
        $this->load->view( "auth/form", $data);
    }

    public function form_validation()
    {
        $data = get_default_data();
        $this->load->helper("url");
        $this->load->library(
            array('form_validation')
        );

        $this->form_validation->set_rules('username', '帳號', 'required');
        $this->form_validation->set_rules('password', '密碼', 'required');

        if( $this->form_validation->run() == false){
            $this->load->view("auth/form", $data);
        }else{
            $username = $this->input->post("username");
            $password = $this->input->post("password");
        }
    }

    public function do_openid_login()
    {
        require_once APPPATH . '../assets/openid/openid.php';

        $openid = new LightOpenID('localhost');
        if (!$openid->mode) {
            if ($_SERVER['REQUEST_METHOD'] == 'POST') {
                $openid->identity = 'http://openid.ntpc.edu.tw/';
                $openid->required = array(
                    'namePerson/friendly',
                    'contact/email',
                    'namePerson',
                    'birthDate',
                    'person/gender',
                    'contact/postalCode/home',
                    'contact/country/home',
                    'pref/language',
                    'pref/timezone'
                );
                header('Location: ' . $openid->authUrl());
            }else{

            }
        }
    }

    public function get_openid_data()
    {
        require_once APPPATH . '../assets/openid/openid.php';

        $openid = new LightOpenID('localhost');

        $this->load->helper('url');

        if (!$openid->mode){
            redirect(base_url() . 'auth/form');
        }elseif( $openid->mode == 'cancel') {
            print "使用者取消";

        }else{
            if ($openid->validate()) {
                $attr = $openid->getAttributes();

                $tmp =explode('/', $openid->identity );
                $userinfo["account"] = end( $tmp );
                $userinfo["cname"] = $attr['namePerson'];
                $userinfo["birth"] = $attr['birthDate'];
                $userinfo["school_name"] = $attr['contact/country/home'];
                $userinfo["email"] = $attr['contact/email'];

                $this->session->userinfo = $userinfo;
                $this->session->is_logined = true;
                $this->session->account = $userinfo['account'];

                $titles = array();
                $groups = array();

                foreach (json_decode($attr['pref/timezone']) as $item) {
                    $titles[] = $item->title;
                    $groups[] = implode('、', $item->groups);
                }

                $this->session->titles = $titles;
                $this->session->groups = $groups;

                if( in_array("資訊組長", $groups)){
                    $this->session->level = 999;
                }elseif( in_array("導師", $groups)){
                    $this->session->level = 10;
                }

                /*dump( $userinfo );
                dump( $this->session );*/

                redirect ('post/show');
            }
        }
    }

    public function logout()
    {
        $this->session->sess_destroy();
        redirect( base_url() . "post/show");
    }
}

application\controllers\Post.php

public function show()
{
    $data = get_default_data();

    $data['account'] = $this->session->account;
    $data['is_logined'] = $this->session->is_logined;
    $data['level'] = $this->session->level;
    $data['cname'] = $this->session->userinfo['cname'];

    $query = null;
    if( ! empty($this->uri->segment(3)) ){
        $query = $this->p->post($this->uri->segment(3));
    }else{
        $query = $this->p->posts();
    }
    $data["posts"] = $query;
    $this->load->view('template/main', $data);
}
...

public function delete()
{
    $this->load->helper('url');

    if( empty( $this->uri->segment(3)) ){
        redirect(base_url() . 'post/show');
    }else{
        $this->p->delete( $this->uri->segment(3) );
        redirect(base_url() . 'post/show');
    }
}

application\config\autoload.php

$autoload['libraries'] = array(
    'database', 'session'
);
...

$autoload['helper'] = array(
    'url', 'form', 'utility'
);

application\config\config.php

  • 在網站根目錄要建一個 sessions 資料夾
$config['sess_save_path'] = APPPATH . '../sessions';

application\config\routes.php

$route['default_controller'] = 'auth';
...

$route['ntpc_openid_login']['post'] = 'auth/do_openid_login';
$route['ntpc_openid_login']['get'] = 'auth/get_openid_data';

assets\openid\index.php

try {
    $openid = new LightOpenID('localhost');
    if (!$openid->mode) {
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $openid->identity = 'http://openid.ntpc.edu.tw/';
            $openid->required = array(
                'namePerson/friendly',
                'contact/email',
                'namePerson',
                'birthDate',
                'person/gender',
                'contact/postalCode/home',
                'contact/country/home',
                'pref/language',
                'pref/timezone'
            );
            header('Location: ' . $openid->authUrl());
        }
...

    } else {
        if ($openid->validate()) {
            $attr = $openid->getAttributes();

            $tmp =explode('/', $openid->identity);
            $myid = end( $tmp );

            echo '<table border="1" cellspacing="0" cellpadding="10">';
            echo '<tr><td>帳號</td><td>' . $myid . '</td></tr>';
...

        }
    }
} catch (ErrorException $e) {
    echo $e->getMessage();
}

學習資源】【九月13日九月20日九月27日

講義:1060920_PHP_Framework_Codeigniter(二)

教學影片:

20170920-CodeIgniter3 MVC開發

 

PHP Composer

範例:蘋果日報 RSS 剖析

  • composer self-update
  • cd CodeIgniter-3.1.5
  • composer require dg/rss-php

CodeIgniter 3 文件:輔助函式

教學內容:

application\config\autoload.php

/*
| -------------------------------------------------------------------
|  Auto-load Helper Files
| -------------------------------------------------------------------
| Prototype:
|
|  $autoload['helper'] = array('url', 'file');
*/
$autoload['helper'] = array(
    'utility_helper'
);

application\config\config.php

$config['base_url'] = 'http://localhost';
...

//$config['language']   = 'english';
$config['language']    = 'zh-tw';
...

//$config['composer_autoload'] = FALSE;
$config['composer_autoload'] = APPPATH . '../vendor/autoload.php';

application\helpers\utility_helper.php

function dump($obj){
    print "<pre>";
    var_dump($obj);
    print "</pre>";
}

function echobr($str){
    print $str . '<br />';
}

function get_default_data(){
    $data["title"] = '語文競賽報名系統';
    $data["menu"] = array(
        "about"     => "說明",
        "enroll"     => "報名",
        "list"     => "清單",
        "userinfo"     => "個人資訊",
        "admin"     => "系統管理",
    );

    return $data;
}

application\models\Post_model.php

class Post_model extends CI_Model
{
    public function __construct()
    {
        parent::__construct();
        $this->load->database();
    }

    public function posts()
    {
        $this->db->select("*");
        //$this->db->where('id', 5);
        //$this->db->order_by('created_time', "DESC");
        $this->db->order_by('id', "DESC");
        $query = $this->db->get('post');

        return $query;
    }

    public function post($post_id = null)
    {
        if( $post_id == null ) return null;

        $this->db->select("*");
        $this->db->where('id', $post_id);
        $query = $this->db->get('post');
        return $query;
    }

    public function add($title=null, $content=null)
    {
        $data = array(
            'post_title' => $title,
            'post_content' => $content
        );

        $this->db->insert( 'post', $data );
        
    }

    public function delete($post_id = null)
    {
        if( $post_id == null ) return null;

        $data = array(
            'id' => $post_id
        );
        $this->db->delete('post', $data);
    }

    public function update()
    {
       
    }
}

application\controllers\Test.php

class Test extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->helper('utility_helper');
    }

    public function rss()
    {
        $this->load->helper('utility_helper');
        $this->load->model('post_model');

        date_default_timezone_set("asia/taipei");

        $rss_url = 'http://www.appledaily.com.tw/rss/newcreate/kind/rnews/type/new';
        $rss = Feed::loadRss($rss_url);

        echo 'Title: ', $rss->title . '<br />';
        echo 'Description: ', $rss->description  . '<br />';
        echo 'Link: ', $rss->link . '<br />';

        $num = 0;
        foreach ($rss->item as $item) {
            //dump( $item );
            /*echo 'Title: ', $item->title . '<br />';
            echo 'Link: ', $item->link . '<br />';
            echo 'Timestamp: ', $item->timestamp . '<br />';
            echo 'Description ', $item->description . '<br />';
            echo 'HTML encoded content: ', $item->{'content:encoded'} . '<br />';*/
            $this->post_model->add($item->title, $item->description );
            $num++;
        }

        echobr('post add ' . $num . ' records.');

        /*$data = array(
            'name' => 'bob',
            'age' => 40,
            'school_name' => 'Shulin Primary School'
        );

        dump($data);*/
    }

    public function test_model()
    {
        $this->load->model('post_model');

        //dump( $this->post_model->posts()  );

        $this->post_model->add('aaaaaaa', 'bbbbbbbbbbbbbbbbbbbb');
        print "insert ok";
    }
}

application\controllers\Auth.php

class Auth extends CI_Controller
{
    public function index()
    {
        $data = get_default_data();
        $this->load->view('template/main', $data);
    }

    public function form()
    {
        $data = get_default_data();
        $this->load->library('form_validation');
        $this->load->view( "auth/form", $data);
    }

    public function form_validation()
    {
        $data = get_default_data();
        $this->load->helper("url");
        $this->load->library(
            array('form_validation')
        );

        $this->form_validation->set_rules('username', '帳號', 'required');
        $this->form_validation->set_rules('password', '密碼', 'required');

        if( $this->form_validation->run() == false){
            $this->load->view("auth/form", $data);
        }else{
            $username = $this->input->post("username");
            $password = $this->input->post("password");
        }
    }
}

application\controllers\Post.php

class Post extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->model('post_model', 'p');
    }
...
...
    public function delete()
    {
        $this->load->helper('url');

        if( empty( $this->uri->segment(3)) ){
            //redirect('post/show');
            //echobr( base_url() );
            redirect(base_url() . 'post/show');
            //$this->show();
        }else{
            $this->p->delete( $this->uri->segment(3) );
            redirect(base_url() . 'post/show');
            //$this->show();
        }
    }
}

複製 system\language\english -> application\language\zh-tw

application\language\zh-tw\form_validation_lang.php

$lang['form_validation_required']      = '【{field}】 這個欄位必須輸入資料';

application\views\auth\form.php

<!-- Post Content -->
<ul>
    <form action="/auth/form_validation" method="post">
        帳號: <input type="text" name="username" id="username">
        <span class="text-danger"><?=form_error("username")?></span>
        密碼: <input type="password" name="password" id="password">
        <span class="text-danger"><?=form_error("password")?></span>
        <input type="submit" value="登入">
    </form>
</ul>

學習資源九月13日九月20日】【九月27日

課程講義:1060913_PHP_Framework_Codeigniter

教學影片:

保太教學錄影:

PHP Codeigniter Step By Step Tutorials for Beginners 2017

教學內容:

application\controllers\Welcome.php

class Welcome extends CI_Controller
{
    public function index()
    {       
        $this->load->view('welcome_message');
    }   
    
    public function hello(){
        print "<h1>";
        print "大家好,歡迎來到 CodeIgniter 3!";
        print "</h1>";
    }
    
    public function bye(){
        $data["title"] = '語文競賽報名系統';
        $data["menu"] = array(
            "about" => "說明",
            "enroll" => "報名",
            "list" => "清單",
            "userinfo" => "個人資訊",
            "admin" => "系統管理",
        );
        $this->load->view('template/main', $data);
    } 
}

application\controllers\Auth.php

class Auth extends CI_Controller
{
    public function index(){
        $data["title"] = '語文競賽報名系統';
        $data["menu"] = array(
            "about" => "說明",
            "enroll" => "報名",
            "list" => "清單",
            "userinfo" => "個人資訊",
            "admin" => "系統管理",
        );

        $this->load->database();

        //$query = $this->db->query("select * from post");
        $this->db->select('id, post_title, post_content, created_time, updated_time');
        $this->db->from('post');
        if( ! empty($this->uri->segment(3)) ){
            $this->db->where('id', $this->uri->segment(3));
        }

        $query = $this->db->get();
        $data["posts"] = $query;

        $this->load->view('template/main', $data);
    }
}

application\controllers\Post.php

class Post extends CI_Controller
{
    public function show(){

        $this->load->database();

        $data["title"] = '語文競賽報名系統';
        $data["menu"] = array(
            "about" => "說明",
            "enroll" => "報名",
            "list" => "清單",
            "userinfo" => "個人資訊",
            "admin" => "系統管理",
        );

        $this->db->select('id, post_title, post_content, created_time, updated_time');
        $this->db->from('post');
        if( ! empty($this->uri->segment(3)) ){
            $this->db->where('id', $this->uri->segment(3));
        }

        $query = $this->db->get();
        $data["posts"] = $query;

        $this->load->view('template/header', $data);
        $this->load->view('template/menu', $data);
        $this->load->view('template/title_block', $data);
        $this->load->view('template/content', $data);
        $this->load->view('template/footer', $data);
    }

    public function post_desc(){

        $this->load->database();

        if( empty($this->uri->segment(3)) ) redirect("/post/show");

        $data["title"] = '語文競賽報名系統';
        $data["menu"] = array(
            "about"     => "說明",
            "enroll"     => "報名",
            "list"     => "清單",
            "userinfo"     => "個人資訊",
            "admin"     => "系統管理",
        );

        $this->db->select('id, post_title, post_content, created_time, updated_time');
        $this->db->from('post');
        if( ! empty( $this->uri->segment(3)) ){
            $this->db->where('id', $this->uri->segment(3));
        }

        $query = $this->db->get();
        $data["posts"] = $query;

        $this->load->view('template/post_desc', $data);
    }
}

.htaccess

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]

application\config\database.php

$db['default'] = array(
   'dsn'  => '',
   'hostname' => 'localhost',
   'username' => 'blogadm',
   'password' => '!2345678',
   'database' => 'blog',
   'dbdriver' => 'mysqli',
   'dbprefix' => '',
   'pconnect' => FALSE,
   'db_debug' => (ENVIRONMENT !== 'production'),
   'cache_on' => FALSE,
   'cachedir' => '',
   'char_set' => 'utf8',
   'dbcollat' => 'utf8_general_ci',
   'swap_pre' => '',
   'encrypt' => FALSE,
   'compress' => FALSE,
   'stricton' => FALSE,
   'failover' => array(),
   'save_queries' => TRUE
);

application\views\template\main.php

<head>
...
<!-- Bootstrap Core CSS -->
<link href="/assets/css/bootstrap.min.css" rel="stylesheet">

<!-- Custom CSS -->
<link href="/assets/css/blog-post.css" rel="stylesheet">
...
</head>
<body>
...
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
    <ul class="nav navbar-nav">
        <?php foreach( $menu as $key => $value): ?>
        <li>
            <a href="#"><?=$value?></a>
        </li>
        <?php endforeach; ?>
    </ul>
</div>
...
<!-- Title -->
<h1><?=$title?></h1>
...

<!-- Post Content -->
<ul>
    <?php foreach( $posts->result() as $row ): ?>
    <li class="lead">
        <a href="/post/post_desc/<?=$row->id?>"><?=$row->post_title?></a>
        <a href="/post/delete/<?=$row->id?>">刪</a>
    </li>
    <?php endforeach; ?>
</ul>

...
<!-- jQuery -->
<script src="/assets/js/jquery.js"></script>

<!-- Bootstrap Core JavaScript -->
<script src="/assets/js/bootstrap.min.js"></script>
</body>

學習資源九月13日】【九月20日】【九月27日

學習資源: