5

以下の編集を参照してください

PHP での OOP 開発に飛び込もうとしていますが、本当に頭痛や潰瘍ができ始めています。頭がまとまりません。部分が非論理的すぎるように思えます。どこから始めればよいか見当もつきません。それを学ぶ努力をする価値があると信じており、より良い概要を提供してくれるので、本当にイライラします。私のコードについて。

昨日は一日中インターネットで実践例や解説記事を探していましたが、今はもっと混乱しているように感じます。次のような例ではなく、実用的なヒントが必要です


class person {
     var $name;
     function set_name($new_name) {
          $this->name = $new_name;
     }
     function get_name() {
          return $this->name;
     }
}
$stefan = new person();
$jimmy = new person;

$stefan->set_name("Stefan"); $jimmy->set_name("Jimmy");

echo "Stefan's full name: " . $stefan->get_name(); echo "Jimmy's full name: " . $jimmy->get_name();

このような例を見ると、なぜすべきではないのか疑問に思います (すべて同じページで定義されているため)。

$name = "Stefan"; 
echo "Stefan's full name: ".$name;

あなたが私に尋ねると、より短く(コードが少なく)、より明白になりますか?

私のプロジェクトにノウ。

私が作ろうとしているのは、シンプルなポートフォリオのウェブサイトです。したがって、ホームページ情報ページ、仕事に関するページ、連絡フォームの 4 ページだけが必要です。私は 3 つのテーブルclientsを使用し、自分の作業ページで使用したいと考えていcontentます。media

私は自分の構造について考えていて、次のようなものを思いつきました(頭の中で、それを達成する方法の手がかりがありません)

class Database{}
class Content extends Database{}
     function showMenu(){}
     function showContent{}
class Clients extends Database{}
     function showClientList{}
     function showClientDetails{}
class Media extends Database{}

パブリック メソッドでデータベース接続を確立するデータベース クラスを作成済みquery($qry)です。クラスから始めましたがContent、現時点では次のようになっています。


