跳转到内容

理解诺亚的分类信息/多图上传

来自 Wikibooks,开放世界中的开放书籍

在诺亚的分类信息中,广告只能提交一张图片,我们希望提交 n 张图片。

解决方案

[编辑 | 编辑源代码]

按照下面列出的步骤修改源代码

初步编码

[编辑 | 编辑源代码]

在我们做任何事情之前,我想将诺亚的图像操作封装到一个类中,或者至少是一组函数中。最初编写代码的人没有这样做。我认为这是一个很大的错误,因为它极大地复杂化了代码。

以下内容来自诺亚源代码和我的天才常识。所有这些都将放在一个新文件中,我们将称之为 image.php。我们的想法是创建一个图像管理库,我们可以将其用于其他项目,而无需进行太多重编码。

Image.php 源代码

目标功能

[编辑 | 编辑源代码]

现在让我们先谈谈我们的目标。我们希望实现以下功能

  • 修改从设定类别屏幕保存的图片最大数量(因此每个类别可以允许可变数量的图片)
  • 从类别屏幕修改最大图片大小和缩略图大小
  • 上传系列中的第一张图片将用作列出所有广告时的显示图片
  • 删除广告时,必须删除图片及其缩略图
  • 每个不同的类别都必须能够插入自定义 HTML 文本,这些文本将用作分隔符。
  • 动态创建上传字段,以便提交不显得杂乱

修改 gorum/dbproperty.php

[编辑 | 编辑源代码]

