12/08/2018, 12:29

Lập trình module đầu tiên cho PHPFOX===

Trong bài viết trước, chúng ta đã biết qua về các Platform mạng xã hội. Trong bài lần này, chúng ta sẽ đi sâu hơn về Phpfox . Phpfox có một điểm mạnh đó là ngoài những module cơ bản (Forum, Blog, Music, Video, News Feed,...) thì nó cung cấp khả năng có thể cho lập trình viên viết ra những Module ...

Trong bài viết trước, chúng ta đã biết qua về các Platform mạng xã hội. Trong bài lần này, chúng ta sẽ đi sâu hơn về Phpfox. Phpfox có một điểm mạnh đó là ngoài những module cơ bản (Forum, Blog, Music, Video, News Feed,...) thì nó cung cấp khả năng có thể cho lập trình viên viết ra những Module khác để chạy cùng, Module này có thể là 1 chức năng riêng biệt hoặc có thể bổ sung, hỗ trợ các module khác đã có trong trang Phpfox. Để viết được 1 module cho 1 trang Phpfox thì các bạn có thể tham khảo tài liệu. Trước khi đi vào viết 1 Module chúng ta sẽ tìm hiểu cấu trúc của 1 module trong Phpfox. Tất cả module của Phpfox đều được chứa trong folder module. Cấu trúc cơ bản của 1 Module của Phpfox bao gồm:

/include/
/include/component/
/include/component/ajax/
/include/component/block/
/include/component/controller/
/include/plugin/
/include/service/
/static/
/static/css/default/default/
/static/image/
/static/jscript/
/template/
/template/default/
/template/default/block/
/template/default/controller/

Trong đó include phần xử lý code Php, static chứa các file javascript, css và template là lớp view. Trong bài này chúng ta sẽ làm 1 đề bài về quản trị danh mục.

Tạo 1 module mới:

  • Đầu tiên chúng ta tạo 1 prouct mới có tên là "Sample Video" bằng cách vào Admin CP > Extensions > Create new product như hình dưới: 1.png Tại trang tạo mới Product thì tạo mới 1 product với các thông số sau
Product Id: sample_video
Title: Sample
Description: This is sample toturial
Version: 1.0

1.png

  • Sau đó vào Admin CP > Extensions > Create New Module và khi thêm mới Module mới điền các thông tin như hình sau: 1.pngLưu ý: Lúc tạo module thì quan trọng nhất phần id, vì khi tạo 1 folder mới trong module của Phpfox thì cần phải trùng với module id này.

Tạo database###

Trong yêu cầu bài ta cần tạo 2 bảng category và video. Để tạo 1 database khi cài đặt 1 module mới trong Phpfox có nhiều cách nhưng ở đây ta sẽ làm 1 cách đơn giản là thêm trực tiếp khi sửa product bằng cách vào Admin Cp > Extensions > Manage Products sau đó tìm đến Sample Video mà ta vừa tạo sau đó sửa đổi chúng trong phần Add New Install/Uninstall Code:

Install

$this->database()->query('CREATE TABLE IF NOT EXISTS `' . Phpfox::getT('sample_category') . '` `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`ordering` int(11) NOT NULL,
PRIMARY KEY (`id`),
);

_ Uninstall _

$this->database()->query('DROP TABLE `' . Phpfox::getT('sample_category') . '`');

Tạo cấu trúc module###

Ta sẽ tạo 1 folder như sau trong folder module

sample/include/
sample/include/component/
sample/include/component/ajax/
sample/include/component/block/
sample/include/component/controller/
sample/include/service/
sample/static/
sample/static/css/default/default/
sample/static/jscript/
sample/template/
sample/template/default/
sample/template/default/block/
sample/template/default/controller/

Làm việc với bảng sample_category###

