Categories
linux

 Sửa lỗi curl (6) could not resolve host

Nếu bạn đang gặp lỗi trên, bạn có thể làm theo cách dưới đây để fix

cd /etc # Đi đến etc folder
nano resolv.conf

Sau đó thêm DNS google vào file

nameserver 8.8.8.8
nameserver 8.8.4.4

Cuối cùng bấm tổ hợp phím control+X (Mac OS) hoặc CTRL + X (window) và chọn Y để save and quit.

Categories
Git

Git Nâng Cao

Clean Commit trong Git

Categories
Bash Script Git

Oh My ZSH

Oh-my-zsh hiểu đơn giản là một framework giúp bạn quản lý các thiết lập của zsh một cách dễ dàng. 

Để dễ hình dung hơn, các bạn có thể nghĩ về Terminal mặc định giống như là Notepad++, còn Oh My ZSH là các editor như là PHPStorm, Visual Code.

Cài Đặt Oh My ZSH

Để cài đặt Oh My ZSH, các bạn vui lòng làm theo hướng dẫn tại trang chủ https://ohmyz.sh/

Các extensions nên có cho Oh My ZSH

  1. zsh-autosuggestions
  2. zsh-syntax-highlighting
  3. zsh-completions

Categories
Git

Command Line Cơ bản trong git

Git clone

Git clone cho phép clone một Remote repo về máy tính của bạn.

git clone remoterepo

Ví dụ

git clone https://github.com/laravel/laravel

Git Fetch

git fetch 

// hoặc

git fetch origin master ## master là tên nhánh bạn muốn fetch

Trường hợp đầu tiên, git sẽ download tất cả các nhánh từ RemoteRepo về LocalRepo.

Trường hợp thứ 2, git sẽ download duy nhất nhánh đó từ RemoteRepo về LocalRepo. Có thể hiểu như sau.

Git Pull

git pull 

Tương tự như git fetch, git pull sẽ download tất cả branch mới từ remote repo về local repo và. Nhưng, nó sẽ tự động merge code tại từ localrepo về nhánh hiện tại.

Xem video dưới đây để hiểu về Git Fetch và Git Pull:

Git checkout

Để tạo 1 nhánh mới:

git checkout -b ten_nhanh_moi 

// hoặc

git checkout -b ten_nhanh_moi master
  1. Khi bạn đang ở nhánh master (working_directory là master) thì git sẽ tạo một nhánh là ten_nhanh_moi và code được copy từ master.
  2. Khi bạn đang ở nhánh khác nhánh master (ví dụ dev) nhưng bạn muốn tạo 1 nhánh mới copy code từ nhánh master thì bạn cần chỉ rõ tên nhánh copy là master.

Để chuyển đổi làm việc từ nhánh này sang nhánh khác:

git checkout ten_nhanh_moi

Git add

git add . // để add tất cả
git add file1.php file2.php folder1 // chỉ rõ files, folders cần add

Git add sẽ add code vào Staging area

Git Commit

git commit -m "Comment o day"

Git commit sẽ đẩy code đã được add trước đó lên LocalRepo

Git Status

git status

Kiểm tra trạng thái các files, folders. Nếu files, folders đã được chạy git add nhưng chưa commit, sẽ có màu xanh. Files, folders chưa được add sẽ có màu đỏ.

Git Remote

git remote -v // Kiểm tra remote repo url
git remote add origin https://remote-repourl // add remote repo url 
git remote set-url origin new.git.url/here // change repo url

Categories
Git

Git là gì?

Git là gì?

Khi lập trình, sẽ có lúc bạn lỡ tay xoá một đoạn code vì nghĩ rằng đoạn code đó không phù hợp nữa, nhưng sau đó lại phát hiện là đoạn code đó bạn vẫn cần dùng.

Bạn nghĩ mình có thể nhớ lại chính xác  những gì mình đã viết không? Thật sự là rất rất khó. Nhưng nếu bạn có dùng phần mềm quản lý phiên bản mã nguồn thì mọi việc sẽ trở nên đơn giản hơn rất nhiều vì phần mềm quản lý phiên bản mã nguồn sẽ cho phép bạn dễ dàng quay lại một phiên bản trước của tập tin đó.

