从头开始构建PHP SaaS应用: PHP SaaS的基本原理

@高效码农  January 11, 2020

2020-01-10T03:28:50.png

第1部分:创建您的应用

我们尝试了解SaaS架构。每个应用程序均由两部分组成:代码和数据。现在,每个客户都有最终用户。数据是在这些最终用户之间共享的,(大多数情况下)不与其他客户端的最终用户共享。因此,(每个客户端的)每组最终用户都应访问另一组数据。在大多数情况下,所有客户端使用的代码可以相同。

现在可以通过多种方式设计SaaS应用程序:


选项1 –单一数据库,单一代码库

使用单个数据库,并将所有客户端数据存储在单个数据库中。您将必须在所有表中添加一个字段,例如“ clientid”,并修改所有SQL查询以选择正确的“ clientid”。如果您已经有一个租户应用程序,则需要对代码进行大量修改。

优点:易于管理数据库和更新;没有重复。
缺点:如果您错过了SQL查询中的“ clientid”,则可能导致另一个客户端出现问题。

选项2 –多个数据库,单个代码库

为每个客户端创建一个单独的数据库。无需修改您现有的单租户代码库。您只需要修改配置文件即可根据客户端选择数据库。

优点:很少修改代码库,易于确保不会混淆客户端数据。
缺点:需要管理多个数据库,因此,在更新数据库架构时,您将必须更新每个数据库。

选项3 –多个数据库,多个代码库

创建一个单独的数据库,并为每个客户端复制完整的代码。完全不需要修改。

优点:无需修改代码库,易于确保客户端数据不会混合,易于执行客户端特定的修改。
缺点:要管理多个数据库/代码,因此,如果数据库模式/代码更新,则必须为每个客户端手动更新。

本教程将坚持选择2。

如果您已经有一个应用程序,则只需修改配置文件,如下所示。如果不这样做,请确保您的配置文件如下所示,并且您可以随心所欲地使用该应用程序的其余部分。

让我们从PHP部分开始。理想情况下,您应该使用Symfony或Zend之类的框架来创建您的应用程序。为简化起见,我只讨论config.php:

这是一个简单的标准config.php文件的样子:(通常,数据库连接不是其中的一部分,但是为了更清楚的说明,我已经添加了它)

<?php
 
define('DB_SERVER','localhost');
define('DB_PORT','3306');
define('DB_USERNAME','root');
define('DB_PASSWORD','password');
define('DB_NAME','dummyapp');
 
$dbh = mysql_connect(DB_SERVER.':'.DB_PORT,DB_USERNAME,DB_PASSWORD);
if (!$dbh) {
    echo "Oops! Something went horribly wrong.";
    exit();
}
mysql_selectdb(DB_NAME,$dbh);

在上面的代码中,当用户访问PHP页面时,它将调用config.php,该文件存储数据库配置并连接数据库。然后,其余的PHP文件(称为此配置文件)可以连接到DB。

上面的代码中的问题是它是为单个客户端(具有一组最终用户)构建的。我们需要修改此代码,以便为每个客户端使用不同的数据库。因此,根据应用程序的调用方式(即取决于URL),我们将连接到其他数据库。如果您在线查看SaaS应用程序,则会发现它们为每个客户端分配了唯一的子域。这项技术将派上用场。

因此,如果您的站点是mydummyapp.com,则当客户端注册时,将为他分配一个URL,例如anantgarg.mydummyapp.com,yourname.mydummyapp.com等。现在,客户端的所有最终用户都将连接到同一子站点-域。

为了使我们的应用程序对SaaS友好,我们需要检查子域,然后相应地连接到数据库。我们将执行以下检查:

1.让最终用户使用* .mydummyapp.com(下一篇文章中的DNS配置)访问该应用程序。
2.检查中心表是否已注册该子域;如果是,给谁?然后获取数据库详细信息
3.将最终用户连接到客户端的数据库

这是修改后的config.php

<?php
 
$data = explode('.',$_SERVER['SERVER_NAME']); // Get the sub-domain here
 
// Add some sanitization for $data
 
if (!empty($data[0])) {
    $subdomain = $data[0]; // The * of *.mydummyapp.com will be now stored in $subdomain
}
 
// Contact a central database (which stores information about all clients
 
