云代码的原委

就MBaaS的腾飞,取代移动企业应用程序平台的倾向也更为引人注目。MBaaS系统为让公司能够方便快捷的开销好走应用程序,提供了不少倒客户端支持,有极度通用的REST
API,也来好移动开发者的软件开发工具确保,还有一定程度之监控与分析服务提供。而于相对比较复杂的应用程序,开发者有时无思呢无须在活动设备上运行颇复杂或者生费力或无法兑现的作业逻辑,这种求催生了云代码的发。

MaxLeap-Cloud-Code-1

Eloquent: 关联模型

云代码的愿景

想象一下,如果你想如果少量结实信息,但也不能不使往设施发送大量对象列表,或者调用大量REST
API才会到位此项工作时(比如统计汇总操作),这种操作明显会消耗而大量的拉动富和用户流量。

设想一下,如果您想使配备周期性定时完成有任务或想在后台一直运行有任务(比如资源回收废品清理),这种操作明显好不可靠,一方面用户或会见随时关闭设备上的应用,另一方面在后台一直运行有任务明确也会见耗费用户设备电量等资源,得不偿失。

想象一下,当您需要调用第三正平台API时需对方回调时遵循就有支付操作,服务提供商在开发成功后实行回调,你得依据回调结果做到后续操作以同记录到数据库被,这种操作以移动应用在从来不协调之后端服务器时也深为难就。

想象一下,你的某App应用来iOS,Android,JavaScript等大多独设施平台版本,当您新增同宗功能,同一套业务逻辑需要在有平台举行联合开发,当您改改一件功能,同样要在所有装备平台做新本子发布更新操作,如果产品迭代很迅猛那这种屡屡之操作明显会大大增加运动支付的工本以及效率,但职能倒是可能不显现得十分好。

设想一下,当某个用户注册了公的运,你得针对该用户增加部分音来用于统计,或者用户购买了使里的某某商品,你要募除订单外额外之信息,这好像在用户触发某些特定操作时会自动额外有的逻辑(Hook操作),这些Hook操作并无适用于运动端编写。

伴随移动支付,类似上面的情况差不多出产生,此时MBaaS系统提供的云代码功能就是是啊走应用量身定做的化解类似上面问题的方案,云代码的愿景就是利移动开发者彻底摆脱服务器,随心所欲的出各种活动应用程序。

MaxLeap作为同暂缓可以之MBaaS平台体系,其云代码的力量如何,是怎么样促成的,又发出怎么样加分项,接下去将为大家逐一揭晓。

简介

数据库中之表经常性的关系其它的表。比如,一个博客文章可以生出成千上万的评价,或者一个订单会干一个用户。Eloquent
使管理及搭档这些涉及转移的怪的易,并且支持多种不同类型的关联:

  • 一对一
  • 一对多
  • 多对多
  • 长距离一对几近
  • 多态关联
  • 多态多针对性大多涉及

MaxLeap云代码的功效

发矣云代码的背景愿景,那云代码需要提供的根底功用就那个显了

  • 首先得提供基础服务及框架,方便用户支出云代码
  • 说不上得提供代码托管,能非常有益于之被用户快速部署代码到云端运行
  • 末提供日志与血脉相通监控工具,能对线上代码的错误与性能特点来更多了解,以便优化自己的次序

概念关联

Eloquent 关联好像定义方法一样在 Eloquent
模型类吃开展定义。同时,它便像 Eloquent
模型自身同样也供了强有力的查询生成器。这允许涉及模型可以链式的行查询能力。比如:

$user->posts()->where('active', 1)->get();

可,在重复透彻的使关联之前,让咱事先来读书一下什么定义各种类型的涉及。

MaxLeap云代码的贯彻

一对一

一定之关联是最好基础的关系。比如,一个 User 模型可能波及一个
Phone。我们用在 User 模型上放一个 phone
方法来定义这种涉及。phone 方法应该回到一个基类 Eloquent 模型上
hasOne 方法的结果:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  /**
   * Get the phone record associated with the user.
   */
  public function phone()
  {
    return $this->hasOne('App\Phone');
  }
}

传递到 hasOne
方法的首先独参数应该是涉嫌模型的名目。一旦涉及被定义完成,我们好以
Eloquent
的动态性来走访关联模型的记录。动态性允许而看关联函数,就比如是它是概念在范中之习性一样:

$phone = User::find(1)->phone;

Eloquent 假定所涉嫌的外键是根据模型的名目的。在这前提下,Phone
模型会自动的使其具有一个 user_id
外键。如果你望修改者惯例,你可以传递第二独参数到 hasOne 方法中:

return $this->hasOne('App\Phone', 'foreign_key');

除此以外,Eloquent 也会见如外键应该在那个上层模型上有着一个匹配的
id(或者打定义之 $primaryKey)值。换句话说,Eloquent 会查询 Phone
记录着的 user_id 列所对应之用户的 id 列的笔录。如果您想关联应用
id 以外的价值,你可以传递第三只参数到 hasOne 方法来指定由定义之键:

return $this->hasOne('App\Phone', 'foreign_key', 'local_key');

概念相对的涉及

那,我们得自咱的 User 中访问 Phone 模型。现在,让我们以
Phone 模型上定义一个提到,让咱得以从 Phone 模型中做客该所属的
User。我们应用 belongsTo 方法来定义 hasOne 相对的关系:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Phone extends Model
{
  /**
   * Get the user that owns the phone.
   */
  public function user()
  {
    return $this->belongsTo('App\User');
  }
}

