Cài đặt Node.JS trên Ubuntu

Cài đặt Node.JS trên Ubuntu

Cách dưới đây cũng tương tự với các distro base trên Ubuntu: Linux Mint, Elementary OS...

Theo thông cáo từ trang package của Ubuntu, nodejs đã sớm có mặt từ biên bản 12.04 LTS, tuy nhiên từ 12.04 đến 13.04 nó đi kèm với phiên bản cũ 0.6.x của node. Ubuntu 13.10 có sẵn nodejs 0.10.15 và Ubuntu 14.04 LTS là 0.10.25.

Người dùng Ubuntu 13.10, 14.04 LTS trở lên có thể cài qua dòng lệnh đơn giản sau:

sudo apt-get install nodejs

Với người sử dụng Ubuntu 12.04 LTS đến Ubuntu 13.04 bạn cần sử dụng ppa bên ngoài để cập nhật phiên bản mới nhất của node.js.

Mình vẫn khuyến khích các bạn sử dụng kho bên ngoài, điều này đảm bảo bạn luôn có phiên bản node.js mới nhất trong máy.

sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs

Cài đặt xong bạn gõ nodejs -v mà ra thông tin phiên bản, tức là đã thành công!

Screenshot from 2014-05-15 10:27:34.png

Gỡ cài đặt

Gỡ cài đặt nodejs nếu bạn muốn:

sudo apt-get remove nodejs npm

Bài viết này có thể được coi là một phần được dịch lại từ trang wiki của nodejs. Đối với các distro khác của Linux, hoặc các OS khác vui lòng tham khảo thêm tại địa chỉ: https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager

Bắt link download video youtube với PHP

Bắt link download video youtube với PHP

Giới thiệu

Vừa rồi bên vn-zoom có một bác đề cập đến vấn đề lấy liên kết download video như IDM hay các addons trên trình duyệt. Vì vậy mình đã viết một đoạn mã nhỏ và đơn giản nhằm mục đích trên.

Vì là nhỏ và đơn giản nên đoạn mã trong bài viết này có thể còn nhiều lỗi phát sinh khi đầu vào không hợp lệ ^^.

Source

<?php

/**
 * Parses the youtube video ID and returns download links.
 *
 * @author Nguyen Van Anh <anhskohbo@gmail.com>
 * @param  string $videoId
 * @return array
 */
function youtube_dl($videoId)
{
    $youtubeUrl = 'http://www.youtube.com/watch?v='.$videoId;

    if ($contentHtml = file_get_contents($youtubeUrl)) {

        if (preg_match('/;ytplayer\.config\s*=\s*({.*?});/', $contentHtml, $matches)) {

            $jsonData  = json_decode($matches[1], true);
            $streamMap = $jsonData['args']['url_encoded_fmt_stream_map'];
            $videoUrls = array();

            foreach (explode(',', $streamMap) as $url)
            {
                $url = str_replace('\u0026', '&', $url);
                $url = urldecode($url);

                parse_str($url, $data);
                $dataURL = $data['url'];
                unset($data['url']);

                $videoUrls[] = array(
                    'itag'    => $data['itag'],
                    'quality' => $data['quality'],
                    'url'     => $dataURL.'&'.urldecode(http_build_query($data))
                );
            }

            return $videoUrls;
        }
    }

    return array();
}

Sử dụng

<?php

$downloads = youtube_dl('B5kV-CIyMOQ');
var_dump($downloads);

youtube_dl sẽ trả về một danh sách các liên kết download có sẵn cho video.

Nếu bạn muốn lấy thông tin về định dạng video, kiểu video ... (kiểu như Mp4 - 720p) youtube xác định nó qua itag. Một thông tin toàn diện về itag có tại địa chỉ: http://users.ohiohills.com/fmacall/YTCRACK.TXT

Tổng kết

Hiện tại mình đang bận nên chưa có thời gian viết chi tiết cách thức hoạt động là lấy liên kết. Chỉ chia sẻ code lên đây ^^.

