2018年6月30日 星期六

php(ReflectionClass)(反射) 從一個實力的物件取得類別方法,並執行

ReflectionClass:
     public static string export()  //打印类的详细信息
     public string getName()        //取得类名或接口名
     public bool isInternal()       //类是否为系统内部类
     public bool isUserDefined()    //类是否为用户自定义类
     public bool isInstantiable()   //类是否被实例化过
     public bool hasMethod(string name)  //类是否有特定的方法
     public bool hasProperty(string name)//类是否有特定的属性
     public string getFileName()         //获取定义该类的文件名,包括路径名
     public int getStartLine()           //获取定义该类的开始行
     public int getEndLine()             //获取定义该类的结束行
     public string getDocComment()       //获取该类的注释
     public ReflectionMethod getConstructor()           //取得该类的构造函数信息
     public ReflectionMethod getMethod(string name)     //取得该类的某个特定的方法信息
     public ReflectionMethod[] getMethods()             //取得该类的所有的方法信息
     public ReflectionProperty getProperty(string name) //取得某个特定的属性信息
     public ReflectionProperty[] getProperties()        //取得该类的所有属性信息
     public array getConstants()                        //取得该类所有常量信息
     public mixed getConstant(string name)              //取得该类特定常量信息
     public ReflectionClass[] getInterfaces()           //取得接口类信息
     public bool isInterface()  //测试该类是否为接口
     public bool isAbstract()   //测试该类是否为抽象类
-----------------------------------------------------------------------
 class X{
    public static function go(){
        echo '<h1>go</h1>';
    }
    
    public function gogo(){
        echo '<h1>gogo</h1>';
    }
}

class Y extends X {
    
}
//==============================================================================
$y = new Y();

// 取得 static
$className = get_parent_class($y);
$ref = new ReflectionMethod($className, 'go');
$ref->invoke(NULL);
//============================================================================== 
 function make($class, $vars = array()) {
    $ref = new ReflectionClass($class);

    if(!$ref->isInstantiable()) {
        throw new Exception("类{$class} 不存在");
    }

    // 取得建構式
    $constructor = $ref->getConstructor();
    if(is_null($constructor)) {
        return new $class;
    }

    // 確定建構式的參數
    $params = $constructor->getParameters();
    
    $resolveParams = array();
    
    foreach ($params as $key=>$value) {
        $name = $value->getName();
        
        if(isset($vars[$name])) {
            $resolveParams[] = $vars[$name];
        } else {
            
            // 參數是否有默認值
            $default = $value->isDefaultValueAvailable() ? $value->getDefaultValue() : null;
            
            if(is_null($default)) {
                // 參數沒有默認值
                
                if($value->getClass()) {                    
                    
                    // 遞迴(這點似乎有點多)
                    $resolveParams[] = make($value->getClass()->getName(), $vars);
                } else {
                    throw new Exception("{$name} 没有传值且没有默认值。");
                }
            } else {
                $resolveParams[] = $default;
            }
        }
    }

    return $ref->newInstanceArgs($resolveParams);
} 

php &fn

Example1>>

<?php
function &_copy(){
   
    // 函數(&)的目的
    static $data = array();
    return $data;
}


// 呼叫函數還是需要&
$a = &_copy();
$a[] = 5;

// 呼叫函數還是需要&
$b = &_copy();

var_dump($a);
var_dump($b);
------------------------------------------------
Example2>>

function &xyz(Array &$d){
    return $d;
}

$data_1 = array(5, 1, 6);
$data_2 = &xyz($data_1);
//----------------------------
var_dump($data_2);
//----------------------------
sort($data_1);
var_dump($data_2);

2018年6月13日 星期三

gseries.js

function gseries(fn, data) {

    return new Promise(function (res, rej) {
        let it = fn();
        job(data);

        //----------------------------
        function job(d) {

            // 主要要不斷重複的步驟
            let g = it.next(d);
            let p = g.value;
            // p.then(...)

            if (g.done) {
                res(p);
            } else if (p instanceof Promise) {
                p.then(function (d) {
                    job(d);
                }, function (err) {
                    rej(err);
                });
            }else{
                job(p);
            }
        }
    });
}

