使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

   2016-10-17 0
核心提示:系列内容:此内容是该系列 2 部分中的第 # 部分: 使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分 http://www.ibm.com/developerworks/cn/views/cognitive/libraryview.jsp?search_by=%E4%BD%BF%E7%94%A8+Bluemix+%E6%9C%8D%E5%8A

系列内容:

此内容是该系列 2 部分中的第 # 部分: 使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分

http://www.ibm.com/developerworks/cn/views/cognitive/libraryview.jsp?search_by=%E4%BD%BF%E7%94%A8+Bluemix+%E6%9C%8D%E5%8A%A1%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%9F%BA%E4%BA%8E%E6%B5%8F%E8%A7%88%E5%99%A8%E7%9A%84+PDF+%E5%AD%98%E5%82%A8%E5%92%8C%E6%90%9C%E7%B4%A2%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F

敬请期待该系列的后续内容。

此内容是该系列的一部分: 使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分

敬请期待该系列的后续内容。

如果您像我一样,您的计算机上现在可能有数以百计的文档。这些文档包括您已经创建的文档、要求您审阅的文档、作为各种项目的组成部分而被复制的文档……这样的例子举不胜举。您通过电子邮件获得了这些文档,在 Slack 对话中获得,以及从网站下载文档……您拥有的文档越多,聚集的文档堆就会越大,也就越难在您需要的时候找到您所需的文档。

借助现有的 Watson 和 Bluemix 服务,您可以将一个很有用的文件存储应用程序与功能完全的关键词搜索支持组合在一起使用。

这就是本文所要解决的问题。在这个由两部分组成的文章系列的第 1 部分中,将向您展示如何创建一个强大的、基于浏览器的文档存储和检索应用程序,它会让搜索文档中的相关内容变得更快更容易。在这个过程中,我还会介绍一些来自 IBM® Watson 的有趣的新服务,并引导您完成在 IBM Bluemix? 上托管最终的应用程序的过程。第 2 部分将展示如何上传和存储已转换的文件。

听起来很有趣?那就请继续阅读!

运行示例应用程序 从 GitHub 上获得代码

本文中介绍的示例应用程序允许用户从其计算机中选择 PDF 文档,并将这些文档上传到一个在线文档存储中。在上传每个文件时,会自动和智能扫描关键词,这些关键词将根据需要被提取和存储在数据库中。用户以后可通过关键词进行搜索,以便快速确定并下载能满足其需求的文档。更不用说,应用程序是针对移动优化的(mobile-optimized),在智能手机和台式电脑上都适用。

在幕后,应用程序通过编排各种服务完成其工作,其中一些服务可直接通过 IBM Bluemix 进行使用,其他服务可作为第三方服务进行使用。以下是一个快速列表:

对于客户端而言,我使用 Bootstrap 为应用程序创建了一个移动友好的用户界面。在服务器上,我将使用 Slim PHP 微框架(micro-framework)来管理应用程序流,使用 MongoDB 来存储关键词列表。应用程序托管在 IBM Bluemix 上,并连接到前面列出的三项服务来实现文档处理和存储。

先决条件

这里会用到许多技术,因此,在这里您需要:

备注:使用 AlchemyAPI 服务的任何应用程序都必须遵从 AlchemyAPI 条款和条件 。同样,使用 Document Conversion and Object Storage 服务的任何应用程序都必须遵从每个服务的使用条款,如服务目录页中所述。在开始您的项目之前,花几分钟阅读一下这些要求,确保您的应用程序满足这些要求。

1

创建裸板应用程序

第一步是创建包含 Slim PHP 微框架和其他各种依赖关系的裸板应用程序,这些依赖关系包括针对 SDK 和 Guzzle HTTP 客户端的 OpenStack SDK,二者是与先前描述的各种服务进行交互所必需的。可以使用 Composer(PHP 依赖关系管理器)轻松下载和安装这些组件。使用以下 Composer 配置文件,而且您应将它保存到 $APP_ROOT/composer.json,$APP_ROOT 在此处中会引用您的项目目录。