Mình sẽ sớm viết 1 thư viện PHP 5.3+ hoàn chỉnh download video từ youtube hay các trang khác.

Giới thiệu Presenter trong Laravel

Giới thiệu Presenter trong Laravel

Laravel là một framework tuyệt vời, có khi trên cả tuyệt vời, với thiết kế đơn giản mà đầy mạnh mẽ, khả năng mở rộng vô biên cùng cú pháp luôn toát lên vẻ thanh lịch...

Tuy nhiên nó không phải là một cô gái hoàn hảo (lẽ dĩ nhiên là vậy khi mà PHP còn nhiều hạn chế), vẫn có nhiều điểm hạn chế khi ta phát triển và mở rộng ứng dụng.

Trong bài viết này mình xin nói một hạn chế thường gặp: Xuất và định dạng dữ liệu từ Model ra View, và cách dùng Presenter để khắc phục nó.

Vấn đề phát sinh

Trước khi đi vào vấn đề chính, hãy xem một ví dụ sau đây:

Bảng users có cấu trúc đơn giản như sau:

<?php

Schema::create('users', function(Blueprint $table)
{
    $table->increments('id');

    $table->string('firstname', 25);
    $table->string('lastname', 25);
    $table->string('email', 100)->unique();
    $table->string('password', 64);

    $table->timestamps();
});

Một Model User cũng khá đơn giản:

<?php

class User extends Eloquent {

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';

}

Và giờ là khi chúng ta xuất dữ liệu của User ra view.

@foreach (User::all() as $user)
    <p>
        <img src="{{ Gravatar::src($user->email)) }}">
        <span>{{ $user->first_name . $user->last_name }}</span>
        <time>{{ $user->created_at->format('d/m/Y - h:m') }}</time>
    </p>
@endforeach

Nếu chỉ có thế thì sẽ không ra chuyện, chuyện sẽ xảy ra khi bạn không chỉ xuất dữ liệu User một lần mà nhiều lần. Và mỗi lần lại xuất fullname lại chấm một cái giữa fist_namelast_name hay format ngày tháng lại thì thật không hay chút nào.

Bằng sự tìm tòi sáng dạ của mình, tôi đã tìm được một giải pháp tình thế hay hơn ^1 :)): định dạng chúng ở trong Model, khi dùng chỉ cần lấy ra:

<?php

class User extends Eloquent {

    // ...

    public function fullname()
    {
        return $this->first_name . $this->last_name;
    }

    public function avatar()
    {
        return HTML::image(Gravatar::src($this->email));
    }

    public function getCreatedAtAttribute($value)
    {
        return \Carbon\Carbon::parse($value)->format('d/m/Y H:i');
    }

}

Và giờ trong view, dữ liệu xuất ra trở nên trong sáng và thống nhất hơn:

@foreach (User::all() as $user)
    <p>
        {{ $user->avatar() }}
        <span>{{ $user->fullname() }}</span>
        <time>{{ $user->created_at }}</time>
    </p>
@endforeach

Cười hả hê một lúc thì nhận thấy:

  • Model là nơi ta thao tác với CSDL, cớ sao ta đút định dạng ra view vào trong đó?
  • Và quả thật, nếu Model có nhiều scope ^2 thì thật tạp nham, không ra thể thống gì!
  • Nếu những thuộc tính xuất ra View cần nhiều sự logic, mã cứng html... thì đúng là không thể chấp nhận được!
  • ...

Đó chính là lúc cần sử dụng đến Presenter để tách những phương thức xuất ra View ra khỏi Model mà vẫn giữ được cách gọi nhẹ nhàng khi ở Model.

Presenter

Presenter là một kiểu thiết kế khá mới mẻ (dường như nó chỉ sinh ra cho Laravel?!), mình chưa tìm thấy định nghĩa chính thức từ wiki hay nơi nào khác?! Tuy nhiên mục đích của rõ ràng nhất là để khắc phục nhược điểm nêu ở trên: Làm cho Model, View được sạch sẽ và nhất quán.

