web-dev-qa-db-ja.com

PHPコンストラクタと静的関数

PHPでのコンストラクターの動作について少し混乱しています。

新しいオブジェクトをインスタンス化するときに呼び出されるコンストラクターを持つクラスがあります。

_$foo = new Foo($args);
_

__construct($params)はクラスFooで呼び出され、適切な初期化コードを実行します。

ただし、クラスを使用して静的関数を呼び出すと、コンストラクターが再度呼び出されます。

_$bar = Foo::some_function(); //runs the constructor from Foo
_

これにより、コンストラクターが実行され、新しいFooオブジェクトを作成するときにのみ対象としたオブジェクト初期化コードが実行されます。

コンストラクタがどのように機能するかというポイントを逃していますか?または、クラスを使用して静的関数を呼び出すときに__construct()が実行されないようにする方法はありますか?

オブジェクトの初期化を行うには、代わりに「ファクトリ」関数を使用する必要がありますか?もしそうなら、コンストラクタのポイントは何ですか?

::編集::ユーザーが写真をアルバムにアップロードできるフォーム(create_photo.php)と、アルバムを表示できるエリア(view_photos.php)があります。フォーム送信時に:

_$photo = new Photo($_FILES['photo'], $_POST['arg1'], ect..);
_

写真コンストラクターが写真を作成して保存します。ただし、view_photo.phpでは、次のように呼び出します。

_$photo = Photo::find_by_id($_POST['id']) //user-defined function to query database
_

これにより、Photoのコンストラクタが実行されます。

17
bar1024

あなたの質問を再現するものは何もありません。

デモを参照してください: http://codepad.org/h2TMPYUV

コード:

class Foo {
    function __construct(){ 
        echo 'hi!';
    }
    static function bar(){
        return 'there';
    }
}

echo Foo::bar(); //output: "there"
22

仮定PHP 5.x

異なる目標、異なるパス

  1. クラス(オブジェクト)の新しいインスタンスを作成する

    _class myClassA
    {
       public $lv;
    
       public function __construct($par)
       {
           echo "Inside the constructor\n";
           $this->lv = $par;
       }
    }
    
    $a = new myClassA(11);
    $b = new myClassA(63);
    _

    新しいオブジェクトを作成するのでPHP呼び出し:

    __construct($par);

    新しいオブジェクトなので、

    _$a->lv == 11 
    
    $b->lv == 63
    _
  2. クラスの関数を使用する

    _class myClassB
    {
        public static $sv;
    
        public static function psf($par)
        {
            self::$sv = $par;
        }
    }
    
    myClassB::psf("Hello!");
    $rf = &myClassB::$sv;
    myClassB::psf("Hi.");
    _

    今_$rf == "Hi."_

    関数または変数は、_::_によってアクセスされるstaticを定義する必要があります。「psf」を呼び出すオブジェクトは作成されません。「クラス変数」svは、クラス内に1つのインスタンスしかありません。

  3. ファクトリによって作成されたシングルトンを使用します(myClassAは上にあります)

    _class myClassC
    {
    
        private static $singleton;
    
        public static function getInstance($par){
    
            if(is_null(self::$singleton)){
    
                self::$singleton = new myClassA($par);
    
            }
    
            return self::$singleton;
    
        }
    
    }
    
    $g = myClassC::getInstance("gino");
    echo "got G\n";
    
    $p = myClassC::getInstance("pino");
    echo "got P\n";
    _

ファクトリ(getInstance)を初めて使用するとき、$ parginoに設定された新しいオブジェクトを構築します=。

2回目のファクトリーの使用$ singletonには、すでに返される値があります。新しいオブジェクトは作成されません(__ constructが呼び出されず、使用されるメモリとCPUが少なくなります)。

もちろん値はオブジェクトinstanceOf myClassAであり、忘れないでください。

_myClassC::$singleton->lv == "gino"_

シングルトンに注意してください:

シングルトンの何が悪いのですか?

http://www.youtube.com/watch?v=-FRm3VPhseI

私の答えでは、シングルトンを昇格/降格したくありません。単に質問の言葉から、私はこの計算を行いました:

"静的" + "__ construct" = "シングルトン"!

6
Ivan Buttinoni

これが私の回避策です:

メソッドconstruct()を静的クラスに配置しました。通常のクラスで使用する__construct()とは異なります。

各クラスは独自のファイルにあるため、クラスを初めて使用するときにそのファイルを遅延ロードします。これは私にクラスの最初の使用のイベントを与えます。

spl_autoload_register(function($class) {

    include_once './' . $class . '.php';

    if (method_exists($class, 'construct')) {
        $class::construct();
    }
});
1
Martin

静的メソッドでクラスプロパティを配列として定義し、メソッドを介して呼び出します。それが最善の解決策かどうかはわかりませんが、うまく機能します。

例:

    class Foo
    {
      private static construct_method()
      {
        return [
          'one' => 1,
          'two' => 2
        ];
      }

      public static any_method()
      {
        return self::construct_method()['one'] + self::construct_method()['two'];
      }

    }

    echo Foo::any_method(); // 3
0
senera