在数组中使用变量

时间:2012-09-14 08:41:45

标签: php

我借用了漂亮的 Cokidoo DateTime 类,将常规DateTime转换为“以前格式化”。

我正在开发多语言网站,并希望用变量替换year agoyears agomonth ago

代码示例:

protected $strings = array(
        'y' => array('1 year ago', '%d years ago'),
        'm' => array('1 month ago', '%d months ago'),
        'd' => array('1 day ago', '%d days ago'),
        'h' => array('1 hour ago', '%d hours ago'),
        'i' => array('1 minute ago', '%d minutes ago'),
        's' => array('now', '%d secons ago'),
    );


这可以不使用替换方法吗?

显然这不起作用:

'm' => array('1' . $month_ago, '%d' . $months_ago),

请帮忙吗?

3 个答案:

答案 0 :(得分:4)

如果没有扩展DateTime,该类会更有用。它唯一能做的就是 format 一个日期,它完全没有理由 一个日期。它可以轻松地按需创建DateTime并对其进行处理而不是$this

如果你做了这个修改(并且适当地将类重命名为例如DateTimeDiffFormatter),那么突然所有的可能性都是开放的:你可以将一个参数传递给确定要使用的语言的构造函数,甚至更好的传递在一些参考你的i18n组件。然后例如你可以

// I have no idea why this was protected, and probably the class author did not as well
private $strings = array(
    'y' => array('years_ago_1', 'years_ago_n'),
    // etc etc
);

return sprintf($localizer->get_string($this->strings[$intervalKey][$pluralKey]),
               $value);

最后,假设您可以将本地化字符串的格式硬编码为“X分钟前”#34;这是一个非常糟糕的主意。和类似的。这个数字需要是格式字符串的一部分,因为在许多文化中它不会超过"多久以前"一部分。

更新

我改编了Ilia的候选解决方案,使其符合上述建议;结果是here

答案 1 :(得分:0)

你有撇号,你不需要它们。

你好吗:

 $month_ago = 'month ago';
 $months_ago = 'months ago';

//Further on within the array
'm' -> array('1 '.$month_ago, '%d '.$months_ago);

答案 2 :(得分:0)

根据建议的想法,我终于找到了一个多功能的多语言解决方案,用于返回时差。

请对我温柔,因为我是面向对象风格编程的完全初学者,这实际上是我的第一个任务。如果您留下评论或建议的想法,我会非常高兴。

特别感谢Jon,对不起,我无法体现你的所有想法。我接受你的回答,因为它有非常好的建议和解释!

