ThinkSNS+ 基于 Laravel master 分支,从 1 到 0,再到 0.1

大家好,下了很大的决心,才决定在 Laravel China 写 ThinkSNS+ 专栏。

什么是 ThinkSNS+

好吧,这不是广告。。。在 09 年,由北京的团队开发了 ThinkSNS 涉足社交开源行业。这么多年累计不少客户(可惜,开源用户极少,都是商业用户)。

2014年,由北京团队移交开发权,在成都重组开发团队。2014-2016,两年都在维护和开发之前基于 TP 的 ThinkSNS , 慢慢的引入新开发概念,可是越是开发越感觉到无力感。终于,在2016年下半年,我们终于决定重写这个程序。抛弃之前的每一行代码。框架上,开发人员一致性的选择了 Laravel 。

并取了一个看起来像手机厂商给手机命名的名字,ThinkSNS Plus 没错就是 Plus 也就是符号 + 因为我们更希望侧重移动端。这就是 ThinkSNS+(程序员的文案,怎么莫名广告感。。。)

如何保持和 Laravel 的升级

起初没想过框架升级的问题,后来个人想了一个问题,最后会不会像之前版本一样?框架难以升级?所以我们决定每周一对 laravel/laravel 的 master 分支进行合并,为了表示对 Taylor Otwell 以及 Laravel 贡献者的尊重,每一个 commit 在合并的时候都进行了保留。

开源协议

由于 Laravel 本身是 MIT 协议,基于 Laravel 开发,我们也希望 ThinkSNS+ 能为开源社区贡献,所以代码上没有采用私有协议,而是选择了 Apache-2.0 协议进行开源。

前端工作流

这块,是一个难以选择的问题,我们希望能由内置 Laravel-Mix 的契合度,又希望构建能更适合我们的应用场景,最后,我们选择 放弃 Laravel-Mix 自己做前端构建,衍生出一个新的问题,我们由希望能和 mix 辅助函数无缝配合,看了源代码后,发现问题太简单了,就是一个 mix-manifest.json 的事情而已,但是这个东西却一波三折。

起初,我们选择在 webpack.config.babel.js 中做生成函数,配合第三方包实现,功能实现了。但是如果是拓展包接入也要使用怎么办?最后个人开发 webpack-laravel-mix-manifest 这个前端包,来生成这个文件。

拓展设计

首选,拓展设计目前由两个,分别是 plus-componentplus-plugin 其实都是由 Composer 中间插件实现。

composer 插件 zhiyicx/plus-install-plugin

plus-component

这个设计其实只是想拓展包可以快速的接入路由模板数据模型这些基础开发,也是中间插件 1.0 版本中唯一实现的拓展方式,存在了长达半年之久,可以快速的写路由、控制器、数据模型,目前我们团队出的应用拓展都是以此方式开发实现。
并封装了 php artisan component 命令安装。

plus-plugin

这是一个很年轻的 type 在 composer 插件 1.1 版本中增加的,这个拓展方式实现原理很简单,其实就是 Laravel 的 Service Provider 熟悉 Laravel 开发都知道,这个服务门面被称之为 "Laravel 拓展" 但是安装并不方便,需要先 composer require vendor/name 然后在 app.phpproviders 字段中配置,然后运行命令生成配置文件等。

考虑到 ThinkSNS+ 面向的都是站长、创业者等用户,让他们改代码?简直不如杀了他们。所以,萌生了一个想法,如何把这个步骤自动化?让用户只需要 composer require vendor/name 就完成呢?而且,对于例如广播系统的使用,很需要一个这样的东西来方便开发拓展。所以想办法把这个步骤,在 composer require 步骤完成,由此开发了这个模式。

Laravel 的拓展不能直接以这种方式使用哟,因为我们做这个的想法是把配置移交到后台配置。

接口和 SPA

接口,在初期没有完全考虑 REST ful 所以,你能会看到 URL 命名很像 REST ful 规范,实际数据却不是,后续逐步规范化。

这里提到了 API 接口,意味着一个事情,我们抛弃了传统网页,ThinkSNS+ 核心就是一个 用户中心,然后功能全部由拓展实现,目前后台、手机端 都是采用 SPA 调用接口的形式开发。


GitHub: https://github.com/zhiyicx/thinksns-plus

开源不易,为了争取开源,我们团队做了很多努力。把基于 Laravel 的作品展示在大家面前,之后专栏会持续不断的分享 ThinkSNS+ 开发过程中的技术细节。

开源是一个很容易的事情,站在公司层面,是一个很难的事情,希望大家可以为我们点个 Satr ?。

本作品采用《CC 协议》,转载必须注明作者和本文链接
Seven 的代码太渣,欢迎关注我的新拓展包 medz/cors 解决 PHP 项目程序设置跨域需求。
本帖由系统于 4年前 自动加精
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 58
medz

