一、创建用户配置文件系统并使用空合并运算符

为了开始这一章,让我们看看 PHP7 中新的空合并。我们还将学习如何使用列出的用户创建一个简单的配置文件页面,您可以单击该页面,并创建一个简单的类似 CRUD 的系统,该系统将使我们能够向系统注册新用户,并出于禁止目的删除用户。

我们将学习使用 PHP7 null 合并运算符,以便在有数据的情况下显示数据,或者在没有数据的情况下只显示一条简单的消息。

让我们创建一个简单的UserProfile类。从 PHP5 开始,就可以创建类。

PHP 中的类以单词class开头,类的名称为:

class UserProfile { 

  private $table = 'user_profiles'; 

} 

} 

我们已经将表设置为私有,并添加了一个private变量,在这里我们定义了它将与哪个表相关。

让我们在类中添加两个函数,也称为方法,以简单地从数据库中获取数据:

function fetch_one($id) { 
  $link = mysqli_connect(''); 
  $query = "SELECT * from ". $this->table . " WHERE `id` =' " .  $id "'"; 
  $results = mysqli_query($link, $query); 
} 

function fetch_all() { 
  $link = mysqli_connect('127.0.0.1', 'root','apassword','my_dataabase' ); 
  $query = "SELECT * from ". $this->table . "; 
 $results = mysqli_query($link, $query); 
} 

空合并运算符

我们可以使用 PHP7 的 null coalesce 操作符来检查结果是否包含任何内容,或者返回一个定义的文本,我们可以在视图上检查该文本,这将负责显示任何数据。

让我们把它放在一个包含所有 define 语句的文件中,并称之为:

//definitions.php 
define('NO_RESULTS_MESSAGE', 'No results found'); 

require('definitions.php'); 
function fetch_all() { 
   ...same lines ... 

   $results = $results ??  NO_RESULTS_MESSAGE; 
   return $message;    
} 

在客户端,我们需要拿出一个模板来显示用户配置文件列表。

让我们创建一个基本的 HTML 块来显示每个概要文件可以是一个div元素,其中有几个列表项元素来输出每个表。

在下面的函数中,我们需要确保所有值都至少填写了名称和年龄。然后,我们只需在调用函数时返回整个字符串:

function profile_template( $name, $age, $country ) { 
 $name = $name ?? null; 
  $age = $age ?? null; 
  if($name == null || $age === null) { 
    return 'Name or Age need to be set';  
   } else { 

    return '<div> 

         <li>Name: ' . $name . ' </li> 

         <li>Age: ' . $age . '</li> 

         <li>Country:  ' .  $country . ' </li> 

    </div>'; 
  } 
} 

关注点分离

在适当的 MVC 体系结构中,我们需要将视图与获取数据的模型分开,控制器将负责处理业务逻辑。

在我们的简单应用程序中,我们将跳过控制器层,因为我们只想在一个面向公众的页面中显示用户配置文件。在 MVC 体系结构中,前面的函数也称为模板渲染部分。

虽然有一些 PHP 框架使用现成的 MVC 体系结构,但现在我们可以坚持现有的框架并使其工作。

PHP 框架可以从 null coalesce 操作符中受益匪浅。在我使用过的一些代码中,我们经常使用三元运算符,但仍然需要添加更多的检查以确保值不是虚假的。

此外,三元运算符可能会变得混乱,需要一些时间才能习惯。另一种选择是使用isSet功能。但是,由于isSet函数的性质,PHP 会将一些 falsy 值解释为一个集合。

创建视图

现在我们已经有了完整的模型,一个模板渲染函数,我们只需要创建一个视图来查看每个概要文件。

我们的视图将放在一个foreach块中,我们将使用我们编写的模板来呈现正确的值:

//listprofiles.php 

<html> 
<!doctype html> 
<head> 
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> 
</head> 
<body> 