描述

  1. 在我的数据库中,我有added_time字段,它指的是Unix时间戳格式中每个上传视频的创建时间,例如: 1345284190
    此时间戳传递给构造函数,如new creationTime( '@' . $timestamp);

  2. 我有一个特殊的功能循环播放每个视频并插入例如:视频已添加 27天前

  3. 我终于通过使用Cokidoo在PHP Time Manual提供的漂亮示例实现了这一点,并添加了对多语言网站的支持,取代years agomonths agodays ago等等,包含从语言文件派生的任何文本。

    扭捏

    1. 我更改了初始值(即:一年前月前前一天等),用英语(为了能够在多语种网站中使用它们)写成易于处理的内容,例如:year_agomonth_agoday_ago等。

    2. 然后我爆炸了返回输出的初始$value变量,例如: 1年前 1个月前 1天前并按照建议使用返回sprintf

    3. 最后我添加了getLocalized函数,将此类与我的语言文件相关联。

    4. 这是不会发出警告的最终和工作代码(警告已启用; PHP版本5.4.6 )。
      我已将班级名称从Cokidoo_DateTime重命名为creationTime

      class creationTime extends DateTime {
      
          private $strings = array(
              'y' => array('1 year_ago', '%d years_ago'),
              'm' => array('1 month_ago', '%d months_ago'),
              'd' => array('1 day_ago', '%d days_ago'),
              'h' => array('1 hour_ago', '%d hours_ago'),
              'i' => array('1 minute_ago', '%d minutes_ago'),
              's' => array('just_now', '%d seconds_ago'),
          );
      
         private function getLocalized($string) {
      
              global $lang;
      
              $string == 'year_ago' ? $string = $lang['global.year_ago'] : null;
              $string == 'years_ago' ? $string = $lang['global.years_ago'] : null;
              $string == 'month_ago' ? $string = $lang['global.month_ago'] : null;
              $string == 'months_ago' ? $string = $lang['global.months_ago'] : null;
              $string == 'day_ago' ? $string = $lang['global.day_ago'] : null;
              $string == 'days_ago' ? $string = $lang['global.days_ago'] : null;
              $string == 'hour_ago' ? $string = $lang['global.hour_ago'] : null;
              $string == 'hours_ago' ? $string = $lang['global.hours_ago'] : null;
              $string == 'hour_ago' ? $string = $lang['global.hour_ago'] : null;
              $string == 'hours_ago' ? $string = $lang['global.hours_ago'] : null;
              $string == 'minute_ago' ? $string = $lang['global.minute_ago'] : null;
              $string == 'minutes_ago' ? $string = $lang['global.minutes_ago'] : null;
              $string == 'just_now' ? $string = $lang['global.just_now'] : null;
              $string == 'seconds_ago' ? $string = $lang['global.seconds_ago'] : null;
      
              return $string;
          }
      
          /**
           * Returns the difference from the current time in the format X time ago
           * @return string
           */
      
         public function __toString() {
              $now = new DateTime('now');
              $diff = $this->diff($now);
              foreach($this->strings as $key => $value){
                  if( ($text = $this->getDiffText($key, $diff)) ){
                      return $text;
                  }
              }
              return '';
          }
      
          /**
           * Try to construct the time diff text with the specified interval key
           * @param string $intervalKey A value of: [y,m,d,h,i,s]
           * @param DateInterval $diff
           * @return string|null
           */
          protected function getDiffText($intervalKey, $diff){
              $pluralKey = 1;
              $value = $diff->$intervalKey;
              if($value > 0){
                  if($value < 2){
                      $pluralKey = 0;
                  }
                  $value = explode(' ', sprintf($this->strings[$intervalKey][$pluralKey], $value) );          
                  return sprintf('%d %s', implode(array_slice($value, 0)), $this->getLocalized(implode(array_slice($value, 1))));
              }
              return null;
          }
      }
      


      EDITED

      这个奇妙的解决方案虽然做了同样的事情,但具有更好的格式和结构(通过 Jon )。

      class DateFormatter {
          private $localizer;
      
          private $strings = array(
              'y' => array('global.years_ago_1', 'global.years_ago_n'),
              'm' => array('global.months_ago_1', 'global.months_ago_n'),
              'd' => array('global.days_ago_1', 'global.days_ago_n'),
              'h' => array('global.hours_ago_1', 'global.hours_ago_n'),
              'i' => array('global.minutes_ago_1', 'global.minutes_ago_n'),
              's' => array('global.seconds_ago_1', 'global.seconds_ago_n'),
          );
      
          public function __construct(Localizer $localizer) {
              $this->localizer = $localizer;
          }
      
          /**
           * Returns the difference from the current time in the format X time ago
           * @return string
           */
          public function formatHowLongAgo(DateTime $date) {
              $now = new DateTime('now');
              $diff = $date->diff($now);
              foreach($this->strings as $unitOfTime => $formatStrings){
                  $howMany = $diff->$unitOfTime;
                  if (!$howMany) {
                      continue;
                  }
      
                  $plural = $howMany > 1;
                  return $this->localizer->format($this->strings[$unitOfTime][$plural], $howMany);
              }
              return '??';
          }
      }
      
      // Packaged the localization stuff inside a class so that it's not
      // just hanging around in the global scope. Not much to see here,
      // a "real" localizer would have more features.
      class Localizer {
          private $lang = array(
              'global.years_ago_1'    => '1 year ago',
              'global.years_ago_n'    => '%d years ago',
              'global.months_ago_1'   => '1 month ago',
              'global.months_ago_n'   => '%d months ago',
              'global.days_ago_1'     => '1 day ago',
              'global.days_ago_n'     => '%d days ago',
              'global.hours_ago_1'    => '1 hour ago',
              'global.hours_ago_n'    => '%d hours ago',
              'global.minutes_ago_1'  => '1 minute ago',
              'global.minutes_ago_n'  => '%d minutes ago',
              'global.seconds_ago_1'  => 'just now',
              'global.seconds_ago_n'  => '%d seconds ago',
          );
      
          public function format($string /*, $param1, $param2, ... */) {
              $params = func_get_args(); // get variable # of params
              array_shift($params); // remove first item, we already have it in $string
              if (!isset($this->lang[$string])) {
                  return '[['.$string.']]'; // a placeholder
              }
      
              return vsprintf($this->lang[$string], $params);
          }
      }
      
      $localizer = new Localizer;
      $timestamp = '1345284190';  // Example of Unix Timestamp
      $datetime = new DateTime("@$timestamp");
      $formatter = new DateFormatter($localizer);
      
      echo $formatter->formatHowLongAgo($datetime);