大家有什么问题,可以在下面问我,我会一一解答。

6年前 评论

火钳刘明,以前好像用过thinsns呢,感觉有点慢,最后还是换成discuz了。希望用新的架构的snsplus能够挑战discuz。

6年前 评论
medz

@andu 是的,以前的 ThinkSNS 很缓慢。这也是重写的原因之一。

6年前 评论

ThinkSNS 团队目前主要的盈利方式是为企业建立 SNS 平台吗

6年前 评论
medz

@MrJing 目前主要的盈利确实来自于我们服务的企业,更多的已经不是搭建 SNS 平台了,而是技术支持、解决方案的提供以及产品定制服务。

6年前 评论
leo

楼主有没有考虑过把这个拓展能力单独抽取出来,独立于ThinkSNS+?

6年前 评论

希望可以搞个 demo 站点,方便看看效果

6年前 评论
medz

@leo 其实这个抽出来也没法直接作用到 Laravel 框架上,你看加载 providers 的地方,其实是按顺序添加的,这里我为了实现这个拓展,继承了 Illuminate\Foundation\Application 然后重写了 registerCoreContainerAliases 函数实现这一拓展。

6年前 评论
medz

@徐小花 其实,不太好搞demo站,因为整个程序没有web页面,唯一有的是后台。

6年前 评论
Ryan

所以ThinkSNS+ 是一个开源SNS程序吗,讲了半天还是没搞懂是干嘛的,不太好搞demo站,因为整个程序没有web页面,唯一有的是后台。 那么搞个后台的demo?

6年前 评论
medz

@Ryan 是开源的程序,之所以不搞demo站,是因为没有pc页面,只演示后台没有意义,而且,我们是等到 SPA 开发完直接上 SPA 作为演示。pc目前正在弱化,这个 ThinkSNS+ 是只提供API的程序。

如果严格的说测试站,邀请测试的服务器 http://test-plus.zhibocloud.cn 这个应该算演示站。对于用户而言,我们的体验站已经发布了,用户下载 app 体验。后端 API部分其实本身没必要上线。

6年前 评论

改个名字说不定更好 laraSNS :satisfied:

6年前 评论
medz

@Boomdawn ?大哥,之前叫 ThinkSNS 不是因为 ThinkPHP 只是最开始和他们公司是合作商的关系而已。

6年前 评论

@medz 没有web页面 怎么不采用lumen呢 嗖嗖嗖的。。

6年前 评论
medz

@redrain 没有web,不代表没有web需求,需求是有的,因为设计了拓展模式。拓展中是无限制的。换句话说,web页面可以用拓展进行开发。其次,我们觉得 lumen 不够优秀。

6年前 评论

@medz 自从有了lumen做API我们一直用lumen,实测并发是laravel的2倍不止。 thinksns从12年开始关注,使用,从2.8一直到到现在的4.0都有关注,但是现在thinksns的社区似乎没有以前热了,希望thinskns+ 你能做得更好!

6年前 评论
medz

@redrain 感谢关注,不选择 lumen 其实是会出于多方面考虑的,而且,社区l 对 lumen 的更新热度远没有 laravel 高。而且,我们希望通过拓展尽可能的发挥 laravel 的优势。以及各方面的服务。而不仅仅是核心提供 API 而已。

6年前 评论

你好,medz 我想请问下这个项目必须php 7.0以上才可以运行吗?
你们现在该成laravel 主要是真对移动api 吗?之前用thanksns就感觉很高大上,设计 还有登录的页面做的都很好,期待你们sns做成更好的产品,我没事的时候也总看一些laravel的项目,目前没发现有用laravel做sns的项目!

6年前 评论
medz

@pszhao 环境上,我们开发 ThinkSNS+ 选择的是 php7 主要考虑的是 5.5 的 Laravel 也是 7,其次,我们希望能用抢类型的方式开发。

6年前 评论

那你们这边的laravel的版本用的是多少? 最新的5.4吗?

6年前 评论
medz

@pszhao 目前是 5.4 准确的说,是 master 分支。一旦 Laravel 把 master 更新到5.5,我们也会随之升级。

6年前 评论

谢谢大神的回复,好神速啊,热真热心

6年前 评论
medz

@pszhao 我也是刚好在线而已,

6年前 评论

php artisan component install 请问这个是怎么封装的啊? 从前没有见过
@medz

6年前 评论
medz

@Hexor 你好,请看 https://github.com/zhiyicx/thinksns-plus/b... 这里是封装 php artisan component [install|update|uninstall] packageName 命令的文件。你应该差不多能明白了。

6年前 评论

如果是用 vagrant 的环境的话, 安装 medz/plus-component-example 之后有点问题,