在方的事例中,Eloquent 将会尝试从 Phone 模型中之 user_id
字段受到匹配配查找 id 相同的 User。Eloquent
会依据所干的型的蛇形命名和 _id 来假定默认的外键名。事实上,如果当
Phone 模型上之外键不是 user_id,那么你可以传递自定义之外键名及
belongsTo 方法的第二只参数:

/**
 * Get the user that owns the phone.
 */
public function user()
{
  return $this->belongsTo('App\User', 'foreign_key');
}

倘若你的上面模型并从未行使 id
作为主键名,或者您盼属下模型关联一个两样的排列。你可传递第三独参数到
belongsTo 方法来指定上级模型表中的自定义键:

/**
 * Get the user that owns the phone.
 */
public function user()
{
  return $this->belongsTo('App\User', 'foreign_key', 'other_key');
}

1、让开发者如何支付云代码

怎么提供基础服务以及框架来好用户支出?由于用户之开发条件与善于的开支语言各种各样,比如使Java,使用NodeJs,使用Python,使用JavaScript的等等,我们提供相应的逐条开语言的底蕴云代码SDK,丰富用户的挑,降低用户支付门槛和本金,这样云代码在CloudCode
SDK基础及出就会见异常简便,这些CloudCode
SDK和MBaaS对外提供的位移SDK不同的地方在于它并无以运动装备及运行,而是以云端运行。也就是说开发者先要挑自己好的云代码SDK,比如自己生善于JAVA,所以我会选择cloud-code-java-sdk来开发自己之云代码,同时云代码SDK还要提供当地开发测试框架,总不克吃用户线上支出调试吧,本地开发本土调试好后重新配备到云端。当然为开发者重新快的开始,MaxLeap同时提供了Demo和Quick-Start项目来深受开发者重新快接触云代码。

一对多

一个一对大多之涉时因此来定义一个模型有别样随意数目的模子。比如,一个博客文章可拥有广大长达评论。就如任何的
Eloquent 关联一样,一针对几近干在 Eloquent 模型中通过艺术来进行定义:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
  /**
   * Get the comments for the blog post.
   */
  public function comments()
  {
    return $this->hasMany('App\Comment');
  }
}

难忘,Eloquent 会自动的依据 Comment
模型来判断合适的外键。依据惯例,Eloquent 会使用自模型的蛇形命名和
_id 来作为外键。所以,在这例子中,Eloquent 会假定 Comment
模型的外键是 post_id

假定涉及定义完成以后,我们可由此 comments
属性来访问有涉及的评的成团。记住,由于 Eloquent
提供了动态性,我们好本着事关函数进行走访,就比如他们是在模型中定义之习性一样:

$comments = App\Post::find(1)->comments;

foreach ($comments as $comment) {
  //
}

自然,由于拥有的干且提供了查询生成器的效果,所以若可于调用
comments
方法时继续的丰富片范围条件,你可透过链式的调用进行询问条件的增长:

$comments = App\Post::find(1)->comments()->where('title', 'foo')->first();

就像 hasOne 方法,你得通过添加额外之参数到 hasMany
方法被来重置外键和主键:

return $this->hasMany('App\Comment', 'foreign_key');

return $this->hasMany('App\Comment', 'foreign_key', 'local_key');

概念相对的关联

现今咱们可以看文章被拥有的评论了,让咱们啊评价定义一个干而其好拜它的上层文章模型。为了定义一个
hasMany 相对的涉,你要以下层模型中定义一个关联方法并调用
belongsTo 方法:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
  /**
   * Get the post that owns the comment.
   */
  public function post()
  {
    return $this->belongsTo('App\Post');
  }
}

倘涉及被定义完成,我们即便可由此 Comment 模型的 post
动态属性来搜寻到其相应的 Post 模型:

$comment = App\Comment::find(1);

echo $comment->post->title;

当方的事例中,Eloquent 会尝试从 Comment 模型中的 post_id
字段寻找和那个相对应 idPost 模型。Eloquent
会使用关联模型的蛇形命名暨 _id 来作为默认的外键。如果 Comment
模型的外键不是 post_id,你得传递一个自定义的键名到 belongsTo
方法的第二单参数:

/**
 * Get the post that owns the comment.
 */
public function post()
{
  return $this->belongsTo('App\Post', 'foreign_key');
}

只要上层模型并不曾使用 id
作为主键,或者你想当下层模型中关系其他的排,你可传递第三独参数到
belongsTo 方法中:

/**
 * Get the post that owns the comment.
 */
public function post()
{
  return $this->belongsTo('App\Post', 'foreign_key', 'other_key');
}

2、云代码如何为用户提供劳务

开发者在以云代码部署到云端后该怎么看云代码?MaxLeap的云代码是由此基础之REST
API来访问,云代码SDK负责提供Http服务对外暴露REST
API,因为根据Http可以很好的配合不同开发语言,实现跨越平台访问,当然这些API不见面直接暴露在用户眼前,用户只有由此调用MBaaS的云代码服务API才能够间接访问。

MaxLeap-cloud-code-2

多对多

