PHP Interview Questions(17)

面试时间:2020年1月7号,星期一,上午十点。


1.What does “&” mean in ‘&$var’?

Passing by Reference

https://www.php.net/manual/en/language.references.pass.php

2.What is MVC?

MVC is a design pattern used to decouple user-interface (view), data (model), and application logic (controller). This pattern helps to achieve separation of concerns.

https://dotnet.microsoft.com/apps/aspnet/mvc

3.What is the difference between $_GET and $_POST?

$_GET — HTTP GET variables
$_POST — HTTP POST variables

https://www.php.net/manual/en/reserved.variables.php

4.What will be the output of each statements below and why?

var_dump(0123 == 123);

var_dump(‘0123’ == 123);

var_dump(‘0123’ === 123);

False
True
False

https://www.php.net/manual/en/language.types.integer.php

5.After the code below is exexuted, what will be the value of $text and what will be strlen($text) return? Explain your answer.

$text = ‘John ‘;

$text[10] = ‘Doe’;

$text = 'John      D';
strlen($text) = 11;

Javascript

1.What is the potential pitfall with using typeof bar == “object” to determine if bar is an object? How can this pitfall be avoided?

typeof null == "object"
bar != null && typeof bar == "object"

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof

2.What is NaN? What is its type? How can you reliably test if a value is equal to NaN?

Not a number
Number
isNaN()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN

3.What is the difference between jQuery.get() and jQuery.ajax()?

$.get(url, data, success, dataType) is a shorthand Ajax function, which is equivalent to:

$.ajax({
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

https://api.jquery.com/jQuery.get/

4.Write a simple function(less than 80 characters) returns a boolean indicating whether or not a string is palindrome.

A palindrome is a word, phrase, number, or other sequence of characters which reads the same backward or forward. Allowances may be made for adjustments to capital letters, punctuation, and word dividers.

console.log(isPalindrome("level"));                    // logs 'true'
console.log(isPalindrome("levels"));                   // logs 'false'
console.log(isPalindrome("A car, a man, a maraca"));   // logs 'true'

function isPalindrome(str) {
    str = str.replace(/\W/g, "").toLowerCase();
    return str.split("").reverse().join("") == str;
}

 5,418 total views,  2 views today

PHP Interview Questions(14)

面试时间:2019年11月20号,星期三,下午两点。


最近的项目中有使用 Laravel 吗?Laravel 的目录结构。

https://laravel.com/docs/6.x/structure

一道编程测试题。(代码点这里)

With the best of your knowledge, create 2 Apis as following: 

1 - Endpoint: /mail/contact

Description: This endpoint is used to send contact form to a specific email, It needs to use the SMTP server provided to dispatch the email to the target user, the email must include Name, Email, Message, and optionally an Attachment

Required Payload: 

{
   name: String,
   email: String,
   message: String,
   attachment: File
}

Tasks

- [ ] Send email using sendgrid to a configurable user email
- [ ] Handle errors
- [ ] Send attachments
- [ ] Send formatted html emails (can be vary basic using tags like div, b, pre etc)

2 - Endpoint: /mail/subscription

Description: This endpoint is used to store user subscription emails, the goal is to keep every email stored in a persistent storage, where it can be later retrieve for further usage. 

Required Payload: { email: string }

Tasks:

- [ ] Handles the case of duplicated entries
- [ ] Persist on local database

Additional Requirements: 

The apis has to work asynchronously (Non Blocking), follow RESTful conventions, clean code, follow Laravel standards, and lastly don’t use excuses like: “I didn’t do this because it’s was a simple project i didn’t felt it was necessary” we want see what you are capable of so do everything that’s under your knowledge. 

Deliverable:
- A ZIP of the project (without the vendor folder)

说说你对设计模式的理解和你运用设计模式的实例。

设计原则 > 设计模式

装饰器模式

适配器模式

你对PHP新版本的特性有关注吗?7.4 有哪些新特性你比较喜欢。

https://laravel-news.com/tag/php74

// 类型属性
https://wiki.php.net/rfc/typed_properties_v2

// 箭头函数
https://wiki.php.net/rfc/arrow_functions_v2

// 数组扩展运算符
https://wiki.php.net/rfc/spread_operator_for_array

What‘s your favorite framework?Why?

Laravel

Document, Community, Packages, Eloquent ORM(ActiveRecord)

https://www.appclonescript.com/laravel-pros-cons/

What‘s the difference between left join and right join?

Can you explain what‘s Eager Loading?

https://laravel.com/docs/6.x/eloquent-relationships#eager-loading

//If we have 25 books, this loop would run 26 queries

$books = App\Book::all();

foreach ($books as $book) {
    echo $book->author->name;
}

//For this operation, only two queries will be executed
$books = App\Book::with('author')->get();

foreach ($books as $book) {
    echo $book->author->name;
}

 1,434 total views,  1 views today

PHP Interview Questions(13)

面试时间:2019-11-13 星期三,下午两点。


Yii2 实现原理

Yii2 生命周期

Request Lifecycle
https://www.yiiframework.com/doc/guide/2.0/en/start-workflow

快速排序算法。

分治,递归,每一次递归能够确定一个数的位置。

不稳定算法,平均算法时间复杂度 O(nlog2n),平均空间复杂度 O(log2n)。

<?php

/**
 * Quick Sort Implement 1
 * @param array $array
 * @return array
 */
function quickSort(array $array) {
    if (count($array) <= 1) {
        return $array;
    }

    $middle = $array[0];
    $left = [];
    $right = [];

    for ($i = 1; $i < count($array); $i++) {
        if ($array[$i] < $middle) {
            $left[] = $array[$i];
        } else {
            $right[] = $array[$i];
        }
    }

    return array_merge(quickSort($left), [$middle], quickSort($right));
}

/**
 * Quick Sort Implement 2
 * @param array $array
 * @param  int $start
 * @param  int $end
 */
function quickSort2(array &$array, int $start, int $end) {
    if ($start >= $end) {
        return;
    }

    $i = $start;
    $middle = $array[$start];

    for ($j = $start + 1; $j <= $end; $j++) {
        if ($array[$j] < $middle) {
            $i++;
            exchange($array[$i], $array[$j]);
        }
    }

    exchange($array[$i], $array[$start]);

    quickSort2($array, $start, $i - 1);
    quickSort2($array, $i + 1, $end);
}

function exchange(&$a, &$b) {
    [$a, $b] = [$b, $a];
}

function printArray($array) {
    foreach ($array as $value) {
        echo $value, " ";
    }
    echo "\n";
}

$array = [6, 5, 3, 1, 8, 7, 2, 4];
printArray(quickSort($array));
quickSort2($array, 0, count($array) - 1);
printArray($array);

自动加载原理。

https://zyf.im/2019/04/28/php-composer-basic/

工作中遇到的最难的问题是什么?怎么解决的。

 438 total views

PHP Interview Questions(12)

面试时间:2019 年 11 月 5 日,星期二,下午三点。


现在使用的 PHP 版本,有哪些新特性。

PHP 7.2

https://tanghengzhi.com/whats-new-in-php-72/

聊一聊PHP SPL,迭代器和生成器。

/**
 * https://www.php.net/manual/en/intro.spl.php
 **/
The Standard PHP Library (SPL) is a collection of interfaces and classes that are meant to solve common problems.

No external libraries are needed to build this extension and it is available and compiled by default in PHP 5.0.0.

SPL provides a set of standard datastructure, a set of iterators to traverse over objects, a set of interfaces, a set of standard Exceptions, a number of classes to work with files and it provides a set of functions like spl_autoload_register()

/**
 * https://www.php.net/manual/zh/class.iterator.php
 **/

/**
 * https://www.php.net/manual/zh/language.generators.overview.php
 **/

TCP 和 UDP 的区别。

        UDP	TCP
是否连接	无连接	面向连接
是否可靠	不可靠传输,不使用流量控制和拥塞控制	可靠传输,使用流量控制和拥塞控制
连接对象个数	支持一对一,一对多,多对一和多对多交互通信	只能是一对一通信
传输方式	面向报文	面向字节流
首部开销	首部开销小,仅8字节	首部最小20字节,最大60字节
适用场景	适用于实时应用(IP电话、视频会议、直播等)	适用于要求可靠传输的应用,例如文件传输

https://segmentfault.com/a/1190000018582150

什么是 Socket 编程。

Socket 是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。

https://www.jianshu.com/p/f671d3895d13

MySQL 索引。

https://dev.mysql.com/doc/refman/8.0/en/optimize-overview.html

MySQL 事务。

https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_transaction

MySQL 读写分离。

'mysql' => [
    'read' => [
        'host' => [
            '192.168.1.1',
            '196.168.1.2',
        ],
    ],
    'write' => [
        'host' => [
            '196.168.1.3',
         ],
    ],
    'sticky'    => true,
    'driver'    => 'mysql',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => '',
    'charset'   => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix'    => '',
],

https://laravel.com/docs/6.x/database

常见的 Redis 数据结构。

https://www.runoob.com/redis/redis-data-types.html

Redis 集合(Set) 常用命令。

https://www.runoob.com/redis/redis-sets.html

Redis cluster 原理。

https://redis.io/topics/cluster-tutorial

Git Rebase

https://git-scm.com/book/en/v2/Git-Branching-Rebasing

https://docs.microsoft.com/en-us/azure/devops/repos/git/merging-with-squash?view=azure-devops

Git 工作原理

http://marklodato.github.io/visual-git-guide/index-zh-cn.html

 378 total views

PHP Interview Questions(11)

面试时间:2019 年 11 月 4 日,星期一,下午两点。


1. 给定一个二维数组,数组每一行从左到右都是递增的,每一列也是递增的。请完成一个函数,输入为如上二维数组和一个整数,函数功能为判断该整数是否存在于数组中。时间复杂度尽可能的低。(请说明你的算法的复杂度。)

下面是一个例子:

二维数组:

1 2 8 9

2 4 9 12

4 7 10 13

6 8 11 15

数字:9

<?php

$array = [
    [1, 2, 8, 9],
    [2, 4, 9, 12],
    [4, 7, 10, 13],
    [6, 8, 11, 15],
];

$number = 9;

/**
 * 最简单的方法就是遍历整个数组
 * 时间复杂度 O(Row*Column-1)
 */
function findNumberInArray($array, $number) {
    foreach ($array as $rowArray) {
        foreach ($rowArray as $value) {
            echo $value, " ";
            if ($number == $value) {
                return true;
            }
        }
    }

    return false;
}

/**
 * 从二维数组的左下角开始逐行查找
 * 时间复杂度 O(Row+Column-1)
 */
function findNumberInArray2($array, $number) {
    $minRow = 0;
    $minColumn = 0;
    $maxRow = count($array) - 1;
    $maxColumn = count($array[0]) - 1;

    if ($number < $array[0][0] || $number > $array[$maxRow][$maxColumn]) {
        return false;
    }

    for ($row = $maxRow; $row >= $minRow; $row--) {
        for ($column = $minColumn; $column <= $maxColumn; $column++) {
            echo $array[$row][$column], " ";
            if ($array[$row][$column] == $number) {
                return true;
            }
            if ($array[$row][$column] > $number) {
                break;
            }
            if ($array[$row][$column] < $number) {
                $minColumn = $column + 1;
            }
        }
    }

    return false;
}

/**
 * 从二维数组的右上角开始逐行查找
 * 时间复杂度 O(Row+Column-1)
 */
function findNumberInArray3($array, $number) {
    $minRow = 0;
    $minColumn = 0;
    $maxRow = count($array) - 1;
    $maxColumn = count($array[0]) - 1;

    if ($number < $array[0][0] || $number > $array[$maxRow][$maxColumn]) {
        return false;
    }
    
    for ($row = $minRow; $row <= $maxRow; $row++) {
        for ($column = $maxColumn; $column >= $minColumn; $column--) {
            echo $array[$row][$column], " ";
            if ($array[$row][$column] == $number) {
                return true;
            }
            if ($array[$row][$column] > $number) {
                $maxColumn = $column - 1;
            }
            if ($array[$row][$column] < $number) {
                break;
            }
        }
    }

    return false;
}

echo "/**
* 最简单的方法就是遍历整个数组
* 时间复杂度 O(Row*Column-1)
*/\n";
for ($number = 0; $number <= 15; $number++) {
    echo "find ", $number, ": ";
    findNumberInArray($array, $number);
    echo "\n";
}

echo "/**
* 从二维数组的左下角开始逐行查找
* 时间复杂度 O(Row+Column-1)
*/\n";
for ($number = 0; $number <= 15; $number++) {
    echo "find ", $number, ": ";
    findNumberInArray2($array, $number);
    echo "\n";
}

echo "/**
* 从二维数组的右上角开始逐行查找
* 时间复杂度 O(Row+Column-1)
*/\n";
for ($number = 0; $number <= 15; $number++) {
    echo "find ", $number, ": ";
    findNumberInArray3($array, $number);
    echo "\n";
}

2.把数组最开始的若干个元素搬到数组末尾,称为数组的旋转。给定一个递增数组的旋转数组,请完成一个函数,时间复杂度尽可能的低,输出该旋转数组的最小元素。并给出复杂度。

例如输入数组(4,5,6,7,8,10,1,2,3),输出 1。

<?php

$array = [4, 5, 6, 7, 8, 10, 1, 2, 3];

/**
 * 使用 min() 函数
 * 时间复杂度:O(N)
 * 源码:https://github.com/php/php-src/blob/master/ext/standard/array.c
 */
echo min($array), "\n";

/**
 * 使用二分查找法
 * 时间复杂度:O(log2N)
 */
function findMinimumNumberInArray($array, $start = 0, $end = null) {
    if ($end == null) {
        $end = count($array) - 1;
    }

    if ($start == $end) {
        return $array[$start];
    }

    $middle = floor(($start + $end) / 2);

    if ($array[$start] < $array[$end]) {
        return findMinimumNumberInArray($array, $start, $middle);
    } else {
        return findMinimumNumberInArray($array, $middle, $end);
    }
}

echo findMinimumNumberInArray($array), "\n";

3.输入一个字符串,输出该字符串中字符的所有组合。(不限编程语言,请注明你选择的语言)

下面是一个例子:

输入参数:字符串:“abc”

输出:“a”, “b”, “c”, “ab”, “ac”, “bc”, “abc”

<?php

$string = "abc";
$length = strlen($string);

/**
 * 使用二进制表示不同的排列组合
 * 
 * 0 0 1 a
 * 0 1 0 b
 * 0 1 1 ab
 * 1 0 0 c
 * 1 0 1 ac
 * 1 1 0 bc
 * 1 1 1 abc
 */
 for ($i = 1; $i < 1 << $length; $i++) {
     for ($j = 0; $j < $length; $j++) {
         if ($i & (1 << $j)) {
             echo $string[$j];
         }
     }
     echo "\n";
 }

参考:

剑指Offer面试题:2.二维数组中的查找

剑指Offer面试题:7.旋转数组的最小数字

剑指Offer面试题:26.字符串的排列

 517 total views

GitLab CI/CD

Workflow

GitLab workflow example

准备工作

在开始使用 GitLab CI/CD 之前,我们需要完成以下准备工作。

  1. 安装 Gitlab 和 Gitlab Runer。
  2. 生成一对 SSH Private Key 和 SSH Public Key。

SSH Private Key 配置在 Setting > CI/CD > Variables 里面。

SSH Public Key 配置在要部署的服务器上的 ~/.ssh/authorized_keys 文件里面。


下面我们用两个例子来体验一下 GitLab CI / CD 配置文件 .gitlab-ci.yml 的语法。

PHP Examples

image: tanghengzhi/gitlab-deploy

before_script:
    # Add the private SSH key to the build environment
    - mkdir -p ~/.ssh
    - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config

stages:
    - test
    - deploy

test:
    stage: test
    script: echo 'PHP is the best language in the world'
    only:
        - master

deploy-dev-and-test:
    stage: deploy
    script:
        # Run git pull
        - ssh ec2-user@54.223.162.119 sudo git -C /opt/case/woof-go-waybill pull
        - ssh ec2-user@54.223.162.119 sudo git -C /opt/case/woof-go-waybill-beta pull
    only:
        - master

deploy-online-1:
    stage: deploy
    script:
        # Run git pull
        - ssh ec2-user@54.222.244.71 sudo git -C /opt/case/waybill-service pull
    when: manual
    only:
        - master

deploy-online-2:
    stage: deploy
    script:
        # Run git pull
        - ssh ec2-user@52.81.109.73 sudo git -C /opt/case/waybill-service pull
    when: manual
    only:
        - master

Java Examples

image: tanghengzhi/gitlab-deploy:java

before_script:
    # Add the private SSH key to the build environment
    - mkdir -p ~/.ssh
    - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config

stages:
    - build
    - deploy

build:
    stage: build
    script:
        - ./gradlew build
    artifacts:
        paths:
          - build/libs/*.jar
    only:
        - master

deploy-dev:
    stage: deploy
    script:
        - rsync build/libs/*.jar ec2-user@54.223.162.119:/opt/case/waybill-service/build/libs/
        - ssh ec2-user@54.223.162.119 sudo service waybill-service restart
    only:
        - master

参考:

https://docs.gitlab.com/ee/ci/introduction/index.html

https://docs.gitlab.com/ee/ci/

https://github.com/tanghengzhi/gitlab-deploy

 841 total views

PHP Interview Questions(10)

面试时间:2019 年 3 月 22 日,星期五,下午四点。


什么是命名空间?

https://www.php.net/manual/zh/language.namespaces.rationale.php

Redis 常见数据结构的使用场景。

https://my.oschina.net/manmao/blog/688230

如何基于 Redis 设计一个秒杀系统。

把商品库存放入 Redis 队列。

了解过 JWT 吗?

https://jwt.io/

了解过 Protocol Buffers 吗?

https://developers.google.com/protocol-buffers/

在实际项目中使用过 Swoole 吗?

https://www.swoole.com/

Go 语言中的 slice 和 map 是线程安全的吗?

https://halfrost.com/go_map_chapter_one/
https://halfrost.com/go_map_chapter_two/

遇到过 TCP 粘包问题吗?如何解决。

https://crossoverjie.top/2018/08/03/netty/Netty(3)TCP-Sticky/

 447 total views

PHP Interview Questions(9)

面试时间:2019 年 3 月 22 日,星期五,下午四点。


审批流程数据库设计

https://www.cnblogs.com/yyy116008/p/8330076.html

MySQL 索引数据结构

Most MySQL indexes (PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT) are stored in B-trees. Exceptions: Indexes on spatial data types use R-trees; MEMORY tables also support hash indexes; InnoDB uses inverted lists for FULLTEXT indexes.

 b-tree 和 b+tree 的区别

B-Tree
B+Tree

非聚集索引和聚集索引的区别

MySQL MyISAM Primary Key(非聚集索引)
MySQL MyISAM Secondary Key(非聚集索引)
MySQL InnoDB Primary Key(聚集索引)
MySQL InnoDB Secondray Key(聚集索引)

参考:

https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html

http://blog.codinglabs.org/articles/theory-of-mysql-index.html

 508 total views,  1 views today

Leetcode: 3 Sum

久违的刷一发 Leetcode。

3 Sum

PHP

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer[][]
     */
    function threeSum($nums) {
        sort($nums);
        $count = count($nums);
        $result = [];
        for ($i = 0; $i < $count - 2; $i++) {
            $j = $i + 1;
            $k = $count - 1;
            while ($j < $k) {
                $sum = $nums[$i] + $nums[$j] + $nums[$k];
                if ($sum === 0) {
                    $result[$nums[$i].",".$nums[$j].",".$nums[$k]] = [$nums[$i], $nums[$j], $nums[$k]];
                    $j++;
                    $k--;
                } elseif ($sum < 0) {
                    $j++;
                } else {
                    $k--;
                }
            }
        }
        return $result;
    }
}

 491 total views

PHP Magic constants: Difference between __FUNCTION__ and __METHOD__

今天我们来比较一下两个 PHP 魔术常量:__FUNCTION__ 和 __METHOD__。

首先看一下官方文档的定义,然后再用几个简单的例子来比较。

__FUNCTION__The function name, or {closure} for anonymous functions.
__METHOD__The class method name.

1. Class 里面的方法

<?php

namespace App;

class Test {
	public static function run() {
		echo __FUNCTION__ , "\n";
		echo __METHOD__ , "\n";
                echo __CLASS__ , '::' , __FUNCTION__ , "\n";
	}
}

Test::run();
$ php Test.php
run
App\Test::run
App\Test::run

2. 函数和闭包

<?php

namespace App;

function test() {
	echo __FUNCTION__ , "\n";
	echo __METHOD__ , "\n";
}

$closure = function() {
	echo __FUNCTION__ , "\n";
	echo __METHOD__ , "\n";
};

test();
$closure();
$ php Test.php
App\test
App\test
App\{closure}
App\{closure}

3. 继承和Trait

<?php

namespace App;

class Papa {
	public static function test() {
		echo __FUNCTION__ . "\n";
		echo __METHOD__ , "\n";
		echo __CLASS__ , '::' , __FUNCTION__ , "\n";
	}
}

trait Mama
{
	public static function test() {
		echo __FUNCTION__ . "\n";
		echo __METHOD__ , "\n";
		echo __CLASS__ , '::' , __FUNCTION__ , "\n";
	}
}


class Test extends Papa {

	use Mama;

	public static function run() {
		parent::test();
		self::test();
	}
}

Test::run();
$ php Test.php
test
App\Papa::test
App\Papa::test
test
App\Mama::test
App\Test::test

总结

最后简单的总结一下:

不在 Class 里面__FUNCTION__ = __METHOD__
在 Class 里面(don‘t use trait)__CLASS__ . “::” . __FUNCTION__ = __METHOD__
在 Class 里面(use trait)只有 __METHOD__ 的结果是正确的。

所以不管什么情况,用 __METHOD__ 就对了。


参考:

http://php.net/manual/en/language.constants.predefined.php

 707 total views,  1 views today