Thư viện Presenter được dùng nhiều tại thời điểm hiện tại là: robclancy/presenter, nó được thiết kế nhỏ nhẹ mà khá mạnh mẽ cho mục đích sử dụng.

robclancy/presenter được lưu trữ tại địa chỉ: https://github.com/robclancy/presenter, trong đó có một tài liệu cài đặt, giới thiệu và sử dụng rõ ràng. Tuy nhiên, cho mục đích của bài viết này, mình xin được nêu cách sử dụng nó ra đây.

Cài đặt

Thêm robclancy/presenter trong phần "require" file composer.json của bạn.

"robclancy/presenter": "1.1.*"

Chạy composer update để cài đặt (hoặc cập nhật) lại source.

Cuối cùng thêm Provider của nó vào app/config/app.php của bạn:

'Robbo\Presenter\PresenterServiceProvider',

Sử dụng

Presenter rất dễ dàng sử dụng và nếu bạn có để mã trong như trong ví dụ đầu thì bạn cũng dễ dàng sửa đổi lại mà không làm vỡ cấu trúc method.

Giờ tôi sẽ viết lại ví dụ trên đầu theo kiểu thiết kế Presenter:

Một lớp UserPresenter kế thừa lại Robbo\Presenter\Presenter. Ném lại các phương thức trong User cũ vào lớp UserPresenter mới.

<?php

class UserPresenter extends Robbo\Presenter\Presenter {

    public function fullname()
    {
        return $this->first_name . $this->last_name;
    }

    public function avatar()
    {
        return HTML::image(Gravatar::src($this->email));
    }

    public function presentCreatedAt()
    {
        return $this->created_at->format('d/m/Y H:i');
    }

}

User đã trở về với sự đơn giản của nó, bạn cần một phương thức getPresenter để trả về lớp Presenter của Model.

<?php

use Robbo\Presenter\PresentableInterface;

class User extends Eloquent implements PresentableInterface {

    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'users';


    /**
     * Return a created presenter.
     *
     * @return Robbo\Presenter\Presenter
     */
    public function getPresenter()
    {
        return new UserPresenter($this);
    }
}

UserPresenter có mục đích là tải lại các phương thức, biến... từ User khi bạn gọi đến. Và ở bạn có thể tự do thêm các phương thức logic để thao tác với View.

Nếu muốn ghi đè biến của Model, bạn có thể sử dụng prefix present trước tên biến. (Như presentCreatedAt() ở trên)

Giờ thì pass biến qua view:

<?php

$users = User::all();
return View::make('view-template', compact('users'))

Ở đây, bạn cần hiểu cách làm việc của Presenter: Khi bạn truy xuất dữ liệu từ User trong controller, bạn sẽ thao tác với User như thông thường. Khi pass biến qua View, dữ liệu sẽ được tự động chuyển thành UserPresenter thông qua phương thức getPresenter().

Vì vậy, trong View bạn có thể gọi bất cứ phương thức nào có trong User hay UserPresenter. Có thể gọi biến thông qua ArrayAccess, xem thêm tại đây

@foreach ($users as $user)
    <p>
        {{ $user->avatar() }}

        {{ $user['first_name'] }}
        {{ $user->first_name }}

        <span>{{ $user->fullname() }}</span>
        <time>{{ $user->created_at }}</time>
    </p>
@endforeach

Giờ thì app của bạn đã được phân định rõ ràng giữa Model, và Presenter Model. Với Model bạn chỉ nên giữ nó với những phương thức thao tác CSDL, hoặc self-validation. Còn Presenter Model bạn có thể thoải mái định dạng lại dữ liệu Model, hay thậm chí chèn cứng mã HTML vào mà không bị cảm thấy lộn xộn như khi để chúng ở Model.


Để cho được rõ ràng, lớp UserPresenter mình khuyến nghị các bạn đặt trong app/presenters/UserPresenter.php, và sử dụng autoload-class trong composer để tự động load chúng.

