如何从反转的列表中删除要执行的操作?

时间:2017-10-13 21:33:50

标签: php arrays oop

我使用 array_reverse 将新创建的待办事项添加到列表顶部。但现在我无法删除它们。当我单击复选框删除项目时,它将删除列表另一端的项目。谁能告诉我扭转订单并让它们正确删除的最佳方法? array_reverse是实现这一目标的最佳方式,还是有更好的选择。我的两个文件在下面。

的index.php

fetch()

TaskList.php

<?php
// cookies
ini_set('session.gc_maxlifetime', 172800);

session_set_cookie_params(172800);

// array('get milk', 'feed dog');
include 'TaskList.php';


$list = new TaskList('tasks');


if(isset($_POST['task'])) {
  // if post task is set the user submitted a task
  $list->addItem($_POST['task']);
  $list->save();
}

if(isset($_POST['delete'])) {
  // delete this item from the array
  $keys = $_POST['delete'];
  foreach($keys as $key) {
      array_reverse($list->deleteItem($key));
  }
  $list->save();
 }


?>

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>To Do List</title>
  </head>
<body>

<h1>To Do List</h1>

<!-- Insert Items -->
<form action="index.php" method="post">
  <label for="task">
    Enter task: <input type="text" name="task" id="task" value="" placeholder="Enter Task Here">
  </label>
  <input type="submit" name="" value="Add">
</form>

<form class="" action="index.php" method="post">
  <ul>
    <?php foreach(array_reverse($list->items) as $key => $task): ?>
      <!-- [] tell browser that it's an array and to delete more than one item at a time -->
      <li><input type="checkbox" name="delete[]" value="<?php echo $key ?>"><?php echo $task; ?></li>
    <?php endforeach; ?>
  </ul>
  <input type="submit" name="" value="Delete">
</form>

<hr>

<?php var_dump(array_reverse($list->items)) ?>

</body>
</html>

2 个答案:

答案 0 :(得分:0)

这里可以使用 for 循环来通过向后循环来保持任务列表中项目的顺序。

我在TaskList类中添加了一个方便的方法来轻松访问键

function getKey($key) {
    return $this->items[$key];
}

修改PHP模板以使用 for 循环:

<form class="" action="index.php" method="post">
  <ul>
    <?php 
      $count = count($taskList->items) - 1;
      for($key=$count; $key >= 0; $key--) {
        $task = $taskList->getKey($key);
    ?>
      <li><input type="checkbox" name="delete[]" value="<?php echo $key ?>">
          <?php echo $task; ?></li>
    <?php  } ?>
  </ul>
  <input type="submit" name="" value="Delete">
</form>

答案 1 :(得分:0)

反向删除

这里的目标是删除数组中相反的元素。一种方法是使用array_keys获取数组的键,然后在结果上使用array_reverse为我们提供相反键的映射。

$reverseKeys = array_reverse(array_keys($arr));

// output of print_r($reverseKeys) for an array indexed from 0 to 4
Array
(
    [0] => 4
    [1] => 3
    [2] => 2
    [3] => 1
    [4] => 0
)

然后我们可以使用此地图删除相应的元素。

if(isset($_POST['delete'])) {
    // delete this item from the array
    $keys = $_POST['delete'];
    $reverseKeys = array_reverse(array_keys($arr));

    foreach($keys as $key) {
        $list->deleteItem($reverseKeys[$key]);
    }
    $list->save();
}

由于此问题具有oop标记,我将尝试着重于提供更加面向对象的方法以及如何改进当前的设计。

TaskList对象

的设计

首先,让我们看看TaskList对象的设计,看看我们可以改进哪些内容。

封装

面向对象编程的关键概念之一( 对某些人来说最重要)是encapsulation的概念。简而言之,封装意味着对象的内部工作和属性对于使用该对象的代码是隐藏的。这在实践中意味着一个对象应该具有private属性,并且只通过公共访问器公开它们(部分或全部)。

访问者可以返回没有修改的值

public function getDateOfBirth() {
    return $this->dateOfBirth;
}

或执行一些修改以赋予数据更多意义

public function getAge() {
    // assuming $dateOfBirth is an instance of DateTime
    $diff = $dateOfBirth->diff(new DateTime());
    return $diff->format('%y');
}

