乐于分享
好东西不私藏

Build a Todo App with Flutter(19)

Build a Todo App with Flutter(19)

Home feature

The home feature is responsible for managing the state of the currently-selected tab and displays the correct subtree.

HomeState

There are only two states associated with the two screens: todos and stats.

EditTodo is a separate route therefore it isn’t part of the HomeState.

part of 'home_cubit.dart';enum HomeTab { todos, stats }final classHomeStateextendsEquatable{  const HomeState({this.tab = HomeTab.todos,  });  final HomeTab tab;  @override  List<Objectget props => [tab];}

HomeCubit

cubit is appropriate in this case due to the simplicity of the business logic. We have one method setTab to change the tab.

part'home_state.dart';classHomeCubitextendsCubit<HomeState{  HomeCubit() : super(const HomeState());void setTab(HomeTab tab) => emit(HomeState(tab: tab));}

HomeView

view.dart is a barrel file that exports all relevant UI components for the home feature.

export'home_page.dart';

home_page.dart contains the UI for the root page that the user will see when the app is launched.

A simplified representation of the widget tree for the HomePage is:

├── HomePage│   └── BlocProvider<HomeCubit>│       └── HomeView│           ├── context.select<HomeCubit, HomeTab>│           └── BottomAppBar│               └── HomeTabButton(s)│                   └── context.read<HomeCubit>

The HomePage provides an instance of HomeCubit to HomeViewHomeView uses context.select to selectively rebuild whenever the tab changes. This allows us to easily widget test HomeView by providing a mock HomeCubit and stubbing the state.

The BottomAppBar contains HomeTabButton widgets which call setTab on the HomeCubit. The instance of the cubit is looked up via context.read and the appropriate method is invoked on the cubit instance.

context.read doesn’t listen for changes, it is just used to access to HomeCubit and call setTab.

Todos Feature

The todos overview feature allows users to manage their todos by creating, editing, deleting, and filtering todos.

TodosOverviewEvent

Let's create todos_overview/bloc/todos_overview_event.dart and defines the events.

part of 'todos_overview_bloc.dart';sealed classTodosOverviewEventextendsEquatable{  const TodosOverviewEvent();  @override  List<Object?get props => [];}final classTodosOverviewSubscriptionRequestedextendsTodosOverviewEvent{  const TodosOverviewSubscriptionRequested();}final classTodosOverviewTodoCompletionToggledextendsTodosOverviewEvent{  const TodosOverviewTodoCompletionToggled({requiredthis.todo,requiredthis.isCompleted,  });  final Todo todo;  final bool isCompleted;  @override  List<Objectget props => [todo, isCompleted];}final classTodosOverviewTodoDeletedextendsTodosOverviewEvent{  const TodosOverviewTodoDeleted(this.todo);  final Todo todo;  @override  List<Objectget props => [todo];}final classTodosOverviewUndoDeletionRequestedextendsTodosOverviewEvent{  const TodosOverviewUndoDeletionRequested();}classTodosOverviewFilterChangedextendsTodosOverviewEvent{  const TodosOverviewFilterChanged(this.filter);  final TodosViewFilter filter;  @override  List<Objectget props => [filter];}classTodosOverviewToggleAllRequestedextendsTodosOverviewEvent{  const TodosOverviewToggleAllRequested();}classTodosOverviewClearCompletedRequestedextendsTodosOverviewEvent{  const TodosOverviewClearCompletedRequested();}
  • • TodosOverviewSubscriptionRequested: This is the startup event. In response, the bloc subscribes to the stream of todos from the TodosRepository.
  • • TodosOverviewTodoDeleted: This deletes a Todo.
  • • TodosOverviewTodoCompletionToggled: This toggles a todo’s completed status.
  • • TodosOverviewToggleAllRequested: This toggles completion for all todos.
  • • TodosOverviewClearCompletedRequested: This deletes all completed todos.
  • • TodosOverviewUndoDeletionRequested: This undoes a todo deletion, e.g. an accidental deletion.
  • • TodosOverviewFilterChanged: This takes a TodosViewFilter as an argument and changes the view by applying a filter.

TodosOverviewState

TodosOverviewState will keep track of a list of todos, the active filter, the lastDeletedTodo, and the status.