define('SITE_DB_SERVER','localhost');
define('SITE_DB_PORT','3306');
define('SITE_DB_USERNAME','root');
define('SITE_DB_PASSWORD','password');
define('SITE_DB_NAME','dummysite');
 
$sitedbh = mysql_connect(SITE_DB_SERVER.':'.SITE_DB_PORT,SITE_DB_USERNAME,SITE_DB_PASSWORD);
 
// Get client's DB details (make sure $subdomain is already sanitized)
 
$sitemysql = mysql_query('select id,dbusername,dbpassword from clients where subdomain = '.$subdomain.');
$appdata = mysql_fetch_row($sitemysql);
 
// You can add caching code here to skip the above DB call
 
if (empty($appdata['id'])) {
    // If the client does not exist i.e. the end-user types the wrong sub-domain
 
    echo "Oops! Sorry, we are unable to find you! Please email us at support@mydummyapp.com";
    exit();
}
 
define('DB_SERVER','localhost');
define('DB_PORT','3306');
define('DB_USERNAME',$appdata['dbusername']);
define('DB_PASSWORD',$appdata['dbpassword']);
define('DB_NAME','dummyapp_'.$appdata['id']);
 
$dbh = mysql_connect(DB_SERVER.':'.DB_PORT,DB_USERNAME,DB_PASSWORD);
if (!$dbh) { exit(); }
 
mysql_selectdb(DB_NAME,$dbh);
 
// Success! Now we can continue to use the app as-is!

如果要修改现有的应用程序,则只需修改配置文件并使它类似于上述内容。该应用程序的其余部分无需进行任何修改(只要您不保存任何文件)。如果您有文件,则必须修改文件上传代码并添加一个文件夹,例如/ uploads / $ subdomain / $ filename。

如果要在localhost上进行测试,则只需将以下内容添加到hosts文件:

127.0.0.1      test.xugj520.cn
127.0.0.1      test2.xugj520.cn

第2部分:创建您的SaaS网站

我假设您可以使用用户注册创建一个简单的SaaS网站。在注册页面上,您需要输入以下内容:

Username: _ _ _ _ _ _ _ _
Password: _ _ _ _ _ _ _ _
Subdomain: _ _ _ _ _ _ _ _ (.mydummyapp.com): 

您将需要使用称为“客户端”的表创建一个公共数据库(例如,虚拟站点)。在您的实际网站中,您还将需要其他表格,例如“订阅”,其中包含付款信息。

create table clients (
  id int default 0 auto_increment,
  username varchar(50),
  password varchar(255),
  subdomain varchar(50),
  dbusername varchar(50),
  dbpassword varchar(50)
)

现在,对于在您的网站上注册的每个客户,您都必须在上表中添加一个条目。您还必须创建随机的dbusername和dbpassword。最后,您需要为此客户端创建一个新的数据库。
该PHP代码将是:

// Connect to database instance (which stores all app DBs)
$dbh = mysql_connect(DB_SERVER.':'.DB_PORT,DB_MASTERUSERNAME,DB_MASTERPASSWORD);
 
// Create DB ($id will have value of client's inserted ID)
mysql_query("CREATE DATABASE mydummyapp_".$id."",$dbh) or die(mysql_error());
 
// Create user and grant all privileges for the above DB
mysql_query("GRANT ALL ON mydummyapp_".$id.".* to  ".$dbusername." identified by '".$dbpassword."'",$dbh) or die(mysql_error());

完成此操作后,您应该能够将所有内容放在一起,并启动并运行您的第一个SaaS应用程序。

第3部分:将所有内容放在一起

网站结构如下:

www.mydummyapp.com:SaaS站点(客户端在其中注册)

  • .mydummyapp.com:SaaS应用程序(全部指向实际应用程序)

工作流程如下:

1.客户端访问www.mydummyapp.com
2.客户端在站点上注册
3.站点为客户端创建一个DB(和用户)(并在站点的DB中添加条目)
4.然后,客户端使用供他本人和最终用户使用的新URL(即clientsubdomain.mydummyapp.com)
5.最终用户直接访问clientsubdomain.mydummyapp.com,这基本上是使用客户端数据库的应用程序



评论已关闭

  1. Iven

    谢谢大佬的分享。

  2. Iven

    很清晰,易懂。