<?php 
foreach($results as $item) { 
  echo profile_template($item->name, $item->age, $item->country; 
} 
?> 
</body> 
</html> 

让我们把上面的代码放到index.php中。

虽然我们可以安装 Apache 服务器,将其配置为运行 PHP,安装新的虚拟主机和其他必要的功能,并将 PHP 代码放入 Apache 文件夹,但这需要时间。因此,为了测试这一点,我们可以运行 PHP 的服务器进行开发。

要运行内置 PHP 服务器(请参阅中的更多内容)http://php.net/manual/en/features.commandline.webserver.php )我们将在终端内使用正在运行的文件夹:

php -S localhost:8000

如果我们打开浏览器,我们应该什么也看不到,没有找到结果。这意味着我们需要填充数据库。

如果您的数据库连接有错误,请确保将我们提供的正确数据库凭据替换到我们进行的每个mysql_connect调用中。

  1. 为了向我们的数据库提供数据,我们可以创建一个简单的 SQL 脚本,如下所示:

    ```php INSERT INTO user_profiles ('Chin Wu', 30, 'Mongolia'); INSERT INTO user_profiles ('Erik Schmidt', 22, 'Germany'); INSERT INTO user_profiles ('Rashma Naru', 33, 'India');

    ```

  2. 让我们将其保存在一个文件中,例如insert_profiles.sql。在与 SQL 文件相同的目录下,使用以下命令登录 MySQL 客户端:

    ```php mysql -u root -p

    ```

  3. 然后键入用法:

    ```php mysql> use ;

    ``` 4. 通过运行源命令

    ```php mysql> source insert_profiles.sql

    ```

    导入脚本

现在,我们的用户配置文件页面应显示以下内容:

Creating views

创建档案输入表单

现在,让我们创建 HTML 表单,供用户输入他们的配置文件数据。

如果我们没有一种简单的方法让用户输入他们的用户配置文件详细信息,那么我们的配置文件应用程序就没有用了。

我们将创建如下配置文件输入表单:

//create_profile.php 

<html> 
<body> 
<form action="post_profile.php" method="POST"> 

  <label>Name</label><input name="name"> 
  <label>Age</label><input name="age"> 
  <label>Country</label><input name="country"> 

</form> 
</body> 
</html> 

在本文中,我们需要创建一个 PHP 脚本来处理用户发布的任何内容。它将根据输入值创建一个 SQL 语句,并输出它们是否被插入。

我们可以再次使用 null coalesce 运算符来验证用户是否输入了所有值,并且没有未定义或 null 的内容:

$name = $_POST['name'] ?? ""; 

$age = $_POST['country'] ?? ""; 

$country = $_POST['country'] ?? ""; 

这可以防止我们在将数据插入数据库时积累错误。

首先,让我们创建一个变量来保存一个数组中的每个输入:

$input_values =  [ 
 'name' => $name, 
 'age' => $age, 
 'country' => $country 
]; 

前面的代码是一种新的 PHP5.4+数组编写方法。在 PHP5.4+中,不再需要输入实际的array();作者个人更喜欢新语法。

我们应该在UserProfile类中创建一个新方法来接受这些值:

Class UserProfile { 

 public function insert_profile($values)  { 

 $link =  mysqli_connect('127.0.0.1', 'username','password', 'databasename'); 

 $q = " INSERT INTO " . $this->table . " VALUES ( '".$values['name']."', '".$values['age'] . "' ,'".$values['country']. "')"; 
   return mysqli_query($q); 

 } 
} 

我们可以简单地使用数组来保存值,而不是像使用 profile template render 函数那样在函数中创建一个参数来保存每个参数。

这样,如果需要在数据库中插入一个新字段,我们可以在 SQLinsert语句中添加另一个字段。

现在,让我们创建编辑配置文件部分。

现在,我们假设使用此编辑配置文件的人是该站点的管理员。

我们需要创建一个页面,如果已经设置了$_GET['id'],我们将从数据库中获取并显示在表单上的用户。下面是该代码的外观:

<?php 
require('class/userprofile.php');//contains the class UserProfile into 

$id = $_GET['id'] ?? 'No ID'; 
//if id was a string, i.e. "No ID", this would go into the if block 
if(is_numeric($id)) { 
  $profile =  new UserProfile(); 
  //get data from our database 
  $results =   $user->fetch_id($id); 
  if($results && $results->num_rows > 0  ) { 
     while($obj = $results->fetch_object()) 
   { 
          $name = $obj->name; 
          $age = $obj->age; 
       $country = $obj->country; 
      } 
        //display form with a hidden field containing the value of the ID 
?> 

  <form action="post_update_profile.php" method="post"> 

  <label>Name</label><input name="name" value="<?=$name?>"> 
  <label>Age</label><input name="age" value="<?=$age?>"> 
  <label>Country</label><input name="country" value="<?=country?>"> 

</form> 

  <?php 

  } else { 
         exit('No such user'); 
  } 

} else { 
  echo $id; //this  should be No ID'; 
 exit; 
}   

请注意,我们在表单中使用了所谓的快捷方式echo语句。它使我们的代码更简单,更容易阅读。因为我们使用的是 PHP7,所以这个特性应该是现成的。

一旦有人提交表单,它就会进入我们的$_POST变量,我们将在UserProfile类中创建一个新的Update函数。

管理系统

最后,让我们为管理仪表板门户创建一个简单的网格,该门户将与我们的用户配置文件数据库一起使用。我们对此的要求很简单:我们可以设置一个基于表的布局,以行的形式显示每个用户配置文件。

从网格中,我们将添加链接,以便能够编辑配置文件,或删除它,如果我们想要的话。在 HTML 视图中显示表的代码如下所示:

<table> 
 <tr> 
  <td>John Doe</td> 
  <td>21</td> 
  <td>USA</td> 
  <td><a href="edit_profile.php?id=1">Edit</a></td> 
  <td><a href="profileview.php?id=1">View</a> 
  <td><a href="delete_profile.php?id=1">Delete</a> 
 </tr> 
</table> 
This script to this is the following: 
//listprofiles.php 
$sql = "SELECT * FROM userprofiles LIMIT $start, $limit ";  
$rs_result = mysqli_query ($sql); //run the query 

while($row = mysqli_fetch_assoc($rs_result) { 
?> 
    <tr> 
           <td><?=$row['name'];?></td> 
           <td><?=$row['age'];?></td>  
        <td><?=$row['country'];?></td>       

         <td><a href="edit_profile.php?id=<?=$id?>">Edit</a></td> 
          <td><a href="profileview.php?id=<?=$id?>">View</a> 
          <td><a href="delete_profile.php?id=<?=$id?>">Delete</a> 
           </tr> 

<?php 
} 

有一件事我们还没有创造出来:一个delete_profile.php页面。查看和编辑页面已经讨论过了。

以下是delete_profile.php页面的外观:

<?php 

//delete_profile.php 
$connection = mysqli_connect('localhost','<username>','<password>', '<databasename>'); 

$id = $_GET['id'] ?? 'No ID'; 

if(is_numeric($id)) { 
mysqli_query( $connection, "DELETE FROM userprofiles WHERE id = '" .$id . "'"); 
} else { 
 echo $id; 
} 
i(!is_numeric($id)) {  
exit('Error: non numeric \$id');  
 } else { 
echo "Profile #" . $id . " has been deleted"; 

?> 

当然,因为我们的数据库中可能有很多用户配置文件,所以我们必须创建一个简单的分页。在任何分页系统中,您只需要计算出总行数以及每页要显示多少行。我们可以创建一个函数,该函数将能够返回一个 URL,其中包含页码以及每页要查看的页数。

从查询数据库中,我们首先创建一个新函数,用于仅选择数据库中的项目总数:

class UserProfile{ 
 // .... Etc ... 
function count_rows($table) { 
      $dbconn = new mysqli('localhost', 'root', 'somepass', 'databasename');  
  $query = $dbconn->query("select COUNT(*) as num from '". $table . "'"); 

   $total_pages = mysqli_fetch_array($query); 

   return $total_pages['num']; //fetching by array, so element 'num' = count 
} 

对于分页,我们可以创建一个简单的paginate函数,它接受分页页面的base_url、每页的行数(也称为我们希望每页拥有的记录数)以及找到的记录总数:

require('definitions.php'); 
require('db.php'); //our database class 

Function paginate ($base_url, $rows_per_page, $total_rows) { 
  $pagination_links = array(); //instantiate an array to hold our html page links 

   //we can use null coalesce to check if the inputs are  null   
  ( $total_rows || $rows_per_page) ?? exit('Error: no rows per page and total rows);  
     //we exit with an error message if this function is called incorrectly  

    $pages =  $total_rows % $rows_per_page; 
    $i= 0; 
       $pagination_links[$i] =  "<a href="http://". $base_url  . "?pagenum=". $pagenum."&rpp=".$rows_per_page. ">"  . $pagenum . "</a>"; 
      } 
    return $pagination_links; 

} 

此功能将帮助在表格中显示上述页面链接:

function display_pagination($links) {
      $display = '<div class="pagination">
                  <table><tr>';
      foreach ($links as $link) {
               echo "<td>" . $link . "</td>";
      }

       $display .= '</tr></table></div>';

       return $display;
    }

请注意,我们遵循的原则是,函数中很少有echo语句。这是因为我们希望确保这些函数的其他用户在调试页面上的某些神秘输出时不会感到困惑。

通过要求程序员回显函数返回的任何内容,调试程序变得更容易。另外,我们遵循关注点分离,我们的代码不输出显示,它只是格式化显示。

因此,任何未来的程序员都可以更新函数的内部代码并返回其他内容。它还使我们的功能可重用;想象一下,将来有人使用我们的函数,这样,他们就不必再次检查我们的函数中是否有一些错误的echo语句。

提示

关于替代短标签的说明

正如您所知,另一种方法是使用<?=标记。你可以这样使用:<?="helloworld"?>,这些被称为短标签。在 PHP7 中,替代的 PHP 标记已被删除。RFC 声明<%<%=%><script language=php>已被弃用。位于的 RFChttps://wiki.php.net/rfc/remove_alternative_php_tags 表示 RFC 没有移除短开标签(<?或带有echo<?=的短开标签)。

由于我们已经为创建分页链接奠定了基础,现在只需调用函数即可。使用上述函数创建分页页面所需的全部脚本如下:

$mysqli = mysqli_connect('localhost','<username>','<password>', '<dbname>'); 

   $limit = $_GET['rpp'] ?? 10;    //how many items to show per page default 10; 

   $pagenum = $_GET['pagenum'];  //what page we are on 

   if($pagenum) 
     $start = ($pagenum - 1) * $limit; //first item to display on this page 
   else 
     $start = 0;                       //if no page var is given, set start to 0 
/*Display records here*/ 
$sql = "SELECT * FROM userprofiles LIMIT $start, $limit ";  
$rs_result = mysqli_query ($sql); //run the query 

while($row = mysqli_fetch_assoc($rs_result) { 
?> 
    <tr> 
           <td><?php echo $row['name']; ?></td> 
           <td><?php echo $row['age']; ?></td>  
        <td><?php echo $row['country']; ?></td>            
           </tr> 

<?php 
} 

/* Let's show our page */ 
/* get number of records through  */ 
   $record_count = $db->count_rows('userprofiles');  

$pagination_links =  paginate('listprofiles.php' , $limit, $rec_count); 
 echo display_pagination($paginaiton_links); 

listprofiles.php中我们的页面链接的 HTML 输出将如下所示:

<div class="pagination"><table> 
 <tr> 
        <td> <a href="listprofiles.php?pagenum=1&rpp=10">1</a> </td> 
         <td><a href="listprofiles.php?pagenum=2&rpp=10">2</a>  </td> 
        <td><a href="listprofiles.php?pagenum=3&rpp=10">2</a>  </td> 
    </tr> 
</table></div> 

总结

正如您所看到的,我们有很多空合并的用例。

我们学习了如何创建一个简单的用户配置文件系统,以及如何在从数据库获取数据时使用 PHP7 的 null 合并功能,如果没有记录,该功能将返回 null。我们还了解到,null coalesce 操作符类似于三元操作符,只是如果没有数据,它默认返回 null。

在下一章中,我们将介绍其他 PHP7 特性的更多用例,特别是在创建数据库抽象层以用于我们的项目时。