developer tip

함수의 PHP 전역

copycodes 2020. 8. 21. 07:57
반응형

함수의 PHP 전역


global 키워드 의 유용성은 무엇입니까 ?

한 방법을 다른 방법보다 선호하는 이유가 있습니까?

  • 보안?
  • 공연?
  • 다른 건 없나요?

방법 1 :

function exempleConcat($str1, $str2)
{
  return $str1.$str2;
}

방법 2 :

function exempleConcat()
{
  global $str1, $str2;
  return $str1.$str2;
}

언제 사용하는 것이 합리적 global입니까?

나에게는 위험 해 보이지만 지식이 부족한 것일 수도 있습니다. 나는에 관심이 있어요 문서화 (예 : 코드, 문서에 링크 ...의 예에) 기술적 인 이유.

미리 감사드립니다!


하사품

이것은 주제에 대한 좋은 일반적인 질문입니다. I (@Gordon)는 추가 답변을 얻기 위해 현상금을 제공하고 있습니다. 귀하의 답변이 저와 일치하는지 또는 다른 관점을 제공하는지 여부는 중요하지 않습니다. global주제가 가끔 나오기 때문에 좋은 "표준"답변을 링크에 사용할 수 있습니다.


글로벌은 악하다

이것은 global키워드뿐만 아니라 로컬 범위에서 전역 범위 (정적, 싱글 톤, 레지스트리, 상수)에 도달하는 다른 모든 것에 대해서도 마찬가지입니다 . 당신은 그것들을 사용하고 싶지 않습니다. 함수 호출은 외부에 의존 할 필요가 없습니다.

function fn()
{
    global $foo;              // never ever use that
    $a = SOME_CONSTANT        // do not use that
    $b = Foo::SOME_CONSTANT;  // do not use that unless self::
    $c = $GLOBALS['foo'];     // incl. any other superglobal ($_GET, …)
    $d = Foo::bar();          // any static call, incl. Singletons and Registries
}

이 모든 것이 코드를 외부에 의존하게 만듭니다. 즉, 이들 중 하나를 안정적으로 호출하려면 애플리케이션이있는 전체 글로벌 상태를 알아야합니다. 그 환경 없이는 기능이 존재할 수 없습니다.

슈퍼 글로벌을 사용하는 것은 명백한 결함이 아닐 수 있지만 명령 줄에서 코드를 호출하면 $_GET또는 $_POST. 코드가 이러한 입력에 의존하는 경우 웹 환경으로 제한됩니다. 요청을 객체로 추상화하고 대신 사용하십시오.

하드 코딩 된 클래스 이름 (정적, 상수)을 결합하는 경우 해당 클래스를 사용할 수 없으면 함수도 존재할 수 없습니다. 동일한 네임 스페이스의 클래스 인 경우에는 문제가되지 않지만 다른 네임 스페이스에서 혼합을 시작하면 엉망이됩니다.

재사용은 위의 모든 사항에 의해 심각하게 방해를받습니다. 단위 테스트도 마찬가지입니다 .

또한 전역 범위에 연결하면 함수 서명이 거짓말을합니다.

function fn()

아무것도 전달하지 않고 그 함수를 호출 할 수 있다고 주장하기 때문에 거짓말 쟁이입니다. 내가 배운 것은 함수 본체를 볼 때만 환경을 특정 상태로 설정해야한다는 것을 알게되었습니다.

함수를 실행하는 데 인수가 필요한 경우이를 명시 적으로 지정하고 전달합니다.

function fn($arg1, $arg2)
{
    // do sth with $arguments
}

서명에서 호출해야하는 것을 명확하게 전달합니다. 특정 상태에있는 것은 환경에 의존하지 않습니다. 당신은 할 필요가 없습니다

$arg1 = 'foo';
$arg2 = 'bar';
fn();

끌어들이는 (글로벌 키워드) 대 밀어 넣는 (인수)의 문제입니다. 의존성을 밀어 넣거나 주입 할 때 함수는 더 이상 외부에 의존하지 않습니다. 당신이 fn(1)때 당신은 어딘가에 1을 보유하는 변수를 가질 필요가 없습니다. 그러나 $one함수 내 에서 전역을 가져 오면 전역 범위에 연결되고 어딘가에 정의 된 변수가있을 것으로 예상합니다. 이 기능은 더 이상 독립적이지 않습니다.