{
    "require": {
        "php-opencloud/openstack": "*",
        "slim/slim": "*",
        "slim/php-view": "*",
        "guzzlehttp/guzzle": "~6.0"
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}

通过以下命令,使用 Composer 安装 Slim 和其他所需的组件:

shell> php composer.phar install

接下来,为所有可通过网络访问的文件创建目录 $APP_ROOT/public,为所有视图创建目录 $APP_ROOT/views,并为配置信息创建目录 $APP_ROOT/config.php。您会最后获得一个如下所示的目录结构:

图 1. 应用程序文件结构

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

您还应该将您的 MongoDB 连接信息添加到 $APP_ROOT/config.php 文件中,如下面例子所示:

<?php
$config['settings']['db']['uri'] = "mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE";

为了让访问应用程序变得更加容易,您还可以在开发环境中定义一个新的虚拟主机,并将其根目录指定为 $APP_ROOT。推荐执行此步骤(可选),因为这一步在 Bluemix 上创建了一个更接近目标部署环境的复制品。

要在 Apache 中为应用程序设置一个指定的虚拟主机,请打开 Apache 配置文件(httpd.conf 或 httpd-vhosts.conf)并添加以下代码行:

NameVirtualHost 127.0.0.1
<VirtualHost 127.0.0.1>
    DocumentRoot "/var/www/pdf-keyword-search/public"
    ServerName pdf-keyword-search.localhost
</VirtualHost>

这些代码行定义了一个新的虚拟主机 http://pdf-keyword-search.localhost/,它的文档根目录对应于 $APP_ROOT(请记得更新它,以反映您自己的本地设置)。重新启动 Web 服务器来激活这些新设置。请注意,您可能需要更新网络的本地 DNS 服务器,告诉它关于新主机的信息。

然后,将使用包含以下设置的 .htaccess 文件添加到 $APP_ROOT/public 目录中:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

接下来,设置应用程序的主控制脚本。该脚本会加载 Slim 框架并初始化 Slim 应用程序。它还包含对每个应用程序路由的回调,并在路由与传入请求相匹配时,借助每个回调定义了所要执行的代码。

在 $APP_ROOT/public/index.php 下使用以下内容创建脚本:

<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
use GuzzleHttp\Psr7\Stream;
use GuzzleHttp\Client;

// set a long time limit to account 
// for large file uploads and processing time
set_time_limit(6000);

// include autoloader and configuration
require '../vendor/autoload.php';
require '../config.php';

// initialize application
$app = new \Slim\App($config);

// initialize dependency injection container
$container = $app->getContainer();

// add view renderer
$container['view'] = function ($container) {
  return new \Slim\Views\PhpRenderer("../views/");
};

$app->run();

该脚本将会加载所有必要的类和配置文件。然后,它会初始化一个新的 Slim 应用程序对象和一个依赖关系注入(dependency injection,DI)容器,并将 PHP 视图渲染器添加到 DI 容器。

您还需要创建一个可用于通过应用程序渲染各种视图的基本用户界面。下面是一个示例,可用于后续代码清单中所示的所有应用程序视图:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Documents</title>
    <link rel="stylesheet" 
      href=http://www.tuicool.com/articles/"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" 
      href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css"
    >
    
        
  
  

    

Documents

该视图从一个 CDN 设置 Bootstrap 并定义了一个基本 Bootstrap 页面,其中包含一个标题、一个主内容区域和一个页脚。

在完成所有准备工作之后,现在可以开始构建应用程序了。

2

创建一个文件上传表单

Slim 通过定义 HTTP 方法和端点的路由器回调来完成其工作。为此,只需为 GET 请求调用相应的 HTTP 方法 get() ,为 POST 请求调用 post() ,以此类推,并将要匹配的 URL 路由作为方法的第一个参数进行传递。方法的第二个参数是一个函数,它指定了在该路由与传入的请求相匹配时应执行的操作。

要查看将要执行的这个操作,可以创建一个文件上传表单,用户可以通过该表单提交文档。首先,通过将以下代码添加到 $APP_ROOT/public/index.php,定义一个 /add 路由和相应的回调函数:

<?php
// Slim application initialization - snipped
// upload form
$app->get('/add', function (Request $request, Response $response) {
  $response = $this->view->render($response, 'add.phtml', 
    array('router' => $this->router));
  return $response;
})->setName('add');

实质上,这会告诉 Slim,使用 add.phtml 视图脚本的内容来响应针对 /add URL 端点的 GET 请求。该视图脚本(位于 $APP_ROOT/views/add.phtml)应该包含文件上传表单所必需的 HTML 代码,如下所示:

<?php if (!isset($_POST['submit'])): ?>
<div>
  <form method="post" enctype="multipart/form-data" 
    action="<?php echo $data['router']->pathFor('add'); ?>">
    <input type="hidden" name="MAX_FILE_SIZE" value="300000000" />
    <div class="form-group">
      <label for="upload">File</label>
      <span class="btn btn-default btn-file">
        <input type="file" name="upload" />
      </span>
    </div>  
    <div class="form-group">
      <label for="body">Description</label>
      <textarea name="description" id="description" 
        class="form-control" rows="3"></textarea>
    </div>
  <div class="form-group">
    <button type="submit" name="submit" 
      class="btn btn-primary">Add</button>
  </div>          
  </form>
</div>
<?php endif; ?>

这定义了一个基本的 PHP 文件上传表单(请注意 multipart/form-data 编码类型和隐藏的 MAX_FILE_SIZE 变量)。它包含一个文件上传字段和用户指定文本的附加说明字段。

而现在,当您在浏览器中访问 http://pdf-keyword-search.localhost/add 时,应该会看到类似以下的界面:

图 2. 文件上传表单

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

现在,已经完成了上传文件的基础架构。下一步是处理这些文件,这需要更多地了解以下两个关键服务:Watson Document Conversion 服务和 AlchemyAPI 服务。

3

理解和配置 Document Conversion 服务

处理上传的文档包括四步:

  1. 将上传的文档从 PDF 格式转换为标准文本
  2. 分析文本来提取关键词
  3. 存储关键词
  4. 存储上传的 PDF

Document Conversion 服务会负责完成这些步骤中的第一步。作为 Watson Developer Cloud 的一部分,该服务提供了一个 API 来将文档从一种格式转换为另一种格式。常见用例包括清理不正确的 HTML 标记,以及将内容转换为 JSON 格式的 Answer 单元,以适合其他 Watson 服务使用。

Document Conversion 服务接受 HTML、PDF 或 Microsoft Word 文档(在本文中,我假设所有文档都是 PDF 文档),将它们作为输入,并返回一个更易于分析的标准 HTML 或纯文本版本。它接受针对服务端点 https://gateway.watsonplatform.net/document-conversion/api/v1 的 POST 请求。每个 POST 请求都应包含将被转换为 JSON 主体的文档,以及 JSON 格式的数组用于指示所需要的输出格式。

要了解此工作原理,可以在 Bluemix 上初始化一个新的 Document Conversion 服务实例。登录到您的 Bluemix 帐户。搜索并选择 Document Conversion 服务。

查看该服务的描述,然后单击启动它。确保“Connect to”字段被设置为“Leave unbound”,而且您将使用“Standard Plan”。最初,该服务实例会在未绑定的状态下运行;这允许远程使用托管在 Bluemix 上的应用程序服务实例,而在本地本地开发应用程序。

图 3. Document Conversion 服务的初始化

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

初始化服务实例,在此操作完成时,会为您显示一个服务信息页面。显示左侧的导航栏,然后单击“Service Credentials”链接来查看该服务实例的用户名和密码。请记下这些凭证和服务名称,因为在后续步骤中需要使用它们。

图 4. Document Conversion 服务凭证

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

现在,通过使用 REST 客户端(比如 Postman)向 Document Conversion 服务发送一个示例请求,您可以测试使用该服务。下图显示了一个示例请求和响应。

图 5. Document Conversion 服务的示例请求/响应

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

现在也是将您的 Document Conversion 服务凭证复制到 PHP 应用程序的好时候。编辑 $APP_ROOT/config.php 文件,并将凭证添加到该文件,如下面示例所示:

<?php
$config['settings']['document-conversion']['user'] = "USERNAME";
$config['settings']['document-conversion']['pass'] = "PASSWORD";

4

理解并配置 AlchemyAPI Keyword Extraction 服务

当然,将 PDF 文档转换为纯文本只是一个开始。下一步是将纯文本输出发送到 AlchemyAPI 服务,以便执行分析和关键词提取。您可以从 Bluemix 目录访问该服务(如前一小节所示),或者通过使用 AlchemyAPI 网站请求一个 API 密钥来单独访问该服务。

该 AlchemyAPI 服务使用了自然语言处理对非结构化文本进行语义分析,并返回关于它的信息。此信息可能与情感或情绪相关(文本为正向、负向,还是中性),或者它可以是由所提取的关键词、概念或关系组成的列表,然后,可以将它链接到新闻消息或其他数据源。这是一个强大得令人难以置信的服务,在处理任何形式的文本内容时,可以将它放在您的工具箱中。

该 AlchemyAPI 服务通过将 POST 请求接受到服务端点 http://gateway-a.watsonplatform.net/calls/text/TextGetRankedKeywords 来完成其工作。每个 POST 请求都应包含 AlchemyAPI 密钥,以及所要分析的文本和所需的响应格式(以作为表单参数数组)。

下面是通过 REST 客户端访问 API 的示例:

图 6. AlchemyAPI 服务的示例请求/响应

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

一旦有机会验证该服务的工作原理,请使用您的 API 密钥更新 $APP_ROOT/config.php 文件:

<?php
$config['settings']['alchemy']['apikey'] = "APIKEY";

5

从已上传的文档中提取关键词

在了解了 Document Conversion 和 AlchemyAPI 服务的工作原理之后,是时候编写应用程序代码了,您可以将上述两项服务和应用程序代码放在一起,并将生成的关键词保存到 MongoDB 数据库。首先,使用 Slim DI 容器为每个服务创建初始化例程,然后在 $APP_ROOT/public/index.php 文件中加入 MongoDB 数据库连接:

<?php
// Slim application initialization - snipped

// initialize dependency injection container
$container = $app->getContainer();

// add PHP Mongo client
$container['db'] = function ($container) {
  $config = $container->get('settings');
  $dbn = substr(parse_url($config['db']['uri'], PHP_URL_PATH), 1);
  $mongo = new MongoClient($config['db']['uri'], 
    array("connectTimeoutMS" => 30000));
  return $mongo->selectDb($dbn);
};

// add Alchemy API client
$container['extractor'] = function ($container) {
  $config = $container->get('settings');
  return new Client(array(
    'base_uri' => 'http://gateway-a.watsonplatform.net/calls/',
    'timeout'  => 6000,
  ));
};

// add Watson document conversion client
$container['converter'] = function ($container) {
  $config = $container->get('settings');
  return new Client(array(
    'base_uri' => 'https://gateway.watsonplatform.net/document-conversion/api/',
    'timeout'  => 6000,
    'auth' => array($config['document-conversion']['user'], 
      $config['document-conversion']['pass'])
  ));
};

在上面的代码中,为 Document Conversion 和 AlchemyAPI 服务创建了一个 Guzzle Client 对象,并使用所需的服务端点和凭证将其初始化。同样,我们还使用 PHP 的 MongoDB 扩展为实现 MongoDB 数据库交互而初始化了一个 MongoClient 对象。服务端点和凭证都源自 $APP_ROOT/config.php 文件。

接下来,将会为负责处理 PHP 文件上传的 /add 端点定义一个回调来处理 POST 请求。此回调会首先检查是否有有效的文件上传,如有发现这样的文件,则会处理它。以下是相关代码:

<?php
// Slim application initialization - snipped

// upload processor
$app->post('/add', function (Request $request, Response $response) {

  // get configuration
  $config = $this->get('settings');
  

  try {
    // check for valid file upload
    if (empty($_FILES['upload']['name'])) {
      throw new Exception('No file uploaded');
    }
    
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $type = $finfo->file($_FILES['upload']['tmp_name']);
    if ($type != 'application/pdf') {
      throw new Exception('Invalid file format');    
    }

    // convert uploaded PDF to text
    // connect to Watson document conversion API  
    // transfer uploaded file for conversion to text format
    $apiResponse = $this->converter->post(
      'v1/convert_document?version=2015-12-15', array('multipart' => array(
        array('name' => 'config', 
          'contents' => '{"conversion_target":"normalized_text"}'),
        array('name' => 'file', 
          'contents' => fopen($_FILES['upload']['tmp_name'], 'r'))
    )));
    
    // store response
    $text = (string)$apiResponse->getBody();
    unset($apiResponse);

    // extract keywords from text
    // connect to Watson/Alchemy API for keyword extraction 
    // transfer text content for keyword extraction
    // request JSON output
    $apiResponse = $this->extractor->post(
      'text/TextGetRankedKeywords', array('form_params' => array(
        'apikey' => $config['alchemy']['apikey'],
        'text' => strip_tags($text),
        'outputMode' => 'json'
    )));

    // process response
    // create keyword array
    $body = $apiResponse->getBody(); 
    $data = json_decode($body);
    $keywords = array();
    foreach ($data->keywords as $k) {
      $keywords[] = $k->text;
    }
    
    // save keywords to MongoDB
    $collection = $this->db->docs;
    $q = trim($_FILES['upload']['name']);
    $params = $request->getParams();
    $result = $collection->findOne(array('name' => $q));
    $doc = new stdClass;
    if (count($result) > 0) {
      $doc->_id = $result['_id'];
    }
    $doc->name = trim($_FILES['upload']['name']);
    $doc->keywords = $keywords;
    $doc->description = trim(strip_tags($params['description']));
    $doc->updated = time();
    $collection->save($doc);
    
    $response = $this->view->render($response, 'add.phtml', 
      array('keywords' => $keywords, 
        'object' => trim($_FILES['upload']['name']), 
        'router' => $this->router));
    return $response;
    
  } catch (ClientException $e) {
    // in case of a Guzzle exception
    // display HTTP response content
    throw new Exception($e->getResponse());
  }

});

在这里,有很多事情要做,所以让我们先来捋顺一下要执行的步骤:

  • 代码的前几行将会检查文件是否实际上传,如果已上传,那么它会检查该文件是否是 PDF 文档。如果其中一个条件失败,则会生成异常。
  • 假如存在一个有效的 PDF 上传,将向 Document Conversion 服务发送一个 POST 请求,并包含该上传文件。如果成功,响应会是存储在 $text 变量中该 PDF 文件的标准化纯文本版本。
  • 一旦获得了 PDF 内容的纯文本版本,就会将一个 POST 请求发送到 AlchemyAPI 服务。该请求包含该 PDF 的纯文本版本、AlchemyAPI 密钥和所请求的输出格式(JSON)。如果成功,响应会是一个由关键词组成的 JSON 编码形式的关键词列表,并按分数对关键词进行排名。
  • 使用 MongoDB 客户端将关键词保存到数据库中。代码首先会检查针对给定文件是否存在已有的 MongoDB 文档,并使用文件名作为标识符。如果没有找到使用相同的文件名的现有 MongoDB 文档,那么它会创建一个新的 MongoDocument 对象,该对象包含适用于文件名( name )、文件描述( description )、日期和时间( updated ),以及关键词列表( keywords )等属性。如果使用相同的文件名找到了现有的 MongoDB 文档(例如,如果该文档是现有 PDF 文档的更新),则会检索这个现有的 MongoDB 文档,并使用新的信息更新其属性。然后,将结果保存到数据库中的 docs 集合中。

一旦完成这些步骤,该回调就会向视图脚本传递一条成功消息,还会传递一个由提取的关键词组成的列表并保存它。下面是修改后的视图脚本,该脚本位于 $APP_ROOT/views/add.phtml,在针对此更改进行调整后,该脚本如下所示:

<?php if (!isset($_POST['submit'])): ?>
<div>
  <form method="post" enctype="multipart/form-data" 
    action="<?php echo $data['router']->pathFor('add'); ?>">
    <input type="hidden" name="MAX_FILE_SIZE" value="300000000" />
    <div class="form-group">
      <label for="upload">File</label>
      <span class="btn btn-default btn-file">
        <input type="file" name="upload" />
      </span>
    </div>  
    <div class="form-group">
      <label for="body">Description</label>
      <textarea name="description" id="description" 
        class="form-control" rows="3"></textarea>
    </div>
  <div class="form-group">
    <button type="submit" name="submit" 
      class="btn btn-primary">Add</button>
  </div>          
  </form>
</div>
<?php else: ?>
<div>
  <div class="alert alert-success">
    <strong>Success!</strong> Your document 
      <strong><?php echo $data['object']; ?></strong> was added. 
      <a role="button" class="btn btn-primary" 
      href=http://www.tuicool.com/articles/"
  IBM Watson and 
  AlchemyAPI services.

正如上面代码所演示的,视图脚本只在关键词列表上迭代,并显示它们,而且还会显示一条简短的成功消息。

要查看此操作,请在浏览器中返回到 http://pdf-keyword-search.localhost/add,并尝试上传一个 PDF 文件。如果一切顺利的话,您的 PDF 文件将会被转换、分析和保存,您还会看到一条成功消息:

图 7. 文件上传结果

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

使用 Bluemix 服务创建一个基于浏览器的 PDF 存储和搜索应用程序,第 1 部分: 使用 Document Conv...

结束语

现在,如果您目光敏锐的话,就会发现,在第 3 步开始的时候,我列出了处理文件上传的四个阶段。到目前为止,您已经看到了完成前三个阶段的代码,但还有一处遗漏:保存实际的 PDF 文件。在本文章系列的第 2 部分中,我将介绍遗留的这一部分,即 IBM Bluemix Object Storage 服务,该服务为文件存储和检索提供了可伸缩的、基于云的基础架构。

我还会带您遍历一遍为应用程序构建一个搜索界面的过程,这样,您就可以开始使用该界面来查找符合搜索关键词的文档。最后,我会向您展示如何将所有代码都部署到 IBM Bluemix,这样您就可以随时随地查找文档。确保您会为学习这方面的知识而回到这里!

 
标签: PHP Bluemix
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • php-fpm进程管理的三种模式 phpfpm子进程
    php-fpm进程管理的三种模式 phpfpm子进程
    php-fpm解读-进程管理的三种模式—程序媛大丽标明转载以示尊重 感谢原作者的分享。php-fpm进程管理一共有三种模式:ondemand、static、dynamic,我们可以在同一个fpm的master配置三种模式,看下图1。php-fpm的工作模式和nginx类似,都是一个master,多个worke
    03-08
  • nginx和php-fpm 是使用 tcp socket 还是 unix s
    tcp socket允许通过网络进程之间的通信,也可以通过loopback进行本地进程之间通信。unix socket允许在本地运行的进程之间进行通信。分析从上面的图片可以看,unix socket减少了不必要的tcp开销,而tcp需要经过loopback,还要申请临时端口和tcp相关资源。但是
    03-08
  • [PHP8] 我参加了PHP8工程师认证初学者考试beta考试
    [PHP8] 我参加了PHP8工程师认证初学者考试beta
    前几天,2022/08/05,PHP工程师认证机构PHP8 技术员认证初级考试宣布实施考试将于 2023 年春季开始。和 beta 测试完成于 2022/09/11所以我收到了。一般社团法人BOSS-CON JAPAN(代表理事:Tadashi Yoshimasa,地点:东京都世田谷区,以下简称“BOSS-CON JAPAN
    03-08
  • 将 PHP Insights 放入旧版 PJ 不是很好吗?谈论
    将 PHP Insights 放入旧版 PJ 不是很好吗?谈论
    介绍在最近的PHP系统开发中,感觉故事在理所当然包含静态分析工具的前提下进行。我的周围现有代码很脏,我很久以前安装了工具,但几乎没有检查已经观察到许多这样的案例。 (这是小说。而不是像 0 或 100 这样不允许单行错误的静态分析,一点一点,逐渐我想介
    03-08
  • PHP基于elasticsearch全文搜索引擎的开发 php使
    1.概述:全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是目前全文搜索引擎的首选。Elastic 的底层是开源库 Lucene。但是,你没法直接用 Lucene,必须自己写代码去调用它的接口。Elastic 是 Lucene 的封装,提供了 REST API 的操作接
    02-09
  • php视图操作
    一、视图的基本介绍         视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。        使用视图需要MySQL5及以后的版本支持。        下面是视图的一些常见应用:        重用SQL语句;        简化复杂的S
    02-09
  • php中图像处理的常用函数 php图形图像处理技术
    php中图像处理的常用函数 php图形图像处理技术
    1.imagecreate()函数imagecreate()函数是基于一个调色板的画布。?php $im = imagecreate(200,80);                //创建一个宽200,高80的画布。$white = imagecolorallocate($im,225,35,180);     //设置画布的背景颜色imagegif($im);
    02-09
  • PHP安全之webshell和后门检测
    PHP安全之webshell和后门检测
    基于PHP的应用面临着各种各样的攻击:XSS:对PHP的Web应用而言,跨站脚本是一个易受攻击的点。攻击者可以利用它盗取用户信息。你可以配置Apache,或是写更安全的PHP代码(验证所有用户输入)来防范XSS攻击SQL注入:这是PHP应用中,数据库层的易受攻击点。防范
    02-09
  • php使用时间戳保存时间的意义 PHP获取时间戳
    时间戳记录的是格林尼治时间,使用date格式化的时候会根据你程序设置的不同时区显示不同的时间。如果使用具体时间,则还需要进行多一步转换。
    02-09
  • PHP 获取提交表单数据方法
    PHP $_GET 和 $_POST变量是用来获取表单中的信息的,比如用户输入的信息。PHP表单操作在我们处理HTML表单和PHP表单时,我们要记住的重要一点是:HTML页面中的任何一个表单元素都可以自动的用于PHP脚本:表单举例: htmlbodyform action="welcome.php" method
    02-09
点击排行