part of 'todos_overview_bloc.dart';enum TodosOverviewStatus { initial, loading, success, failure }final classTodosOverviewStateextendsEquatable{  const TodosOverviewState({this.status = TodosOverviewStatus.initial,this.todos = const [],this.filter = TodosViewFilter.all,this.lastDeletedTodo,  });  final TodosOverviewStatus status;  final List<Todo> todos;  final TodosViewFilter filter;  final Todo? lastDeletedTodo;  Iterable<Todo> get filteredTodos => filter.applyAll(todos);  TodosOverviewState copyWith({    TodosOverviewStatus Function()? status,List<Todo> Function()? todos,    TodosViewFilter Function()? filter,    Todo? Function()? lastDeletedTodo,  }) {return TodosOverviewState(      status: status != null ? status() : this.status,      todos: todos != null ? todos() : this.todos,      filter: filter != null ? filter() : this.filter,      lastDeletedTodo: lastDeletedTodo != null          ? lastDeletedTodo()          : this.lastDeletedTodo,    );  }  @override  List<Object?get props => [    status,    todos,    filter,    lastDeletedTodo,  ];}

In addition to the default getters and setters, we have a custom getter called filteredTodos. The UI uses BlocBuilder to access either state.filteredTodos or state.todos.

TodosOverviewBloc

The bloc does not create an instance of the TodosRepository internally. Instead, it relies on an instance of the repository to be injected via constructor.

part'todos_overview_event.dart';part 'todos_overview_state.dart';classTodosOverviewBlocextendsBloc<TodosOverviewEventTodosOverviewState{  TodosOverviewBloc({required TodosRepository todosRepository,  }) : _todosRepository = todosRepository,super(const TodosOverviewState()) {on<TodosOverviewSubscriptionRequested>(_onSubscriptionRequested);on<TodosOverviewTodoCompletionToggled>(_onTodoCompletionToggled);on<TodosOverviewTodoDeleted>(_onTodoDeleted);on<TodosOverviewUndoDeletionRequested>(_onUndoDeletionRequested);on<TodosOverviewFilterChanged>(_onFilterChanged);on<TodosOverviewToggleAllRequested>(_onToggleAllRequested);on<TodosOverviewClearCompletedRequested>(_onClearCompletedRequested);  }  final TodosRepository _todosRepository;  Future<void> _onSubscriptionRequested(    TodosOverviewSubscriptionRequested event,    Emitter<TodosOverviewState> emit,  ) async {    emit(state.copyWith(status: () => TodosOverviewStatus.loading));await emit.forEach<List<Todo>>(      _todosRepository.getTodos(),      onData: (todos) => state.copyWith(        status: () => TodosOverviewStatus.success,        todos: () => todos,      ),      onError: (_, _) => state.copyWith(        status: () => TodosOverviewStatus.failure,      ),    );  }  Future<void> _onTodoCompletionToggled(    TodosOverviewTodoCompletionToggled event,    Emitter<TodosOverviewState> emit,  ) async {final newTodo = event.todo.copyWith(isCompleted: event.isCompleted);await _todosRepository.saveTodo(newTodo);  }  Future<void> _onTodoDeleted(    TodosOverviewTodoDeleted event,    Emitter<TodosOverviewState> emit,  ) async {    emit(state.copyWith(lastDeletedTodo: () => event.todo));await _todosRepository.deleteTodo(event.todo.id);  }  Future<void> _onUndoDeletionRequested(    TodosOverviewUndoDeletionRequested event,    Emitter<TodosOverviewState> emit,  ) async {assert(      state.lastDeletedTodo != null,'Last deleted todo can not be null.',    );final todo = state.lastDeletedTodo!;    emit(state.copyWith(lastDeletedTodo: () => null));await _todosRepository.saveTodo(todo);  }  void _onFilterChanged(    TodosOverviewFilterChanged event,    Emitter<TodosOverviewState> emit,  ) {    emit(state.copyWith(filter: () => event.filter));  }  Future<void> _onToggleAllRequested(    TodosOverviewToggleAllRequested event,    Emitter<TodosOverviewState> emit,  ) async {final areAllCompleted = state.todos.every((todo) => todo.isCompleted);await _todosRepository.completeAll(isCompleted: !areAllCompleted);  }  Future<void> _onClearCompletedRequested(    TodosOverviewClearCompletedRequested event,    Emitter<TodosOverviewState> emit,  ) async {await _todosRepository.clearCompleted();  }}