查看TaskList类,我们可以将属性$items$listName转换为私有成员,并为其创建访问者。

class TaskList {

    private $items = [];
    private $listname = '';

    public function __construct($listname){
        /* ... */
    }

    public function getListName() {
        return $this->listName;
    }

    public function getItems() {
        return $this->items;
    }
}

班上其他人对我好看; addItem()deleteItem()save()都非常不言自明,而且包含得很好。但其余的代码怎么样?查看index.php文件,我们可以将其重构为TaskList。最大的一个是执行批量删除的foreach循环。 TaskList类应该能够自己执行此操作,而不会将其内部结构暴露给其余代码。

// rename delete to deleteOne
public function deleteOne($key) {
    unset $this->items[$key];
}

public function deleteItems($keys) {
    foreach($keys as $key) {
        $this->deleteOne($key);
    }
}

// reverse delete from earlier
public function reverseDeleteItems($keys) {
    $reverseKeys = array_reverse(array_keys($arr));

    foreach($keys as $key) {
        $this->deleteOne($reverseKeys[$key]);
    }
}

责任

在面向对象编程中经常应用的Antoher重要原则是Single Responsability。单一责任原则(SRP)没有详细说明,一个对象应该只处理自己的数据/进程,而不是在该范围之外。在这里,TaskList的职责是维护任务列表。然而,它也在它的构造函数中处理php会话,这不属于它的责任。

的index.php:

<?php
    session_start()
    /* ... */

TaskList.php:

class TaskList {
    /* ... */
    public function __construct($name) {
        $this->listname = $name;

        if(isset($_SESSION[$this->listname])) {
            $this->items = $_SESSION[$this->listname];
        }
        else {
            $this->items = array();
        }
    }

进一步改进

上面应该有足够的信息来帮助您解决问题,但我想借此机会提供一些建议。

首先,$items是一个简单的数组,现在效果很好,但将来可能会出现问题。数组可以包含任何内容,它可能不是正确的格式。你可以做的是创建一个Task类,让Item的每个元素实例化它。通过这种方式验证每个任务是否具有适当的元素变得非常容易,并且它也可以更好地扩展。

class Task {

    private $name;
    private $value;
    private $priority;  // value from 0 to 9
    private $createdAt;
    private $updatedAt;

    public function __construct($name, $value, $priority = 5) {
        $this->name = $name;
        $this->value = $value;
        $this->priority = $priority;

        $now = new DateTime();
        $this->createdAt = $now;
        $this->updatedAt = $now;
    }

    public function getName() {
        return $this->name;
    }

    public function getValue() {
        return $this->value;
    }

    public function setValue($value) {
        $this->value = $value;
        $this->updatedAt = new DateTime();
    }

    public function getPriority() {
        return $this->priority;
    }

    public function toArray() {
        return [
            'name' => $this->name,
            'value' => $this->value,
            'priority' => $this->priority,
            'createdAt' => $this->createdAt->format('Y-m-d H:i:s'),
            'updatedAt' => $this->updatedAt->format('Y-m-d H:i:s'),
        ];
    }
}

这使您可以像这样修改add函数

public function addItem($name, $value, $priority = null) {
    // if items must be unique
    if(array_key_exists($name, $this->items)) {
        throw new Exception('An item with the same name already exists');
    }

    $this->items[$name] = new Task($name, $value, $priority);
}

正如您所看到的,我现在可以获得有关每个Task的更多信息,只需对TaskList类进行少量修改。

此外,您可以通过重构TaskList中的保存机制来进一步提高TaskListRepository,该机制将负责获取TaskList的实例并将它们保存到您喜欢的任何系统(MySQL) ,SQLite,MongoDB,.txt文件,会话变量)。

class TaskListRepository {

    public function save($list) {
        /* store list */
    }

    public function getOne($name) {
        /* fetch instance of a TaskList */
        return $taskList;
    }
}

您现在可以像这样修改index.php

<?php
    session_start();

    $taskListRepo = new TaskListRepository();
    $taskList = $taskListRepo->getOne('myList');

    $taskList->addOne('groceries', 'I need to pick up the groceries');
    $taskListRepo->save($taskList);