더 나쁜 것은 함수 내에서 전역을 변경할 때 함수가 사방에 부작용이 있기 때문에 코드를 완전히 이해할 수 없게됩니다.

더 나은 예가 없으면

function fn()
{
    global $foo;
    echo $foo;     // side effect: echo'ing
    $foo = 'bar';  // side effect: changing
}

그리고 당신은

$foo = 'foo';
fn(); // prints foo
fn(); // prints bar <-- WTF!!

$foo이 세 줄에서 변경된 것을 볼 방법이 없습니다 . 동일한 인수를 사용하여 동일한 함수를 호출하면 갑자기 출력이 변경되거나 전역 상태의 값이 변경되는 이유는 무엇입니까? 함수는 정의 된 입력 Y에 대해 X를 수행해야합니다. 항상.

OOP는 캡슐화에 관한 것이고 전역 범위에 도달하면 캡슐화를 깨뜨리기 때문에 OOP를 사용할 때 더욱 심각해집니다. 프레임 워크에서 볼 수있는 이러한 모든 싱글 톤 및 레지스트리는 종속성 주입을 위해 제거해야하는 코드 냄새입니다. 코드를 분리하십시오.

더 많은 리소스 :


반대하는 한 가지 큰 이유 global는 기능이 다른 범위에 종속된다는 것을 의미합니다. 이것은 매우 빨리 지저분해질 것입니다.

$str1 = 'foo';
$str2 = 'bar';
$str3 = exampleConcat();

$str = exampleConcat('foo', 'bar');

함수가 작동하기 위해 호출 범위에서 요구 $str1되고 $str2설정된다는 것은 불필요한 종속성을 도입한다는 것을 의미합니다. 함수에서 이름을 변경하지 않고는 더 이상이 범위에서 이러한 변수의 이름을 바꿀 수 없으며 따라서이 함수를 사용하는 다른 모든 범위에서도 이름을 바꿀 수 있습니다. 이것은 곧 변수 이름을 추적하려고 할 때 혼란스러워집니다.

global$db자원 과 같은 전역적인 것을 포함하는 경우에도 나쁜 패턴 입니다. 됩니다 이름을 바꿀 때 일을 올 $db하지만 전체 응용 프로그램 이름에 의존하기 때문에, 할 수 없습니다.

중간 정도의 복잡한 응용 프로그램을 작성하려면 변수 범위를 제한하고 분리하는 것이 필수적 입니다.


글로벌은 피할 수 없습니다.

오래된 토론이지만 위에서 언급 한 답변에서 그리워서 몇 가지 생각을 추가하고 싶습니다. 이러한 대답은 글로벌이 너무 많은 것을 단순화하고 문제에 대한 해결책이 아닌 해결책을 제시합니다. 문제는 글로벌 변수와 글로벌 키워드를 사용하는 적절한 방법은 무엇입니까? 이를 위해 먼저 글로벌이 무엇인지 조사하고 설명해야합니다.

이 Zend 코드를 살펴보십시오. Zend가 잘못 작성되었다고 제안하지 않습니다.