在 config/component_routes.php 中

<?php 
return 
array (
  'medz/plus-component-example' => '/Users/Hexor/Workspace/lookfeel/thinksns-plus/vendor/medz/plus-component-example/router.php',
);

因为实际 php 环境在 vagrant 中, 所以这个路径应该在 vagrant 中的路径, 比如

/home/vagrant/thinksns-plus/vendor/medz/plus-component-example/router.php

否则会报错.

你看这能不能用一个相对路径?

6年前 评论
medz

@Hexor 其实这种情况属于php文件系统在虚拟机中的问题,因为这个地址是有包提供给我的,基本上用的都是类似

return __DIR__.'/routes.php';

这类方法返回的,如果使用相对路径,包只能给我相对于他包的路径,然后我安装的时候还需要依赖 composer/composer 包得到 vendor 下的包路径进行设置。不知道在虚拟机中 realpath 函数的表现形式是否和魔术常量 __DIR__等表现一致,如果不一致,在包里面可以采用

return realpath('./routes.php');

的方式返回。目前测试,在真实环境以及 docker 环境都是没问题的,vagrant在开发过程中其实没想到还有这个东西。
您有vagrant环境,是否愿意测试并修复这个问题呢??

6年前 评论

@medz 好的 我下午测测

6年前 评论
medz

@Hexor 好滴,非常感谢。?

6年前 评论

感觉还是不行.

首先不论虚拟机里的表现是如何的, 因为 php artisan component install 命令只能在外部机上运行, 而一旦运行, 如果生成的是下面这种具体的路径, 那就肯定是不对的, 而且无论在外部机上怎么修改, 这个路径也不会生成为虚拟机内部的路径.

'medz/plus-component-example' => '/Users/Hexor/Workspace/lookfeel/thinksns-plus/vendor/medz/plus-component-example/router.php',

除非生成的路径不是具体的, 是用某些函数或者是其他符号组成的相对路径, 而具体路径需要在程序运行时拼出来, 才行吧.

另外无法去到虚拟机内部运行命令是因为, vagrant 虚拟机内部是没有代码文件的, 虚拟机内运行程序时, 程序代码是从外部机实时映射进虚拟机, 而在虚拟机内部运行命令是无法改变外部机的代码文件的.

最后
realpath('./routes.php');
返回是空啊

6年前 评论
medz

@Hexor 额~我不太明白了~为何程序运行在虚拟机里面,命令行却不在虚拟机里面运行?

6年前 评论

@medz 恩 应该是我之前对 vagrant 的理解有偏差, 对虚拟中的文件的更改是双向的 (也就是说在虚拟机中更改文件, 宿主中的文件也会同样发生变化), 所以只要在虚拟机中运行所有命令就可以了.

6年前 评论
medz

@Hexor 嗯~因为在我的印象中,应该在虚拟机运行命令的,举例window10 自带linux子系统,我用linux部署的程序,在cmd里面运行就会出现你描述的问题,在window10中,正确的应该是在子系统里面运行命令,所以虚拟机同理。

6年前 评论

主要是基于什么目的 自己重写了一个 Illuminate\Foundation\Application ?

6年前 评论
medz

@Hexor 没有重写,在 plus-component 中只是在 AppServiceProvider.php 增加了路由的加载项。如果你说的是 1.1 的 plus-plugin 的话,是继承 Illuminate\Foundation\Application 对加载 app.providers 的函数做了修改而已。

6年前 评论
medz

@anyuzhe 其实使用很简单,文档主要讲的是安装和一些拓展开发细节。技术分享文档暂时没有计划写。不过会在 Laravel china 持续发贴分享开发心得。

6年前 评论

@medz

问题1:

我的意思是, 现在代码中使用了一个非系统的 Zhiyi\Plus\Application::class, 使用这个的目的是什么?

因为你之前回答能否单独抽取这个功能时候, 说为了实现拓展功能必须要这样做. 我是想知道为什么必须要这样做才能实现拓展.

问题2:

由于系统中的 registerCoreContainerAliases() 方法已经注册了 app 这个 alias

'app'  => [\Illuminate\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class,\Illuminate\Contracts\Foundation\Application::class],

那么, 在系统注册了之后, 又注册了一次
$this->alias('app', \Zhiyi\Plus\Application::class);

意思是会把原来注册的覆盖? 如果不是覆盖而是同时存在的话, 那在从 container 中解析的时候, 系统会按什么样的逻辑解析出来这个 class, 是解析哪个出来呢?

6年前 评论

其实我们也想做一个类似的系统, 想要实现的效果跟你的 component 非常类似.

