3

编辑:

因为我将最初的赏金授予300@arcain 太晚了,所以我要重新开放。并将额外的奖励授予150@arcain。当然,除非有人提供更好的答案。:)

/ 编辑

考虑以下形式:

language | region | active | default |
-----------------------------------------------
en       | GB     | [x]    | (*)     | [X delete]
nl       | NL     | [x]    | ( )     | [X delete]
nl       | BE     | [x]    | ( )     | [X delete]

[x] let visitors browser-settings determine the default language

[save]

上表的设置将保存在一个数据库表中,其中列映射到上述列(显然不包括最后一列)。

所有(保存和删除)操作都直接发送到本地化控制器。本地化控制器基本上调用 LocalizationService 上的方法,如下所示:

$localizationService->updateCollection( $_POST ) // update collection settings
// or
$localizationService->delete( $_POST ) // delete a single locale

LocalizationService 又调用 LocaleMapperDb,如下所示:

foreach( $localeCollection as $locale )
{
    $localeMapperDb->update( LocaleModel $locale );
}
// or
$localeMapperDb->delete( LocaleModel $locale );

但是,保存此设置的责任是:

[x] let visitors browser-settings determine default language

它将保存在名为 site_settings 的数据库表中。我想到了几个选择:

  • 在 LocalizationController 中使用 SiteService / SiteSettingsService。但是,完整的表单已经在 LocalizationService 中生成和处理。
  • 在 LocalizationService 中使用 SiteMapperDb / SiteSettingsMapperDb 并在 updateCollection( $_POST ) 中使用它
  • 在 LocaleMapperDb 中使用 SiteMapperDb / SiteSettingsMapperDb

第一个和最后一个选项看起来是最糟糕的选项,但我不确定。你觉得最好的选择是什么?或者,也许您有其他选择,我没有想到?

4

1 回答 1

2

我认为在这种情况下将域模型对象投影到视图模型对象上效果很好。

在附加代码的情况下(请原谅我用 C# 编写它;它应该是相当可移植的)域模型对象永远不会公开(它们只能在服务对象中直接访问。)服务只公开视图模型对象, like LocalViewModel,并且这些视图模型对象由控制器操作。

还将服务返回的LocaleConfigController数据映射到一个LocaleConfigViewModel对象中,而这个对象是唯一与视图直接交换的对象。

所以,简而言之,视图有一个专用的控制器,视图通过LocaleConfigViewModel对象与控制器通信。控制器操作LocaleConfigViewModel对象并调用ILocaleConfigService和 的实现ISystemConfigService。服务对象从不将域模型暴露给控制器,它们负责将视图模型对象映射到域模型对象(通过任何需要的持久性机制。)

请注意,语言环境服务是一个配置服务,它没有任何实现来查找正确的本地化字符串是什么。我会将它放到另一个服务中,因为它可以用于您不想公开任何允许更改本地化配置的方法的地方。

例如,在应用程序的管理端,您可能需要本地化配置服务和本地化字符串呈现服务(因为管理站点也可以本地化。)对于面向客户的前端,您可能只需要本地化字符串呈现服务,因为系统配置修改应该是不需要的并且超出了该站点的范围。

所以,最后回答你的问题:控制器包含对语言环境和系统配置服务的引用,并且控制器专用于视图——它有一个定义明确的合同,其中只有LocaleConfigViewModels 被交换。

至于保存系统范围设置的责任在哪里,控制器负责将系统设置解包LocaleConfigViewModel并将它们推送到适当的服务(在这种情况下是ISystemConfigService实例)中,它们将被持久化。

class LocaleViewModel
{
  public int Id;
  public string Language;
  public string Region;
  public bool Enabled;
  public bool Deleted;
}

class LocaleConfigViewModel
{
  public bool UseVisitorBrowserLocale;
  public LocaleViewModel DefaultLocale;
  public List<LocaleViewModel> Locales; 
}

class LocaleConfigController : ILocaleConfigController
{
  ILocaleConfigService localeConfig;
  ISystemConfigService systemConfig;

  public void Save(LocaleConfigViewModel model)
  {
    foreach (var locale in model.Locales)
    {
      if (locale.Deleted)
      {
        localeConfig.DeleteLocale(locale);
        continue;
      }
      localeConfig.UpdateLocale(locale);
    }
    systemConfig.DefaultLocaleId = model.DefaultLocale.Id;
    systemConfig.UseVisitorBrowserLocale = model.UseVisitorBrowserLocale;
  }

  public LocaleConfigViewModel GetCurrentView()
  {
    var model = new LocaleConfigViewModel();
    model.Locales = localeConfig.Locales;
    model.DefaultLocale = model.Locales.FirstOrDefault(l => l.Id == systemConfig.DefaultLocaleId);
    model.UseVisitorBrowserLocale = systemConfig.UseVisitorBrowserLocale;
    return model;
  }

  // ...
}

interface ILocaleConfigController
{
  void Save(LocaleConfigViewModel model);
  LocaleConfigViewModel GetCurrentView();
  // ... 
}

interface ILocaleConfigService // services will be stateless and threadsafe
{
  void DeleteLocale(LocaleViewModel locale);
  void UpdateLocale(LocaleViewModel locale);
  List<LocaleViewModel> Locales { get; }
  // ...
}

interface ISystemConfigService // services will be stateless and threadsafe
{
  int DefaultLocaleId { get; set; }
  bool UseVisitorBrowserLocale { get; set; }
  // ...
}
于 2011-01-28T07:21:36.457 回答