onSubscriptionRequested

When TodosOverviewSubscriptionRequested is added, the bloc starts by emitting a loading state. In response, the UI can then render a loading indicator.

We use emit.forEach<List<Todo>>( ... ) which creates a subscription on the todos stream from the TodosRepository.

emit.forEach() is not the same forEach() used by lists. This forEach enables the bloc to subscribe to a Stream and emit a new state for each update from the stream.

Using await emit.forEach() is a newer pattern for subscribing to a stream which allows the bloc to manage the subscription internally.

After we handled the subscription, we will handle the other events, like addingmodifying, and deleting todos.

onTodoSaved

_onTodoSaved simply calls _todosRepository.saveTodo(event.todo).

emit is never called from within onTodoSaved and many other event handlers. Instead, they notify the repository which emits an updated list via the todos stream.

Undo

The undo feature allows users to restore the last deleted item.

_onTodoDeleted does two things. First, it emits a new state with the Todo to be deleted. Then, it deletes the Todo via a call to the repository.

_onUndoDeletionRequested runs when the undo deletion request event comes from the UI.

_onUndoDeletionRequested does the following:

  • • Temporarily saves a copy of the last deleted todo.
  • • Updates the state by removing the lastDeletedTodo.
  • • Reverts the deletion.

Filtering

_onFilterChanged emits a new state with the new event filter.

Models

There is one model file that deals with the view filtering.

todos_view_filter.dart is an enum that represents the three view filters and the methods to apply the filter.

enum TodosViewFilter { all, activeOnly, completedOnly }extension TodosViewFilterX on TodosViewFilter {  bool apply(Todo todo) {switch (this) {case TodosViewFilter.all:returntrue;case TodosViewFilter.activeOnly:return !todo.isCompleted;case TodosViewFilter.completedOnly:return todo.isCompleted;    }  }  Iterable<Todo> applyAll(Iterable<Todo> todos) {return todos.where(apply);  }}

models.dart is the barrel file for exports.

export'todos_view_filter.dart';

TodosOverviewPage

A simplified representation of the widget tree for the TodosOverviewPage is:

├── TodosOverviewPage│   └── BlocProvider<TodosOverviewBloc>│       └── TodosOverviewView│           ├── BlocListener<TodosOverviewBloc>│           └── BlocListener<TodosOverviewBloc>│               └── BlocBuilder<TodosOverviewBloc>│                   └── ListView

The TodosOverviewPage provides an instance of the TodosOverviewBloc to the subtree via BlocProvider<TodosOverviewBloc>. This scopes the TodosOverviewBloc to just the widgets below TodosOverviewPage.

view.dart is the barrel file that exports todos_overview_page.dart.

export'todos_overview_page.dart';

There are three widgets that are listening for changes in the TodosOverviewBloc.

  1. 1. The first is a BlocListener that listens for errors. The listener will only be called when listenWhen returns true. If the status is TodosOverviewStatus.failure, a SnackBar is displayed.
  2. 2. We created a second BlocListener that listens for deletions. When a todo has been deleted, a SnackBar is displayed with an undo button. If the user taps undo, the TodosOverviewUndoDeletionRequested event will be added to the bloc.
  3. 3. Finally, we use a BlocBuilder to builds the ListView that displays the todos.

The AppBar contains two actions which are dropdowns for filtering and manipulating the todos.

  • • TodosOverviewTodoCompletionToggled and TodosOverviewTodoDeleted are added to the bloc via context.read.

Widgets

widgets.dart is another barrel file that exports all the components used within the todos_overview feature.

export'todo_list_tile.dart';export'todos_overview_filter_button.dart';export'todos_overview_options_button.dart';

todo_list_tile.dart is the ListTile for each todo item.

