0

問題 1 以下のコードがありますが、多くのクラスの使用について人々が話しているのを耳にします。以下のコードをクラスとして配置するメリットはありますか (私はすでにデータをオブジェクトに変換しています)、どうすればそれを行うことができますか? (私はOOP PHPが初めてです)。

try {

    $connection = new PDO(DATA, USER, PASSWORD);

    $connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

    $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

} catch (PDOException $error) {

    PDOcrash($error);

}

// Scrubbing remember data
$_POST['remember'] = (int)$_POST['remember'];

// Query the database for the unique salt
$query = $connection->prepare("SELECT id, salt FROM {$_SESSION['environment']->database}.system_user WHERE username = :username LIMIT 1");

$query->execute(array(':username' => $_POST['username']));

$security = $query->fetch(PDO::FETCH_OBJ);

$query->closeCursor();

// Form the hash using sha1 alrorithm
$_POST['password'] = sha1(sha1($security->salt) . sha1($_POST['password']));

$query = $connection->prepare("SELECT id, centre, reference, first_name, last_name FROM {$_SESSION['environment']->database}.system_user WHERE username = :username AND password = :password");

$query->execute(array(':username' => $_POST['username'], ':password' => $_POST['password']));

$_SESSION['user'] = $query->fetch(PDO::FETCH_OBJ);

$query->closeCursor();

問題2

このコード ブロックの場合:

try {

    $connection = new PDO(DATA, USER, PASSWORD);

} catch (PDOException $error) {

    PDOcrash($error);

}

定数を使用して接続の詳細を定義していますが、ページで直接定義した場合にのみ機能するようです。定数はシステム全体で一定のままであると思いました。関数を以前に遭遇したページに移動すると、define()機能しません。これは、定数のスコープが単一のページであることを意味しますか? また、別の apache ドキュメントで接続情報を定義できると聞きましたが、これはより安全な方法です。どうすればこれを行うことができますか?

4

3 に答える 3

1

OOP コード自体を書かなくても問題はありませんが、適切な OOP スタイルのコーディングを使用することで得られる利点は非常に役立ちます。これにより、コードの読み取り、保守、デバッグ、およびテストが容易になります。

PHP 変数 (あちこちのスーパーグローバル以外) と定数は、リクエストごとにのみ有効です。あなたがやろうとしていることについては、私は定数さえ使いません。によって作成された定数define()globalであることを思い出してください。どこでも global を聞いたり見たりする場合は、ほとんどの場合、おそらく OOP を間違って実行していることがわかります。

あなたの場合(OOPルートに行きたい場合)に私がすることは、データベース接続をセットアップするブートストラップファイルを作成することです。その後、データベースオブジェクトを必要とする他のクラス/メソッドに簡単に注入できます。

もう 1 つは、パスワード ハッシュ ライブラリを使用してください。これにより、それを台無しにすることを防ぐことができます。リンクしたばかりのパスワード lib は、PHP5.5 で実装されます。ただし、そのバージョンを実行する前に、そのライブラリを使用してください。ハッシュは実際にはそれほど安全ではないためです。高速であることを意図しているため、パスワードのハッシュには適していません。少なくとも を使用しますが、リンクされたパスワード ライブラリを使用してください。sha1bcrypt

また、MySQL PDO ドライバーを使用している場合に備えて、エミュレートされた準備済みステートメントを無効にします。

最後に、実際にあなたの質問に答えるために:いいえ、単にそのコードをクラスに移動するメリットはありません。自分が何をしているのか、またはSOLIDの原則について考えずにそれを行うと、クラスは派手な名前空間にすぎません。コードをクラスに移動するだけでは、魔法のように OOP にはなりません。

アップデート

ブートストラップ ファイル

ブートストラップ ファイルは、作成されたすべてのリクエストに含まれるファイルです。アプリケーションが機能するために必要なものをセットアップするために使用できます。この例 (ほとんどの (Web) アプリケーションの場合) は、データベース接続です。ただし、ブートストラップ ファイルを使用して、エラー レポートを有効にするなど、一部の PHP 設定をセットアップすることもできます。そして非常に便利なオートローディング。

私のアプリケーションでは、ブートストラップ ファイルは常に 2 番目にアクセスされるファイルです。すべてのリクエストの最初のファイルindex.phpは、ドキュメント ルート内の単純なファイルであり、ブートストラップ ファイルのロードという 1 つのことだけを行います。他のすべての PHP ファイルは、ドキュメント ルートの外に保持されます。これにより、何らかの理由で PHP コードが表示されなくなります。サーバーの設定ミスか何か。このセットアップは、次のディレクトリ構造に少し似ています。

/src
/app
  /public
    /index.php
  /bootstrap.php

そして、index.phpドキュメント ルートのファイルに含まれる唯一のものは次のとおりです。

<?php

require __DIR__ . '/../bootstrap.php';

