composer install update 报错需要 vendor autoload.php

先说一下背景。这些天在整一些laravel底层架构。今天composer update了某个包,报错。因为是实验性的,所以也没怎么注意,删掉vendor重新install一下呗。转念一想,顺便把composer.lock也重新构建一下吧。

然后。

就嗝屁了。

Warning: require(vendor/autoload.php): failed to open stream: No such file or directory in 

总之得出来的一个教训就是,composer.lock和vendor不能同时删除。

也找到了之前一个配置谜之被删的原因了:Remove-pre-update-cmd

参考资料


转载 | Alpine Linux,一个只有5M的Docker镜像

Alpine Linux Docker镜像基于Alpine Linux操作系统,后者是一个面向安全的轻型Linux发行版。不同于通常Linux发行版,Alpine Linux采用了musl libc和busybox以减小系统的体积和运行时资源消耗。在保持瘦身的同时,Alpine Linux还提供了自己的包管理工具apk,可以在其网站上查询,或者直接通过apk命令查询和安装。

Alpine Linux Docker镜像也继承了Alpine Linux发行版的这些优势。相比于其他Docker镜像,它的容量非常小,仅仅只有5M,且拥有非常友好的包管理器。

下表是一些官方镜像的大小:

镜像名称 大小(MB)
ubuntu:latest 187.9
debian:latest 125.1
centos:latest 196.6
alpine 4.794

除了小,Alpine镜像的另外一大优势就是内置完整包管理器。相较于其他微型基础镜像(如busybox,基础镜像大小为1.113MB),拥有一个包管理器,可以快速构建应用镜像。例如这个dnsmasq镜像,Dockerfile非常简单,仅仅运行了Alpine提供的apk工具安装了dnsmasq包即可:

FROM alpine:3.2
RUN apk -U add dnsmasq
EXPOSE 53 53/udp
ENTRYPOINT ["dnsmasq", "-k"]

使用

由于Alpine Linux有完整的包管理器,其使用方式和其他的基础镜像类似,直接使用其包管理命令apk即可。

如README中例子,如果需要安装一个mysql客户端,只需要创建如下Dockerfile:

FROM gliderlabs/alpine:3.3
RUN apk add --no-cache mysql-client
ENTRYPOINT ["mysql"]

然后通过docker build命令,即可构建出自己的mysql客户端。同样,基于Alpine Linux构建出来的镜像,有其空间上的巨大优势:

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
alpine/mysql        latest              edf988b8f4c8        58 seconds ago      35.74 MB

争论

对于Alpine Linux,Hacker News上争论还是比较激烈的。

首先是空间占用问题,小是Alpine Linux的最大优势,但是Docker的文件系统可以进行分层缓存,对于已经构建或者拉取过镜像的机器来说,每次的增量更新内容可能并不会很多。也就是说,如果所有镜像都使用相同的基础镜像,这个镜像在所有机器上都只会拉取一遍。

另外,Alpine Linux使用了musl,可能和其他Linux发行版使用的glibc实现会有所不同。在容器化中最可能遇到的是DNS问题,即musl实现的DNS服务不会使用resolv.conf文件中的search和domain两个配置,这对于一些通过DNS来进行服务发现的框架可能会遇到问题。

总结

Alpine Linux,一个只有5M的Docker镜像,它尽可能的简化了镜像的大小,易于分发,有着完善的包管理器和预编译的包。如果你需要一个干净、简洁的容器,开始尝试使用吧!

转载自 infoQ


Linux 命令之basename、dirname

basename命令用于去掉文件名的目录和后缀,dirname命令用于截取目录

path dirname basename
“/usr/lib” “/usr” “lib”
“/usr/” ”/” “usr”
“usr” ”.” “usr”
”/” ”/” ”/”
”.” ”.” ”.”
”..” ”.” ”..”

语法

basename String [ Suffix ]
dirname [ Option ] Name

basename 命令读取 String 参数,删除以 /(斜杠) 结尾的前缀以及任何指定的 Suffix 参数,并将剩余的基本文件名称写至标准输出。dirname则相反。

代码实例

#!/bin/sh  
  
# 跳转到脚本所在目录  
cd $(dirname "$0") || exit 1  
// cd `dirname $0`

man文档

basename

NAME
       basename - strip directory and suffix from filenames

SYNOPSIS
       basename NAME [SUFFIX]
       basename OPTION... NAME...