classTodoListTileextendsStatelessWidget{  const TodoListTile({required this.todo,super.key,this.onToggleCompleted,this.onDismissed,this.onTap,  });  final Todo todo;  final ValueChanged<bool>? onToggleCompleted;  final DismissDirectionCallback? onDismissed;  final VoidCallback? onTap;  @override  Widget build(BuildContext context) {final theme = Theme.of(context);final captionColor = theme.textTheme.bodySmall?.color;return Dismissible(      key: Key('todoListTile_dismissible_${todo.id}'),      onDismissed: onDismissed,      direction: DismissDirection.endToStart,      background: Container(        alignment: Alignment.centerRight,        color: theme.colorScheme.error,        padding: const EdgeInsets.symmetric(horizontal: 16),        child: const Icon(          Icons.delete,          color: Color(0xAAFFFFFF),        ),      ),      child: ListTile(        onTap: onTap,        title: Text(          todo.title,          maxLines: 1,          overflow: TextOverflow.ellipsis,          style: !todo.isCompleted              ? null              : TextStyle(                  color: captionColor,                  decoration: TextDecoration.lineThrough,                ),        ),        subtitle: Text(          todo.description,          maxLines: 1,          overflow: TextOverflow.ellipsis,        ),        leading: Checkbox(          shape: const ContinuousRectangleBorder(            borderRadius: BorderRadius.all(Radius.circular(8)),          ),          value: todo.isCompleted,          onChanged: onToggleCompleted == null              ? null              : (value) => onToggleCompleted!(value!),        ),        trailing: onTap == null ? null : const Icon(Icons.chevron_right),      ),    );  }}

todos_overview_options_button.dart exposes two options for manipulating todos:

  • • toggleAll
  • • clearCompleted
@visibleForTestingenum TodosOverviewOption { toggleAll, clearCompleted }classTodosOverviewOptionsButtonextendsStatelessWidget{  const TodosOverviewOptionsButton({super.key});  @override  Widget build(BuildContext context) {final l10n = context.l10n;final todos = context.select((TodosOverviewBloc bloc) => bloc.state.todos);final hasTodos = todos.isNotEmpty;final completedTodosAmount = todos.where((todo) => todo.isCompleted).length;return PopupMenuButton<TodosOverviewOption>(      shape: const ContinuousRectangleBorder(        borderRadius: BorderRadius.all(Radius.circular(16)),      ),      tooltip: l10n.todosOverviewOptionsTooltip,      onSelected: (options) {switch (options) {case TodosOverviewOption.toggleAll:            context.read<TodosOverviewBloc>().add(const TodosOverviewToggleAllRequested(),            );case TodosOverviewOption.clearCompleted:            context.read<TodosOverviewBloc>().add(const TodosOverviewClearCompletedRequested(),            );        }      },      itemBuilder: (context) {return [          PopupMenuItem(            value: TodosOverviewOption.toggleAll,            enabled: hasTodos,            child: Text(              completedTodosAmount == todos.length                  ? l10n.todosOverviewOptionsMarkAllIncomplete                  : l10n.todosOverviewOptionsMarkAllComplete,            ),          ),          PopupMenuItem(            value: TodosOverviewOption.clearCompleted,            enabled: hasTodos && completedTodosAmount > 0,            child: Text(l10n.todosOverviewOptionsClearCompleted),          ),        ];      },      icon: const Icon(Icons.more_vert_rounded),    );  }}

todos_overview_filter_button.dart exposes three filter options:

  • • all
  • • activeOnly
  • • completedOnly
