Php 使环境变量全球化是一种良好的做法吗?
我有一些模块化(对象和类)JavaScript和PHP。我不断得到建议,要去掉全局变量…“它们很糟糕”…我想是因为它们会导致依赖关系 然而,我应该把环境变量放在哪里——最好的例子是路径信息 这是一个典型的例子 下面的UploadFile类需要Php 使环境变量全球化是一种良好的做法吗?,php,Php,我有一些模块化(对象和类)JavaScript和PHP。我不断得到建议,要去掉全局变量…“它们很糟糕”…我想是因为它们会导致依赖关系 然而,我应该把环境变量放在哪里——最好的例子是路径信息 这是一个典型的例子 下面的UploadFile类需要 const PICTURES = '../pictures/'; 特别是在这一点上(无需阅读整个课程) 不允许将文件上载到任何位置。我更愿意把它放在一个GlobalClass中,然后从那里访问它。这是有意义的,因为其他代码需要知道图片的去向,而我
const PICTURES = '../pictures/';
特别是在这一点上(无需阅读整个课程)
不允许将文件上载到任何位置。我更愿意把它放在一个GlobalClass中,然后从那里访问它。这是有意义的,因为其他代码需要知道图片的去向,而我只有一个位置可以进行更新
环境变量可以作为全局变量使用,这样就可以从多个模块中访问它们,并且只在一个地方进行编辑
<?php
/**
* Module : Model
* Name : UploadFile
* Input : File Information
* Output : Resized Files in .jpg format
* Notes :
resizeMove() - resizes the picture to $maxMedium and $maxSmall and moves the file to a permanent location.
makeDimensions() - calculates the dimensions of the new images so that there is not distortion if possible.
getImage() - creates a php image for manipulation.
updateSessionAndDb - updates the mysql table - move out.
*/
class UploadedFile
{
const PICTURES = '../pictures/';
private $originalWidth,
$originalHeight,
$newWidth,
$newHeight,
$maxMedium = 50,
$maxSmall = 20;
private $src = NULL;
private
$fileType,
$fileName,
$sessionId,
$path_medium,
$path_small;
function __construct($fileType, $fileName)
{
$this->sessionId = Session::get('id');
$this->path_medium = UploadedFile::PICTURES . "$this->sessionId.jpg";
$this->path_small = UploadedFile::PICTURES . "$this->sessionId-1.jpg";
$this->fileType = $fileType;
$this->fileName = $fileName;
}
public function createImages()
{
if(move_uploaded_file($this->fileName, $this->path_medium))
{
if($this->getImage($this->path_medium))
{
list($this->originalWidth,$this->originalHeight)=getimagesize($this->path_medium);
$this->resizeMove($this->maxMedium,$this->path_medium);
$this->resizeMove($this->maxSmall,$this->path_small);
imagedestroy($this->src);
}
}
}
private function resizeMove($max, $path)
{
$this->makeDimensions($max);
$image_true_color = imagecreatetruecolor($this->newWidth, $this->newHeight);
imagecopyresampled($image_true_color, $this->src, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->
originalWidth, $this->originalHeight);
imagejpeg($image_true_color, $path);
imagedestroy($image_true_color);
}
private function makeDimensions($max)
{
$this->newWidth=$this->originalWidth;
$this->newHeight=$this->originalHeight;
if(($this->originalWidth > $this->originalHeight) && ($this->originalWidth > $max))
{
$this->newWidth = $max;
$this->newHeight = ($max / $this->originalWidth) * $this->originalHeight;
}
elseif($this->originalHeight > $this->originalWidth && $this->originalHeight > $max)
{
$this->newHeight = $max;
$this->newWidth = ($max / $this->originalHeight) * $this->originalWidth;
}
elseif ($this->originalWidth > $max)
{
$this->newWidth = $this->newHeight = $max;
}
}
private function getImage($path)
{
$type_creators = array(
'image/gif' => 'imagecreatefromgif',
'image/pjpeg' => 'imagecreatefromjpeg',
'image/jpeg' => 'imagecreatefromjpeg',
'image/png' => 'imagecreatefrompng');
if(array_key_exists($this->fileType, $type_creators))
{
$this->src = $type_creators[$this->fileType]($path);
return true;
}
return false;
}
}
修改对象生成器示例
class ObjectMaker
{
public function makeSignUp()
{
$DatabaseObject = new Database();
$TextObject = new Text();
$MessageObject = new Message();
return new ControlSignUp( $DatabaseObject, $TextObject, $MessageObject );
}
注意事项:
我可能有类似于SignUp的类,所以我可以使用继承来减少对象创建的冗余,通过使用ObjectMaker类-回到最初的问题-我可以在这个“模式”中包括全局对象的注入,而不仅仅是对象。可能不会。您可以创建一个路径获取程序,它输出路径类的属性(即
path::pictures
)
然后,在这个级别上,这取决于开发人员
我认为,为了公司的利益,最好将它们都放在一个名称空间中,并以这种方式调用它们。当新开发人员出现时,它会有所帮助。常量没有全局变量那么糟糕,将其用于path是迄今为止克服PHP没有“真”根路径变量的尴尬的最常用方法(您可以使用DIR基于当前脚本,但不能基于调用当前脚本的脚本) 全局变量不好的主要原因不是因为它们是全局变量,而是因为它们可以在脚本中的任何位置更改。事实上,这是我对PHP的主要抱怨之一-$\服务器变量可以在脚本运行期间更改,我希望它们是常量 只能定义和使用常量,无法对其进行编辑。只要您能够很好地记录全局变量的存在,那么管理它们并不比管理任何其他PHP环境变量更困难
只要你不跟他们一起发疯就好了。请记住,在进行测试时,环境总是扮演着一个角色,只要您了解环境并可以轻松地模拟它,那么它就不会给测试带来更多问题。如果您想使类可重用,您不应该在其中硬编码,而应该将其注入。例如会话id和映像的基本目录。将这些作为参数添加到构造函数中:
function __construct($fileType, $fileName, $sessionId, $prefixPictures)
{
$this->fileType = $fileType;
$this->fileName = $fileName;
$this->sessionId = $sessionId;
$this->prefixPictures = $prefixPictures;
$this->path_medium = $prefixPictures . $this->sessionId . ".jpg";
$this->path_small = $prefixPictures . $this->sessionId . "-1.jpg";
}
此外,您应该创建自己的类,一个用于调整图片大小,另一个用于进行大小计算。实际上,这样的类已经存在,所以您只需要包含一些文件,并调整大小(例如使用)。全局变量的问题在于,它使您的类依赖于它的存在,从而默认情况下破坏了类。如果它是一个库类,那么这一点很重要,但如果它专用于您的应用程序,那么这一点就不那么重要了——但它始终是一个很好的目标。此外,如果它是一个
const
或define
,那么它在执行过程中就不能被更改(这种情况的发生频率可能比人们想象的要高,即使是在您的示例中,例如在单元测试中)。最优雅的解决方案是采用依赖注入模式,虽然有时设置该类的成本超过了减少依赖项的好处。是的……如果我设置了一个具有私有成员的全局类并通过getter进行访问……那么我可以使用依赖项注入来注入该类……最佳实践与大量工作相比……hmmmmIfUploadedFile
的唯一配置项是根路径,我会将$picturesRoot
添加到构造函数中,或者可能会将settersetPicturesRoot($picturesRoot)
添加到类中。这样,这个类就不必担心接受特定于应用程序的配置对象——你的控制器可以做这些事情。@halfr-同意,下面的hakre也同意。这样,我就可以在一个位置更新它们,使它们成为私有的,但是访问任何地方。这听起来像是最佳实践。我已经看到了很多…通过构造函数进行依赖注入…这比创建一个处理DI的ObjectMaker(我目前的做法)要简单一些。实际上我需要更新该文件以通过构造函数…更简洁一些。这是会话方面的一个好地方,另一种依赖。然而,我可能倾向于使用更多的setter——虽然对象需要所有这些变量,但我目前在某种程度上同意Clean Code的格言,即三个以上的参数变得非常笨拙。但是,+1还是一样。@halfer:如前所述,该类做的太多了,$fileType
和$fileName
看起来多余,实际上只是为了标识一个图像。@Allfoo您所做的不是DI容器就是抽象工厂。需要注意的是,DI(依赖项注入)在没有DI容器或抽象工厂的大多数项目中都很有用。全局变量(包括常量)的最大问题是它们创建了一个难以控制的依赖项列表。如果您构建了一个接受注入设置的类,那么可以轻松地单独测试该类。与依赖全局变量和/或常量的类(类常量更好,但请注意,它们在配置时使用有限)相比,它们不容易注入,但必须在运行测试之前进行设置。这正是我所说的wilmoore。但由于软件已经依赖于环境(PHP版本引入了某些在其他版本上不可用的服务器变量,Apache和Nginx也引入了不同的变量),如果您有一个框架或更大的系统
class ObjectMaker
{
public function makeSignUp()
{
$DatabaseObject = new Database();
$TextObject = new Text();
$MessageObject = new Message();
return new ControlSignUp( $DatabaseObject, $TextObject, $MessageObject );
}
function __construct($fileType, $fileName, $sessionId, $prefixPictures)
{
$this->fileType = $fileType;
$this->fileName = $fileName;
$this->sessionId = $sessionId;
$this->prefixPictures = $prefixPictures;
$this->path_medium = $prefixPictures . $this->sessionId . ".jpg";
$this->path_small = $prefixPictures . $this->sessionId . "-1.jpg";
}