class DecoratorPluginManager extends AbstractPluginManager
{
/**
 * Default set of decorators
 *
 * @var array
 */
protected $invokableClasses = array(
    'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud',
    'htmltag'   => 'Zend\Tag\Cloud\Decorator\HtmlTag',
    'tag'       => 'Zend\Tag\Cloud\Decorator\HtmlTag',
   );

There are a lot of invisible dependencies here. Those constants are actually classes. You can also see require_once in some pages of this framework. Require_once is a global dependency, hence creating external dependencies. That is inevitable for a framework. How can you create a class like DecoratorPluginManager without a lot of external code on which it depends? It can not function without a lot of extras. Using the Zend framework, have you ever changed the implementation of an interface? An interface is in fact a global.

Another globally used application is Drupal. They are very concerned about proper design, but just like any big framework, they have a lot of external dependencies. Take a look at the globals in this page:

/**
 * @file
 * Initiates a browser-based installation of Drupal.
 */

/**
 * Root directory of Drupal installation.
 */
define('DRUPAL_ROOT', getcwd());

/**
 * Global flag to indicate that site is in installation mode.
 */
define('MAINTENANCE_MODE', 'install');

// Exit early if running an incompatible PHP version to avoid fatal errors.
if (version_compare(PHP_VERSION, '5.2.4') < 0) {
  print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the     <a     href="http://drupal.org/requirements">system requirements</a> page for more     information.';
  exit;
}

// Start the installer.
require_once DRUPAL_ROOT . '/includes/install.core.inc';
install_drupal();

Ever written a redirect to the login page? That is changing a global value. (And then are you not saying 'WTF', which I consider as a good reaction to bad documentation of your application.) The problem with globals is not that they are globals, you need them in order to have a meaningful application. The problem is the complexity of the overall application which can make it a nightmare to handle. Sessions are globals, $_POST is a global, DRUPAL_ROOT is a global, the includes/install.core.inc' is an unmodifiable global. There is big world outside any function that is required in order to let that function do its job.

The answer of Gordon is incorrect, because he overrates the independence of a function and calling a function a liar is oversimplifying the situation. Functions do not lie and when you take a look at his example the function is designed improperly - his example is a bug. (By the way, I agree with this conclusion that one should decouple code.) The answer of deceze is not really a proper definition of the situation. Functions always function within a wider scope and his example is way too simplistic. We will all agree with him that that function is completely useless, because it returns a constant. That function is anyhow bad design. If you want to show that the practice is bad, please come with a relevant example. Renaming variables throughout an application is no big deal having a good IDE (or a tool). The question is about the scope of the variable, not the difference in scope with the function. There is a proper time for a function to perform its role in the process (that is why it is created in the first place) and at that proper time may it influence the functioning of the application as a whole, hence also working on global variables. The answer of xzyfer is a statement without argumentation. Globals are just as present in an application if you have procedural functions or OOP design. The next two ways of changing the value of a global are essentially the same:

function xzy($var){
 global $z;
 $z = $var;
}

function setZ($var){
 $this->z = $var;
}

In both instances is the value of $z changed within a specific function. In both ways of programming can you make those changes in a bunch of other places in the code. You could say that using global you could call $z anywhere and change there. Yes, you can. But will you? And when done in inapt places, should it then not be called a bug?

Bob Fanger comments on xzyfer.

Should anyone then just use anything and especially the keyword 'global'? No, but just like any type of design, try to analyze on what it depends and what depends on it. Try to find out when it changes and how it changes. Changing global values should only happen with those variables that can change with every request/response. That is, only to those variables that are belonging to the functional flow of a process, not to its technical implementation. The redirect of an URL to the login page belongs to the functional flow of a process, the implementation class used for an interface to the technical implementation. You can change the latter during the different versions of the application, but should not change those with every request/response.

To further understand when it is a problem working with globals and the keyword global and when not will I introduce the next sentence, which comes from Wim de Bie when writing about blogs: 'Personal yes, private no'. When a function is changing the value of a global variable in sake of its own functioning, then will I call that private use of a global variable and a bug. But when the change of the global variable is made for the proper processing of the application as a whole, like the redirect of the user to the login page, then is that in my opinion possibly good design, not by definition bad and certainly not an anti-pattern.

In retrospect to the answers of Gordon, deceze and xzyfer: they all have 'private yes'(and bugs) as examples. That is why they are opposed to the use of globals. I would do too. They, however, do not come with 'personal yes, private no'-examples like I have done in this answer several times.


Simply put there is rarely a reason to global and never a good one in modern PHP code IMHO. Especially if you're using PHP 5. And extra specially if you're develop Object Orientated code.

Globals negatively affect maintainability, readability and testability of code. Many uses of global can and should be replaced with Dependency Injection or simply passing the global object as a parameter.

function getCustomer($db, $id) {
    $row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id));
    return $row;
}

Dont hesitate from using global keyword inside functions in PHP. Especially dont take people who are outlandishly preaching/yelling how globals are 'evil' and whatnot.

Firstly, because what you use totally depends on the situation and problem, and there is NO one solution/way to do anything in coding. Totally leaving aside the fallacy of undefinable, subjective, religious adjectives like 'evil' into the equation.

Case in point :

Wordpress and its ecosystem uses global keyword in their functions. Be the code OOP or not OOP.

And as of now Wordpress is basically 18.9% of internet, and its running the massive megasites/apps of innumerable giants ranging from Reuters to Sony, to NYT, to CNN.

And it does it well.