大抵对准大多之干比 hasOnehasMany
关联而稍复杂一些。假如一个用户所有多独角色,而角色同时好于外的用户所共享。比如,多单用户可有管理员的角色。如果定义这种关涉,我们用定义三个数据库表:usersroles,和
role_userrole_user
表的命名是盖互关联的有数独模型数据表来依照字母逐一命名,并且表中含了
user_idrole_id 列。

大抵针对多关系需要编制一个办法调用基础 Eloquent 类 belongsToMany
方法。比如,让我们以 User 模型中定义一个 roles 方法:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  /**
   * The roles that belong to the user.
   */
  public function roles()
  {
    return $this->belongsToMany('App\Role');
  }
}

万一涉及被定义,你可经 roles 动态属性来访问用户之角色:

$user = App\User::find(1);

foreach ($user->roles as $role) {
  //
}

自然,就像其他种类的涉,你可以调用 roles 方法而链式调用查询条件:

$roles = App\User::find(1)->roles()->orderBy('name')->get();

虽如先所提到的,Eloquent
会合并两独涉模型并遵循字母逐一进行命名。当然你为堪随便的重写这个约定,你可传递第二独参数到
belongsToMany 方法:

return $this->belongsToMany('App\Role', 'role_user');

除由定义合并数据表的号之外,你吧足以经往 belongsToMany
方法传传递额外参数来自定义数据表里的键的字段名称。第三单参数是你定义在关系中范外键的称谓。第四独参数则是公如合并之范外键的称:

return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');

概念相对关联

公不过需要在互相呼应之关联模型里放置任何的方式来调用 belongsToMany
方法就足以定义相对关联。继续我们地方的用户角色示例,让咱于 Role
模型中定义一个 users 方法:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
  /**
   * The users that belongs to the role.
   */
  public function users()
  {
    return $this->belongsToMany('App\User');
  }
}

虽假设您所观看底,这个关系的定义和用户的涉及定义完全相同。因为咱们更的应用了
belongsToMany
方法,当定义相对于多对多的干时,所有常用之自定义数据表和键的挑选项都是可用的。

找寻中间表字段

碰巧使您早就了解及的。定义多针对多之涉嫌需要引入一个中间表。Eloquent
提供了几乎种植好有帮的方来与此表进行相互。比如,让咱们要我们的
User 对象关系到了很多 Role
对象。在走访这些涉及对象时,我们得透过当范上应用 pivot
属性来访问中间表:

$user = App\User::find(1);

foreach ($user->roles as $role) {
  echo $role->pivot->created_at;
}

瞩目我们取出的每个 Role 对象,都见面被自动的分配 pivot
属性。这个特性包含了一个意味着中间表的范,并且可以像其他 Eloquent
模型一样为应用。

默认的,只有模型的键会被 pivot
对象提供,如果您的中间表包含了附加的特性,你要以概念关联时指定它们:

return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');

假如你想如果中间表自动保护 created_atupdated_at
时间戳,你可于概念关联时利用 withTimestamps 方法:

return $this->belongsToMany('App\Role')->withTimestamps();

经过中间表字段过滤关系

乃可经以概念关联时用 wherePrivotwherePivotIn
方法来当回的结果遭到展开过滤:

return $this->belongsToMany('App\Role')->wherePivot('approved', 1);

return $this->belongsToMany('App\Role')->wherePivotIn('approved', [1, 2]);

3、云代码能吧用户提供怎样服务

今非昔比开发语言的底子云代码SDK其实都有所同等之效益,最要紧之凡数量存储服务,CloudCode
SDK通过包一系列REST
API来为开发者很便捷的走访基础MBaaS服务。除此之外还要供云函数、后台任务、Hook操作、消息推送、日志、安全访问、分布式计数器、分布式锁等职能。

MaxLeap-cloud-code-3

  • 数码存储服务

    由此SDK可以挺有益之采取MaxLeap的积存服务,例如对象的CRUD操作,同时并入了手机行业主流的金币系统。

  • 云函数

    运转在MaxLeap云端的函数,定义好云函数后可以通过REST
    API方式来拜会,这个API是同的。同时云函数提供白名单功能(通过界面设置),方便于另外第三着网络服务调用。

  • 后台任务

    同样是运作于MaxLeap云端的函数,对于长期运行的任务而言,后台任务非常有因此,例如与响应时间比丰富之外部网站并或分批发送推送通知。如果你当运作云函数时常常遇到过错误,则好设想采取后台任务,同时当你安排云代码后,可经过后台界面进行计划任务,你可以计划一次性任务还是周期性任务,这不单可方便管理你的后台任务,同时为会亮的寻踪你的职责状态。

  • Hook操作

    Hook用于在针对 Cloud Data
    进行其他操作时(包括新建,删除及修改)执行一定的操作。例如,我们以用户注册成功之前,可以由此beforeCreate
    Hook,来检查该是否重名。也得以当其报成功后,通过afterCreate
    Hook,向该发送一长达欢迎信息。Hook能十分好地实现与数操作相关的事情逻辑,它的优势在于,所有的政工于云端实现,而且受不同的使用/平台共享。

  • 消息推送

    在倒采用中,为每个客户端用户推送系统信息还是定制消息必不可少,通过该意义开发者可以生便捷的拿消息推送到有或指定设备及。

  • 分布式计数器/锁

    云代码在云端是一个分布式应用,提供计数器、锁相关的功力以便多个实例之间可以共享同一卖数据。

  • 日志

    供Logging功能,以便你能记录Function,Hook或者Job在运作过程遭到起的音信。

  • 命令行工具

    足便宜用户云代码项目之上传,部署,停止与本管理。

