PHPFog is a relatively new cloud hosting provider specifically designed for PHP applications. Their mission statement is “less management, more code” and the entire platform is centered around the most used and reliable PHP tools. As an example I tried to start a brand new WordPress blog on a free plan and it took just 3 minutes! Also, the process of installing and updating plugins and themes is instantaneous!
PHPFog是一个相对较新的云托管提供商,专门为PHP应用程序设计。 他们的使命是“减少管理,增加代码”,整个平台以最常用和可靠PHP工具为中心。 举例来说,我尝试免费启动一个全新的WordPress博客,只花了3分钟! 另外,安装和更新插件和主题的过程是瞬时的!
In this tutorial I’ll build a simple subcription form application using two of PHPFog supported frameworks: Slim for the PHP part and Twitter Bootstrap for the CSS part. As a bonus the app will take advantage of the new responsive features of the Bootstrap 2 framework and will be usable out of the box from desktop PCs, tablets and smartphones.
在本教程中,我将使用两个受PHPFog支持的框架构建一个简单的订阅表单应用程序:Slim用于PHP部分,而Twitter Bootstrap用于CSS部分。 作为奖励,该应用程序将利用Bootstrap 2框架的新响应功能,并可从台式机,平板电脑和智能手机直接使用。
How PHFog is different from other providers?
PHFog与其他提供商有何不同?
Firstly, the PHPFog platform is built upon well known and reliable open source technologies. HTTP requests are first filtered by a Varnish cache proxy server, then passed through an Nginx load balancer that distributes the workload between several application servers. These servers are dedicated Linux machines running Apache with mod_php and the APC (Advanced PHP Cache) extension. The database storage is managed by MySQL using a master-slave scalable setup.
首先,PHPFog平台建立在众所周知且可靠的开源技术之上。 HTTP请求首先由Varnish缓存代理服务器过滤,然后通过Nginx负载平衡器传递,该负载平衡器在多个应用程序服务器之间分配工作负载。 这些服务器是运行带有mod_php和APC(高级PHP缓存)扩展名的Apache的专用Linux计算机。 MySQL使用主从可伸缩设置来管理数据库存储。
Secondly, the platform is designed for both developers and non-developers alike. During the application setup you can choose to start with a blank customizable PHP application, with one of the suggested PHP Frameworks (which include CakePHP, CodeIgniter, Zend Framework, etc) or, for non-developers, you can choose to deploy a ready application from a list that includes WordPress, Drupal, Joomla, Media Wiki and other more.
其次,该平台是为开发人员和非开发人员设计的。 在应用程序安装过程中,您可以选择从空白的可自定义PHP应用程序开始,使用建议PHP框架之一(包括CakePHP,CodeIgniter,Zend Framework等),或者对于非开发人员,则可以选择部署就绪的应用程序。从包括WordPress,Drupal,Joomla,Media Wiki等的列表中。
You also get free SSL if you use the .phpfogapp.com domain.
如果您使用.phpfogapp.com域,那么您还将获得免费的SSL。
Even the signup process is very fast at PHPFog, you just need to provide an email address, choose a password and you’re in. No credit card is required initially, because each account starts with a free plan that uses a shared cloud with 3 applications, 100MB of disk storage and 20MB of MySQL storage. If you decide to upgrade to a premium plan you will have a private cloud with dedicated resources (CPU, RAM, disk and database storage). Premium plans also allow you to scale the number of database and application servers used, even for one or two days, paying only for what you use, with a minimum unit of 24 hours.
即使使用PHPFog进行注册过程也非常快,您只需要提供一个电子邮件地址,选择一个密码即可进入。最初不需要信用卡,因为每个帐户都以免费计划开头,该计划使用共享云和3应用程序,100MB磁盘存储和20MB MySQL存储。 如果您决定升级到高级计划,您将拥有一个具有专用资源(CPU,RAM,磁盘和数据库存储)的私有云。 高级计划还允许您扩展使用的数据库和应用程序服务器的数量,即使是一两天,也只需为使用的内容付费,最少24小时。
The most “complicated” thing you’ll have to do during your account setup is setting your SSH keys, but PHPFog staff provides you with this step-by-step guide. And that’all, you’re in! Your account page should look like this:
在帐户设置过程中,您要做的最“复杂”的事情就是设置SSH密钥,但是PHPFog的工作人员会为您提供此分步指南 。 就这样,您就进入了! 您的帐户页面应如下所示:
From you account page you should see the shared cloud box. Create a new application using the “New App” button. Your screen should look similar to this:
从您的帐户页面,您应该看到共享云框。 使用“新应用”按钮创建一个新应用。 您的屏幕应类似于以下内容:
From there you can choose to deploy any of the pre-made applications (above) or a framework based application (below), where the first choice is a blank PHP app. We need to select Slim because the version of this framework provided by PHPFog includes some modifications in order to perform better, we’ll get the Bootstrap stuff later. In the next step we are prompted to choose our application details: the app domain name and MySQL password.
从那里,您可以选择部署任何预制的应用程序(上方)或基于框架的应用程序(下方),其中首选是空白PHP应用程序。 我们需要选择Slim,因为PHPFog提供的该框架的版本包括一些修改以便更好地执行,我们稍后会介绍Bootstrap。 在下一步中,系统提示您选择应用程序详细信息:应用程序域名和MySQL密码。
Your app will be reachable with the URL http://myappname.phpfogapp.com, I chose http://subscribers.phpfogapp.com for my application.
您的应用将可以通过URL http://myappname.phpfogapp.com访问,我为应用选择了http://subscribers.phpfogapp.com 。
For the next 2 or 3 minutes the PHPFog platform will work for you, creating the environment for your app and will give you full access to the application’s console:
在接下来的2或3分钟内,PHPFog平台将为您工作,为您的应用程序创建环境,并使您可以完全访问应用程序的控制台:
At this point you can clone the application’s repository to your local machine using your favorite Git tool:
此时,您可以使用喜欢的Git工具将应用程序的存储库克隆到本地计算机:
[sourcecode]$ git clone git@git01.phpfog.com:subscribers.phpfogapp.com ./SlimSubscribers Cloning into ‘./SlimSubscribers’… Identity added: /Users/ragman/.ssh/id_rsa (/Users/ragman/.ssh/id_rsa) remote: Counting objects: 82, done. remote: Compressing objects: 100% (74/74), done. remote: Total 82 (delta 35), reused 0 (delta 0) Receiving objects: 100% (82/82), 75.79 KiB, done. Resolving deltas: 100% (35/35), done. [/sourcecode]
[源代码] $ git clone git@git01.phpfog.com:subscribers.phpfogapp.com ./SlimSubscribers克隆到'./SlimSubscribers'…添加的标识:/Users/ragman/.ssh/id_rsa(/Users/ragman/.ssh / id_rsa)远程:计数对象:82,已完成。 远程:压缩对象:100%(74/74),已完成。 远程:总计82(增量35),已重用0(增量0)接收对象:100%(82/82),75.79 KiB,已完成。 解析增量:100%(35/35),已完成。 [/源代码]
I simply cloned the application directory inside the DocumentRoot of my local Apache, so that my developement URL is http://localhost/SlimSubscribers/.
我只是在本地Apache的DocumentRoot中克隆了应用程序目录,因此我的开发URL为http://localhost/SlimSubscribers/ 。
Now you have a local copy of a Slim Framework “hello world” application. What we need in the first place is to add the other components and organize our project.
现在,您有了Slim Framework“ hello world”应用程序的本地副本。 首先,我们需要添加其他组件并组织我们的项目。
As you can see from the screenshot above, the application root contains only two files: the .htaccess which is left “as is” and the index.php file that will be our main application controller.
从上面的屏幕快照中可以看到,应用程序根目录仅包含两个文件:“。 .htaccess ”(保留原样)和index.php文件,它将作为我们的主要应用程序控制器。
I’ve created a lib directory where I moved the full Slim package, then I’ve added two more libraries. The db library is a simple PHP class that wraps around PDO. The cake directory contains two classes extraced from the CakePHP framework, used here to sanitize and validate user input. Both classes are available with this article’s code package.
我创建了一个lib目录,在其中移动了完整的Slim软件包,然后又添加了两个库。 db库是包装PDO的简单PHP类。 cake目录包含来自CakePHP框架的两个类,此处用于清理和验证用户输入。 这两个类在本文的代码包中均可用。
At this point you can download the official Twitter Bootstrap package along with the latest version of jQuery and fill the other directories with its css, js and image files.
此时,您可以下载官方的Twitter Bootstrap软件包以及最新版本的jQuery,并使用其CSS,JS和图像文件填充其他目录。
Then create an empty database on you local MySQL server and name it slim_subscribers, and use the following query to create the subscribers table:
然后在本地MySQL服务器上创建一个空数据库,并将其命名为slim_subscribers ,并使用以下查询创建subscribers表:
[sourcecode]CREATE TABLE subscribers ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, firstname VARCHAR(128) NOT NULL, lastname VARCHAR(128) NOT NULL, email VARCHAR(128) NOT NULL UNIQUE, created TIMESTAMP ); [/sourcecode]
[源代码]创建表订阅者(id INT(11)NOT NULL AUTO_INCREMENT PRIMARY KEY,名字VARCHAR(128)NOT NULL,姓氏VARCHAR(128)NOT NULL,电子邮件VARCHAR(128)NOT NULL UNIQUE,创建TIMESTAMP); [/源代码]
With all the main components in place we’ll concentrate our work on the main controller index.php and the templates directory where the frontend files will be stored. The application will have two static descriptive pages, home.php and about.php and the subscribe.php page that contains the subscription form. All these pages will include the common header and footer, which I’ve put together starting with the sample files provided by Bootstrap on its website.
在所有主要组件就绪后,我们将把工作集中在主控制器index.php和将存储前端文件的templates目录中。 该应用程序将有两个静态描述页面, home.php和about.php和subscribe.php包含订阅表单页面。 所有这些页面都将包含通用的页眉和页脚,我将它们与Bootstrap网站上提供的示例文件一起放在一起。
This is the header:
这是标题:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title><?php echo (!empty($pageTitle))? $pageTitle . ' | ' : ''; ?>Slim Subscribe</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="Sample application with Slim Framework and Twitter Bootstrap"> <meta name="author" content="Your Name"> <!-- Le styles --> <link href="css/bootstrap.min.css" rel="stylesheet"> <style> body { padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */ } .form-actions { background-color: transparent; border: none; } </style> <link href="css/bootstrap-responsive.min.css" rel="stylesheet"> <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements --> <!--[if lt IE 9]> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <!-- Le fav and touch icons --> <link rel="shortcut icon" href="https://www.sitepoint.com/wp-content/uploads/2012/04/ico/favicon.ico"> <link rel="apple-touch-icon-precomposed" sizes="114x114" href="https://www.sitepoint.com/wp-content/uploads/2012/04/ico/apple-touch-icon-114-precomposed.png"> <link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://www.sitepoint.com/wp-content/uploads/2012/04/ico/apple-touch-icon-72-precomposed.png"> <link rel="apple-touch-icon-precomposed" href="https://www.sitepoint.com/wp-content/uploads/2012/04/ico/apple-touch-icon-57-precomposed.png"> </head> <body> <div class="navbar navbar-fixed-top"> <div class="navbar-inner"> <div class="container"> <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </a> <a class="brand" href="<?php echo $baseurl ?>/">Slim Subscribe</a> <div class="nav-collapse"> <ul class="nav"> <li<?php if ('home' == $action) echo ' class="active"'; ?>><a href="<?php echo $baseurl ?>/">Home</a></li> <li<?php if ('subscribe' == $action) echo ' class="active"'; ?>><a href="<?php echo $baseurl ?>/subscribe">Subscribe</a></li> <li<?php if ('about' == $action) echo ' class="active"'; ?>><a href="<?php echo $baseurl ?>/about">About</a></li> </ul> </div><!--/.nav-collapse --> </div> </div> </div> <div class="container">The first thing I added is a dynamic title tag, the $pageTitle variable will be passed by the controller file so we can have a different title for each page or fallback to a default one. The viewport meta tag is provided by default with this version of Bootstrap to support mobile devices and tablets. Then come the styles, first the main bootstrap.css, then some embedded customizations, and last the bootstrap-responsive.css that uses @media queries to adapt the layout for smaller screens.
我添加的第一件事是动态标题标签, $pageTitle变量将由控制器文件传递,因此我们可以为每个页面使用不同的标题,或将其回退为默认页面。 此版本的Bootstrap默认提供viewport元标记,以支持移动设备和平板电脑。 然后是样式,首先是主要的bootstrap.css ,然后是一些嵌入式自定义项,最后是使用@media查询来适应较小屏幕布局的bootstrap-responsive.css @media 。
Another default Bootstrap component is the HTML5 shim javascript, loaded from Google, that injects HTML5 tags support for IE 8 and older. At the end of the header section I placed the favicon and touch icon links, leaving the default Bootstrap icons found on Github.
另一个默认的Bootstrap组件是从Google加载HTML5 shim javascript,它注入了对IE 8和更早版本HTML5标签支持。 在标题部分的末尾,我放置了图标和触摸图标链接,并在Github上保留了默认的Bootstrap图标。
The common body starts with a responsive Navbar component. I copied the base code from Bootstrap documentation and added the $action variables, injected by Slim controller, to trigget the link active states. The default javascript “collapse” plugin inside the bootstrap.js will take care of transforming the navigation to a dropdown for small screens.
公共主体从响应式Navbar组件开始。 我从Bootstrap文档中复制了基本代码,并添加了由Slim控制器注入的$action变量,以触发链接的活动状态。 bootstrap.js的默认javascript“ collapse”插件将负责将导航转换为小屏幕的下拉菜单。
The footer code is:
页脚代码为:
<footer> <p>(cc) 2012 Your Name &bull; Some rights reserved.</p> </footer> </div> <!-- /container --> <!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script>window.jQuery || document.write('<script src="js/jquery-1.7.1.min.js"></script>')</script> <script src="js/bootstrap.min.js"></script> </body> </html>The footer file simply closes the application container and inserts the jQuery library and the bootstrap.js file.
页脚文件只是关闭应用程序容器,然后插入jQuery库和bootstrap.js文件。
We can start working on the index file now. This file processes all URLs passed by the .htaccess which don’t map to actual files on the server.
我们现在可以开始处理索引文件了。 该文件处理.htaccess传递的所有URL,这些URL不会映射到服务器上的实际文件。
/** * Simple Configuration */ if ('localhost' == $_SERVER['SERVER_NAME']) { $config['app']['home'] = '/SlimSubscribers'; $config['db'] = array( 'host' => 'localhost', 'user' => 'myuser', 'pass' => 'mypass', 'name' => 'slim_subscribers', ); } else { $config['app']['home'] = ''; $config['db'] = array( 'host' => 'mysql-shared-xx.phpfog.com', 'user' => 'Slim-xxxxx', 'pass' => 'THE ONE YOU CHOSE', 'name' => 'yourdb_phpfogapp_com', ); } // end if /** * Step 1: Require the Slim PHP 5 Framework */ require 'lib/Slim/Slim.php'; // ...add other accessory libraries require_once 'lib/db/db.class.php'; require_once 'lib/cake/sanitize.php'; require_once 'lib/cake/validation.php'; /** * Step 2: Instantiate the Slim application */ $app = new Slim();In the first lines I’m doing a quick config, placing the database details and the base path which will be prepended to all links. I need this bacause my local version is running in a sub path of localhost. Then the Slim framework and the other libraries are loaded and a new Slim application object in created with the default settings (see Slim docs for more info on this).
在第一行中,我正在进行快速配置,将数据库详细信息和基本路径放置在所有链接之前。 我需要这个,因为我的本地版本正在本地主机的子路径中运行。 然后,加载Slim框架和其他库,并使用默认设置创建一个新的Slim应用程序对象(有关更多信息,请参阅Slim文档)。
Once the $app object is created we can use it. Slim allows us to map the URLs we want to process to our custom functions, and all the unprocessed URLs are treated by default as 404 errors. The simplest mapping are the two static pages:
一旦创建了$app对象,我们就可以使用它。 Slim允许我们将要处理的URL映射到自定义函数,并且所有未处理的URL默认情况下均视为404错误。 最简单的映射是两个静态页面:
// Map the Home route $app->get('/', function () use($app, $config) { $pageTitle = 'Welcome to Slim Subscribe'; $action = 'home'; $app->render('home.php', array( 'pageTitle' => $pageTitle, 'action' => $action, 'baseurl' => $config['app']['home'], )); }); // Map the About route $app->get('/about', function () use($app, $config) { $pageTitle = 'About Slim Subscribe'; $action = 'about'; $app->render('about.php', array( 'pageTitle' => $pageTitle, 'action' => $action, 'baseurl' => $config['app']['home'], )); });The $app->get() method takes the given URI path (/ and /about) as first parameter and maps the HTTP method GET for this URL to a function passed as a second parameter. In this example I use two anonymous functions (PHP 5.3 or above is required) to which I pass the $app and $config variables that will be seen as local in scope.
$app->get()方法将给定的URI路径( /和/about )作为第一个参数,并将该URL的HTTP方法GET映射到作为第二个参数传递的函数。 在此示例中,我使用两个匿名函数(需要PHP 5.3或更高版本),将$app和$config变量传递给该匿名函数,这些变量将在范围内被视为本地变量。
First I’m setting the current $pageTitle and $action values, then with the method $app->render() I tell the application object to load the home.php template file (first parameter) from the default templates directory and to inject the give variables using the the array provided as second parameter. The same is done for the /about URI. The home.php template file looks like:
首先,我设置当前的$pageTitle和$action值,然后使用$app->render() ,告诉应用程序对象从默认templates目录加载home.php模板文件(第一个参数)并注入使用提供的数组作为第二个参数给定变量。 对/about URI也是一样。 home.php模板文件如下所示:
<?php require_once 'header.php';?> <div class="hero-unit"> <h1>Hello, world!</h1> <p>This is a simple subscription form application built with Slim Framework, styled with Bootstrap and hosted on PHPFog.</p> <p> <a class="btn btn-primary btn-large" href="<?php echo $baseurl ?>/subscribe">Subscribe now</a> or <a class="btn" rel="external" href="http://phpfog.com/">Learn more about PHPFog &raquo;</a> </p> </div> <?php require_once 'footer.php'; ?>And the about.php template file is:
而about.php模板文件是:
<?php require_once 'header.php';?> <div class="page-header"> <h1>About Slim Subscribe</h1> </div> <div class="row content"> <div class="span12"> <p>Slim Subscribe is a demo application written to test the PHPFog cloud platform.</p> <ul> <li>Built using <a href="http://www.slimframework.com/">Slim Framework</a></li> <li>Styled with <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap</a></li> </ul> </div> </div> <hr/> <?php require_once 'footer.php'; ?>Both files include the common header and footer. The home template uses a component called hero-unit, which is intended to showcase content, and some well styled buttons. The about page uses a standard page-header component and a one-column container for its content.
这两个文件都包含公共页眉和页脚。 主页模板使用一个名为hero-unit ,该组件用于展示内容以及一些样式合理的按钮。 “关于”页面使用标准的page-header组件和一个一列的容器作为其内容。
The /subscribe URL is the application’s core functionality, it has a structure similar to the other two pages but it also has to handle the form interface and the data posted by the user. The controller code for subcribe is:
/subscribe URL是应用程序的核心功能,它的结构与其他两个页面相似,但是还必须处理表单界面和用户发布的数据。 订阅的控制器代码为:
// Map the Subscribe route $app->map('/subscribe', function () use($app, $config) { $pageTitle = 'Join Slim Subscribe'; $action = 'subscribe'; $data = array(); $errors = array(); if ($app->request()->isPost()) { // Sanitize $data = $app->request()->post(); $data = Sanitize::clean($data, array('escape' => FALSE)); // Validate $valid = Validation::getInstance(); if (!$valid->email($data['email'])) { $errors['email'] = 'Invalid email address'; } // end if if (!$valid->notEmpty($data['firstname'])) { $errors['firstname'] = 'Please insert your name'; } // end if if (!$valid->notEmpty($data['lastname'])) { $errors['lastname'] = 'Please insert your last name'; } // end if // Check/Insert subscriber if (empty($errors)) { if ($db = Db::getConnection()) { try { // First check $query = "SELECT COUNT(id) AS count FROM subscribers WHERE email = :email"; $stmt = $db->prepare($query); $stmt->bindParam(':email', $data['email'], PDO::PARAM_STR); $stmt->execute(); $row = $stmt->fetch(PDO::FETCH_ASSOC); if ((int) $row['count'] > 0) { throw new PDOException("This email address is already subscribed!"); } // end if // Then Insert $query = "INSERT INTO subscribers (firstname, lastname, email) VALUES(:firstname, :lastname, :email)"; $stmt = $db->prepare($query); $stmt->bindParam(':firstname', $data['firstname']); $stmt->bindParam(':lastname', $data['lastname']); $stmt->bindParam(':email', $data['email']); $stmt->execute(); $app->flashNow('success', "Subscription completed successfully!"); } catch (PDOException $e) { $app->flashNow('error', "Unable to process your request: " . $e->getMessage()); } // end try } else { $app->flashNow('error', "Unable to access access database"); } // end if } // end if } // end if $app->render('subscribe.php', array( 'pageTitle' => $pageTitle, 'action' => $action, 'data' => $data, 'errors' => $errors, 'baseurl' => $config['app']['home'], )); })->via('GET', 'POST');First of all you can notice that the method used to map the URI is different. I’m using the $app->map() method which allows to specify more than one HTTP method. In this case the GET method displays the form and the POST method deals with the submitted data. The first and last part of the function is similar to the other pages: at the beginning we set some variables and at the end they are passed to the view file. This function uses two additional variables, $errors that contains the input validation errors and $data that stores the data submitted by the user.
首先,您会注意到用于映射URI的方法是不同的。 我正在使用$app->map()方法,该方法允许指定多个HTTP方法。 在这种情况下,GET方法显示表单,而POST方法处理提交的数据。 该函数的第一部分和最后一部分与其他页面相似:在开始时,我们设置了一些变量,最后,它们被传递到视图文件。 该函数使用两个附加变量, $errors包含输入验证错误, $data存储用户提交的数据。
The method $app->request()->isPost() checks for posted data, if there is something posted it’s then copied into the $data array with $app->request()->post(). The posted data is first sanitized in order to remove invalid characters and then validated and any error found is stored into the $errors array. If there are no data validation errors the script tries to connect to the database, the $app->flashNow() method is used to store an error message into the current session. The template will have access to an associative array called $flash containing all the messages.
$app->request()->isPost()检查已发布的数据,如果有已发布的内容,则使用$app->request()->post()将其复制到$data数组中。 首先对发布的数据进行清理,以删除无效字符,然后对其进行验证,并将发现的任何错误存储到$errors数组中。 如果没有数据验证错误,脚本将尝试连接到数据库, $app->flashNow()方法用于将错误消息存储到当前会话中。 该模板将访问包含所有消息的名为$flash的关联数组。
The database logic takes place inside the try/catch statement. First we check if the email address submitted is already registered, if so an exception is thrown. Then we try to insert the posted data into the subscribers table, the $app->flashNow() is used in both success and error cases. This lead us directly to the subscribe frontend.
数据库逻辑发生在try/catch语句中。 首先,我们检查提交的电子邮件地址是否已注册,如果已注册,则会引发异常。 然后我们尝试将发布的数据插入订户表,在成功和错误情况下都使用$app->flashNow() 。 这直接将我们引向了订阅前端。
<?php require_once 'header.php';?> <div class="page-header"> <h1>Join Subscribe</h1> </div> <?php if (!empty($flash['error'])): ?> <div class="alert alert-error"> <a class="close" data-dismiss="alert">×</a> <?php echo $flash['error'] ?> </div> <?php endif; ?> <?php if (!empty($flash['success'])): ?> <div class="alert alert-success"> <?php echo $flash['success'] ?> <a href="<?php echo $baseurl ?>/subscribe">Do it again &raquo;</a> </div> <?php else: ?> <div class="row content"> <div class="span12"> <form class="form-horizontal" action="" method="post"> <div class="control-group<?php if (!empty($errors['email'])) echo ' error' ?>"> <label for="email" class="control-label">Your email address</label> <div class="controls"> <input name="email" id="email" class="input-xlarge" type="email" placeholder="john@example.com" value="<?php echo (!empty($data['email'])) ? $data['email'] : ''; ?>"> <?php $field = 'email'; if (!empty($errors[$field])):?><span class="help-inline"><?php echo $errors[$field] ?></span><?php endif; ?> </div> </div> <div class="control-group<?php if (!empty($errors['firstname'])) echo ' error' ?>"> <label for="firstname" class="control-label">Name</label> <div class="controls"> <input name="firstname" id="firstname" class="input-xlarge" type="text" placeholder="John" value="<?php echo (!empty($data['firstname'])) ? $data['firstname'] : ''; ?>"> <?php $field = 'firstname'; if (!empty($errors[$field])):?><span class="help-inline"><?php echo $errors[$field] ?></span><?php endif; ?> </div> </div> <div class="control-group<?php if (!empty($errors['lastname'])) echo ' error' ?>"> <label for="lastname" class="control-label">Last Name</label> <div class="controls"> <input name="lastname" id="lastname" class="input-xlarge" type="text" placeholder="Smith" value="<?php echo (!empty($data['lastname'])) ? $data['lastname'] : ''; ?>"> <?php $field = 'lastname'; if (!empty($errors[$field])):?><span class="help-inline"><?php echo $errors[$field] ?></span><?php endif; ?> </div> </div> <div class="form-actions"> <button class="btn btn-primary btn-large" type="submit">Subscribe</button> </div> </form> </div> </div> <?php endif; ?> <hr/> <?php require_once 'footer.php'; ?>The common header and footer templates are included and a page-header component is used for the title. Just after the page title the script checks the $flash session variable for global application errors. The error message is displayed using the alert classes provided by Bootstrap. The “x” anchor is hooked automatically by the Javascript and used to close the message box.
包括通用的页眉和页脚模板,并且page-header组件用于标题。 在页面标题之后,脚本将检查$flash会话变量中是否存在全局应用程序错误。 使用Bootstrap提供的警报类显示错误消息。 Java脚本会自动挂钩“ x”锚点,并用于关闭消息框。
A similar check is performed for success messages, displayed using the “alert-success” class. If we don’t have any success messages either there were some errors or there weren’t data posted, so the form is displayed. The subscription form is built using the component provided by Bootstrap. I chose the “form-horizontal” form type and each control is wrapped around a “control-group” div. For each control group I check to see if the related data triggered any validation error and if it’s the case a class of “error” is added to the group and the corresponding message is displayed near the input field.
使用“ alert-success”类对成功消息进行类似的检查。 如果我们没有任何成功消息,则可能有一些错误或没有发布数据,因此将显示该表单。 订阅表单是使用Bootstrap提供的组件构建的。 我选择了“水平表单”表单类型,每个控件都包裹在“控件组” div周围。 对于每个控制组,我检查是否相关数据触发了任何验证错误,如果是,则将“错误”类别添加到该组中,并在输入字段附近显示相应的消息。
The last line of the index.php controller file is $app->run(); and it’s responsible for executing the Slim application.
index.php控制器文件的最后一行是$app->run(); 它负责执行Slim应用程序。
We should have our application working perfectly from our localhost machine at this point. All we have to do in order to publish it is:
在这一点上,我们应该使我们的应用程序在本地计算机上运行良好。 为了发布它,我们要做的就是:
create the subscribers table into our remote database using the phpMyAdmin provided by PHPFog, 使用PHPFog提供的phpMyAdmin将订阅者表创建到我们的远程数据库中,do a git push command from our favorite git interface.
从我们最喜欢的git界面执行git push命令。
Your application is up and running at http://theappname.phpfogapp.com and it’s perfectly usable from desktop machines, tablets and smartphones.
您的应用程序已在http://theappname.phpfogapp.com启动并运行,可以在台式机,平板电脑和智能手机上完美使用。
Undoubtely PHPFog is another great tool at your disposal to publish you applications quickly. Is has still some limitations, most of them due to the fact that it’s still a young platform. Nontheless reading the documentation you see that the staff behind the scenes is working really hard to fill the gaps and in the meantime they provide you with tips and tricks to work around the current limits.
毫无疑问,PHPFog是您可以使用的另一个出色工具,可以快速发布应用程序。 Is仍然有一些局限性,其中大多数是由于它仍然是一个年轻的平台。 但是,阅读文档后,您会发现幕后工作人员确实在努力填补空白,与此同时,他们为您提供了一些技巧和窍门,以解决当前的限制。
Then there is the Bootstrap interface framework, that coupled with Slim or any other of your favorite PHP library, is a great starting point to build awesome user interfaces and let you concentrate on programming. In fact it took me more time to write this article than to build the sample application from scratch. :)
然后是Bootstrap接口框架,它与Slim或您喜欢的任何其他PHP库结合使用,是构建很棒的用户界面并让您专注于编程的一个很好的起点。 实际上,我花了更多时间写这篇文章,而不是从头开始构建示例应用程序。 :)
I hope this tutorial has boost your couriosity to explore the other platform features. Happy Coding!
我希望本教程能帮助您提高探索其他平台功能的热情。 编码愉快!
翻译自: https://www.sitepoint.com/a-cloud-dedicated-to-php-apps-say-hello-to-phpfog/