我们需要一种插件或者组件的功能, 在项目中能够自由的控制哪些模块被开放, 以及在不需要某个模块的时候直接 uninstall 就可以清除掉剩下的遗留文件. 这样在多个项目中就可以非常清晰的控制复用的部分, 也能减少整个项目内部功能之间的耦合性.

所以我们也在考虑是否仿照你的 component 写一个我们自己的系统, 或者直接使用你们开源的thinksns+, 我们也贡献代码, 一起完善这个项目项目. :laughing:

6年前 评论
medz

@Hexor

问题1

使用 Zhiyi\Plus\Application::class 的目的如下:

/**
     * Register all of the configured providers.
     *
     * @return void
     * @author Seven Du <shiweidu@outlook.com>
     */
    public function registerConfiguredProviders()
    {
        (new ProviderRepository($this, new Filesystem, $this->getCachedServicesPath()))
                    ->load($this->getConfiguredProviders());
    }

/**
     * Get all of the configured providers.
     *
     * @return array
     * @author Seven Du <shiweidu@outlook.com>
     */
    protected function getConfiguredProviders(): array
    {
        return array_merge(
            $this->config['app.providers'],
            $this->config['providers'] ?? []
        );
    }

同于实现 plus-plugin 可以直接使用 Laravel 的 Poviders.

问题2

$this->alias('app', \Zhiyi\Plus\Application::class); 并非覆盖 Laravel 的别名,而是把 \Zhiyi\Plus\Application::class 注入到别名列表中,按照持续运行逻辑 app()\Illuminate\Foundation\ApplicationIlluminate\Container\ContainerIlluminate\Contracts\Container\Container 在使用 app(class) 的时候都是得到 Zhiyi\Plus\Application 的单例,这个你可以看 laravel 的容器概念你就会明白了。

回复你

ThinkSNS+ 定位已经不是一个存粹的开源sns持续了,计划开发的就是一个只带有用户,其他都是拓展实现的框架系统。哈哈,你可以仿照也可以一起维护。也可以同构。

6年前 评论
medz

@Hexor 其实无论你是参考ts+自己开发,或者一起维护,都是非常好的事情。如果一起维护,非常欢迎的哟,可以加到协作者中。

6年前 评论

那区别不就是加了一个 $this->config['providers'] ?? [] 吗? 而且这个其实也是个空数组, 没有什么用啊.

我把 bootstrap/app.php 里的

$app = new Zhiyi\Plus\Application(
    realpath(__DIR__.'/../')
);

换成

$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

这样就没有使用你的 Application 了吧. 运行了一下 php artisan component install 以及 php artisan component uninstall
也没有报错啊

6年前 评论
medz

@Hexor 是的,因为你安装的拓展是 plus-component 类型,你安装的是 plus-plugin 类型,也不会报错,但是安装后不会生效。不过,今天设计了一个覆盖配置的服务,1.2的时候会修改上。

6年前 评论

之前的安装方法 貌似木有了~

6年前 评论
medz

@pszhao 在的,因为整理文档的原因,新的文档编写还没有写上去。

6年前 评论

哦哦 原来如此啊,大神真辛苦

6年前 评论
medz

@pszhao 是的,最近一直在整理文档。

6年前 评论
Luff

composer create-project zhiyicx/thinksns-plus 报错了,版本约束冲突了

file

5年前 评论
medz

@QiyueShiyi 额~能说一下您的 PHP 版本么~还有,我刚刚收到回复后,在 PHP 7.1.14 环境下试了下,是 ok 的

5年前 评论
Luff

file

5年前 评论
medz

@QiyueShiyi https://github.com/slimkit/plus/commit/376... 我提交了新的版本依赖,但是还没有发版本。至少累计 5 个后发版本。你要不试一下 :

git clone https://github.com/slimkit/plus && cd plus && composer install
5年前 评论
Luff

我又试了遍还是不行,我是在 Homestead

file

5年前 评论
medz

@QiyueShiyi 你执行 composer create-project slimkit/plus -vvv 详细错误信息答应,我看一下呢~谢谢

slimkit/plus 和 zhiyicx/thinksns-plus 是一个包,昨晚改名了?

5年前 评论
Luff

@medz 好的

5年前 评论
Luff

composer create-project zhiyicx/thinksns-plus -vvv

file

5年前 评论
medz

@QiyueShiyi 问题找到了,你是不是使用了 https://packagist.laravel-china.org 这个中国镜像?这个没有同步一些新包,导致 composer 找不到匹配的包导致的。推荐你切换到 https://pkg.phpcomposer.com

5年前 评论
Luff

OK 了,我换成了 https://packagist.phpcomposer.com 的镜像好了

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
创始人 @ Odore Inc.
文章
33
粉丝
202
喜欢
532
收藏
198
排名:23
访问:24.7 万
私信
所有博文
社区赞助商