远程一针对性大多

长途一对准几近干提供了简要便捷的道通过中关联件来拜访远端的关联。比如,一个
Country 模型应该经过 User 模型可以具备众多之 Post
模型。在这个事例中,你得非常容易的就算摸索出一个国度吃的保有的篇章。让我们来拘禁一下概念这些涉及所待的表明:

countries
  id - integer
  name - string

users
  id - integer
  country_id - integer
  name - string

posts
  id - integer
  user_id - integer
  title - string

远端的 posts 并没含 country_id 列,hasManyThrough 关联好经过
$country->posts 来访问一个国的文章。为了履行是查询,Eloquent
会通过中间表 userscountry_id 来检索 posts 表中用户 ID
相匹配的记录。

今我们就明确了关联表的构造,那么让咱来当 Country
模型上定义关联:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
  /**
   * Get all of the posts for the country.
   */
  public function posts()
  {
    return $this->hasManyThrough('App\Post', 'App\User');
  }
}

传递到 hasManyThrough
方法的率先单参数是咱最终想要拜到之型,而第二独参数则是中间层的范名称。

当使用关联查询时,通常 Eloquent
会遵循外键约定。如果你要对事关的键进行打定义,你可以传递第三跟季单参数到
hasManyThrough
方法。第三个参数是中间层模型的外键名称,第四单参数是终极想要博之型中的所对应的中间层的外键,
而第五个参数则是目前型的主键:

class Country extends Model
{
  public function posts()
  {
    return $this->hasManyThrough(
      'App\Post', 'App\User',
      'country_id', 'user_id', 'id'
    );
  }
}

4、云代码该如何管理

云代码作为以云端部署之代码,MaxLeap是怎样保管它们的吧?在这项重大方面我们或许会见碰到下面这些问题:

  • 每个开发者的环境差,操作系统也非雷同,如何降低搭建各种环境的血本以及降低对操作系统的靠、降低硬件要求以及应用环境之间耦合度同时降低虚拟化消耗?
  • 治本之运用或过多,但是服务器资源就那么多,该怎么对每个应用实现虚拟化来组成利用及服务器降低资金?
  • 每个应用的最主要程度呢不比,有重度用户要强可用大性能的服务,有低度用户可能同样龙呢不见面产生几乎单请求,资源该如何分配?
  • 用户的代码部署于云端,如何管用户之施用代码安全?
  • 用户代码服务如何就高可用,出现故障该如何转移,如何好服务不间歇,新颁发之代码出现异常该如何回滚?

依据上面遇到的题目,我们管用户的云代码作为一个松耦合的单个服务,也就是现风行的微服务架构,通过docker来实现对微服务容器化,因为docker本身就是发源Paas,在MBaaS系统为生适用,我们不要也每个云代码应用被一个虚拟机来降低硬件要求与应用环境之间的耦合度,这能够大大降低虚拟化消耗,降低资金,而且docker还会也下提供一个于开到布置上线都平等的条件,非常便于管理代码的流程,让咱们得以本着云代码从开支到发布布简单可靠的控制。同时Docker隔离应用的力量大适用于用户之云代码,能给我们较通过虚拟机更好之结缘云代码应用以及服务器,基于docker,我们会吧每个不同的云代码应用创建隔离的条件,并为他们分配指定的劳务端口、内存资源等来隔断应用。

MaxLeap-cloud-code-4

以咱们看来用户每次的代码发布还是一个构建镜像并推送镜像到私服上的经过,每次代码部署都是打私服上落镜像并启动一个容器的长河,每次停止部署都是一个器皿卸载的进程,每次升级代码都是一个重转不同标签的应用镜像的历程。用户每次上传发布云代码都需要为其指定一个版,不同之版会扭转不同的镜像标签,可以而且部署多只版本,但咱开了限定,最多只能以宣布2个版,我们叫灰度发布,这是为能够让您的代码能平滑对接升级,在灰度发布过程被用户用安装版本负载均衡比重,以得服务不暂停,基于版本控制你可回滚你的代码,你可以选择而发表了之擅自版本进行布置,这实在挺有利。

MaxLeap-cloud-code-5

对于用户的云代码镜像、启动之容器、部署之国策与容器所于的宿主机我们会发生一个专门的CloudCode-Manager服务来拓展保管,我们遂之服务吗hydra(海德拉)。它希腊神话中的九头蛇,传说它们有着九颗头,其中同样颗头如是给砍断,立刻又见面特别起片发头来,在此我们寓意用户的云代码可以齐高可用,如果用户部署之其它一个云代码实例出现故障达服务不用,系统会自动在其余宿主机上再次起动一个一样实例。为了上高可用、故障转移,云代码SDK需要提供心跳接口,在用户部署云代码后各隔一段时间hydra都见面做心跳检查,检查失败重试一定次数后虽觉得该服务都失效,我们见面在其他一样令宿主机上重新部署一个和故障实例一模一样的实例,然后又推载故障实例,如果卸载故障实例失败,比如故障实例所当的宿主机发生宕机,那么该故障实例会永远成为一个孤岛实例等给挟持回收。如果使用的云代码被重度使用过负荷可以天天扩容,或者经缩容来比少资金,通过随机扩容和缩容也不怕是经配备容器任意实例数量来的确达到高可用,最常用的行使状况是合作社以做活动时有访问高峰可以快增加实例资源来减压力,日常时虽然缩减实例以低本钱运行。