Ta tạo 2 file trong sample/inlcude/service/category/ (Để gọi service trong module thì cần tạo file trong folder include/service và đặt tên class theo quy định của Phpfox đó là <tên model>_component_service_<path + tên file>. 2 file này sẽ bao gồm file process.class.php với mục đích thêm, sửa, xóa, sắp xếp trong database, và file category.class.php với mục đích gọi danh sách các bản ghi trong database.

File include/service/category/process.class.php####

<?php
/**
 * Created by Huy Nguyen.
 * User: Huy Nguyen
 * Date: 25/10/2015
 * Time: 23:27 CH
 */
<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 25/10/2015
 * Time: 23:27 CH
 */
class Sample_Service_Category_Process extends Phpfox_Service
{
    public function __construct()
    {
        $this->_sTable = Phpfox::getT('sample_category');
    }

    public function add($aVals)
    {
        $oInput = Phpfox::getLib('parse.input');
        $aData = array(
            'name' => $oInput->clean($aVals['name'], 255),
            'ordering' => 0
        );
        return $this->database()->insert($this->_sTable, $aData);
    }

    public function update($aVals, $iId)
    {
        $oInput = Phpfox::getLib('parse.input');
        $aData = array(
            'name' => $oInput->clean($aVals['name'], 255)
        );
        return $this->database()->update($this->_sTable, $aData, 'id = ' . $iId);
    }

    public function delete($iId)
    {
        return $this->database()->delete($this->_sTable, 'id = ' . $iId);
    }

    public function updateOrder($aVals)
    {
        foreach ($aVals as $iId => $iOrder) {
            $this->database()->update($this->_sTable, array('ordering' => $iOrder), 'id = ' . (int)$iId);
        }
    }
}

File include/service/category/category.class.php####

<?php
/**
 * Created by Huy Nguyen.
 * User: Huy Nguyen
 * Date: 26/10/2015
 * Time: 21:05 CH
 */
class Sample_Service_Category_Category extends Phpfox_Service
{
    public function __construct()
    {
        $this->_sTable = Phpfox::getT('sample_category');
    }

    public function get()
    {
        $aCategories = $this->database()
            ->select('*')
            ->from($this->_sTable)
            ->order('ordering')
            ->execute('getRows');
        return $aCategories;
    }

    public function getForEdit($iId)
    {
        $aCategory = $this->database()
            ->select('*')
            ->from($this->_sTable)
            ->where('id = ' . $iId)
            ->execute('getRow');
        return $aCategory;
    }
}

Lớp Controller###

Ở đây ta cần xư lý các chức năng: Hiển thị danh sách, sắp xếp, xóa, thêm mới, sửa thì các chức năng này làm trong 2 controller đó là: index (Danh sách, sắp xếp, xóa) và add (thêm mới và xóa)

File include/component/admincp/category/index.class.php

Trong file này sẽ kiểm tra nếu có truyền đến controller biến delete là id của category muốn xóa thì sẽ xóa category đó. Nếu truyền đến là 1 mảng các id và ordering thì sẽ cập nhật lại sắp xếp của category.

<?php
/**
 * Created by Huy Nguyen.
 * User: Huy Nguyen
 * Date: 26/10/2015
 * Time: 21:20 CH
 */
class Sample_Component_Controller_Admincp_Category_Category extends Phpfox_Component
{
    public function process()
    {
        if ($iDelete = $this->request()->getInt('delete')) {
            Phpfox::getService('sample.category.process')->delete($iDelete);
            $this->url()->send('admincp.category', null, 'Delete success');
        }

        if ($aOrder = $this->request()->getArray('order'))
        {
            if (Phpfox::getService('sample.category.process')->updateOrder($aOrder))
            {
                $this->url()->send('sample.category', null, 'Order update success');
            }
        }
        $aCategories = Phpfox::getService('sample.category')->get();
        $this->template()
            ->setHeader(array(
                    'jquery/ui.js' => 'static_script',
                    'admin.js' => 'module_sample',
                    '<script type="text/javascript">$Behavior.loadSampleCategoryUrl = function() { $Core.sample.url(' . $this->url()->makeUrl('admincp.sample.category') . '); }</script>'
                )
            )
            ->assign(array(
                'aCategories' => $aCategories
            ));
    }
}

Trong file controller này ta cần sử dụng đến file javascript là admin.js của module Sample và ui.js của Phpfox

File include/component/controller/admincp/category/add.class.php

Controller này sẽ thực hiện việc thêm mới và sửa category. Để nhận biết được đang sửa hay thêm mới thì sẽ kiểm tra xem lúc gửi dữ liệu có biến id hay không, nếu có thì sang hàm update còn không thì là add

<?php
/**
 * Created by Huy Nguyen.
 * User: Huy Nguyen
 * Date: 26/10/2015
 * Time: 22:17 CH
 */
class Sample_Component_Controller_Admincp_Category_Index extends Phpfox_Component
{
    public function process()
    {
        if ($aVals = $this->request()->getArray('val')) {
            if ($iId = $this->request()->getInt('id')) {
                Phpfox::getService('sample.category.process')->update($aVals, $iId);
            } else {
                Phpfox::getService('sample.category.process')->add($aVals);
            }
            $this->url()->send('admincp.sample.cateogry', null, 'Success');
        }
        if ($iId = $this->request()->getInt('id')) {
            $aCategory = Phpfox::getService('sample.category')->getForEdit($iId);
            $this->template()
                ->assign('aCategory', $aCategory);
        }
    }
}

Lớp View###

Tương ứng với 2 controller trên ta sẽ có 2 view cho từng controller tương ứng là 2 file index.html.php và add.html.php.

File template/default/controller/admincp/category/index.html.php####

<div id="js_menu_drop_down" style="display:none;">
    <div class="link_menu dropContent" style="display:block;">
        <ul>
            <li><a href="#" onclick="return $Core.sample.action(this, 'edit');">Edit</a></li>
            <li><a href="#" onclick="return $Core.sample.action(this, 'delete');">Delete</a></li>
        </ul>
    </div>
</div>
<div class="table_header">
    {phrase var='event.categories'}
</div>
<form method="post" action="{url link='admincp.sample.category'}">
    <div class="table">
        <div class="sortable">
            <ul class="ui-sortable">
                {foreach from=$aCategories item=aCategory}
                    <li>
                        {img theme='misc/draggable.png'}
                        <input type="hidden" name="order[{$aCategory.id}]" value="{$aCategory.ordering}" class="js_mp_order">
                        <a href="#?id=1" class="js_drop_down">{$aCategory.name}</a>
                    </li>
                {endforeach}
            </ul>
        </div>
    </div>
    <div class="table_clear">
        <input type="submit" value="Update order" class="button" />
    </div>
</form>

File template/default/controller/admincp/category/add.html.php

<?php

defined('PHPFOX') or exit('NO DICE!');

?>
<form method="post" action="{url link='current'}">
    <div class="table_header">
        Category detail
    </div>
    <div class="table">
        <div class="table_left">
            Name
        </div>
        <div class="table_right">
            <input type="text" name="val[name]" size="30" maxlength="100" value="{value type='input' id='name'}" />
        </div>
        <div class="clear"></div>
    </div>
    <div class="table_clear">
        <input type="submit" value="Submit" class="button" />
    </div>
</form>

Như đã nói ở phần Controller thì có load 1 file javascript là admin.js từ module Sample. Vậy file admin.js sẽ như sau:

File static/jscript/admin.js

$Core.sample =
{
    sUrl: ',

    url: function(sUrl)
    {
        this.sUrl = sUrl;
    },

    action: function(oObj, sAction)
    {
        aParams = $.getParams(oObj.href);

        $('.dropContent').hide();

        switch (sAction)
        {
            case 'edit':
                window.location.href = this.sUrl + 'add/id_' + aParams['id'] + '/';
                break;
            case 'delete':
                if (confirm(oTranslations['event.are_you_sure_this_will_delete_all_events_that_belong_to_this_category_and_cannot_be_undone']))
                {
                    window.location.href = this.sUrl + 'delete_' + aParams['id'] + '/';
                }
                break;
            default:

                break;
        }

        return false;
    }
}

$(function()
{
    $('.sortable ul').sortable({
            axis: 'y',
            update: function(element, ui)
            {
                var iCnt = 0;
                $('.js_mp_order').each(function()
                {
                    iCnt++;
                    this.value = iCnt;
                });
            },
            opacity: 0.4
        }
    );

    $('.js_drop_down').click(function()
    {
        eleOffset = $(this).offset();

        aParams = $.getParams(this.href);

        $('#js_cache_menu').remove();

        $('body').prepend('<div id="js_cache_menu" style="position:absolute; left:' + eleOffset.left + 'px; top:' + (eleOffset.top + 15) + 'px; z-index:100; background:red;">' + $('#js_menu_drop_down').html() + '</div>');

        $('#js_cache_menu .link_menu li a').each(function()
        {
            this.href = '#?id=' + aParams['id'];
        });

        $('.dropContent').show();

        $('.dropContent').mouseover(function()
        {
            $('.dropContent').show();

            return false;
        });

        $('.dropContent').mouseout(function()
        {
            $('.dropContent').hide();
            $('.sJsDropMenu').removeClass('is_already_open');
        });

        return false;
    });

});
/**
 * Created by Administrator on 26/10/2015.
 */

Nhận xét###

Vậy qua việc áp dụng tạo 1 module quản trị danh mục của Phpfox đã nhận thấy trong việc lập trình Phpfox có những chuẩn và cách sử dụng khác với Php thuần.

  1. Như tên của Class phải đảm bảo theo quy chuẩn riêng như:
  • Với controller thì là: <Tên module>Component_Controller<Đường dẫn>_<Tên File>
  • Với Service thì là <Tên Module>Serive<Đường dẫn>_<Tên file>
  1. Khi load file js thì gọi trong Controller theo cách setHeader('<tên file>.js', <tên module>). Với tên module có thể là static là load từ Phpfox.
  2. Về javascript thì bình thường ta sẽ dùng hàm $(document).ready() để sử dụng jquery sau khi load trang xong, nhưng ở Phpfox sử dụng 1 hàm có sẵn là Behavior.<Tên ham> = function{}

Hi vọng qua bài này sẽ giúp các bạn hiểu và tự viết cho mình những module cho Phpfox và kiếm tiền từ những Module này.

0