"classmap": [
    "app/presenters",
]

Chạy composer dump-autoload để nạp lại file autoload.

Tổng kết

Trong bài viết này bạn đã có thêm một cách thức đẹp nhất cho việc tuyền và định dạng lại dữ liệu từ Model sang View trong Laravel. Một cách thiết kế và tổ chức các lớp, thư mục sao cho gọn gàng và sạch sẽ...

Nếu có bất kỳ thắc mắc hoặc ý kiến, vui lòng để lại comment bên dưới!

Chuyển đổi qua lại giữa các bảng mã tiếng Việt

Chuyển đổi qua lại giữa các bảng mã tiếng Việt

Lý do

Vừa qua thì mình có việc phải đọc dữ liệu từ text-file rồi insert vào CSDL. Tưởng dễ ăn lắm, nhưng than ôi! Thật là khó nhằn!!! Ngoài những file nội dung tiếng Anh ra, còn tiếng Việt thì phần lớn được viết theo kiểu VNI.

Thế là đành tìm trên github với packagist: "VNI", "Unicode", "TCVN3"... không có! Quay sang tra google: "Chuyển đổi VNI sang Unicode với PHP", tìm được vài bài đăng cách chuyển đổi VNI sang Unicode tuy nhiên phần lớn là theo cơ chế lookup rồi thay thế cơ bản nên còn không đúng.

Tiếp tục tra google đi ra ngoài phạm vi PHP thì có khá nhiều cái viết cho js, python, java... hoạt động ổn. Chọn một cái mang tính open-source dùng nó viết hàm vni2unicode() để giải quyết vấn đề tạm thời.

Đến bữa nay rảnh, ngồi đọc code mãi cũng chán thành thử có ý định viết nâng cao hơn cả vni2unicode ngồi google, tra bảng mã, tìm hiểu cơ chế các soft khác... cuối cùng cũng viết ra được cái này.

Nếu bạn đang cần xử lý một tình huống tương tự, chắc hẳn bạn sẽ cần đến thư viện này!

Giới thiệu

UConvert hiện tại cho phép bạn chuyển đổi qua lại giữa các bảng mã của tiếng Việt. Hiện tại hỗ trợ 4 bảng mã:

  • UNICODE
  • VNI
  • TCVN3
  • VIQR

Sẽ sớm hỗ trợ các bảng mã còn lại trong tương lai.

Dữ liệu được dùng để chuyển đổi trong UConvert được lấy từ địa chỉ: http://vietunicode.sourceforge.net/charset

Cài đặt

UConvert có sẵn trên GithubPackagist, vậy nên bạn có thể cài đặt nó qua 2 cách cơ bản:

Qua Composer

Nếu bạn sử dụng Composer để quản lý thư viện cho dự án của mình, một cách dễ dàng nhất, thêm "anhskohbo/u-convert": "dev-master" vào phần require trong file composer.json:

"require": {
    "anhskohbo/u-convert": "dev-master"
}

Tiếp theo, update lại các gói:

composer update

Thủ công

Nếu bạn chưa quen với Composer vì lý do gì, UConvert cho bạn một cách thủ công để nhúng nó vào dự án của bạn.

Đầu tiên, tải UConvert tại đây:

Giải nén tập tin và bạn nên để tên thư mục chứa mã nguồn là u-convert. Ném nó vào thư mục chứa thư viện bên thứ 3 của bạn hoặc bất cứ nơi đâu bạn thích :)

Nhúng nó vào nơi bạn cần sử dụng:

<?php

require '/path-to-libs/u-convert/autoload.php';

//..

Sử dụng

Quy chuẩn về tên bảng mã

Trước khi vào phần sử dụng bạn cần biết tên chuẩn của các bảng mã mà UConvert sử dụng.

Tất cả các tên bảng mã đều phải viết HOA và liền không dấu. Ví dụ UNICODE, VNI, TCVN3, VIQR...