Usage of global keyword inside functions frees Wordpress from MASSIVE bloat which would happen given its huge ecosystem. Imagine every function was asking/passing any variable that is needed from another plugin, core, and returning. Added with plugin interdependencies, that would end up in a nightmare of variables, or a nightmare of arrays passed as variables. A HELL to track, a hell to debug, a hell to develop. Inanely massive memory footprint due to code bloat and variable bloat too. Harder to write too.

There may be people who come up and criticize Wordpress, its ecosystem, their practices and what goes on around in those parts.

Pointless, since this ecosystem is pretty much 20% of roughly entire internet. Apparently, it DOES work, it does its job and more. Which means its the same for the global keyword.

Another good example is the "iframes are evil" fundamentalism. A decade ago it was heresy to use iframes. And there were thousands of people preaching against them around internet. Then comes facebook, then comes social, now iframes are everywhere from 'like' boxes to authentication, and voila - everyone shut up. There are those who still did not shut up - rightfully or wrongfully. But you know what, life goes on despite such opinions, and even the ones who were preaching against iframes a decade ago are now having to use them to integrate various social apps to their organization's own applications without saying a word.

......

Coder Fundamentalism is something very, very bad. A small percentage among us may be graced with the comfortable job in a solid monolithic company which has enough clout to endure the constant change in information technology and the pressures it brings in regard to competition, time, budget and other considerations, and therefore can practice fundamentalism and strict adherence to perceived 'evils' or 'goods'. Comfortable positions reminiscent of old ages these are, even if the occupiers are young.

For the majority however, the i.t. world is an ever changing world in which they need to be open minded and practical. There is no place for fundamentalism, leave aside outrageous keywords like 'evil' in the front line trenches of information technology.

Just use whatever makes the best sense for the problem AT HAND, with appropriate considerations for near, medium and long term future. Do not shy away from using any feature or approach because it has a rampant ideological animosity against it, among any given coder subset.

They wont do your job. You will. Act according to your circumstances.


It makes no sense to make a concat function using the global keyword.

It's used to access global variables such as a database object.

Example:

function getCustomer($id) {
  global $db;
  $row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id));
  return $row;
}

It can be used as a variation on the Singleton pattern


I think everyone has pretty much expounded on the negative aspects of globals. So I will add the positives as well as instructions for proper use of globals:

  1. The main purpose of globals was to share information between functions. back when there was nothing like a class, php code consisted of a bunch of functions. Sometimes you would need to share information between functions. Typically the global was used to do this with the risk of having data corrupted by making them global.

    Now before some happy go lucky simpleton starts a comment about dependency injection I would like to ask you how the user of a function like example get_post(1) would know all the dependencies of the function. Also consider that dependencies may differ from
    version to version and server to server. The main problem with dependency injection is dependencies have to be known beforehand. In a situation where this is not possible or unwanted global variables were the only way to do achieve this goal.

    Due to the creation of the class, now common functions can easily be grouped in a class and share data. Through implementations like Mediators even unrelated objects can share information. This is no longer necessary.

  2. Another use for globals is for configuration purposes. Mostly at the beginning of a script before any autoloaders have been loaded, database connections made, etc.

    During the loading of resources, globals can be used to configure data (ie which database to use where library files are located, the url of the server etc). The best way to do this is by use of the define() function since these values wont change often and can easily be placed in a configuration file.

  3. The final use for globals is to hold common data (ie CRLF, IMAGE_DIR, IMAGE_DIR_URL), human readable status flags (ie ITERATOR_IS_RECURSIVE). Here globals are used to store information that is meant to be used application wide allowing them to be changed and have those changes appear application wide.

  4. The singleton pattern became popular in php during php4 when each instance of an object took up memory. The singleton helped to save ram by only allowing one instance of an object to be created. Before references even dependancy injection would have been a bad idea.

    The new php implementation of objects from PHP 5.4+ takes care of most of these problems you can safely pass objects around with little to no penalty any more. This is no longer necessary.

    Another use for singletons is the special instance where only one instance of an object must exist at a time, that instance might exist before / after script execution and that object is shared between different scripts / servers / languages etc. Here a singleton pattern solves the solution quite well.

So in conclusion if you are in position 1, 2 or 3 then using a global would be reasonable. However in other situations Method 1 should be used.

Feel free to update any other instances where globals should be used.

참고URL : https://stackoverflow.com/questions/5166087/php-global-in-functions

반응형