由于所有 object_vars 都自动保存到数据库中,因此使用 $this->data 将数据从一个函数传递到下一个函数存在问题。为了解决这个问题,需要对 dbproperty.php 进行以下修改。

 function getCreateSetStr($base, $typ, $create=TRUE)
 {
     $object_vars = get_object_vars($base);
     $firstField = TRUE;
     $query = "";
     $typ = $base->getTypeInfo();
     foreach( $object_vars as $attribute=>$value )
     {
  // NEW DAWID
  if (!isset($typ["attributes"][$attribute]))
  continue;
  // NEW DAWID

修改 gorum/object.php

[编辑 | 编辑源代码]

更改函数 getVisibility,如所示

 function getVisibility( $typ, $attr )
 {
     global $gorumroll;
  
  if (!isset($typ["attributes"][$attr]))
  return Form_hidden;

修改分类

[编辑 | 编辑源代码]

首先,我们需要在我们的类别数据库(表:classifieds_classifiedscategory)中添加 6 行新数据。

imagesAllowed, Type int(4), default = 10, Unsigned
ThumbSizeX, Type int(10), default = 64, Unsigned
ThumbSizeY, Type int(10), default = 100, Unsigned
imageMaxSizeX, Type int(12), default = 800, Unsigned
imageMaxSizeY, Type int(12), default = 600, Unsigned
imageSpacer, Type varchar(250), default = 'HTML TEXT'

这些是我添加的新行。从信息中您可以看到,imagesAllowed 的范围是 0-16,thumbSize 的范围是 0-1024,imageSize 的范围是 0-2048。如果这些太少或太多,请相应地调整,以免占用数据库空间。

以下是用于添加这些内容的 SQL 脚本

 ALTER TABLE `classifieds_classifiedscategory` ADD `imagesAllowed` INT( 4 ) UNSIGNED NOT NULL DEFAULT '10',
 ADD `thumbSizeX` INT( 10 ) UNSIGNED NOT NULL DEFAULT '64',
 ADD `thumbSizeY` INT( 10 ) UNSIGNED NOT NULL DEFAULT '100',
 ADD `imageMaxSizeX` INT( 12 ) UNSIGNED NOT NULL DEFAULT '800',
 ADD `imageMaxSizeY` INT( 12 ) UNSIGNED NOT NULL DEFAULT '600';
 ADD `imageSpacer` VARCHAR( 250 ) NOT NULL DEFAULT '<br/><img src="i/spacer.gif" alt="." width="$thumbWidth" height="20" />';

修改 category.php 的源代码

由于诺亚使用的框架很出色,我们可以轻松地将更多字段添加到类别中。只需在文件顶部添加这些行。

 $category_typ["attributes"]["picture"] =  
             array(
                 "type"=>"VARCHAR",
                 "file",
                 "max" =>"250"
              );
 
 /* DAWID JOUBERT IMAGE MODIFICATIONS ADDITIONS */
 $category_typ["attributes"]["imagesAllowed"] =  
             array(
                 "type"=>"INT",
                 "text",
                 "max" =>"16"
              );  
 $category_typ["attributes"]["thumbSizeX"] =  
             array(
                 "type"=>"INT",
                 "text",
                 "max" =>"1024"
              );    
 $category_typ["attributes"]["thumbSizeY"] =  
             array(
                 "type"=>"INT",
                 "text",
                 "max" =>"1024"
              ); 
 $category_typ["attributes"]["imageMaxSizeX"] =  
             array(
                 "type"=>"INT",
                 "text",
                 "max" =>"2048"
              );
 $category_typ["attributes"]["imageMaxSizeY"] =  
             array(
                 "type"=>"INT",
                 "text",
                 "max" =>"2048"
              ); 
 $category_typ["attributes"]["imageSpacer"] =  
             array(
                 "type"=>"VARCHAR",
                 "text",
                 "max" =>"250"
              );        
 
 class ClassifiedsCategory extends Category

将新文本添加到语言文件

现在,我们还需要将以下内容添加到 lang_en.php(以及您计划使用的所有其他语言)中。为了保持一致性,请将其添加到名为“类别”的注释之后

 // Dawid Joubert Image Editing
 $lll["imagesAllowed"]="Number of Images Allowed";
 $lll["thumbSizeX"]="Generated Thumbnails' size X";
 $lll["thumbSizeY"]="Generated Thumbnails' size Y";
 $lll["imageMaxSizeX"]="Max Image Size X";
 $lll["imageMaxSizeY"]="Max Image Size Y";
 $lll["imageSpacer"]="HTML Text to place after each image (use as spacer)";
 $lll["pictureTemp"]='Pictures';
 $lll["imageFileNotLoaded"]='Image file not saved/created!';

修改广告

[编辑 | 编辑源代码]

在表 classifieds_advertisement 中,我们不会添加任何行。相反,我们将修改一个名为 picture 的现有行。

Picture 是大小为 250 的字符串(VARCHAR)。目前,诺亚将上传的 1 张图片的扩展名存储在 picture 中。我们将执行类似的操作,我们将存储文件的扩展名,但将它们用逗号分隔。因此,第一个扩展名是第一张图片,第二个扩展名是第二张图片,依此类推。

现在我们必须修改 advertisements.php 的源代码 这将是大量的修改,因此让我们首先就当前的功能达成一致。

图片保存在“$adAttDir/$this->id".".".$ext”下,它们的缩略图保存在“$adAttDir/th_$this->id".".".$ext”下。这种格式对于存储单个图片没有问题,但对于存储多个图片来说就存在问题。因此,我们将对其进行修改。

首先,为了保持向后兼容性,我们将保留序列中第一个图片的当前格式,但第二个、第三个和第 n 个图片将采用以下模式。

完整图片:“$adAttDir/$this->id"."-$i.".$this->picture”

缩略图:“$adAttDir/th_$this->id"."-$i.".$this->picture”

其中 $i 是图片编号,从 0 开始,因此如果用户有 6 张 jpeg 图片,它们将被命名为以下方式

pictures/listings/5.jpg // First image. Shown in advert listing
pictures/listings/5-0.jpg // Second Image. Shown in details view (when viewing the advert)
pictures/listings/5-1.jpg // ""
pictures/listings/5-2.jpg // ""
pictures/listings/5-3.jpg // ""
pictures/listings/5-4.jpg // ""

我们需要一个函数,可以将像“jpg,gif,jpg”这样的字符串拆分为数组(“jpg”,“gif”,“jpg”)。在 image.php 中已经创建了这样一个函数,名为 getImageExtensionsFromString($string)


因此,我认为我们需要修改 4 个函数

  • delete()
    当您删除广告时,将调用此函数
  • showListVal()
    此函数用于显示广告列表和广告详情本身中的每条信息。我们需要此函数,以便它现在在查看广告详情时列出所有图片
  • activateVariableFields()
    此函数需要进行修改,以便它显示上传 n 张图片的选项
  • storeAttatchment()
    修改,以便它实际存储所有传入的图片
  • showDetials()
    显示广告的详细视图

替换里面的所有内容

 if ($this->picture) 
 {
 .. Old Code ..
 };

用这个,使整个块看起来像(现在任何人都敢告诉我这看起来不干净!!!)

  if( $this->picture )
  {
  $this->getImageExtensions();
  $limit = count($this->imageExtensions); 
  for ($i=0;$i < $limit;$i++)
  {
  cleanDelete($this->getImageName($i));
  cleanDelete($this->getThumbName($i)); 
  }
  }

showListVal()

[编辑 | 编辑源代码]

替换里面的所有内容

 elseif ($attr=="showpic") 
 {
  ..old source code...
 }
</syntaxhighlight">

With. After which I briefly describe what we are doing.
<syntaxhighlight lang="php">
 elseif ($attr=="showpic") 
  {
  $s="<img src='$adAttDir/no.png'>"; // Will be overwritten later
  $this->getImageLimits();
  
  if($this->picture && $this->imagesAllowed) // Do we have any extensions to work with?
  {
  // Create the image extensions for use
  $this->getImageExtensions(); 
  $this->Debug(); 
  // Are we in the details view?
  if ($gorumroll->method == "showdetails")
  {
  $limit = count($this->imageExtensions); 
  $s = ''; 
  for ($i=0;$i < $limit;$i++)
  {
  if (strlen($this->imageExtensions[$i]) > 2)
  { 
  $s .= $this->getImageHTML($i)."<br />"; 
  }
  } 
  }
  else
  { 
  // Just make the output equal to a single image
  $s= $this->getImageHTML(0);
  }
  }
  }

$s 是函数的输出缓冲区。所有 HTML 必须写入其中。我们首先将 $s 设置为默认图像图标。这样,如果未找到任何图像,至少会显示默认图标。接下来,我们查看 picture 中是否有任何文本(请记住,在 php 中 "" 或 0 或 "0" 都被视为“false”)。因此,如果其中有图片,我们会继续。使用 getImageExtensions() 提取图像扩展名。然后,根据这是列表视图还是详细视图,我们将第一个或所有图像打印到缓冲区。


activateVariableFields()

[编辑 | 编辑源代码]

在 advertisement.php 的顶部,有 $item_typ["attributes"]["picture"] = {..}; 将此添加到数组 "form invisible" 中,这将确保在修改/创建添加时不会将其添加到表单中。上面提到的声明现在将如下所示。

 $item_typ["attributes"]["picture"] =  
             array(
                 "type"='>'"VARCHAR",
                 "file",
                 "max" ='>'"250",
  "form invisible"
              );

现在,下一部分将确保在调用 CREATE_FORM 和 MODIFY_FORM 方法时,图像字段将添加到表单中。将此添加到全局定义之后。

 global $gorumroll, $expiration;
 // NEW CODE DAWID
 $this-'>'getImageLimits(); 
 // Create new input boxes for each picture, but only if we are creating a new advert or modifying an existing one
 if (($gorumroll-'>'method == "modify_form") || ($gorumroll-'>'method == "create_form"))
 {
  for ($i = 0;$i '<' $this-'>'imagesAllowed;$i++)
  {
  $lll["picture$i"]=str_replace('$i',$i$,lll["pictureTemp"]); // Creates language thingies
  $item_typ["attributes"]["picture$i"] =  
  array(
  "type"='>'"VARCHAR",
  "file",
  "max" ='>'"250"
   ); 
  };
 };
 // NEW CODE DAWID
 
 hasAdminRights($isAdm);

abba

此函数验证上传的单个图像,然后再存储图像。其余的验证由它继承的类完成。只需删除整个内容即可。

storeAttachment()

[编辑 | 编辑源代码]

此函数几乎完全修改了,只需复制新的函数即可。

 function storeAttachment()
 {
     global $HTTP_POST_FILES;
     global $whatHappened, $lll, $infoText;
     global $adAttDir, $applName, $itemClassName;
     global $maxPicSize;
  
  // New code
     // Load this class
  $this->getImageLimits(); // Get the dimensions and stuff allowed
  $this->getImageExtensions();
  $parsedAtleastOne = false;
  $count = 0;
  // Loop for every image allowed
  for ($i = 0;$i < $this->imagesAllowed;$i++)
  { 
  if ((isset($this->imageExtensions[$count]) == false))
  $this->imageExtensions[$count] = ".";
  
  if (strlen($this->imageExtensions[$count]) > 2) 
  {
  $count++;
  $hasImage = true;
  } else $hasImage = false;
  
  $ind = "picture$i";
      if (!isset($HTTP_POST_FILES[$ind]["name"]) || $HTTP_POST_FILES[$ind]["name"]=="")
  continue;
 
  if (!file_exists($HTTP_POST_FILES[$ind]["tmp_name"]))
  {
  // This should never happen
  handleError("Temp Image doesn't exists?? WTF"); 
  continue;
  }
 
  if (strstr($HTTP_POST_FILES[$ind]["name"]," "))
  {
          $infoText .= $lll["spacenoatt"].'<br />';
  continue;
      }
  
      if ($HTTP_POST_FILES[$ind]["tmp_name"]=="none")
  continue;
  
      if ($HTTP_POST_FILES[$ind]["size"] > $maxPicSize) 
  {
          $infoText .= sprintf($lll["picFileSizeToLarge2"], $maxPicSize).'<br />';
  continue; 
      }
  
  $fname=$HTTP_POST_FILES[$ind]["tmp_name"];
  $size = getimagesize($fname);
  if (!$size) 
  {
  $infoText.=$lll["notValidImageFile"].'<br />';
  continue; 
  }
  
  $type = $size[2];
  global $g_Extensions; // Found in image.php
  if (!isset($g_Extensions[$type])) 
  {
  $infoText .=$lll["notValidImageFile"].'<br />';
  continue; 
  } 
  
  // We are checking dimensions anymore as we might as well resize the image
 /* if( $size[0]>$this->imageMaxSizeX || $size[1]>$this->imageMaxSizeY )
  {
  $infoText .=sprintf($lll["picFileDimensionToLarge"], $this->imageMaxSizeX, $this->imageMaxSizeY).'<br />';
  $whatHappened = "invalid_form";
  continue;
  } */ 
  if ($hasImage) $count--;
  
  // Instanciate a new image
  $image = new myImage;
  // Read the image
  $image->ReadImage($HTTP_POST_FILES[$ind]["tmp_name"]);
 
  // Remove old pictures and thumbnails
  cleanDelete($this->getImageName($count));
  cleanDelete($this->getThumbName($count));
  
  // Save the image extension
  $this->imageExtensions[$count] = $g_Extensions[$type]; 
 
  // Now create our image
  if ($image->CreateLocal($this->getImageName($count),$this->imageMaxSizeX$,this->imageMaxSizeY))
  {
  // Create the thumb
  $image->CreateLocal($this->getThumbName($count),$this->thumbSizeX$,this->thumbSizeY,true);   
  
  $parsedAtleastOne = true; 
  $count++;
  }
  else 
  {
  // Why wasn't it created, could it be because the file format doesn't support resizing
  if ($image->supported == false)
  $infoText .=sprintf($lll["picFileDimensionToLarge"], $this->imageMaxSizeX, $this->imageMaxSizeY).'<br />';
  else $infoText.=$lll["imageFileNotLoaded"].'<br />';
  $this->imageExtensions[$count] = "."; 
  }
  }
     $HTTP_POST_FILES["picture"]["name"]="";
  if ($parsedAtleastOne)
  {
  $this->picture = addslashes(createImageExtensionsStringFromArray($this->imageExtensions));
  $this->Debug();
  // Create the extensions string
  $query = "UPDATE $applName"."_$itemClassName SET picture='$this->picture'".
   " WHERE id=$this->id";
  executeQuery( $query );
  }
     return ok;
 }

showDetails()

[编辑 | 编辑源代码]

更改内部的所有内容

 if($this-'>'picture)
 {
  ...
 }

改为

  if($this->picture)
  { 
  $s.="<tr><td valign='top' align='left' rowspan='30' class='cell'>\n";
  $s.=$this->showListVal("showpic");
  $s.="</td>";
  $s.="</tr>\n";
  }

最后更多函数

[编辑 | 编辑源代码]

将这些新函数添加到文件顶部

 /**********************************/
 // Advertisement specific image functions
 function cleanDelete($name)
 {
  if (file_exists($name))
  {
  // Attempt to delete
      $ret=@unlink($name); 
  if(!$ret) $infoText=sprintf($lll["cantdelfile"],$name);
  return $ret;
  }
  return true;
 };
 
 function getImageExtensionsFromString($string)
 {
  return split('[,]', $string);
 };
 
 function createImageExtensionsStringFromArray($arr)
 {
  $out = "";
  foreach ($arr as $value)
  {
  $out .= $value.',';
  }
  return $out;
 }
 
 /**********************************/
 
 class Advertisement extends Item
 {
 
 /**********************************/
 // Advertisement specific image functions
 
  function getImageExtensions()
  {
  if (isset($this->picture))
  $this->imageExtensions = getImageExtensionsFromString($this->picture);
  }
  
  function getImageName($i)
  {
  if (!isset($this->imageExtensions[$i])) return ""; 
  global $adAttDir;
  if ($i != 0) 
  {
  return $fileName = "$adAttDir/$this->id"."-$i.".$this->imageExtensions[$i];
  }
  else return $fileName = "$adAttDir/$this->id".".".$this->imageExtensions[$i];
  }
  
  function getThumbName($i)
  {
  if (!isset($this->imageExtensions[$i])) return ""; 
  global $adAttDir;
  if ($i != 0) 
  {
  return $thumbName = "$adAttDir/th_$this->id"."-$i.".$this->imageExtensions[$i];
  }
  else return $thumbName = "$adAttDir/th_$this->id".".".$this->imageExtensions[$i];
  }
  
  function getImageHTML($i)
  {
  if (!isset($this->imageExtensions[$i])) return "";
  if (strlen($this->imageExtensions[$i]) < 2) return "";
  $picName = $this->getImageName($i); // Get the first image
  $thName = $this->getThumbName($i); // Get the first thumb
  
  // If the thumbnail doesn't exists use the original picture's name instead.
  if (!file_exists($thName)) $thName = $picName;
  if (!file_exists($picName)) return "";
  
  // Okay now we need to find the dimensions of the thumbnail and scale them for viewing.
  // If it really is a thumbnail we won't have to scale using html. If it isn't then we have no
  // other choice as the reason no thumb exists is because this format is not supported by php
  $size = getimagesize( $thName );
  $size = RatioImageSize($size,$this->thumbSizeX,$this->thumbSizeY,true);
  return "<a href='$picName' target='_blank'><img src='$thName' width='$size[0]' height='$size[1]' border='0'></a>$this->imageSpacer"; 
  }
 
  // Get the image settings from this advert's category 
  function getImageLimits()
  {
  //if (!isset($this->imageLimitsLoaded)) return;
  
      global $categoryClassName;
         $c = new $categoryClassName;
         $c->id = $this->cid;
         load($c);
         $this->imagesAllowed = $c->imagesAllowed;
         $this->thumbSizeX = $c->thumbSizeX;
         $this->thumbSizeY = $c->thumbSizeY;
         $this->imageMaxSizeX= $c->imageMaxSizeX; 
         $this->imageMaxSizeY= $c->imageMaxSizeY; 
  $this->imageLimitsLoaded = true;
  // Construct the image spacer
  $this->imageSpacer = 
  str_replace(array('$thumbWidth','$thumbHeight'),
  array($c->thumbSizeX$,c->thumbSizeY),$c->imageSpacer);
  
  // Quick validation test
  if ($c->imagesAllowed)
  {
  if ($c->thumbSizeX * $c->thumbSizeY * $c->imageMaxSizeX * $c->imageMaxSizeY <= 0)
  die('Image dimensions impossible');
  }
  }
  
  function Debug()
  {
  if (false)
  {
  if (isset($this->imageExtensions))
  echo array_to_str($this->imageExtensions); 
  if (isset($this->picture)) 
  echo array_to_str($this->picture); 
  }
  }
 /**********************************/

请注意,一半在类上面,另一半在类内部。

Image.php 源代码

华夏公益教科书