Trong lớp Anhskohbo\UConvert\UConvert một số hằng được khai báo giúp bạn nhất quán trong việc gọi tên bảng mã:

<?php

namespace Anhskohbo\UConvert;

class UConvert implements UConvertInterface {

    const UNICODE = 'UNICODE';
    const TCVN3   = 'TCVN3';
    const VNI     = 'VNI';
    const VIQR    = 'VIQR';

Khởi tạo thông thường

UConvert cung cấp một cách rất dễ dàng để sử dụng, hãy xem một ví dụ:

<?php
// Autoload library...

use Anhskohbo\UConvert\UConvert;

$vni_string = "Xin chaøo theá giôùi";

// Khoi tao UConvert voi string va bang ma cua no.
$convert    = new UConvert($vni_string, UConvert::VNI);

// Chuyen doi sang UNICODE
echo $convert->transform(UConvert::UNICODE);

// Output: Xin chào thế giới

Construct của UConvert chấp nhận 2 đối số:

Anhskohbo\UConvert\UConvert( string $text, string $character)

$text: Nội dung bạn muốn chuyển đổi.

$character: Tên bảng mã hiện tại của nó.

Sau khi khởi tạo bạn cần gọi method transform(string $toCharacter) với tham số là tên bảng mã cần chuyển đến để chuyển nó sang bảng mã cuối.

Gọi trực tiếp qua static.

Ngoài ra thay vì phải khởi tạo lớp, UConvert cho phéo bạn gọi trực tiếp tới một số static-method đặc biệt chuyển đổi.

Những static-method đặc biệt là: to + tên bảng mã sẵn có (trong hệ thống) viết liền và viết hoa chữ cái đầu.

Dưới đây là một ví dụ gọi trực tiếp kiểu static:

<?php

use Anhskohbo\UConvert\UConvert;

UConvert::toUnicode($vni, UConvert::VIQR);

UConvert::toVni($unicde, UConvert::UNICODE);

UConvert::toTcvn3($vni, UConvert::VNI);

Convert::toViqr($tcvn3, UConvert::TCVN3);

Hạn chế

  • Chưa hỗ trợ đầy đủ các bảng mã (sẽ dần có sớm).
  • Thiếu cơ chế tự động nhận diện bảng mã của chuỗi nhập vào (đang xem xét tuy nhiên gặp khó khăn vài regex kém @@)
  • Đọc, chuyển đổi và ghi từ text-file, hay word, excel...
  • ...

Đóng góp

Thư viện được cấp giấy phép MIT nên bạn có thể sửa đổi hay phân phát lại nó. Nếu bạn có bất kỳ chỉnh sửa, thêm mới... bạn có thể:

Gửi pull-request tại: https://github.com/anhskohbo/u-convert/pulls

Tôi rất sẵn lòng!

Thông tin gói

Hello World

Hello World

Xin chào!

Tôi có ý định đăng một bài viết khác nhưng ngẫm lại thôi. Thiết nghĩ nên đăng một bài giới thiệu qua website này trước đã :).

Trang web này tôi có ý định chủ yếu đăng về những vấn đề sau:

  • Linux (tôi yêu Linux và muốn giới thiệu nó cho mọi người).
  • PHP (chủ yếu Laravel framework).
  • Javascript (và các thành phần liên quan).
  • HTML, CSS.
  • Chắc còn vài cái nữa...

Trang web được lưu trữ trên trên Github, sử dụng Jekyll và lấy theme hyde, tôi có chỉnh sửa vài phần để hợp mắt. Cấp giấy phép MIT bạn có thể hoàn toàn xem mã nguồn lấy và chỉnh sửa nó (thực ra cũng chả có gì mà xem ^^). Tuy nhiên mọi bài viết của tôi đều không được sử dụng, chỉnh sửa... mà không ghi rõ nguồn.

Okie, nói nhăng quậy đủ rồi, có lẽ nên dừng, cảm ơn đã đọc.

Chúc mọi điều tốt lành!

Trang trước Trang tiếp