class Content extends Database {
    public function topMenu($page){
        $db = new Database();
        $db->connect();
        $db->query("SELECT m_link, m_title, m_accesskey FROM menu WHERE m_type = 'top'"); 
        $res = $db->getResult();
        foreach($res AS $show){
            if($page == $show['m_link']){
                echo("<li id="active">$show['m_title']."</li>\n");
            }else{
                echo("<li>$show['m_title']."</li>\n");
            }
        }
    }
}

ところで、これはまったく意味がありますか?

私のindex.phpには、メニューを表示するための次の行があります(正常に動作します)$content = new Content(); $content->topMenu($_aGET[0]);

私がそれを失っているポイントは、変数(URLを保持する)に依存するクライアントリストまたはクライアントの詳細のいずれかを表示する方法です。$_aGET[0]

クライアントの詳細を表示したいとします。そのため、3 つのテーブルすべてのレコードが必要なので、通常は 2 つの結合を使用します。

$query = "
    SELECT cl.c_id, cl.c_client, cl.c_client_desc, ncc.clco_cl_id, ncc.clco_co_id, co.c_content, ncm.clme_me_id, ncm.clme_cl_id, GROUP_CONCAT(me.m_link) AS images_link
    FROM clienten AS cl
    LEFT JOIN norm_cl_co_rel AS ncc ON cl.c_id = ncc.clco_cl_id
    LEFT JOIN content AS co ON ncc.clco_co_id = co.c_id
    LEFT JOIN norm_cl_me_rel AS ncm ON cl.c_id = ncm.clme_cl_id
    LEFT JOIN media AS me ON me.m_id = ncm.clme_me_id
    WHERE cl.c_client = '".mysql_real_escape_string($_aGET[1])."'
    AND cl.c_language_id = '"._LANGUAGE."' 
    AND cl.c_active = '1'
";

しかし、私が OOP の考えを理解している限り、クラスで定義されたテーブルごとにメソッドが必要です (そうですか?) しかし、これらを結合するにはどうすればよいでしょうか?

それとも、私の「ストーリー」は次のようなものですか?

編集:

わかりました、Fluffeh の投稿の後、私は彼の例を使用し、それを少し変更してテストしました。問題は、出力が得られることですが、望ましいものではありません。私の出力は以下のようなものです

ID: 会社名
ハ
内容:C
メディア:
:
:
:
:
:

取得する必要がありますが(値はデータベースにあります):

ID: 会社名
会社名
説明: CompanyName は会社です
メディア:
:画像1
:画像2
:画像3
:画像4
:画像5

私のコードは次のようになります。

class media{
    public $type;
    public $title;
    public $image;
    public $desc;
}

class client{
    public $name;
    public $desc;
}

class clientDetails{

    private $clientID;
    public $clientName;
    public $clientDesc;
    public $clientMedia = array();
    public $clientMediaFiles = 0;

    public function __construct($myID){
        $this->clientID = $myID;
    }

    public function getMyDetails(){

        $db = new Database();
        $db->connect();
        $db->query("
            SELECT c_client, c_client_desc 
            FROM clienten 
            WHERE c_client = '".mysql_real_escape_string($this->clientID)."'
        ");
        foreach($db->getResult() as $client){
            $this->name = $client['c_client'];
            $this->desc = $client['c_client_desc'];
        }

        $db = new Database();
        $db->connect();
        $db->query("
            SELECT ncm.clme_me_id, ncm.clme_cl_id, cl.c_id, me.m_id, me.m_type, me.m_title, me.m_desc, me.m_link
            FROM norm_cl_me_rel AS ncm
            LEFT JOIN clienten AS cl ON cl.c_id = ncm.clme_cl_id
            LEFT JOIN media AS me ON me.m_id = ncm.clme_me_id
            WHERE me.m_id IN(1,2,3,4,5)
        ");
        foreach($db->getResult() as $media){
            $this->clientMedia[$i]= new media();
            $this->clientMedia[$i]->type = $media['m_type'];
            $this->clientMedia[$i]->title = $media['m_title'];
            $this->clientMedia[$i]->image = $media['m_image'];
            $this->clientMedia[$i]->desc = $media['m_desc'];
            $this->clientMediaFiles++;
        }
    }

    public function displayMyResults(){
        echo "ID: $this->clientID";
        echo "&lt;div>&lt;h3>".$this->name."&lt;/h3>";
        echo "Desc: ".$this->desc."&lt;br>";
        echo "Media:&lt;br>";
        for($i=0;$i<$this->clientMediaFiles;$i++){
            echo $this->clientMedia[$i]->title." : ".$this->clientMedia[$i]->desc."&lt;br>";
        }
        echo "&lt;/div>";
    }

}
4

4 に答える 4

6

OOPを続けてください。一度取得すると、厄介で厄介で厄介で恐ろしく、過激な手続き型コードには戻りたくないでしょう。

この例を挙げると、クライアントの詳細を表示したいとします。したがって、3 つのテーブルすべてからのレコードが必要なので、通常は 2 つの結合を使用します。

これは、OOP がいかに有用であるかを示すために使用できる優れた例です。

ClientDetailsのクラスを作成する

  • clientID を引数として受け入れるコンストラクターをその中に作成します。
  • このコンストラクター内でコードを実行し、その内部変数にクエリによって返されたデータを入力します。
  • 返されたデータを適切な形式で出力する関数を作成します。
  • メインコードから作成し、詳細を表示します

突然、クラスに数行のコードができましたが、2 行のコードでデータを完全に表示できます。

すぐにいくつかのサンプル コードを追加し、デモ用にいくつかのクラスをかき回せるかどうかを確認します。

編集:くそー、古いクラスをかき回さないでください。これには詳細すぎますが、例としていくつかのコードを書きました:

<?php

class clientContact
{
    public $name;
    public $phone;
}

class clientDetails
{
    private $clientID;      //only this class can access this variable.
    public $clientName;     // Anything can change these.
    public $clientPhone;
    public $additionalContacts= array();
    public $associates=0;

    public function __construct($myID)
    // This is a magic function that is called every time we make a new object of this class.
    {
        $this->$clientID=$myID;
    }

    public function getMyDetails()
    // This function will query the database to get it's information properly
    // and populate itself with everything it needs. You could do this as part
    // of the __construct() call, but I didn't want to do TOO much code.
    {
        $sql="select clientName, clientPhone from clients where clientID=".$this->clientID.";";
        // skipping over full SQl bits...
        foreach($stmt as $clientContact)
        {
            $this->clientName=$clientContact->clientName;
            $this->clientPhone=$clientContact->clientPhone;
        }

        $sql="select clientName, clientPhone from associates where assocID=".$this->clientID.";";
        // skipping over full SQl bits...
        foreach($stmt as $clientContact)
        {
            $this->additionalContacts[$i]= new clientContact();
            $this->additionalContacts[$i]->name=$clientContact->name;
            $this->additionalContacts[$i]->phone=$clientContact->phone;
            $this->associates++;
        }

    }

    public function displayMyResults()
    // This function will simply display everything it has in a nicely format
    {
        echo "<div><h3>".$this->clientName."</h3>";
        echo "My contact phone number is :".$this->phone."<br>";
        echo "My associates are:<br>";
        for($i=0;$i<$this-associates;$i++)
        {
            echo $this->additionalContacts[$i]->name." : ".$this->additionalContacts[$i]->phone."<br>";
        }
        echo "</div>";

    }
}

?>

なんてこった、それは長くて恐ろしいですよね?

あまり。これが理由です。

もちろん、クラスには少しコードがありますが、メイン ページで次の操作を実行できます。

<?php 

    $someArray=array(36, 25, 76); 
    // This could be from a query, or a form, or anything else

    for($i=0;$i<count($someArray);$i++)
    {
        $currentContact= new clientDetails($someArray[$i]);
        // This is how we create the object.

        $currentContact->getMyDetails();
        // This now tells the object to get it's own data

        $currentContact->displayMyResults();
        // This now displays the data in the object to the page.
        echo "<hr>";
        unset($currentContact);
    }
?>

そして、その小さなコード スニペットを使用して、必要に応じて書式設定されたすべての連絡先を表示し、すべての連絡先を希望どおりに完全に表示しました。

このような小さな例の代わりに、すべてのコンテンツにこの種のオブジェクトを使用することを想像してみてください。フォーラムへの投稿?1 つのオブジェクト。ビジネス KPI の複雑な計算ですか? 持っているすべてのデータを取得し、予測を計算し、結果をグラフに表示して、それを必要とするユーザーに電子メールで送信できる 1 つのオブジェクト。

OOP は、上から下まで実行される HTML および PHP スクリプトのバックグラウンドを持っている場合、学習曲線が急勾配になる可能性があります。

編集:

m_imageクエリに列がないようです:

    $db = new Database();
    $db->connect();
    $db->query("
        SELECT cl.c_id, ncm.clme_me_id, ncm.clme_cl_id, me.m_type, me.m_title, me.m_desc, me.m_link, m_image
        FROM clienten AS cl
        LEFT JOIN norm_cl_me_rel AS ncm ON cl.c_id = ncm.clme_cl_id
        LEFT JOIN media AS me ON me.m_id = ncm.clme_me_id
        WHERE me.m_id IN(1,2,3,4,5)
    ");
    foreach($db->getResult() as $media){
        $this->clientMedia[$i]= new media();
        $this->clientMedia[$i]->type = $media['m_type'];
        $this->clientMedia[$i]->title = $media['m_title'];
        $this->clientMedia[$i]->image = $media['m_image'];
        $this->clientMedia[$i]->desc = $media['m_desc'];
        $this->clientMediaFiles++;
    }

編集 2: 100% 確実ではありませんが、フィールド名が返されている可能性があります。クエリを次のように置き換えてみてください。

SELECT cl.c_id as c_id, ncm.clme_me_id as clme_me_id, ncm.clme_cl_id as clme_cl_id, me.m_type as m_type, me.m_title as m_title, me.m_desc as m_desc, me. as m_link
FROM clienten AS cl
LEFT JOIN norm_cl_me_rel AS ncm ON cl.c_id = ncm.clme_cl_id
LEFT JOIN media AS me ON me.m_id = ncm.clme_me_id
WHERE me.m_id IN(1,2,3,4,5)
于 2012-08-01T09:08:13.150 に答える
0

私が Java で OOP を学んだとき、各オブジェクト型を新しい変数型と考えるように言われました。つまり、クラスがある場合Person(PS クラス名の最初の文字を大文字にするのは良い命名規則です)、オブジェクトを保持するオブジェクトは typePersonと見なすことができます。Person

私があなたに与えることができる最も良い例は、私がIRC Botを作っていたときです。Userボットは、 s、Channels、およびsを追跡する必要がありましたServer。IRC プロトコルは完全に文字列に基づいています。

文字列を扱うことはできますが、アプリケーションの複雑さとコードの読みやすさが大幅に増加します。代わりに、そのデータを、IRC サーバーとやり取りするためのメソッドを持つ および オブジェクトに変換することにしChannelましたUserServer

例えば:

/**
 * Add $user to $channel.
 * @param Channel $channel
 * @param User    $user
 *
 * @throws Exception
 */
protected function addUser(Channel $channel, User $user) {
    if (!isset($this->chanList[$channel->name])) {          #Channel is not on channel list
        throw new Exception("You are not on that channel");
    }
    if (!isset($this->userList[$user->nick])) {             #User is not on global user list (New user)
        $this->userList[$user->nick] = $user;               #Add user to list
    }
    $this->chanList[$channel->name]->addUser($user);        #Add the user to the channel user list
}

これは、ユーザーがチャネルに参加するたびに呼び出されます。これにより、Botオブジェクトはユーザーとユーザーが使用しているチャネルを追跡できます。Userコードはいくつかの検証を行ってから、オブジェクトをオブジェクトに追加しChannelます。

文字列だけを使用する必要があるとしたら、IRC プロトコルから各行を解析し、必要なデータを抽出し、いくつかの非常に大きな配列を操作する必要があると想像してください。最終的には、物事をうまく整理する代わりに、1 つの大きな混乱が発生することになります。

于 2012-08-11T09:36:58.573 に答える
-1

したがって、たとえば MVC やフロント コントローラーのパターンで取り上げる場合、OOP は適切なアプローチです。しかし、4 ページの単純なサイトのみが必要な場合は、手続き型コードを実際に使用できます。問題ありません。drupal を知っている場合、90% は手続き型コードです。

しかし...

$db = new Database();
        $db->connect();

db オブジェクトを作成し、各メソッドで接続することはお勧めできません。スクリプト全体で 1 つの db con オブジェクトのみを共有する方がはるかに優れています。シングルトンパターンを使用して、このようなことを行うことができます。

class Database extends PDO {

  private static db = null;

  private function __construct() {
        parent::__construct(/* here get some conf data*/);    
  }

  public static getDb() {
    if(!self::db) self::db = new self();
    return self::db;
  }

  /* here you can add your custom methods like loadMenu etc. */
}

ロジック ビュー レイヤーを分離しすぎることをお勧めします。extract php 関数を参照してください。配列のすべての要素が実際のシンボル テーブルに追加されます (キーはその変数の名前で、値は値です)。抽出機能を使用すると、ロジックをビューから分離する、優れたビュー レイヤーを実行できます。何かのようなもの:

define('TEMPLATE_DIR', __DIR__ . '/templates');

function render($template, $variables) {
  extract($variables);
  require TEMPLATE_DIR . "/$template.tpl.php"; 
}

$variables = array('menu_links' => Database::getDb()->getMenu());

render('menu', $variables);

menu.tpl.php で:

<ul>
  <?php foreach($menu_links as $link) : ?>
  <li><a href="<?= $link['href'] ?>"><?= $link['title'] ?></a></li>
  <?php endforeach; ?> 
</ul>
于 2012-08-01T09:21:41.580 に答える
-2

PHP OOP は、多くの場合、優れた MVC (モデル ビュー コントローラー) の接続と実装に要約されます。

前に述べたように、野球ボールの代わりにブリキ缶に核兵器を発射するため、PHP で OOP を使用する必要がないことがよくあります... Web サイトはそのページ自体によって MVC される傾向があり、冗長なコードはそこにいる人を実際に傷つけることはありません (データベース/セッション/フォームにめちゃくちゃなセキュリティがないため)

PHP MVC のわかりやすい例はhttp://anantgarg.com/2009/03/13/write-your-own-php-mvc-framework-part-1/です。

最初の部分は非常に理解しやすく、2 番目の部分 (#1 の最後にリンクされています) は少し混乱しています。

しかし、zip ファイルで提供されているコードを調べると、すでに良いアイデアが得られます。

于 2012-08-01T09:45:39.447 に答える