透过docker来整合利用和服务器,一雅宿主机上可能部署了众独容器应用,那以是什么样分发的吧,在云代码SDK中我们提供了REST服务,比如云函数、后台任务、心跳等API,所有以之这些REST服务在启动后还是监听在容器的8080端口,容器需要允许外部看就得须要映射容器端口到宿主机,所以在使分发过程被,宿主机的端口管理好必要,我们运用mysql来储存所有宿主机的消息,包括有提供被云代码容器使用的可用端口,通过开展锁来确保端口的产出分配,启动任意云代码容器时犹见面分配一个映射端口给容器,同时于zookeeper中协同运用之云代码服务地方提供给MBaaS云代码服务应用。这个过程使用工作来确保容器启动和数据库信息的一致性,同时采取zookeeper分布式锁来严防和一个使用被同时操作。云代码服务之REST层实时监察zookeeper中云容器访问地址信息变更,通过hosting形式提供路由于功能,通过负载均衡算法选择可用地址来做客宿主机上的云代码达到疏散作用,这样虽可知不负众望简约实用的行使分发。

地方我们说交云代码容器通过端口映射来允许外部看,但考虑到用户之代码安全,并无是其他机器都得看云代码容器,这就需一个网络安全系来对用户之造访与网络展开限制。在网隔离安全方面,我们于Docker的正规化网络桥接接口docker0上启用内核防火墙iptables规则来界定Docker容器的源IP地址范围以及外面通讯,所有的云代码宿主机只能由maxleap和hydra服务所在的机械访问,而云代码访问maxleap内部服务得通过反向代理实现。

MaxLeap-cloud-code-6

以宿主机和容器中安全隔离者,通过顾控制的安全策略,使用selinux配置Linux内核安全模块,从而实现强制性的访问控制(MAC)用以将经过约束在同样模拟有限的系统资源或权限中。在容器与容器中通过cgroups防止通过耗尽系统资源引发拒绝服务(DoS)攻击,比如限制容器的CPU使用、内存以、存储使用。

多态关联

表结构

多态关联允许一个模子在么关联中起属于一个或多个其他模型。比如,想象一下下被的用户可以好文章及其评论。如果运用多态关联,那么你尽管可利用一个独的
likes 表来波及这有限只场景。首先,让咱们规定定义这种关系所需要的阐明结构:

posts
  id - integer
  title - string
  body - text

comments
  id - integer
  post_id - integer
  body - text

likes
  id - integer
  likeable_id - integer
  likeable_type - string

您待注意到的有限单以 likes 表中着重之字段 likeable_id
likeable_typelikeable_id 字段会包含文章或评论的 ID 值,而
likeable_type 字段会包含其所属的模型的类名。likeable_type 就是当访问
likeable 关联时 ORM 用来判定所属之模型是哪位项目。

型结构

继,让我们检查一下这个涉及所需要的范定义:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class like extends Model
{
  /**
   * Get all of the owning likeable models.
   */
  public function likeable()
  {
    return $this->morphTo();
  }
}

class Post extends Model
{
  /**
   * Get all of the post's likes.
   */
  public function likes()
  {
    return $this->morphMany('App\Like', 'likeable');
  }
}

class Comment extends Model
{
  /**
   * Get all of the comment's likes.
   */
  public function likes()
  {
    return $this->morphMany('App\Like', 'likeable');
  }
}

取多态关联

假定数据库表和模型都定义完成,你就是可当您的范中做客这些涉嫌。比如,你可以使用
likes 动态属性来拜访文章被持有涉的 likes 模型:

$post = App\Post::find(1);

foreach ($post->likes as $like) {
  //
}

汝啊得由此当模型上调用提供 morphTo
的措施来获得多态模型其关系所有者。在上头的例子中,指的哪怕是 Like
模型中之 likeable
方法。所以,我们得以像下动态性一样用方式来展开访问:

$like = App\Like::find(1);

$likeable = $like->likeable;

Like 模型的 likeable 关联将会见回到一个 Post 或者 Comment
实例,这在该所属者的类。

自从定义多态类型

默认的,Laravel
会使用包了限定类名来囤所涉及模型的种类。比如,上面的例子中 Like
可以属于 Post 或者 Comment。默认的 likeable_type 应该是 App\Post
或者
App\Comment。事实上,你可能要打您的应用程序的内部结构分离数据库。在是例子中,你可以定义一个涉嫌的多态映射来点
Eloquent 使用模型关联的表名称来替代类名:

use Illuminate\Database\Eloquent\Relations\Relation;

Relation::morphMap([
  App\Post::class,
  App\Comment::class,
]);

还是,你可以指定一个自定的字符串与每个模型进行关联:

use Illuminate\Database\Eloquent\Relations\Relation;

Relation::morphMap([
  'posts' => App\Post::class,
  'likes' => App\Like::class,
]);

而可以当你的 AppServiceProvider 或者一个别离之服务提供者的 boot
方法被登记你的 morphMap

5、云代码该怎么监督