java extend 的問題

public class A {
    String name = "A";
   
    public void a(){
        System.out.println("i am " + name);
    }
   
    public void getName(){
        System.out.println(name);
    }
}
//=====================================
public class B extends A {
    String name = "B";
   
    public void b(){
        System.out.println("i am " + name);
    }
   
    public void getName(){
        System.out.println("extend " + name);
    }
}
//=====================================
public static void main(String[] args) {
        A a = new B();       
        a.a(); // i am A
        a.getName(); // extend B
        //----------------------------
        B b = (B)a;
       
        b.a(); // 容易出問題 => i am A
        b.getName();  // extend B
        b.b(); // i am B
    }  

2018年6月5日 星期二

讓 js.generator 不斷往下執行

let gseries = require('../node_modules/gseries');

function asynce(index) {
  
    return new Promise(function (res, rej) {
        console.log('index(%s) start', index);
      
        setTimeout(function () {
            console.log('index(%s) end', index);
            res(index);
        }, 3000);
    });
}


function* main() {

    yield asynce(0);

    yield asynce(1);

    return asynce(2);
}


let p = gseries(main);
--------------------------------------------------------
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
module.exports = gseries;

function gseries(fn, data) {

    return new Promise(function (res, rej) {
        let it = fn();
        job(data);

        //----------------------------
        function job(d) {

            // 主要要不斷重複的步驟
            let g = it.next(d);
            let p = g.value;
            // p.then(...)

            if (g.done) {
                res(p);
            } else if (p instanceof Promise) {
                p.then(function (d) {
                    job(d);
                }, function (err) {
                    rej(err);
                });
            }else{
                job(p);
            }
        }
    });
}

2018年6月2日 星期六

php 檔案鎖定(檔案同步)

PHP flock() 函數

定義和用法

flock() 函數鎖定或釋放文件。
若成功,則返回 true。若失敗,則返回 false。

語法

flock(file,lock,block)
參數 描述
file 必需。規定要鎖定或釋放的已打開的文件。
lock 必需。規定要使用哪種鎖定類型。
block 可選。若設置為 1 或 true,則當進行鎖定時阻擋其他進程。

說明

flock() 操作的 file 必須是一個已經打開的文件指針。
lock 參數可以是以下值之一:
  • 要取得共享鎖定(讀取的程序),將 lock 設為 LOCK_SH(PHP 4.0.1 以前的版本設置為 1)。
  • 要取得獨佔鎖定(寫入的程序),將 lock 設為 LOCK_EX(PHP 4.0.1 以前的版本中設置為 2)。
  • 要釋放鎖定(無論共享或獨佔),將 lock 設為 LOCK_UN(PHP 4.0.1 以前的版本中設置為 3)。
  • 如果不希望 flock() 在鎖定時堵塞,則給 lock 加上 LOCK_NB(PHP 4.0.1 以前的版本中設置為 4)。

提示和註釋

提示:可以通過 fclose() 來釋放鎖定操作,代碼執行完畢時也會自動調用。
註釋:由於 flock() 需要一個文件指針, 因此可能不得不用一個特殊的鎖定文件來保護打算通過寫模式打開的文件的訪問(在 fopen() 函數中加入 "w" 或 "w+")。
-----------------------------------------------------------

例子

a_1.php>>

<?php

ob_start();

$filename = "a1.txt";

$file = fopen($filename, "r+");

$res = '';

// 排它性的锁定
if (flock($file, LOCK_EX)) {
    sleep(15);


    while(!feof($file)){
        $res .= fgets($file);
    }
    
    flock($file, LOCK_UN);
} else {
    echo "Error locking file!";
}

fclose($file);

printf('<p>finish(%s)</p>', $res);
----------------------------------------------------------- 

a_2.php>>

 <?php

ob_start();

$filename = "a1.txt";

$file = fopen($filename, "r+");

$res = '';

// 排它性的锁定
if (flock($file, LOCK_EX)) {
    
    while(!feof($file)){
        $res .= fgets($file);
    }
    
    flock($file, LOCK_UN);
} else {
    echo "Error locking file!";
}

fclose($file);

printf('<p>finish(%s)</p>', $res);