Có thể nói phần mềm quản lý mã nguồn là công cụ không thể thiếu đối với lập trình viên và một trong những phần mềm hỗ trợ quản lý phiên bản rất phổ biến hiện nay là Git


Git sẽ giúp người dùng lưu lại các phiên bản của những lần thay đổi mã nguồn để dễ dàng khôi phục lại phiên bản cũ mà không cần phải nhớ là mình đã chỉnh ở đâu, tất cả phiên bản bạn cần đều đã được sao lưu. 

Để cài đặt git, vui lòng đọc https://backlog.com/git-tutorial/vn/intro/intro2_1.html

Quy Trình Xử Lý Công Việc Trên Git (Workflow)

Repository

Repository – kho lưu trữ – là nơi Git lưu trữ mọi thông tin của dự án (ảnh, file, folder, …) cũng như lịch sử sửa đổi trong dự án của bạn.

Chúng ta sẽ chia ra thành 2 khu vực:

  1. Local repository: Là kho lưu trữ của Git trên máy tính của bạn.
  2. Remote repository: Là kho lưu trữ của một nhà cung cấp dịch vụ về git (như Github, GitLab, Bitbucket).

Nó tự tự như bạn làm một website cho khách hàng:

  1. Ban đầu, bạn sẽ code trên máy tính (Local Repository)
  2. Sau đó, đẩy code lên một hosting (Remote Repository)

Branch – Nhánh

Nhánh là một khái niệm quan trọng trong Git. Bạn có thể sử dụng nhánh để tách riêng các tính năng trong một dự án, hoặc bạn cũng có thể dùng nhánh để fix một bug …

Ví dụ 1:

Chính phủ có kế hoạch làm đường cao tốc Hà Nội – Lào Cai để giảm thời gian di chuyển cho các phương tiện.

Khi triển khai, không thể làm đường cao tốc ngay trên đường cũ, vì làm như vậy thì mọi người muốn đi từ Hà Nội lên Lào Cai phải đợi đường làm xong mới được đi à :v.

Vậy, chính phủ sẽ phải tạo một nhánh là feature/duong-cao-toc, và toàn bộ quá trình thi công sẽ hoạt động trên nhánh này. Sau khi hoàn thành, chính phủ mới có thể đưa con đường vào sử dụng (trong git gọi là merge code ở nhánh này vào nhánh chính).

Nhờ có nhánh, chúng ta vẫn đảm bảo phương tiện di chuyển từ HN lên LC bằng đường cũ mà không vấn đề gì, đồng thời thi công đường mới ở nhánh feature/duong-cao-toc.

Checkout

Checkout cho phép chúng ta tạo một nhánh mới hoặc nhảy từ nhánh này sang nhánh khác.

Ví dụ:

Kỹ sư A được phân công làm đường cao tốc HN -> LC. Vì nhánh này chưa tồn tại, nên cần ký một quyết định A làm việc tại đường cao tốc HN -> LC.

Để tạo một nhánh mới, chúng ta sẽ sử dụng lệnh:

git checkout -b feature/duong-cao-toc master
  1. feature/duong-cao-toc là tên nhánh mới
  2. master là tên nhánh bạn muốn copy code sang nhánh mới.

Kỹ sư A đang làm việc tại đường cao tốc. Nhưng có việc gấp, nên cần triệu tập về trung ương. Vì nhánh trung ương đã tồn tại (master hoặc main), nên kỹ sư A sẽ lên xe phi về trung ương:

Để nhảy từ nhánh này sang nhánh khác (giả sử bạn đang ở nhánh master), chúng ta sẽ sử dụng lệnh:

git checkout feature/duong-cao-toc

Sau khi hoàn thành việc ở trung ương, A lại lên ô tô phi về cao tốc HN -> LC

git checkout master

Workflow

Working Directory

Như ở ví dụ trên, khi kỹ sư làm việc ở cao tốc HN -> LC thì working directory là feature/duong-cao-toc.

Khi kỹ sư A về trung ương thì working directory là master

Staging area (Khu vực chờ)

Sau khi hoàn thành dự án, kỹ sư A nhận được 100 triệu :v (rẻ vãi).

