클래스에서 전역 변수 사용
PHP클래스에서 전역 변수 사용
페이지 매김 클래스를 만들고 클래스 밖에서 변수를 사용하려고합니다.
하지만 그것은 나에게 치명적인 오류 "구성원 함수 쿼리 () 비 - 개체에 대한 호출"을주고있어.
다음은 색인 파일입니다.
$db = new DB_MySQL("localhost", "root", "", "test"); // connect to the database
include_once("pagi.php");
$pagination = new pagi();
$records = $pagination->get_records("SELECT * FROM `table`");
그리고 이것은 pagi.php 파일입니다 :
class pagi {
public function get_records($q) {
$x = $db->query($q);
return $db->fetch($x);
}
}
클래스 내부에 새로운 변수를 만들지 않고이 변수를 클래스 내부의 클래스 외부에서 사용할 수 있습니까?
해결법
-
==============================
1.이 문제를 해결하는 올바른 방법은 데이터베이스 객체를 다른 클래스에 삽입하는 것입니다 (종속성 삽입).
이 문제를 해결하는 올바른 방법은 데이터베이스 객체를 다른 클래스에 삽입하는 것입니다 (종속성 삽입).
$db = new DB_MySQL("localhost", "root", "", "test"); // connect to the database include_once("pagi.php"); $pagination = new Paginator($db); $records = $pagination->get_records("SELECT the, fields, you, want, to retrieve FROM `table`"); class Paginator { protected $db; // Might be better to use some generic db interface as typehint when available public function __construct(DB_MySQL $db) { $this->db = $db; } public function get_records($q) { $x = $this->db->query($q); return $this->db->fetch($x); } }
당신이 그것을 해결할 수있는 또 다른 방법은 그것을 사용하는 메소드에 데이터베이스 클래스의 인스턴스를 삽입하는 것입니다 :
$db = new DB_MySQL("localhost", "root", "", "test"); // connect to the database include_once("pagi.php"); $pagination = new Paginator(); $records = $pagination->get_records("SELECT the, fields, you, want, to retrieve FROM `table`", $db); class Paginator { public function get_records($q, DB_MySQL $db) { $x = $db->query($q); return $db->fetch($x); } }
어떤 방법을 선택하든 상황에 따라 다릅니다. 만약 하나의 메소드 만이 데이터베이스의 인스턴스를 필요로한다면, 당신은 그것을 메소드에 삽입 할 수 있습니다. 그렇지 않으면 클래스의 생성자에 그것을 주입 할 것입니다.
또한 클래스 이름을 pagi에서 Paginator로 변경했습니다. Paginator는 다른 사람 (코드)을 보는 것이 분명하기 때문에 클래스에 대한 더 나은 이름의 IMHO입니다. 또한 첫 글자를 대문자로 만들었습니다.
내가 한 또 다른 일은 "와일드 카드"*를 사용하는 대신 사용중인 필드를 선택하도록 쿼리를 변경하는 것입니다. 이것은 클래스 이름을 변경 한 것과 같은 이유입니다. 코드를 보는 사람들은 데이터베이스 및 / 또는 결과를 확인하지 않고 어떤 필드가 검색되는지 정확히 알 수 있습니다.
최신 정보
그 대답은 왜 객체를 전역으로 선언하는 대신에 의존성 주입 라우트를 사용하는지에 대한 논의를 야기했기 때문에 전역 키워드에 대한 의존성 주입을 사용하는 이유를 명확히하고자합니다. 다음과 같은 메소드가있을 때 :
function get_records($q) { global $db; $x = $db->query($q); return $db->fetch($x); }
위의 방법을 어딘가에 사용하면 클래스 또는 메소드 사용이 $ db에 종속된다는 것이 확실하지 않습니다. 따라서 숨겨진 종속성입니다. 위의 이유가 또 다른 이유는 $ db 인스턴스 (따라서 DB_MySQL) 클래스를 해당 메소드 / 클래스에 밀접하게 연결했기 때문입니다. 어떤 시점에서 2 개의 데이터베이스를 사용해야하는 경우에는 어떻게해야합니까? 이제 전역 $ db를 global $ db2로 변경하기 위해 모든 코드를 검토해야합니다. 다른 데이터베이스로 전환하기 위해 코드를 변경하지 않아도됩니다. 이러한 이유로 다음과 같이해서는 안됩니다.
function get_records($q) { $db = new DB_MySQL("localhost", "root", "", "test"); $x = $db->query($q); return $db->fetch($x); }
다시 말하지만 이것은 숨겨진 종속성이며 DB_MySQL 클래스를 메서드 / 클래스와 밀접하게 연결합니다. 이 때문에 Paginator 클래스를 제대로 단위 테스트하는 것도 불가능합니다. 유닛 (Paginator 클래스) 만 테스트하는 대신 DB_MySQL 클래스도 동시에 테스트합니다. 그리고 밀접하게 결합 된 종속성이 여러 개 있다면 어떨까요? 이제 당신은 갑자기 단위 테스트라고 불리는 여러 클래스들을 테스트하고 있습니다. 따라서 의존성 주입을 사용하면 테스트 목적으로 다른 데이터베이스 클래스 또는 조롱 된 데이터베이스 클래스로 쉽게 전환 할 수 있습니다. 종속성으로 인해 잘못된 결과를 얻는 것에 대해 걱정할 필요가없는 단 하나의 단위 만 테스트하는 이점 외에도 테스트가 빠르게 완료 될 것입니다.
어떤 사람들은 Singleton 패턴이 데이터베이스 객체에 접근 할 수있는 올바른 방법이라고 생각할 수 있습니다. 그러나 위의 모든 것을 읽은 후, 싱글 톤은 기본적으로 물건을 글로벌하게 만드는 또 다른 방법입니다. 그것은 다르게 보일지도 모르지만, 그것은 똑같은 특성을 가지고 있으며 따라서 세계와 동일한 문제를 가지고 있습니다.
-
==============================
2.종속성 모델이 좋다는 데는 동의하지만, 데이터베이스의 경우, 필자는 개인적으로 데이터베이스 클래스의 모든 인스턴스에서 사용할 수있는 정적 연결을 사용하고 필요할 때마다 인스턴스를 쿼리합니다. 다음은 그 예입니다.
종속성 모델이 좋다는 데는 동의하지만, 데이터베이스의 경우, 필자는 개인적으로 데이터베이스 클래스의 모든 인스턴스에서 사용할 수있는 정적 연결을 사용하고 필요할 때마다 인스턴스를 쿼리합니다. 다음은 그 예입니다.
<?php //define a database class class DB { //the static connection. //This is available to all instances of the class as the same connection. private static $_conn; //store the result available to all methods private $result; //store the last query available to all methods private $lastQuery; //static connection function. connects to the database and stores that connection statically. public static function connect($host, $user, $pass, $db){ self::$_conn = mysqli_connect($host, $user, $pass, $db); } //standard function for doing queries. uses the static connnection property. public function query($query){ $this->lastQuery = $query; $this->result = mysqli_query(self::$_conn, $query); //process result, return expected output. } } //create connection to the database, this connection will be used in all instances of DB class DB::connect('local', 'DB_USER', 'DB_PASS'); //create instance to query $test = new DB; //do query $test->query("SELECT * FROM TABLE"); //test function function foo(){ //create instance to use in this function $bar = new DB; //do query $bar->query("SELECT * FROM OTHER_TABLE"); //return results return $bar->fetchArray(); }
그런 식으로 모든 함수, 메서드 ... 내에서 DB를 원하는 모든 인스턴스를 만들 수 있으며 클래스의 해당 로컬 인스턴스를 사용하여 모든 쿼리를 수행 할 수 있습니다. 모든 인스턴스는 동일한 연결을 사용합니다.
한 가지주의 할 점은이 클래스는 정의 된 클래스 당 하나의 데이터베이스 연결 만 허용한다는 것입니다. 그러나이 클래스는 나에게 문제가되지 않도록 하나만 사용합니다.
-
==============================
3.get_records 메소드 호출에 db-connection ($ db)을 추가 할 수 있습니다.
get_records 메소드 호출에 db-connection ($ db)을 추가 할 수 있습니다.
다음은 관련 코드 행뿐입니다.
첫 번째 파일 :
$records = $pagination->get_records("SELECT * FROM `table`", $db);
두 번째 파일 :
public function get_records($q, $db) {
-
==============================
4.지금까지의 다른 답변들은 캡슐화를 망칠 것이므로 (예를 들어 그 메소드를 호출하기 전에 그 객체를 정의해야 할 필요가 있기 때문에) 전역을 사용하는 것이 좋습니다.
지금까지의 다른 답변들은 캡슐화를 망칠 것이므로 (예를 들어 그 메소드를 호출하기 전에 그 객체를 정의해야 할 필요가 있기 때문에) 전역을 사용하는 것이 좋습니다.
메서드 시그니처에 적용하거나 클래스를 사용하지 않는 것이 훨씬 좋습니다.
-
==============================
5.싱글 톤 패턴을 사용하고 DB_MySQL에 정적 인스턴스를 삽입하십시오!
싱글 톤 패턴을 사용하고 DB_MySQL에 정적 인스턴스를 삽입하십시오!
from https://stackoverflow.com/questions/11923272/use-global-variables-in-a-class by cc-by-sa and MIT license
'PHP' 카테고리의 다른 글
PHP 정규 표현식 : 없음 구분 기호 '^'가 없습니다. (0) | 2018.09.10 |
---|---|
PHP : 문자열 분할 [duplicate] (0) | 2018.09.10 |
Telegram API를 사용하여 권한 부여를 구현하는 방법은 무엇입니까? (0) | 2018.09.10 |
password_hash 사용법 (0) | 2018.09.10 |
PHP의 DOMDocument (0) | 2018.09.10 |