行使微服务容器化云代码能为下开发者省去部署及护卫方面的负,但代价是早晚水准达到削弱了线及环境之透明性,为了能针对线达代码的一无是处和特性特点来重复多了解以便优化自己的代码或者扩容、缩容来达成水平扩展,我们用为老好的监察云代码。

MaxLeap-cloud-code-7

1、首先是日记信息之集,云代码的系统日志、用户之日志这些还急需募起来提供给用户查看,MaxLeap的云代码使用主流的Logstash+elasticsearch来完成日志收集工作,我们会以列台宿主机上启动一个logstash-forwarder服务作为shipper来收集指定的云代码日志,Logstash汇聚日志后转发到ES存储。

2、其次是对容器资源的督查,Docker容器通过namespace做资源隔离,通过cgroup来开资源限制,我们有个专门的docker-monitor服务来监督有宿主机上云代码容器的指标,它会周期性获取已报的宿主机上所有云代码容器的cgroup
stats,收集指标包括CPU MEM IO等,然后拿数据PUSH到ES里。

3、最后是亮受用户,MaxLeap通过后台界面的方展示起具有容器实例的性及状态,还有配备的云代码版本有的日记信息,用户可生直观的垂询及好的云代码有啊错的信息,在什么地方产生瓶颈,该于哪方优化代码。而我辈其中会通过Kibana来显示,并经过Nagios来报警。

多态多对几近涉及

表结构

除外习俗的多态关联,你也可定义多对准几近之多态关联。比如,一个博客的
PostVideo 模型应该好共享一个多态关联的 Tag
模型。使用多对多的多态关联好允许而的博客文章与视频能共享独特标签的么列表。首先,让咱来拘禁一下说明结构:

posts
  id - integer
  name - string

videos
  id - integer
  name - string

tags
  id - integer
  name - string

taggables
  tag_id - integer
  taggable_id - integer
  taggable_type - string

型结构

跟着,我们来定义模型中的干。PostVideo 模型将都见面蕴藏调用基础
Eloquent 类的 morphToMany 方法的 tags 方法:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
  /**
   * Get all of the tags for the post.
   */
  public function tags()
  {
    return $this->morphToMany('App\Tag', 'taggable');
  }
}

概念相对的关联

接着,在 Tag
模型中,你应当吗拥有涉模型定义相应的方。所以,在斯例子中,我们以定义
posts 方法和 videos 方法:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
  /**
   * Get all of the posts that are assigned this tag.
   */
  public function posts()
  {
    return $this->morphedByMany('App\Post', 'taggable');
  }

  /**
   * Get all of the videos that are assigned this tag.
   */
  public function videos()
  {
    return $this->morphedByMany('App\Video', 'taggable');
  }
}

取得涉及

当定义完成数据表和模型之后,你就是得经模型来访问那干。比如,你得略的动
tags 动态属性来访问文章的装有标签模型:

$post = App\Post::find(1);

foreach ($post->tags as $tag) {
  //
}

君呢得以经走访模型中提供执行 morphedByMany
方法的主意来获取涉及模型的所属模型。在点的事例中,就是 Tag 模型上之
posts 或者 videos 方法。所以,你可像动态性一样看这些方法:

$tab = App\Tag::find(1);

foreach ($tag->videos as $video) {
  //
}

MaxLeap云代码的衍生-云容器

起客户看到此间说:你说了那么多,我就是勿思就此你的云代码SDK来写,熟悉而的SDK都使消费好长时间,用看官方文档头都非常了,我就是想就此干项目数据库,我哪怕想用自身自己写的后端服务要之前公司现已写好的次,咋办?嘿,MBaaS系统的愿景是于用户完全摆脱服务器,但遇到这种既来和好服务器和数据库并大方线及以的客户于他们选择MBaaS系统即得过细勘察是否值得了。考量到这类似需求,MaxLeap在云代码的基本功及衍生出了云容器的概念,它是好协助用户部署及运维其后端应用程序的代码托管服务,用户只待提供劳动端的业务逻辑,包括静态网站或动态应用程序,而服务端的胜可用、多实例、负载均衡、不停顿服务之坦升级当还是因为云容器提供支持。没错,云代码有的效益它都得生出,云代码没有的功力它吧发出,一个是数据源功能,很多铺客户内使用的数据库都是mysql这种涉及项目数据库,让她们瞬间切换到MBaaS上的NoSql数据库会生无放心,特别对事情要求大严格的工作逻辑,人家可能一看到你的数据库是应用Nosql就放弃了,能杀有利的迁徙也颇,就是这般一直,云容器的数据源功能虽然会支援于他们放下很十分一些担心,它好给用户以并管理自己之涉嫌项目数据库,而任何一个二级域名功能可以叫用户在布局云容器后好一直看他的谈话服务。作为云代码的晋级版本,云容器的底部架构都是冲云代码的实现,这完全降低了用户Dev&Ops上之难度。由于篇幅由,更多云容器相关的音信本篇文章不再赘述了。

波及查询

鉴于负有的 Eloquent
关联类型且是经措施定义的,所以你得调用这些方法来博所关联的型的实例而随便需实际的推行关联查询。另外,所有的
Eloquent
关联呢都提供了询问生成器服务,这允许你可以持续的链式执行查询操作。

本,想象一下博客系统中 User 模型拥有许多 Post 关联的模子:

<?ph

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
  /**
   * Get all of the posts for the user.
   */
  public function posts()
  {
    return $this->hasMany('App\Post');
  }
}