Kỹ sư A là người tu chí nên a quyết định gửi ngân hàng chứ không đi bay.

Anh lên ngân hàng, gặp giao dịch viên, giao dịch viên mở nhánh feature/ky-su-a-gui-tien đưa cho a tờ giấy gửi tiền.

git checkout -b feature/ky-su-a-gui-tien

Giấy gửi tiền có 3 thông tin:

  1. Họ tên
  2. Tuổi
  3. Và số tiền

Mỗi lần a ghi một thông tin, a gõ git add

git add ho-ten.php
git add tuoi.php
git add so-tien.php

Kỹ sư A cũng có thể viết hết cả 3 thông ti và gõ

git add .

Khi gõ git add, thông tin nộp tiền đang ở Staging area.

Localrepo

Khi hoàn thành toàn bộ thông tin, anh mỉnh cười và ký chữ ký:

git commit -m "Ky su Nguyen Van A"

Lúc này, tờ giấy gửi tiền vẫn ở trong tay anh (Local Repository)

Remote

Sau đó, a đưa giấy gửi tiền cho giao dịch viên cùng 100 triệu.

Em giao dịch viên nhìn thấy a gửi 100 triệu lòng đầy ngưỡng mộ. E cầm giấu đỏ gõ phạch một phát vào tờ giấy:

git push

Sau lệnh git push, thông tin đã được gửi lên Ngân Hàn Trung Ương – Remote Local.

Thực hành

Categories
DevOps

Tìm hiểu về psalm

Psalm là gì?

Psalm là một công cụ để tìm lỗi code trong ứng dụng của bạn.

Cài đặt Psalm và kiểm tra code

Bước 1: Download psalm với Composer

composer require --dev vimeo/psalm

Bước 2: Sau đó tạo file config tự động bằng lệnh

./vendor/bin/psalm --init

Bước 3: Sau đó chạy lệnh dưới đây để verify code

./vendor/bin/psalm 

Bước 4: Nếu bạn đang sử dụng PHPStorm, làm theo video dưới đây

Ví dụ

Categories
Uncategorized

CircleCI

Bài Liên Quan

Reference trong YML

Mục Lục

  1. version
  2. orbs (orchestration)
  3. commands
  4. parameters
  5. executors
  6. jobs
  7. workflow

Dưới đây là một ví dụ đơn giản về một config circle:

version: 2.0
jobs:
  build:
    docker:
      - image: circleci/php:7.2-apache
    steps:
      - checkout
      - run:
          name: Kiem tra folder
          command: ls -la
      - run:
          name: Kiem tra folder cha
          command: cd ../ && ls -la
  build_voi_duong_dan_moi:
    docker:
      - image: circleci/php:7.2-apache
    working_directory: ~/wiloke
    steps:
      - run:
          name: Kiem tra folder
          command: ls -la
      - run:
          name: Kiem tra folder cha
          command: cd ../ && ls -la
      - run:
         name: Kiem tra folder ong
         command: cd ../../ && ls -la
workflows:
  version: 2
  build_test_deploy:
    jobs:
      - build
      - build_voi_duong_dan_moi

version

Khai báo version của circleci bạn muốn sử dụng.

Tại thời điểm viết bài, version mới nhất của circleci là 2.1. Trường hợp các bạn sử dụng 2.1, các bạn có thể thêm các config mới https://circleci.com/docs/2.0/configuration-reference/

jobs

Sơ đồ config của job như sau:

jobs
  <job_name>
    docker/machine/macops/window (required)
    working_directory (required)
    environment
    steps
  
   

workflows

Workflows xác định một list các job và thứ tự chạy của chúng. Bạn có thể cho chúng chạy song song, tuần tự, theo một lịch cố định hoặc cổng thủ công sử dụng approval job.

Một workflow bắt đầu bằng version và workflow_name. workflow_name được hiểu như là key và nó phải là duy nhất.

workspace

Workspace là một tính năng của Workflows và được sử dụng để move data từ một job trong workflow sang các công việc tiếp theo.