その後、次のようなブートストラップ ファイルが作成される場合があります。

<?php

error_reporting(E_ALL);
// note that for production we would disable the displaying of errors and 
// enable logging of errors
ini_set('display_errors', 1);

require_once __DIR__ . '/../src/bootstrap.php'

// btw also don't forget to set the encoding
$dbConnection = new PDO('DSN', 'username', 'password');

// now we can simply call a class and pass the database object as an argument
$user = new User($dbConnection);
$user->changePassword('new password');

// because we still have the database object we can simply reuse it for some other class
$page = new Page($dbConnection);
echo $page->render('home');

ご覧のとおり、データベース接続を必要なクラス/メソッドに渡し続けることができます。これにより、データベース接続を別のものに簡単に交換して、単体テストを高速化できます。この疎結合により、他のストレージ メカニズムが必要になった場合に備えて、データベース オブジェクトを別のものに簡単に交換できます。

上記のほとんどを実際に見たい場合は、私が現在取り組んでいるプロジェクトを見ることができます。なぜ OOP にメリットしかないのか疑問に思っている場合は、次のシリーズをご覧ください。

http://www.g-truc.net/post-0182.html

于 2013-01-16T18:47:42.517 に答える
0

既存のコードをクラスに変換することは、コードの再利用を計画している場合、または単一のクラスの複数のインスタンスを利用するためにコードをリファクタリングできる場合に最も役立ちます。この例では、それを行うことが本当に有益かどうかを判断することは不可能ですが、そうではないというのが私の推測です。

クラスは、コードがより明確になり、保守が容易になる場合にのみ役立ちます。PHP などの言語では、アプリケーション内の他のコードとはまったく異なる、1 回限りの処理を行うスクリプトを記述することが多いため、それをクラスに変換する意味がない場合があります。

定数に関しては、はい、それらが定義されているページに対してのみ有効です。PHP のエンジンはそれを実行するページのみを検査するため、解析および実行時に他の場所のページで定義された定数についてはわかりません。ページ。これに対する解決策は、DB資格情報の質問に関連しています。

1 つのオプションは、これらの定数が定義されているインクルード ファイルを定義することですが、それらを必要とする各ページに含まれます。このようなもの:

page1.php

define(SOMETHING, 'value');

page2.php

require('page1.php');
echo SOMETHING;

page1.php を要求する (含め、ファイルが見つからない場合は失敗する) ことで、解析および実行時に現在のページの一部として扱われるため、それに含まれる定義はそのページの後のコードに適用されます。

于 2013-01-16T18:41:43.493 に答える
0

オブジェクト

オブジェクトは、最も基本的には、作業を容易にするために個々のユニットにパッケージ化できる一般的な関数と変数の単なるコレクションです。あなたのコードは、データベース クエリに関して少し反復的であるように思われます。コードを簡素化するために、PDO の周りにラッパー クラスを作成または使用することでメリットが得られる場合があります。

個人的には、このようなものを数年前から使用しており、うまく機能しています。ドロップインの代替品として、または独自のものを構築するための例として役立つ場合があります。

資格

通常、データベース資格情報を定義する方法は、専用ファイル内の配列であり、接続をセットアップした直後にunset()配列を作成します。すなわち:

inc.db_cfg.php

<?php
$conn_info = array(
  'hostname' => 'mysql.domain.com',
  'username' => 'bob',
  'password' => '1234',
  'dbname' => 'mydb'
);

index.php

<?php
require('inc.db_cfg.php');
$uri = sprintf("mysql:host=%s;dbname=%s", $conn_info['hostname'], $conn_info['dbname']);
$this->dbh = new PDO($uri, $conn_info['username'], $conn_info['password']);
unset($conn_info, $uri);

データベース資格情報をコンストラクターで直接定義するのではなく、変数で定義する主な理由は、接続が失敗し、スクリプトが例外またはエラーをスローした場合、スタック トレース/エラー メッセージが、ユーザー名を含む生のコード行を出力する可能性があるためです。 、パスワード、ホスト名、および他のビットを非公開にしたい場合があります。

また、資格情報が、誰かが要求した生のテキストで出力されないファイルの種類に保存されていることを確認する必要があります。たとえば、「初期の頃」は、単純にインクルード ファイルdb_cfg.incなどに名前を付けていました。問題なくコードに含めることができinclude('db_cfg.inc');ますが、Apache のデフォルト設定では、誰かがhttp://mysite.com/db_cfg.inc.

最後に、資格情報に特に必要というunset()わけではありませんが、害はなく、私のパラノイアを満足させます。

パスワードハッシュ

SHA1 はしばらくの間根本的に壊れていましたcrypt()。SHA256 や SHA512 などのより優れたアルゴリズムにアクセスしたり、インターウェブ上からbcrypt実装を引っ掛けたりすることができます。

于 2013-01-16T19:27:42.153 に答える