DESCRIPTION
       Print NAME with any leading directory components removed.  If specified, also remove a trailing SUFFIX.

       Mandatory arguments to long options are mandatory for short options too.

       -a, --multiple
              support multiple arguments and treat each as a NAME

       -s, --suffix=SUFFIX
              remove a trailing SUFFIX; implies -a

       -z, --zero
              end each output line with NUL, not newline

       --help display this help and exit

       --version
              output version information and exit

EXAMPLES
       basename /usr/bin/sort
              -> "sort"

       basename include/stdio.h .h
              -> "stdio"

       basename -s .h include/stdio.h
              -> "stdio"

       basename -a any/str1 any/str2
              -> "str1" followed by "str2"

dirname

NAME
       dirname - strip last component from file name

SYNOPSIS
       dirname [OPTION] NAME...

DESCRIPTION
       Output each NAME with its last non-slash component and trailing slashes removed; if NAME contains no /'s, output '.' (meaning the current directory).

       -z, --zero
              end each output line with NUL, not newline

       --help display this help and exit

       --version
              output version information and exit

EXAMPLES
       dirname /usr/bin/
              -> "/usr"

       dirname dir1/str dir2/str
              -> "dir1" followed by "dir2"

       dirname stdio.h
              -> "."

php 报错 date default timezone get

今天在使用satis生成网页

php bin/satis build satis.json public/

报了如下的错误:

[Twig_Error_Runtime]
An exception has been thrown during the rendering of a template ("date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone.").

[ErrorException]
date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. 

解决方法:

修改php.ini配置文件(我的路径为C:\my_pp\php\php-5.5.30-nts-Win32-VC11-x64\php.ini)

在php.ini配置文件中找到: ;date.timezone =

date.timezone = "Asia/Shanghai"

修改完后,重启apache/nginx。


使用 laravel 的 queryScope 处理 relations

本文是 Laravel scope 的两个应用技巧。在官方文档 5.1 的文档中给出的是这样的描述。

全局作用域(Global Scopes)可让你定义有限制的共用集合,它可以轻松地在你的应用程序中被重复使用。例如,你可能需要频繁地获取所有被认为是「受欢迎的」用户。要定义此范围,则可以简单地在 Eloquent 模型方法前面加上前缀 scope. 它总是返回查询构造器的实例.

scope 的便利之处在于在繁杂的数据中确定出数据间的逻辑关系。在简单的应用中,按照官方文档,scope 已经很好满足了我们的要求了。在下面的例子中,我在 trait 中定义了一系列具有共性的 scope:

namespace App\Supports;

use Carbon\Carbon;

trait ScopeTrait
{
    /**查询创建时间
     * 使用 prefix 是历史原因使用了 leftjoin.
     * @param $query
     * @return mixed
     */
    public function scopeCreatedAt($query, $start = '', $end = '', $equal = true)// start <= target < end
    {
        $className = get_class($this);
        $prefix = $className::TABLE . '.';
        if ($start) {
            $compare = $equal ? '>=' : '>';
            $query->where($prefix .'created_at', $compare, $start);
        }
        if ($end) {
            $query->where($prefix .'created_at', '<', $end);
        }
        return $query;
    }
    
    public function scopeSource($query, $source)
    {
        $className = get_class($this);
        $prefix = $className::TABLE . '.';
        if ($source) {
            $query->where($prefix . 'source', '=', $source);
        }
        return $query;
    }

    public function scopeYesterday($query)
    {
        $start = Carbon::yesterday();
        $end = Carbon::today();
        return $query->createdAt($start, $end);
    }
}

我们通过这个方法查询某个时间段内表的有效数据。假定 Account 表中使用了这个 trait,需要查找昨天创建的帐号,可以这么使用:

$accounts = Account::yesterday()->get();

在 laravel Eloquent ORM 中还经常用到 with 这一方法来关联表。普通的使用场景也很简单,例如

class Talent{
    public function account()
    {
        return $this->belongsTo('App\Models\Account', 'account_uuid');
    }
}

使用 Talent::with(‘account’) 就可以获取到关联数据。如果希望leftjoin,可以在行内使用如下语句实现:

$yesterdayCreateTalent = Talent::with(['account' => function ($q) {
  $q->yesterday();
}])->get();

也可以拆分方法进行使用。

// Talent
public function test()
{
   return $this->belongsTo('App\Models\Account', 'account_uuid')->yesterday();
   // or
   // return $this->account()->yesterday();
}

参考资料