Ví dụ: Khi code PHP, chúng ta thường sử dụng composer để install các extensions cho project. Các extensions sau khi được install sẽ nằm ở dưới file vendor (tương tự như việc install node_modules trong js). Thay vì chạy lệnh composer install ở mỗi Job Layer, chúng ta sẽ install nó ở layer đầu tiên, sau đó lưu vendor vào workspace và tái sử dụng ở những layers sau.

version: 2.0
jobs:
  build:
    docker:
      - image: circleci/php:7.2-apache
        enviroment:
    working_directory: ~/wordpress
    steps:
      - checkout
      - run:
          name: Update Composer
          command: sudo composer self-update
      - restore_cache: # special step to restore the dependency cache if `composer.lock` does not change
          keys:
            - composer-v1-{{ checksum "composer.lock" }}
            # fallback to using the latest cache if no exact match is found (See https://circleci.com/docs/2.0/caching/)
            - composer-v1-
      - run:
          name: Installing Composer
          command: composer install -n --prefer-dist
      - run:
          name: Generate autoload
          command: composer dump-autoload
      - run:
          name: Build co gi
          command: ls -la
      - persist_to_workspace:
          root: .
          paths:
            - vendor
      - run:
          name: Build co gi 1
          command: ls -la
  build_voi_duong_dan_moi:
    docker:
      - image: circleci/php:7.2-apache
    working_directory: ~/wiloke
    steps:
      - run:
          name: Kiem tra lai working directory
          command: ls -la
      - attach_workspace:
          at: ~/wiloke
      - run:
          name: Kiem tra attack workspace
          command: ls -la
      - run:
          name: Kiem tra folder
          command: ls -la
      - run:
          name: Kiem tra folder cha
          command: cd ../ && ls -la
      - run:
          name: Kiem tra folder ong
          command: cd ../../ && ls -la
workflows:
  version: 2
  build_test_deploy:
    jobs:
      - build
      - build_voi_duong_dan_moi:
          requires:
            - build

Kết quả thu được như sau

Categories
DevOps

YAML references

Trong bài viết này, chúng ta sẽ tìm hiểu về references section trong YAML.

Anchor và Reference & *

Cùng theo dõi ví dụ dưới đây:

foo: &anchor
FIRSTNAME: "Wiloke"
LASTNAME: "Family"
bar: *anchor

references cho phép chúng ta tận dụng một chức năng ít được biết đến của YAML: anchor và references.

Anchors (được ký hiệu bới &) cho phép định nghĩa các nodes mà chúng ta muốn tái sử dụng trong YAML.

Sau đó, chúng ta sẽ sử dụng ký hiệu * để tham chiếu đến anchor đó.

Ở ví dụ trên, kết quả nhận được sẽ như sau:

Có thể viết lại đoạn code trên bằng JS như sau:

{
    "foo": {
        "K1": "One",
        "K2": "Two"
    },
    "bar": {
        "K1": "One",
        "K2": "Two"
    }
}

Extend Toàn Bộ <<

Ngoài ra, bạn còn có thể add thêm giá trị cho nốt tham chiếu bằng cách sử dụng ký hiệu <<

Cùng theo dõi ví dụ dưới đây:

foo: &anchor
  K1: "One"
  K2: "Two"

bar:
  <<: *anchor
  K2: "I Changed"
  K3: "Three"

Kết quả thu được là:

{
    "foo": {
        "K1": "One",
        "K2": "Two"
    },
    "bar": {
        "K1": "One",
        "K2": "I Changed",
        "K3": "Three"
    }
}

Extend Một Phần

Trong trường hợp bạn muốn extend một vài phần tử từ một node, ta có thể làm như sau:

foo:
  <<: &anchor
        K1: "One"
   K2: "Two"
bar:
  <<: *anchor
  K3: "Three"

Và kết quả nhận được là:

{
   "foo": {
      "K1:"One",
      "K2": "Two"
   },
   bar: {
      "K1": "One",
      "K3": "Three"
   }
}
Categories
Sqlite

Sqlite là gì?

SQLite là gì?

SQLite là phần mềm quản lý cơ sở dữ liệu (DBMS) tương tự như Mysql, PostgreSQL… Đặc điểm của SQLite là gọn, nhẹ, đơn giản. Chương trình gồm 1 file duy nhất vỏn vẹn chưa đến 250 KB, không cần cài đặt, không cần cấu hình hay khởi động mà có thể sử dụng ngay. Dữ liệu Database cũng được lưu ở một file duy nhất. Không có khái niệm user, password hay quyền hạn trong SQLite Database.