若得查询 posts 关联的还要添加一些外加的查询约束:

$user = App\User::find(1);

$user->posts()->where('active', 1)->get();

君应当小心到了,你可当关乎中采用外的询问生成器的主意。

涉方法 Vs. 动态性

比方你莫待以开展 Eloquent
关联查询时加加额外的羁绊,你可大概的如它的属性一样进行访问。比如,我们延续应用
UserPost 示例模型。我们得像这样来拜访用户之所有文章:

$user = App\User::find(1);

foreach ($user->posts as $post) {
  //
}

动态性是惰性加载的,这象征当你其实访问他们事先,其涉嫌数据是无会见加载的。正因为如此,开发的时节一般采用预加载来进展加载一些将以的干模型。预加载要求要加载一个型的涉嫌,这行之减少了查询的次数。

询问关联是否存在

当访问一个模型的记录时,你恐怕会见想基于关联的记录是否存在来对结果开展界定。比如,想象一下而希望获得最少有同样修评论的博客文章。你得传递关联的称呼到
has 方法来做这些:

// Retrieve all posts that have at least one comment...
$posts = App\Post::has('comments')->get();

卿呢得以指定操作符,和数码来一发定制查询:

// Retrieve all posts that have three or more comments...
$posts = Post::has('comments', '>=', 3)->get();

公啊得采用 . 语法来布局嵌套的 has
语句子。比如,你可以赢得有包含至少一条评论与投票的稿子:

// Retrieve all posts that hava at least one comment with votes...
$posts = Post::has('comments.votes')->get();

若果你待再胜似之支配,你可以下 whereHasorWhereHas 方法来当
has 查询中插入 where
子句子。这些措施允许而呢涉进行打定义的格查询。比如检查评论的始末:

// Retrieve all posts with at least one comment containing words like foo%
$posts = Post::whereHas('comments', function ($query) {
  $query->where('content', 'like', 'foo%'); 
})->get();

统计关联结果

假定您盼统计关联的结果如果休实际的加载它们,你得用 withCount
方法,这将于你的结果模型中补充加 {relation}_count 列。比如:

$posts = App\Post::withCount('comments')->get();

foreach ($posts as $post) {
  echo $post->comments_count;
}

而也可以招来多单涉及的统计,以及长询问约束:

$posts = Post::withCount(['votes', 'comments' => function ($query) {
  $query->where('content', 'like', 'foo%');
}])->get();

echo $posts[0]->votes_count;
echo $posts[0]->comments_count;

MaxLeap云代码的展望

看样子就我们发现MaxLeap的云代码、云容器的架构基本还是环绕docker容器这个生态圈来贯彻之,那么什么样还好的护卫及优化是生态圈将是我们前的基本点,在此处我们吃起一部分咱们前途一段时间将要实现与优化的要紧信息:

MaxLeap-cloud-code-8

  • 有容器资源通过Mesos申请
  • 所有容器生命周期通过Marathon管理
  • 更智能的资源分配机制,更智能的下压力监控落实机关扩容/缩容
  • 用户云代码托管方支持git等第三正在仓库
  • 用户达传云代码、云容器支持增量达到传播减少等候时
  • 重复多容器安全地方的优化
  • 再也多提代码/容器操作的Dev&Ops自动化
  • 再多基建架构方面的调优化

MaxLeap更强有力又可以之云代码/云容器服务请大家希望。


连锁阅读:
移步称平台的基础架构之一起-云应用篇

作者系力谱宿云 LeapCloud 团队_谈服务研发成员:David Young【原创】
力谱宿云首发地址:https://blog.maxleap.cn/archives/942

预加载

当通过性能访问 Eloquent
关联时,该干的数会叫推加载。这代表该干数据只有以你真正的造访属性时才见面进行加载。事实上,Eloquent
可以于上层模型中一次性预加载的。预加载有效避免了 N + 1
的探寻问题。要说明 N + 1 找问题,我们可来拘禁一个 Author 关联 Book
的示例:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
  /**
   * Get the author that wrote the book.
   */
  public function author()
  {
    return $this->belongsTo('App\Author');
  }
}

本,让咱找所有的书与她们之撰稿人:

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

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

以此循环会执行同样差找回有的图书,接着每本书会运作一软寻作者的操作。所以,如果我们具备
25 本书,那么循环将会开展 26 次查询:1 次查询所有的图书,25
次查询相关书籍的作者。

死幸运的,我们好采取预加载来将查询有效之支配在 2 次。当查问时,使用
with 方法来指定关联的预加载:

$books = App\Book::with('author')->get();

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

对此这个操作,只会履两单查询:

select * from books

select * from authors where id in (1, 2, 3, 4, 5, ...)

预加载多只关系

奇迹你或许用以一个操作着预加载多个事关,你仅仅需要传递额外的参数到
with 方法被尽管可以:

$books = App\Book::with('author', 'publisher')->get();

嵌套的预加载

而可采取 . 语法来加载嵌套的关联。比如,让咱们当一个 Eloquent
语词被平等赖加载所有图书的撰稿人和作者的僵尸通讯簿:

$books = App\Book::with('author.contacts')->get();

预加载约束

偶你可能希望预加载一些涉及,但是也需对预加载查询指定额外的格,这里发出个示范:

$users = App\User::with(['posts' => function ($query) {
  $query->where('title', 'like', '%first%');
}])->get();