classTodosOverviewFilterButtonextendsStatelessWidget{  const TodosOverviewFilterButton({super.key});  @override  Widget build(BuildContext context) {final l10n = context.l10n;final activeFilter = context.select(      (TodosOverviewBloc bloc) => bloc.state.filter,    );return PopupMenuButton<TodosViewFilter>(      shape: const ContinuousRectangleBorder(        borderRadius: BorderRadius.all(Radius.circular(16)),      ),      initialValue: activeFilter,      tooltip: l10n.todosOverviewFilterTooltip,      onSelected: (filter) {        context.read<TodosOverviewBloc>().add(          TodosOverviewFilterChanged(filter),        );      },      itemBuilder: (context) {return [          PopupMenuItem(            value: TodosViewFilter.all,            child: Text(l10n.todosOverviewFilterAll),          ),          PopupMenuItem(            value: TodosViewFilter.activeOnly,            child: Text(l10n.todosOverviewFilterActiveOnly),          ),          PopupMenuItem(            value: TodosViewFilter.completedOnly,            child: Text(l10n.todosOverviewFilterCompletedOnly),          ),        ];      },      icon: const Icon(Icons.filter_list_rounded),    );  }}
基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-04-28 14:17:45 HTTP/1.1 GET : https://www.yeyulingfeng.com/a/562128.html
  2. 运行时间 : 0.183807s [ 吞吐率:5.44req/s ] 内存消耗:4,559.11kb 文件加载:145
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=074573ae257d1161daa210e56992375a
  1. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/composer/autoload_static.php ( 6.05 KB )
  7. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/ralouphie/getallheaders/src/getallheaders.php ( 1.60 KB )
  10. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  11. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  12. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  13. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  14. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  15. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  16. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  17. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  18. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  19. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions_include.php ( 0.16 KB )
  21. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/guzzlehttp/guzzle/src/functions.php ( 5.54 KB )
  22. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  23. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  24. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  25. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/provider.php ( 0.19 KB )
  26. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  27. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  28. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  29. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/common.php ( 0.03 KB )
  30. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  32. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/alipay.php ( 3.59 KB )
  33. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  34. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/app.php ( 0.95 KB )
  35. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cache.php ( 0.78 KB )
  36. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/console.php ( 0.23 KB )
  37. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/cookie.php ( 0.56 KB )
  38. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/database.php ( 2.48 KB )
  39. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/filesystem.php ( 0.61 KB )
  40. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/lang.php ( 0.91 KB )
  41. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/log.php ( 1.35 KB )
  42. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/middleware.php ( 0.19 KB )
  43. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/route.php ( 1.89 KB )
  44. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/session.php ( 0.57 KB )
  45. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/trace.php ( 0.34 KB )
  46. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/config/view.php ( 0.82 KB )
  47. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/event.php ( 0.25 KB )
  48. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  49. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/service.php ( 0.13 KB )
  50. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/AppService.php ( 0.26 KB )
  51. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  52. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  53. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  54. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  55. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  56. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/services.php ( 0.14 KB )
  57. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  58. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  59. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  60. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  61. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  62. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  63. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  64. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  65. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  66. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  67. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  68. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  69. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  70. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  71. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  72. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  73. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  74. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  75. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  76. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  77. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  78. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  79. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  80. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  81. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  82. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  83. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  84. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  85. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  86. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  87. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/Request.php ( 0.09 KB )
  88. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  89. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/middleware.php ( 0.25 KB )
  90. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  91. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  92. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  93. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  94. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  95. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  96. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  97. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  98. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  99. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  100. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  101. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  102. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  103. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/route/app.php ( 3.94 KB )
  104. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  105. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  106. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Index.php ( 9.87 KB )
  108. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/BaseController.php ( 2.05 KB )
  109. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  110. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  111. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  112. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  113. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  114. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  115. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  116. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  117. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  118. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  119. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  120. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  121. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  122. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  123. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  124. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  125. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  126. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  127. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  128. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  129. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  130. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  131. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  132. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  133. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  134. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  135. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/app/controller/Es.php ( 3.30 KB )
  136. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  137. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  138. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  139. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  140. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  141. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  142. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  143. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  144. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/runtime/temp/c935550e3e8a3a4c27dd94e439343fdf.php ( 31.50 KB )
  145. /yingpanguazai/ssd/ssd1/www/wwww.yeyulingfeng.com/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000828s ] mysql:host=127.0.0.1;port=3306;dbname=wenku;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000715s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000333s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000267s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000494s ]
  6. SELECT * FROM `set` [ RunTime:0.000205s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000599s ]
  8. SELECT * FROM `article` WHERE `id` = 562128 LIMIT 1 [ RunTime:0.002173s ]
  9. UPDATE `article` SET `lasttime` = 1777357065 WHERE `id` = 562128 [ RunTime:0.003440s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000272s ]
  11. SELECT * FROM `article` WHERE `id` < 562128 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000409s ]
  12. SELECT * FROM `article` WHERE `id` > 562128 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000423s ]
  13. SELECT * FROM `article` WHERE `id` < 562128 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.003009s ]
  14. SELECT * FROM `article` WHERE `id` < 562128 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.006063s ]
  15. SELECT * FROM `article` WHERE `id` < 562128 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.002461s ]
0.187223s