Cài Đặt Sqlite

https://www.sqlite.org/download.html

Phần mềm quản lý

Table Plus https://tableplus.com/

Categories
Design Pattern

Ứng dụng Strategy Pattern Để Optimize Wilcity App Code

Bài Toán Đặt Ra cho Wiloke PHP.

API để get posts:

https://demo.wilcityapp.com/wp-json/wiloke/v3/posts

public function getBlog($aData)
{
   $aArgs = $this->buildBlogQuery($aData);
   $query = new \WP_Query($aArgs);
   $aResults = [];
   $aPosts = [];

   if ($query->have_posts()) {
      // query tai day
   } else {
      $aResults['status'] = 'error';
      $aResults['msg'] = esc_html__('No Post Founds', 'wilcity-mobile-app');

      return $aResults;
   }

   return $aResults;
}

Có 2 phần chính ở đây:

  1. Argument cung cấp cho query.
  2. Trả về kết quả

API để get một post:

https://demo.wilcityapp.com/wp-json/wiloke/v3/posts/20523

public function getPost($aData)
{
   $post = get_post(abs($aData['ID']));
   if (empty($post) || is_wp_error($post)) {
      return [
         'status' => 'error',
         'msg'    => esc_html__('This page no longer available', 'wilcity-mobile-app')
      ];
   }

   // build args trả về tại đây

   return [
      'status'  => 'success',
      'oResult' => $aData
   ];
}

Cũng có 2 phần chính ở đây:

  1. Argument cung cấp cho query.
  2. Trả về kết quả

Ta nhận thấy, có sự thay đổi về args trong query, nhưng cấu trúc kết quả trả về là giống nhau.

=> Đóng gói sự thay đổi và tách phần này ra.

<?php
// đóng gói sự thay đổi
interface IQueryArgs {
    public function parseRawArgs(array $aRawArgs): array;
}

class PostsQueryArgs {
    private $aArgs;

    public function buildQueryArgs(array $aRawArgs): array {
       // phân tích tại đây

       return $this->aArgs;
    } 
}

class PostQueryArgs {
    private $aArgs;

    public function buildQueryArgs(array $aRawArgs): array {
       return $this->aArgs;
    } 
}



class PostController {
    private $oQueryArgs;
    
    public function __construct(){
         register_rest_route(WILOKE_PREFIX . '/' . WILOKE_MOBILE_REST_VERSION, 'posts', [
                'methods'             => 'GET',
                'callback'            => [$this, 'getPosts'],
                'permission_callback' => '__return_true',
        ]);

        register_rest_route(WILOKE_PREFIX . '/' . WILOKE_MOBILE_REST_VERSION, 'posts/(?P<id>\d+)', [
                'methods'             => 'GET',
                'callback'            => [$this, 'getPost'],
                'permission_callback' => '__return_true',
        ]);
    }

    public function setHandlerQueryArgs(IQueryArgs $oQueryArgs) {
        $this->oQueryArgs = $oQueryArgs;
        return $this;
    }

    public function getPost($post) {
       /// get du lieu
    }

    public function getPosts(\WP_REST_Request $oRequest) {
       // phân tích tại đây
       $aArgs = $this->oQueryArgs->buildQueryArgs($oRequest->get_params());
       $query = new WP_Query($aArgs);
       
       $aPosts = [];

       if ($query->have_posts()) {
           while ($query->have_posts()) {
                $query->the_post();
                $aPosts[] = $this->getPost($query->post);
           }
       }
       // tra ve
    } 

    public function getPost(\WP_REST_Request $oRequest) {
       // phân tích tại đây
       $aArgs = $this->oQueryArgs->buildQueryArgs($oRequest->get_params());
       $query = new WP_Query($aArgs);
       
       $aPost = [];

       if ($query->have_posts()) {
           while ($query->have_posts()) {
                $query->the_post();
                $aPost = $this->getPost($query->post);
           }
       }
       // tra ve
    } 
}