于此事例中,Eloquent 会值预加载文章的 title 列包含 first
单词的记录。当然,你吗得以调用其他查询生成器可用之计:

$users = App\User::with(['posts' => function ($query) {
  $query->orderBy('created_at', 'desc');
}])->get();

推预加载

奇迹你可能需要在上层模型被抱后才预加载其涉嫌。当你需要来动态控制是否加载关联模型时尤其有效:

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

if ($someCondition) {
  $books->load('author', 'publisher');
}

假若你得对预加载做有询问约束,你得传递 Closureload 方法:

$books->load(['author' => function ($query) {
  $query->orderBy('published_date', 'asc');
}]);

插入关系模型

Save 方法

Eloquent 提供了有利的章程来吗模型加上一个关联。比如,也许你得为 Post
模型新增一个 Comment。除了手动的装 Commentpost_id
属性,你为可一直以关系模型中调用 save 方法来插入 Comment:

$comment = new App\Comment(['message' => 'A new comment.']);

$post = App\Post::find(1);

$post->comments()->save($comment);

顾点我们连从未应用关联模型的动态性之方法来访问
comments,而是下 comments 方法的花样来取涉及模型的实例。save
方法会自动的丰富对应的 post_id 值到新的 Comment 模型上。

使您要同糟补充加多单涉及模型,你得用 saveMany 方法:

$post = App\Post::find(1);

$post->comments()->saveMany([
  new App\Comment(['message' => 'A new comment.']),
  new App\Comment(['message' => 'Another comment.']),
]);

Save & 多对大多涉及

当及多针对性多关系互动时,save
方法接收一个中间层表属性的附加参数数组作为第二独参数:

App\User::find(1)->roles()->save($role, ['expires' => $expires]);

Create 方法

除了 savesaveMany 方法之外,你也可使用 create
方法,它好接受属性组成的多次组,创建一个型并且以该储存到数据库。这无异次于,save
create 方法的界别是 save 接收一个总体的 Eloquent 模型实例,而
create 接收的凡一个原生的 PHP array:

$post = App\Post::find(1);

$comment = $post->comments()->create([
  'message' => 'A new comment.',
]);

在使用 create 方法之前,你应该保证已经读了性之
批量赋值文档。

更新从属于涉模型

当更新一个 belongsTo 关联时,你应有运用 associate
方法。这个方法会在下层模型中安装外键:

$account = App\Account::find(10);

$user->account()->associate($account);

$user->save();

当删除 belongsTo 关联时,你当下 dissociate
方法,该方法会重置下层模型所涉及的外键:

$user->account()->dissociate();

$user->save();

大多针对几近涉及

附加 / 抽离

当以多针对性大多涉及时,Eloquent
提供了一些分外的援助方法来更便民的保管涉及模型。比如,让我们想像一下用户可发好多角色以角色可以产生好多用户。你可行使
attach 方法来附加一个角色到用户以于中间表中进入这条记下:

$user = App\User::find(1);

$user->roles()->attach($roleId);

当附加关联到模型时,你也可传递一个饱含额外数据的数组来以那个补充加至中间表中:

$user->roles()->attach($roleId, ['expires' => $expires]);

本,有时候你可能用从用户中除去一个角色。你得运用 detach
方法来删除多对准几近干的记录。datech
方法将由中间表中去除相应的记录。但是,除了中间表,其它少只模型的记录还还会见为保留:

// Detach a single role from the user...
$user->roles()->detach($roleId);

// Detach all roles from the user...
$user->roles()->detach();

为了更的便利,attachdetach 也得以吸纳 IDs
所组成的数组作为输入:

$user = App\User::find(1);

$user->roles()->detach([1, 2, 3]);

$user->roles()->attach([1 => ['expires' => $expires], 2, 3]);

履新中间表的记录
设若您要更新中间表中留存的履行,你可行使 updateExistingPivot 方法:

$user = App\User::find(1);

$user->roles()->updateExistingPivot($roleId, $attributes);

便民之共

卿吗可以动用 sync 方法来构建多针对几近的关系。sync 方法接收放置中间表
IDs 所组成的数组。任意 IDs
如果没在所加的数组中,那么该用会见自中间表中展开删减。所以,在操作完以后,只有有为吃定数组里的
IDs 才见面满怀在于中间表中:

$user->roles()->sync([1, 2, 3]);

公也可同时传递额外的中间表的键值对:

$user->roles()->sync([1 => ['expires' => true], 2, 3]);

联动上层模型时穿

当一个模型 belongsTo 或者 belongsToMany 另外一个模子时,比如
Comment 从属于
Post,这对下层模型更新时同时要求更新上层模型的时戳时很有帮。比如,当
Comment 模型更新了,你想只要自行的换代其所属的 Post 模型的
updated_at 时间戳。Eloquent
使之移的非常容易。你就需要在下层模型中上加一个 touches
属性来含有关联的称即使足以了:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
  /**
   * All of the relationships to be touched.
   *
   * @var array
   */
  protected $touches = ['post'];

  /**
   * Get the post that the comment belongs to.
   */
  public function post()
  {
    return $this->belongsTo('App\Post');
  }
}

现,当你更新 Comment 时,其所属的 Post 将见面同时更新 updated_at
列:

$comment = App\Comment::find(1);

$comment->text = 'Edit to this comment!';

$comment->save();